Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion notion_cache.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"1aabb9ea-bd14-8003-94cb-e05052c8e884": "2026-01-16T07:24:00.000Z", "1aabb9ea-bd14-801b-b84e-e5e6759bab17": "2026-01-19T15:32:00.000Z", "1aabb9ea-bd14-8034-ac22-eb67957b287c": "2025-12-30T15:43:00.000Z", "1aabb9ea-bd14-804b-980b-d17b3028bda5": "2025-12-27T14:02:00.000Z", "1aabb9ea-bd14-805e-bffa-cad47843be2b": "2025-12-30T16:56:00.000Z", "1aabb9ea-bd14-8064-9817-f1b7ee3cd7d8": "2025-12-30T13:56:00.000Z", "1aabb9ea-bd14-807b-8eec-e2f5da97fc9d": "2026-01-21T16:28:00.000Z", "1aabb9ea-bd14-80b4-9d41-ed343f0f84fb": "2025-12-15T04:50:00.000Z", "1aabb9ea-bd14-80c4-b066-c6241af213d8": "2025-12-30T13:57:00.000Z", "1aabb9ea-bd14-80d4-bcae-c47505f078f7": "2025-12-30T15:03:00.000Z", "1aabb9ea-bd14-80fc-b09d-f119168392b0": "2025-12-26T13:14:00.000Z", "1aabb9ea-bd14-80fe-89eb-f5b5495943ef": "2025-12-28T07:30:00.000Z", "2c9bb9ea-bd14-8111-a197-fd2b924a628c": "2025-12-27T09:20:00.000Z", "2c9bb9ea-bd14-8157-a1b2-e2ba27313a99": "2025-12-29T16:31:00.000Z", "2c9bb9ea-bd14-815b-adb0-c3c3e1227924": "2025-12-29T03:38:00.000Z", "2cabb9ea-bd14-8127-a5b5-d0c4be038074": "2025-12-27T09:20:00.000Z", "2cabb9ea-bd14-8155-867c-c90aef7e6ddf": "2025-12-30T01:35:00.000Z"}
{"2cabb9ea-bd14-8155-867c-c90aef7e6ddf": "2026-08-03T15:33:00.000Z", "2cabb9ea-bd14-8127-a5b5-d0c4be038074": "2026-08-03T15:33:00.000Z", "2c9bb9ea-bd14-8111-a197-fd2b924a628c": "2026-08-03T15:33:00.000Z", "2c9bb9ea-bd14-8157-a1b2-e2ba27313a99": "2026-08-03T15:33:00.000Z", "2c9bb9ea-bd14-815b-adb0-c3c3e1227924": "2026-08-03T15:33:00.000Z", "1aabb9ea-bd14-8003-94cb-e05052c8e884": "2026-08-03T15:33:00.000Z", "1aabb9ea-bd14-804b-980b-d17b3028bda5": "2026-08-03T15:33:00.000Z", "1aabb9ea-bd14-8064-9817-f1b7ee3cd7d8": "2026-08-03T15:33:00.000Z", "1aabb9ea-bd14-807b-8eec-e2f5da97fc9d": "2026-08-03T15:33:00.000Z", "1aabb9ea-bd14-80c4-b066-c6241af213d8": "2026-08-03T15:32:00.000Z", "1aabb9ea-bd14-80d4-bcae-c47505f078f7": "2026-08-03T15:33:00.000Z", "1aabb9ea-bd14-801b-b84e-e5e6759bab17": "2026-08-03T15:32:00.000Z", "1aabb9ea-bd14-8034-ac22-eb67957b287c": "2026-07-06T05:52:00.000Z", "1aabb9ea-bd14-805e-bffa-cad47843be2b": "2026-08-03T15:32:00.000Z", "1aabb9ea-bd14-80b4-9d41-ed343f0f84fb": "2026-08-03T15:32:00.000Z", "1aabb9ea-bd14-80fc-b09d-f119168392b0": "2026-08-04T10:04:00.000Z", "1aabb9ea-bd14-80fe-89eb-f5b5495943ef": "2026-08-03T15:32:00.000Z"}
Binary file modified public/member_images/doan_quoc_an.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions scripts/fetch-members.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

# --- Set up ---
NOTION_TOKEN = os.environ.get("NOTION_TOKEN")
DATABASE_ID = os.environ.get("DATABASE_ID")

