Files
GSB-Construction/resources/js/Components/Dashboard/ContractorDashboardView.tsx

126 lines
8.3 KiB
TypeScript

import React from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '@/Components/ui/card';
import { Link } from '@inertiajs/react';
import { FileText, DollarSign, Layers, ArrowRight, CheckCircle2 } from 'lucide-react';
import { formatCurrency } from '@/lib/utils';
interface ContractorDashboardViewProps {
analytics: any;
activities: any[];
}
export default function ContractorDashboardView({ analytics, activities }: ContractorDashboardViewProps) {
return (
<div className="space-y-6">
{/* Subcontractor Financial & Bidding Summary */}
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
<Card className="bg-white dark:bg-gray-900 border border-gray-100 dark:border-gray-800 shadow-sm">
<CardContent className="p-4 flex items-center justify-between">
<div>
<p className="text-xs uppercase font-semibold text-gray-500 dark:text-gray-400">Active Bids</p>
<h4 className="text-2xl font-black mt-1 text-gray-900 dark:text-white">{analytics?.bidding?.open_invitations} Invitations</h4>
<p className="text-xs text-gray-500 mt-1">{analytics?.bidding?.active_packages} packages total</p>
</div>
<FileText className="w-8 h-8 text-indigo-600 dark:text-indigo-400" />
</CardContent>
</Card>
<Card className="bg-white dark:bg-gray-900 border border-gray-100 dark:border-gray-800 shadow-sm">
<CardContent className="p-4 flex items-center justify-between">
<div>
<p className="text-xs uppercase font-semibold text-gray-500 dark:text-gray-400">Submitted Billing</p>
<h4 className="text-2xl font-black mt-1 text-gray-900 dark:text-white">{formatCurrency(analytics?.financials?.total_billed)}</h4>
<p className="text-xs text-gray-500 mt-1">Paid: {formatCurrency(analytics?.financials?.total_paid)}</p>
</div>
<DollarSign className="w-8 h-8 text-emerald-600 dark:text-emerald-400" />
</CardContent>
</Card>
<Card className="bg-white dark:bg-gray-900 border border-gray-100 dark:border-gray-800 shadow-sm">
<CardContent className="p-4 flex items-center justify-between">
<div>
<p className="text-xs uppercase font-semibold text-gray-500 dark:text-gray-400">Retention Remitted / Withheld</p>
<h4 className="text-2xl font-black mt-1 text-rose-600 dark:text-rose-400">-{formatCurrency(analytics?.financials?.total_retention)}</h4>
<p className="text-xs text-gray-500 mt-1">Withheld until final acceptance</p>
</div>
<Layers className="w-8 h-8 text-rose-600 dark:text-rose-400" />
</CardContent>
</Card>
<Card className="bg-white dark:bg-gray-900 border border-gray-100 dark:border-gray-800 shadow-sm">
<CardContent className="p-4 flex items-center justify-between">
<div>
<p className="text-xs uppercase font-semibold text-gray-500 dark:text-gray-400">Documents Hub</p>
<h4 className="text-2xl font-black mt-1 text-gray-900 dark:text-white">{analytics?.logistics?.documents} Shared</h4>
<p className="text-xs text-gray-500 mt-1">Contracts & Specifications</p>
</div>
<FileText className="w-8 h-8 text-sky-600 dark:text-sky-400" />
</CardContent>
</Card>
</div>
{/* Subcontractor Action Desk */}
<div className="grid grid-cols-1 lg:grid-cols-12 gap-6">
<Card className="lg:col-span-8 shadow-sm bg-white dark:bg-gray-900 border border-gray-100 dark:border-gray-800">
<CardHeader className="flex flex-row items-center justify-between border-b border-gray-100 dark:border-gray-800 bg-gray-50/50 dark:bg-gray-800/50">
<div>
<CardTitle className="text-base font-bold text-gray-900 dark:text-white">Subcontractor Activity & Bids</CardTitle>
<p className="text-xs text-gray-500">Track progress claims, bids, and submitted invoices</p>
</div>
<Link href={route('bids.my')} className="text-xs text-emerald-600 dark:text-emerald-400 font-semibold hover:underline flex items-center gap-1">
My Bids Portal <ArrowRight className="w-3.5 h-3.5" />
</Link>
</CardHeader>
<CardContent className="p-0">
{activities && activities.length > 0 ? (
<div className="divide-y divide-gray-100 dark:divide-gray-800">
{activities.slice(0, 6).map((act, idx) => (
<div key={idx} className="p-4 flex items-center justify-between hover:bg-gray-50 dark:hover:bg-gray-800/50">
<div className="flex items-center gap-3">
<CheckCircle2 className="w-4 h-4 text-emerald-500 shrink-0" />
<p className="text-sm font-medium text-gray-900 dark:text-white">{act.title}</p>
</div>
<span className="text-xs text-gray-400 font-medium whitespace-nowrap">{act.time}</span>
</div>
))}
</div>
) : (
<div className="p-8 text-center text-gray-500 text-sm flex flex-col items-center justify-center">
<FileText className="w-8 h-8 text-gray-300 dark:text-gray-600 mb-2" />
<p className="font-semibold text-gray-700 dark:text-gray-300">No recent contractor activity logged</p>
<p className="text-xs text-gray-400 mt-1">Tender invitations, bid submissions, and invoice updates will appear here.</p>
</div>
)}
</CardContent>
</Card>
<Card className="lg:col-span-4 shadow-sm bg-white dark:bg-gray-900 border border-gray-100 dark:border-gray-800">
<CardHeader className="border-b border-gray-100 dark:border-gray-800 bg-gray-50/50 dark:bg-gray-800/50">
<CardTitle className="text-base font-bold text-gray-900 dark:text-white">Contractor Quick Actions</CardTitle>
</CardHeader>
<CardContent className="space-y-3 p-5">
<Link
href="/bids"
className="w-full text-center block text-xs bg-indigo-600 hover:bg-indigo-700 text-white py-2.5 px-3 rounded-lg font-semibold transition-colors shadow-sm"
>
View Active Bids & Bidding Packages
</Link>
<Link
href="/finance"
className="w-full text-center block text-xs bg-emerald-600 hover:bg-emerald-700 text-white py-2.5 px-3 rounded-lg font-semibold transition-colors shadow-sm"
>
Submit Progress Billing / Invoice
</Link>
<Link
href="/documents"
className="w-full text-center block text-xs bg-gray-100 hover:bg-gray-200 dark:bg-gray-800 dark:hover:bg-gray-700 text-gray-900 dark:text-white py-2.5 px-3 rounded-lg font-semibold transition-colors border border-gray-200 dark:border-gray-700"
>
Upload Compliance Documents
</Link>
</CardContent>
</Card>
</div>
</div>
);
}