feat(project-finance): add finance data export functionality
- Implemented a new endpoint in the project finance controller to export financial data as an Excel file, allowing users to download project finance details. - Enhanced the frontend to include an export button that triggers the finance data export, with appropriate loading states and error handling. - Added functionality to group exported data by status, priority, or phases, improving the usability of the exported reports. - Updated the project finance API service to handle the export request and return the generated Excel file as a Blob.
This commit is contained in:
@@ -49,4 +49,18 @@ export const projectFinanceApiService = {
|
||||
);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
exportFinanceData: async (
|
||||
projectId: string,
|
||||
groupBy: 'status' | 'priority' | 'phases' = 'status'
|
||||
): Promise<Blob> => {
|
||||
const response = await apiClient.get(
|
||||
`${rootUrl}/project/${projectId}/export`,
|
||||
{
|
||||
params: { groupBy },
|
||||
responseType: 'blob'
|
||||
}
|
||||
);
|
||||
return response.data;
|
||||
},
|
||||
}
|
||||
@@ -1,10 +1,14 @@
|
||||
import { Button, ConfigProvider, Flex, Select, Typography } from 'antd';
|
||||
import { Button, ConfigProvider, Flex, Select, Typography, message } from 'antd';
|
||||
import GroupByFilterDropdown from './group-by-filter-dropdown';
|
||||
import { DownOutlined } from '@ant-design/icons';
|
||||
import { useAppDispatch } from '../../../../../hooks/useAppDispatch';
|
||||
import { useAppSelector } from '../../../../../hooks/useAppSelector';
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { changeCurrency, toggleImportRatecardsDrawer } from '@/features/finance/finance-slice';
|
||||
import { projectFinanceApiService } from '@/api/project-finance-ratecard/project-finance.api.service';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useState } from 'react';
|
||||
|
||||
type ProjectViewFinanceHeaderProps = {
|
||||
activeTab: 'finance' | 'ratecard';
|
||||
@@ -21,8 +25,50 @@ const ProjectViewFinanceHeader = ({
|
||||
}: ProjectViewFinanceHeaderProps) => {
|
||||
// localization
|
||||
const { t } = useTranslation('project-view-finance');
|
||||
const { projectId } = useParams<{ projectId: string }>();
|
||||
const [exporting, setExporting] = useState(false);
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const { project } = useAppSelector(state => state.projectReducer);
|
||||
|
||||
const handleExport = async () => {
|
||||
if (!projectId) {
|
||||
message.error('Project ID not found');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
setExporting(true);
|
||||
const blob = await projectFinanceApiService.exportFinanceData(projectId, activeGroup);
|
||||
|
||||
// Get project name from Redux state
|
||||
const projectName = project?.name || 'Unknown_Project';
|
||||
|
||||
// Create filename with project name, date and time
|
||||
const sanitizedProjectName = projectName.replace(/[^a-zA-Z0-9\s]/g, '').replace(/\s+/g, '_');
|
||||
const dateTime = new Date().toISOString().replace(/[:.]/g, '-').split('T');
|
||||
const date = dateTime[0];
|
||||
const time = dateTime[1].split('.')[0];
|
||||
const filename = `${sanitizedProjectName}_Finance_Data_${date}_${time}.xlsx`;
|
||||
|
||||
// Create download link
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = filename;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
window.URL.revokeObjectURL(url);
|
||||
|
||||
message.success('Finance data exported successfully');
|
||||
} catch (error) {
|
||||
console.error('Export failed:', error);
|
||||
message.error('Failed to export finance data');
|
||||
} finally {
|
||||
setExporting(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<ConfigProvider wave={{ disabled: true }}>
|
||||
@@ -52,7 +98,13 @@ const ProjectViewFinanceHeader = ({
|
||||
</Flex>
|
||||
|
||||
{activeTab === 'finance' ? (
|
||||
<Button type="primary" icon={<DownOutlined />} iconPosition="end">
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<DownOutlined />}
|
||||
iconPosition="end"
|
||||
loading={exporting}
|
||||
onClick={handleExport}
|
||||
>
|
||||
{t('exportButton')}
|
||||
</Button>
|
||||
) : (
|
||||
|
||||
Reference in New Issue
Block a user