This commit is contained in:
Stefan Lazic committed 2026-08-03 21:15:24 +01:00
1 parent ec5583f972
commit 546613e677
189 files changed
+9873 -655

No files matched your search

@@ -0,0 +1,61 @@
import type { Metadata } from "next";
import { notFound, redirect } from "next/navigation";
import { auth } from "@/auth";
import { TopNav } from "@/components/navigation/top-nav";
import { prisma } from "@/lib/db/prisma";
import { hasPermission } from "@/lib/auth/permissions";
import { Permission } from "@/generated/prisma/enums";
import { getActingStaff } from "@/lib/staff/get-acting-staff";
import { listTimeOff } from "@/services/staff/staff.service";
import { TimeOffList } from "@/features/staff/components/time-off-list";
import { createOwnerTimeOffActionSet } from "@/features/owner/actions/time-off-action-set";
export const metadata: Metadata = { title: "Staff Time Off" };
export const dynamic = "force-dynamic";
function toCalendarDate(date: Date): string {
return date.toISOString().slice(0, 10);
}
export default async function OwnerStaffTimeOffPage({ params }: { params: Promise<{ id: string }> }) {
const session = await auth();
if (!session?.user) redirect("/sign-in");
const canManage = await hasPermission(session.user.id, Permission.MANAGE_STAFF);
if (!canManage) redirect("/staff");
const owner = await getActingStaff();
if (!owner) redirect("/staff");
const { id } = await params;
const target = await prisma.staffProfile.findFirst({
where: { id, businessId: owner.businessId },
include: { user: { select: { name: true } } },
});
if (!target) notFound();
const { upcoming, past } = await listTimeOff(prisma, id);
// Whole-day rows only — partial-day "Block Time" entries are managed from the owner calendar (see owner-block-time-button.tsx).
const wholeDay = (rows: typeof upcoming) => rows.filter((r) => r.startMinutes === null && r.endMinutes === null);
const toEditable = (rows: typeof upcoming) =>
wholeDay(rows).map((t) => ({
id: t.id,
startDate: toCalendarDate(t.startDate),
endDate: toCalendarDate(t.endDate),
reason: t.reason,
}));
return (
<div className="pb-12">
<TopNav title={`${target.user.name ?? "Staff"} — Time Off`} onBack sticky className="bg-stone" />
<main className="mx-auto max-w-2xl px-6 py-6">
<TimeOffList
upcoming={toEditable(upcoming)}
past={toEditable(past)}
actions={createOwnerTimeOffActionSet(id)}
appointmentHrefBase="/owner/appointments"
/>
</main>
</div>
);
}