운영자 화면의 대기 상태 및 통계 기능을 요청하신 대로 세분화하여 업데이트

This commit is contained in:
2026-01-05 04:30:37 +09:00
parent b868603280
commit d60017ca30
2 changed files with 38 additions and 37 deletions

View File

@@ -238,7 +238,9 @@ try {
SELECT
COALESCE(SUM(contract_amount), 0) as total_sales,
COALESCE(SUM(payout_amount), 0) as total_comm, -- 정산 지급액 합계
COUNT(*) as total_count
COUNT(*) as total_count,
SUM(CASE WHEN join_approved = 0 THEN 1 ELSE 0 END) as pending_join,
SUM(CASE WHEN join_approved = 1 AND payment_approved = 0 THEN 1 ELSE 0 END) as pending_payment
FROM sales_tenant_products
");
$tpData = $stmt->fetch(PDO::FETCH_ASSOC);
@@ -256,7 +258,9 @@ try {
$totalStats = [
'totalSales' => $tpData['total_sales'] + $srData['total_sales'],
'totalCommission' => $tpData['total_comm'] + $srData['total_comm'],
'totalCount' => $tpData['total_count'] + $srData['total_count']
'totalCount' => $tpData['total_count'] + $srData['total_count'],
'pendingJoin' => (int)($tpData['pending_join'] ?? 0),
'pendingPayment' => (int)($tpData['pending_payment'] ?? 0)
];
} else {
$totalStats = calculateTotalStats($pdo, $rootUserId, $rootUserId, 0);

View File

@@ -430,10 +430,8 @@
totalSales: 0,
totalCommission: 0,
totalCount: 0,
monthlySales: 0,
monthlyCommission: 0,
monthlyCount: 0,
pendingApprovals: 0
pendingJoin: 0,
pendingPayment: 0
});
useEffect(() => {
@@ -442,34 +440,17 @@
const fetchOperatorDashboard = async () => {
try {
// Fetch global stats
// Fetch global stats including pending counts from backend
const res = await fetch(`api/get_performance.php`);
const result = await res.json();
// Fetch tenant product statistics for pending count
const tenantRes = await fetch('api/sales_tenants.php?action=list_tenants');
const tenantData = await tenantRes.json();
let pendingCount = 0;
if (tenantData.success) {
for (const tenant of tenantData.data) {
const prodRes = await fetch(`api/sales_tenants.php?action=tenant_products&tenant_id=${tenant.id}`);
const prodData = await prodRes.json();
if (prodData.success) {
pendingCount += prodData.data.filter(p => p.join_approved == 0 || p.payment_approved == 0).length;
}
}
}
if (result.success && result.total_stats) {
setOperatorStats({
totalSales: result.total_stats.totalSales || 0,
totalCommission: result.total_stats.totalCommission || 0,
totalCount: result.total_stats.totalCount || 0,
monthlySales: result.period_stats?.total_period_commission || 0, // Just a placeholder for monthly
monthlyCommission: result.period_stats?.total_period_commission || 0,
monthlyCount: 0,
pendingApprovals: pendingCount
pendingJoin: result.total_stats.pendingJoin || 0,
pendingPayment: result.total_stats.pendingPayment || 0
});
}
} catch (err) {
@@ -495,7 +476,7 @@
</button>
</div>
{/* Dashboard Metrics */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-6 mb-8">
<StatCard
title="전체 누적 매출"
value={formatCurrency(operatorStats.totalSales)}
@@ -503,10 +484,10 @@
icon={<LucideIcon name="trending-up" className="w-5 h-5" />}
/>
<StatCard
title="전체 지급 수당"
title="지급 완료 수당"
value={formatCurrency(operatorStats.totalCommission)}
subtext="영업 인력에게 지급된 총액"
icon={<LucideIcon name="wallet" className="w-5 h-5" />}
subtext="최종 지급 승인된 총액"
icon={<LucideIcon name="wallet" className="w-5 h-5 text-emerald-500" />}
/>
<StatCard
title="전체 계약 건수"
@@ -514,17 +495,33 @@
subtext="활성 테넌트 계약 총계"
icon={<LucideIcon name="file-check" className="w-5 h-5" />}
/>
<div className={`bg-white rounded-card p-6 shadow-sm border ${operatorStats.pendingApprovals > 0 ? 'border-red-200 bg-red-50/10' : 'border-slate-100'}`}>
{/* 가입 승인 대기 */}
<div className={`bg-white rounded-card p-6 shadow-sm border ${operatorStats.pendingJoin > 0 ? 'border-amber-200 bg-amber-50/10' : 'border-slate-100'}`}>
<div className="flex items-start justify-between mb-4">
<h3 className="text-sm font-medium text-slate-500">대기 승인</h3>
<div className={`p-2 rounded-lg ${operatorStats.pendingApprovals > 0 ? 'bg-red-100 text-red-600' : 'bg-slate-100 text-slate-400'}`}>
<LucideIcon name="alert-circle" className="w-5 h-5" />
<h3 className="text-sm font-medium text-slate-500">가입 대기</h3>
<div className={`p-2 rounded-lg ${operatorStats.pendingJoin > 0 ? 'bg-amber-100 text-amber-600' : 'bg-slate-100 text-slate-400'}`}>
<LucideIcon name="user-plus" className="w-5 h-5" />
</div>
</div>
<div className={`text-2xl font-black mb-1 ${operatorStats.pendingApprovals > 0 ? 'text-red-600' : 'text-slate-900'}`}>
{operatorStats.pendingApprovals}
<div className={`text-2xl font-black mb-1 ${operatorStats.pendingJoin > 0 ? 'text-amber-600' : 'text-slate-900'}`}>
{operatorStats.pendingJoin}
</div>
<div className="text-xs text-slate-400">즉시 검토가 필요한 계약 </div>
<div className="text-xs text-slate-400">신규 가입 검토 대기</div>
</div>
{/* 지급 승인 대기 */}
<div className={`bg-white rounded-card p-6 shadow-sm border ${operatorStats.pendingPayment > 0 ? 'border-rose-200 bg-rose-50/10' : 'border-slate-100'}`}>
<div className="flex items-start justify-between mb-4">
<h3 className="text-sm font-medium text-slate-500">지급 승인 대기</h3>
<div className={`p-2 rounded-lg ${operatorStats.pendingPayment > 0 ? 'bg-rose-100 text-rose-600' : 'bg-slate-100 text-slate-400'}`}>
<LucideIcon name="credit-card" className="w-5 h-5" />
</div>
</div>
<div className={`text-2xl font-black mb-1 ${operatorStats.pendingPayment > 0 ? 'text-rose-600' : 'text-slate-900'}`}>
{operatorStats.pendingPayment}
</div>
<div className="text-xs text-slate-400">수당 지급 검토 대기</div>
</div>
</div>