Update stack message

pull/7102/head
Kamran Ahmed 2 months ago
parent 298b137a7d
commit bbcd7e18e5
  1. 4
      src/components/Dashboard/DashboardBookmarkCard.tsx
  2. 32
      src/components/Dashboard/EmptyStackMessage.tsx
  3. 218
      src/components/Dashboard/ProgressStack.tsx

@ -27,9 +27,9 @@ export function DashboardBookmarkCard(props: DashboardBookmarkCardProps) {
<a <a
href={url} href={url}
key={resourceId} key={resourceId}
className="group relative flex w-full items-center gap-2 text-left text-sm hover:text-black hover:underline" className="group relative flex flex-row items-center gap-2 rounded-md border border-gray-300 bg-white px-1.5 py-2 text-left text-sm transition-all hover:border-gray-400"
> >
<Bookmark className="size-4 fill-current text-gray-400" /> <Bookmark className="size-4 fill-current text-gray-300" />
<h4 className="truncate font-medium text-gray-900">{resourceTitle}</h4> <h4 className="truncate font-medium text-gray-900">{resourceTitle}</h4>
</a> </a>
); );

@ -0,0 +1,32 @@
type EmptyStackMessageProps = {
number: number;
title: string;
description: string;
buttonText: string;
buttonLink: string;
};
export function EmptyStackMessage(props: EmptyStackMessageProps) {
const { number, title, description, buttonText, buttonLink } = props;
return (
<div className="absolute inset-0 flex items-center justify-center rounded-md bg-black/50">
<div className="flex max-w-[200px] flex-col items-center justify-center rounded-md bg-white p-4 shadow-sm">
<span className="flex h-8 w-8 items-center justify-center rounded-full bg-gray-300 text-white">
{number}
</span>
<div className="my-3 text-center">
<h3 className="text-sm font-medium text-black">{title}</h3>
<p className="text-center text-xs text-gray-500">{description}</p>
</div>
<a
href={buttonLink}
className="rounded-md bg-black px-3 py-1 text-xs text-white transition-transform hover:scale-105 hover:bg-gray-900"
>
{buttonText}
</a>
</div>
</div>
);
}

