diff --git a/apps/web/src/routes/projekt.tsx b/apps/web/src/routes/projekt.tsx index db0a991..6341abc 100644 --- a/apps/web/src/routes/projekt.tsx +++ b/apps/web/src/routes/projekt.tsx @@ -143,17 +143,7 @@ export function ProjektRoute() {
- - -

Verlinkungen

-
- - - - - - -
+ @@ -1850,6 +1840,83 @@ function AbschlussDialog({ ); } +const LINK_FIELDS = [ + { key: 'outlineSteckbriefUrl', label: 'Outline-Steckbrief', placeholder: 'https://wiki.tool-ctrl.de/doc/…' }, + { key: 'planeProjectUrl', label: 'Plane-Board', placeholder: 'https://project.tool-ctrl.de/…' }, + { key: 'risikolisteUrl', label: 'Risikoliste', placeholder: 'https://… (z. B. Outline / Plane)' }, + { key: 'lessonsLearnedUrl', label: 'Lessons Learned', placeholder: 'https://… (Retro / Doku)' }, +] as const; + +function VerlinkungenSection({ projectId, project: p }: { projectId: string; project: ProjectDetail }) { + const utils = trpc.useUtils(); + const [editing, setEditing] = useState(false); + const [vals, setVals] = useState>({}); + const update = trpc.project.update.useMutation({ + onSuccess: async () => { + toast(voice.toast.saved); + await utils.project.byId.invalidate({ id: projectId }); + setEditing(false); + }, + }); + + function startEdit() { + setVals(Object.fromEntries(LINK_FIELDS.map((f) => [f.key, p[f.key] ?? '']))); + setEditing(true); + } + function save() { + update.mutate({ + projectId, + ...Object.fromEntries(LINK_FIELDS.map((f) => [f.key, (vals[f.key] ?? '').trim() || null])), + }); + } + + return ( + + +

Verlinkungen

+ {!editing && ( + + )} +
+ + {editing ? ( +
+ {LINK_FIELDS.map((f) => ( + + ))} +

Leer lassen entfernt den Link. URLs müssen mit http(s):// beginnen.

+
+ + +
+
+ ) : ( + LINK_FIELDS.map((f) => ) + )} +
+
+ ); +} + function LinkRow({ label, url }: { label: string; url: string | null }) { return (

diff --git a/packages/shared/src/schemas/project.ts b/packages/shared/src/schemas/project.ts index 0df9388..eb8b1c4 100644 --- a/packages/shared/src/schemas/project.ts +++ b/packages/shared/src/schemas/project.ts @@ -104,6 +104,10 @@ export const updateProjectInput = z.object({ nichtZiele: z.string().max(2000).nullable().optional(), liefergegenstaende: z.string().max(2000).nullable().optional(), zieldreieckFlex: zieldreieckFlexSchema.nullable().optional(), + outlineSteckbriefUrl: z.string().url().nullable().optional(), + planeProjectUrl: z.string().url().nullable().optional(), + risikolisteUrl: z.string().url().nullable().optional(), + lessonsLearnedUrl: z.string().url().nullable().optional(), }); export type UpdateProjectInput = z.infer;