Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 23 additions & 84 deletions app/(main)/activities/page.tsx
Original file line number Diff line number Diff line change
@@ -1,106 +1,45 @@
import type { Metadata } from "next";
import { SessionsSection } from "@/components/activities/sessions-section";
import { PageHeader } from "@/components/layout/page-header";
import { activities } from "@/lib/activities";
import { getSessions } from "@/lib/data";

export const metadata: Metadata = {
title: "Activities",
description:
"정기 세션, 팀 연습, 대회 참가로 이루어진 모르고리즘의 활동을 소개합니다.",
title: "활동",
description: "정기 세션, 팀 연습, 대회 참가로 이루어진 모르고리즘의 활동을 소개합니다.",
};

const activities = [
{
number: "01",
label: "WEEKLY SESSION",
title: "정기 세션",
description:
"매주 진행되는 알고리즘 세션. 난이도별 트랙으로 나뉘어 문제를 풀고, 풀이를 공유하고 리뷰합니다.",
details: [
{ label: "주기", value: "매주" },
{ label: "형식", value: "주제별 발표와 문제풀이 리뷰" },
{ label: "주제", value: "DP, 그래프, 문자열, 수학 등" },
],
},
{
number: "02",
label: "TEAM PRACTICE",
title: "팀 연습",
description:
"ICPC 대회를 대비한 3인 1팀 연습. 실전과 동일한 환경에서 팀 커뮤니케이션과 전략을 다듬습니다.",
details: [
{ label: "주기", value: "매주 토요일" },
{ label: "구분", value: "Div 1, Div 2 구분 운영" },
{ label: "문제 셋", value: "Codeforces, AtCoder 기출 활용" },
],
},
{
number: "03",
label: "COMPETITIONS",
title: "대회 참가",
description:
"ICPC, SCPC, UCPC 등 국내외 주요 프로그래밍 대회에 참가하며 실전 경험을 쌓습니다.",
details: [{ label: "주요 대회", value: "ICPC, SUAPC, SCPC, UCPC" }],
},
];

