diff --git a/messages/en.json b/messages/en.json index 26ac9c8..424533b 100644 --- a/messages/en.json +++ b/messages/en.json @@ -2,6 +2,7 @@ "$schema": "https://inlang.com/schema/inlang-message-format", "nav_greeting": "Hello {name}!", "nav_menu_sms": "SMS", + "nav_menu_residents": "Residents", "nav_menu_settings": "Settings", "nav_menu_logout": "Logout", "login_tab_login": "Login", @@ -21,6 +22,12 @@ "sms_label_phone": "Phone Number", "sms_label_message": "Message", "sms_button_submit": "Send Message", + "residents_title": "Residents", + "residents_button_new": "New Resident", + "residents_modal_title": "Create a Resident", + "residents_modal_submit": "Submit", + "residents_modal_label_name": "Name", + "residents_modal_label_phone": "Phone Number", "settings_title": "Settings", "settings_category_twilio": "Twilio Config", "settings_twilio_account_sid": "Account SID", diff --git a/src/lib/components/Residents/ResidentTable.stories.svelte b/src/lib/components/Residents/ResidentTable.stories.svelte new file mode 100644 index 0000000..b71c898 --- /dev/null +++ b/src/lib/components/Residents/ResidentTable.stories.svelte @@ -0,0 +1,21 @@ + + +{#snippet template(props: ComponentProps)} + +{/snippet} + + diff --git a/src/lib/components/Residents/ResidentTable.svelte b/src/lib/components/Residents/ResidentTable.svelte new file mode 100644 index 0000000..cf5cc3f --- /dev/null +++ b/src/lib/components/Residents/ResidentTable.svelte @@ -0,0 +1,33 @@ + + + + + + + + Name + Phone Number + + + + + {#each items as resident, index (resident.id)} + + {index + 1} + {resident.name} + {resident.phoneNumber} + + {/each} + + diff --git a/src/lib/components/Residents/index.ts b/src/lib/components/Residents/index.ts new file mode 100644 index 0000000..08b406c --- /dev/null +++ b/src/lib/components/Residents/index.ts @@ -0,0 +1 @@ +export { default as ResidentTable } from './ResidentTable.svelte'; diff --git a/src/routes/app/residents/+page.server.ts b/src/routes/app/residents/+page.server.ts new file mode 100644 index 0000000..0f22441 --- /dev/null +++ b/src/routes/app/residents/+page.server.ts @@ -0,0 +1,58 @@ +import { PhoneRegex } from '$lib/regex/phone.js'; +import { logger } from '$lib/server/logger/index.js'; +import { prisma } from '$lib/server/prisma'; +import { fail } from '@sveltejs/kit'; +import zod from 'zod'; + +export const load = async ({ locals }) => { + const residents = await prisma.resident.findMany({ + where: { + tenantId: locals.tenant.id, + }, + select: { + id: true, + name: true, + phoneNumber: true, + }, + }); + + return { + residents: residents, + }; +}; + +export const actions = { + default: async (event) => { + const form = await event.request.formData(); + + if (!form.has('name')) { + return fail(400, { error: 'phone_missing' }); + } + if (!form.get('phoneNumber')) { + return fail(400, { error: 'message_missing' }); + } + + const name = form.get('name'); + if (typeof name !== 'string') { + return fail(400, { error: 'invalid_name' }); + } + + const { + success: phoneSuccess, + data: phone, + error: phoneError, + } = zod.string().regex(PhoneRegex).safeParse(form.get('phoneNumber')); + if (!phoneSuccess) { + logger.error(phoneError); + return fail(400, { error: 'invalid_phone' }); + } + + await prisma.resident.create({ + data: { + name: name, + phoneNumber: phone, + tenantId: event.locals.tenant.id, + }, + }); + }, +}; diff --git a/src/routes/app/residents/+page.svelte b/src/routes/app/residents/+page.svelte new file mode 100644 index 0000000..aa99bf6 --- /dev/null +++ b/src/routes/app/residents/+page.svelte @@ -0,0 +1,65 @@ + + + + + + {messages.residents_modal_title()} + + ✕ + + + + + {#snippet label()} + + {messages.residents_modal_label_name()} + {/snippet} + + + {#snippet label()} + + {messages.residents_modal_label_phone()} + {/snippet} + + + dialog?.close()} + >{messages.residents_modal_submit()} + + + + + + + + {messages.residents_title()} + { + dialog?.showModal(); + }} + color="primary">{messages.residents_button_new()} + + + +