feat: introduce PersonCard component for displaying and managing person details and gifts
This commit is contained in:
89
src/lib/components/molecules/PersonCard.svelte
Normal file
89
src/lib/components/molecules/PersonCard.svelte
Normal 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>
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user