- Scope @typescript-eslint/no-explicit-any off for *.spec.ts test doubles - Type enhance() submit callbacks with SubmitFunction in api-keys page - Drop as-any casts in proclamations upsert by using typed form data - Fix useless regex escapes in profiles phone validation - Remove unused locals param from api-keys load - Use resolve() for admin nav/error links; store literal hrefs in adminModels - Update README admin section and ADMIN_OVERHAUL lint caveat
129 lines
3.6 KiB
TypeScript
129 lines
3.6 KiB
TypeScript
import type { PageServerLoad } from './$types';
|
|
import { prisma } from '$lib/db';
|
|
import { superValidate } from 'sveltekit-superforms/server';
|
|
import { zod4 } from 'sveltekit-superforms/adapters';
|
|
import { z } from 'zod';
|
|
import { superFormErrorsToFieldErrors } from '$lib/superform-errors';
|
|
|
|
const ProclamationSchema = z.object({
|
|
name: z.string().min(1, 'Required'),
|
|
solfeggioFrequencyId: z.coerce.number().int(),
|
|
categoryId: z.coerce.number().int(),
|
|
groupId: z.coerce.number().int(),
|
|
content: z.string().optional().default('')
|
|
});
|
|
|
|
function isSuper(locals: App.Locals): boolean {
|
|
return ((locals.user as { roleId?: number } | null)?.roleId ?? 4) <= 1;
|
|
}
|
|
|
|
export const load: PageServerLoad = async ({ locals }) => {
|
|
const [proclamations, frequencies, categories, groups] = await Promise.all([
|
|
prisma.proclamation.findMany({
|
|
include: { category: true, group: true, solfeggioFrequency: true },
|
|
orderBy: { name: 'asc' }
|
|
}),
|
|
prisma.solfeggioFrequency.findMany({
|
|
select: { id: true, name: true, value: true },
|
|
orderBy: { name: 'asc' }
|
|
}),
|
|
prisma.proclamationCategory.findMany({
|
|
select: { id: true, name: true },
|
|
orderBy: { name: 'asc' }
|
|
}),
|
|
prisma.proclamationGroup.findMany({
|
|
select: { id: true, name: true },
|
|
orderBy: { sortOrder: 'asc' }
|
|
})
|
|
]);
|
|
|
|
const records = proclamations as unknown as Record<string, unknown>[];
|
|
|
|
// Strip content from non-Super users
|
|
if (!isSuper(locals)) {
|
|
for (const record of records) {
|
|
delete record.content;
|
|
}
|
|
}
|
|
|
|
return { records, frequencies, categories, groups };
|
|
};
|
|
|
|
export const actions = {
|
|
upsert: async ({ request, locals }) => {
|
|
if (!locals.user) {
|
|
return { success: false, action: 'upsert', error: 'Unauthorized' };
|
|
}
|
|
|
|
if (!isSuper(locals)) {
|
|
return {
|
|
success: false,
|
|
action: 'upsert',
|
|
error: 'Only Super admins can edit proclamations'
|
|
};
|
|
}
|
|
|
|
const formData = await request.formData();
|
|
const form = await superValidate(formData, zod4(ProclamationSchema));
|
|
if (!form.valid) {
|
|
const { error: formError, fieldErrors } = superFormErrorsToFieldErrors(
|
|
form.errors as Record<string, unknown>
|
|
);
|
|
return { success: false, action: 'upsert', error: formError, fieldErrors };
|
|
}
|
|
|
|
const rawId = formData.get('id')?.toString();
|
|
|
|
try {
|
|
if (rawId) {
|
|
const existing = await prisma.proclamation.findUnique({ where: { id: rawId } });
|
|
if (!existing) {
|
|
return { success: false, action: 'upsert', error: 'Record not found' };
|
|
}
|
|
await prisma.proclamation.update({ where: { id: rawId }, data: form.data });
|
|
} else {
|
|
await prisma.proclamation.create({ data: form.data });
|
|
}
|
|
} catch (e: unknown) {
|
|
if (e && typeof e === 'object' && 'code' in e && (e as { code: string }).code === 'P2002') {
|
|
return {
|
|
success: false,
|
|
action: 'upsert',
|
|
error: 'A record with this name already exists.'
|
|
};
|
|
}
|
|
throw e;
|
|
}
|
|
|
|
return { success: true, action: 'upsert' };
|
|
},
|
|
delete: async ({ request, locals }) => {
|
|
if (!isSuper(locals)) {
|
|
return {
|
|
success: false,
|
|
action: 'delete',
|
|
error: 'Only Super admins can delete proclamations'
|
|
};
|
|
}
|
|
|
|
const formData = await request.formData();
|
|
const rawId = formData.get('id')?.toString();
|
|
if (!rawId) return { success: false, action: 'delete', error: 'Missing id' };
|
|
|
|
try {
|
|
await prisma.proclamation.delete({ where: { id: rawId } });
|
|
} catch (e: unknown) {
|
|
if (e && typeof e === 'object' && 'code' in e && (e as { code: string }).code === 'P2003') {
|
|
return {
|
|
success: false,
|
|
action: 'delete',
|
|
error: 'Cannot delete: this proclamation is assigned to users.'
|
|
};
|
|
}
|
|
throw e;
|
|
}
|
|
|
|
return { success: true, action: 'delete' };
|
|
}
|
|
};
|