diff --git a/src/components/dashboard/reimbursement/ReimbursementManagementPortal.tsx b/src/components/dashboard/reimbursement/ReimbursementManagementPortal.tsx index c0888e1..e46bbe1 100644 --- a/src/components/dashboard/reimbursement/ReimbursementManagementPortal.tsx +++ b/src/components/dashboard/reimbursement/ReimbursementManagementPortal.tsx @@ -32,6 +32,10 @@ interface FilterOptions { dateRange: 'all' | 'week' | 'month' | 'year'; sortBy: 'date_of_purchase' | 'total_amount' | 'status'; sortOrder: 'asc' | 'desc'; + hidePaid: boolean; // Auto-hide paid reimbursements + hideRejected: boolean; // Auto-hide rejected reimbursements + compactView: boolean; // Toggle for compact list view + search: string; // Search query } interface ItemizedExpense { @@ -53,7 +57,11 @@ export default function ReimbursementManagementPortal() { department: [], dateRange: 'all', sortBy: 'date_of_purchase', - sortOrder: 'desc' + sortOrder: 'desc', + hidePaid: true, + hideRejected: true, + compactView: false, + search: '' }); const [auditNote, setAuditNote] = useState(''); const [loadingStatus, setLoadingStatus] = useState(false); @@ -110,6 +118,21 @@ export default function ReimbursementManagementPortal() { filter = `(${statusFilter})`; } + // When searching, don't auto-hide paid/rejected unless explicitly filtered + const isSearching = filters.search.trim().length > 0; + + // Auto-hide paid reimbursements if the option is enabled and not searching + if (filters.hidePaid && !isSearching) { + const hidePaidFilter = 'status != "paid"'; + filter = filter ? `${filter} && ${hidePaidFilter}` : hidePaidFilter; + } + + // Auto-hide rejected reimbursements if the option is enabled and not searching + if (filters.hideRejected && !isSearching) { + const hideRejectedFilter = 'status != "rejected"'; + filter = filter ? `${filter} && ${hideRejectedFilter}` : hideRejectedFilter; + } + if (filters.department.length > 0) { const departmentFilter = filters.department.map(d => `department = "${d}"`).join(' || '); filter = filter ? `${filter} && (${departmentFilter})` : `(${departmentFilter})`; @@ -160,11 +183,10 @@ export default function ReimbursementManagementPortal() { submitter: userMap[record.submitted_by] })); - setReimbursements(enrichedRecords); - // Load associated receipts const receiptIds = enrichedRecords.flatMap(r => r.receipts || []); + let receiptMap: Record = {}; if (receiptIds.length > 0) { try { const receiptRecords = await Promise.all( @@ -200,7 +222,7 @@ export default function ReimbursementManagementPortal() { const validReceipts = receiptRecords.filter((r): r is ExtendedReceipt => r !== null); - const receiptMap = Object.fromEntries( + receiptMap = Object.fromEntries( validReceipts.map(receipt => [receipt.id, receipt]) ); setReceipts(receiptMap); @@ -217,6 +239,52 @@ export default function ReimbursementManagementPortal() { // console.log('No receipt IDs found in reimbursements'); setReceipts({}); } + + // Apply client-side search filtering + let filteredRecords = enrichedRecords; + if (isSearching) { + const searchTerm = filters.search.toLowerCase().trim(); + + filteredRecords = enrichedRecords.filter(record => { + // Search in title + if (record.title.toLowerCase().includes(searchTerm)) return true; + + // Search in submitter name + if (record.submitter?.name?.toLowerCase().includes(searchTerm)) return true; + + // Search in date (multiple formats) + const date = new Date(record.date_of_purchase); + const dateFormats = [ + date.toLocaleDateString(), // Default locale format + date.toLocaleDateString('en-US'), // MM/DD/YYYY + date.toISOString().split('T')[0], // YYYY-MM-DD + date.toDateString(), // "Mon Jan 01 2024" + `${date.getMonth() + 1}/${date.getDate()}/${date.getFullYear()}`, // M/D/YYYY + `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}` // YYYY-MM-DD + ]; + if (dateFormats.some(format => format.toLowerCase().includes(searchTerm))) return true; + + // Search in receipt location names + const reimbursementReceipts = record.receipts?.map(id => receiptMap[id]).filter(Boolean) || []; + if (reimbursementReceipts.some(receipt => + receipt.location_name?.toLowerCase().includes(searchTerm) || + receipt.location_address?.toLowerCase().includes(searchTerm) + )) return true; + + // Search in department + if (record.department.toLowerCase().includes(searchTerm)) return true; + + // Search in status + if (record.status.toLowerCase().replace('_', ' ').includes(searchTerm)) return true; + + // Search in additional info + if (record.additional_info?.toLowerCase().includes(searchTerm)) return true; + + return false; + }); + } + + setReimbursements(filteredRecords); } catch (error) { console.error('Error loading reimbursements:', error); toast.error('Failed to load reimbursements. Please try again later.'); @@ -694,12 +762,59 @@ export default function ReimbursementManagementPortal() {

Reimbursement Requests

- - {reimbursements.length} Total - +
+ + {reimbursements.length} Total + + {filters.hidePaid && ( + + + Paid Hidden + + )} + {filters.hideRejected && ( + + + Rejected Hidden + + )} +
+ {/* Search Bar */} +
+
+
+ +
+ setFilters(prev => ({ ...prev, search: e.target.value }))} + /> + {filters.search && ( + + )} +
+ {filters.search && ( +
+ + + Search includes all reimbursements (including paid/rejected) + +
+ )} +
+ + {/* Status Filter */}
@@ -755,6 +870,7 @@ export default function ReimbursementManagementPortal() {
+ {/* Department Filter */}
@@ -807,6 +923,7 @@ export default function ReimbursementManagementPortal() {
+ {/* Date Range Filter */}
@@ -825,7 +942,8 @@ export default function ReimbursementManagementPortal() {
-
+ {/* Sort Controls */} +
@@ -851,6 +969,54 @@ export default function ReimbursementManagementPortal() {
+ + {/* Additional Filter Options */} +
+
+ +
+ +
+ +
+ +
+ +
+
{loading ? ( @@ -874,7 +1040,7 @@ export default function ReimbursementManagementPortal() { ) : ( -
+
{reimbursements.map((reimbursement, index) => ( setSelectedReimbursement(reimbursement)} > -
-
-
-

+ {filters.compactView ? ( + // Compact Grid View +
+
+

{reimbursement.title}

-
-
- - {new Date(reimbursement.date_of_purchase).toLocaleDateString()} -
-
- - {reimbursement.department} -
+
+ {new Date(reimbursement.date_of_purchase).toLocaleDateString()} + + ${reimbursement.total_amount.toFixed(2)} + +
+
+ + {reimbursement.status.replace('_', ' ')} +
-
- - ${reimbursement.total_amount.toFixed(2)} - - - - {reimbursement.status.replace('_', ' ')} - +
+ ) : ( + // Regular View +
+
+
+

+ {reimbursement.title} +

+
+
+ + {new Date(reimbursement.date_of_purchase).toLocaleDateString()} +
+
+ + {reimbursement.department} +
+
+
+
+ + ${reimbursement.total_amount.toFixed(2)} + + + + {reimbursement.status.replace('_', ' ')} + +
-
+ )} ))}
@@ -1710,4 +1905,4 @@ export default function ReimbursementManagementPortal() { )}

); -} \ No newline at end of file +} \ No newline at end of file