setSelectedTeamId(undefined)}
+ avatar={userAvatar}
/>
{isLoading && (
<>
@@ -55,14 +67,21 @@ export function DashboardPage(props: DashboardPageProps) {
{!isLoading && (
<>
- {teamList.map((team) => (
- setSelectedTeamId(team._id)}
- />
- ))}
+ {teamList.map((team) => {
+ const { avatar } = team;
+ const avatarUrl = avatar
+ ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${avatar}`
+ : '/images/default-avatar.png';
+ return (
+ setSelectedTeamId(team._id)}
+ avatar={avatarUrl}
+ />
+ );
+ })}
- {!selectedTeamId && }
+ {!selectedTeamId && (
+
+ )}
{selectedTeamId && }
);
@@ -81,6 +105,6 @@ export function DashboardPage(props: DashboardPageProps) {
function DashboardTabLoading() {
return (
-
+
);
}
diff --git a/src/components/Dashboard/DashboardTab.tsx b/src/components/Dashboard/DashboardTab.tsx
index 96204e264..0895fe107 100644
--- a/src/components/Dashboard/DashboardTab.tsx
+++ b/src/components/Dashboard/DashboardTab.tsx
@@ -7,10 +7,12 @@ type DashboardTabProps = {
onClick?: () => void;
className?: string;
href?: string;
+ avatar?: string;
+ icon?: ReactNode;
};
export function DashboardTab(props: DashboardTabProps) {
- const { isActive, onClick, label, className, href } = props;
+ const { isActive, onClick, label, className, href, avatar, icon } = props;
const Slot = href ? 'a' : 'button';
@@ -18,12 +20,20 @@ export function DashboardTab(props: DashboardTabProps) {
+ {avatar && (
+
+ )}
+ {icon}
{label}
);
diff --git a/src/components/Dashboard/PersonalDashboard.tsx b/src/components/Dashboard/PersonalDashboard.tsx
index f8f100aa6..e03cf8ee7 100644
--- a/src/components/Dashboard/PersonalDashboard.tsx
+++ b/src/components/Dashboard/PersonalDashboard.tsx
@@ -7,15 +7,31 @@ import { ProjectProgress } from '../Activity/ProjectProgress';
import type { PageType } from '../CommandMenu/CommandMenu';
import { useToast } from '../../hooks/use-toast';
import { LoadingProgress } from './LoadingProgress';
+import { ArrowUpRight, Pencil } from 'lucide-react';
type UserDashboardResponse = {
+ name: string;
+ email: string;
+ avatar: string;
+ headline: string;
+ username: string;
progresses: UserProgress[];
projects: ProjectStatusDocument[];
};
-type PersonalDashboardProps = {};
+export type BuiltInRoadmap = {
+ id: string;
+ title: string;
+ description: string;
+};
+
+type PersonalDashboardProps = {
+ builtInRoadmaps?: BuiltInRoadmap[];
+ builtInBestPractices?: BuiltInRoadmap[];
+};
export function PersonalDashboard(props: PersonalDashboardProps) {
+ const { builtInRoadmaps = [], builtInBestPractices = [] } = props;
const toast = useToast();
const [isLoading, setIsLoading] = useState(true);
@@ -79,19 +95,81 @@ export function PersonalDashboard(props: PersonalDashboardProps) {
});
const enrichedProjects =
- personalDashboardDetails?.projects?.map((project) => {
- const projectDetail = projectDetails.find(
- (page) => page.id === project.projectId,
- );
+ personalDashboardDetails?.projects
+ ?.map((project) => {
+ const projectDetail = projectDetails.find(
+ (page) => page.id === project.projectId,
+ );
+
+ return {
+ ...project,
+ title: projectDetail?.title || 'N/A',
+ };
+ })
+ ?.sort((a, b) => {
+ const isPendingA = !a.repositoryUrl && !a.submittedAt;
+ const isPendingB = !b.repositoryUrl && !b.submittedAt;
+
+ if (isPendingA && !isPendingB) {
+ return -1;
+ }
+
+ if (!isPendingA && isPendingB) {
+ return 1;
+ }
- return {
- ...project,
- title: projectDetail?.title || 'N/A',
- };
- }) || [];
+ return 0;
+ }) || [];
+
+ const { avatar, name, headline, email, username } =
+ personalDashboardDetails || {};
+ const avatarLink = avatar
+ ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${avatar}`
+ : '/images/default-avatar.png';
return (
+ {isLoading && (
+
+ )}
+ {!isLoading && (
+
+
+
+
+
{name}
+
{headline || email}
+
+
+
+
+
+ )}
+
Progress and Bookmarks
@@ -141,6 +219,59 @@ export function PersonalDashboard(props: PersonalDashboardProps) {
})}
);
}
+
+type ListRoadmapsProps = {
+ roadmaps: BuiltInRoadmap[];
+};
+export function ListRoadmaps(props: ListRoadmapsProps) {
+ const { roadmaps } = props;
+
+ const [showAll, setShowAll] = useState(roadmaps.length <= 12);
+ const roadmapsToShow = showAll ? roadmaps : roadmaps.slice(0, 12);
+
+ return (
+
+ );
+}
diff --git a/src/components/Dashboard/TeamDashboard.tsx b/src/components/Dashboard/TeamDashboard.tsx
index 4c36c51e9..1f9e617b8 100644
--- a/src/components/Dashboard/TeamDashboard.tsx
+++ b/src/components/Dashboard/TeamDashboard.tsx
@@ -5,7 +5,6 @@ import { useToast } from '../../hooks/use-toast';
import { getUser } from '../../lib/jwt';
import { LoadingProgress } from './LoadingProgress';
import { ResourceProgress } from '../Activity/ResourceProgress';
-import { Plus, Minus } from 'lucide-react';
import { TeamActivityPage } from '../TeamActivity/TeamActivityPage';
import { cn } from '../../lib/classname';
@@ -21,7 +20,6 @@ export function TeamDashboard(props: TeamDashboardProps) {
const [isLoading, setIsLoading] = useState(true);
const [teamMembers, setTeamMembers] = useState