Skip to content

Commit 63061a7

Browse files
authored
Merge pull request #6 from pythonkr/feat/main-page-and-communities
feat: 메인 페이지 개편 + 푸터 주관/주최 + 오픈소스 커뮤니티 페이지
2 parents 47130e7 + 76a8795 commit 63061a7

23 files changed

Lines changed: 574 additions & 442 deletions

src/App.jsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { HashRouter as Router, Routes, Route, useLocation } from 'react-router-d
33

44
import Navbar from './components/Navbar';
55
import { trackPageView } from './lib/analytics';
6-
import Home from './pages/Home';
76
import Timetable from './pages/Timetable';
87
import TimetableDetail from './pages/TimetableDetail';
98
import Team from './pages/Team';
@@ -19,6 +18,8 @@ import Session from './pages/Session';
1918
import Prospectus from './pages/Prospectus';
2019
import Patrons from './pages/Patrons';
2120
import Tickets from './pages/Tickets';
21+
import Communities from './pages/Communities';
22+
import CommunityDetail from './pages/CommunityDetail';
2223
import Footer from './components/Footer';
2324
import Goods from './pages/Goods';
2425
import './i18n';
@@ -41,8 +42,7 @@ function App() {
4142

4243
<main>
4344
<Routes>
44-
<Route path="/" element={<Home />} />
45-
<Route path="/pyconbusan" element={<PyConBusan />} />
45+
<Route path="/" element={<PyConBusan />} />
4646
<Route path="/safety" element={<Safety />} />
4747
<Route path="/conduct" element={<Conduct />} />
4848
<Route path="/volunteer" element={<Volunteer />} />
@@ -58,6 +58,8 @@ function App() {
5858
<Route path="/prospectus" element={<Prospectus />} />
5959
<Route path="/patrons" element={<Patrons />} />
6060
<Route path="/tickets" element={<Tickets />} />
61+
<Route path="/communities" element={<Communities />} />
62+
<Route path="/communities/:id" element={<CommunityDetail />} />
6163
</Routes>
6264
</main>
6365

src/components/CommunityItem.css

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
.community-item {
2+
display: flex;
3+
flex-direction: column;
4+
align-items: center;
5+
text-align: center;
6+
gap: 16px;
7+
padding: 28px 20px;
8+
background: rgba(255, 255, 255, 0.08);
9+
border: 1px solid rgba(255, 255, 255, 0.15);
10+
border-radius: 14px;
11+
text-decoration: none;
12+
color: inherit;
13+
transition: transform 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
14+
}
15+
16+
.community-item:hover {
17+
transform: translateY(-4px);
18+
box-shadow: 0 12px 28px rgba(0, 0, 0, 0.25);
19+
background: rgba(255, 255, 255, 0.12);
20+
}
21+
22+
.community-logo {
23+
width: 96px;
24+
height: 96px;
25+
object-fit: contain;
26+
background: #ffffff;
27+
border-radius: 50%;
28+
padding: 12px;
29+
}
30+
31+
.community-logo-placeholder {
32+
display: flex;
33+
align-items: center;
34+
justify-content: center;
35+
font-size: 2.4rem;
36+
font-weight: 700;
37+
color: #764ba2;
38+
padding: 0;
39+
}
40+
41+
.community-name {
42+
font-size: 1.05rem;
43+
font-weight: 600;
44+
color: #ffffff;
45+
margin: 0;
46+
line-height: 1.4;
47+
}

src/components/CommunityItem.jsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { Link } from "react-router-dom";
2+
import { useTranslation } from "react-i18next";
3+
import "./CommunityItem.css";
4+
5+
function CommunityItem({ community }) {
6+
const { i18n } = useTranslation();
7+
const isEn = i18n.language === "en";
8+
const name = isEn ? community.name.en : community.name.ko;
9+
10+
return (
11+
<Link to={`/communities/${community.id}`} className="community-item">
12+
{community.logo ? (
13+
<img src={community.logo} alt={name} className="community-logo" />
14+
) : (
15+
<div className="community-logo community-logo-placeholder">
16+
{name.charAt(0)}
17+
</div>
18+
)}
19+
<h3 className="community-name">{name}</h3>
20+
</Link>
21+
);
22+
}
23+
24+
export default CommunityItem;

src/components/CommunityList.css

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
.community-list {
2+
display: grid;
3+
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
4+
gap: 24px;
5+
margin-top: 30px;
6+
}
7+
8+
@media (max-width: 768px) {
9+
.community-list {
10+
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
11+
gap: 16px;
12+
}
13+
}

src/components/CommunityList.jsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import CommunityItem from "./CommunityItem";
2+
import "./CommunityList.css";
3+
4+
function CommunityList({ communities }) {
5+
return (
6+
<div className="community-list">
7+
{communities.map((c) => (
8+
<CommunityItem key={c.id} community={c} />
9+
))}
10+
</div>
11+
);
12+
}
13+
14+
export default CommunityList;

src/components/Footer.css

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
.footer {
22
background: linear-gradient(135deg, #9e3d5c 0%, #7a2d48 100%);
33
color: white;
4-
padding: 40px 20px;
4+
padding: 20px 20px 40px;
55
text-align: center;
66
}
77

@@ -82,4 +82,77 @@
8282
margin-top: 8px;
8383
font-size: 0.7rem;
8484
opacity: 0.6;
85+
}
86+
87+
.footer-hosts {
88+
display: flex;
89+
flex-direction: column;
90+
gap: 14px;
91+
padding-bottom: 14px;
92+
margin-bottom: 14px;
93+
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
94+
}
95+
96+
.footer-hosts-row {
97+
display: flex;
98+
align-items: center;
99+
justify-content: center;
100+
gap: 16px;
101+
flex-wrap: wrap;
102+
}
103+
104+
.footer-hosts-label {
105+
font-size: 1.4rem;
106+
font-weight: 700;
107+
letter-spacing: 0.05em;
108+
opacity: 0.95;
109+
min-width: 120px;
110+
text-align: right;
111+
}
112+
113+
.footer-hosts-logos {
114+
display: flex;
115+
gap: 12px;
116+
flex-wrap: wrap;
117+
justify-content: center;
118+
}
119+
120+
.footer-logo {
121+
display: inline-flex;
122+
align-items: center;
123+
justify-content: center;
124+
height: 112px;
125+
padding: 16px 28px;
126+
background: #ffffff;
127+
border-radius: 6px;
128+
}
129+
130+
.footer-logo img {
131+
height: 100%;
132+
width: auto;
133+
max-width: 440px;
134+
object-fit: contain;
135+
display: block;
136+
}
137+
138+
@media (max-width: 768px) {
139+
.footer-hosts-row {
140+
flex-direction: column;
141+
gap: 8px;
142+
}
143+
144+
.footer-hosts-label {
145+
text-align: center;
146+
min-width: auto;
147+
font-size: 1.2rem;
148+
}
149+
150+
.footer-logo {
151+
height: 88px;
152+
padding: 12px 20px;
153+
}
154+
155+
.footer-logo img {
156+
max-width: 320px;
157+
}
85158
}

src/components/Footer.jsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import {
99
} from "react-icons/fa";
1010
import { FaXTwitter } from "react-icons/fa6";
1111
import { useTranslation } from "react-i18next";
12+
import hostBusanLogo from "../images/host-busan.png";
13+
import hostPythonKrLogo from "../images/host-pythonkr.png";
14+
import organizerBipaLogo from "../images/organizer-bipa.png";
1215

1316
const Footer = () => {
1417
const { t } = useTranslation();
@@ -17,6 +20,24 @@ const Footer = () => {
1720
<footer className="footer">
1821
<div className="footer-container">
1922

23+
{/* Hosts & Organizers */}
24+
<div className="footer-hosts">
25+
<div className="footer-hosts-row">
26+
<span className="footer-hosts-label">{t("hostsOrganizers")}</span>
27+
<div className="footer-hosts-logos">
28+
<div className="footer-logo">
29+
<img src={hostBusanLogo} alt={t("hostBusanCity")} />
30+
</div>
31+
<div className="footer-logo">
32+
<img src={organizerBipaLogo} alt={t("organizerBipa")} />
33+
</div>
34+
<div className="footer-logo">
35+
<img src={hostPythonKrLogo} alt={t("hostPythonKorea")} />
36+
</div>
37+
</div>
38+
</div>
39+
</div>
40+
2041
{/* Organization */}
2142
<h3 className="footer-title">{t("footerOrgName")}</h3>
2243

0 commit comments

Comments
 (0)