Skip to content

Commit d02797a

Browse files
committed
feat: 커뮤니티 소개 타임테이블 추가
1 parent 5636104 commit d02797a

8 files changed

Lines changed: 82 additions & 27 deletions

File tree

src/components/CommunityItem.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import "./CommunityItem.css";
44

55
function CommunityItem({ community }) {
66
const { i18n } = useTranslation();
7-
const isEn = i18n.language === "en";
7+
const isEn = i18n.language?.startsWith("en");
88
const name = isEn ? community.name.en : community.name.ko;
99

1010
return (

src/components/TimetableList.jsx

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,24 @@ import { Link } from 'react-router-dom';
33
import { speakerAvatars } from '../data/speakerAvatars';
44
import './TimetableList.css';
55

6-
function SessionCell({ title, speaker, code }) {
6+
function SessionCell({ title, speaker, speakerEn, code, isEn }) {
77
const avatarUrl = code ? speakerAvatars[code] : null;
8+
const speakerLabel = isEn && speakerEn != null ? speakerEn : speaker;
89

910
const body = (
1011
<div className="tt-session">
1112
<div className="tt-session-title">{title}</div>
12-
{speaker && (
13+
{speakerLabel && (
1314
<div className={`tt-session-speaker ${avatarUrl ? 'has-avatar' : ''}`}>
1415
{avatarUrl && (
1516
<img
1617
className="tt-session-avatar"
1718
src={avatarUrl}
18-
alt={speaker}
19+
alt={speakerLabel}
1920
loading="lazy"
2021
/>
2122
)}
22-
<span>{speaker}</span>
23+
<span>{speakerLabel}</span>
2324
</div>
2425
)}
2526
</div>
@@ -50,7 +51,7 @@ function TimeRange({ start, end }) {
5051

5152
function TimetableList({ sessions }) {
5253
const { i18n } = useTranslation();
53-
const isEn = i18n.language === 'en';
54+
const isEn = i18n.language?.startsWith('en');
5455

5556
const title = (row) => (isEn && row.titleEn != null ? row.titleEn : row.title);
5657
const roomTitle = (room) => (isEn && room.titleEn != null ? room.titleEn : room.title);
@@ -74,7 +75,13 @@ function TimetableList({ sessions }) {
7475
<TimeRange start={row.time} end={row.endTime} />
7576
</td>
7677
<td className="tt-td tt-cell-full">
77-
<SessionCell title={title(row)} speaker={row.speaker} code={row.code} />
78+
<SessionCell
79+
title={title(row)}
80+
speaker={row.speaker}
81+
speakerEn={row.speakerEn}
82+
code={row.code}
83+
isEn={isEn}
84+
/>
7885
</td>
7986
<td className="tt-td tt-cell-empty"></td>
8087
</tr>
@@ -88,10 +95,22 @@ function TimetableList({ sessions }) {
8895
<TimeRange start={row.time} end={row.endTime} />
8996
</td>
9097
<td className="tt-td tt-cell-session">
91-
<SessionCell title={roomTitle(row.room1)} speaker={row.room1.speaker} code={row.room1.code} />
98+
<SessionCell
99+
title={roomTitle(row.room1)}
100+
speaker={row.room1.speaker}
101+
speakerEn={row.room1.speakerEn}
102+
code={row.room1.code}
103+
isEn={isEn}
104+
/>
92105
</td>
93106
<td className="tt-td tt-cell-session">
94-
<SessionCell title={roomTitle(row.room2)} speaker={row.room2.speaker} code={row.room2.code} />
107+
<SessionCell
108+
title={roomTitle(row.room2)}
109+
speaker={row.room2.speaker}
110+
speakerEn={row.room2.speakerEn}
111+
code={row.room2.code}
112+
isEn={isEn}
113+
/>
95114
</td>
96115
</tr>
97116
);

src/data/schedule.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export const schedule = [
2020
title: '오프닝',
2121
titleEn: 'Opening',
2222
speaker: '준비위원회',
23+
speakerEn: 'Organizing Committee',
2324
},
2425
{
2526
time: '10:10',
@@ -50,6 +51,16 @@ export const schedule = [
5051
},
5152
{
5253
time: '11:50',
54+
endTime: '12:20',
55+
type: 'full',
56+
code: 'community-intro',
57+
title: '커뮤니티 소개',
58+
titleEn: 'Community Introduction',
59+
speaker: '준비위원회',
60+
speakerEn: 'Organizing Committee',
61+
},
62+
{
63+
time: '12:20',
5364
type: 'break',
5465
title: '점심 시간',
5566
titleEn: 'Lunch Break',
@@ -190,6 +201,7 @@ export function findSessionByCode(code) {
190201
title: row.title,
191202
titleEn: row.titleEn,
192203
speaker: row.speaker,
204+
speakerEn: row.speakerEn,
193205
abstract: row.abstract,
194206
tag: row.tag,
195207
time: row.time,
@@ -210,6 +222,7 @@ export function findSessionByCode(code) {
210222
title: r.title,
211223
titleEn: r.titleEn,
212224
speaker: r.speaker,
225+
speakerEn: r.speakerEn,
213226
abstract: r.abstract,
214227
time: row.time,
215228
endTime: row.endTime,

src/data/sessionDetails.js

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/locales/en/translation.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,15 @@
9797

9898
"timetableHeading": "Timetable",
9999
"timetableDesc": "May 9, 2026 (Sat) · Busan Centum Venture Town",
100+
"timetableDetailBack": "Back to timetable",
101+
"timetableDetailNotFoundTitle": "Session not found",
102+
"timetableDetailNotFoundDesc": "No information was found for the requested session code {{code}}.",
103+
"timetableDetailTime": "Time",
104+
"timetableDetailLocation": "Location",
105+
"timetableDetailSpeaker": "Speaker",
106+
"timetableDetailSessionIntro": "Session Overview",
107+
"timetableDetailSpeakerIntro": "Speaker Bio",
108+
"timetableDetailPlaceholder": "This information is not ready yet. It will be updated once confirmed.",
100109

101110
"communities": "Open Source Communities",
102111
"communitiesHeading": "Open Source Communities",

src/locales/kr/translation.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,15 @@
9797

9898
"timetableHeading": "시간표",
9999
"timetableDesc": "2026년 5월 9일 (토) · 부산 센텀벤처타운",
100+
"timetableDetailBack": "타임테이블로 돌아가기",
101+
"timetableDetailNotFoundTitle": "세션을 찾을 수 없습니다",
102+
"timetableDetailNotFoundDesc": "요청하신 세션 코드 {{code}} 에 해당하는 정보가 없습니다.",
103+
"timetableDetailTime": "시간",
104+
"timetableDetailLocation": "장소",
105+
"timetableDetailSpeaker": "발표자",
106+
"timetableDetailSessionIntro": "세션 소개",
107+
"timetableDetailSpeakerIntro": "발표자 소개",
108+
"timetableDetailPlaceholder": "해당 정보가 아직 준비되지 않았습니다. 확정되는 대로 업데이트됩니다.",
100109

101110
"communities": "오픈소스 커뮤니티",
102111
"communitiesHeading": "오픈소스 커뮤니티",

src/pages/CommunityDetail.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import "./CommunityDetail.css";
66
function CommunityDetail() {
77
const { id } = useParams();
88
const { t, i18n } = useTranslation();
9-
const isEn = i18n.language === "en";
9+
const isEn = i18n.language?.startsWith("en");
1010

1111
const community = communities.find((c) => c.id === id);
1212

src/pages/TimetableDetail.jsx

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@ import { sessionDetails } from "../data/sessionDetails";
66
import { speakerAvatars } from "../data/speakerAvatars";
77
import "./TimetableDetail.css";
88

9-
const PLACEHOLDER_TEXT =
10-
"해당 정보가 아직 준비되지 않았습니다. 확정되는 대로 업데이트됩니다.";
11-
129
function TimeRange({ start, end }) {
1310
if (!start) return <span>TBA</span>;
1411
if (!end) return <span>{start}</span>;
@@ -26,20 +23,20 @@ function pickLang(valKo, valEn, isEn) {
2623

2724
function TimetableDetail() {
2825
const { code } = useParams();
29-
const { i18n } = useTranslation();
30-
const isEn = i18n.language === "en";
26+
const { t, i18n } = useTranslation();
27+
const isEn = i18n.language?.startsWith("en");
3128
const session = findSessionByCode(code);
3229

3330
if (!session) {
3431
return (
3532
<div className="tt-detail-page">
3633
<div className="tt-detail-container">
37-
<h1 className="tt-detail-title">세션을 찾을 수 없습니다</h1>
34+
<h1 className="tt-detail-title">{t("timetableDetailNotFoundTitle")}</h1>
3835
<p className="tt-detail-abstract">
39-
요청하신 세션 코드 <code>{code}</code> 에 해당하는 정보가 없습니다.
36+
{t("timetableDetailNotFoundDesc", { code })}
4037
</p>
4138
<Link to="/timetable" className="tt-detail-back">
42-
타임테이블로 돌아가기
39+
{t("timetableDetailBack")}
4340
</Link>
4441
</div>
4542
</div>
@@ -50,7 +47,7 @@ function TimetableDetail() {
5047
const title =
5148
isEn && session.titleEn != null ? session.titleEn : session.title;
5249
const room = isEn ? session.roomEn : session.room;
53-
const speakerName = session.speaker || "TBD";
50+
const speakerName = isEn && session.speakerEn != null ? session.speakerEn : session.speaker || "TBD";
5451
const speakerInitial = speakerName.trim().slice(0, 1) || "?";
5552
const avatarUrl = speakerAvatars[code];
5653

@@ -61,7 +58,7 @@ function TimetableDetail() {
6158
<div className="tt-detail-page">
6259
<div className="tt-detail-container">
6360
<Link to="/timetable" className="tt-detail-back">
64-
타임테이블로 돌아가기
61+
{t("timetableDetailBack")}
6562
</Link>
6663

6764
<header className="tt-detail-header">
@@ -75,28 +72,30 @@ function TimetableDetail() {
7572

7673
<section className="tt-detail-meta">
7774
<div className="meta-row">
78-
<span className="meta-label">시간</span>
75+
<span className="meta-label">{t("timetableDetailTime")}</span>
7976
<span className="meta-value">
8077
<TimeRange start={session.time} end={session.endTime} />
8178
</span>
8279
</div>
8380
<div className="meta-row">
84-
<span className="meta-label">장소</span>
81+
<span className="meta-label">{t("timetableDetailLocation")}</span>
8582
<span className="meta-value">{room}</span>
8683
</div>
8784
<div className="meta-row">
88-
<span className="meta-label">발표자</span>
85+
<span className="meta-label">{t("timetableDetailSpeaker")}</span>
8986
<span className="meta-value">{speakerName}</span>
9087
</div>
9188
</section>
9289

9390
<section className="tt-detail-section">
94-
<h2 className="section-heading">세션 소개</h2>
95-
<div className="description-box">{description || PLACEHOLDER_TEXT}</div>
91+
<h2 className="section-heading">{t("timetableDetailSessionIntro")}</h2>
92+
<div className="description-box">
93+
{description || t("timetableDetailPlaceholder")}
94+
</div>
9695
</section>
9796

9897
<section className="tt-detail-section">
99-
<h2 className="section-heading">발표자 소개</h2>
98+
<h2 className="section-heading">{t("timetableDetailSpeakerIntro")}</h2>
10099
<article className="speaker-card">
101100
<div className="speaker-avatar">
102101
{avatarUrl ? (
@@ -109,7 +108,7 @@ function TimetableDetail() {
109108
</div>
110109
<div className="speaker-info">
111110
<h3 className="speaker-name">{speakerName}</h3>
112-
<p className="speaker-bio">{bio || PLACEHOLDER_TEXT}</p>
111+
<p className="speaker-bio">{bio || t("timetableDetailPlaceholder")}</p>
113112
</div>
114113
</article>
115114
</section>

0 commit comments

Comments
 (0)