feat: Rx 사용량 페이지에 도매상 잔고 조회 버튼 추가
- 💰 도매상 잔고 버튼 (검색 바 옆)
- 모달로 백제/지오영/수인 3개 도매상 잔고 표시
- 총 미수금 합계 표시
- 새로고침 기능
This commit is contained in:
parent
1829c3efa7
commit
2d09f139ca
@ -727,6 +727,7 @@
|
||||
</select>
|
||||
</div>
|
||||
<button class="search-btn" onclick="loadUsageData()">🔍 조회</button>
|
||||
<button class="search-btn" style="background: linear-gradient(135deg, #a855f7, #7c3aed);" onclick="openBalanceModal()">💰 도매상 잔고</button>
|
||||
</div>
|
||||
|
||||
<!-- 통계 -->
|
||||
@ -2151,5 +2152,205 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 잔고 조회 모달 -->
|
||||
<div class="order-modal" id="balanceModal">
|
||||
<div class="order-modal-content" style="max-width:500px;">
|
||||
<div class="order-modal-header" style="background:linear-gradient(135deg, #7c3aed, #a855f7);">
|
||||
<h3>💰 도매상 잔고 현황</h3>
|
||||
<button class="order-close" onclick="closeBalanceModal()">✕</button>
|
||||
</div>
|
||||
<div class="order-modal-body" id="balanceContent">
|
||||
<div class="loading-state">
|
||||
<div class="loading-spinner"></div>
|
||||
<div>잔고 조회 중...</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="order-modal-footer">
|
||||
<button class="btn-order-test" onclick="loadBalances()">🔄 새로고침</button>
|
||||
<button class="btn-order-real" onclick="closeBalanceModal()">닫기</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
/* 잔고 모달 스타일 */
|
||||
.balance-grid {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
.balance-card {
|
||||
background: var(--bg-secondary);
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
border: 1px solid var(--border);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
}
|
||||
.balance-card.loading {
|
||||
opacity: 0.6;
|
||||
}
|
||||
.balance-card.error {
|
||||
border-color: var(--accent-rose);
|
||||
background: rgba(244, 63, 94, 0.1);
|
||||
}
|
||||
.balance-icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 24px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.balance-icon.baekje { background: linear-gradient(135deg, #d97706, #f59e0b); }
|
||||
.balance-icon.geoyoung { background: linear-gradient(135deg, #0891b2, #06b6d4); }
|
||||
.balance-icon.sooin { background: linear-gradient(135deg, #7c3aed, #a855f7); }
|
||||
|
||||
.balance-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
.balance-name {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.balance-detail {
|
||||
font-size: 11px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
.balance-amount {
|
||||
text-align: right;
|
||||
}
|
||||
.balance-value {
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
}
|
||||
.balance-value.baekje { color: #f59e0b; }
|
||||
.balance-value.geoyoung { color: #06b6d4; }
|
||||
.balance-value.sooin { color: #a855f7; }
|
||||
|
||||
.balance-label {
|
||||
font-size: 10px;
|
||||
color: var(--text-muted);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
.balance-total {
|
||||
background: linear-gradient(135deg, rgba(168, 85, 247, 0.1), rgba(6, 182, 212, 0.1));
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
margin-top: 8px;
|
||||
}
|
||||
.balance-total-label {
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.balance-total-value {
|
||||
font-size: 28px;
|
||||
font-weight: 700;
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
background: linear-gradient(135deg, #a855f7, #06b6d4);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
.balance-updated {
|
||||
text-align: center;
|
||||
font-size: 11px;
|
||||
color: var(--text-muted);
|
||||
margin-top: 12px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
// ──────────────── 잔고 조회 ────────────────
|
||||
function openBalanceModal() {
|
||||
document.getElementById('balanceModal').classList.add('show');
|
||||
loadBalances();
|
||||
}
|
||||
|
||||
function closeBalanceModal() {
|
||||
document.getElementById('balanceModal').classList.remove('show');
|
||||
}
|
||||
|
||||
async function loadBalances() {
|
||||
const content = document.getElementById('balanceContent');
|
||||
content.innerHTML = `
|
||||
<div class="loading-state">
|
||||
<div class="loading-spinner"></div>
|
||||
<div>잔고 조회 중...</div>
|
||||
</div>`;
|
||||
|
||||
const wholesalers = [
|
||||
{ id: 'baekje', name: '백제약품', icon: '💉', api: '/api/baekje/balance' },
|
||||
{ id: 'geoyoung', name: '지오영', icon: '🏭', api: '/api/geoyoung/balance' },
|
||||
{ id: 'sooin', name: '수인약품', icon: '💊', api: '/api/sooin/balance' }
|
||||
];
|
||||
|
||||
const results = {};
|
||||
let totalBalance = 0;
|
||||
|
||||
// 병렬로 조회
|
||||
await Promise.all(wholesalers.map(async (ws) => {
|
||||
try {
|
||||
const resp = await fetch(ws.api, { timeout: 30000 });
|
||||
const data = await resp.json();
|
||||
results[ws.id] = data;
|
||||
if (data.success && data.balance) {
|
||||
totalBalance += data.balance;
|
||||
}
|
||||
} catch (err) {
|
||||
results[ws.id] = { success: false, error: err.message };
|
||||
}
|
||||
}));
|
||||
|
||||
// 결과 렌더링
|
||||
let html = '<div class="balance-grid">';
|
||||
|
||||
wholesalers.forEach(ws => {
|
||||
const data = results[ws.id];
|
||||
const isError = !data.success;
|
||||
const balance = data.balance || 0;
|
||||
const prevBalance = data.prev_balance || data.prev_month_balance || 0;
|
||||
|
||||
html += `
|
||||
<div class="balance-card ${isError ? 'error' : ''}">
|
||||
<div class="balance-icon ${ws.id}">${ws.icon}</div>
|
||||
<div class="balance-info">
|
||||
<div class="balance-name">${ws.name}</div>
|
||||
<div class="balance-detail">
|
||||
${isError
|
||||
? `❌ ${data.error || '조회 실패'}`
|
||||
: `전월/전일: ${prevBalance.toLocaleString()}원`}
|
||||
</div>
|
||||
</div>
|
||||
<div class="balance-amount">
|
||||
<div class="balance-value ${ws.id}">
|
||||
${isError ? '-' : balance.toLocaleString()}
|
||||
</div>
|
||||
<div class="balance-label">현재 잔고</div>
|
||||
</div>
|
||||
</div>`;
|
||||
});
|
||||
|
||||
html += `
|
||||
<div class="balance-total">
|
||||
<div class="balance-total-label">총 미수금</div>
|
||||
<div class="balance-total-value">${totalBalance.toLocaleString()}원</div>
|
||||
</div>
|
||||
<div class="balance-updated">🕐 ${new Date().toLocaleString('ko-KR')}</div>
|
||||
</div>`;
|
||||
|
||||
content.innerHTML = html;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user