diff --git a/app/projects/page.tsx b/app/projects/page.tsx index cb97766..1543d84 100644 --- a/app/projects/page.tsx +++ b/app/projects/page.tsx @@ -35,8 +35,12 @@ const ProjectPage: React.FC = () => { const { theme } = useTheme(); const [projects, setProjects] = useState([]); const [loading, setLoading] = useState(true); + const [error, setError] = useState(false); useEffect(() => { + setLoading(true); + setError(false); + const fetchProjects = async () => { try { const res = await fetch("/api/projects-with-members"); @@ -45,25 +49,103 @@ const ProjectPage: React.FC = () => { setProjects(data.data as Project[]); } else { console.error("Error loading project data"); + throw new Error("Network response was not ok"); } - } catch (err) { - console.error("Error fetching projects:", err); - } finally{ setTimeout(() => { setLoading(false); }, 500); + } catch (err) { + console.error("Error fetching projects:", err); + setError(true); + setLoading(false); } }; fetchProjects(); }, []); + const renderProjects = () => { + if (loading) { + return ( + + {Array.from({ length: 6 }).map((_, i) => ( + + ))} + + ); + } + + if (error) { + return ( +
+
+ + + + {/* purple-500 */} + {/* pink-500 */} + + + + + + +

+ Failed to fetch projects +

+
+
+ ); + } + + if (projects.length === 0) { + return ( +
+

+ No projects found +

+
+ ); + } + + return ( + + {projects.map((project, i) => ( + } + github={project.githubUrl} + live={project.deployUrl} + tooltipItems={project.members?.map((member) => ({ + id: member.id, + name: member.name, + image: member.image || "/default-avatar.png", + }))} + className={i === 3 || i === 6 ? "md:col-span-2" : ""} + /> + ))} + + ); + }; + + return (
{
- {/* Loading State */} - {loading && ( - - {Array.from({ length: 6 }).map((_, i) => ( - - ))} - - )} - - {/* Empty State */} - {!loading && projects.length === 0 && ( -
-
- - - - {/* purple-500 */} - {/* pink-500 */} - - - - - - -

- Failed to fetch projects -

-
-
- )} - - {/* Projects Grid */} - {!loading && projects.length > 0 && ( - - {projects.map((project, i) => ( - - } - github={project.githubUrl} - live={project.deployUrl} - tooltipItems={project.members?.map((member) => ({ - id: member.id, - name: member.name, - image: member.image || "/default-avatar.png", - }))} - className={i === 3 || i === 6 ? "md:col-span-2" : ""} - /> - ))} - - )} + {renderProjects()} +
diff --git a/components/Members-Text.tsx b/components/Members-Text.tsx index 4e138d3..46dffc0 100644 --- a/components/Members-Text.tsx +++ b/components/Members-Text.tsx @@ -120,6 +120,15 @@ export default function MembersPage() { const [founders, setFounders] = useState([]); const [loading, setLoading] = useState(true); const [tabLoading, setTabLoading] = useState(false); + const [tabError, setTabError] = useState<{ + present: boolean; + seniors: boolean; + founders: boolean; + }>({ + present: false, + seniors: false, + founders: false, + }); const handleTabChange = (idx: number) => { @@ -149,6 +158,12 @@ export default function MembersPage() { useEffect(() => { const abortController = new AbortController(); + setLoading(true); + setTabError({ + present: false, + seniors: false, + founders: false, + }); const fetchMembers = async () => { try { @@ -170,6 +185,7 @@ export default function MembersPage() { setFounders([]); setSuperSeniors([]); setPresentMembers([]); + setLoading(false); return; } @@ -199,16 +215,21 @@ export default function MembersPage() { setFounders(foundersList); setSuperSeniors(superSeniorsList); setPresentMembers(presentList); + setTimeout(() => { + setLoading(false); + }, 500); } catch (err) { if (err instanceof Error && err.name === "AbortError") { return; } console.error("Failed to fetch members", err); - } finally{ - setTimeout(() => { - setLoading(false); - }, 1000); - } + setTabError({ + present: true, + seniors: true, + founders: true, + }); + setLoading(false); + } }; fetchMembers(); @@ -249,41 +270,47 @@ export default function MembersPage() { ); + const TAB_LABELS = { + present: "Present Members", + seniors: "Super Seniors", + founders: "Founders", + } as const; + + const renderMembersTab = (members: DisplayMember[], tab: "present" | "seniors" | "founders", isFounder = false) => { + if (loading || tabLoading) { + return ; + } + + if (tabError[tab]) { + return ( + + ); + } + + if (members.length === 0) { + return ; + } + + return ; + }; + const tabs = [ - { - title: "Present Members", - value: "present", - content: loading || tabLoading ? ( - - ) : presentMembers.length === 0 ? ( - - ) : ( - - ), - }, - { - title: "Super Seniors", - value: "seniors", - content: loading || tabLoading ? ( - - ) : superSeniors.length === 0 ? ( - - ) : ( - - ), - }, - { - title: "Founders", - value: "founders", - content: loading || tabLoading ? ( - - ) : founders.length === 0 ? ( - - ) : ( - - ), - }, + { + title: "Present Members", + value: "present", + content: renderMembersTab(presentMembers, "present"), + }, + { + title: "Super Seniors", + value: "seniors", + content: renderMembersTab(superSeniors, "seniors"), + }, + { + title: "Founders", + value: "founders", + content: renderMembersTab(founders, "founders", true), + }, ];