Skip to content

Commit 9cc1edc

Browse files
dtinthclaude[bot]
andcommitted
เพิ่มส่วนทีมงาน (Event Staff) ลงในเว็บไซต์
- สร้าง StaffSection.astro แสดงรายชื่อทีมงานทั้งหมด - แสดงชื่อเล่น, ชื่อจริง, และบทบาทของแต่ละคน - เชื่อมโยงกับโปรไฟล์ Creatorsgarten สำหรับคนที่มี username - ใช้ Dicebear avatar สำหรับคนที่ไม่มี username - จัดเรียงบทบาทตามตัวอักษร โดยให้ Lead Organizer อยู่ด้านบน - เพิ่ม tooltip แสดงรายละเอียดบทบาทเมื่อ hover - อัปเดตเมนูนำทาง: เพิ่ม Staff หลัง Sponsors, ลบ What to Bring - วางส่วน Staff ก่อน Venue ในหน้าเว็บ Co-authored-by: Claude <209825114+claude[bot]@users.noreply.github.com>
1 parent b3cf1be commit 9cc1edc

4 files changed

Lines changed: 566 additions & 8 deletions

File tree

src/components/Header.astro

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,9 @@ import logotype from "../assets/logotype.svg?url";
103103
<a href="#about" class="nav-pill mr-2"> About </a>
104104
<a href="#venue" class="nav-pill mr-2"> Venue </a>
105105
<a href="#agenda" class="nav-pill mr-2"> Agenda </a>
106-
<a href="#what-to-bring" class="nav-pill mr-2"> What to Bring </a>
107106
<a href="#code-of-conduct" class="nav-pill mr-2"> Code of Conduct </a>
108-
<a href="#sponsors" class="nav-pill mr-4"> Sponsors </a>
107+
<a href="#sponsors" class="nav-pill mr-2"> Sponsors </a>
108+
<a href="#staff" class="nav-pill mr-4"> Staff </a>
109109
<a href="#projects" class="nav-pill-solid">
110110
<span>Projects</span>
111111
<div
@@ -178,12 +178,6 @@ import logotype from "../assets/logotype.svg?url";
178178
>
179179
Agenda
180180
</a>
181-
<a
182-
href="#what-to-bring"
183-
class="mobile-nav-link block text-white text-lg font-medium hover:text-gray-300"
184-
>
185-
What to Bring
186-
</a>
187181
<a
188182
href="#code-of-conduct"
189183
class="mobile-nav-link block text-white text-lg font-medium hover:text-gray-300"
@@ -196,6 +190,12 @@ import logotype from "../assets/logotype.svg?url";
196190
>
197191
Sponsors
198192
</a>
193+
<a
194+
href="#staff"
195+
class="mobile-nav-link block text-white text-lg font-medium hover:text-gray-300"
196+
>
197+
Staff
198+
</a>
199199
</div>
200200

201201
<div class="mt-8">

