diff --git a/.astro/settings.json b/.astro/settings.json index 76d2425cb..17407a348 100644 --- a/.astro/settings.json +++ b/.astro/settings.json @@ -3,6 +3,6 @@ "enabled": false }, "_variables": { - "lastUpdateCheck": 1723855511353 + "lastUpdateCheck": 1724902244772 } } \ No newline at end of file diff --git a/src/components/Dashboard/DashboardPage.tsx b/src/components/Dashboard/DashboardPage.tsx new file mode 100644 index 000000000..d9ebaf2e6 --- /dev/null +++ b/src/components/Dashboard/DashboardPage.tsx @@ -0,0 +1,68 @@ +import { useEffect, useState, type ReactNode } from 'react'; +import { httpGet } from '../../lib/http'; +import type { UserProgress } from '../TeamProgress/TeamProgressPage'; +import { useToast } from '../../hooks/use-toast'; +import { useStore } from '@nanostores/react'; +import { $teamList } from '../../stores/team'; +import type { TeamListResponse } from '../TeamDropdown/TeamDropdown'; +import { cn } from '../../lib/classname'; +import { DashboardTab } from './DashboardTab'; +import { PersonalDashboard } from './PersonalDashboard'; + +type DashboardPageProps = {}; + +export function DashboardPage(props: DashboardPageProps) { + const toast = useToast(); + const teamList = useStore($teamList); + + const [isLoading, setIsLoading] = useState(true); + const [selectedTeamId, setSelectedTeamId] = useState(); + + async function getAllTeams() { + if (teamList.length > 0) { + return; + } + + const { response, error } = await httpGet( + `${import.meta.env.PUBLIC_API_URL}/v1-get-user-teams`, + ); + if (error || !response) { + toast.error(error?.message || 'Something went wrong'); + return; + } + + $teamList.set(response); + } + + useEffect(() => { + getAllTeams().finally(() => setIsLoading(false)); + }, []); + + return ( +
+
+ setSelectedTeamId(undefined)} + /> + {teamList.map((team) => ( + setSelectedTeamId(team._id)} + /> + ))} + +
+ + {!selectedTeamId && } +
+ ); +} diff --git a/src/components/Dashboard/DashboardTab.tsx b/src/components/Dashboard/DashboardTab.tsx new file mode 100644 index 000000000..96204e264 --- /dev/null +++ b/src/components/Dashboard/DashboardTab.tsx @@ -0,0 +1,30 @@ +import type { ReactNode } from 'react'; +import { cn } from '../../lib/classname'; + +type DashboardTabProps = { + label: string | ReactNode; + isActive: boolean; + onClick?: () => void; + className?: string; + href?: string; +}; + +export function DashboardTab(props: DashboardTabProps) { + const { isActive, onClick, label, className, href } = props; + + const Slot = href ? 'a' : 'button'; + + return ( + + {label} + + ); +} diff --git a/src/components/Dashboard/PersonalDashboard.tsx b/src/components/Dashboard/PersonalDashboard.tsx new file mode 100644 index 000000000..81faffcba --- /dev/null +++ b/src/components/Dashboard/PersonalDashboard.tsx @@ -0,0 +1,91 @@ +import { useEffect, useState } from 'react'; +import { httpGet } from '../../lib/http'; +import type { UserProgress } from '../TeamProgress/TeamProgressPage'; +import type { ProjectStatusDocument } from '../Projects/ListProjectSolutions'; +import { ResourceProgress } from '../Activity/ResourceProgress'; + +type UserDashboardResponse = { + progresses: UserProgress[]; + projects: ProjectStatusDocument[]; +}; + +type PersonalDashboardProps = {}; + +export function PersonalDashboard(props: PersonalDashboardProps) { + const [isLoading, setIsLoading] = useState(true); + const [personalDashboardDetails, setPersonalDashboardDetails] = + useState(); + + async function loadProgress() { + setIsLoading(true); + + const { response: progressList, error } = + await httpGet( + `${import.meta.env.PUBLIC_API_URL}/v1-user-dashboard`, + ); + + if (error || !progressList) { + return; + } + + setPersonalDashboardDetails(progressList); + } + + useEffect(() => { + loadProgress().finally(() => setIsLoading(false)); + }, []); + + const learningRoadmaps = + personalDashboardDetails?.progresses?.filter( + (progress) => progress.resourceType === 'roadmap', + ) || []; + + const learningRoadmapsToShow = learningRoadmaps.sort((a, b) => { + const updatedAtA = new Date(a.updatedAt); + const updatedAtB = new Date(b.updatedAt); + + if (a.isFavorite && !b.isFavorite) { + return -1; + } + + if (!a.isFavorite && b.isFavorite) { + return 1; + } + + return updatedAtB.getTime() - updatedAtA.getTime(); + }); + + return ( +
+

+ Progress and Bookmarks +

+
+ {learningRoadmapsToShow.map((roadmap) => { + const learningCount = roadmap.learning || 0; + const doneCount = roadmap.done || 0; + const totalCount = roadmap.total || 0; + const skippedCount = roadmap.skipped || 0; + + return ( + totalCount ? totalCount : doneCount} + learningCount={ + learningCount > totalCount ? totalCount : learningCount + } + totalCount={totalCount} + skippedCount={skippedCount} + resourceId={roadmap.resourceId} + resourceType="roadmap" + updatedAt={roadmap.updatedAt} + title={roadmap.resourceTitle} + showActions={false} + /> + ); + })} +
+
+ ); +} diff --git a/src/pages/dashboard.astro b/src/pages/dashboard.astro new file mode 100644 index 000000000..dc0b43887 --- /dev/null +++ b/src/pages/dashboard.astro @@ -0,0 +1,8 @@ +--- +import { DashboardPage } from '../components/Dashboard/DashboardPage'; +import BaseLayout from '../layouts/BaseLayout.astro'; +--- + + + +