feat: 환자 처방 내역에서 조제 상세 정보 인라인 펼침 기능 추가
- 환자 처방 내역 모달에서 처방 행 클릭 시 상세 정보 펼침 - 중첩 모달 문제 해결을 위해 인라인 표시 방식으로 변경 - 구성 약재 정보 테이블 표시 (약재명, 보험코드, 첩당용량, 총용량) - 재고 소비 내역 테이블 표시 (약재명, 원산지, 도매상, 사용량, 단가, 원가) - 총 원가 자동 계산 및 표시 - chevron 아이콘으로 펼침/접힘 상태 표시 - 다른 행 클릭 시 자동으로 이전 행 닫기 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
83f9f10f3d
commit
041d1d81c4
146
static/app.js
146
static/app.js
@ -254,7 +254,7 @@ $(document).ready(function() {
|
||||
</tr>
|
||||
`);
|
||||
} else {
|
||||
compounds.forEach(compound => {
|
||||
compounds.forEach((compound, index) => {
|
||||
// 상태 뱃지
|
||||
let statusBadge = '';
|
||||
switch(compound.status) {
|
||||
@ -271,8 +271,13 @@ $(document).ready(function() {
|
||||
statusBadge = '<span class="badge bg-secondary">대기</span>';
|
||||
}
|
||||
|
||||
const detailRowId = `compound-detail-${compound.compound_id}`;
|
||||
|
||||
tbody.append(`
|
||||
<tr>
|
||||
<tr class="compound-row" style="cursor: pointer;" data-compound-id="${compound.compound_id}">
|
||||
<td>
|
||||
<i class="bi bi-chevron-right toggle-icon"></i>
|
||||
</td>
|
||||
<td>${compound.compound_date || '-'}</td>
|
||||
<td>${compound.formula_name || '직접조제'}</td>
|
||||
<td>${compound.je_count || 0}</td>
|
||||
@ -282,20 +287,59 @@ $(document).ready(function() {
|
||||
<td>${formatCurrency(compound.sell_price_total || 0)}</td>
|
||||
<td>${statusBadge}</td>
|
||||
<td>${compound.prescription_no || '-'}</td>
|
||||
<td>
|
||||
<button class="btn btn-sm btn-outline-info view-compound-detail"
|
||||
data-id="${compound.compound_id}">
|
||||
<i class="bi bi-eye"></i> 상세
|
||||
</button>
|
||||
</tr>
|
||||
<tr id="${detailRowId}" class="collapse-row" style="display: none;">
|
||||
<td colspan="10" class="p-0">
|
||||
<div class="card m-2">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h6><i class="bi bi-capsule"></i> 구성 약재</h6>
|
||||
<div id="ingredients-${compound.compound_id}" class="mb-3">
|
||||
<div class="text-center text-muted">
|
||||
<div class="spinner-border spinner-border-sm" role="status"></div>
|
||||
로딩 중...
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h6><i class="bi bi-box-seam"></i> 재고 소비 내역</h6>
|
||||
<div id="consumptions-${compound.compound_id}">
|
||||
<div class="text-center text-muted">
|
||||
<div class="spinner-border spinner-border-sm" role="status"></div>
|
||||
로딩 중...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
`);
|
||||
});
|
||||
|
||||
// 상세보기 버튼 이벤트
|
||||
$('.view-compound-detail').on('click', function() {
|
||||
const compoundId = $(this).data('id');
|
||||
viewCompoundDetail(compoundId);
|
||||
// 행 클릭 이벤트 - 상세 정보 토글
|
||||
$('.compound-row').on('click', function() {
|
||||
const compoundId = $(this).data('compound-id');
|
||||
const detailRow = $(`#compound-detail-${compoundId}`);
|
||||
const icon = $(this).find('.toggle-icon');
|
||||
|
||||
if (detailRow.is(':visible')) {
|
||||
// 닫기
|
||||
detailRow.slideUp();
|
||||
icon.removeClass('bi-chevron-down').addClass('bi-chevron-right');
|
||||
} else {
|
||||
// 열기 - 다른 모든 행 닫기
|
||||
$('.collapse-row').slideUp();
|
||||
$('.toggle-icon').removeClass('bi-chevron-down').addClass('bi-chevron-right');
|
||||
|
||||
// 현재 행 열기
|
||||
detailRow.slideDown();
|
||||
icon.removeClass('bi-chevron-right').addClass('bi-chevron-down');
|
||||
|
||||
// 상세 정보 로드
|
||||
loadCompoundDetailInline(compoundId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -311,6 +355,70 @@ $(document).ready(function() {
|
||||
});
|
||||
}
|
||||
|
||||
// 환자 처방 내역 모달 내에서 조제 상세 정보 로드 (인라인)
|
||||
function loadCompoundDetailInline(compoundId) {
|
||||
$.get(`/api/compounds/${compoundId}`, function(response) {
|
||||
if (response.success && response.data) {
|
||||
const data = response.data;
|
||||
|
||||
// 구성 약재 테이블
|
||||
let ingredientsHtml = '<table class="table table-sm table-bordered"><thead class="table-light"><tr><th>약재명</th><th>보험코드</th><th>첩당용량</th><th>총용량</th></tr></thead><tbody>';
|
||||
|
||||
if (data.ingredients && data.ingredients.length > 0) {
|
||||
data.ingredients.forEach(ing => {
|
||||
ingredientsHtml += `
|
||||
<tr>
|
||||
<td><strong>${ing.herb_name}</strong></td>
|
||||
<td>${ing.insurance_code || '-'}</td>
|
||||
<td>${ing.grams_per_cheop}g</td>
|
||||
<td>${ing.total_grams}g</td>
|
||||
</tr>
|
||||
`;
|
||||
});
|
||||
} else {
|
||||
ingredientsHtml += '<tr><td colspan="4" class="text-center text-muted">약재 정보가 없습니다</td></tr>';
|
||||
}
|
||||
ingredientsHtml += '</tbody></table>';
|
||||
|
||||
$(`#ingredients-${compoundId}`).html(ingredientsHtml);
|
||||
|
||||
// 재고 소비 내역 테이블
|
||||
let consumptionsHtml = '<table class="table table-sm table-bordered"><thead class="table-light"><tr><th>약재명</th><th>원산지</th><th>도매상</th><th>사용량</th><th>단가</th><th>원가</th></tr></thead><tbody>';
|
||||
|
||||
if (data.consumptions && data.consumptions.length > 0) {
|
||||
let totalCost = 0;
|
||||
data.consumptions.forEach(con => {
|
||||
totalCost += con.cost_amount || 0;
|
||||
consumptionsHtml += `
|
||||
<tr>
|
||||
<td><strong>${con.herb_name}</strong></td>
|
||||
<td>${con.origin_country || '-'}</td>
|
||||
<td>${con.supplier_name || '-'}</td>
|
||||
<td>${con.quantity_used}g</td>
|
||||
<td>${formatCurrency(con.unit_cost_per_g)}/g</td>
|
||||
<td>${formatCurrency(con.cost_amount)}</td>
|
||||
</tr>
|
||||
`;
|
||||
});
|
||||
consumptionsHtml += `
|
||||
<tr class="table-info">
|
||||
<td colspan="5" class="text-end"><strong>총 원가:</strong></td>
|
||||
<td><strong>${formatCurrency(totalCost)}</strong></td>
|
||||
</tr>
|
||||
`;
|
||||
} else {
|
||||
consumptionsHtml += '<tr><td colspan="6" class="text-center text-muted">재고 소비 내역이 없습니다</td></tr>';
|
||||
}
|
||||
consumptionsHtml += '</tbody></table>';
|
||||
|
||||
$(`#consumptions-${compoundId}`).html(consumptionsHtml);
|
||||
}
|
||||
}).fail(function() {
|
||||
$(`#ingredients-${compoundId}`).html('<div class="alert alert-danger">데이터를 불러오는데 실패했습니다.</div>');
|
||||
$(`#consumptions-${compoundId}`).html('<div class="alert alert-danger">데이터를 불러오는데 실패했습니다.</div>');
|
||||
});
|
||||
}
|
||||
|
||||
// 처방 목록 로드
|
||||
function loadFormulas() {
|
||||
$.get('/api/formulas', function(response) {
|
||||
@ -847,7 +955,21 @@ $(document).ready(function() {
|
||||
// 비고
|
||||
$('#detailNotes').text(data.notes || '');
|
||||
|
||||
// 모달 표시
|
||||
// 부모 모달(환자 처방 내역)을 임시로 숨기고 조제 상세 모달 열기
|
||||
const parentModal = $('#patientCompoundsModal');
|
||||
const wasParentOpen = parentModal.hasClass('show');
|
||||
|
||||
if (wasParentOpen) {
|
||||
// 부모 모달 숨기기 (DOM에서 제거하지 않음)
|
||||
parentModal.modal('hide');
|
||||
|
||||
// 조제 상세 모달이 닫힐 때 부모 모달 다시 열기
|
||||
$('#compoundDetailModal').off('hidden.bs.modal').on('hidden.bs.modal', function() {
|
||||
parentModal.modal('show');
|
||||
});
|
||||
}
|
||||
|
||||
// 조제 상세 모달 열기
|
||||
$('#compoundDetailModal').modal('show');
|
||||
}
|
||||
}).fail(function() {
|
||||
|
||||
@ -1088,9 +1088,10 @@
|
||||
<!-- 처방 내역 테이블 -->
|
||||
<h6><i class="bi bi-list-ul"></i> 처방 내역</h6>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-hover">
|
||||
<table class="table table-sm">
|
||||
<thead class="table-dark">
|
||||
<tr>
|
||||
<th width="40"></th>
|
||||
<th width="100">조제일</th>
|
||||
<th>처방명</th>
|
||||
<th width="60">제수</th>
|
||||
@ -1100,11 +1101,10 @@
|
||||
<th width="100">판매가</th>
|
||||
<th width="80">상태</th>
|
||||
<th width="100">처방전번호</th>
|
||||
<th width="100">작업</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="patientCompoundsList">
|
||||
<!-- Dynamic content -->
|
||||
<!-- Dynamic content with collapsible details -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user