- Registry: Remove 'parent.name' from listFields (all shown records are top-level with no parent), remove 'parent: true' from include since unused - +page.server.ts: Custom load filters to parentId=null (top-level only); custom upsert syncs children (create/update/delete) and handles P2002 duplicate-name errors; custom delete cascades to children first to avoid FK constraint violations - CategoryForm.svelte: Replace parentId select dropdown with dynamic list of sub-category inputs. Each row has a name field and Remove button. Pre-populates from record.children when editing existing categories. Add Sub-category button appends new rows - +page.svelte: Remove unused relationOptionsData prop from CategoryForm; rename submit button label from 'Update' to 'Save' - prisma: Add ProclamationCategorySubscriptionLevel join table migration and regenerate client - General: Update TipTap mock, Toast, license-keys page, proclamations server/route tests, README, AGENTS.md, and other admin forms
75 lines
2.2 KiB
TypeScript
75 lines
2.2 KiB
TypeScript
import { z } from 'zod';
|
|
|
|
const email = z.string().email('Invalid email address');
|
|
const phone = z
|
|
.string()
|
|
.min(10, 'Phone number must be at least 10 digits')
|
|
.regex(/^[\d\-\+\(\) ]+$/, 'Invalid phone number format');
|
|
const name = z.string().min(1, 'Required').max(100, 'Too long');
|
|
|
|
export const UserRole = z.object({
|
|
name: z.string().min(1, 'Required')
|
|
});
|
|
|
|
export const User = z.object({
|
|
name: z.string().min(1, 'Required'),
|
|
email,
|
|
roleId: z.coerce.number().int().min(1)
|
|
});
|
|
|
|
export const Profile = z.object({
|
|
userId: z.string().min(1, 'Required'),
|
|
firstName: name,
|
|
lastName: name,
|
|
phoneNumber: phone
|
|
});
|
|
|
|
export const Address = z.object({
|
|
profileId: z.string().min(1),
|
|
street: z.string().min(1, 'Street is required'),
|
|
city: z.string().min(1, 'City is required'),
|
|
state: z.string().min(1, 'State is required'),
|
|
postalCode: z.string().min(1, 'Postal code is required'),
|
|
country: z.string().min(1, 'Country is required'),
|
|
type: z.enum(['Mailing', 'Billing', 'Shipping']).default('Mailing'),
|
|
isDefaultMailing: z.coerce.boolean().default(false),
|
|
isDefaultBilling: z.coerce.boolean().default(false),
|
|
isDefaultShipping: z.coerce.boolean().default(false)
|
|
});
|
|
|
|
export const SolfeggioFrequency = z.object({
|
|
name: z.string().min(1, 'Required'),
|
|
value: z.coerce.number().int('Must be a whole number')
|
|
});
|
|
|
|
export const SubscriptionLevel = z.object({
|
|
name: z.string().min(1, 'Required'),
|
|
description: z.string().optional().default('')
|
|
});
|
|
|
|
export const ProclamationCategory = z.object({
|
|
name: z.string().min(1, 'Required'),
|
|
parentId: z.coerce.number().int().optional()
|
|
});
|
|
|
|
export const Proclamation = z.object({
|
|
name: z.string().min(1, 'Required'),
|
|
solfeggioFrequencyId: z.coerce.number().int(),
|
|
parentCategoryId: z.coerce.number().int(),
|
|
categoryId: z.coerce.number().int().optional(),
|
|
subscriptionLevelId: z.coerce.number().int(),
|
|
content: z.string().optional().default('')
|
|
});
|
|
|
|
export const LicenseKey = z.object({
|
|
active: z.coerce.boolean(),
|
|
level: z.string().min(1, 'Required'),
|
|
userId: z.string().min(1, 'Required')
|
|
});
|
|
|
|
export const UserUpdate = z.object({
|
|
id: z.string().min(1),
|
|
name: z.string().min(1, 'Required').optional(),
|
|
email: z.string().email().optional()
|
|
});
|