diff --git a/src/components/Dashboard/PersonalDashboard.tsx b/src/components/Dashboard/PersonalDashboard.tsx index 705df46ae..fb4c65b44 100644 --- a/src/components/Dashboard/PersonalDashboard.tsx +++ b/src/components/Dashboard/PersonalDashboard.tsx @@ -59,8 +59,6 @@ type DashboardStatsProps = { topicsDoneToday?: number; finishedProjectsCount?: number; isLoading: boolean; - isAllCollapsed: boolean; - onToggleCollapseAll: () => void; }; type DashboardStatItemProps = { @@ -101,8 +99,6 @@ function DashboardStats(props: DashboardStatsProps) { topicsDoneToday = 0, finishedProjectsCount = 0, isLoading, - onToggleCollapseAll, - isAllCollapsed, } = props; return ( @@ -130,23 +126,6 @@ function DashboardStats(props: DashboardStatsProps) { isLoading={isLoading} /> */} </div> - - <button - className="flex items-center gap-1 rounded-lg border border-transparent py-1.5 pl-3 pr-3 text-xs uppercase tracking-wide text-slate-400 hover:border-slate-800 hover:bg-slate-800" - onClick={onToggleCollapseAll} - > - {isAllCollapsed ? ( - <> - <ChevronsUpDown className="size-3" /> - <span>Expand All</span> - </> - ) : ( - <> - <ChevronsDownUp className="size-3" /> - <span>Collapse All</span> - </> - )} - </button> </div> ); } @@ -161,7 +140,6 @@ export function PersonalDashboard(props: PersonalDashboardProps) { const toast = useToast(); const [isLoading, setIsLoading] = useState(true); - const [isAllCollapsed, setIsAllCollapsed] = useState(false); const [personalDashboardDetails, setPersonalDashboardDetails] = useState<UserDashboardResponse>(); const [projectDetails, setProjectDetails] = useState<PageType[]>([]); @@ -305,10 +283,6 @@ export function PersonalDashboard(props: PersonalDashboardProps) { isLoading={isLoading} accountStreak={accountStreak} topicsDoneToday={personalDashboardDetails?.topicDoneToday} - onToggleCollapseAll={() => { - setIsAllCollapsed(!isAllCollapsed); - }} - isAllCollapsed={isAllCollapsed} finishedProjectsCount={ enrichedProjects?.filter((p) => p.submittedAt && p.repositoryUrl) .length @@ -321,7 +295,6 @@ export function PersonalDashboard(props: PersonalDashboardProps) { aiRoadmaps={aiGeneratedRoadmaps} projects={enrichedProjects || []} isLoading={isLoading} - isAllCollapsed={isAllCollapsed} /> <div className="relative mt-6 border-t border-t-[#1e293c] pt-12"> diff --git a/src/components/HeroSection/FavoriteRoadmaps.tsx b/src/components/HeroSection/FavoriteRoadmaps.tsx index 5b00d21e1..91563ef79 100644 --- a/src/components/HeroSection/FavoriteRoadmaps.tsx +++ b/src/components/HeroSection/FavoriteRoadmaps.tsx @@ -29,18 +29,10 @@ type FavoriteRoadmapsProps = { customRoadmaps: UserProgress[]; aiRoadmaps: AIRoadmapType[]; isLoading: boolean; - isAllCollapsed: boolean; }; export function FavoriteRoadmaps(props: FavoriteRoadmapsProps) { - const { - progress, - isLoading, - customRoadmaps, - aiRoadmaps, - projects, - isAllCollapsed, - } = props; + const { progress, isLoading, customRoadmaps, aiRoadmaps, projects } = props; const [showCompleted, setShowCompleted] = useState(false); const completedProjects = projects.filter( @@ -61,7 +53,6 @@ export function FavoriteRoadmaps(props: FavoriteRoadmapsProps) { icon={<CheckIcon additionalClasses="mr-1.5 h-[14px] w-[14px]" />} isLoading={isLoading} title="Your progress and bookmarks" - isAllCollapsed={isAllCollapsed} > {progress.map((resource) => ( <HeroRoadmap @@ -87,7 +78,6 @@ export function FavoriteRoadmaps(props: FavoriteRoadmapsProps) { icon={<MapIcon className="mr-1.5 h-[14px] w-[14px]" />} isLoading={isLoading} title="Your custom roadmaps" - isAllCollapsed={isAllCollapsed} > {customRoadmaps.map((customRoadmap) => ( <HeroRoadmap @@ -111,7 +101,6 @@ export function FavoriteRoadmaps(props: FavoriteRoadmapsProps) { icon={<Sparkle className="mr-1.5 h-[14px] w-[14px]" />} isLoading={isLoading} title="Your AI roadmaps" - isAllCollapsed={isAllCollapsed} > {aiRoadmaps.map((aiRoadmap) => ( <HeroRoadmap @@ -141,7 +130,6 @@ export function FavoriteRoadmaps(props: FavoriteRoadmapsProps) { icon={<FolderKanban className="mr-1.5 h-[14px] w-[14px]" />} isLoading={isLoading} title="Your active projects" - isAllCollapsed={isAllCollapsed} rightContent={ completedProjects.length > 0 && ( <button diff --git a/src/components/HeroSection/HeroItemsGroup.tsx b/src/components/HeroSection/HeroItemsGroup.tsx index 13c7dc4d8..fdab0bb1b 100644 --- a/src/components/HeroSection/HeroItemsGroup.tsx +++ b/src/components/HeroSection/HeroItemsGroup.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState, type ReactNode } from 'react'; +import { useEffect, useRef, useState, type ReactNode } from 'react'; import { cn } from '../../lib/classname'; import { HeroTitle } from './HeroTitle'; @@ -7,7 +7,6 @@ type HeroItemsGroupProps = { isLoading?: boolean; title: string | ReactNode; rightContent?: ReactNode; - isAllCollapsed?: boolean; children?: ReactNode; className?: string; }; @@ -18,24 +17,34 @@ export function HeroItemsGroup(props: HeroItemsGroupProps) { isLoading = false, title, rightContent, - isAllCollapsed = false, children, className, } = props; - const [isCollapsed, setIsCollapsed] = useState(isLoading || isAllCollapsed); + const isInitialRender = useRef(true); + + const storageKey = `hero-group-${title}-collapsed`; + const [isCollapsed, setIsCollapsed] = useState(true); + + function isCollapsedByStorage() { + const stored = localStorage.getItem(storageKey); + + return stored === 'true'; + } useEffect(() => { - setIsCollapsed(isAllCollapsed || isLoading); - }, [isAllCollapsed, isLoading]); + setIsCollapsed(isCollapsedByStorage()); + }, [isLoading]); + + const isLoadingOrCollapsed = isLoading || isCollapsed; return ( <div className={cn( 'border-b border-gray-800/50', { - 'py-4': !isCollapsed, - 'py-3': isCollapsed, + 'py-4': !isLoadingOrCollapsed, + 'py-3': isLoadingOrCollapsed, 'opacity-50 transition-opacity hover:opacity-100': isCollapsed && !isLoading, }, @@ -51,9 +60,10 @@ export function HeroItemsGroup(props: HeroItemsGroupProps) { isCollapsed={isCollapsed} onToggleCollapse={() => { setIsCollapsed(!isCollapsed); + localStorage.setItem(storageKey, (!isCollapsed).toString()); }} /> - {!isCollapsed && ( + {!isLoadingOrCollapsed && ( <div className="mt-4 grid grid-cols-1 gap-2.5 sm:grid-cols-2 md:grid-cols-3"> {children} </div>