-
+
+
+
+ {Math.floor(+progressPercentage)}%
+
+
+
+ {isCustomResource ? (
+ <>Last updated {getRelativeTimeString(updatedAt)}>
+ ) : (
+ <>Last practiced {getRelativeTimeString(updatedAt)}>
+ )}
+
);
}
diff --git a/src/components/Dashboard/DashboardTab.tsx b/src/components/Dashboard/DashboardTab.tsx
index 0895fe107..74c4fdec7 100644
--- a/src/components/Dashboard/DashboardTab.tsx
+++ b/src/components/Dashboard/DashboardTab.tsx
@@ -20,7 +20,7 @@ export function DashboardTab(props: DashboardTabProps) {
+ ) : (
) : null;
+ const Slot = isAIGeneratedRoadmaps ? 'a' : 'button';
+
return (
<>
{customRoadmapModal}
+
- Custom Roadmaps
+ {isAIGeneratedRoadmaps ? 'AI Generated Roadmaps' : 'Custom Roadmaps'}
- {isLoading ? (
-
- {Array.from({ length: 8 }).map((_, index) => (
-
- ))}
-
- ) : (
-
- {progresses.map((progress) => (
-
- ))}
+
+ {isLoading ? (
+ <>
+ {Array.from({ length: 8 }).map((_, index) => (
+
+ ))}
+ >
+ ) : (
+ <>
+ {progresses.map((progress) => (
+
+ ))}
-
-
- )}
+
{
+ setIsCreateCustomRoadmapModalOpen(true);
+ },
+ })}
+ >
+ {isAIGeneratedRoadmaps ? '+ Generate New' : '+ Create New'}
+
+ >
+ )}
+
>
);
}
diff --git a/src/components/Dashboard/ListDashboardProgress.tsx b/src/components/Dashboard/ListDashboardProgress.tsx
index 258d7c665..4fd9609f2 100644
--- a/src/components/Dashboard/ListDashboardProgress.tsx
+++ b/src/components/Dashboard/ListDashboardProgress.tsx
@@ -22,22 +22,24 @@ export function ListDashboardProgress(props: ListDashboardProgressProps) {
Progress and Bookmarks
- {isLoading ? (
-
- {Array.from({ length: 8 }).map((_, index) => (
-
- ))}
-
- ) : (
-
- {progresses.map((progress) => (
-
- ))}
-
- )}
+
+ {isLoading ? (
+ <>
+ {Array.from({ length: 8 }).map((_, index) => (
+
+ ))}
+ >
+ ) : (
+ <>
+ {progresses.map((progress) => (
+
+ ))}
+ >
+ )}
+
>
);
}
@@ -48,6 +50,6 @@ export function DashboardProgressCardSkeleton(
props: DashboardProgressCardSkeletonProps,
) {
return (
-
+
);
}
diff --git a/src/components/Dashboard/PersonalDashboard.tsx b/src/components/Dashboard/PersonalDashboard.tsx
index 073e4510c..a3399906a 100644
--- a/src/components/Dashboard/PersonalDashboard.tsx
+++ b/src/components/Dashboard/PersonalDashboard.tsx
@@ -47,7 +47,6 @@ export function PersonalDashboard(props: PersonalDashboardProps) {
builtInBestPractices = [],
builtInSkillRoadmaps = [],
} = props;
- const toast = useToast();
const [isLoading, setIsLoading] = useState(true);
const [personalDashboardDetails, setPersonalDashboardDetails] =
@@ -111,22 +110,37 @@ export function PersonalDashboard(props: PersonalDashboardProps) {
return updatedAtB.getTime() - updatedAtA.getTime();
});
- const { avatar, name, headline, email, username } =
- personalDashboardDetails || {};
+ const aiGeneratedRoadmaps = customRoadmaps.filter(
+ (progress) => progress?.aiRoadmapId,
+ );
+ const customRoadmapsToShow = customRoadmaps.filter(
+ (progress) => !progress?.aiRoadmapId,
+ );
+
+ const { avatar, name } = personalDashboardDetails || {};
const avatarLink = avatar
? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${avatar}`
: '/images/default-avatar.png';
const currentPeriod = getCurrentPeriod();
- const relatedRoadmapIds = [...builtInRoleRoadmaps, ...builtInSkillRoadmaps]
+ const allRoadmapsAndBestPractices = [
+ ...builtInRoleRoadmaps,
+ ...builtInSkillRoadmaps,
+ ...builtInBestPractices,
+ ];
+
+ const relatedRoadmapIds = allRoadmapsAndBestPractices
.filter((roadmap) =>
learningRoadmapsToShow?.some(
(learningRoadmap) => learningRoadmap.resourceId === roadmap.id,
),
)
.flatMap((roadmap) => roadmap.relatedRoadmapIds)
- .filter(Boolean);
+ .filter(
+ (roadmapId) =>
+ !learningRoadmapsToShow.some((lr) => lr.resourceId === roadmapId),
+ );
const recommendedRoadmapIds = new Set(
relatedRoadmapIds.length === 0
@@ -134,10 +148,9 @@ export function PersonalDashboard(props: PersonalDashboardProps) {
: relatedRoadmapIds,
);
- const recommendedRoadmaps = [
- ...builtInRoleRoadmaps,
- ...builtInSkillRoadmaps,
- ].filter((roadmap) => recommendedRoadmapIds.has(roadmap.id));
+ const recommendedRoadmaps = allRoadmapsAndBestPractices.filter((roadmap) =>
+ recommendedRoadmapIds.has(roadmap.id),
+ );
return (
@@ -149,47 +162,54 @@ export function PersonalDashboard(props: PersonalDashboardProps) {
)}
-
+
-
);
@@ -238,9 +258,15 @@ function DashboardCard(props: DashboardCardProps) {
-
{title}
+
{title}
{description}
);
}
+
+function DashboardCardSkeleton() {
+ return (
+
+ );
+}
diff --git a/src/components/Dashboard/RecommendedRoadmaps.tsx b/src/components/Dashboard/RecommendedRoadmaps.tsx
index 9b587ea73..1c18338e5 100644
--- a/src/components/Dashboard/RecommendedRoadmaps.tsx
+++ b/src/components/Dashboard/RecommendedRoadmaps.tsx
@@ -1,6 +1,5 @@
-import { useEffect, useState } from 'react';
import type { BuiltInRoadmap } from './PersonalDashboard';
-import { MarkFavorite } from '../FeaturedItems/MarkFavorite';
+import { ArrowUpRight } from 'lucide-react';
type RecommendedRoadmapsProps = {
roadmaps: BuiltInRoadmap[];
@@ -8,20 +7,7 @@ type RecommendedRoadmapsProps = {
};
export function RecommendedRoadmaps(props: RecommendedRoadmapsProps) {
- const { roadmaps, isLoading } = props;
-
- const [showAll, setShowAll] = useState(false);
- const roadmapsToShow = showAll ? roadmaps : roadmaps.slice(0, 12);
-
- const [isMounted, setIsMounted] = useState(false);
-
- useEffect(() => {
- setIsMounted(true);
- }, []);
-
- useEffect(() => {
- setShowAll(roadmaps.length < 12);
- }, [roadmaps]);
+ const { roadmaps: roadmapsToShow, isLoading } = props;
return (
<>
@@ -36,57 +22,39 @@ export function RecommendedRoadmaps(props: RecommendedRoadmapsProps) {
))}
) : (
-
-
- {roadmapsToShow.map((roadmap) => (
-
- ))}
-
-
- {!showAll && (
-
-
-
- )}
+
+ {roadmapsToShow.map((roadmap) => (
+
+ ))}
)}
>
);
}
+type RecommendedRoadmapCardProps = {
+ roadmap: BuiltInRoadmap;
+};
+
+export function RecommendedRoadmapCard(props: RecommendedRoadmapCardProps) {
+ const { roadmap } = props;
+ const { title, url, description } = roadmap;
+
+ return (
+
+ {title}
+ {description}
+
+
+
+ );
+}
+
function RecommendedCardSkeleton() {
return (
-
+
);
}
diff --git a/src/components/TeamProgress/TeamProgressPage.tsx b/src/components/TeamProgress/TeamProgressPage.tsx
index 6f386d55e..b0e39b660 100644
--- a/src/components/TeamProgress/TeamProgressPage.tsx
+++ b/src/components/TeamProgress/TeamProgressPage.tsx
@@ -23,6 +23,7 @@ export type UserProgress = {
updatedAt: string;
isCustomResource?: boolean;
roadmapSlug?: string;
+ aiRoadmapId?: string;
};
export type TeamMember = {
@@ -191,7 +192,7 @@ export function TeamProgressPage() {
key={grouping.value}
className={`rounded-md border p-1 px-2 text-sm ${
selectedGrouping === grouping.value
- ? ' border-gray-400 bg-gray-200 '
+ ? 'border-gray-400 bg-gray-200'
: ''
}`}
onClick={() => setSelectedGrouping(grouping.value)}