Skip to content

Commit 0536d39

Browse files
committed
done codebility admins
1 parent f39e404 commit 0536d39

5 files changed

Lines changed: 198 additions & 132 deletions

File tree

‎.gitignore‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,4 @@ distapps/bot/.env
9191
.env
9292
apps/codebility/public/assets/onboardingvideos/*.mp4
9393
.planning/
94+
.cursor/

‎apps/codebility/app/(marketing)/_components/landing/LandingIntern-CodevPagination.tsx‎

Lines changed: 39 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,3 @@
1-
// components/landing/LandingIntern-CodevPagination.tsx
2-
//
3-
// This component displays a paginated list of team members (Interns and Codevs)
4-
// with prioritization applied using the prioritizeCodevs utility function.
5-
// Team members are automatically sorted by:
6-
// 1. Total codev points (highest first)
7-
// 2. Level 2+ badges (prioritized)
8-
// 3. Number of valid badges
9-
// 4. Has profile image
10-
// 5. Has work experience
11-
// 6. Years of experience
12-
131
"use client";
142

153
import { useState, useEffect } from "react";
@@ -41,7 +29,7 @@ type TeamMember = {
4129
};
4230

4331
interface TeamMembersApiResponse {
44-
TEAM_MEMBERS: { // Changed from INTERNS to TEAM_MEMBERS to match new API
32+
TEAM_MEMBERS: {
4533
id: string;
4634
name: string;
4735
role: string;
@@ -67,136 +55,62 @@ const TEAM_ROLES = {
6755
CODEV: 'Codev' as const,
6856
} as const;
6957

70-
export default function TeamMembersPagination() {
71-
const [currentPage, setCurrentPage] = useState<number>(1);
72-
const [allTeamMembers, setAllTeamMembers] = useState<TeamMember[]>([]);
73-
const [isLoading, setIsLoading] = useState<boolean>(true);
74-
const [fetchError, setFetchError] = useState<string | null>(null);
58+
export default function TeamMembersPagination({allTeamMembers}: {allTeamMembers: TeamMembersApiResponse}) {
59+
console.log(allTeamMembers);
60+
61+
const teamMembers = allTeamMembers.TEAM_MEMBERS.map((member) => member as TeamMember)
7562

76-
const ITEMS_PER_PAGE = 10;
63+
// const ITEMS_PER_PAGE = 10;
7764

7865
// Helper functions for role identification
79-
const isInternRole = (role: string): boolean => role === TEAM_ROLES.INTERN;
80-
const isCodevRole = (role: string): boolean => role === TEAM_ROLES.CODEV;
81-
const validateTeamRole = (role: string): PersonRole => {
82-
return isCodevRole(role) ? TEAM_ROLES.CODEV : TEAM_ROLES.INTERN;
83-
};
84-
85-
useEffect(() => {
86-
let isMounted = true;
87-
88-
const fetchAllTeamMembers = async () => {
89-
setIsLoading(true);
90-
setFetchError(null);
91-
92-
try {
93-
const response = await fetch("/api/all-active-interns-codev-prioritized");
94-
if (!response.ok) {
95-
const errorText = await response.text();
96-
throw new Error(`Failed to fetch team members: ${response.status} ${errorText}`);
97-
}
98-
99-
const apiData = (await response.json()) as TeamMembersApiResponse;
100-
101-
if (!apiData || !Array.isArray(apiData.TEAM_MEMBERS)) {
102-
console.warn("Unexpected API response shape for /api/all-active-interns-codev-prioritized:", apiData);
103-
if (!isMounted) return;
104-
setAllTeamMembers([]);
105-
} else {
106-
// Map API response to TeamMember objects with proper role validation
107-
const mappedTeamMembers = apiData.TEAM_MEMBERS.map((member) => ({
108-
id: member.id,
109-
name: member.name,
110-
role: validateTeamRole(member.role), // Ensures only Intern or Codev roles
111-
image: member.image,
112-
display_position: member.display_position,
113-
years_of_experience: member.years_of_experience,
114-
internal_status: member.internal_status,
115-
level: member.level,
116-
codev_points: member.codev_points,
117-
work_experience: member.work_experience,
118-
}));
119-
120-
if (!isMounted) return;
121-
setAllTeamMembers(mappedTeamMembers);
122-
setCurrentPage(1); // Reset to first page when new data loads
123-
}
124-
} catch (fetchErr: any) {
125-
console.error("Error fetching team members:", fetchErr);
126-
if (!isMounted) return;
127-
setFetchError(fetchErr?.message ?? "Unknown error occurred");
128-
setAllTeamMembers([]);
129-
} finally {
130-
if (!isMounted) return;
131-
setIsLoading(false);
132-
}
133-
};
134-
135-
fetchAllTeamMembers();
136-
137-
return () => {
138-
isMounted = false;
139-
};
140-
}, []);
141-
142-
const totalPages = Math.max(1, Math.ceil(allTeamMembers.length / ITEMS_PER_PAGE));
66+
// const isInternRole = (role: string): boolean => role === TEAM_ROLES.INTERN;
67+
// const isCodevRole = (role: string): boolean => role === TEAM_ROLES.CODEV;
68+
// const validateTeamRole = (role: string): PersonRole => {
69+
// return isCodevRole(role) ? TEAM_ROLES.CODEV : TEAM_ROLES.INTERN;
70+
// };
71+
72+
// const totalPages = Math.max(1, Math.ceil(allTeamMembers.length / ITEMS_PER_PAGE));
14373

14474
// Ensure current page stays within valid range
145-
useEffect(() => {
146-
if (currentPage > totalPages) setCurrentPage(totalPages);
147-
if (currentPage < 1) setCurrentPage(1);
148-
}, [currentPage, totalPages]);
149-
150-
// Get current page team members (both Interns and Codevs)
151-
const currentPageTeamMembers = allTeamMembers.slice(
152-
(currentPage - 1) * ITEMS_PER_PAGE,
153-
currentPage * ITEMS_PER_PAGE
154-
);
75+
// useEffect(() => {
76+
// if (currentPage > totalPages) setCurrentPage(totalPages);
77+
// if (currentPage < 1) setCurrentPage(1);
78+
// }, [currentPage, totalPages]);
79+
80+
// const currentPageTeamMembers = allTeamMembers.slice(
81+
// (currentPage - 1) * ITEMS_PER_PAGE,
82+
// currentPage * ITEMS_PER_PAGE
83+
// );
15584

15685
// Navigation functions
157-
const goToPreviousPage = () => {
158-
setCurrentPage((prevPage) => Math.max(1, prevPage - 1));
159-
};
86+
// const goToPreviousPage = () => {
87+
// setCurrentPage((prevPage) => Math.max(1, prevPage - 1));
88+
// };
16089

161-
const goToNextPage = () => {
162-
setCurrentPage((prevPage) => Math.min(totalPages, prevPage + 1));
163-
};
90+
// const goToNextPage = () => {
91+
// setCurrentPage((prevPage) => Math.min(totalPages, prevPage + 1));
92+
// };
16493

165-
const handlePreviousPageClick = () => {
166-
goToPreviousPage();
167-
};
94+
// const handlePreviousPageClick = () => {
95+
// goToPreviousPage();
96+
// };
16897

169-
const handleNextPageClick = () => {
170-
goToNextPage();
171-
};
98+
// const handleNextPageClick = () => {
99+
// goToNextPage();
100+
// };
172101

173102
// Button disabled states
174-
const isPreviousPageDisabled = currentPage <= 1 || isLoading;
175-
const isNextPageDisabled = currentPage >= totalPages || isLoading;
103+
// const isPreviousPageDisabled = currentPage <= 1 || isLoading;
104+
// const isNextPageDisabled = currentPage >= totalPages || isLoading;
176105

177106
return (
178107
<div className="w-full flex flex-col items-center gap-6">
179-
{/* Team Members Cards Container (Both Interns and Codevs) */}
180108
<div className="w-full min-h-[300px]">
181-
{isLoading ? (
182-
<div className="py-12 text-sm text-gray-500 flex items-center justify-center">
183-
Loading team members…
184-
</div>
185-
) : fetchError ? (
186-
<div className="py-12 text-sm text-red-500 flex items-center justify-center">
187-
Error: {fetchError}
188-
</div>
189-
) : currentPageTeamMembers.length > 0 ? (
190-
<InternCards interns={currentPageTeamMembers} />
191-
) : (
192-
<div className="py-12 text-sm text-gray-400 flex items-center justify-center">
193-
No team members available (Interns or Codevs)
194-
</div>
195-
)}
109+
<InternCards interns={teamMembers} />
196110
</div>
197111

