Files
KAFM-Project/components/dashboard/finance/budget.tsx

201 lines
8.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import {
Database,
FileText,
Activity,
AlertTriangle,
Plus
} from "lucide-react";
import InfoBanner from "@/components/common/infoBanner";
import Button from "@/components/common/button";
import StatCard from "@/components/common/dashStatCard";
import { Card } from '@/components/common/cardWrapper';
import { CardHeader } from '@/components/common/cardHeader';
import { approvalQueueData, categoryData } from "@/constants/constant";
export default function BudgetPortal() {
return (
<div className="my-15 text-slate-100 font-sans">
{/* --- HEADER SECTION WITH BUTTONS --- */}
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4 mb-6">
<div>
<div className="flex items-center gap-2 text-[10px] font-bold tracking-widest text-slate-500 uppercase font-mono">
<span className="text-teal-400">Apple One HQ Tower</span>
<span></span>
<span>FINANCE</span>
<span></span>
<span>O&M BUDGET</span>
</div>
<h1 className="text-2xl font-bold text-white tracking-tight mt-2">
O&M budget management
</h1>
<p className="text-sm font-medium text-slate-400 mt-2 max-w-xl leading-relaxed">
Multi-dimensional budgets by site, department and asset planned vs actual, variance, approvals and overrun alerts.
</p>
</div>
{/* --- HEADER BUTTONS --- */}
<div className="flex items-center gap-2.5 self-start md:mt-6">
<Button className="bg-[#0b1727] hover:bg-slate-800/60 text-slate-200 border border-slate-800 text-xs px-4 py-2 rounded-lg font-semibold transition-colors">
<span>Export</span>
</Button>
<Button className="bg-teal-400 hover:bg-teal-300 text-slate-950 font-bold text-xs px-4 py-2 rounded-lg flex items-center gap-1.5 transition-colors">
<Plus className="w-4 h-4 stroke-[3]" />
<span>New budget</span>
</Button>
</div>
</div>
{/* --- STAT CARDS --- */}
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
{/* Annual budget */}
<StatCard
variant="icon"
title="Annual budget"
value="₹1.91 Cr"
icon={Database}
badgeText="FY 2026"
badgeClassName="text-slate-400 lowercase font-mono"
iconContainerClassName="bg-blue-950/40 border-blue-800/30 text-blue-400"
/>
{/* Spent YTD */}
<StatCard
variant="icon"
title="Spent YTD"
value="₹1.42 Cr"
icon={FileText}
badgeText="74% used"
badgeClassName="text-emerald-400 lowercase font-mono"
iconContainerClassName="bg-emerald-950/40 border-emerald-800/30 text-emerald-400"
/>
{/* Remaining */}
<StatCard
variant="icon"
title="Remaining"
value="₹49.0 L"
icon={Activity}
badgeText="26% left"
badgeClassName="text-slate-400 lowercase font-mono"
iconContainerClassName="bg-amber-950/40 border-amber-800/30 text-amber-400"
/>
{/* Overrun lines */}
<StatCard
variant="icon"
title="Overrun lines"
value="1"
icon={AlertTriangle}
badgeText="review"
badgeClassName="text-rose-400 lowercase font-mono"
iconContainerClassName="bg-rose-950/40 border-rose-900/30 text-rose-400"
/>
</div>
{/* --- BUDGET DETAILS & APPROVAL QUEUE SECTION --- */}
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-8">
{/* Planned vs Actual Table (Left 2 Columns) */}
<Card className="lg:col-span-2 justify-start">
<CardHeader
title="Planned vs actual · by category"
subtitle="CAPEX ₹35.0 L • OPEX ₹1.56 Cr"
/>
<div className="overflow-x-auto mt-2">
<table className="w-full text-left border-collapse">
<thead>
<tr className="border-b border-[#162942]/60 text-[11px] font-mono font-bold text-slate-500 uppercase tracking-wider">
<th className="py-2.5 px-2">Category</th>
<th className="py-2.5 px-2">Type</th>
<th className="py-2.5 px-2 font-mono">Planned</th>
<th className="py-2.5 px-2 font-mono">Actual</th>
<th className="py-2.5 px-2 font-mono">Variance</th>
<th className="py-2.5 px-2 font-mono min-w-[120px]">Utilization</th>
</tr>
</thead>
<tbody className="divide-y divide-[#162942]/40 text-xs">
{categoryData.map((row, idx) => (
<tr key={idx} className="hover:bg-slate-900/30 transition-colors">
<td className="py-3 px-2 font-semibold text-slate-100">
{row.category}
</td>
<td className="py-3 px-2">
<span className="bg-[#12233a] border border-[#1d3554] text-slate-300 font-mono text-[10px] px-2 py-0.5 rounded">
{row.type}
</span>
</td>
<td className="py-3 px-2 font-mono text-slate-300">
{row.planned}
</td>
<td className="py-3 px-2 font-mono text-slate-300">
{row.actual}
</td>
<td className={`py-3 px-2 font-mono font-semibold ${row.varianceColor}`}>
{row.variance}
</td>
<td className="py-3 px-2">
<div className="w-full bg-[#12233a] h-1.5 rounded-full overflow-hidden mb-1">
<div
className={`h-full ${row.barColor}`}
style={{ width: `${Math.min(row.utilization, 100)}%` }}
/>
</div>
<span className="text-[10px] font-mono text-slate-400">
{row.utilization}%
</span>
</td>
</tr>
))}
</tbody>
</table>
</div>
</Card>
{/* Approval Queue Panel (Right 1 Column) */}
<Card className="justify-start">
<CardHeader title="Approval queue" subtitle="multi-level" />
<div className="divide-y divide-[#162942]/60 mt-1">
{approvalQueueData.map((item) => (
<div key={item.id} className="py-3.5 flex items-center justify-between gap-3">
<div>
<h4 className="text-xs font-semibold text-white leading-snug">
{item.title}
</h4>
<p className="text-[11px] font-mono text-slate-500 mt-1">
{item.id} · {item.meta}
</p>
</div>
{item.status === "pending" ? (
<button className="bg-[#12233a] hover:bg-[#1a3252] border border-[#1d3554] text-slate-200 text-xs font-semibold px-3 py-1 rounded transition-colors whitespace-nowrap">
Approve
</button>
) : (
<span className="flex items-center gap-1.5 bg-emerald-950/40 border border-emerald-800/30 text-emerald-400 text-[10px] font-mono font-bold px-2.5 py-1 rounded-full whitespace-nowrap">
<span className="w-1.5 h-1.5 rounded-full bg-emerald-400" />
COMPLETED
</span>
)}
</div>
))}
</div>
</Card>
</div>
{/* Info Banner */}
<div className="my-8">
<InfoBanner
boldText="Utilization %"
normalText=" per category = Actual ÷ Planned × 100 (the bar turns amber past 90%, red on overrun); categories & types are configured in Master Data → Finance. Integration: budget lines link to work orders, purchase orders and vendor invoices — actuals post back automatically and overruns raise an alert to the approver."
/>
</div>
</div>
);
}