diff --git a/src/__tests__/planAuditDescription.test.ts b/src/__tests__/planAuditDescription.test.ts new file mode 100644 index 0000000..11ae902 --- /dev/null +++ b/src/__tests__/planAuditDescription.test.ts @@ -0,0 +1,95 @@ +import { describe, it, expect } from "vitest"; +import { + planCategoryLabel, + buildPlanAuditDescription, +} from "../utils/planAuditDescription"; + +describe("planCategoryLabel", () => { + it("maps known plan categories to Czech labels", () => { + expect(planCategoryLabel("work")).toBe("Práce"); + expect(planCategoryLabel("preparation")).toBe("Příprava"); + expect(planCategoryLabel("travel")).toBe("Cesta / Montáž"); + expect(planCategoryLabel("leave")).toBe("Dovolená"); + expect(planCategoryLabel("sick")).toBe("Nemoc"); + expect(planCategoryLabel("training")).toBe("Školení"); + expect(planCategoryLabel("other")).toBe("Jiné"); + }); + + it("falls back to the raw value for an unknown category", () => { + expect(planCategoryLabel("unknown_xyz")).toBe("unknown_xyz"); + }); +}); + +describe("buildPlanAuditDescription", () => { + it("describes a multi-day entry with project", () => { + const desc = buildPlanAuditDescription({ + userName: "Jan Novák", + category: "work", + projectName: "Rekonstrukce haly", + dateFrom: "2026-06-08", + dateTo: "2026-06-12", + }); + expect(desc).toBe( + "Jan Novák · 08.06.2026 – 12.06.2026 · Práce · Rekonstrukce haly", + ); + }); + + it("collapses a single-day range to one date", () => { + const desc = buildPlanAuditDescription({ + userName: "Jan Novák", + category: "work", + projectName: "Rekonstrukce haly", + dateFrom: "2026-06-08", + dateTo: "2026-06-08", + }); + expect(desc).toBe("Jan Novák · 08.06.2026 · Práce · Rekonstrukce haly"); + }); + + it("omits the project segment when there is no project", () => { + const desc = buildPlanAuditDescription({ + userName: "Petr Svoboda", + category: "leave", + projectName: null, + dateFrom: "2026-06-10", + dateTo: "2026-06-10", + }); + expect(desc).toBe("Petr Svoboda · 10.06.2026 · Dovolená"); + }); + + it("appends the emergency-edit note when force is set", () => { + const desc = buildPlanAuditDescription({ + userName: "Jan Novák", + category: "work", + projectName: null, + dateFrom: "2026-01-02", + dateTo: "2026-01-02", + force: true, + }); + expect(desc).toBe("Jan Novák · 02.01.2026 · Práce · nouzová úprava"); + }); + + it("appends a custom suffix (e.g. replaced override)", () => { + const desc = buildPlanAuditDescription({ + userName: "Jan Novák", + category: "sick", + projectName: null, + dateFrom: "2026-06-10", + dateTo: "2026-06-10", + suffix: "nahrazeno novým záznamem", + }); + expect(desc).toBe( + "Jan Novák · 10.06.2026 · Nemoc · nahrazeno novým záznamem", + ); + }); + + it("treats a whitespace-only project name as no project", () => { + const desc = buildPlanAuditDescription({ + userName: "Jan Novák", + category: "work", + projectName: " ", + dateFrom: "2026-06-08", + dateTo: "2026-06-08", + }); + expect(desc).toBe("Jan Novák · 08.06.2026 · Práce"); + }); +}); diff --git a/src/admin/components/PlanCellModal.tsx b/src/admin/components/PlanCellModal.tsx index 23ebcb9..9af8a48 100644 --- a/src/admin/components/PlanCellModal.tsx +++ b/src/admin/components/PlanCellModal.tsx @@ -1,9 +1,17 @@ import { useState } from "react"; +import { motion, AnimatePresence } from "framer-motion"; import FormModal from "./FormModal"; import FormField from "./FormField"; import AdminDatePicker from "./AdminDatePicker"; import ConfirmModal from "./ConfirmModal"; -import { ResolvedCell } from "../lib/queries/plan"; +import useReducedMotion from "../hooks/useReducedMotion"; +import { + ResolvedCell, + PLAN_CATEGORIES, + planCategoryLabel, + cellProjectLabel, +} from "../lib/queries/plan"; +import { formatDate } from "../utils/formatters"; interface Project { id: number; @@ -68,16 +76,6 @@ interface Props { onSwitchToEditRange: (entryId: number, userId: number, date: string) => void; } -const CATEGORIES = [ - { value: "work", label: "Práce" }, - { value: "preparation", label: "Příprava" }, - { value: "travel", label: "Cesta / Montáž" }, - { value: "leave", label: "Dovolená" }, - { value: "sick", label: "Nemoc" }, - { value: "training", label: "Školení" }, - { value: "other", label: "Jiné" }, -]; - export default function PlanCellModal(props: Props) { const { open, mode, onClose } = props; if (!open || mode.kind === "closed") return null; @@ -218,19 +216,36 @@ function EditForm(props: Props) { onSubmit={handleSubmit} submitLabel={mode.kind === "create" ? "Vytvořit" : "Uložit"} loading={submitting} - > - {mode.kind !== "create" && ( -