Refactor hero items group

pull/8189/head
Kamran Ahmed 3 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}`
: '/images/default-avatar.png';
const allRoadmapsAndBestPractices = [
...builtInRoleRoadmaps,
...builtInSkillRoadmaps,
...builtInBestPractices,
];
const enrichedProjects = personalDashboardDetails?.projects
.map((project) => {
const projectDetail = projectDetails.find(

@ -7,14 +7,13 @@ import {
EyeOff,
} from 'lucide-react';
import { useState } from 'react';
import { cn } from '../../lib/classname.ts';
import type { ProjectStatusDocument } from '../Projects/ListProjectSolutions.tsx';
import { CheckIcon } from '../ReactIcons/CheckIcon.tsx';
import type { UserProgress } from '../TeamProgress/TeamProgressPage.tsx';
import { HeroProject } from './HeroProject';
import { HeroRoadmap } from './HeroRoadmap';
import { HeroTitle } from './HeroTitle';
import { CreateRoadmapButton } from '../CustomRoadmap/CreateRoadmap/CreateRoadmapButton.tsx';
import { HeroItemsGroup } from './HeroItemsGroup';
export type AIRoadmapType = {
id: string;
@ -58,169 +57,120 @@ export function FavoriteRoadmaps(props: FavoriteRoadmapsProps) {
return (
<div className="flex flex-col">
<div
className={cn('', {
'border-b border-b-slate-800/70 pb-5 pt-5': !isAllCollapsed,
'py-2': isAllCollapsed,
})}
<HeroItemsGroup
icon={<CheckIcon additionalClasses="mr-1.5 h-[14px] w-[14px]" />}
isLoading={isLoading}
title="Your progress and bookmarks"
isAllCollapsed={isAllCollapsed}
>
<div className="container">
<HeroTitle
icon={
(
<CheckIcon additionalClasses="mr-1.5 h-[14px] w-[14px]" />
) as any
{progress.map((resource) => (
<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}`
}
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">
{progress.map((resource) => (
<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>
))}
<CreateRoadmapButton />
</HeroItemsGroup>
<div
className={cn('', {
'border-b border-b-slate-800/70 pb-5 pt-5': !isAllCollapsed,
'py-2': isAllCollapsed,
})}
<HeroItemsGroup
icon={<MapIcon className="mr-1.5 h-[14px] w-[14px]" />}
isLoading={isLoading}
title="Your custom roadmaps"
isAllCollapsed={isAllCollapsed}
>
<div className="container">
<HeroTitle
icon={(<MapIcon className="mr-1.5 h-[14px] w-[14px]" />) as any}
isLoading={isLoading}
title="Your custom roadmaps"
{customRoadmaps.map((customRoadmap) => (
<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}
/>
{!isLoading && customRoadmaps.length > 0 && !isAllCollapsed && (
<div className="mt-3 grid grid-cols-1 gap-2 sm:grid-cols-2 md:grid-cols-3">
{customRoadmaps.map((customRoadmap) => (
<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>
))}
<CreateRoadmapButton />
</HeroItemsGroup>
<div
className={cn('', {
'border-b border-b-slate-800/70 pb-5 pt-5': !isAllCollapsed,
'py-2': isAllCollapsed,
})}
<HeroItemsGroup
icon={<Sparkle className="mr-1.5 h-[14px] w-[14px]" />}
isLoading={isLoading}
title="Your AI roadmaps"
isAllCollapsed={isAllCollapsed}
>
<div className="container">
<HeroTitle
icon={(<Sparkle className="mr-1.5 h-[14px] w-[14px]" />) as any}
isLoading={isLoading}
title="Your AI roadmaps"
{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}
/>
{!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
href="/ai"
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'
}
>
<Plus size={16} />
Generate New
</a>
</div>
)}
</div>
</div>
<a
href="/ai"
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'
}
>
<Plus size={16} />
Generate New
</a>
</HeroItemsGroup>
<div
className={cn('', {
'border-b border-b-slate-800/70 pb-5 pt-5': !isAllCollapsed,
'py-2': isAllCollapsed,
})}
<HeroItemsGroup
icon={<FolderKanban className="mr-1.5 h-[14px] w-[14px]" />}
isLoading={isLoading}
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">
<HeroTitle
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} />
))}
{projectsToShow.map((project) => (
<HeroProject key={project._id} project={project} />
))}
<a
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"
>
<Plus size={16} />
Start a new project
</a>
</div>
)}
</div>
</div>
<a
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"
>
<Plus size={16} />
Start a new project
</a>
</HeroItemsGroup>
</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