113 lines
5.0 KiB
TypeScript
113 lines
5.0 KiB
TypeScript
import { Head, useForm } from '@inertiajs/react';
|
||
import { Clock3, Save, ShieldCheck } from 'lucide-react';
|
||
import type { FormEvent } from 'react';
|
||
import InputError from '@/components/input-error';
|
||
import { PageHeading } from '@/components/page-heading';
|
||
import { Button } from '@/components/ui/button';
|
||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||
import { Input } from '@/components/ui/input';
|
||
|
||
type Definition = {
|
||
label: string;
|
||
description: string;
|
||
default: number;
|
||
min: number;
|
||
max: number;
|
||
unit: string;
|
||
};
|
||
|
||
export default function ReservationPolicyPage({
|
||
definitions,
|
||
values,
|
||
}: {
|
||
definitions: Record<string, Definition>;
|
||
values: Record<string, number>;
|
||
}) {
|
||
const form = useForm(values);
|
||
|
||
function submit(event: FormEvent) {
|
||
event.preventDefault();
|
||
form.put('/administracao/regras', { preserveScroll: true });
|
||
}
|
||
|
||
return (
|
||
<>
|
||
<Head title="Regras de reserva" />
|
||
<main className="mx-auto flex w-full max-w-5xl flex-1 flex-col gap-7 p-5 sm:p-8">
|
||
<PageHeading
|
||
eyebrow="Administração"
|
||
title="Regras de reserva"
|
||
description="Parâmetros aplicados centralmente a novos pedidos, conflitos temporais e prazos de aprovação."
|
||
/>
|
||
|
||
<div className="flex gap-3 rounded-xl border border-sky-200 bg-sky-50 p-4 text-sm text-sky-900 dark:bg-sky-950/30 dark:text-sky-100">
|
||
<ShieldCheck className="mt-0.5 size-5 shrink-0" />
|
||
<p>
|
||
As margens já gravadas permanecem associadas às reservas
|
||
existentes. Alterações entram em vigor imediatamente
|
||
para novas requisições.
|
||
</p>
|
||
</div>
|
||
|
||
<form onSubmit={submit} className="space-y-5">
|
||
<div className="grid gap-4 md:grid-cols-2">
|
||
{Object.entries(definitions).map(
|
||
([key, definition]) => (
|
||
<Card key={key} className="gap-4 shadow-none">
|
||
<CardHeader>
|
||
<CardTitle className="flex items-center gap-2 text-base">
|
||
<Clock3 className="size-4 text-primary" />
|
||
{definition.label}
|
||
</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="space-y-3">
|
||
<p className="min-h-10 text-sm text-muted-foreground">
|
||
{definition.description}
|
||
</p>
|
||
<div className="flex items-center gap-3">
|
||
<Input
|
||
type="number"
|
||
min={definition.min}
|
||
max={definition.max}
|
||
value={form.data[key]}
|
||
onChange={(event) =>
|
||
form.setData(
|
||
key,
|
||
Number(
|
||
event.target.value,
|
||
),
|
||
)
|
||
}
|
||
/>
|
||
<span className="min-w-24 text-sm text-muted-foreground">
|
||
{definition.unit}
|
||
</span>
|
||
</div>
|
||
<InputError
|
||
message={form.errors[key]}
|
||
/>
|
||
<p className="text-xs text-muted-foreground">
|
||
Intervalo permitido:{' '}
|
||
{definition.min}–{definition.max}
|
||
</p>
|
||
</CardContent>
|
||
</Card>
|
||
),
|
||
)}
|
||
</div>
|
||
<Button type="submit" disabled={form.processing}>
|
||
<Save /> Guardar e aplicar regras
|
||
</Button>
|
||
</form>
|
||
</main>
|
||
</>
|
||
);
|
||
}
|
||
|
||
ReservationPolicyPage.layout = {
|
||
breadcrumbs: [
|
||
{ title: 'Administração', href: '/administracao/regras' },
|
||
{ title: 'Regras de reserva', href: '/administracao/regras' },
|
||
],
|
||
};
|