import { Alert, Box, Button, ColorSwatch, Flex, Group, NumberInput, Paper, Table, Title } from '@mantine/core'; import { MetaFunction, LoaderArgs, redirect, json } from '@remix-run/node'; import { Link, useFetcher, useLoaderData, useNavigate } from '@remix-run/react'; import { getTimeEntriesByDateAndProject } from '~/models/timeEntry.server'; import { getProjects, Project } from '~/models/project.server'; import { requireUserId } from '~/session.server'; import { DateRangePicker, DateRangePickerValue } from '@mantine/dates'; import { useEffect, useState } from 'react'; import dayjs from 'dayjs'; import { Calendar } from 'react-feather'; import { useMediaQuery } from '@mantine/hooks'; import 'dayjs/locale/it'; export const meta: MetaFunction = () => { return { title: 'Reports | WorkTimer', description: 'Generate reports of your time entries. You must be logged in to do this.' }; }; export async function loader({ request }: LoaderArgs) { const userId = await requireUserId(request); if (!userId) return redirect('/login'); const url = new URL(request.url); const dateFrom = url.searchParams.get('dateFrom') ? dayjs(url.searchParams.get('dateFrom')).toDate() : dayjs().startOf('month').toDate(); const dateTo = url.searchParams.get('dateTo') ? dayjs(url.searchParams.get('dateTo')).toDate() : dayjs().endOf('month').toDate(); return json({ timeByProject: await getTimeEntriesByDateAndProject({ userId, dateFrom, dateTo }), projects: await getProjects({ userId }) }); } export default function ReportPage() { const reports = useFetcher(); const [dateRange, setDateRange] = useState([ dayjs().startOf('month').toDate(), dayjs().endOf('month').toDate() ]); useEffect(() => { if (dateRange[0] && dateRange[1]) { reports.load( `/reports?dateFrom=${dayjs(dateRange[0]).format( 'YYYY-MM-DD' )}&dateTo=${dayjs(dateRange[1]).format('YYYY-MM-DD')}` ); } }, [dateRange]); const [costPerHour, setCostPerHour] = useState(); const mobile = useMediaQuery('(max-width: 600px)'); return ( <>

Reports

} mb="md" /> Time per project {reports.data && ( {costPerHour && } {( Object.values(reports.data.timeByProject ?? {}) as { projectId: string; _sum: { duration: number }; }[] ).map((projectData) => ( {costPerHour && ( )} ))}
Project TimeBilling
p.id === projectData.projectId )?.color ?? '#000' } /> {reports.data?.projects?.projects?.find( (p) => p.id === projectData.projectId )?.name ?? 'No project'} {projectData._sum.duration / 1000 / 60 / 60} h {(projectData._sum.duration * costPerHour) / 1000 / 60 / 60}{' '} €
)} ); }