Enhance Badge component styling for better visibility, update GiftCard component to include Heading and FaTrashAlt icon for delete action, and refactor PersonCard to streamline layout and remove unnecessary state management.

This commit is contained in:
Norbert Maciaszek
2025-11-11 19:45:30 +01:00
parent 38f034b0e2
commit 924a58501a
6 changed files with 60 additions and 50 deletions

10
package-lock.json generated
View File

@@ -12,6 +12,7 @@
"pocketbase": "^0.26.3",
"react": "19.2.0",
"react-dom": "19.2.0",
"react-icons": "^5.5.0",
"zustand": "^5.0.8"
},
"devDependencies": {
@@ -1556,6 +1557,15 @@
"react": "^19.2.0"
}
},
"node_modules/react-icons": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz",
"integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==",
"license": "MIT",
"peerDependencies": {
"react": "*"
}
},
"node_modules/scheduler": {
"version": "0.27.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",

View File

@@ -12,6 +12,7 @@
"pocketbase": "^0.26.3",
"react": "19.2.0",
"react-dom": "19.2.0",
"react-icons": "^5.5.0",
"zustand": "^5.0.8"
},
"devDependencies": {

View File

@@ -6,5 +6,9 @@ type Props = {
};
export const Badge: FC<Props> = ({ children, disabled }) => {
return <span className='px-2 py-1 text-xs font-medium text-blue-600 bg-blue-50 rounded-lg'>{children}</span>;
return (
<span className='px-3 py-1 text-xs font-medium text-gray-800 bg-amber-300 rounded-lg hover:bg-amber-400 transition-all duration-200 ease-in-out'>
{children}
</span>
);
};

View File

@@ -9,6 +9,8 @@ import { useRouter } from 'next/navigation';
import { Button } from '@/components/atoms/Button';
import { Badge } from '@/components/atoms/Badge';
import Link from 'next/link';
import { Heading } from '@/components/atoms/Heading';
import { FaTrashAlt } from 'react-icons/fa';
type Props = {
hideDetails?: boolean;
@@ -20,6 +22,7 @@ export const GiftCard: FC<Gift & Props> = ({ hideDetails = false, editable = fal
const [isOpen, setIsOpen] = useState(false);
const year = useGlobalStore((s) => s.year);
const router = useRouter();
editable = editable || !!gift.id;
const { title, description, cost, status, created, expand, link } = gift;
@@ -38,42 +41,30 @@ export const GiftCard: FC<Gift & Props> = ({ hideDetails = false, editable = fal
return (
<>
<div
className={`rounded-2xl shadow-sm p-4 my-6 md:p-6 transition-all duration-200 ease-in-out ${
bgByStatus[status]
} ${editable ? 'cursor-pointer hover:shadow-md ' : ''}`}
className={`rounded-2xl shadow-sm p-4 my-6 transition-all duration-200 ease-in-out ${bgByStatus[status]} ${
editable ? 'cursor-pointer hover:shadow-md ' : ''
}`}
onClick={editable ? () => setIsOpen(true) : undefined}>
<div className='flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4'>
<div className='flex-1'>
<div className='flex items-center justify-between gap-3 mb-2'>
<h3 className='text-lg font-semibold text-gray-800'>{title}</h3>
<div className='flex flex-col gap-2'>
<div className='flex justify-between items-center flex-wrap gap-2'>
<div className='flex items-center gap-2'>
<Heading size='small' spacing='none'>
{title}
</Heading>
{editable && (
<div className='ml-auto'>
<Button
variant='danger'
onClick={(e) => {
e.stopPropagation();
handleDelete();
}}>
Usuń
</Button>
</div>
<FaTrashAlt
size={14}
color='red'
onClick={(e) => {
e.stopPropagation();
handleDelete();
}}
/>
)}
</div>
{description && <p className='text-base text-gray-600 mb-3'>{description}</p>}
<div
className={`flex flex-wrap text-sm text-gray-500 ${editable ? 'flex-col gap-2' : 'items-center gap-4'}`}>
<span>Data dodania: {new Date(created).toLocaleDateString()}</span>
<span>Koszt: {formatCurrency(cost)}</span>
{!hideDetails && (
<>
<span></span>
<span>Dla: {expand?.person.name}</span>
</>
)}
<span>Status: {formatStatus(status)}</span>
</div>
{link && (
<div className='flex flex-wrap items-center gap-2 mt-6'>
<div className='flex flex-wrap items-center gap-2'>
{link.split('\n').map((line, index) => (
<Link href={line} target='_blank' key={index} onClick={(e) => e.stopPropagation()}>
<Badge>Link {index + 1}</Badge>
@@ -82,6 +73,16 @@ export const GiftCard: FC<Gift & Props> = ({ hideDetails = false, editable = fal
</div>
)}
</div>
<div className='flex flex-wrap items-center gap-2'>
<span>Koszt: {formatCurrency(cost)}</span>
{!hideDetails && (
<>
<span></span>
<span>Dla: {expand?.person.name}</span>
</>
)}
</div>
{description && <p className='text-base text-gray-600'>{description}</p>}
</div>
</div>

View File

@@ -28,7 +28,7 @@ export const PersonCardEdit: FC<Props> = ({ person }) => {
<Button variant='primary' onClick={() => setIsOpen(true)}>
Edytuj
</Button>
<Button variant='secondary' onClick={handleDelete}>
<Button variant='danger' onClick={handleDelete}>
Usuń
</Button>
</div>

View File

@@ -1,42 +1,36 @@
'use client';
import { Heading } from '@/components/atoms/Heading';
import { formatCurrency } from '@/helpers/formatCurrency';
import { FC, useState } from 'react';
import { FC } from 'react';
import { GiftCard } from '../GiftCard';
import { GiftCardAdd, PersonCardEdit } from './client';
import { Button } from '@/components/atoms/Button';
export const PersonCard: FC<Person> = (person) => {
const [isOpen, setIsOpen] = useState(false);
const { name, notes, expand } = person;
const { gifts } = expand;
return (
<div className='bg-white rounded-2xl shadow-sm hover:shadow-md p-4 md:p-6 transition-all duration-200 ease-in-out mt-6'>
<div className='flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 pb-2 mb-6 border-b border-gray-200'>
<div className='flex-1'>
<Heading size='large'>{name}</Heading>
</div>
<div className='flex flex-col sm:items-center sm:justify-between gap-4 pb-4 mb-6 border-b border-gray-200'>
<Heading size='large' spacing='none'>
{name}
</Heading>
<PersonCardEdit person={person} />
{notes && <p className='text-gray-600'>{notes}</p>}
</div>
{notes && <p className='text-gray-600'>{notes}</p>}
<div className='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(gifts?.reduce((acc, gift) => acc + gift.cost, 0) || 0)}</span>
</div>
<div className='mt-8 mb-4 flex items-start gap-4'>
<div className='mt-8 mb-4 flex items-start justify-between gap-4'>
<Heading size='medium' spacing='none'>
Prezenty <br />
</Heading>
{isOpen && <GiftCardAdd person={person} />}
<div className='ml-auto'>
<Button variant='secondary' onClick={() => setIsOpen(!isOpen)}>
{isOpen ? 'Mniej' : 'Więcej'}
</Button>
</div>
<GiftCardAdd person={person} />
</div>
{isOpen && gifts?.map((gift) => <GiftCard key={gift.id} {...gift} hideDetails editable personId={person.id} />)}
{gifts?.map((gift) => (
<GiftCard key={gift.id} {...gift} hideDetails personId={person.id} />
))}
</div>
);
};