diff --git a/apps/web/src/app/(app)/estimates/EstimatesClient.tsx b/apps/web/src/app/(app)/estimates/EstimatesClient.tsx index 32f9dea..6ed7780 100644 --- a/apps/web/src/app/(app)/estimates/EstimatesClient.tsx +++ b/apps/web/src/app/(app)/estimates/EstimatesClient.tsx @@ -8,7 +8,7 @@ import type { inferRouterOutputs } from "@trpc/server"; import { clsx } from "clsx"; import { EstimateWizard } from "~/components/estimates/EstimateWizard.js"; import { usePermissions } from "~/hooks/usePermissions.js"; -import { formatDateLong } from "~/lib/format.js"; +import { formatDateLong, formatMoney } from "~/lib/format.js"; import { trpc } from "~/lib/trpc/client.js"; type RouterOutput = inferRouterOutputs; @@ -30,14 +30,6 @@ const VERSION_STYLES: Record = { SUPERSEDED: "bg-zinc-200 text-zinc-700", }; -function formatMoney(cents: number | null | undefined, currency = "EUR") { - return new Intl.NumberFormat("de-DE", { - style: "currency", - currency, - maximumFractionDigits: 0, - }).format((cents ?? 0) / 100); -} - function formatMetricValue(metric: EstimateDetail["versions"][number]["metrics"][number]) { if (metric.valueCents != null) { return formatMoney(metric.valueCents, metric.currency ?? "EUR"); diff --git a/apps/web/src/components/admin/RateCardsClient.tsx b/apps/web/src/components/admin/RateCardsClient.tsx index 9da33d8..ffc34da 100644 --- a/apps/web/src/components/admin/RateCardsClient.tsx +++ b/apps/web/src/components/admin/RateCardsClient.tsx @@ -1,6 +1,7 @@ "use client"; import { useState } from "react"; +import { formatCents } from "~/lib/format.js"; import { trpc } from "~/lib/trpc/client.js"; // ─── Local types ──────────────────────────────────────────────────────────── @@ -86,11 +87,6 @@ const emptyLine: EditingLine = { machineRateCents: 0, }; -function formatCents(cents: number | null | undefined): string { - if (cents == null) return "-"; - return (cents / 100).toFixed(2); -} - function formatDate(d: string | null | undefined): string { if (!d) return "-"; return new Date(d).toLocaleDateString("de-DE"); diff --git a/apps/web/src/components/allocations/AllocationModal.tsx b/apps/web/src/components/allocations/AllocationModal.tsx index b953d58..146e526 100644 --- a/apps/web/src/components/allocations/AllocationModal.tsx +++ b/apps/web/src/components/allocations/AllocationModal.tsx @@ -2,6 +2,7 @@ import { useState, useEffect, useRef } from "react"; import { useFocusTrap } from "~/hooks/useFocusTrap.js"; +import { useInvalidatePlanningViews } from "~/hooks/useInvalidatePlanningViews.js"; import { AllocationStatus } from "@planarchy/shared"; import type { AllocationWithDetails, RecurrencePattern } from "@planarchy/shared"; import { trpc } from "~/lib/trpc/client.js"; @@ -64,17 +65,7 @@ export function AllocationModal({ allocation, onClose, onSuccess }: AllocationMo { staleTime: 60_000 }, ); - const utils = trpc.useUtils(); - const invalidatePlanningViews = () => { - void utils.allocation.list.invalidate(); - void (utils as { allocation: { listView: { invalidate: () => Promise } } }).allocation.listView.invalidate(); - void utils.allocation.listDemands.invalidate(); - void utils.allocation.listAssignments.invalidate(); - void utils.timeline.getEntries.invalidate(); - void utils.timeline.getEntriesView.invalidate(); - void utils.timeline.getProjectContext.invalidate(); - void utils.timeline.getBudgetStatus.invalidate(); - }; + const invalidatePlanningViews = useInvalidatePlanningViews(); // eslint-disable-next-line @typescript-eslint/no-explicit-any const createDemandMutation = (trpc.allocation.createDemandRequirement.useMutation as any)({ diff --git a/apps/web/src/components/allocations/AllocationsClient.tsx b/apps/web/src/components/allocations/AllocationsClient.tsx index c88d527..38c4ba0 100644 --- a/apps/web/src/components/allocations/AllocationsClient.tsx +++ b/apps/web/src/components/allocations/AllocationsClient.tsx @@ -20,14 +20,7 @@ import { usePermissions } from "~/hooks/usePermissions.js"; import { useColumnConfig } from "~/hooks/useColumnConfig.js"; import { useViewPrefs } from "~/hooks/useViewPrefs.js"; import { getPlanningEntryMutationId } from "~/lib/planningEntryIds.js"; - -const STATUS_BADGE: Record = { - ACTIVE: "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400", - PROPOSED: "bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400", - CONFIRMED: "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400", - COMPLETED: "bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400", - CANCELLED: "bg-red-100 text-red-600 dark:bg-red-900/30 dark:text-red-400", -}; +import { ALLOCATION_STATUS_BADGE as STATUS_BADGE } from "~/lib/status-styles.js"; const ALL_ALLOC_STATUSES = [ { value: "PROPOSED", label: "Proposed" }, @@ -221,12 +214,11 @@ export function AllocationsClient() { const singleDeletePending = deleteDemandMutation.isPending || deleteAssignmentMutation.isPending; return ( -
- {/* Page header */} -
+
+
-

Allocations

-

+

Allocations

+

{isLoading ? "Loading…" : `${filteredAllocations.length} assignment${filteredAllocations.length !== 1 ? "s" : ""}${filteredDemands.length > 0 ? ` · ${filteredDemands.length} open demand${filteredDemands.length !== 1 ? "s" : ""}` : ""}`} @@ -237,28 +229,27 @@ export function AllocationsClient() { href="/api/reports/allocations" target="_blank" rel="noopener noreferrer" - className="px-3 py-1.5 text-sm rounded-lg border border-gray-200 dark:border-gray-700 text-gray-600 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-700/50 transition-colors flex items-center gap-2" + className="inline-flex items-center gap-2 rounded-xl border border-gray-300 bg-white px-3 py-2 text-sm font-medium text-gray-700 transition hover:border-gray-400 hover:bg-gray-50 dark:border-gray-600 dark:bg-gray-900 dark:text-gray-200 dark:hover:bg-gray-800" > ↓ PDF ↓ XLS

- {/* Filters */} setFilterStatus(e.target.value)} - className="px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-500 text-sm bg-white dark:bg-gray-900 dark:text-gray-100" + className="app-select" > {ALL_ALLOC_STATUSES.map((s) => ( @@ -285,7 +276,7 @@ export function AllocationsClient() { ))} -