import { useQuery } from '@tanstack/react-query'
import { FileText, CheckCircle2, AlertTriangle, TrendingUp, Coins, Pencil, Clock, Inbox } from 'lucide-react'
import { useNavigate } from 'react-router-dom'
import { PageHeader } from '@/components/PageHeader'
import { BarChart } from '@/components/BarChart'
import { PhaseBadge } from '@/components/PhaseBadge'
import { useAuth } from '@/contexts/AuthContext'
import { api } from '@/lib/api'
import type { DashboardStats } from '@/types/reports'
type MyDashboard = {
draftsInProgress: number
pendingMyApproval: number
dueSoon: number
overdue: number
draftsTotalValue: number
}
const fmtMoney = (v: number) => {
if (v >= 1_000_000_000) return (v / 1_000_000_000).toFixed(1) + ' tỷ'
if (v >= 1_000_000) return (v / 1_000_000).toFixed(1) + ' tr'
return v.toLocaleString('vi-VN')
}
function StatCard({ icon: Icon, label, value, hint, tone = 'default' }: {
icon: React.ComponentType<{ className?: string }>
label: string
value: React.ReactNode
hint?: string
tone?: 'default' | 'warn' | 'good'
}) {
const toneClass = tone === 'warn' ? 'text-amber-600' : tone === 'good' ? 'text-emerald-600' : 'text-brand-600'
return (
)
}
function MyDashboardRow() {
const navigate = useNavigate()
const { user } = useAuth()
const q = useQuery({
queryKey: ['my-dashboard'],
queryFn: async () => (await api.get('/reports/my-dashboard')).data,
staleTime: 30_000,
})
const d = q.data
if (!d) return null
// Admin thấy everything nhưng card "Tôi đang soạn thảo" + "Chờ tôi duyệt"
// thường = 0 cho admin. Chỉ show row nếu có ít nhất 1 card có giá trị.
const anyValue = d.draftsInProgress + d.pendingMyApproval + d.dueSoon + d.overdue > 0
if (!anyValue && user?.roles.includes('Admin')) return null
return (
Của tôi
)
}
export function DashboardPage() {
const stats = useQuery({
queryKey: ['dashboard-stats'],
queryFn: async () => (await api.get('/reports/dashboard')).data,
staleTime: 60_000,
})
if (stats.isLoading) {
return (
{[1, 2, 3, 4, 5].map(i => (
))}
)
}
const d = stats.data
if (!d) return null
return (
Toàn hệ thống
{/* KPI Cards */}
{/* By Phase */}
HĐ theo phase
{d.byPhase.length === 0 &&
Chưa có HĐ nào
}
{d.byPhase
.slice()
.sort((a, b) => b.count - a.count)
.map(p => {
const total = d.byPhase.reduce((s, x) => s + x.count, 0) || 1
const pct = (p.count / total) * 100
return (
)
})}
{/* Monthly value */}
Giá trị HĐ theo tháng (12 tháng gần nhất)
({
label: `${String(m.month).padStart(2, '0')}/${m.year}`,
value: m.totalValue,
sublabel: `${m.count} HĐ`,
}))}
formatValue={fmtMoney}
/>
{/* Top suppliers */}
Top NCC theo số HĐ
({
label: s.supplierName,
value: s.count,
sublabel: `Tổng ${fmtMoney(s.totalValue)} VND`,
}))}
/>
{/* Top projects */}
Top dự án theo số HĐ
({
label: p.projectName,
value: p.count,
sublabel: `Tổng ${fmtMoney(p.totalValue)} VND`,
}))}
/>
)
}