feat: implement PersonModal component for adding and editing person details
This commit is contained in:
80
src/lib/components/molecules/PersonModal.svelte
Normal file
80
src/lib/components/molecules/PersonModal.svelte
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { ComponentProps } from 'svelte';
|
||||||
|
import type { DB } from '$lib/integrations/db';
|
||||||
|
import Modal from '../atoms/Modal.svelte';
|
||||||
|
import Button from '../atoms/Button.svelte';
|
||||||
|
import { page } from '$app/state';
|
||||||
|
|
||||||
|
type CreatePerson = Parameters<typeof DB.createPerson>[0];
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
onSave: (data: CreatePerson) => Promise<void>;
|
||||||
|
editPerson?: Person;
|
||||||
|
} & Omit<ComponentProps<typeof Modal>, 'children'>;
|
||||||
|
|
||||||
|
let { onSave, isOpen, onClose, editPerson }: Props = $props();
|
||||||
|
|
||||||
|
let person = $state<Person>(editPerson ?? ({} as Person));
|
||||||
|
let isLoading = $state(false);
|
||||||
|
|
||||||
|
if (!person?.name) {
|
||||||
|
person.name = '';
|
||||||
|
person.notes = '';
|
||||||
|
person.years = [page.params.year || new Date().getFullYear().toString()];
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSubmit = async (e: Event) => {
|
||||||
|
e.preventDefault();
|
||||||
|
if (!person) return;
|
||||||
|
|
||||||
|
isLoading = true;
|
||||||
|
try {
|
||||||
|
await onSave(person);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
} finally {
|
||||||
|
isLoading = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Modal {isOpen} {onClose} title={person ? 'Edytuj osobę' : 'Dodaj nową osobę'}>
|
||||||
|
<form onsubmit={handleSubmit} class="space-y-4">
|
||||||
|
<div>
|
||||||
|
<label for="name" class="mb-2 block text-sm font-medium text-gray-700">
|
||||||
|
Imię i nazwisko *
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="name"
|
||||||
|
type="text"
|
||||||
|
class="w-full rounded-xl border border-gray-300 px-4 py-2 transition-all outline-none focus:border-transparent focus:ring-2 focus:ring-blue-500"
|
||||||
|
required
|
||||||
|
disabled={isLoading}
|
||||||
|
bind:value={person.name}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="notes" class="mb-2 block text-sm font-medium text-gray-700"> Notatki </label>
|
||||||
|
<textarea
|
||||||
|
id="notes"
|
||||||
|
rows={4}
|
||||||
|
class="w-full resize-none rounded-xl border border-gray-300 px-4 py-2 transition-all outline-none focus:border-transparent focus:ring-2 focus:ring-blue-500"
|
||||||
|
disabled={isLoading}
|
||||||
|
bind:value={person.notes}
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{#snippet footer()}
|
||||||
|
<div class="flex justify-end gap-3">
|
||||||
|
<Button variant="secondary" onClick={onClose} disabled={isLoading}>Anuluj</Button>
|
||||||
|
<Button
|
||||||
|
variant="primary"
|
||||||
|
onClick={handleSubmit}
|
||||||
|
disabled={isLoading || !person?.name?.trim()}
|
||||||
|
>
|
||||||
|
{isLoading ? 'Zapisywanie...' : 'Zapisz'}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
{/snippet}
|
||||||
|
</Modal>
|
||||||
@@ -18,7 +18,8 @@ export const DB = {
|
|||||||
return await pb.collection('gifts_person').getFirstListItem(`name = "${name}"`);
|
return await pb.collection('gifts_person').getFirstListItem(`name = "${name}"`);
|
||||||
},
|
},
|
||||||
createPerson: async (data: Pick<DB.Person, 'name' | 'notes' | 'years'>): Promise<DB.Person> => {
|
createPerson: async (data: Pick<DB.Person, 'name' | 'notes' | 'years'>): Promise<DB.Person> => {
|
||||||
return await pb.collection('gifts_person').create({ ...data });
|
const year = await pb.collection('gifts_year').getFirstListItem(`year = ${data.years[0]}`);
|
||||||
|
return await pb.collection('gifts_person').create({ ...data, years: [year.id] });
|
||||||
},
|
},
|
||||||
updatePerson: async (id: string, data: Pick<DB.Person, 'name' | 'notes'>): Promise<Person> => {
|
updatePerson: async (id: string, data: Pick<DB.Person, 'name' | 'notes'>): Promise<Person> => {
|
||||||
return await pb.collection('gifts_person').update(id, data);
|
return await pb.collection('gifts_person').update(id, data);
|
||||||
|
|||||||
Reference in New Issue
Block a user