diff --git a/notion_cache.json b/notion_cache.json index 95636a4..72b5553 100644 --- a/notion_cache.json +++ b/notion_cache.json @@ -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"} \ No newline at end of file +{"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"} \ No newline at end of file diff --git a/public/member_images/doan_quoc_an.jpg b/public/member_images/doan_quoc_an.jpg index 87b4a2c..95e591f 100644 Binary files a/public/member_images/doan_quoc_an.jpg and b/public/member_images/doan_quoc_an.jpg differ diff --git a/scripts/fetch-members.py b/scripts/fetch-members.py index e6d618d..357127c 100644 --- a/scripts/fetch-members.py +++ b/scripts/fetch-members.py @@ -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}", @@ -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 }) diff --git a/src/App.js b/src/App.js index bac4c83..9ccd8b1 100644 --- a/src/App.js +++ b/src/App.js @@ -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]) { @@ -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; @@ -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()); @@ -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({ @@ -189,12 +193,10 @@ function App() { }); } - // Set initial visibility with a small delay const timer = setTimeout(() => { setIsVisible(true); }, 100); - // Cleanup function return () => { clearTimeout(timer); }; @@ -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", }} > @@ -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%", }} @@ -726,13 +728,19 @@ function App() { alignItems: "center", }} > +
- {member.name} -
++ {member.name} +
+ + {/* Position added */} + {member.position && ( + + {member.position} + + )} +