From 782c619a9177542a0b719f469d59724d9ab13e0c Mon Sep 17 00:00:00 2001 From: Ilia Mashkov Date: Mon, 18 May 2026 12:39:41 +0300 Subject: [PATCH] feat: ExperienceCard stack field and Card subcomponent layout --- .../ui/ExperienceCard/ExperienceCard.test.tsx | 9 ++--- .../ui/ExperienceCard/ExperienceCard.tsx | 33 ++++++++++++++----- src/shared/api/types.ts | 4 +++ .../ExperienceSection.test.tsx | 2 ++ .../ExperienceSection/ExperienceSection.tsx | 1 + 5 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/entities/experience/ui/ExperienceCard/ExperienceCard.test.tsx b/src/entities/experience/ui/ExperienceCard/ExperienceCard.test.tsx index ecfc824..61bf825 100644 --- a/src/entities/experience/ui/ExperienceCard/ExperienceCard.test.tsx +++ b/src/entities/experience/ui/ExperienceCard/ExperienceCard.test.tsx @@ -6,6 +6,7 @@ const DEFAULT_PROPS = { company: 'Acme Corp', period: '2021 – 2024', description: 'Built scalable frontend systems.', + stack: [], }; describe('ExperienceCard', () => { @@ -32,9 +33,9 @@ describe('ExperienceCard', () => { }); describe('structure', () => { - it('title is rendered as an h4', () => { + it('title is rendered as an h3', () => { render(); - expect(screen.getByRole('heading', { level: 4 })).toHaveTextContent('Senior Developer'); + expect(screen.getByRole('heading', { level: 3 })).toHaveTextContent('Senior Developer'); }); it('period badge has brutal-border, bg-blue, text-cream, text-sm', () => { @@ -43,11 +44,11 @@ describe('ExperienceCard', () => { expect(badge).toHaveClass('brutal-border', 'bg-blue', 'text-cream', 'text-sm'); }); - it('company paragraph has opacity-80', () => { + it('company paragraph has opacity-60', () => { render(); const company = screen.getByText('Acme Corp'); expect(company.tagName).toBe('P'); - expect(company).toHaveClass('opacity-80'); + expect(company).toHaveClass('opacity-60'); }); it('description renders via RichText with rich-text class', () => { diff --git a/src/entities/experience/ui/ExperienceCard/ExperienceCard.tsx b/src/entities/experience/ui/ExperienceCard/ExperienceCard.tsx index ba05de3..a60c9ee 100644 --- a/src/entities/experience/ui/ExperienceCard/ExperienceCard.tsx +++ b/src/entities/experience/ui/ExperienceCard/ExperienceCard.tsx @@ -1,4 +1,4 @@ -import { Card, RichText } from '$shared/ui'; +import { Card, CardContent, CardFooter, CardHeader, CardTitle, RichText } from '$shared/ui'; type Props = { /** @@ -17,6 +17,10 @@ type Props = { * Description of responsibilities and achievements */ description: string; + /** + * Technologies used during this role + */ + stack: string[]; /** * Additional CSS classes forwarded to the card */ @@ -24,19 +28,30 @@ type Props = { }; /** - * Work experience card with title, company, period, and description. + * Work experience card with title, company, period, description, and tech stack. */ -export function ExperienceCard({ title, company, period, description, className }: Props) { +export function ExperienceCard({ title, company, period, description, stack, className }: Props) { return ( -
-
-

{title}

-

{company}

+ +
+ {title} +

{company}

{period} -
- + + + + + {stack.length > 0 && ( + + {stack.map((tech) => ( + + {tech} + + ))} + + )} ); } diff --git a/src/shared/api/types.ts b/src/shared/api/types.ts index 787ec8b..6c8db9b 100644 --- a/src/shared/api/types.ts +++ b/src/shared/api/types.ts @@ -77,6 +77,10 @@ export type ExperienceRecord = BaseRecord & { * Rich text description of responsibilities and achievements */ description: string; + /** + * Technologies used during this role + */ + stack: string[]; /** * Sorting weight for chronological display */ diff --git a/src/widgets/ExperienceSection/ui/ExperienceSection/ExperienceSection.test.tsx b/src/widgets/ExperienceSection/ui/ExperienceSection/ExperienceSection.test.tsx index 2303fde..3530baa 100644 --- a/src/widgets/ExperienceSection/ui/ExperienceSection/ExperienceSection.test.tsx +++ b/src/widgets/ExperienceSection/ui/ExperienceSection/ExperienceSection.test.tsx @@ -18,6 +18,7 @@ const mockItems = [ start_date: '2022-01-01T00:00:00Z', end_date: null, description: 'Built critical systems.', + stack: ['React', 'TypeScript'], order: 1, }, { @@ -31,6 +32,7 @@ const mockItems = [ start_date: '2020-01-01T00:00:00Z', end_date: '2021-12-31T00:00:00Z', description: 'Learned the ropes.', + stack: [], order: 2, }, ]; diff --git a/src/widgets/ExperienceSection/ui/ExperienceSection/ExperienceSection.tsx b/src/widgets/ExperienceSection/ui/ExperienceSection/ExperienceSection.tsx index a0bedc9..570788b 100644 --- a/src/widgets/ExperienceSection/ui/ExperienceSection/ExperienceSection.tsx +++ b/src/widgets/ExperienceSection/ui/ExperienceSection/ExperienceSection.tsx @@ -21,6 +21,7 @@ export default async function ExperienceSection() { company={exp.company} period={formatYearRange(exp.start_date, exp.end_date)} description={exp.description} + stack={exp.stack} /> ))}