Files
NextChair/src/features/staff/components/time-off-list.tsx
T
2026-08-03 21:15:24 +01:00

99 lines
3.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { Plus } from "lucide-react";
import { useState } from "react";
import { Button } from "@/components/ui/button";
import type { EditableTimeOff, TimeOffActionSet } from "./time-off-form-sheet";
import { TimeOffFormSheet } from "./time-off-form-sheet";
function formatRange(startDate: string, endDate: string): string {
const start = new Date(`${startDate}T00:00:00`);
const end = new Date(`${endDate}T00:00:00`);
const startLabel = start.toLocaleDateString("en-GB", { weekday: "short", day: "numeric", month: "short" });
if (startDate === endDate) return startLabel;
const endLabel = end.toLocaleDateString("en-GB", { weekday: "short", day: "numeric", month: "short" });
return `${startLabel} – ${endLabel}`;
}
export function TimeOffList({
upcoming,
past,
actions,
appointmentHrefBase,
}: {
upcoming: EditableTimeOff[];
past: EditableTimeOff[];
actions?: TimeOffActionSet;
appointmentHrefBase?: string;
}) {
const [sheetOpen, setSheetOpen] = useState(false);
const [editing, setEditing] = useState<EditableTimeOff | null>(null);
const openNew = () => {
setEditing(null);
setSheetOpen(true);
};
const openEdit = (t: EditableTimeOff) => {
setEditing(t);
setSheetOpen(true);
};
return (
<div className="space-y-6">
<Button variant="secondary" className="w-full" onClick={openNew}>
<Plus className="h-4 w-4" aria-hidden="true" />
Add Time Off
</Button>
<div>
<p className="mb-2 text-xs font-bold uppercase tracking-widest text-muted">Upcoming</p>
{upcoming.length === 0 ? (
<p className="text-muted rounded-jumbo border border-line bg-white p-5 text-center text-sm">
No upcoming time off.
</p>
) : (
<ul className="divide-y divide-line rounded-jumbo border border-line bg-white">
{upcoming.map((t) => (
<li key={t.id}>
<button
type="button"
onClick={() => openEdit(t)}
className="flex w-full items-center justify-between gap-4 px-5 py-4 text-left hover:bg-stone"
>
<div>
<p className="text-sm font-bold">{formatRange(t.startDate, t.endDate)}</p>
{t.reason && <p className="text-xs text-muted">{t.reason}</p>}
</div>
</button>
</li>
))}
</ul>
)}
</div>
{past.length > 0 && (
<div>
<p className="mb-2 text-xs font-bold uppercase tracking-widest text-muted">Past</p>
<ul className="divide-y divide-line rounded-jumbo border border-line bg-stone/50">
{past.map((t) => (
<li key={t.id} className="px-5 py-4">
<p className="text-sm font-bold text-muted">{formatRange(t.startDate, t.endDate)}</p>
{t.reason && <p className="text-xs text-muted">{t.reason}</p>}
</li>
))}
</ul>
</div>
)}
<TimeOffFormSheet
key={editing?.id ?? "new"}
open={sheetOpen}
onClose={() => setSheetOpen(false)}
existing={editing}
actions={actions}
appointmentHrefBase={appointmentHrefBase}
/>
</div>
);
}