|
|
@ -47,7 +47,6 @@ export function PersonalDashboard(props: PersonalDashboardProps) { |
|
|
|
builtInBestPractices = [], |
|
|
|
builtInBestPractices = [], |
|
|
|
builtInSkillRoadmaps = [], |
|
|
|
builtInSkillRoadmaps = [], |
|
|
|
} = props; |
|
|
|
} = props; |
|
|
|
const toast = useToast(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const [isLoading, setIsLoading] = useState(true); |
|
|
|
const [isLoading, setIsLoading] = useState(true); |
|
|
|
const [personalDashboardDetails, setPersonalDashboardDetails] = |
|
|
|
const [personalDashboardDetails, setPersonalDashboardDetails] = |
|
|
@ -111,22 +110,37 @@ export function PersonalDashboard(props: PersonalDashboardProps) { |
|
|
|
return updatedAtB.getTime() - updatedAtA.getTime(); |
|
|
|
return updatedAtB.getTime() - updatedAtA.getTime(); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
const { avatar, name, headline, email, username } = |
|
|
|
const aiGeneratedRoadmaps = customRoadmaps.filter( |
|
|
|
personalDashboardDetails || {}; |
|
|
|
(progress) => progress?.aiRoadmapId, |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
const customRoadmapsToShow = customRoadmaps.filter( |
|
|
|
|
|
|
|
(progress) => !progress?.aiRoadmapId, |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const { avatar, name } = personalDashboardDetails || {}; |
|
|
|
const avatarLink = avatar |
|
|
|
const avatarLink = avatar |
|
|
|
? `${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 currentPeriod = getCurrentPeriod(); |
|
|
|
const currentPeriod = getCurrentPeriod(); |
|
|
|
|
|
|
|
|
|
|
|
const relatedRoadmapIds = [...builtInRoleRoadmaps, ...builtInSkillRoadmaps] |
|
|
|
const allRoadmapsAndBestPractices = [ |
|
|
|
|
|
|
|
...builtInRoleRoadmaps, |
|
|
|
|
|
|
|
...builtInSkillRoadmaps, |
|
|
|
|
|
|
|
...builtInBestPractices, |
|
|
|
|
|
|
|
]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const relatedRoadmapIds = allRoadmapsAndBestPractices |
|
|
|
.filter((roadmap) => |
|
|
|
.filter((roadmap) => |
|
|
|
learningRoadmapsToShow?.some( |
|
|
|
learningRoadmapsToShow?.some( |
|
|
|
(learningRoadmap) => learningRoadmap.resourceId === roadmap.id, |
|
|
|
(learningRoadmap) => learningRoadmap.resourceId === roadmap.id, |
|
|
|
), |
|
|
|
), |
|
|
|
) |
|
|
|
) |
|
|
|
.flatMap((roadmap) => roadmap.relatedRoadmapIds) |
|
|
|
.flatMap((roadmap) => roadmap.relatedRoadmapIds) |
|
|
|
.filter(Boolean); |
|
|
|
.filter( |
|
|
|
|
|
|
|
(roadmapId) => |
|
|
|
|
|
|
|
!learningRoadmapsToShow.some((lr) => lr.resourceId === roadmapId), |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
const recommendedRoadmapIds = new Set( |
|
|
|
const recommendedRoadmapIds = new Set( |
|
|
|
relatedRoadmapIds.length === 0 |
|
|
|
relatedRoadmapIds.length === 0 |
|
|
@ -134,10 +148,9 @@ export function PersonalDashboard(props: PersonalDashboardProps) { |
|
|
|
: relatedRoadmapIds, |
|
|
|
: relatedRoadmapIds, |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
const recommendedRoadmaps = [ |
|
|
|
const recommendedRoadmaps = allRoadmapsAndBestPractices.filter((roadmap) => |
|
|
|
...builtInRoleRoadmaps, |
|
|
|
recommendedRoadmapIds.has(roadmap.id), |
|
|
|
...builtInSkillRoadmaps, |
|
|
|
); |
|
|
|
].filter((roadmap) => recommendedRoadmapIds.has(roadmap.id)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
return ( |
|
|
|
<section> |
|
|
|
<section> |
|
|
@ -149,47 +162,54 @@ export function PersonalDashboard(props: PersonalDashboardProps) { |
|
|
|
</h2> |
|
|
|
</h2> |
|
|
|
)} |
|
|
|
)} |
|
|
|
|
|
|
|
|
|
|
|
<div className="mt-8 grid grid-cols-4 gap-2"> |
|
|
|
<div className="mt-8 grid grid-cols-1 gap-2 sm:grid-cols-2 md:grid-cols-4"> |
|
|
|
{isLoading ? ( |
|
|
|
{isLoading ? ( |
|
|
|
<div className="h-[129px] animate-pulse rounded-lg border border-gray-300 bg-white"></div> |
|
|
|
<> |
|
|
|
|
|
|
|
<DashboardCardSkeleton /> |
|
|
|
|
|
|
|
<DashboardCardSkeleton /> |
|
|
|
|
|
|
|
<DashboardCardSkeleton /> |
|
|
|
|
|
|
|
<DashboardCardSkeleton /> |
|
|
|
|
|
|
|
</> |
|
|
|
) : ( |
|
|
|
) : ( |
|
|
|
<a |
|
|
|
<> |
|
|
|
className="overflow-hidden rounded-lg border border-gray-300 bg-white" |
|
|
|
<a |
|
|
|
href="/account/update-profile" |
|
|
|
className="overflow-hidden rounded-lg border border-gray-300 bg-white" |
|
|
|
> |
|
|
|
href="/account/update-profile" |
|
|
|
<div className="px-4 py-2.5"> |
|
|
|
> |
|
|
|
<img |
|
|
|
<div className="px-4 py-2.5"> |
|
|
|
src={avatarLink} |
|
|
|
<img |
|
|
|
alt={name} |
|
|
|
src={avatarLink} |
|
|
|
className="size-8 rounded-full" |
|
|
|
alt={name} |
|
|
|
/> |
|
|
|
className="size-8 rounded-full" |
|
|
|
</div> |
|
|
|
/> |
|
|
|
|
|
|
|
</div> |
|
|
|
<div className="flex flex-col gap-0.5 p-4"> |
|
|
|
|
|
|
|
<h3 className="font-medium">{name}</h3> |
|
|
|
<div className="flex flex-col gap-0.5 p-4"> |
|
|
|
<p className="text-xs">Setup your profile</p> |
|
|
|
<h3 className="truncate font-medium">{name}</h3> |
|
|
|
</div> |
|
|
|
<p className="text-xs">Setup your profile</p> |
|
|
|
</a> |
|
|
|
</div> |
|
|
|
)} |
|
|
|
</a> |
|
|
|
|
|
|
|
|
|
|
|
<DashboardCard |
|
|
|
<DashboardCard |
|
|
|
icon={'💡'} |
|
|
|
icon={'💡'} |
|
|
|
title="Learn a new Skill" |
|
|
|
title="Learn a new Skill" |
|
|
|
description="Visit our Roadmaps" |
|
|
|
description="Visit our Roadmaps" |
|
|
|
href="/roadmaps" |
|
|
|
href="/roadmaps" |
|
|
|
/> |
|
|
|
/> |
|
|
|
<DashboardCard |
|
|
|
<DashboardCard |
|
|
|
icon={'🏗️'} |
|
|
|
icon={'🏗️'} |
|
|
|
title="Practice your skills" |
|
|
|
title="Practice your skills" |
|
|
|
description="Visit Projects" |
|
|
|
description="Visit Projects" |
|
|
|
href="/backend/projects" |
|
|
|
href="/backend/projects" |
|
|
|
/> |
|
|
|
/> |
|
|
|
<DashboardCard |
|
|
|
<DashboardCard |
|
|
|
icon={'📚'} |
|
|
|
icon={'📚'} |
|
|
|
title="Do things right way" |
|
|
|
title="Do things right way" |
|
|
|
description="Visit Best Practices" |
|
|
|
description="Visit Best Practices" |
|
|
|
href="/best-practices" |
|
|
|
href="/best-practices" |
|
|
|
/> |
|
|
|
/> |
|
|
|
|
|
|
|
</> |
|
|
|
|
|
|
|
)} |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<ListDashboardProgress |
|
|
|
<ListDashboardProgress |
|
|
@ -203,13 +223,13 @@ export function PersonalDashboard(props: PersonalDashboardProps) { |
|
|
|
/> |
|
|
|
/> |
|
|
|
|
|
|
|
|
|
|
|
<ListDashboardCustomProgress |
|
|
|
<ListDashboardCustomProgress |
|
|
|
progresses={customRoadmaps} |
|
|
|
progresses={customRoadmapsToShow} |
|
|
|
isLoading={isLoading} |
|
|
|
isLoading={isLoading} |
|
|
|
/> |
|
|
|
/> |
|
|
|
<DashboardCardLink |
|
|
|
<ListDashboardCustomProgress |
|
|
|
href="/ai" |
|
|
|
progresses={aiGeneratedRoadmaps} |
|
|
|
title="Generate Roadmaps with AI" |
|
|
|
isLoading={isLoading} |
|
|
|
description="You can generate your own roadmap with AI" |
|
|
|
isAIGeneratedRoadmaps={true} |
|
|
|
/> |
|
|
|
/> |
|
|
|
</section> |
|
|
|
</section> |
|
|
|
); |
|
|
|
); |
|
|
@ -238,9 +258,15 @@ function DashboardCard(props: DashboardCardProps) { |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<div className="flex grow flex-col justify-center gap-0.5 bg-white p-4"> |
|
|
|
<div className="flex grow flex-col justify-center gap-0.5 bg-white p-4"> |
|
|
|
<h3 className="font-medium text-black">{title}</h3> |
|
|
|
<h3 className="truncate font-medium text-black">{title}</h3> |
|
|
|
<p className="text-xs text-black">{description}</p> |
|
|
|
<p className="text-xs text-black">{description}</p> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</a> |
|
|
|
</a> |
|
|
|
); |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function DashboardCardSkeleton() { |
|
|
|
|
|
|
|
return ( |
|
|
|
|
|
|
|
<div className="h-[129px] animate-pulse rounded-lg border border-gray-300 bg-white"></div> |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
} |
|
|
|