운영자 화면의 대기 상태 및 통계 기능을 요청하신 대로 세분화하여 업데이트
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user