diff --git a/packages/shared/src/features/profile/components/experience/UserExperiencesList.spec.tsx b/packages/shared/src/features/profile/components/experience/UserExperiencesList.spec.tsx index 0b54f830b5..f4345e3700 100644 --- a/packages/shared/src/features/profile/components/experience/UserExperiencesList.spec.tsx +++ b/packages/shared/src/features/profile/components/experience/UserExperiencesList.spec.tsx @@ -100,7 +100,7 @@ describe('UserExperiencesList', () => { }); describe('Basic rendering', () => { - it('should render empty fragment when no experiences provided', () => { + it('should render empty state with add button for owner when no experiences provided', () => { const user = createUser(); renderComponent({ experiences: [], @@ -109,6 +109,23 @@ describe('UserExperiencesList', () => { user, }); + // Owner should see empty state with title and add button + expect(screen.getByText('Work Experience')).toBeInTheDocument(); + expect(screen.getByText('Add your work experience')).toBeInTheDocument(); + expect( + screen.getByRole('link', { name: /add your first work experience/i }), + ).toBeInTheDocument(); + }); + + it('should render empty fragment for non-owner when no experiences provided', () => { + const user = createUser({ id: 'otheruser', username: 'otheruser' }); + renderComponent({ + experiences: [], + title: 'Work Experience', + experienceType: UserExperienceType.Work, + user, + }); + expect(screen.queryByText('Work Experience')).not.toBeInTheDocument(); }); @@ -461,13 +478,13 @@ describe('UserExperiencesList', () => { user, }); - // The edit button is rendered as a link/button with href - const editLinks = screen.getAllByRole('link'); - const editButton = editLinks.find((link) => - link.getAttribute('href')?.includes('settings/profile/experience/work'), - ); - expect(editButton).toBeTruthy(); - expect(editButton?.getAttribute('href')).toBe( + // The edit button is rendered as a link/button with href to settings page + const editButton = screen.getByRole('link', { + name: 'Edit Work Experience', + }); + expect(editButton).toBeInTheDocument(); + expect(editButton).toHaveAttribute( + 'href', 'https://app.daily.dev/settings/profile/experience/work', ); }); diff --git a/packages/shared/src/features/profile/components/experience/UserExperiencesList.tsx b/packages/shared/src/features/profile/components/experience/UserExperiencesList.tsx index d6314cbcfe..b65d649b38 100644 --- a/packages/shared/src/features/profile/components/experience/UserExperiencesList.tsx +++ b/packages/shared/src/features/profile/components/experience/UserExperiencesList.tsx @@ -1,11 +1,10 @@ import type { ReactElement } from 'react'; import React, { useMemo } from 'react'; -import type { - UserExperience, - UserExperienceType, -} from '../../../../graphql/user/profile'; +import type { UserExperience } from '../../../../graphql/user/profile'; +import { UserExperienceType } from '../../../../graphql/user/profile'; import { Typography, + TypographyColor, TypographyTag, TypographyType, } from '../../../../components/typography/Typography'; @@ -17,13 +16,71 @@ import { ButtonSize, ButtonVariant, } from '../../../../components/buttons/Button'; -import { MoveToIcon, EditIcon } from '../../../../components/icons'; +import { + MoveToIcon, + PlusIcon, + EditIcon, + JobIcon, + TerminalIcon, + TourIcon, +} from '../../../../components/icons'; +import { GraduationIcon } from '../../../../components/icons/Graduation'; +import { MedalIcon } from '../../../../components/icons/Medal'; +import { VolunteeringIcon } from '../../../../components/icons/Volunteering'; import { IconSize } from '../../../../components/Icon'; import Link from '../../../../components/utilities/Link'; import { useAuthContext } from '../../../../contexts/AuthContext'; import { webappUrl } from '../../../../lib/constants'; import type { PublicProfile } from '../../../../lib/user'; import { useProfilePreview } from '../../../../hooks/profile/useProfilePreview'; +import type { IconProps } from '../../../../components/Icon'; + +const experienceTypeConfig: Record< + UserExperienceType, + { + icon: React.FC; + label: string; + heading: string; + subheading: string; + } +> = { + [UserExperienceType.Work]: { + icon: JobIcon, + label: 'work experience', + heading: 'Add your work experience', + subheading: "Show where you've worked and what you've accomplished", + }, + [UserExperienceType.Education]: { + icon: GraduationIcon, + label: 'education', + heading: 'Add your education', + subheading: 'Share your academic background and achievements', + }, + [UserExperienceType.Certification]: { + icon: MedalIcon, + label: 'certification', + heading: 'Add your certifications', + subheading: 'Showcase your professional certifications and credentials', + }, + [UserExperienceType.OpenSource]: { + icon: TerminalIcon, + label: 'open source contribution', + heading: 'Add your open source work', + subheading: 'Highlight your contributions to open source projects', + }, + [UserExperienceType.Project]: { + icon: TourIcon, + label: 'project', + heading: 'Add your projects', + subheading: 'Share your side projects and publications', + }, + [UserExperienceType.Volunteering]: { + icon: VolunteeringIcon, + label: 'volunteering experience', + heading: 'Add your volunteering', + subheading: 'Share your community involvement and volunteer work', + }, +}; interface UserExperienceListProps { experiences: T[]; @@ -75,13 +132,64 @@ export function UserExperienceList({ [experiences], ); - if (!user || !experiences?.length) { + const hasExperiences = experiences?.length > 0; + + if (!user) { + return null; + } + + if (!hasExperiences && !isOwner) { return null; } const showMoreUrl = `${webappUrl}${user.username}/${experienceType}`; const editBaseUrl = `${webappUrl}settings/profile/experience/edit`; + const addUrl = `${editBaseUrl}?type=${experienceType}`; const settingsUrl = `${webappUrl}settings/profile/experience/${experienceType}`; + const config = experienceTypeConfig[experienceType]; + const IconComponent = config.icon; + + if (!hasExperiences && isOwner) { + return ( +
+ {title && ( + + {title} + + )} +
+
+ +
+
+ + {config.heading} + + + {config.subheading} + +
+ + + +
+
+ ); + } return (
@@ -90,7 +198,7 @@ export function UserExperienceList({ {title} - {settingsUrl && isOwner && ( + {isOwner && (