39157-vm/frontend/src/pages/reports.tsx
2026-03-13 19:43:56 +00:00

117 lines
4.9 KiB
TypeScript

import { mdiChartBar } from '@mdi/js';
import Head from 'next/head';
import React, { ReactElement, useState } from 'react';
import CardBox from '../components/CardBox';
import LayoutAuthenticated from '../layouts/Authenticated';
import SectionMain from '../components/SectionMain';
import SectionTitleLineWithButton from '../components/SectionTitleLineWithButton';
import { getPageTitle } from '../config';
import FormField from '../components/FormField';
import BaseButton from '../components/BaseButton';
import axios from 'axios';
const ReportsPage = () => {
const [reportData, setReportData] = useState(null);
const [loading, setLoading] = useState(false);
const [filters, setFilters] = useState({
startDate: '',
endDate: '',
employeeId: ''
});
const fetchReport = async () => {
setLoading(true);
try {
const response = await axios.post('/reports', filters);
setReportData(response.data);
} catch (error) {
console.error('Failed to fetch report:', error);
} finally {
setLoading(false);
}
};
return (
<>
<Head>
<title>{getPageTitle('Payroll Reports')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartBar} title='Payroll Reports' main>
{''}
</SectionTitleLineWithButton>
<CardBox className="mb-6">
<div className="grid grid-cols-1 md:grid-cols-4 gap-6">
<FormField label="Start Date">
<input type="date" value={filters.startDate} onChange={e => setFilters({...filters, startDate: e.target.value})} className="px-3 py-2 border border-gray-300 rounded w-full" />
</FormField>
<FormField label="End Date">
<input type="date" value={filters.endDate} onChange={e => setFilters({...filters, endDate: e.target.value})} className="px-3 py-2 border border-gray-300 rounded w-full" />
</FormField>
<FormField label="Employee ID">
<input type="text" value={filters.employeeId} onChange={e => setFilters({...filters, employeeId: e.target.value})} className="px-3 py-2 border border-gray-300 rounded w-full" />
</FormField>
<div className="flex items-end">
<BaseButton label="Generate Report" color="info" onClick={fetchReport} disabled={loading} className="w-full" />
</div>
</div>
</CardBox>
{reportData && (
<>
<CardBox className="mb-6">
<h2 className="text-xl font-bold mb-4">Summary</h2>
<div className="grid grid-cols-3 gap-4">
<div className="p-4 bg-gray-100 rounded">
<p className="text-sm text-gray-500">Total Gross Pay</p>
<p className="text-2xl font-semibold">${reportData.summary.totalGrossPay.toFixed(2)}</p>
</div>
<div className="p-4 bg-gray-100 rounded">
<p className="text-sm text-gray-500">Total Hours</p>
<p className="text-2xl font-semibold">{reportData.summary.totalHours.toFixed(2)}</p>
</div>
<div className="p-4 bg-gray-100 rounded">
<p className="text-sm text-gray-500">Total Work Comp</p>
<p className="text-2xl font-semibold">${reportData.summary.totalWorkersComp.toFixed(2)}</p>
</div>
</div>
</CardBox>
<CardBox>
<h2 className="text-xl font-bold mb-4">Line Items</h2>
<div className="overflow-x-auto">
<table className="w-full text-left">
<thead>
<tr>
<th className="p-2 border-b">Employee</th>
<th className="p-2 border-b">Hours</th>
<th className="p-2 border-b">Gross Pay</th>
<th className="p-2 border-b">Work Comp Amount</th>
<th className="p-2 border-b">Created At</th>
</tr>
</thead>
<tbody>
{reportData.lineItems.map((item: any) => (
<tr key={item.id}>
<td className="p-2 border-b">{item.employee?.firstName} {item.employee?.lastName || ''}</td>
<td className="p-2 border-b">{item.total_hours}</td>
<td className="p-2 border-b">${item.gross_pay}</td>
<td className="p-2 border-b">${item.workers_comp_amount}</td>
<td className="p-2 border-b">{new Date(item.createdAt).toLocaleDateString()}</td>
</tr>
))}
</tbody>
</table>
</div>
</CardBox>
</>
)}
</SectionMain>
</>
);
};
ReportsPage.getLayout = function getLayout(page: ReactElement) {
return <LayoutAuthenticated>{page}</LayoutAuthenticated>;
};
export default ReportsPage;