|
|
@ -1,27 +1,20 @@ |
|
|
|
import { |
|
|
|
import { ArrowUpRight } from 'lucide-react'; |
|
|
|
ArrowUpRight, |
|
|
|
|
|
|
|
Bookmark, |
|
|
|
|
|
|
|
Check, |
|
|
|
|
|
|
|
CheckCircle, |
|
|
|
|
|
|
|
CheckIcon, |
|
|
|
|
|
|
|
CircleCheck, |
|
|
|
|
|
|
|
CircleDashed, |
|
|
|
|
|
|
|
} from 'lucide-react'; |
|
|
|
|
|
|
|
import { ResourceProgress } from '../Activity/ResourceProgress'; |
|
|
|
|
|
|
|
import type { UserProgress } from '../TeamProgress/TeamProgressPage'; |
|
|
|
import type { UserProgress } from '../TeamProgress/TeamProgressPage'; |
|
|
|
import { getPercentage } from '../../helper/number'; |
|
|
|
|
|
|
|
import type { ProjectStatusDocument } from '../Projects/ListProjectSolutions'; |
|
|
|
import type { ProjectStatusDocument } from '../Projects/ListProjectSolutions'; |
|
|
|
import { DashboardBookmarkCard } from './DashboardBookmarkCard'; |
|
|
|
import { DashboardBookmarkCard } from './DashboardBookmarkCard'; |
|
|
|
import { DashboardProjectCard } from './DashboardProjectCard'; |
|
|
|
import { DashboardProjectCard } from './DashboardProjectCard'; |
|
|
|
import { useState } from 'react'; |
|
|
|
import { useState } from 'react'; |
|
|
|
import { cn } from '../../lib/classname'; |
|
|
|
import { cn } from '../../lib/classname'; |
|
|
|
import { DashboardProgressCard } from './DashboardProgressCard'; |
|
|
|
import { DashboardProgressCard } from './DashboardProgressCard'; |
|
|
|
|
|
|
|
import { useStore } from '@nanostores/react'; |
|
|
|
|
|
|
|
import { $accountStreak, type StreakResponse } from '../../stores/streak'; |
|
|
|
|
|
|
|
|
|
|
|
type ProgressStackProps = { |
|
|
|
type ProgressStackProps = { |
|
|
|
progresses: UserProgress[]; |
|
|
|
progresses: UserProgress[]; |
|
|
|
projects: (ProjectStatusDocument & { |
|
|
|
projects: (ProjectStatusDocument & { |
|
|
|
title: string; |
|
|
|
title: string; |
|
|
|
})[]; |
|
|
|
})[]; |
|
|
|
|
|
|
|
accountStreak?: StreakResponse; |
|
|
|
isLoading: boolean; |
|
|
|
isLoading: boolean; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@ -30,7 +23,7 @@ const MAX_PROJECTS_TO_SHOW = 8; |
|
|
|
const MAX_BOOKMARKS_TO_SHOW = 8; |
|
|
|
const MAX_BOOKMARKS_TO_SHOW = 8; |
|
|
|
|
|
|
|
|
|
|
|
export function ProgressStack(props: ProgressStackProps) { |
|
|
|
export function ProgressStack(props: ProgressStackProps) { |
|
|
|
const { progresses, projects, isLoading } = props; |
|
|
|
const { progresses, projects, isLoading, accountStreak } = props; |
|
|
|
|
|
|
|
|
|
|
|
const bookmarkedProgresses = progresses.filter( |
|
|
|
const bookmarkedProgresses = progresses.filter( |
|
|
|
(progress) => |
|
|
|
(progress) => |
|
|
@ -57,7 +50,25 @@ export function ProgressStack(props: ProgressStackProps) { |
|
|
|
? bookmarkedProgresses |
|
|
|
? bookmarkedProgresses |
|
|
|
: bookmarkedProgresses.slice(0, MAX_BOOKMARKS_TO_SHOW); |
|
|
|
: bookmarkedProgresses.slice(0, MAX_BOOKMARKS_TO_SHOW); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const totalProjectFinished = projects.filter( |
|
|
|
|
|
|
|
(project) => project.repositoryUrl, |
|
|
|
|
|
|
|
).length; |
|
|
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
return ( |
|
|
|
|
|
|
|
<> |
|
|
|
|
|
|
|
<div className="mt-2 grid grid-cols-1 gap-2 sm:grid-cols-2 md:grid-cols-3"> |
|
|
|
|
|
|
|
<StatsCard |
|
|
|
|
|
|
|
title="Current Streak" |
|
|
|
|
|
|
|
value={accountStreak?.count || 0} |
|
|
|
|
|
|
|
isLoading={isLoading} |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
<StatsCard |
|
|
|
|
|
|
|
title="Projects Finished" |
|
|
|
|
|
|
|
value={totalProjectFinished} |
|
|
|
|
|
|
|
isLoading={isLoading} |
|
|
|
|
|
|
|
/> |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<div className="mt-2 grid min-h-[330px] grid-cols-1 gap-2 sm:grid-cols-2 md:grid-cols-3"> |
|
|
|
<div className="mt-2 grid min-h-[330px] grid-cols-1 gap-2 sm:grid-cols-2 md:grid-cols-3"> |
|
|
|
<div className="h-full rounded-md border bg-white p-4 shadow-sm"> |
|
|
|
<div className="h-full rounded-md border bg-white p-4 shadow-sm"> |
|
|
|
<h3 className="text-xs uppercase text-gray-500">Your Progress</h3> |
|
|
|
<h3 className="text-xs uppercase text-gray-500">Your Progress</h3> |
|
|
@ -186,6 +197,7 @@ export function ProgressStack(props: ProgressStackProps) { |
|
|
|
)} |
|
|
|
)} |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
|
|
|
|
</> |
|
|
|
); |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -229,3 +241,24 @@ function CardSkeleton(props: CardSkeletonProps) { |
|
|
|
/> |
|
|
|
/> |
|
|
|
); |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type StatsCardProps = { |
|
|
|
|
|
|
|
title: string; |
|
|
|
|
|
|
|
value: number; |
|
|
|
|
|
|
|
isLoading?: boolean; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function StatsCard(props: StatsCardProps) { |
|
|
|
|
|
|
|
const { title, value, isLoading = false } = props; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
|
|
|
<div className="flex flex-col gap-1 rounded-md border bg-white p-4 shadow-sm"> |
|
|
|
|
|
|
|
<h3 className="text-xs uppercase text-gray-500">{title}</h3> |
|
|
|
|
|
|
|
{isLoading ? ( |
|
|
|
|
|
|
|
<CardSkeleton className="h-8" /> |
|
|
|
|
|
|
|
) : ( |
|
|
|
|
|
|
|
<span className="text-2xl font-medium text-black">{value}</span> |
|
|
|
|
|
|
|
)} |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
} |
|
|
|