From d892621e9b18fdbd346daed577ba7af36da1a30b Mon Sep 17 00:00:00 2001 From: Daniel Kirby Date: Fri, 26 Jun 2026 13:04:54 +0100 Subject: [PATCH] feat: manage primary address action --- src/lib/schemas/addresses.schema.ts | 2 +- .../clients/[id]/addresses/+page.server.ts | 80 ++++++++++++++++++- .../[id]/addresses/addresses-table.svelte | 14 ++++ .../[id]/addresses/edit-address-dialog.svelte | 21 ----- 4 files changed, 91 insertions(+), 26 deletions(-) diff --git a/src/lib/schemas/addresses.schema.ts b/src/lib/schemas/addresses.schema.ts index c91f743..f5bbafd 100644 --- a/src/lib/schemas/addresses.schema.ts +++ b/src/lib/schemas/addresses.schema.ts @@ -13,4 +13,4 @@ export const addressCreateSchema = z.object({ country: requiredText('Country', 80).default('United Kingdom') }); -export const addressEditSchema = addressCreateSchema.extend(idSchema.shape); +export const addressEditSchema = addressCreateSchema.omit({ type: true }).extend(idSchema.shape); diff --git a/src/routes/dashboard/clients/[id]/addresses/+page.server.ts b/src/routes/dashboard/clients/[id]/addresses/+page.server.ts index ddfbd58..c1d83b4 100644 --- a/src/routes/dashboard/clients/[id]/addresses/+page.server.ts +++ b/src/routes/dashboard/clients/[id]/addresses/+page.server.ts @@ -78,7 +78,8 @@ export const actions: Actions = { if (!form.valid) return message(form, 'Check the highlighted fields.', { status: 400 }); try { - await db.insert(addresses).values({ + const now = new Date(); + const insertAddress = db.insert(addresses).values({ id: crypto.randomUUID(), organizationId: activeOrganizationId, clientId: form.data.clientId, @@ -90,9 +91,28 @@ export const actions: Actions = { region: form.data.region || null, postcode: form.data.postcode, country: form.data.country, - updatedAt: new Date(), - createdAt: new Date() + updatedAt: now, + createdAt: now }); + + if (form.data.type === 'primary') { + await db.batch([ + db + .update(addresses) + .set({ type: 'invoicing', updatedAt: now }) + .where( + and( + eq(addresses.clientId, params.id), + eq(addresses.organizationId, activeOrganizationId), + eq(addresses.type, 'primary'), + isNull(addresses.archivedAt) + ) + ), + insertAddress + ]); + } else { + await insertAddress; + } } catch { return message(form, 'Unable to create address.', { status: 400 }); } @@ -113,7 +133,6 @@ export const actions: Actions = { .update(addresses) .set({ clientId: form.data.clientId, - type: form.data.type, line1: form.data.line1, line2: form.data.line2 || null, line3: form.data.line3 || null, @@ -137,6 +156,59 @@ export const actions: Actions = { return message(form, 'Address updated.'); }, + makePrimary: async ({ locals, params, request }) => { + const { activeOrganizationId } = await loadOrganizationContext(locals); + const form = await superValidate(await request.formData(), zod4(archiveSchema), { + id: 'addresses-primary' + }); + + if (!form.valid) return message(form, 'Address id is required.', { status: 400 }); + + const [address] = await db + .select({ id: addresses.id, type: addresses.type }) + .from(addresses) + .where( + and( + eq(addresses.id, form.data.id), + eq(addresses.clientId, params.id), + eq(addresses.organizationId, activeOrganizationId), + isNull(addresses.archivedAt) + ) + ) + .limit(1); + + if (!address) return message(form, 'Choose a valid address.', { status: 400 }); + if (address.type === 'primary') return message(form, 'Address is already primary.'); + + const now = new Date(); + await db.batch([ + db + .update(addresses) + .set({ type: address.type, updatedAt: now }) + .where( + and( + eq(addresses.clientId, params.id), + eq(addresses.organizationId, activeOrganizationId), + eq(addresses.type, 'primary'), + isNull(addresses.archivedAt) + ) + ), + db + .update(addresses) + .set({ type: 'primary', updatedAt: now }) + .where( + and( + eq(addresses.id, form.data.id), + eq(addresses.clientId, params.id), + eq(addresses.organizationId, activeOrganizationId), + isNull(addresses.archivedAt) + ) + ) + ]); + + return message(form, 'Primary address updated.'); + }, + archive: async ({ locals, params, request }) => { const { activeOrganizationId } = await loadOrganizationContext(locals); const form = await superValidate(await request.formData(), zod4(archiveSchema), { diff --git a/src/routes/dashboard/clients/[id]/addresses/addresses-table.svelte b/src/routes/dashboard/clients/[id]/addresses/addresses-table.svelte index 32ed919..6cc5d50 100644 --- a/src/routes/dashboard/clients/[id]/addresses/addresses-table.svelte +++ b/src/routes/dashboard/clients/[id]/addresses/addresses-table.svelte @@ -4,6 +4,7 @@ import { Button } from '$lib/components/ui/button/index.js'; import * as DropdownMenu from '$lib/components/ui/dropdown-menu/index.js'; import * as Table from '$lib/components/ui/table/index.js'; + import { cn } from '$lib/utils.js'; let { data, openEdit, @@ -50,6 +51,19 @@ > openEdit(record)}>Edit + {#if record.type !== 'primary'} +
+ +
+ {/if} openArchive(record)} >Archive diff --git a/src/routes/dashboard/clients/[id]/addresses/edit-address-dialog.svelte b/src/routes/dashboard/clients/[id]/addresses/edit-address-dialog.svelte index 0b3f358..6b6acfa 100644 --- a/src/routes/dashboard/clients/[id]/addresses/edit-address-dialog.svelte +++ b/src/routes/dashboard/clients/[id]/addresses/edit-address-dialog.svelte @@ -1,7 +1,6 @@