|
1 | 1 | /** @jsxImportSource @theme-ui/core */ |
2 | | -import { jsx } from "theme-ui"; |
3 | | -import { useState, useEffect } from "react"; |
4 | 2 | import { Container, Grid } from "theme-ui"; |
5 | 3 | import SectionHeader from "../components/section-header"; |
6 | 4 | import TeamCard from "../components/team-card"; |
7 | | -// import axios from "axios"; |
8 | | -// import { data } from "../data/committee.data"; |
9 | | -// New update with images |
10 | | -export default function Committee({ committeeData }) { |
11 | | - // const [committeeData, setCommitteeData] = useState([]); |
12 | | - // useEffect(() => { |
13 | | - // const fetchData = async () => { |
14 | | - // try { |
15 | | - // const response = await axios.get("/api/committee"); |
16 | | - // setCommitteeData(response.data); |
17 | | - // } catch (error) { |
18 | | - // console.error("Error fetching data:", error); |
19 | | - // } |
20 | | - // }; |
21 | | - |
22 | | - // fetchData(); |
23 | | - // }, []); |
24 | | - //console.log(committeeData.data); |
25 | | - |
26 | | - /* |
27 | | - TODO : Create a single array of data with positions sorted manually with precedence |
28 | | - */ |
29 | | - |
30 | | - const executiveHead = committeeData.data?.["Executive Head"] || ""; |
31 | | - const viceExecutiveHead = committeeData.data?.["Vice Executive Head"] || ""; |
32 | | - const executiveMember = committeeData.data?.["Executive Member"] || ""; //mapping required |
33 | | - // const treasurer = committeeData.data?.["Executive Memberand Treasurer"] || ""; |
34 | | - |
35 | | - const advisor = committeeData.data?.["Advisor"] || ""; //mapping required |
36 | | - const senior4th = committeeData.data?.["4th year Senior Member"] || ""; |
37 | | - const senior3rd = committeeData.data?.["3rd year Senior Member"] || ""; //mapping required |
38 | | - const designTransformer = committeeData.data?.["Design Transformer"] || ""; |
39 | | - const logisticShaft = committeeData.data?.["Logistic Shaft"] || ""; |
40 | | - const mediaRectifier = committeeData.data?.["Media Rectifier"] || ""; |
41 | | - const projectCombuster = committeeData.data?.["Project Combuster"] || ""; |
42 | | - const publicRelationProcessor = |
43 | | - committeeData.data?.["Public Relation Processor"] || ""; |
44 | | - |
45 | | - const generalMember = committeeData.data?.["General Member"] || ""; //mapping required |
46 | | - |
47 | | - const toplevel = [...executiveHead, ...viceExecutiveHead]; |
48 | | - const secondlevel = [...executiveMember]; |
49 | | - const thirdlevel = [...advisor, ...senior4th, ...senior3rd]; |
50 | | - const fourthlevel = [ |
51 | | - ...designTransformer, |
52 | | - ...logisticShaft, |
53 | | - ...mediaRectifier, |
54 | | - ...projectCombuster, |
55 | | - ...publicRelationProcessor, |
56 | | - ]; |
57 | | - const fifthlevel = [...generalMember]; |
58 | 5 |
|
| 6 | +// ----------------------------- |
| 7 | +// Safe helpers |
| 8 | +// ----------------------------- |
| 9 | +const safeArray = (data) => (Array.isArray(data) ? data : []); |
| 10 | + |
| 11 | +const get = (obj, key) => safeArray(obj?.data?.[key]); |
| 12 | + |
| 13 | +function toGoogleImageUrl(url = "") { |
| 14 | + const match = url.match(/id=([^&]+)/); |
| 15 | + if (!match) return url; |
| 16 | + return `https://lh3.googleusercontent.com/d/${match[1]}=w500`; |
| 17 | +} |
| 18 | + |
| 19 | +// ----------------------------- |
| 20 | +// Page Component |
| 21 | +// ----------------------------- |
| 22 | +export default function Committee({ committeeData = {} }) { |
| 23 | + const data = committeeData; |
| 24 | + |
| 25 | + // Role mapping (clean + scalable) |
| 26 | + const roles = { |
| 27 | + top: [ |
| 28 | + ...get(data, "Executive Head"), |
| 29 | + ...get(data, "Vice Executive Head"), |
| 30 | + ], |
| 31 | + |
| 32 | + second: get(data, "Executive Member"), |
| 33 | + |
| 34 | + third: [ |
| 35 | + ...get(data, "Advisor"), |
| 36 | + ...get(data, "4th year Senior Member"), |
| 37 | + ...get(data, "3rd year Senior Member"), |
| 38 | + ], |
| 39 | + |
| 40 | + fourth: [ |
| 41 | + ...get(data, "Design Transformer"), |
| 42 | + ...get(data, "Logistic Shaft"), |
| 43 | + ...get(data, "Media Rectifier"), |
| 44 | + ...get(data, "Project Combuster"), |
| 45 | + ...get(data, "Public Relation Processor"), |
| 46 | + ], |
| 47 | + |
| 48 | + fifth: get(data, "General Member"), |
| 49 | + }; |
| 50 | + |
| 51 | + // ----------------------------- |
| 52 | + // Reusable renderer |
| 53 | + // ----------------------------- |
| 54 | + const renderCards = (list = []) => |
| 55 | + list.map((member, idx) => ( |
| 56 | + <TeamCard |
| 57 | + key={`${member?.name?.[0] || "member"}-${idx}`} |
| 58 | + src={toGoogleImageUrl(member?.image?.[0])} |
| 59 | + title={member?.name?.[0]} |
| 60 | + altText={member?.name?.[0]} |
| 61 | + designation={member?.position?.[0]} |
| 62 | + fb={member?.fb?.[0]} |
| 63 | + insta={member?.insta?.[0]} |
| 64 | + tweet={member?.twitter?.[0]} |
| 65 | + linkedin={member?.linkedin?.[0]} |
| 66 | + /> |
| 67 | + )); |
59 | 68 |
|
60 | 69 | return ( |
61 | 70 | <section sx={styles.banner} id="committee"> |
62 | | - {committeeData && ( |
63 | | - <Container sx={styles.banner.container}> |
64 | | - <SectionHeader slogan="Meet Our Enthusiastic 20th Executive Committee" /> |
65 | | - <Grid sx={styles.grid}> |
66 | | - {toplevel.map((level, idx) => ( |
67 | | - <TeamCard |
68 | | - key={idx} |
69 | | - // src={level.image[0]} |
70 | | - src={toGoogleImageUrl(level.image[0])} |
71 | | - title={level.name[0]} |
72 | | - altText={level.name[0]} |
73 | | - designation={level.position[0]} |
74 | | - fb={level.fb[0]} |
75 | | - insta={level.insta[0]} |
76 | | - tweet={level?.twitter[0]} |
77 | | - linkedin={level?.linkedin[0]} |
78 | | - /> |
79 | | - ))} |
80 | | - {secondlevel.map((level, idx) => ( |
81 | | - <TeamCard |
82 | | - key={idx} |
83 | | - // src={level.image[0]} |
84 | | - src={toGoogleImageUrl(level.image[0])} |
85 | | - title={level.name[0]} |
86 | | - altText={level.name[0]} |
87 | | - designation={level.position[0]} |
88 | | - fb={level.fb[0]} |
89 | | - insta={level.insta[0]} |
90 | | - tweet={level.twitter[0]} |
91 | | - linkedin={level.linkedin[0]} |
92 | | - /> |
93 | | - ))} |
94 | | - {thirdlevel.map((level, idx) => ( |
95 | | - <TeamCard |
96 | | - key={idx} |
97 | | - // src={level.image[0]} |
98 | | - src={toGoogleImageUrl(level.image[0])} |
99 | | - title={level.name[0]} |
100 | | - altText={level.name[0]} |
101 | | - designation={level.position[0]} |
102 | | - fb={level.fb[0]} |
103 | | - insta={level.insta[0]} |
104 | | - tweet={level.twitter[0]} |
105 | | - linkedin={level.linkedin[0]} |
106 | | - /> |
107 | | - ))} |
108 | | - {fourthlevel.map((level, idx) => ( |
109 | | - <TeamCard |
110 | | - key={idx} |
111 | | - // src={level.image[0]} |
112 | | - src={toGoogleImageUrl(level.image[0])} |
113 | | - title={level.name[0]} |
114 | | - altText={level.name[0]} |
115 | | - designation={level.position[0]} |
116 | | - fb={level.fb[0]} |
117 | | - insta={level.insta[0]} |
118 | | - tweet={level.twitter[0]} |
119 | | - linkedin={level.linkedin[0]} |
120 | | - /> |
121 | | - ))} |
122 | | - {/* {!generalMember ? ( |
123 | | - <SectionHeader slogan="No members to show" /> |
124 | | - ) : ( */} |
125 | | - {fifthlevel.map((level, idx) => ( |
126 | | - <TeamCard |
127 | | - key={idx} |
128 | | - // src={level.image[0]} |
129 | | - src={toGoogleImageUrl(level.image[0])} |
130 | | - title={level.name[0]} |
131 | | - altText={level.name[0]} |
132 | | - designation={level.position[0]} |
133 | | - fb={level.fb[0]} |
134 | | - insta={level.insta[0]} |
135 | | - tweet={level.twitter[0]} |
136 | | - linkedin={level.linkedin[0]} |
137 | | - /> |
138 | | - ))} |
139 | | - </Grid> |
140 | | - </Container> |
141 | | - )} |
| 71 | + <Container sx={styles.banner.container}> |
| 72 | + <SectionHeader slogan="Meet Our Executive Committee" /> |
| 73 | + |
| 74 | + <Grid sx={styles.grid}> |
| 75 | + {renderCards(roles.top)} |
| 76 | + {renderCards(roles.second)} |
| 77 | + {renderCards(roles.third)} |
| 78 | + {renderCards(roles.fourth)} |
| 79 | + {renderCards(roles.fifth)} |
| 80 | + </Grid> |
| 81 | + </Container> |
142 | 82 | </section> |
143 | 83 | ); |
144 | 84 | } |
145 | | -function toGoogleImageUrl(thumbnailUrl) { |
146 | | - const match = thumbnailUrl.match(/id=([^&]+)/); |
147 | | - if (!match) return thumbnailUrl; |
148 | | - const fileId = match[1]; |
149 | | - return `https://lh3.googleusercontent.com/d/${fileId}=w500`; |
150 | | -} |
151 | 85 |
|
152 | | - |
153 | | -} |
| 86 | +// ----------------------------- |
| 87 | +// Data fetching |
| 88 | +// ----------------------------- |
154 | 89 | export async function getStaticProps() { |
155 | | - const res = await fetch("https://wrcrobotics.pythonanywhere.com/committee"); |
156 | | - const committeeData = await res.json(); |
| 90 | + try { |
| 91 | + const res = await fetch( |
| 92 | + "https://wrcrobotics.pythonanywhere.com/committee" |
| 93 | + ); |
157 | 94 |
|
158 | | - return { |
159 | | - props: { committeeData }, |
160 | | - revalidate: 10, // updates every 10 seconds |
161 | | - }; |
| 95 | + const committeeData = await res.json(); |
162 | 96 |
|
| 97 | + return { |
| 98 | + props: { committeeData }, |
| 99 | + revalidate: 10, |
| 100 | + }; |
| 101 | + } catch (err) { |
| 102 | + return { |
| 103 | + props: { committeeData: {} }, |
| 104 | + revalidate: 10, |
| 105 | + }; |
| 106 | + } |
| 107 | +} |
| 108 | + |
| 109 | +// ----------------------------- |
| 110 | +// Styles (cleaned) |
| 111 | +// ----------------------------- |
163 | 112 | const styles = { |
164 | 113 | banner: { |
165 | | - pt: ["140px", "145px", "155px", "170px", null, null, "180px", "215px"], |
166 | | - pb: [2, null, 0, null, 2, 0, null, 5], |
| 114 | + pt: ["140px", "145px", "155px", "170px", null, null, "180px"], |
| 115 | + pb: [2, null, 5], |
167 | 116 | position: "relative", |
168 | 117 | zIndex: 2, |
169 | 118 |
|
170 | 119 | container: { |
171 | | - minHeight: "inherit", |
172 | 120 | display: "flex", |
173 | 121 | flexDirection: "column", |
174 | 122 | justifyContent: "center", |
175 | 123 | }, |
176 | | - contentBox: { |
177 | | - width: ["100%", "90%", "535px", null, "57%", "60%", "68%", "60%"], |
178 | | - mx: "auto", |
179 | | - textAlign: "center", |
180 | | - mb: ["40px", null, null, null, null, 7], |
181 | | - }, |
182 | | - imageBox: { |
183 | | - justifyContent: "center", |
184 | | - textAlign: "center", |
185 | | - display: "inline-flex", |
186 | | - mb: [0, null, -6, null, null, "-40px", null, -3], |
187 | | - img: { |
188 | | - position: "relative", |
189 | | - height: [200, "auto"], |
190 | | - // width: [200, "auto"], |
191 | | - |
192 | | - }, |
193 | | - }, |
194 | 124 | }, |
| 125 | + |
195 | 126 | grid: { |
196 | | - mt: [0, null, -6, null, -4], |
197 | | - gridGap: ["35px 0px", null, 0, null, null, "30px 35px"], |
| 127 | + mt: 0, |
| 128 | + gridGap: ["30px"], |
198 | 129 | gridTemplateColumns: [ |
199 | 130 | "repeat(1,1fr)", |
200 | | - null, |
201 | 131 | "repeat(2,1fr)", |
202 | | - null, |
203 | 132 | "repeat(3,1fr)", |
204 | 133 | ], |
205 | 134 | }, |
|
0 commit comments