117 lines
4.9 KiB
TypeScript
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;
|