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:
10
package-lock.json
generated
10
package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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'
|
||||
<FaTrashAlt
|
||||
size={14}
|
||||
color='red'
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleDelete();
|
||||
}}>
|
||||
Usuń
|
||||
</Button>
|
||||
</div>
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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} />
|
||||
</div>
|
||||
{notes && <p className='text-gray-600'>{notes}</p>}
|
||||
</div>
|
||||
<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>
|
||||
<GiftCardAdd person={person} />
|
||||
</div>
|
||||
</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>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user