IMAGE_FOLDER = "public/member_images"
HEADERS = {
"Authorization": f"Bearer {NOTION_TOKEN}",
Expand Down Expand Up @@ -114,7 +114,8 @@ def process_notion_data():

final_data.append({
"name": name,
"role": props.get("Role", {}).get("select", {}).get("name", "N/A"),
"role": (props.get("Role", {}).get("select") or {}).get("name", "N/A"),
"position": (props.get("Position", {}).get("select") or {}).get("name", ""),
"image": img_path
})

Expand Down
72 changes: 51 additions & 21 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ const groupedData = (() => {
return acc;
}, {});

Object.keys(groups).forEach((role) => {
groups[role].sort((a, b) => {
// Weight: Lead ranks 1st, Member ranks 2nd, and Senior Advisor (or blank/empty) ranks 3rd
const getWeight = (pos) => pos === "Lead" ? 1 : (pos === "Member" ? 2 : 3);
return getWeight(a.position) - getWeight(b.position);
});
});

const sortedGroups = {};
ROLE_ORDER.forEach((role) => {
if (groups[role]) {
Expand Down Expand Up @@ -145,7 +153,6 @@ function App() {

// Resource hints for performance
useEffect(() => {
// Add preconnect for external domains
performanceConfig.resourceHints.forEach((hint) => {
const link = document.createElement("link");
link.rel = hint.rel;
Expand All @@ -155,7 +162,6 @@ function App() {
});

return () => {
// Cleanup on unmount
performanceConfig.resourceHints.forEach((hint) => {
const links = document.querySelectorAll(`link[href="${hint.href}"]`);
links.forEach((link) => link.remove());
Expand All @@ -169,9 +175,7 @@ function App() {
{ label: "Thông báo", href: "https://svuit.org/mmtt/docs/ThongBao/index" },
];

// Register service worker and set up performance monitoring
useEffect(() => {
// Register service worker if enabled
if (performanceConfig.features.serviceWorker) {
const { register } = require("./utils/serviceWorker");
register({
Expand All @@ -189,12 +193,10 @@ function App() {
});
}

// Set initial visibility with a small delay
const timer = setTimeout(() => {
setIsVisible(true);
}, 100);

// Cleanup function
return () => {
clearTimeout(timer);
};
Expand Down Expand Up @@ -273,7 +275,7 @@ function App() {
overflow: "hidden",
opacity: isVisible ? 1 : 0,
transition: "opacity 1s ease-in-out",
zIndex: 2, // Adjusted z-index
zIndex: 2,
marginBottom: "-1rem",
}}
>
Expand Down Expand Up @@ -708,11 +710,11 @@ function App() {
style={{
display: "flex",
flexDirection: "row",
flexWrap: "wrap", // ← fix slider
flexWrap: "wrap",
justifyContent: "center",
alignItems: "center",
gap: "2rem",
overflow: "hidden", // ← remove horizontal scroll
overflow: "hidden",
paddingBottom: "1rem",
width: "100%",
}}
Expand All @@ -726,13 +728,19 @@ function App() {
alignItems: "center",
}}
>

<div
style={{
width: "200px",
height: "200px",
borderRadius: "50%",
overflow: "hidden",
border: `3px solid ${index % 2 === 0 ? "#7c4dff" : "#b388ff"}`,
// Color border
border: `3px solid ${
member.position === "Lead" || member.role === "Senior Advisor"
? (index % 2 === 0 ? "#7c4dff" : "#b388ff")
: "rgba(255, 255, 255, 0.7)" // Members will have white border and leads will have purple
}`,
marginBottom: "0.5rem",
}}
>
Expand All @@ -748,16 +756,38 @@ function App() {
/>
</div>

<p
style={{
color: "#fff",
fontSize: "1.1rem",
margin: "0.5rem 0",
textAlign: "center",
}}
>
{member.name}
</p>
<div style={{ display: "flex", flexDirection: "column", alignItems: "center" }}>
<p
style={{
color: member.position === "Lead" ? "#b388ff" : "#fff",
fontSize: "1.1rem",
margin: "0.5rem 0 0.2rem 0",
textAlign: "center",
fontWeight: member.position === "Lead" ? "bold" : "normal",
}}
>
{member.name}
</p>

{/* Position added */}
{member.position && (
<span
style={{
fontSize: "0.75rem",
color: member.position === "Lead" ? "#fff" : "rgba(255, 255, 255, 0.6)",
backgroundColor: member.position === "Lead" ? "rgba(179, 136, 255, 0.2)" : "transparent",
border: member.position === "Lead" ? "1px solid rgba(179, 136, 255, 0.5)" : "none",
padding: member.position === "Lead" ? "2px 8px" : "0",
borderRadius: "10px",
fontWeight: member.position === "Lead" ? "600" : "400",
letterSpacing: "0.5px",
textTransform: "uppercase"
}}
>
{member.position}
</span>
)}
</div>
</div>
))}
</div>
Expand Down Expand Up @@ -1057,4 +1087,4 @@ function App() {
);
}

export default App;
export default App;
95 changes: 56 additions & 39 deletions src/data/notion_member.json
Original file line number Diff line number Diff line change
@@ -1,87 +1,104 @@
[
{
"name": "Nguyễn Thế Lập",
"role": "Website Development",
"image": "/member_images/nguyen_the_lap.jpg"
"name": "Trần Phạm Bảo Trân",
"role": "Platform Operations",
"position": "Member",
"image": "/member_images/tran_pham_bao_tran.jpg"
},
{
"name": "Nguyễn Hoàng Lộc",
"name": "Ngô Lê Tấn Huy",
"role": "Platform Operations",
"image": "/member_images/nguyen_hoang_loc.jpg"
"position": "Member",
"image": "/member_images/ngo_le_tan_huy.jpg"
},
{
"name": "Trần Công Hải",
"role": "Senior Advisor",
"image": "/member_images/tran_cong_hai.jpg"
"name": "Lý Nhật Minh",
"role": "Social Media",
"position": "Member",
"image": "/member_images/ly_nhat_minh.jpg"
},
{
"name": "Đoàn Nguyễn Minh Thư",
"role": "Website Development",
"position": "Member",
"image": "/member_images/doan_nguyen_minh_thu.jpg"
},
{
"name": "Trịnh Hoài An",
"role": "Website Development",
"position": "Member",
"image": "/member_images/trinh_hoai_an.jpg"
},
{
"name": "Nguyễn Thế Lập",
"role": "Website Development",
"position": "Member",
"image": "/member_images/nguyen_the_lap.jpg"
},
{
"name": "Nguyễn Thành An",
"role": "Social Media",
"position": "Member",
"image": "/member_images/nguyen_thanh_an.jpg"
},
{
"name": "Tống Võ Anh Thuận",
"role": "Operations Lead",
"image": "/member_images/tong_vo_anh_thuan.jpg"
},
{
"name": "Sơn Nguyễn Kỳ Duyên",
"role": "Social Media",
"position": "Member",
"image": "/member_images/son_nguyen_ky_duyen.jpg"
},
{
"name": "Đoàn Quốc An",
"role": "Social Media",
"position": "Lead",
"image": "/member_images/doan_quoc_an.jpg"
},
{
"name": "Lê Huỳnh Quang Vũ",
"role": "Senior Advisor",
"image": "/default.png"
},
{
"name": "Phạm Việt Hoàng",
"role": "Platform Operations",
"position": "Member",
"image": "/member_images/pham_viet_hoang.jpg"
},
{
"name": "Trương Đỗ Như Quỳnh",
"role": "Website Development",
"position": "Lead",
"image": "/member_images/truong_do_nhu_quynh.jpg"
},
{
"name": "Đoàn Nguyễn Lâm",
"role": "Platform Operations",
"image": "/member_images/doan_nguyen_lam.jpg"
},
{
"name": "Đặng Chí Thành",
"name": "Nguyễn Hoàng Lộc",
"role": "Platform Operations",
"image": "/member_images/dang_chi_thanh.jpg"
"position": "Lead",
"image": "/member_images/nguyen_hoang_loc.jpg"
},
{
"name": "Lý Nhật Minh",
"role": "Social Media",
"image": "/member_images/ly_nhat_minh.jpg"
"name": "Trần Công Hải",
"role": "Senior Advisor",
"position": "",
"image": "/member_images/tran_cong_hai.jpg"
},
{
"name": "Đoàn Nguyễn Minh Thư",
"role": "Website Development",
"image": "/member_images/doan_nguyen_minh_thu.jpg"
"name": "Tống Võ Anh Thuận",
"role": "Senior Advisor",
"position": "",
"image": "/member_images/tong_vo_anh_thuan.jpg"
},
{
"name": "Trịnh Hoài An",
"role": "Website Development",
"image": "/member_images/trinh_hoai_an.jpg"
"name": "Lê Huỳnh Quang Vũ",
"role": "Senior Advisor",
"position": "",
"image": "/default.png"
},
{
"name": "Ngô Lê Tấn Huy",
"role": "Platform Operations",
"image": "/member_images/ngo_le_tan_huy.jpg"
"name": "Đoàn Nguyễn Lâm",
"role": "Senior Advisor",
"position": "",
"image": "/member_images/doan_nguyen_lam.jpg"
},
{
"name": "Trần Phạm Bảo Trân",
"name": "Đặng Chí Thành",
"role": "Platform Operations",
"image": "/member_images/tran_pham_bao_tran.jpg"
"position": "Member",
"image": "/member_images/dang_chi_thanh.jpg"
}
]
Loading