feat: complete administration and reporting
This commit is contained in:
@@ -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' }],
|
||||
};
|
||||
|
||||
@@ -21,11 +21,18 @@ export default function CreateReservation({
|
||||
selectedAssetId,
|
||||
period,
|
||||
periodSelected,
|
||||
policy,
|
||||
}: {
|
||||
assets: Asset[];
|
||||
selectedAssetId: number;
|
||||
period: { starts_at?: string; ends_at?: string };
|
||||
periodSelected: boolean;
|
||||
policy: {
|
||||
minNoticeHours: number;
|
||||
maxDurationHours: number;
|
||||
turnaroundMinutes: number;
|
||||
maxAssets: number;
|
||||
};
|
||||
}) {
|
||||
const form = useForm({
|
||||
purpose: '',
|
||||
@@ -70,6 +77,15 @@ export default function CreateReservation({
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
<p className="rounded-xl border bg-muted/40 px-4 py-3 text-sm text-muted-foreground">
|
||||
Regras atuais: antecedência mínima de{' '}
|
||||
{policy.minNoticeHours} h, duração máxima de{' '}
|
||||
{policy.maxDurationHours} h, até {policy.maxAssets}{' '}
|
||||
equipamentos
|
||||
{policy.turnaroundMinutes > 0
|
||||
? ` e margem operacional de ${policy.turnaroundMinutes} min.`
|
||||
: '.'}
|
||||
</p>
|
||||
<form
|
||||
onSubmit={submit}
|
||||
className="grid gap-6 lg:grid-cols-[1fr_320px]"
|
||||
|
||||
Reference in New Issue
Block a user