Refactor hero items group

pull/8189/head
Kamran Ahmed 4 months ago
parent 6abc5ff916
commit 0bd4c0af03
  1. 6
      src/components/Dashboard/PersonalDashboard.tsx
  2. 254
      src/components/HeroSection/FavoriteRoadmaps.tsx
  3. 54
      src/components/HeroSection/HeroItemsGroup.tsx

@ -274,12 +274,6 @@ export function PersonalDashboard(props: PersonalDashboardProps) {
? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${avatar}` ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${avatar}`
: '/images/default-avatar.png'; : '/images/default-avatar.png';
const allRoadmapsAndBestPractices = [
...builtInRoleRoadmaps,
...builtInSkillRoadmaps,
...builtInBestPractices,
];
const enrichedProjects = personalDashboardDetails?.projects const enrichedProjects = personalDashboardDetails?.projects
.map((project) => { .map((project) => {
const projectDetail = projectDetails.find( const projectDetail = projectDetails.find(

@ -7,14 +7,13 @@ import {
EyeOff, EyeOff,
} from 'lucide-react'; } from 'lucide-react';
import { useState } from 'react'; import { useState } from 'react';
import { cn } from '../../lib/classname.ts';
import type { ProjectStatusDocument } from '../Projects/ListProjectSolutions.tsx'; import type { ProjectStatusDocument } from '../Projects/ListProjectSolutions.tsx';
import { CheckIcon } from '../ReactIcons/CheckIcon.tsx'; import { CheckIcon } from '../ReactIcons/CheckIcon.tsx';
import type { UserProgress } from '../TeamProgress/TeamProgressPage.tsx'; import type { UserProgress } from '../TeamProgress/TeamProgressPage.tsx';
import { HeroProject } from './HeroProject'; import { HeroProject } from './HeroProject';
import { HeroRoadmap } from './HeroRoadmap'; import { HeroRoadmap } from './HeroRoadmap';
import { HeroTitle } from './HeroTitle';
import { CreateRoadmapButton } from '../CustomRoadmap/CreateRoadmap/CreateRoadmapButton.tsx'; import { CreateRoadmapButton } from '../CustomRoadmap/CreateRoadmap/CreateRoadmapButton.tsx';
import { HeroItemsGroup } from './HeroItemsGroup';
export type AIRoadmapType = { export type AIRoadmapType = {
id: string; id: string;
@ -58,169 +57,120 @@ export function FavoriteRoadmaps(props: FavoriteRoadmapsProps) {
return ( return (
<div className="flex flex-col"> <div className="flex flex-col">
<div <HeroItemsGroup
className={cn('', { icon={<CheckIcon additionalClasses="mr-1.5 h-[14px] w-[14px]" />}
'border-b border-b-slate-800/70 pb-5 pt-5': !isAllCollapsed, isLoading={isLoading}
'py-2': isAllCollapsed, title="Your progress and bookmarks"
})} isAllCollapsed={isAllCollapsed}
> >
<div className="container"> {progress.map((resource) => (
<HeroTitle <HeroRoadmap
icon={ key={`${resource.resourceType}-${resource.resourceId}`}
( resourceId={resource.resourceId}
<CheckIcon additionalClasses="mr-1.5 h-[14px] w-[14px]" /> resourceType={resource.resourceType}
) as any resourceTitle={resource.resourceTitle}
isFavorite={resource.isFavorite}
percentageDone={
((resource.skipped + resource.done) / resource.total) * 100
}
url={
resource.resourceType === 'roadmap'
? `/${resource.resourceId}`
: `/best-practices/${resource.resourceId}`
} }
isLoading={isLoading}
title="Your progress and bookmarks"
/> />
{!isLoading && progress.length > 0 && !isAllCollapsed && ( ))}
<div className="mt-3 grid grid-cols-1 gap-2 sm:grid-cols-2 md:grid-cols-3"> <CreateRoadmapButton />
{progress.map((resource) => ( </HeroItemsGroup>
<HeroRoadmap
key={`${resource.resourceType}-${resource.resourceId}`}
resourceId={resource.resourceId}
resourceType={resource.resourceType}
resourceTitle={resource.resourceTitle}
isFavorite={resource.isFavorite}
percentageDone={
((resource.skipped + resource.done) / resource.total) * 100
}
url={
resource.resourceType === 'roadmap'
? `/${resource.resourceId}`
: `/best-practices/${resource.resourceId}`
}
/>
))}
<CreateRoadmapButton />
</div>
)}
</div>
</div>
<div <HeroItemsGroup
className={cn('', { icon={<MapIcon className="mr-1.5 h-[14px] w-[14px]" />}
'border-b border-b-slate-800/70 pb-5 pt-5': !isAllCollapsed, isLoading={isLoading}
'py-2': isAllCollapsed, title="Your custom roadmaps"
})} isAllCollapsed={isAllCollapsed}
> >
<div className="container"> {customRoadmaps.map((customRoadmap) => (
<HeroTitle <HeroRoadmap
icon={(<MapIcon className="mr-1.5 h-[14px] w-[14px]" />) as any} key={customRoadmap.resourceId}
isLoading={isLoading} resourceId={customRoadmap.resourceId}
title="Your custom roadmaps" resourceType={'roadmap'}
resourceTitle={customRoadmap.resourceTitle}
percentageDone={
((customRoadmap.skipped + customRoadmap.done) /
customRoadmap.total) *
100
}
url={`/r/${customRoadmap?.roadmapSlug}`}
allowFavorite={false}
/> />
{!isLoading && customRoadmaps.length > 0 && !isAllCollapsed && ( ))}
<div className="mt-3 grid grid-cols-1 gap-2 sm:grid-cols-2 md:grid-cols-3"> <CreateRoadmapButton />
{customRoadmaps.map((customRoadmap) => ( </HeroItemsGroup>
<HeroRoadmap
key={customRoadmap.resourceId}
resourceId={customRoadmap.resourceId}
resourceType={'roadmap'}
resourceTitle={customRoadmap.resourceTitle}
percentageDone={
((customRoadmap.skipped + customRoadmap.done) /
customRoadmap.total) *
100
}
url={`/r/${customRoadmap?.roadmapSlug}`}
allowFavorite={false}
/>
))}
<CreateRoadmapButton />
</div>
)}
</div>
</div>
<div <HeroItemsGroup
className={cn('', { icon={<Sparkle className="mr-1.5 h-[14px] w-[14px]" />}
'border-b border-b-slate-800/70 pb-5 pt-5': !isAllCollapsed, isLoading={isLoading}
'py-2': isAllCollapsed, title="Your AI roadmaps"
})} isAllCollapsed={isAllCollapsed}
> >
<div className="container"> {aiRoadmaps.map((aiRoadmap) => (
<HeroTitle <HeroRoadmap
icon={(<Sparkle className="mr-1.5 h-[14px] w-[14px]" />) as any} key={aiRoadmap.id}
isLoading={isLoading} resourceId={aiRoadmap.id}
title="Your AI roadmaps" resourceType={'roadmap'}
resourceTitle={aiRoadmap.title}
url={`/ai/${aiRoadmap.slug}`}
percentageDone={0}
allowFavorite={false}
isTrackable={false}
/> />
{!isLoading && aiRoadmaps.length > 0 && !isAllCollapsed && ( ))}
<div className="mt-3 grid grid-cols-1 gap-2 sm:grid-cols-2 md:grid-cols-3">
{aiRoadmaps.map((aiRoadmap) => (
<HeroRoadmap
key={aiRoadmap.id}
resourceId={aiRoadmap.id}
resourceType={'roadmap'}
resourceTitle={aiRoadmap.title}
url={`/ai/${aiRoadmap.slug}`}
percentageDone={0}
allowFavorite={false}
isTrackable={false}
/>
))}
<a <a
href="/ai" href="/ai"
className={ className={
'flex h-full w-full items-center justify-center gap-1 overflow-hidden rounded-md border border-dashed border-gray-800 p-3 text-sm text-gray-400 hover:border-gray-600 hover:bg-gray-900 hover:text-gray-300' 'flex h-full w-full items-center justify-center gap-1 overflow-hidden rounded-md border border-dashed border-gray-800 p-3 text-sm text-gray-400 hover:border-gray-600 hover:bg-gray-900 hover:text-gray-300'
} }
> >
<Plus size={16} /> <Plus size={16} />
Generate New Generate New
</a> </a>
</div> </HeroItemsGroup>
)}
</div>
</div>
<div <HeroItemsGroup
className={cn('', { icon={<FolderKanban className="mr-1.5 h-[14px] w-[14px]" />}
'border-b border-b-slate-800/70 pb-5 pt-5': !isAllCollapsed, isLoading={isLoading}
'py-2': isAllCollapsed, title="Your active projects"
})} isAllCollapsed={isAllCollapsed}
rightContent={
completedProjects.length > 0 && (
<button
onClick={() => setShowCompleted(!showCompleted)}
className="flex items-center gap-2 rounded-md px-2 py-1 text-xs text-slate-400 hover:text-slate-300"
>
{showCompleted ? (
<EyeOff className="h-3.5 w-3.5" />
) : (
<Eye className="h-3.5 w-3.5" />
)}
{completedProjects.length} Completed
</button>
)
}
className="border-b-0"
> >
<div className="container"> {projectsToShow.map((project) => (
<HeroTitle <HeroProject key={project._id} project={project} />
icon={ ))}
(<FolderKanban className="mr-1.5 h-[14px] w-[14px]" />) as any
}
isLoading={isLoading}
title="Your active projects"
rightContent={
completedProjects.length > 0 && (
<button
onClick={() => setShowCompleted(!showCompleted)}
className="flex items-center gap-2 rounded-md px-2 py-1 text-xs text-slate-400 hover:text-slate-300"
>
{showCompleted ? (
<EyeOff className="h-3.5 w-3.5" />
) : (
<Eye className="h-3.5 w-3.5" />
)}
{completedProjects.length} Completed
</button>
)
}
/>
{!isLoading && projectsToShow.length > 0 && !isAllCollapsed && (
<div className="mt-3 grid grid-cols-1 gap-2 sm:grid-cols-2 md:grid-cols-3">
{projectsToShow.map((project) => (
<HeroProject key={project._id} project={project} />
))}
<a <a
href="/projects" href="/projects"
className="flex min-h-[80px] items-center justify-center gap-2 rounded-md border border-dashed border-slate-800 p-4 text-sm text-slate-400 hover:border-slate-600 hover:bg-slate-900/50 hover:text-slate-300" className="flex min-h-[80px] items-center justify-center gap-2 rounded-md border border-dashed border-slate-800 p-4 text-sm text-slate-400 hover:border-slate-600 hover:bg-slate-900/50 hover:text-slate-300"
> >
<Plus size={16} /> <Plus size={16} />
Start a new project Start a new project
</a> </a>
</div> </HeroItemsGroup>
)}
</div>
</div>
</div> </div>
); );
} }

@ -0,0 +1,54 @@
import type { ReactNode } from 'react';
import { cn } from '../../lib/classname';
import { HeroTitle } from './HeroTitle';
type HeroItemsGroupProps = {
icon: any;
isLoading?: boolean;
title: string | ReactNode;
rightContent?: ReactNode;
isAllCollapsed?: boolean;
children?: ReactNode;
className?: string;
};
export function HeroItemsGroup(props: HeroItemsGroupProps) {
const {
icon,
isLoading = false,
title,
rightContent,
isAllCollapsed = false,
children,
className,
} = props;
const isCollapsed = isAllCollapsed || isLoading;
return (
<div
className={cn(
'',
{
'border-b border-b-slate-800/70 pb-5 pt-5': !isCollapsed,
'py-2': isCollapsed,
},
className,
)}
>
<div className="container">
<HeroTitle
icon={icon}
isLoading={isLoading}
title={title}
rightContent={rightContent}
/>
{!isLoading && !isAllCollapsed && (
<div className="mt-3 grid grid-cols-1 gap-2 sm:grid-cols-2 md:grid-cols-3">
{children}
</div>
)}
</div>
</div>
);
}
Loading…
Cancel
Save