diff --git a/src/pages/subcontractor/SubContractorDashboard.jsx b/src/pages/subcontractor/SubContractorDashboard.jsx index a681de1..84e4adb 100644 --- a/src/pages/subcontractor/SubContractorDashboard.jsx +++ b/src/pages/subcontractor/SubContractorDashboard.jsx @@ -5,7 +5,7 @@ import { useAuth } from '../../context/AuthContext'; import { useMockStore } from '../../data/mockStore'; import { StatCard } from '../../components/StatCard'; import { SpotlightCard } from '../../components/SpotlightCard'; -import { CheckSquare, Clock, Wallet, MapPin, Camera, X, Calendar, DollarSign, ChevronRight, AlertCircle } from 'lucide-react'; +import { CheckSquare, Clock, Wallet, MapPin, Camera, X, Calendar, DollarSign, ChevronRight, AlertCircle, ArrowDown, ArrowUp, FileText, Receipt } from 'lucide-react'; import TaskDetailsModal from '../../components/contractor/TaskDetailsModal'; import FinancialSummaryModal from '../../components/contractor/FinancialSummaryModal'; import { NotificationsPanel } from '../../components/subcontractor/NotificationsPanel'; @@ -239,6 +239,56 @@ const SubContractorDashboard = () => { { date: '2026-02-14', project: '2612 Dunwick Dr — Interior Renovation', clockIn: '7:30 AM', clockOut: '5:00 PM', hours: '9.5' }, ], []); + // Project history & payment tracking + const [historyFilter, setHistoryFilter] = useState('all'); // all | Paid | Requested | Pending + const [historySort, setHistorySort] = useState('desc'); // desc = newest first + const [noteModal, setNoteModal] = useState(null); // { title, body, project, requestedAt, receivedAt, status } + + const projectById = useMemo(() => { + const m = new Map(); + for (const p of projects) m.set(p.id, p); + return m; + }, [projects]); + + const paymentHistoryRows = useMemo(() => { + const items = myAssignments.map(t => { + const project = t.projectId ? projectById.get(t.projectId) : null; + const requestedAt = t.paymentRequestedAt || null; + const receivedAt = t.paidAt || null; + const status = t.paymentStatus === 'Paid' + ? 'Paid' + : (requestedAt ? 'Requested' : 'Pending'); + return { + id: t.id, + projectId: t.projectId || null, + projectName: project ? (project.projectType || project.address) : 'Standalone Task', + projectAddress: project?.address || t.location || '', + requestedAt, + receivedAt, + note: t.title || '', + description: t.description || '', + status, + }; + }); + const filtered = historyFilter === 'all' ? items : items.filter(r => r.status === historyFilter); + const sorted = [...filtered].sort((a, b) => { + const av = a.requestedAt || ''; + const bv = b.requestedAt || ''; + if (av === bv) return 0; + if (!av) return 1; // missing requested dates sink to bottom + if (!bv) return -1; + return historySort === 'desc' ? (bv > av ? 1 : -1) : (av > bv ? 1 : -1); + }); + return sorted; + }, [myAssignments, projectById, historyFilter, historySort]); + + const historyCounts = useMemo(() => ({ + all: myAssignments.length, + Paid: myAssignments.filter(t => t.paymentStatus === 'Paid').length, + Requested: myAssignments.filter(t => t.paymentStatus !== 'Paid' && t.paymentRequestedAt).length, + Pending: myAssignments.filter(t => !t.paymentRequestedAt).length, + }), [myAssignments]); + // Modal states const [detailModal, setDetailModal] = useState({ isOpen: false, type: null, title: '' }); const [selectedTask, setSelectedTask] = useState(null); @@ -324,7 +374,7 @@ const SubContractorDashboard = () => { {/* Main Task List */}
+ Track payment requests and receipts across every project you've worked on. +
+No project history yet.
++ {historyFilter === 'all' ? 'Tasks assigned to you will appear here.' : `No projects with status "${historyFilter}".`} +
+| Project ID | +Project Name | ++ + | +Received | +Note | +Status | +
|---|---|---|---|---|---|
| + + {row.projectId || '—'} + + | +
+
+
+
+ {row.projectName}
+
+ {row.projectAddress && (
+
+ {row.projectAddress}
+
+ )}
+ |
+ + + {row.requestedAt ? new Date(row.requestedAt).toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' }) : '—'} + + | ++ + {row.receivedAt ? new Date(row.receivedAt).toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' }) : 'Not received'} + + | ++ + | ++ + {row.status} + + | +
{noteModal.description}
+ )} +