import Link from "next/link"; import { redirect } from "next/navigation"; import { getTranslations } from "next-intl/server"; import { AlarmClock, CalendarDays, CheckCheck, ClipboardCheck, ClipboardList, Hourglass, PenLine, Receipt, RefreshCw, Siren, Wrench, type LucideIcon, } from "lucide-react"; import { PageHead } from "@/components/mockup-ui"; import { buttonCls } from "@/components/work-orders/button-cls"; import { pageContext } from "@/components/work-orders/page-context"; import { Field, inputCls } from "@/components/work-orders/ui"; import { isoDay, parseListParams, toQuery, type Preset } from "@/lib/work-orders/filters"; import { WORK_ORDER_PRIORITIES } from "@/lib/work-orders/schemas"; import { getDashboardTiles } from "@/server/services/work-orders/dashboard"; import { customerDisplayName, customerFilterOptions, teamOptions, userOptions } from "@/server/services/work-orders/options"; import { listOrderTypes } from "@/server/services/work-orders/settings"; type SP = Record; const TILES: { key: Preset | "sync_conflicts"; icon: LucideIcon; tone: string }[] = [ { key: "open", icon: ClipboardList, tone: "var(--ui-primary)" }, { key: "today", icon: CalendarDays, tone: "var(--info)" }, { key: "running", icon: Wrench, tone: "var(--ui-accent)" }, { key: "not_accepted", icon: Hourglass, tone: "var(--warn)" }, { key: "overdue", icon: AlarmClock, tone: "var(--risk)" }, { key: "reports_in_review", icon: ClipboardCheck, tone: "var(--info)" }, { key: "completed", icon: CheckCheck, tone: "var(--ok)" }, { key: "billing", icon: Receipt, tone: "var(--ok)" }, { key: "emergency_new", icon: Siren, tone: "var(--risk)" }, { key: "missing_signatures", icon: PenLine, tone: "var(--warn)" }, { key: "sync_conflicts", icon: RefreshCw, tone: "var(--risk)" }, ]; /** Backoffice dashboard (spec ยง21). Field roles are sent to the mobile start page. */ export default async function DashboardPage({ searchParams }: { searchParams: Promise }) { const { session, ctx, can } = await pageContext(); if (!can("work_order:read_all")) redirect("/m"); const sp = await searchParams; const t = await getTranslations("dashboard"); const tw = await getTranslations("workOrders"); const moduleRow = await ctx.db.tenantModule.findFirst({ where: { moduleKey: "work_orders" }, select: { enabled: true } }); const moduleEnabled = !moduleRow || moduleRow.enabled; const f = parseListParams(sp); const filter = { from: f.from, to: f.to, customerId: f.customerId, teamId: f.teamId, userId: f.userId, orderTypeId: f.orderTypeId, priority: f.priority }; const [tiles, customers, teams, users, orderTypes] = moduleEnabled ? await Promise.all([getDashboardTiles(ctx, filter), customerFilterOptions(ctx), teamOptions(ctx), userOptions(ctx), listOrderTypes(ctx)]) : [null, [], [], [], []]; return (
{sp.module === "disabled" && (

{t("moduleDisabled")}

)} {!tiles ? (

{t("workOrdersDisabled")}

) : ( <>
{t("filterTitle")}
{tw("filter.reset")}
    {TILES.filter((tile) => tile.key !== "sync_conflicts" || can("work_order:write")).map(({ key, icon: Icon, tone }) => { const count = key === "sync_conflicts" ? tiles.syncConflicts : key === "reports_in_review" ? tiles.reportsToReview : tiles[key]; const href = key === "sync_conflicts" ? "/work-orders/conflicts" : key === "emergency_new" && can("emergency:review") ? "/work-orders/emergency-review" : `/work-orders${toQuery({ ...filter, preset: key })}`; return (
  • 0 ? tone : "var(--line)" }} >

    {t(`tiles.${key}`)}

    {count}

    {t(`hints.${key}`)}

  • ); })}
)}
); }