@ -14,6 +14,7 @@ import { cn } from '../../lib/classname';
import { DashboardProgressCard } from './DashboardProgressCard'; import { DashboardProgressCard } from './DashboardProgressCard';
import { useStore } from '@nanostores/react'; import { useStore } from '@nanostores/react';
import { $accountStreak, type StreakResponse } from '../../stores/streak'; import { $accountStreak, type StreakResponse } from '../../stores/streak';
import { EmptyStackMessage } from './EmptyStackMessage.tsx';
type ProgressStackProps = { type ProgressStackProps = {
progresses: UserProgress[]; progresses: UserProgress[];
@ -26,8 +27,8 @@ type ProgressStackProps = {
}; };
const MAX_PROGRESS_TO_SHOW = 5; const MAX_PROGRESS_TO_SHOW = 5;
const MAX_BOOKMARKS_TO_SHOW = 5;
const MAX_PROJECTS_TO_SHOW = 8; const MAX_PROJECTS_TO_SHOW = 8;
const MAX_BOOKMARKS_TO_SHOW = 8;
type ProgressLaneProps = { type ProgressLaneProps = {
title: string; title: string;
@ -74,7 +75,7 @@ function ProgressLane(props: ProgressLaneProps) {
{linkText && linkHref && ( {linkText && linkHref && (
<a <a
href={linkHref} href={linkHref}
className="flex items-center gap-1 text-xs text-gray-500" className="flex items-center gap-1 text-xs text-gray-500 hover:text-black"
> >
<ArrowUpRight size={12} /> <ArrowUpRight size={12} />
{linkText} {linkText}
@ -83,7 +84,7 @@ function ProgressLane(props: ProgressLaneProps) {
</div> </div>
)} )}
<div className="mt-4 flex flex-grow flex-col gap-2"> <div className="mt-4 flex flex-grow flex-col gap-1.5">
{isLoading && ( {isLoading && (
<> <>
{Array.from({ length: loadingSkeletonCount }).map((_, index) => ( {Array.from({ length: loadingSkeletonCount }).map((_, index) => (
@ -166,98 +167,139 @@ export function ProgressStack(props: ProgressStackProps) {
</div> </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">
<ProgressLane <div className="relative">
title={'Your Progress'} {!isLoading && bookmarksToShow.length === 0 && (
isLoading={isLoading} <EmptyStackMessage
loadingSkeletonCount={5} number={1}
isEmpty={userProgressesToShow.length === 0} title={'Bookmark Roadmaps'}
emptyMessage={'Update your Progress'} description={'Bookmark some roadmaps to access them quickly'}
emptyIcon={Map} buttonText={'Explore Roadmaps'}
emptyLinkText={'Explore Roadmaps'} buttonLink={'/roadmaps'}
>
{userProgressesToShow.length > 0 && (
<>
{userProgressesToShow.map((progress) => {
return (
<DashboardProgressCard
key={progress.resourceId}
progress={progress}
/>
);
})}
</>
)}
{userProgresses.length > MAX_PROGRESS_TO_SHOW && (
<ShowAllButton
showAll={showAllProgresses}
setShowAll={setShowAllProgresses}
count={userProgresses.length}
maxCount={MAX_PROGRESS_TO_SHOW}
className="mb-0.5 mt-3"
/> />
)} )}
</ProgressLane>
<ProgressLane <ProgressLane
title={'Projects'} title={'Bookmarks'}
isLoading={isLoading} isLoading={isLoading}
loadingSkeletonClassName={'h-5'} loadingSkeletonCount={5}
loadingSkeletonCount={8} linkHref={'/roadmaps'}
isEmpty={projectsToShow.length === 0} linkText={'Roadmaps'}
emptyMessage={'No projects started'} isEmpty={bookmarksToShow.length === 0}
emptyIcon={FolderKanban} emptyIcon={Bookmark}
emptyLinkText={'Explore Projects'} emptyMessage={'No bookmarks to show'}
emptyLinkHref={'/projects'} emptyLinkHref={'/roadmaps'}
> emptyLinkText={'Explore Roadmaps'}
{projectsToShow.map((project) => { >
return ( {bookmarksToShow.map((progress) => {
<DashboardProjectCard key={project.projectId} project={project} /> return (
); <DashboardBookmarkCard
})} key={progress.resourceId}
bookmark={progress}
{projects.length > MAX_PROJECTS_TO_SHOW && ( />
<ShowAllButton );
showAll={showAllProjects} })}
setShowAll={setShowAllProjects} {bookmarkedProgresses.length > MAX_BOOKMARKS_TO_SHOW && (
count={projects.length} <ShowAllButton
maxCount={MAX_PROJECTS_TO_SHOW} showAll={showAllBookmarks}
className="mb-0.5 mt-3" setShowAll={setShowAllBookmarks}
count={bookmarkedProgresses.length}
maxCount={MAX_BOOKMARKS_TO_SHOW}
className="mb-0.5 mt-3"
/>
)}
</ProgressLane>
</div>
<div className="relative">
{!isLoading && userProgressesToShow.length === 0 && (
<EmptyStackMessage
number={2}
title={'Track Progress'}
description={'Pick your first roadmap and start learning'}
buttonText={'Explore roadmaps'}
buttonLink={'/roadmaps'}
/> />
)} )}
</ProgressLane> <ProgressLane
title={'Progress'}
linkHref={'/roadmaps'}
linkText={'Roadmaps'}
isLoading={isLoading}
loadingSkeletonCount={5}
isEmpty={userProgressesToShow.length === 0}
emptyMessage={'Update your Progress'}
emptyIcon={Map}
emptyLinkText={'Explore Roadmaps'}
>
{userProgressesToShow.length > 0 && (
<>
{userProgressesToShow.map((progress) => {
return (
<DashboardProgressCard
key={progress.resourceId}
progress={progress}
/>
);
})}
</>
)}
<ProgressLane {userProgresses.length > MAX_PROGRESS_TO_SHOW && (
title={'Bookmarks'} <ShowAllButton
isLoading={isLoading} showAll={showAllProgresses}
loadingSkeletonClassName={'h-5'} setShowAll={setShowAllProgresses}
loadingSkeletonCount={8} count={userProgresses.length}
linkHref={'/roadmaps'} maxCount={MAX_PROGRESS_TO_SHOW}
linkText={'Explore'} className="mb-0.5 mt-3"
isEmpty={bookmarksToShow.length === 0}
emptyIcon={Bookmark}
emptyMessage={'No bookmarks to show'}
emptyLinkHref={'/roadmaps'}
emptyLinkText={'Explore Roadmaps'}
>
{bookmarksToShow.map((progress) => {
return (
<DashboardBookmarkCard
key={progress.resourceId}
bookmark={progress}
/> />
); )}
})} </ProgressLane>
{bookmarkedProgresses.length > MAX_BOOKMARKS_TO_SHOW && ( </div>
<ShowAllButton
showAll={showAllBookmarks} <div className="relative">
setShowAll={setShowAllBookmarks} <ProgressLane
count={bookmarkedProgresses.length} title={'Projects'}
maxCount={MAX_BOOKMARKS_TO_SHOW} linkHref={'/projects'}
className="mb-0.5 mt-3" linkText={'Projects'}
/> isLoading={isLoading}
)} loadingSkeletonClassName={'h-5'}
</ProgressLane> loadingSkeletonCount={8}
isEmpty={projectsToShow.length === 0}
emptyMessage={'No projects started'}
emptyIcon={FolderKanban}
emptyLinkText={'Explore Projects'}
emptyLinkHref={'/projects'}
>
{!isLoading && projectsToShow.length === 0 && (
<EmptyStackMessage
number={3}
title={'Build your first project'}
description={'Pick a project to practice and start building'}
buttonText={'Explore Projects'}
buttonLink={'/projects'}
/>
)}
{projectsToShow.map((project) => {
return (
<DashboardProjectCard
key={project.projectId}
project={project}
/>
);
})}
{projects.length > MAX_PROJECTS_TO_SHOW && (
<ShowAllButton
showAll={showAllProjects}
setShowAll={setShowAllProjects}
count={projects.length}
maxCount={MAX_PROJECTS_TO_SHOW}
className="mb-0.5 mt-3"
/>
)}
</ProgressLane>
</div>
</div> </div>
</> </>
); );

Loading…
Cancel
Save