import { fail } from '@sveltejs/kit'; import { env } from '$env/dynamic/private'; import { parseBackendError } from '$lib/shared/errors'; import type { Actions, PageServerLoad } from './$types'; import type { components } from '$lib/generated/api'; export interface InviteListItem { id: string; code: string; displayCode: string; label?: string; useCount: number; maxUses?: number; expiresAt?: string; revoked: boolean; status: string; createdAt: string; shareableUrl: string; } export type UserGroup = components['schemas']['UserGroup']; export const load: PageServerLoad = async ({ url, fetch }) => { const status = url.searchParams.get('status') ?? 'active'; const apiUrl = env.API_INTERNAL_URL || 'http://localhost:8080'; const [invitesRes, groupsRes] = await Promise.all([ fetch(`${apiUrl}/api/invites?status=${encodeURIComponent(status)}`), fetch(`${apiUrl}/api/groups`) ]); let invites: InviteListItem[] = []; let loadError: string | null = null; if (!invitesRes.ok) { const backendError = await parseBackendError(invitesRes); loadError = backendError?.code ?? 'INTERNAL_ERROR'; } else { invites = await invitesRes.json(); } let groups: UserGroup[] = []; let groupsLoadError: string | null = null; if (!groupsRes.ok) { const backendError = await parseBackendError(groupsRes); groupsLoadError = backendError?.code ?? 'INTERNAL_ERROR'; } else { const raw: UserGroup[] = await groupsRes.json(); groups = [...raw].sort((a, b) => a.name.localeCompare(b.name)); } return { invites, status, loadError, groups, groupsLoadError }; }; export const actions = { create: async ({ request, fetch }) => { const formData = await request.formData(); const label = (formData.get('label') as string) || undefined; const maxUsesRaw = formData.get('maxUses') as string; const maxUses = maxUsesRaw ? parseInt(maxUsesRaw, 10) : undefined; const prefillFirstName = (formData.get('prefillFirstName') as string) || undefined; const prefillLastName = (formData.get('prefillLastName') as string) || undefined; const prefillEmail = (formData.get('prefillEmail') as string) || undefined; const expiresAt = (formData.get('expiresAt') as string) || undefined; const groupIds = formData.getAll('groupIds') as string[]; const apiUrl = env.API_INTERNAL_URL || 'http://localhost:8080'; const res = await fetch(`${apiUrl}/api/invites`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ label, maxUses, prefillFirstName, prefillLastName, prefillEmail, expiresAt, groupIds }) }); if (!res.ok) { const backendError = await parseBackendError(res); return fail(res.status, { createError: backendError?.code ?? 'INTERNAL_ERROR' }); } const created: InviteListItem = await res.json(); return { created }; }, revoke: async ({ request, fetch }) => { const formData = await request.formData(); const id = formData.get('id') as string; const apiUrl = env.API_INTERNAL_URL || 'http://localhost:8080'; const res = await fetch(`${apiUrl}/api/invites/${encodeURIComponent(id)}`, { method: 'DELETE' }); if (!res.ok) { const backendError = await parseBackendError(res); return fail(res.status, { revokeError: backendError?.code ?? 'INTERNAL_ERROR' }); } return { revoked: id }; } } satisfies Actions;