export default function ActivitiesPage() {
const sessions = getSessions();

return (
<section className="bg-surface" id="activities">
<section id="activities">
<PageHeader
label="03 // THE CURRICULUM"
title="Activities"
labelColor="tertiary"
eyebrow="Activities"
title="활동"
description="한 학기 동안 동아리원들이 함께하는 세 가지 활동입니다."
/>

{activities.map((item, index) => (
<div
key={item.title}
className={
index % 2 === 0
? "border-t border-outline-variant/20 bg-surface px-6 py-24 md:px-12"
: "border-t border-outline-variant/20 bg-surface-container-low px-6 py-24 md:px-12"
}
>
<div className="grid grid-cols-1 items-start gap-16 lg:grid-cols-[1fr_2fr]">
<div>
<span className="mb-4 block font-headline text-7xl font-extrabold text-primary/10 md:text-8xl">
{item.number}
</span>
<span className="mb-2 block font-label text-[10px] tracking-widest text-primary">
{item.label}
</span>
<h2 className="font-headline text-3xl font-bold md:text-4xl">
{item.title}
</h2>
<div className="flex flex-col divide-y divide-border border-y border-border">
{activities.map((activity) => (
<article key={activity.slug} className="grid grid-cols-1 gap-8 px-6 py-16 md:grid-cols-[minmax(0,0.8fr)_minmax(0,1.2fr)] md:gap-16 md:px-10 md:py-24">
<div className="flex flex-col gap-3">
<span className="wide font-display text-xs font-semibold uppercase tracking-wide text-outline">{activity.eyebrow}</span>
<h2 className="text-3xl font-bold md:text-4xl">{activity.title}</h2>
</div>
<div>
<p className="mb-12 text-lg leading-relaxed text-on-surface-variant">
{item.description}
</p>
<div className="grid grid-cols-1 gap-8 sm:grid-cols-3">
{item.details.map((detail) => (
<div
key={detail.label}
className="border-l-2 border-primary/20 pl-6"
>
<p className="mb-2 font-label text-[10px] uppercase tracking-widest text-outline">
{detail.label}
</p>
<p className="text-sm font-bold text-foreground">
{detail.value}
</p>
<div className="flex flex-col gap-10">
<p className="max-w-2xl text-lg leading-relaxed text-muted-foreground">{activity.description}</p>
<dl className="grid grid-cols-1 gap-6 sm:grid-cols-3">
{activity.details.map((detail) => (
<div key={detail.label} className="flex flex-col gap-1 border-t border-border pt-4">
<dt className="text-xs text-outline">{detail.label}</dt>
<dd className="text-sm font-semibold">{detail.value}</dd>
</div>
))}
</div>
</dl>
</div>
</div>
</div>
))}

</article>
))}
</div>
<SessionsSection sessions={sessions} />
</section>
);
Expand Down
18 changes: 7 additions & 11 deletions app/(main)/awards/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,22 @@ import { PageHeader } from "@/components/layout/page-header";
import { getAwards, getAwardStats } from "@/lib/data";

export const metadata: Metadata = {
title: "Awards",
description:
"모르고리즘 동아리원들이 국내외 알고리즘 대회에서 거둔 수상 기록입니다.",
title: "수상 기록",
description: "모르고리즘 동아리원들이 국내외 알고리즘 대회에서 거둔 수상 기록입니다.",
};

export default function AwardsPage() {
const awards = getAwards();
const stats = getAwardStats();
const meta = stats.years
? `${stats.total} RECORDS // ${stats.years.min}–${stats.years.max}`
: undefined;
const meta = stats.years ? `${stats.total} records · ${stats.years.min}–${stats.years.max}` : undefined;

return (
<section className="bg-surface" id="awards">
<section id="awards">
<PageHeader
label="02 // VERIFIED STATS"
title="Awards"
labelColor="tertiary"
eyebrow="Awards"
title="수상 기록"
meta={meta}
description="ICPC, SUAPC, SCPC, UCPC 등 국내외 대회에서 모르고리즘 동아리원들이 거둔 성과입니다. 이름을 누르면 solved.ac 프로필로 이동합니다."
description="ICPC, SUAPC, SCPC, UCPC 등 국내외 대회에서 거둔 성과입니다. 이름을 누르면 solved.ac 프로필로 이동합니다."
/>
<AwardsExplorer awards={awards} competitions={stats.competitions} />
</section>
Expand Down
43 changes: 22 additions & 21 deletions app/(main)/donate/page.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,38 @@
import type { Metadata } from "next";
import { PageHeader } from "@/components/layout/page-header";
import { DonationCard } from "@/components/main/donation-card";

export const metadata: Metadata = {
title: "Donate",
title: "후원",
description: "모르고리즘 후원 안내입니다.",
};

export default function DonatePage() {
const donationAccount = process.env.DONATION_ACCOUNT?.trim();
const accountHolder =
process.env.DONATION_ACCOUNT_HOLDER?.trim() || "모르고리즘";
const accountHolder = process.env.DONATION_ACCOUNT_HOLDER?.trim() || "모르고리즘";
const contactUrl = process.env.DONATION_CONTACT_URL?.trim();

return (
<section
className="py-48 px-6 md:px-12 bg-surface flex flex-col items-center text-center"
id="donate"
>
<span className="font-label text-primary tracking-widest uppercase text-xs mb-8">
06 // SUPPORT
</span>
<h1 className="font-headline text-4xl md:text-6xl font-bold tracking-tighter mb-8">
후원 안내
</h1>
<p className="max-w-2xl text-outline text-lg leading-relaxed mb-16">
모르고리즘의 대회 참가비, 서버 운영비, 스터디 교재비 등을 후원해 주세요.
여러분의 후원이 다음 세대의 알고리즘 인재를 키웁니다.
</p>
<DonationCard
account={donationAccount}
accountHolder={accountHolder}
contactUrl={contactUrl}
<section id="donate">
<PageHeader
eyebrow="Donate"
title="후원"
description="대회 참가비, 서버 운영비, 스터디 교재비에 쓰입니다. 후원은 다음 세대의 풍선이 됩니다."
/>
<div className="grid grid-cols-1 gap-12 px-6 pb-32 md:grid-cols-[minmax(0,1fr)_420px] md:gap-20 md:px-10">
<div className="flex flex-col">
{[
{ title: "쓰이는 곳", body: "ICPC 등 대회 참가비와 교통비, 팀 연습에 쓰는 서버 운영비, 세션 교재비에 씁니다." },
{ title: "후원 방법", body: "오른쪽 계좌로 입금해 주세요. 입금자명에 이름을 남겨 주시면 감사 인사를 드립니다." },
].map((section) => (
<div key={section.title} className="grid grid-cols-1 gap-3 border-t border-border py-8 last:border-b md:grid-cols-[180px_minmax(0,1fr)] md:gap-10">
<h2 className="text-lg font-bold">{section.title}</h2>
<p className="leading-relaxed text-muted-foreground">{section.body}</p>
</div>
))}
</div>
<DonationCard account={donationAccount} accountHolder={accountHolder} contactUrl={contactUrl} />
</div>
</section>
);
}
72 changes: 25 additions & 47 deletions app/(main)/join/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import type { Metadata } from "next";
import { Clock, ExternalLink } from "lucide-react";
import { PageHeader } from "@/components/layout/page-header";
import { Button } from "@/components/ui/button";

export const metadata: Metadata = {
title: "Join",
title: "지원",
description: "모르고리즘 신입 동아리원 모집 안내입니다.",
};

Expand All @@ -26,62 +27,39 @@ export default function JoinPage() {
const joinFormUrl = process.env.JOIN_FORM_URL?.trim();

return (
<section className="bg-primary px-6 py-32 md:px-12" id="join">
<div className="grid grid-cols-1 items-start gap-24 lg:grid-cols-2">
<div className="text-primary-foreground">
<span className="mb-4 block font-label text-xs uppercase tracking-widest opacity-80">
05 // RECRUITMENT
</span>
<h1 className="mb-12 font-headline text-6xl font-black tracking-tighter md:text-8xl">
Join the
<br />
Monolith.
</h1>
<div className="max-w-lg">
{sections.map((section, index) => (
<div
key={section.title}
className={
index < sections.length - 1
? "border-b border-primary-foreground/20 py-8 first:pt-0"
: "pt-8"
}
>
<h2 className="mb-2 font-headline text-xl font-bold">
{section.title}
</h2>
<p className="opacity-80">{section.body}</p>
</div>
))}
</div>
<section id="join">
<PageHeader eyebrow="Join" title="지원" description="같이 풀 사람을 찾습니다. 서류만 내면 끝입니다." />
<div className="grid grid-cols-1 gap-12 px-6 pb-32 md:grid-cols-[minmax(0,1fr)_420px] md:gap-20 md:px-10">
<div className="flex flex-col">
{sections.map((section) => (
<div key={section.title} className="grid grid-cols-1 gap-3 border-t border-border py-8 last:border-b md:grid-cols-[180px_minmax(0,1fr)] md:gap-10">
<h2 className="text-lg font-bold">{section.title}</h2>
<p className="leading-relaxed text-muted-foreground">{section.body}</p>
</div>
))}
</div>

<div className="bg-background p-12 text-foreground shadow-2xl">
<h2 className="mb-4 font-headline text-3xl font-bold">지원하기</h2>
<p className="mb-12 text-outline">
아래 버튼을 눌러 구글폼 지원서를 작성해 주세요. 간단한 자기소개와
알고리즘 관심 분야를 적어 주시면 됩니다.
</p>
<div className="flex flex-col gap-6 self-start rounded-3xl bg-surface p-8 md:p-10">
<div className="flex flex-col gap-2">
<span className="wide font-display text-xs font-semibold uppercase tracking-wide text-primary">Apply</span>
<h2 className="text-2xl font-bold">지원서 작성</h2>
<p className="text-sm leading-relaxed text-muted-foreground">
구글폼으로 받습니다. 간단한 자기소개와 알고리즘 관심 분야를 적어 주시면 됩니다.
</p>
</div>
{joinFormUrl ? (
<Button
asChild
size="lg"
className="h-14 w-full font-headline uppercase tracking-widest"
>
<Button asChild className="h-14 rounded-full bg-foreground text-base font-semibold text-white hover:bg-foreground/90">
<a href={joinFormUrl} target="_blank" rel="noopener noreferrer">
<ExternalLink className="size-4" aria-hidden="true" />
지원서 작성
<ExternalLink className="size-4" aria-hidden="true" />
</a>
</Button>
) : (
<div className="flex min-h-14 items-center justify-center gap-2 border border-outline-variant/40 px-4 text-center font-headline text-sm font-bold uppercase tracking-widest text-outline">
<div className="flex min-h-14 items-center justify-center gap-2 rounded-full border border-border text-sm font-medium text-muted-foreground">
<Clock className="size-4 shrink-0" aria-hidden="true" />
현재 모집 기간이 아닙니다.
지금은 모집 기간이 아닙니다
</div>
)}
<p className="mt-6 text-center text-xs text-outline">
모집 기간이 아닌 경우 다음 모집 시 안내드리겠습니다.
</p>
<p className="text-xs text-outline">모집 기간이 아니면 다음 모집 때 안내드립니다.</p>
</div>
</div>
</section>
Expand Down
Loading