@@ -28,15 +28,21 @@ import ClearIcon from '@mui/icons-material/Clear';
2828import { useGetMaterialsForWbsElement } from '../../hooks/bom.hooks' ;
2929import { useAllReimbursementRequests } from '../../hooks/finance.hooks' ;
3030import { useSingleProject } from '../../hooks/projects.hooks' ;
31- import { Material , WbsNumber , ReimbursementRequest , WBSElementData , OtherProductReason , equalsWbsNumber } from 'shared' ;
31+ import { Material , WbsNumber , ReimbursementRequest , WBSElementData , equalsWbsNumber } from 'shared' ;
3232
3333interface ProjectSpendingHistoryProps {
3434 wbsNum : WbsNumber ;
3535}
3636
3737const ProjectSpendingHistory : React . FC < ProjectSpendingHistoryProps > = ( { wbsNum } ) => {
3838 const { data : materials , isLoading : materialsLoading , isError : materialsError } = useGetMaterialsForWbsElement ( wbsNum ) ;
39- const { data : allReimbursementRequests , isLoading : rrLoading , isError : rrError } = useAllReimbursementRequests ( ) ;
39+ const {
40+ data : allReimbursementRequests ,
41+ isLoading : rrLoading ,
42+ isError : rrError ,
43+ error : rrErrorDetails
44+ } = useAllReimbursementRequests ( ) ;
45+
4046 const { data : project , isLoading : projectLoading } = useSingleProject ( wbsNum ) ;
4147 const [ openRows , setOpenRows ] = useState < Record < string , boolean > > ( { } ) ;
4248 const [ showFilters , setShowFilters ] = useState ( false ) ;
@@ -50,27 +56,13 @@ const ProjectSpendingHistory: React.FC<ProjectSpendingHistoryProps> = ({ wbsNum
5056 const [ amountMaxFilter , setAmountMaxFilter ] = useState ( '' ) ;
5157
5258 const grouped = useMemo ( ( ) => {
59+ // Return empty array if any required data is missing
5360 if ( ! allReimbursementRequests || ! project ) return [ ] ;
54-
55- // Create a map of reimbursement requests that include both:
56- // 1. Requests with BOM materials for this project
57- // 2. Requests with products linked directly to this project
61+
62+ // Create a map of reimbursement requests that are linked to this project
5863 const requestMap = new Map < string , { request : ReimbursementRequest ; materials : Material [ ] } > ( ) ;
59-
60- // First, add reimbursement requests from BOM materials
61- if ( materials ) {
62- materials . forEach ( ( mat ) => {
63- const rr = mat . reimbursementRequest ;
64- if ( rr ) {
65- if ( ! requestMap . has ( rr . reimbursementRequestId ) ) {
66- requestMap . set ( rr . reimbursementRequestId , { request : rr , materials : [ ] } ) ;
67- }
68- requestMap . get ( rr . reimbursementRequestId ) ! . materials . push ( mat ) ;
69- }
70- } ) ;
71- }
72-
73- // Then, add standalone reimbursement requests linked to this project
64+
65+ // First, find all reimbursement requests that are directly linked to this project
7466 allReimbursementRequests . forEach ( ( rr ) => {
7567 const hasProjectProduct = rr . reimbursementProducts . some ( ( product ) => {
7668 const reason = product . reimbursementProductReason ;
@@ -83,12 +75,23 @@ const ProjectSpendingHistory: React.FC<ProjectSpendingHistoryProps> = ({ wbsNum
8375 }
8476 return false ;
8577 } ) ;
86-
87- if ( hasProjectProduct && ! requestMap . has ( rr . reimbursementRequestId ) ) {
78+
79+ if ( hasProjectProduct ) {
8880 requestMap . set ( rr . reimbursementRequestId , { request : rr , materials : [ ] } ) ;
8981 }
9082 } ) ;
91-
83+
84+ // Then, add BOM materials ONLY for reimbursement requests that are already linked to this project
85+ if ( materials && materials . length > 0 ) {
86+ materials . forEach ( ( mat ) => {
87+ const rr = mat . reimbursementRequest ;
88+ if ( rr && requestMap . has ( rr . reimbursementRequestId ) ) {
89+ // Only add the material if the RR is already linked to this project
90+ requestMap . get ( rr . reimbursementRequestId ) ! . materials . push ( mat ) ;
91+ }
92+ } ) ;
93+ }
94+
9295 return Array . from ( requestMap . values ( ) ) ;
9396 } , [ materials , allReimbursementRequests , project , wbsNum ] ) ;
9497
@@ -97,7 +100,8 @@ const ProjectSpendingHistory: React.FC<ProjectSpendingHistoryProps> = ({ wbsNum
97100 return grouped . filter ( ( { request } ) => {
98101 // Submitter filter
99102 if ( submitterFilter ) {
100- const submitterName = `${ request . recipient ?. firstName } ${ request . recipient ?. lastName } ` || request . recipient ?. email || '' ;
103+ const submitterName =
104+ `${ request . recipient ?. firstName } ${ request . recipient ?. lastName } ` || request . recipient ?. email || '' ;
101105 if ( ! submitterName . toLowerCase ( ) . includes ( submitterFilter . toLowerCase ( ) ) ) {
102106 return false ;
103107 }
@@ -178,10 +182,21 @@ const ProjectSpendingHistory: React.FC<ProjectSpendingHistoryProps> = ({ wbsNum
178182 submitterFilter || statusFilter || dateFromFilter || dateToFilter || amountMinFilter || amountMaxFilter ;
179183
180184 const isLoading = materialsLoading || rrLoading || projectLoading ;
181- const isError = materialsError || rrError ;
182185
183186 if ( isLoading ) return < Typography > Loading spending history...</ Typography > ;
184- if ( isError ) return < Typography color = "error" > Failed to load spending history.</ Typography > ;
187+
188+ // Handle specific errors
189+ if ( rrError ) {
190+ console . error ( 'Failed to load reimbursement requests:' , rrErrorDetails ) ;
191+ return < Typography color = "error" > Failed to load spending history.</ Typography > ;
192+ }
193+
194+ if ( materialsError ) {
195+ console . error ( 'Failed to load materials for project' ) ;
196+ return < Typography color = "error" > Failed to load spending history.</ Typography > ;
197+ }
198+
199+ // If we have no data but no errors, show "no spending history"
185200 if ( ! grouped . length ) return < Typography > No spending history for this project.</ Typography > ;
186201
187202 const handleToggleRow = ( id : string ) => {
@@ -326,12 +341,14 @@ const ProjectSpendingHistory: React.FC<ProjectSpendingHistoryProps> = ({ wbsNum
326341 </ IconButton >
327342 </ TableCell >
328343 < TableCell >
329- < Link
344+ < Link
330345 href = { `/finance/reimbursement-requests/${ request . reimbursementRequestId } ` }
331346 underline = "hover"
332347 color = "primary"
333348 >
334- { `${ request . recipient ?. firstName } ${ request . recipient ?. lastName } ` || request . recipient ?. email || 'N/A' }
349+ { `${ request . recipient ?. firstName } ${ request . recipient ?. lastName } ` ||
350+ request . recipient ?. email ||
351+ 'N/A' }
335352 </ Link >
336353 </ TableCell >
337354 < TableCell > { new Date ( request . dateCreated ) . toLocaleDateString ( ) } </ TableCell >
@@ -372,8 +389,8 @@ const ProjectSpendingHistory: React.FC<ProjectSpendingHistoryProps> = ({ wbsNum
372389 </ Table >
373390 ) : (
374391 < Typography variant = "body2" color = "textSecondary" >
375- This reimbursement request has no associated BOM line items.
376- It may have been created independently or with non-BOM products.
392+ This reimbursement request has no associated BOM line items. It may have been created
393+ independently or with non-BOM products.
377394 </ Typography >
378395 ) }
379396 </ Box >
0 commit comments