feat: complete administration and reporting

This commit is contained in:
2026-08-04 17:40:52 +01:00
parent d829f34580
commit 7a4ac48aaf
42 changed files with 2595 additions and 76 deletions

View File

@@ -10,9 +10,13 @@ const weekdays = ['Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb', 'Dom'];
export default function ReservationCalendar({
month,
reservations,
scope = 'personal',
}: {
month: string;
reservations: Reservation[];
reservations: (Reservation & {
requester?: { name: string; department: string | null };
})[];
scope?: 'personal' | 'global';
}) {
const [year, monthNumber] = month.split('-').map(Number);
const monthStart = new Date(year, monthNumber - 1, 1);
@@ -32,21 +36,35 @@ export default function ReservationCalendar({
}).format(monthStart);
const previousMonth = monthKey(new Date(year, monthNumber - 2, 1));
const nextMonth = monthKey(new Date(year, monthNumber, 1));
const global = scope === 'global';
const calendarUrl = global
? '/calendario-global'
: '/requisicoes/calendario';
return (
<>
<Head title="O meu calendário" />
<Head title={global ? 'Calendário global' : 'O meu calendário'} />
<main className="mx-auto flex w-full max-w-7xl flex-1 flex-col gap-7 p-5 sm:p-8">
<PageHeading
eyebrow="Planeamento pessoal"
title="O meu calendário"
description="Consulte as suas requisições no mês e identifique rapidamente períodos sobrepostos."
eyebrow={
global
? 'Planeamento institucional'
: 'Planeamento pessoal'
}
title={global ? 'Calendário global' : 'O meu calendário'}
description={
global
? 'Visão consolidada de todas as requisições, requisitantes e equipamentos.'
: 'Consulte as suas requisições no mês e identifique rapidamente períodos sobrepostos.'
}
action={
<Button asChild>
<Link href="/requisicoes/nova">
<Plus /> Nova requisição
</Link>
</Button>
!global ? (
<Button asChild>
<Link href="/requisicoes/nova">
<Plus /> Nova requisição
</Link>
</Button>
) : undefined
}
/>
@@ -54,7 +72,7 @@ export default function ReservationCalendar({
<header className="flex items-center justify-between border-b p-4">
<Button asChild variant="outline" size="sm">
<Link
href={`/requisicoes/calendario?month=${previousMonth}`}
href={`${calendarUrl}?month=${previousMonth}`}
>
<ArrowLeft /> Anterior
</Link>
@@ -63,9 +81,7 @@ export default function ReservationCalendar({
{title}
</h2>
<Button asChild variant="outline" size="sm">
<Link
href={`/requisicoes/calendario?month=${nextMonth}`}
>
<Link href={`${calendarUrl}?month=${nextMonth}`}>
Seguinte <ArrowRight />
</Link>
</Button>
@@ -132,6 +148,10 @@ export default function ReservationCalendar({
)}
>
{reservation.reference}
{global &&
reservation.requester
? ` · ${reservation.requester.name}`
: ''}
</div>
))}
{entries.length > 3 && (
@@ -202,8 +222,5 @@ function statusBorder(status: string): string {
}
ReservationCalendar.layout = {
breadcrumbs: [
{ title: 'Requisições', href: '/requisicoes' },
{ title: 'Calendário', href: '/requisicoes/calendario' },
],
breadcrumbs: [{ title: 'Calendário', href: '/requisicoes/calendario' }],
};