198112
{/* Pagination Controls for Team Members */}
199-
<div className="flex items-center gap-3 relative z-[100] mt-8">
113+
{/* <div className="flex items-center gap-3 relative z-[100] mt-8">
200114
<Button
201115
variant="outline"
202116
size="icon"
@@ -222,7 +136,7 @@ export default function TeamMembersPagination() {
222136
>
223137
<ChevronRight size={16} className="shrink-0" />
224138
</Button>
225-
</div>
139+
</div> */}
226140

227141

228142
</div>

‎apps/codebility/app/(marketing)/_components/landing/LandingInternSection.tsx‎

Lines changed: 75 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,74 @@
1-
import React from "react";
1+
import React, { Suspense } from "react";
22
import Link from "next/link";
33
import BlueBg from "./LandingBlueBg";
44
import Section from "../MarketingSection";
55
import LandingInternPagination from "./LandingIntern-CodevPagination";
66
import { Button } from "@/components/ui/button";
7+
import { fetchApiJson } from "@/utils/api-fetch";
8+
9+
const isCodevRole = (role: string): boolean => role === TEAM_ROLES.CODEV;
10+
type PersonRole = 'Intern' | 'Codev';
11+
12+
const TEAM_ROLES = {
13+
INTERN: 'Intern' as const,
14+
CODEV: 'Codev' as const,
15+
} as const;
16+
17+
const validateTeamRole = (role: string): PersonRole => {
18+
return isCodevRole(role) ? TEAM_ROLES.CODEV : TEAM_ROLES.INTERN;
19+
};
20+
interface TeamMembersApiResponse {
21+
TEAM_MEMBERS: {
22+
id: string;
23+
name: string;
24+
role: string;
25+
image?: string;
26+
display_position?: string;
27+
years_of_experience?: number;
28+
internal_status?: string;
29+
level?: Record<string, any>;
30+
codev_points?: Array<{
31+
id: string;
32+
codev_id?: string;
33+
skill_category_id?: string;
34+
points: number;
35+
}>;
36+
work_experience?: Array<any>;
37+
}[];
38+
error?: string;
39+
}
40+
41+
const getAllTeamMembers = async () => {
42+
const result = await fetchApiJson<TeamMembersApiResponse>(
43+
"/api/all-active-interns-codev-prioritized",
44+
{
45+
next: {
46+
revalidate: 3600,
47+
tags: ["active-interns"],
48+
},
49+
},
50+
);
51+
52+
if (!result.ok) {
53+
console.error("Error fetching team members:", result.error);
54+
return null;
55+
}
56+
57+
return result.data;
58+
};
59+
60+
const LandingIntern = async () => {
61+
const users = await getAllTeamMembers();
62+
if (!users) return (
63+
<div className="py-12 text-sm text-gray-400 flex items-center justify-center">
64+
No team members available (Interns or Codevs)
65+
</div>
66+
);
67+
68+
69+
return <LandingInternPagination allTeamMembers={users} />
70+
71+
}
772

873
export default function InternSectionContainer(){
974
return (
@@ -20,10 +85,15 @@ export default function InternSectionContainer(){
2085
us forward with energy and determination.
2186
</p>
2287

23-
<div>
24-
<LandingInternPagination />
25-
</div>
26-
88+
<Suspense fallback={
89+
<div className="py-12 text-sm text-gray-500 flex items-center justify-center">
90+
Loading team members…
91+
</div>}
92+
>
93+
<LandingIntern />
94+
</Suspense>
95+
96+
2797
{/* Hire a CoDevs Button */}
2898
<div className="flex justify-center mt-8 mb-12">
2999
<div className="relative">

‎apps/codebility/app/(marketing)/page.tsx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ export default async function Index() {
3838
<WhyChooseUs />
3939
<WorkWithUs />
4040
<Admins />
41-
{/* <InternSectionContainer />
42-
<Partners />
41+
<InternSectionContainer />
42+
{/* <Partners />
4343
<Testimonials />
4444
<Calendly /> */}
4545
</>

0 commit comments

Comments
 (0)