diff --git a/src/entities/project/ui/ProjectCard/ProjectCard.test.tsx b/src/entities/project/ui/ProjectCard/ProjectCard.test.tsx index e16c08f..306a255 100644 --- a/src/entities/project/ui/ProjectCard/ProjectCard.test.tsx +++ b/src/entities/project/ui/ProjectCard/ProjectCard.test.tsx @@ -15,7 +15,7 @@ describe('ProjectCard', () => { expect(screen.getByText('My Project')).toBeInTheDocument(); }); - it('renders the year badge', () => { + it('renders the year', () => { render(); expect(screen.getByText('2024')).toBeInTheDocument(); }); @@ -37,23 +37,55 @@ describe('ProjectCard', () => { }); }); + describe('layout', () => { + it('year is inside the sidebar column', () => { + render(); + expect(screen.getByText('2024').closest('.brutal-border-sidebar')).toBeInTheDocument(); + }); + + it('tags are inside the sidebar column', () => { + render(); + expect(screen.getByText('React').closest('.brutal-border-sidebar')).toBeInTheDocument(); + expect(screen.getByText('Node').closest('.brutal-border-sidebar')).toBeInTheDocument(); + }); + + it('View Project button is inside the sidebar column', () => { + render(); + const btn = screen.getByRole('button', { name: /view project/i }); + expect(btn.closest('.brutal-border-sidebar')).toBeInTheDocument(); + }); + + it('title is outside the sidebar column', () => { + render(); + expect(screen.getByText('My Project').closest('.brutal-border-sidebar')).toBeNull(); + }); + + it('description is outside the sidebar column', () => { + render(); + expect(screen.getByText('A cool project description').closest('.brutal-border-sidebar')).toBeNull(); + }); + }); + describe('structure', () => { it('card has hover transition classes', () => { const { container } = render(); - const card = container.firstChild as HTMLElement; - expect(card).toHaveClass('group', 'transition-shadow', 'duration-300'); + expect(container.firstChild).toHaveClass('group', 'transition-shadow', 'duration-300'); }); - it('year badge has correct classes', () => { + it('title renders as h3', () => { render(); - const yearBadge = screen.getByText('2024'); - expect(yearBadge).toHaveClass('brutal-border', 'bg-blue', 'text-cream', 'text-sm'); + expect(screen.getByRole('heading', { level: 3 })).toHaveTextContent('My Project'); }); - it('tags have correct classes', () => { + it('year has Badge default classes', () => { + render(); + expect(screen.getByText('2024')).toHaveClass('brutal-border', 'bg-blue', 'text-cream'); + }); + + it('tags are xs outline badges', () => { render(); const tag = screen.getByText('React'); - expect(tag).toHaveClass('brutal-border', 'bg-cream', 'text-blue', 'text-sm', 'uppercase', 'tracking-wide'); + expect(tag).toHaveClass('brutal-border', 'bg-transparent', 'px-2'); }); }); @@ -68,7 +100,7 @@ describe('ProjectCard', () => { expect(screen.getByRole('img')).toBeInTheDocument(); }); - it('image wrapper has aspect-video and overflow-hidden when imageUrl is provided', () => { + it('image wrapper has aspect-video and overflow-hidden', () => { const { container } = render(); const imgWrapper = container.querySelector('img')?.parentElement; expect(imgWrapper).toHaveClass('aspect-video', 'overflow-hidden', 'brutal-border'); diff --git a/src/entities/project/ui/ProjectCard/ProjectCard.tsx b/src/entities/project/ui/ProjectCard/ProjectCard.tsx index cdc4002..e0d708c 100644 --- a/src/entities/project/ui/ProjectCard/ProjectCard.tsx +++ b/src/entities/project/ui/ProjectCard/ProjectCard.tsx @@ -1,6 +1,6 @@ import Image from 'next/image'; import { cn } from '$shared/lib'; -import { Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '$shared/ui'; +import { Badge, Button, Card, CardSidebar, CardTitle } from '$shared/ui'; type Props = { /** @@ -26,38 +26,42 @@ type Props = { }; /** - * Compact project card for grid/list display. + * Project card with sidebar layout. + * Sidebar: year badge, stack tags, View Project button. + * Main: title, optional image, description. */ export function ProjectCard({ title, year, description, tags, imageUrl }: Props) { return ( - -
- {title} - {year} + + {year} + {tags.length > 0 && ( +
+ {tags.map((tag) => ( + + {tag} + + ))} +
+ )} + +
+ } + > +
+ {title} + {imageUrl && ( +
+ {title} +
+ )} +

{description}

- {description} -
- - {imageUrl && ( -
- {title} -
- )} - - - {tags.map((tag) => ( - - {tag} - - ))} - - - - - +
); }