feat: introduce PersonCard component for displaying and managing person details and gifts

This commit is contained in:
Norbert Maciaszek
2025-11-17 22:19:51 +01:00
parent 2f53620de7
commit 259bb23ec9
2 changed files with 90 additions and 1 deletions

View File

@@ -0,0 +1,89 @@
<script lang="ts">
import { refreshAll } from '$app/navigation';
import { formatCurrency } from '$lib/helpers/formatCurrency';
import { DB } from '$lib/integrations/db';
import Button from '../atoms/Button.svelte';
import Heading from '../atoms/Heading.svelte';
import GiftCard from './GiftCard.svelte';
import GiftModal from './GiftModal.svelte';
import PersonModal from './PersonModal.svelte';
let person: Person = $props();
const gifts = $derived(person.expand.gifts);
const totalCost = $derived(gifts?.reduce((acc, gift) => acc + gift.cost, 0) || 0);
let editPersonModal = $state(false);
let addGiftModal = $state(false);
</script>
<div
class="mt-6 rounded-2xl bg-gray-300 p-4 text-gray-700 shadow-sm transition-all duration-200 ease-in-out hover:shadow-md md:p-6"
>
<div
class="mb-6 flex flex-col items-center gap-4 border-b border-gray-700 pb-4 sm:justify-between"
>
<Heading size="large" spacing="none">
<span class="text-gray-700">
{person.name}
</span>
</Heading>
<div class="flex flex-row items-center justify-center gap-2">
<Button variant="primary" onClick={() => (editPersonModal = true)}>Edytuj</Button>
<Button
variant="danger"
onClick={() => {
DB.deletePerson(person.id).finally(() => {
refreshAll();
});
}}>Usuń</Button
>
</div>
<PersonModal
isOpen={editPersonModal}
onClose={() => (editPersonModal = false)}
editPerson={person}
title="Edytuj osobę"
onSave={async (data) => {
await DB.updatePerson(person.id, data);
refreshAll();
editPersonModal = false;
}}
/>
{#if person.notes}
<p class="text-gray-600">{person.notes}</p>
{/if}
</div>
<div class="flex flex-wrap items-center gap-4 text-sm text-gray-500">
<span>Ilość prezentów: {gifts?.length || 0}</span>
<span></span>
<span>Koszt: {formatCurrency(totalCost)}</span>
</div>
<div class="mt-8 mb-4 flex items-start justify-between gap-4">
<Heading size="medium" spacing="none">
<span class="text-gray-700">
Prezenty <br />
</span>
</Heading>
<Button variant="secondary" onClick={() => (addGiftModal = true)}>+</Button>
<!-- <GiftCardAdd person={person} /> -->
<GiftModal
title="Dodaj nowy prezent"
isOpen={addGiftModal}
onClose={() => (addGiftModal = false)}
onSave={async (data) => {
await DB.createGift(data);
refreshAll();
addGiftModal = false;
}}
personId={person.id}
/>
</div>
{#each gifts as gift (gift.id)}
<GiftCard {...gift} editable />
{/each}
</div>

View File

@@ -14,7 +14,7 @@
let { onSave, isOpen, onClose, editPerson }: Props = $props();
let person = $state<Person>(editPerson ?? ({} as Person));
let person = $state<Person>(editPerson ? { ...editPerson } : ({} as Person));
let isLoading = $state(false);
if (!person?.name) {