diff --git a/frontend/src/lib/components/admin/PatchTestsManagement.svelte b/frontend/src/lib/components/admin/PatchTestsManagement.svelte index dbf6cf5..c7e7310 100644 --- a/frontend/src/lib/components/admin/PatchTestsManagement.svelte +++ b/frontend/src/lib/components/admin/PatchTestsManagement.svelte @@ -45,15 +45,35 @@ import { Button } from '$lib/components/ui/button'; expiry: '' }); - function validateForm(): boolean { - formErrors = { - name: !formData.name.trim() ? 'Name is required' : '', - notice_duration: (formData.notice_duration_hours < 0 || isNaN(formData.notice_duration_hours)) ? 'Must be a positive number' : '', - expiry: (formData.expiry_months < 1 || isNaN(formData.expiry_months)) ? 'Must be at least 1 month' : '' - }; - return Object.values(formErrors).every(err => err === ''); + function validateNameField() { + formErrors.name = !formData.name.trim() ? 'Name is required' : ''; } + function validateNoticeDurationField() { + formErrors.notice_duration = (formData.notice_duration_hours < 0 || isNaN(formData.notice_duration_hours)) ? 'Must be a positive number' : ''; + } + + function validateExpiryField() { + formErrors.expiry = (formData.expiry_months < 1 || isNaN(formData.expiry_months)) ? 'Must be at least 1 month' : ''; + } + + function validateAllFields() { + validateNameField(); + validateNoticeDurationField(); + validateExpiryField(); + } + + let isFormValid = $derived( + formData.name.trim() !== '' && + !formErrors.name && + !formErrors.notice_duration && + !formErrors.expiry && + formData.notice_duration_hours >= 0 && + !isNaN(formData.notice_duration_hours) && + formData.expiry_months >= 1 && + !isNaN(formData.expiry_months) + ); + async function fetchData() { loading = true; try { @@ -94,6 +114,11 @@ import { Button } from '$lib/components/ui/button'; expiry_months: 6, service_ids: [] }; + formErrors = { + name: '', + notice_duration: '', + expiry: '' + }; isEditing = false; } @@ -111,6 +136,11 @@ import { Button } from '$lib/components/ui/button'; expiry_months: pt.expiry_months, service_ids: pt.service_ids || [] }; + formErrors = { + name: '', + notice_duration: '', + expiry: '' + }; isEditing = true; showModal = true; } @@ -124,8 +154,9 @@ import { Button } from '$lib/components/ui/button'; } async function savePatchTest() { - if (!formData.name.trim()) { - toast.error('Patch test name is required'); + validateAllFields(); + if (!isFormValid) { + toast.error('Please fix validation errors before submitting'); return; } @@ -346,6 +377,7 @@ import { Button } from '$lib/components/ui/button'; type="text" placeholder="e.g. Standard Glue Patch Test" bind:value={formData.name} + onblur={validateNameField} class="w-full {formErrors.name ? 'border-red-500' : ''}" /> {#if formErrors.name} @@ -373,6 +405,7 @@ import { Button } from '$lib/components/ui/button'; inputmode="numeric" min="0" bind:value={formData.notice_duration_hours} + onblur={validateNoticeDurationField} class="w-full {formErrors.notice_duration ? 'border-red-500' : ''}" /> {#if formErrors.notice_duration} @@ -389,6 +422,7 @@ import { Button } from '$lib/components/ui/button'; inputmode="numeric" min="1" bind:value={formData.expiry_months} + onblur={validateExpiryField} class="w-full {formErrors.expiry ? 'border-red-500' : ''}" /> {#if formErrors.expiry} @@ -424,10 +458,8 @@ import { Button } from '$lib/components/ui/button'; Cancel