Skip to content

Commit e48caeb

Browse files
committed
Add CSV Download Button
1 parent 46dae7c commit e48caeb

3 files changed

Lines changed: 51 additions & 4 deletions

File tree

src/frontend/src/apis/finance.api.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
} from './transformers/reimbursement-requests.transformer';
1818
import { saveAs } from 'file-saver';
1919
import { PDFDocument, PDFImage } from 'pdf-lib';
20-
import { ExpenseType } from 'shared';
20+
import { ExpenseType, ReimbursementRequest } from 'shared';
2121

2222
enum AllowedFileType {
2323
JPEG = 'image/jpeg',
@@ -136,7 +136,7 @@ export const getCurrentUserReimbursementRequests = () => {
136136
* Gets all the reimbursement requests
137137
*/
138138
export const getAllReimbursementRequests = () => {
139-
return axios.get(apiUrls.financeEndpoints(), {
139+
return axios.get<ReimbursementRequest[]>(apiUrls.financeEndpoints(), {
140140
transformResponse: (data) => JSON.parse(data).map(reimbursementRequestTransformer)
141141
});
142142
};

src/frontend/src/hooks/finance.hooks.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@ import {
3939
Vendor,
4040
ReimbursementStatus,
4141
OtherReimbursementProductCreateArgs,
42-
WbsReimbursementProductCreateArgs
42+
WbsReimbursementProductCreateArgs,
43+
ReimbursementStatusType
4344
} from 'shared';
45+
import { fullNamePipe } from '../utils/pipes';
4446

4547
export interface CreateReimbursementRequestPayload {
4648
vendorId: string;
@@ -356,6 +358,31 @@ export const useDownloadPDFOfImages = () => {
356358
});
357359
};
358360

361+
export const useDownloadCSVFileOfReimbursementRequests = () => {
362+
return useMutation(['reimbursement-requests'], async () => {
363+
const { data } = await getAllReimbursementRequests();
364+
const csvContent =
365+
'data:text/csv;charset=utf-8,' +
366+
'SABO ID,Recipient,Total Cost,Status,Account,Date Created,Date Delivered,Date Submitted,Vendor\n' +
367+
data
368+
.map(
369+
(rr) =>
370+
`${rr.saboId},${fullNamePipe(rr.recipient)},${rr.totalCost},${
371+
rr.reimbursementStatuses[rr.reimbursementStatuses.length - 1].type
372+
},${rr.account},${rr.dateCreated},${rr.dateDelivered ?? ''},${
373+
rr.reimbursementStatuses.find((rs) => rs.type === ReimbursementStatusType.SABO_SUBMITTED)?.dateCreated ?? ''
374+
},${rr.vendor.name}`
375+
)
376+
.join('\n');
377+
const encodedUri = encodeURI(csvContent);
378+
const link = document.createElement('a');
379+
link.setAttribute('href', encodedUri);
380+
link.setAttribute('download', 'reimbursement-requests.csv');
381+
document.body.appendChild(link);
382+
link.click();
383+
});
384+
};
385+
359386
/**
360387
* Custom react hook to get the list of Reimbursement Requests that are pending Advisor Approval
361388
*

src/frontend/src/pages/FinancePage/FinancePage.tsx

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import ReimbursementRequestTable from './ReimbursementRequestsSection';
1616
import {
1717
useAllReimbursementRequests,
1818
useCurrentUserReimbursementRequests,
19+
useDownloadCSVFileOfReimbursementRequests,
1920
useGetPendingAdvisorList
2021
} from '../../hooks/finance.hooks';
2122
import ErrorPage from '../ErrorPage';
@@ -26,9 +27,10 @@ import { routes } from '../../utils/routes';
2627
import ReportRefundModal from './FinanceComponents/ReportRefundModal';
2728
import GenerateReceiptsModal from './FinanceComponents/GenerateReceiptsModal';
2829
import PendingAdvisorModal from './FinanceComponents/PendingAdvisorListModal';
29-
import { isGuest } from 'shared';
30+
import { isAdmin, isGuest } from 'shared';
3031
import WorkIcon from '@mui/icons-material/Work';
3132
import TotalAmountSpentModal from './FinanceComponents/TotalAmountSpentModal';
33+
import { useToast } from '../../hooks/toasts.hooks';
3234

3335
const FinancePage = () => {
3436
const user = useCurrentUser();
@@ -53,6 +55,8 @@ const FinancePage = () => {
5355
isError: allPendingAdvisorListIsError,
5456
error: allPendingAdvisorListError
5557
} = useGetPendingAdvisorList();
58+
const { mutateAsync: downloadCSVFileOfReimbursementRequests } = useDownloadCSVFileOfReimbursementRequests();
59+
const toast = useToast();
5660

5761
const { isFinance } = user;
5862

@@ -83,6 +87,16 @@ const FinancePage = () => {
8387
setAnchorEl(null);
8488
};
8589

90+
const downloadReimbursementRequests = async () => {
91+
try {
92+
await downloadCSVFileOfReimbursementRequests();
93+
} catch (error: unknown) {
94+
if (error instanceof Error) {
95+
toast.error(error.message);
96+
}
97+
}
98+
};
99+
86100
const financeActionsDropdown = (
87101
<>
88102
<NERButton
@@ -136,6 +150,12 @@ const FinancePage = () => {
136150
</ListItemIcon>
137151
Total Amount Spent
138152
</MenuItem>
153+
<MenuItem onClick={async () => await downloadReimbursementRequests()} disabled={!isFinance && !isAdmin(user.role)}>
154+
<ListItemIcon>
155+
<WorkIcon fontSize="small" />
156+
</ListItemIcon>
157+
Download Reimbursement Requests To CSV
158+
</MenuItem>
139159
</Menu>
140160
</>
141161
);

0 commit comments

Comments
 (0)