feat: PMR 이전 처방 비교 기능

- /pmr/api/patient/<cus_code>/history: 환자 이전 처방 이력 API
- 하단에 이전 처방 영역 + < > 네비게이션
- 현재 처방과 이전 처방 한눈에 비교 가능
This commit is contained in:
thug0bin
2026-03-04 23:35:11 +09:00
parent fc2db78816
commit 6192f635ca
2 changed files with 302 additions and 0 deletions

View File

@@ -242,6 +242,75 @@
animation: spin 1s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
/* 이전 처방 비교 영역 */
.history-section {
border-top: 3px solid #e2e8f0;
background: #fafafa;
}
.history-header {
background: linear-gradient(135deg, #64748b, #94a3b8);
color: #fff;
padding: 12px 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
.history-header .title { font-weight: 600; }
.history-nav {
display: flex;
align-items: center;
gap: 10px;
}
.history-nav button {
background: rgba(255,255,255,0.2);
border: none;
color: #fff;
width: 32px;
height: 32px;
border-radius: 50%;
font-size: 1.1rem;
cursor: pointer;
transition: all 0.2s;
}
.history-nav button:hover:not(:disabled) { background: rgba(255,255,255,0.4); }
.history-nav button:disabled { opacity: 0.4; cursor: not-allowed; }
.history-nav .index { font-size: 0.9rem; }
.history-info {
padding: 10px 20px;
background: #f1f5f9;
font-size: 0.85rem;
color: #64748b;
display: flex;
gap: 15px;
}
.history-meds {
max-height: 200px;
overflow-y: auto;
padding: 10px 20px;
}
.history-meds table {
width: 100%;
border-collapse: collapse;
font-size: 0.85rem;
}
.history-meds th {
background: #e2e8f0;
padding: 8px 10px;
text-align: left;
font-weight: 600;
color: #475569;
}
.history-meds td {
padding: 8px 10px;
border-bottom: 1px solid #e2e8f0;
}
.history-meds .med-name { font-weight: 500; }
.history-empty {
padding: 30px;
text-align: center;
color: #94a3b8;
}
</style>
</head>
<body>
@@ -310,11 +379,30 @@
</div>
</div>
</div>
<!-- 이전 처방 비교 -->
<div class="history-section" id="historySection" style="display:none;">
<div class="history-header">
<span class="title">📜 이전 처방</span>
<div class="history-nav">
<button onclick="prevHistory()" id="historyPrev" disabled></button>
<span class="index" id="historyIndex">-</span>
<button onclick="nextHistory()" id="historyNext" disabled></button>
</div>
</div>
<div class="history-info" id="historyInfo"></div>
<div class="history-meds" id="historyMeds">
<div class="history-empty">이전 처방 없음</div>
</div>
</div>
</div>
</div>
<script>
let currentPrescriptionId = null;
let currentPatientCode = null;
let historyData = [];
let historyIndex = 0;
// HTML 이스케이프
function escapeHtml(text) {
@@ -458,16 +546,117 @@
}
document.getElementById('actionBar').style.display = 'flex';
// 이전 처방 로드
currentPatientCode = data.patient.code;
if (currentPatientCode) {
loadPatientHistory(currentPatientCode, prescriptionId);
}
}
} catch (err) {
medList.innerHTML = `<div class="empty-state"><div class="text">오류: ${err.message}</div></div>`;
}
}
// 환자 이전 처방 로드
async function loadPatientHistory(cusCode, excludeSerial) {
const section = document.getElementById('historySection');
const medsDiv = document.getElementById('historyMeds');
try {
const res = await fetch(`/pmr/api/patient/${cusCode}/history?limit=10&exclude=${excludeSerial}`);
const data = await res.json();
if (data.success && data.history.length > 0) {
historyData = data.history;
historyIndex = 0;
section.style.display = 'block';
renderHistory();
} else {
section.style.display = 'none';
historyData = [];
}
} catch (err) {
console.error('History error:', err);
section.style.display = 'none';
}
}
// 이전 처방 렌더링
function renderHistory() {
if (historyData.length === 0) return;
const h = historyData[historyIndex];
// 인덱스 표시
document.getElementById('historyIndex').textContent =
`${historyIndex + 1} / ${historyData.length}`;
// 네비게이션 버튼
document.getElementById('historyPrev').disabled = historyIndex <= 0;
document.getElementById('historyNext').disabled = historyIndex >= historyData.length - 1;
// 정보
document.getElementById('historyInfo').innerHTML = `
<span>📅 ${h.date}</span>
<span>🏥 ${h.hospital || '-'}</span>
<span>👨‍⚕️ ${h.doctor || '-'}</span>
<span>💊 ${h.medication_count}종</span>
<span>💰 ${(h.copayment || 0).toLocaleString()}원</span>
`;
// 약품 테이블
if (h.medications && h.medications.length > 0) {
document.getElementById('historyMeds').innerHTML = `
<table>
<thead>
<tr>
<th>약품명</th>
<th>용량</th>
<th>횟수</th>
<th>일수</th>
</tr>
</thead>
<tbody>
${h.medications.map(m => `
<tr>
<td>
<div class="med-name">${m.med_name || m.medication_code}</div>
${m.add_info ? `<div style="font-size:0.7rem;color:#94a3b8;">${escapeHtml(m.add_info)}</div>` : ''}
</td>
<td>${m.dosage || '-'}</td>
<td>${m.frequency || '-'}회</td>
<td>${m.duration || '-'}일</td>
</tr>
`).join('')}
</tbody>
</table>
`;
} else {
document.getElementById('historyMeds').innerHTML = '<div class="history-empty">약품 정보 없음</div>';
}
}
// 이전 처방 네비게이션
function prevHistory() {
if (historyIndex > 0) {
historyIndex--;
renderHistory();
}
}
function nextHistory() {
if (historyIndex < historyData.length - 1) {
historyIndex++;
renderHistory();
}
}
// 상세 초기화
function clearDetail() {
document.getElementById('detailHeader').style.display = 'none';
document.getElementById('actionBar').style.display = 'none';
document.getElementById('historySection').style.display = 'none';
document.getElementById('medicationList').innerHTML = `
<div class="empty-state">
<div class="icon">👈</div>
@@ -475,6 +664,9 @@
</div>
`;
currentPrescriptionId = null;
currentPatientCode = null;
historyData = [];
historyIndex = 0;
}
// 전체 선택 토글