Skip to content

Commit 4462c5c

Browse files
Fix Meet The Team due to incorrect fetching of role. Now fetched the data accordingly to roles in Supabase.
1 parent c7392ea commit 4462c5c

2 files changed

Lines changed: 141 additions & 137 deletions

File tree

‎apps/codebility/app/api/team/route.ts‎

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,38 @@ import { createClientServerComponent } from "@/utils/supabase/server";
44

55
type Person = { name: string; role: string; image?: string };
66

7-
// Replace from the admin group
8-
const CEO_FULL_NAME = process.env.CEO_FULLNAME ?? ""; // or import from a shared constants file
7+
// CEO identification
8+
const CEO_FIRST_NAME = "Jzeff Kendrew";
9+
const CEO_LAST_NAME = "Somera";
910

1011
export async function GET() {
1112
try {
1213
const supabase = await createClientServerComponent();
1314

15+
// Fetch CEO and Admins/Mentors separately
16+
const { data: ceoData, error: ceoError } = await supabase
17+
.from("codev")
18+
.select(`
19+
first_name,
20+
last_name,
21+
image_url
22+
`)
23+
.eq("first_name", CEO_FIRST_NAME)
24+
.eq("last_name", CEO_LAST_NAME)
25+
.eq("availability_status", true)
26+
.single();
27+
28+
let CEO: Person | null = null;
29+
30+
if (!ceoError && ceoData) {
31+
CEO = {
32+
name: `${ceoData.first_name} ${ceoData.last_name}`.replace(/\s+/g, ' ').trim(),
33+
role: "Founder / CEO",
34+
image: ceoData.image_url ?? undefined
35+
};
36+
}
37+
38+
// Fetch Admins and Mentors (excluding CEO)
1439
const { data, error } = await supabase
1540
.from("codev")
1641
.select(`
@@ -25,54 +50,47 @@ export async function GET() {
2550
roles!inner ( name )
2651
`)
2752
.eq("availability_status", true)
28-
.in("roles.name", ["Admin", "Mentor"]);
53+
.in("roles.name", ["Admin", "Mentor"])
54+
.neq("first_name", CEO_FIRST_NAME); // Exclude CEO from this query
2955

3056
if (error) {
3157
console.error("Supabase query error:", error);
3258
return NextResponse.json(
33-
{ ADMINS: [], MENTORS: [], CEO: null, error: error.message ?? "DB error" },
59+
{ ADMINS: [], MENTORS: [], CEO, error: error.message ?? "DB error" },
3460
{ status: 500 }
3561
);
3662
}
3763

3864
const ADMINS: Person[] = [];
3965
const MENTORS: Person[] = [];
40-
let CEO: Person | null = null;
4166

4267
(data ?? []).forEach((row: any) => {
43-
const name = `${row.first_name ?? ""} ${row.last_name ?? ""}`.trim();
68+
const firstName = (row.first_name ?? "").trim();
69+
const lastName = (row.last_name ?? "").trim();
70+
const name = `${firstName} ${lastName}`.replace(/\s+/g, ' ').trim();
4471
const role = row.roles?.name ?? "Member";
72+
4573
const person: Person = {
4674
name: name || "Unknown",
4775
role,
4876
image: row.image_url ?? undefined,
4977
};
5078

51-
// Normalize comparison
52-
const normalizedName = name.toLowerCase();
53-
const normalizedCEO = CEO_FULL_NAME.trim().toLowerCase();
54-
55-
if (role === "Admin" && normalizedCEO && normalizedName === normalizedCEO) {
56-
// ✅ Found CEO: assign to CEO, exclude from ADMINS
57-
CEO = { ...person, role: "Founder / CEO" };
58-
} else if (role === "Admin") {
79+
if (role === "Admin") {
5980
ADMINS.push(person);
6081
} else if (role === "Mentor") {
6182
MENTORS.push(person);
6283
}
6384
});
6485

65-
// filter admins with project_id e0124447-1978-400f-bfc7-7ea2f974d100 and role `member` or project_id 54d5fba1-056c-45a2-b492-02eec8530640 and role `member` or name is `Ian Troy Pahilga
66-
const filteredAdmins = ADMINS.filter((admin) => {
67-
const projectMember = data?.find((row: any) => {
68-
const name = `${row.first_name ?? ""} ${row.last_name ?? ""}`.trim();
69-
return name === admin.name;
70-
})?.project_members;
86+
7187

72-
return !projectMember?.some((pm: any) => ((pm.project_id === 'e0124447-1978-400f-bfc7-7ea2f974d100' && pm.role === 'member') || (pm.project_id === '54d5fba1-056c-45a2-b492-02eec8530640' && pm.role === 'member'))) && admin.name !== 'Ian Troy Pahilga';
88+
return NextResponse.json({
89+
ADMINS,
90+
MENTORS,
91+
CEO
7392
});
74-
75-
return NextResponse.json({ ADMINS: filteredAdmins, MENTORS, CEO });
93+
7694
} catch (err) {
7795
console.error("Unexpected error in /api/team:", err);
7896
return NextResponse.json(

‎apps/codebility/app/auth/onboarding/_components/Team/TeamSection.tsx‎

Lines changed: 100 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// components/TeamSection.tsx
1+
// onboarding/components/TeamSection.tsx
22
"use client";
33

44
import React, { useEffect, useState } from "react";
@@ -7,41 +7,37 @@ import { cn } from "@/lib/utils";
77
// -------------------------
88
// Types
99
// -------------------------
10-
type Person = {
11-
name: string;
12-
role: string;
13-
image?: string;
14-
};
15-
16-
interface TeamResponse {
17-
ADMINS?: Person[];
18-
MENTORS?: Person[];
19-
error?: string;
20-
}
21-
22-
// -------------------------
23-
// CEO Fullname Reference
24-
// -------------------------
25-
const CEO_FULLNAME = "Jzeff Kendrew Somera"; // <-- replace with actual first+last name from Supabase
10+
type Person = {
11+
name: string;
12+
role: string;
13+
image?: string;
14+
};
15+
16+
interface TeamResponse {
17+
ADMINS?: Person[];
18+
MENTORS?: Person[];
19+
CEO?: Person | null;
20+
error?: string;
21+
}
2622

2723
// -------------------------
2824
// Avatar
2925
// -------------------------
30-
function Avatar({
31-
person,
32-
size = 72,
33-
position = "center top"
34-
}: {
35-
person: Person;
36-
size?: number;
37-
position?: string;
38-
}) {
39-
const initials = (person.name || "")
40-
.split(" ")
41-
.slice(0, 2)
42-
.map((n) => n[0] ?? "")
43-
.join("")
44-
.toUpperCase();
26+
function Avatar({
27+
person,
28+
size = 72,
29+
position = "center top"
30+
}: {
31+
person: Person;
32+
size?: number;
33+
position?: string;
34+
}) {
35+
const initials = (person.name || "")
36+
.split(" ")
37+
.slice(0, 2)
38+
.map((n) => n[0] ?? "")
39+
.join("")
40+
.toUpperCase();
4541

4642
return person.image ? (
4743
<div
@@ -79,95 +75,85 @@ import { cn } from "@/lib/utils";
7975
// -------------------------
8076
// PersonCard
8177
// -------------------------
82-
function PersonCard({ person }: { person: Person }) {
83-
return (
84-
<div
85-
className={cn(
86-
"group relative overflow-hidden rounded-2xl border",
87-
"border-white/10 bg-white/[0.06] p-4 shadow-[0_10px_30px_-15px_rgba(0,0,0,0.6)] backdrop-blur-md",
88-
"transition-all duration-300 hover:border-cyan-400/30 hover:shadow-cyan-500/20"
89-
)}
90-
>
91-
<div className="flex items-center gap-3">
92-
<Avatar person={person} size={56} />
93-
<div className="min-w-0">
94-
<h4 className="text-sm font-semibold text-white/90">{person.name}</h4>
95-
<p className="truncate text-xs text-white/60">{person.role}</p>
96-
</div>
78+
function PersonCard({ person }: { person: Person }) {
79+
return (
80+
<div
81+
className={cn(
82+
"group relative overflow-hidden rounded-2xl border",
83+
"border-white/10 bg-white/[0.06] p-4 shadow-[0_10px_30px_-15px_rgba(0,0,0,0.6)] backdrop-blur-md",
84+
"transition-all duration-300 hover:border-cyan-400/30 hover:shadow-cyan-500/20"
85+
)}
86+
>
87+
<div className="flex items-center gap-3">
88+
<Avatar person={person} size={56} />
89+
<div className="min-w-0">
90+
<h4 className="text-sm font-semibold text-white/90">{person.name}</h4>
91+
<p className="truncate text-xs text-white/60">{person.role}</p>
9792
</div>
98-
<span className="pointer-events-none absolute inset-x-0 bottom-0 h-0.5 bg-gradient-to-r from-cyan-400 via-fuchsia-500 to-emerald-400 opacity-70" />
9993
</div>
100-
);
101-
}
94+
<span className="pointer-events-none absolute inset-x-0 bottom-0 h-0.5 bg-gradient-to-r from-cyan-400 via-fuchsia-500 to-emerald-400 opacity-70" />
95+
</div>
96+
);
97+
}
10298

10399
// -------------------------
104100
// TeamSection
105101
// -------------------------
106-
export default function TeamSection() {
107-
const [admins, setAdmins] = useState<Person[]>([]);
108-
const [mentors, setMentors] = useState<Person[]>([]);
109-
const [ceo, setCeo] = useState<Person>({
110-
name: "CEO Name",
111-
role: "Founder / CEO",
112-
image: ""
113-
});
114-
const [loading, setLoading] = useState(true);
115-
const [errMsg, setErrMsg] = useState<string | null>(null);
116-
117-
useEffect(() => {
118-
let mounted = true;
119-
async function load() {
120-
setLoading(true);
121-
setErrMsg(null);
122-
102+
export default function TeamSection() {
103+
const [admins, setAdmins] = useState<Person[]>([]);
104+
const [mentors, setMentors] = useState<Person[]>([]);
105+
const [ceo, setCeo] = useState<Person>({
106+
name: "CEO Name",
107+
role: "Founder / CEO",
108+
image: ""
109+
});
110+
const [loading, setLoading] = useState(true);
111+
const [errMsg, setErrMsg] = useState<string | null>(null);
112+
113+
useEffect(() => {
114+
let mounted = true;
115+
async function load() {
116+
setLoading(true);
117+
setErrMsg(null);
118+
119+
try {
120+
const res = await fetch("/api/team");
121+
122+
let body: TeamResponse;
123123
try {
124-
const res = await fetch("/api/team");
125-
126-
let body: TeamResponse;
127-
try {
128-
body = (await res.json()) as TeamResponse;
129-
} catch {
130-
body = {} as TeamResponse;
131-
}
132-
133-
if (!res.ok) {
134-
throw new Error(body.error ?? `Fetch failed (${res.status})`);
135-
}
136-
137-
if (!mounted) return;
138-
139-
const adminsList = Array.isArray(body.ADMINS) ? body.ADMINS : [];
140-
const mentorsList = Array.isArray(body.MENTORS) ? body.MENTORS : [];
141-
142-
// Match CEO by full name in admins list
143-
const foundCeo = adminsList.find(
144-
(p) => p.name?.trim().toLowerCase() === CEO_FULLNAME.toLowerCase()
145-
);
146-
147-
if (foundCeo) {
148-
setCeo({
149-
...foundCeo,
150-
role: "Founder / CEO" // force CEO role
151-
});
152-
// Remove CEO from admins list so not duplicated
153-
setAdmins(adminsList.filter((p) => p !== foundCeo));
154-
} else {
155-
setAdmins(adminsList);
156-
}
157-
158-
setMentors(mentorsList);
159-
} catch (err: any) {
160-
console.error("Error loading team:", err);
161-
if (mounted) setErrMsg(err?.message ?? "Failed to load team");
162-
} finally {
163-
if (mounted) setLoading(false);
124+
body = (await res.json()) as TeamResponse;
125+
} catch {
126+
body = {} as TeamResponse;
127+
}
128+
129+
if (!res.ok) {
130+
throw new Error(body.error ?? `Fetch failed (${res.status})`);
164131
}
132+
133+
if (!mounted) return;
134+
135+
const adminsList = Array.isArray(body.ADMINS) ? body.ADMINS : [];
136+
const mentorsList = Array.isArray(body.MENTORS) ? body.MENTORS : [];
137+
138+
// Set CEO directly from API response
139+
if (body.CEO) {
140+
setCeo(body.CEO);
141+
}
142+
143+
setAdmins(adminsList);
144+
setMentors(mentorsList);
145+
} catch (err: any) {
146+
console.error("Error loading team:", err);
147+
if (mounted) setErrMsg(err?.message ?? "Failed to load team");
148+
} finally {
149+
if (mounted) setLoading(false);
165150
}
166-
load();
167-
return () => {
168-
mounted = false;
169-
};
170-
}, []);
151+
}
152+
load();
153+
return () => {
154+
mounted = false;
155+
};
156+
}, []);
171157

172158
return (
173159
<section className="relative w-full overflow-hidden bg-gradient-to-br from-zinc-900 via-zinc-950 to-black py-16 sm:py-20 lg:py-24">
@@ -198,7 +184,7 @@ import { cn } from "@/lib/utils";
198184
<h3 className="mb-4 text-center text-lg font-bold tracking-tight text-white/85">Admins</h3>
199185
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
200186
{admins.length > 0 ? (
201-
admins.map((p) => <PersonCard key={`${p.name}-${p.role}`} person={p} />)
187+
admins.map((p, idx) => <PersonCard key={`${p.name}-${idx}`} person={p} />)
202188
) : (
203189
<div className="col-span-full text-center text-white/50">No admins available</div>
204190
)}
@@ -220,7 +206,7 @@ import { cn } from "@/lib/utils";
220206
<h3 className="mb-4 text-center text-lg font-bold tracking-tight text-white/85">Mentors</h3>
221207
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
222208
{mentors.length > 0 ? (
223-
mentors.map((p) => <PersonCard key={`${p.name}-${p.role}`} person={p} />)
209+
mentors.map((p, idx) => <PersonCard key={`${p.name}-${idx}`} person={p} />)
224210
) : (
225211
<div className="col-span-full text-center text-white/50">No mentors available</div>
226212
)}

0 commit comments

Comments
 (0)