src/components/StaffSection.astro

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
---
2+
import { staffs, websiteRoles } from "../data/staff";
3+
4+
// Create a map of role IDs to role names for easy lookup
5+
const roleMap = new Map(websiteRoles.map(role => [role.id, role]));
6+
7+
// Function to get role names for a staff member
8+
function getStaffRoles(roleIds: number[]) {
9+
// Get unique role IDs to avoid duplicates
10+
const uniqueRoleIds = [...new Set(roleIds)];
11+
const roles = uniqueRoleIds
12+
.map(id => roleMap.get(id))
13+
.filter(role => role !== undefined)
14+
.map(role => role!.name);
15+
16+
// Sort alphabetically but put "Lead Organizer" first
17+
return roles.sort((a, b) => {
18+
if (a === "Lead Organizer") return -1;
19+
if (b === "Lead Organizer") return 1;
20+
return a.localeCompare(b);
21+
});
22+
}
23+
24+
// Function to generate Creatorsgarten profile URL
25+
function getProfileUrl(username: string) {
26+
return `https://creatorsgarten.org/wiki/People/${username}`;
27+
}
28+
29+
// Function to generate Creatorsgarten avatar URL
30+
function getAvatarUrl(username: string) {
31+
return `https://creatorsgarten.org/api/users/@${username}/picture`;
32+
}
33+
34+
// Function to generate fallback avatar URL
35+
function getFallbackAvatarUrl(nickname: string) {
36+
return `https://api.dicebear.com/6.x/bottts-neutral/svg?seed=${encodeURIComponent(nickname)}`;
37+
}
38+
---
39+
40+
<section
41+
id="staff"
42+
class="w-full bg-gradient-to-br from-[#05232e] to-[#05204E] text-white pt-24 pb-16"
43+
>
44+
<div class="max-w-6xl mx-auto px-8">
45+
<h2
46+
class="text-4xl md:text-7xl text-white mb-6 text-center tracking-wide font-display scroll-animate fade-down"
47+
>
48+
EVENT STAFF
49+
</h2>
50+
51+
<div
52+
class="inline-block text-white px-6 py-3 rounded-lg mb-12 text-xl md:text-2xl font-medium transform -rotate-1 bg-[#19806f] scroll-animate bounce-up stagger-1 mx-auto block text-center"
53+
style="font-family: 'K2D', sans-serif;"
54+
>
55+
ทีมงานแห่งความเพี้ยน 🎭
56+
</div>
57+
58+
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-6 max-w-6xl mx-auto">
59+
{
60+
staffs.map((staff, index) => {
61+
const roles = getStaffRoles(staff.websiteRoleIds);
62+
const hasUsername = staff.username && staff.username.trim() !== "";
63+
64+
return (
65+
<div
66+
class={`bg-gray-900 rounded-xl p-6 border border-gray-800 hover:border-[#19806f] transition-all duration-300 scroll-animate fade-up stagger-${index + 2}`}
67+
>
68+
{/* Avatar + Names Row */}
69+
<div class="flex items-center gap-4 mb-4">
70+
{/* Avatar - always show */}
71+
<div class="flex-shrink-0">
72+
{hasUsername ? (
73+
<a
74+
href={getProfileUrl(staff.username!)}
75+
target="_blank"
76+
rel="noopener noreferrer"
77+
class="block"
78+
>
79+
<img
80+
src={getAvatarUrl(staff.username!)}
81+
alt={staff.name}
82+
class="w-16 h-16 rounded-full bg-gray-800 object-cover hover:opacity-80 transition-opacity"
83+
/>
84+
</a>
85+
) : (
86+
<img
87+
src={getFallbackAvatarUrl(staff.nickname)}
88+
alt={staff.name}
89+
class="w-16 h-16 rounded-full bg-gray-800 object-cover"
90+
/>
91+
)}
92+
</div>
93+
94+
{/* Names */}
95+
<div class="flex-1 min-w-0">
96+
{/* Nickname - prominently displayed */}
97+
{hasUsername ? (
98+
<a
99+
href={getProfileUrl(staff.username!)}
100+
target="_blank"
101+
rel="noopener noreferrer"
102+
class="text-white font-bold text-lg hover:text-[#19806f] transition-colors block"
103+
style="font-family: 'K2D', sans-serif;"
104+
>
105+
{staff.nickname}
106+
</a>
107+
) : (
108+
<h3
109+
class="text-white font-bold text-lg"
110+
style="font-family: 'K2D', sans-serif;"
111+
>
112+
{staff.nickname}
113+
</h3>
114+
)}
115+
116+
{/* Full Name */}
117+
<p class="text-[#19806f] font-medium text-sm mt-1">
118+
{staff.name}
119+
</p>
120+
</div>
121+
</div>
122+
123+
{/* Roles Row */}
124+
{roles.length > 0 && (
125+
<div class="flex flex-wrap gap-1">
126+
{roles.map((roleName) => {
127+
const roleDetails = roleMap.get(websiteRoles.find(r => r.name === roleName)?.id);
128+
return (
129+
<span
130+
class="inline-block px-2 py-0.5 bg-gray-800 text-gray-300 text-xs rounded hover:bg-gray-700 transition-colors cursor-help"
131+
title={roleDetails?.description || roleName}
132+
>
133+
{roleName}
134+
</span>
135+
);
136+
})}
137+
</div>
138+
)}
139+
</div>
140+
);
141+
})
142+
}
143+
</div>
144+
145+
{/* Thank you message */}
146+
<div class="mt-16 bg-[#19806f]/10 border border-[#19806f]/30 rounded-xl p-8 text-center scroll-animate fade-up">
147+
<iconify-icon icon="mdi:heart" class="text-[#19806f] text-4xl mb-4 block"></iconify-icon>
148+
<h3 class="text-2xl font-bold mb-4 text-white font-subhead">Thank You to Our Amazing Team!</h3>
149+
<p class="text-gray-300 leading-relaxed max-w-3xl mx-auto">
150+
This hackathon wouldn't be possible without the incredible dedication and hard work of our volunteer staff.
151+
From organizing logistics to creating the perfect atmosphere for creativity, each person contributed their unique skills
152+
to make Stupido Hackettino #9 a wonderfully weird success! 🎉
153+
</p>
154+
</div>
155+
</div>
156+
</section>

0 commit comments

Comments
 (0)