diff --git a/frontend/src/routes/persons/[id]/edit/+page.server.ts b/frontend/src/routes/persons/[id]/edit/+page.server.ts new file mode 100644 index 00000000..6b5f9ebc --- /dev/null +++ b/frontend/src/routes/persons/[id]/edit/+page.server.ts @@ -0,0 +1,87 @@ +import { error, fail, redirect } from '@sveltejs/kit'; +import { createApiClient } from '$lib/api.server'; +import { getErrorMessage } from '$lib/errors'; + +export async function load({ params, fetch, locals }) { + const canWrite = + (locals.user as { groups?: { permissions: string[] }[] } | undefined)?.groups?.some((g) => + g.permissions.includes('WRITE_ALL') + ) ?? false; + + if (!canWrite) throw error(403, 'Forbidden'); + + const { id } = params; + const api = createApiClient(fetch); + const result = await api.GET('/api/persons/{id}', { params: { path: { id } } }); + + if (!result.response.ok) { + const code = (result.error as unknown as { code?: string })?.code; + throw error(result.response.status, getErrorMessage(code)); + } + + return { person: result.data! }; +} + +export const actions = { + update: async ({ request, params, fetch }) => { + const formData = await request.formData(); + const firstName = formData.get('firstName')?.toString().trim(); + const lastName = formData.get('lastName')?.toString().trim(); + const alias = formData.get('alias')?.toString().trim() || undefined; + const notes = formData.get('notes')?.toString().trim() || undefined; + const birthYearStr = formData.get('birthYear')?.toString().trim(); + const deathYearStr = formData.get('deathYear')?.toString().trim(); + const birthYear = birthYearStr ? parseInt(birthYearStr, 10) : undefined; + const deathYear = deathYearStr ? parseInt(deathYearStr, 10) : undefined; + + if (!firstName || !lastName) { + return fail(400, { updateError: 'Vor- und Nachname sind Pflichtfelder.' }); + } + + const api = createApiClient(fetch); + const result = await api.PUT('/api/persons/{id}', { + params: { path: { id: params.id } }, + body: { + firstName, + lastName, + ...(alias ? { alias } : {}), + ...(notes ? { notes } : {}), + ...(birthYear ? { birthYear } : {}), + ...(deathYear ? { deathYear } : {}) + } + }); + + if (!result.response.ok) { + const code = (result.error as unknown as { code?: string })?.code; + return fail(result.response.status, { updateError: getErrorMessage(code) }); + } + + throw redirect(303, `/persons/${params.id}`); + }, + + discard: async ({ params }) => { + throw redirect(303, `/persons/${params.id}`); + }, + + merge: async ({ request, params, fetch }) => { + const formData = await request.formData(); + const targetPersonId = formData.get('targetPersonId')?.toString(); + + if (!targetPersonId) { + return fail(400, { mergeError: 'Bitte eine Zielperson auswählen.' }); + } + + const api = createApiClient(fetch); + const result = await api.POST('/api/persons/{id}/merge', { + params: { path: { id: params.id } }, + body: { targetPersonId } + }); + + if (!result.response.ok) { + const code = (result.error as unknown as { code?: string })?.code; + return fail(result.response.status, { mergeError: getErrorMessage(code) }); + } + + throw redirect(303, `/persons/${targetPersonId}`); + } +}; diff --git a/frontend/src/routes/persons/[id]/edit/+page.svelte b/frontend/src/routes/persons/[id]/edit/+page.svelte new file mode 100644 index 00000000..a3483e4b --- /dev/null +++ b/frontend/src/routes/persons/[id]/edit/+page.svelte @@ -0,0 +1,56 @@ + + +