feat(members,header): overhaul members page with CV dialog and english-ify navigation

- Rewrite Members page to English: LAB MEMBERS, Prof. Seok-Joo Koh, Active Researchers, and Graduates
- Add ProfessorDetailsDialog component with comprehensive CV modal
- Standardize degree course label mappings (Ph. D., M. S.)
- Translate mobile navigation panel and header aria-labels to English
- Update E2E test suite assertions for the updated members structure
This commit is contained in:
2026-08-21 23:16:06 +09:00
parent 8eabd7a2db
commit 44c21ab59e
5 changed files with 337 additions and 79 deletions
@@ -0,0 +1,179 @@
"use client";
import React, { useRef } from "react";
// CUSTOMIZATION HOOK: Detailed career & background data for Prof. Seok-Joo Koh
const EDUCATION = [
"KAIST, Management Science, B. S., 1992. 2.",
"KAIST, Management Science, M. S., 1994. 2.",
"KAIST, Industrial Engineering, Ph. D., 1998. 8.",
];
const CAREER = [
{
period: "2024. 3 - Present",
role: "Dean",
org: "College of IT Engineering (CITE)",
inst: "Kyungpook National University (KNU)",
},
{
period: "2015. 12 - Present",
role: "Director",
org: "Institute of Software Education (SWEDU)",
inst: "Kyungpook National University (KNU)",
},
{
period: "2004. 3 - Present",
role: "Professor",
org: "School of Computer Science and Engineering (CSE), College of IT Engineering (CITE)",
inst: "Kyungpook National University (KNU)",
},
{
period: "1998. 8 - 2004. 2",
role: "Senior Researcher",
org: "Protocol Engineering Center (PEC)",
inst: "Electronics Telecommunications Research Institute (ETRI)",
},
];
const STANDARDIZATION = [
"ISO/IEC JTC1 SC6/WG7: Reliable/Mobile Multicasting (1999 ~ 2019): Project Editor",
"ISO/IEC JTC1 SC41/WG5: Internet-of-Things (IoT) Applications (2020 ~ Present): Project Editor",
"ITU-T SG13: Mobility Management (1999 ~ 2015): Project Editor",
"ITU-T SG20: VLC-based IoT (2018 ~ 2020): Project Editor",
"IEC TC100: Multimedia Systems and Equipment (2018 ~ Present): Project Editor, TA15 TAM, WG11 Convenor",
];
const MEMBERSHIPS = [
"KIPS (Korea Information Processing Society)",
"KICS (Korean Institute of Communications and Information Sciences)",
"KIISE (Korean Institute of Information Scientists and Engineers)",
"IEEE (Institute of Electrical and Electronics Engineers)",
];
export function ProfessorDetailsDialog() {
const dialogRef = useRef<HTMLDialogElement>(null);
const handleOpen = () => {
dialogRef.current?.showModal();
};
const handleClose = () => {
dialogRef.current?.close();
};
const handleBackdropClick = (e: React.MouseEvent<HTMLDialogElement>) => {
if (e.target === dialogRef.current) {
dialogRef.current?.close();
}
};
return (
<>
<button
type="button"
onClick={handleOpen}
className="inline-flex items-center gap-1 font-mono text-xs font-semibold text-cobalt-dark hover:underline focus:outline-none focus:ring-1 focus:ring-cobalt-dark rounded"
aria-haspopup="dialog"
>
<span>Details </span>
</button>
<dialog
ref={dialogRef}
aria-labelledby="prof-dialog-title"
onClick={handleBackdropClick}
className="bg-paper text-ink border border-line rounded-lg p-0 max-w-2xl w-[92vw] max-h-[85vh] max-h-[85dvh] backdrop:bg-ink/50 backdrop:backdrop-blur-sm open:flex open:flex-col shadow-2xl m-auto"
>
{/* Modal Header */}
<div className="flex items-center justify-between border-b border-line p-6 bg-paper sticky top-0 z-10">
<div>
<span className="font-mono text-xs text-cobalt-dark uppercase tracking-wider font-bold">
Curriculum Vitae
</span>
<h2
id="prof-dialog-title"
className="font-serif text-2xl font-normal text-ink mt-0.5"
>
Prof. Seok-Joo Koh
</h2>
</div>
<button
type="button"
onClick={handleClose}
aria-label="Close dialog"
className="p-1.5 rounded border border-line hover:bg-ivory text-ink-mute hover:text-ink transition-colors font-mono text-xs"
>
Close
</button>
</div>
{/* Modal Scrollable Content */}
<div className="p-6 sm:p-8 space-y-8 overflow-y-auto overscroll-contain text-sm">
{/* Education */}
<section className="space-y-3">
<h3 className="font-mono text-xs font-bold uppercase tracking-wider text-cobalt-dark border-b border-line pb-1.5">
Education
</h3>
<ul className="space-y-2 text-ink/90 font-sans">
{EDUCATION.map((edu, idx) => (
<li key={idx} className="flex items-start gap-2.5">
<span className="inline-block w-1.5 h-1.5 rounded-full bg-cobalt-dark mt-2 shrink-0"></span>
<span>{edu}</span>
</li>
))}
</ul>
</section>
{/* Career */}
<section className="space-y-3">
<h3 className="font-mono text-xs font-bold uppercase tracking-wider text-cobalt-dark border-b border-line pb-1.5">
Career
</h3>
<div className="space-y-4">
{CAREER.map((car, idx) => (
<div key={idx} className="border-l-2 border-line pl-3 space-y-0.5">
<div className="font-mono text-xs text-ink-mute">{car.period}</div>
<div className="font-medium text-ink">
{car.role} · <span className="text-ink-mute font-normal">{car.org}</span>
</div>
<div className="text-xs text-ink-soft">{car.inst}</div>
</div>
))}
</div>
</section>
{/* International Standardization */}
<section className="space-y-3">
<h3 className="font-mono text-xs font-bold uppercase tracking-wider text-cobalt-dark border-b border-line pb-1.5">
International Standardization
</h3>
<ul className="space-y-2.5 text-ink/90 font-sans">
{STANDARDIZATION.map((std, idx) => (
<li key={idx} className="flex items-start gap-2.5 leading-relaxed">
<span className="inline-block w-1.5 h-1.5 rounded-full bg-cobalt-dark mt-2 shrink-0"></span>
<span>{std}</span>
</li>
))}
</ul>
</section>
{/* Membership on Academic Society */}
<section className="space-y-3">
<h3 className="font-mono text-xs font-bold uppercase tracking-wider text-cobalt-dark border-b border-line pb-1.5">
Membership on Academic Society
</h3>
<ul className="grid grid-cols-1 sm:grid-cols-2 gap-2 text-ink/90 font-sans">
{MEMBERSHIPS.map((mem, idx) => (
<li key={idx} className="flex items-start gap-2">
<span className="inline-block w-1.5 h-1.5 rounded-full bg-cobalt-dark mt-2 shrink-0"></span>
<span>{mem}</span>
</li>
))}
</ul>
</section>
</div>
</dialog>
</>
);
}