>({});
+ 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;