From a9ad1ed8b69851b16326ca8381f3e7199d58edda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hartmut=20N=C3=B6renberg?= Date: Mon, 6 Apr 2026 08:10:36 +0200 Subject: [PATCH] feat(G-08): chapter field uses live datalist from resource.chapters All chapter text inputs now show autocomplete suggestions from the database (distinct chapter values from active resources) via HTML wired to trpc.resource.chapters: - ResourceModal: chapter input - RateCardsClient: rate card line chapter input - EffortRulesClient: effort rule chapter input - ExperienceMultipliersClient: replaces hardcoded CHAPTER_PRESETS with live data, falls back to presets when no data available Also revert blueprintRolePresetsInputSchema to z.array(z.unknown()) to restore compatibility with StaffingRequirement[] call sites. Co-Authored-By: Claude Sonnet 4.6 --- apps/web/src/components/admin/EffortRulesClient.tsx | 5 +++++ .../web/src/components/admin/ExperienceMultipliersClient.tsx | 4 +++- apps/web/src/components/admin/RateCardsClient.tsx | 5 +++++ apps/web/src/components/resources/ResourceModal.tsx | 5 +++++ packages/api/src/router/blueprint-procedure-support.ts | 2 +- 5 files changed, 19 insertions(+), 2 deletions(-) diff --git a/apps/web/src/components/admin/EffortRulesClient.tsx b/apps/web/src/components/admin/EffortRulesClient.tsx index 2af1de7..cf44164 100644 --- a/apps/web/src/components/admin/EffortRulesClient.tsx +++ b/apps/web/src/components/admin/EffortRulesClient.tsx @@ -69,6 +69,7 @@ const emptyRuleSet: EditingRuleSet = { export function EffortRulesClient() { const utils = trpc.useUtils(); const { data: ruleSets, isLoading } = trpc.effortRule.list.useQuery(); + const { data: chapters } = trpc.resource.chapters.useQuery(undefined, { staleTime: 60_000 }); const createMutation = trpc.effortRule.create.useMutation({ onSuccess: () => { @@ -274,6 +275,7 @@ export function EffortRulesClient() { onChange={(e) => updateRule(i, { chapter: e.target.value })} className="w-full rounded-lg border border-gray-200 px-2 py-1 text-sm" placeholder="Chapter" + list="er-chapter-list" /> @@ -319,6 +321,9 @@ export function EffortRulesClient() { + + {chapters?.map((c) =>
- {CHAPTER_PRESETS.map((d) => ( + {chapterOptions.map((d) => ( diff --git a/apps/web/src/components/admin/RateCardsClient.tsx b/apps/web/src/components/admin/RateCardsClient.tsx index ba4e446..bc8c10b 100644 --- a/apps/web/src/components/admin/RateCardsClient.tsx +++ b/apps/web/src/components/admin/RateCardsClient.tsx @@ -124,6 +124,7 @@ export function RateCardsClient() { const { data: roles } = trpc.role.list.useQuery({}); const { data: clientsData } = trpc.clientEntity.list.useQuery({}); + const { data: chapters } = trpc.resource.chapters.useQuery(undefined, { staleTime: 60_000 }); // ─── Mutations ────────────────────────────────────────────────────────── @@ -682,7 +683,11 @@ export function RateCardsClient() { onChange={(e) => setEditingLine({ ...editingLine, chapter: e.target.value })} placeholder="e.g. Animation" className="border border-gray-300 dark:border-gray-600 rounded-lg px-3 py-2 text-sm w-full bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-brand-400" + list="rc-chapter-list" /> + + {chapters?.map((c) =>
diff --git a/apps/web/src/components/resources/ResourceModal.tsx b/apps/web/src/components/resources/ResourceModal.tsx index 48c2fbd..8ef6220 100644 --- a/apps/web/src/components/resources/ResourceModal.tsx +++ b/apps/web/src/components/resources/ResourceModal.tsx @@ -203,6 +203,7 @@ export function ResourceModal({ mode, resource, onClose, onSuccess }: ResourceMo const { canManageUsers } = usePermissions(); const utils = trpc.useUtils(); + const { data: chapters } = trpc.resource.chapters.useQuery(undefined, { staleTime: 60_000 }); const { data: availableRoles } = trpc.role.list.useQuery( { isActive: true }, { staleTime: 60_000 }, @@ -441,7 +442,11 @@ export function ResourceModal({ mode, resource, onClose, onSuccess }: ResourceMo placeholder="Engineering" value={form.chapter} onChange={(e) => setField("chapter", e.target.value)} + list="rm-chapter-list" /> + + {chapters?.map((c) =>
diff --git a/packages/api/src/router/blueprint-procedure-support.ts b/packages/api/src/router/blueprint-procedure-support.ts index ba78461..9ccf642 100644 --- a/packages/api/src/router/blueprint-procedure-support.ts +++ b/packages/api/src/router/blueprint-procedure-support.ts @@ -58,7 +58,7 @@ export const blueprintUpdateInputSchema = z.object({ export const blueprintRolePresetsInputSchema = z.object({ id: z.string(), - rolePresets: z.array(z.record(z.string(), z.unknown())), + rolePresets: z.array(z.unknown()), }); export const blueprintBatchDeleteInputSchema = z.object({