Skip to content
This repository was archived by the owner on Jul 3, 2026. It is now read-only.

Commit 4e7c566

Browse files
committed
feat: 반응형 디자인
1 parent a0630e9 commit 4e7c566

26 files changed

Lines changed: 727 additions & 111 deletions

‎package.json‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
"dependencies": {
1212
"@hookform/resolvers": "^5.0.1",
1313
"@primer/octicons-react": "^19.15.1",
14+
"@radix-ui/react-dialog": "^1.1.14",
1415
"@tailwindcss/postcss": "^4.0.16",
16+
"class-variance-authority": "^0.7.1",
1517
"date-fns": "^4.1.0",
1618
"framer-motion": "^12.6.3",
1719
"iconsax-react": "^0.0.8",
@@ -26,6 +28,7 @@
2628
"tailwind-merge": "^3.1.0",
2729
"tailwind-scrollbar": "^4.0.2",
2830
"tailwindcss": "^4.0.16",
31+
"tw-animate-css": "^1.3.0",
2932
"zod": "^3.24.4",
3033
"zustand": "^5.0.3"
3134
},

‎pnpm-lock.yaml‎

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

‎src/app/[id]/_component/table-container.tsx‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export default function TableContainer({ handleDragEnd, children }: TableContain
1111
return (
1212
<div className="relative mt-4 flex overflow-y-auto" onMouseUp={handleDragEnd}>
1313
{/*왼쪽 시간 라벨*/}
14-
<div className="relative w-28">
14+
<div className="relative w-16">
1515
{Array.from({ length: endHour - startHour + 1 }, (_, i) => (
1616
<div
1717
key={i}
@@ -24,7 +24,10 @@ export default function TableContainer({ handleDragEnd, children }: TableContain
2424
</div>
2525

2626
<div className="relative flex-1">
27-
<div className="relative z-10 grid grid-cols-5" style={{ height: `${totalHeight}px` }}>
27+
<div
28+
className="relative z-10 grid min-[0px]:grid-cols-1 min-[420px]:grid-cols-2 min-[570px]:grid-cols-3 min-[768px]:grid-cols-2 min-[918px]:grid-cols-3 min-[1068px]:grid-cols-4 min-[1218px]:grid-cols-4"
29+
style={{ height: `${totalHeight}px` }}
30+
>
2831
{children}
2932
</div>
3033
</div>

‎src/app/[id]/_component/table-summary.tsx‎

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { useMemo } from 'react';
1+
import { useEffect, useMemo, useState } from 'react';
22

33
import { RedirectType, redirect } from 'next/navigation';
44

55
import { RoomResponse } from '@/api/dto/room';
6-
import { nowExcludeTime } from '@/util';
6+
import { getGridCols, nowExcludeTime } from '@/util';
77
import { formatDate } from 'date-fns';
88
import { MoveLeft } from 'lucide-react';
99
import { twMerge } from 'tailwind-merge';
@@ -16,6 +16,15 @@ interface TableSummaryProps {
1616

1717
export default function TableSummary({ date, dates, room }: TableSummaryProps) {
1818
const today = useMemo(nowExcludeTime, []);
19+
const [cols, setCols] = useState(() =>
20+
getGridCols(typeof window !== 'undefined' ? window.innerWidth : 1200),
21+
);
22+
23+
useEffect(() => {
24+
const onResize = () => setCols(getGridCols(window.innerWidth));
25+
window.addEventListener('resize', onResize);
26+
return () => window.removeEventListener('resize', onResize);
27+
}, []);
1928

2029
return (
2130
<div className="flex flex-col gap-3 rounded-t-2xl">
@@ -37,28 +46,30 @@ export default function TableSummary({ date, dates, room }: TableSummaryProps) {
3746
</div>
3847

3948
<div className="flex">
40-
<div className="min-w-28" />
41-
{dates.map((date) => (
42-
<div key={date.getTime()} className="flex w-full flex-col items-center gap-1">
43-
<div
44-
className={twMerge(
45-
'text-xs font-bold text-zinc-500',
46-
today.getTime() === date.getTime() && 'text-classpick-500',
47-
)}
48-
>
49-
{formatDate(date, 'E').toUpperCase()}
50-
</div>
49+
<div className="min-w-16" />
50+
<div className="grid flex-1 min-[0px]:grid-cols-1 min-[420px]:grid-cols-2 min-[570px]:grid-cols-3 min-[768px]:grid-cols-2 min-[918px]:grid-cols-3 min-[1068px]:grid-cols-4 min-[1218px]:grid-cols-4">
51+
{dates.slice(0, cols).map((date) => (
52+
<div key={date.getTime()} className="flex w-full flex-col items-center gap-1">
53+
<div
54+
className={twMerge(
55+
'text-xs font-bold text-zinc-500',
56+
today.getTime() === date.getTime() && 'text-classpick-500',
57+
)}
58+
>
59+
{formatDate(date, 'E').toUpperCase()}
60+
</div>
5161

52-
<span
53-
className={twMerge(
54-
'flex size-11 items-center justify-center text-2xl font-bold text-neutral-700',
55-
today.getTime() === date.getTime() && 'bg-classpick-500 rounded-full text-white',
56-
)}
57-
>
58-
{date.getDate()}
59-
</span>
60-
</div>
61-
))}
62+
<span
63+
className={twMerge(
64+
'flex size-11 items-center justify-center text-2xl font-bold text-neutral-700',
65+
today.getTime() === date.getTime() && 'bg-classpick-500 rounded-full text-white',
66+
)}
67+
>
68+
{date.getDate()}
69+
</span>
70+
</div>
71+
))}
72+
</div>
6273
</div>
6374
</div>
6475
);

‎src/app/[id]/page.tsx‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { DailyReservation, RoomResponse } from '@/api/dto/room';
1919
import useTimetableDrag from '@/hook/timetable/drag';
2020
import { useApi } from '@/hook/use-api';
2121
import { useFilterStore } from '@/store/filter.store';
22+
import { getGridCols } from '@/util';
2223
import { eachDayOfInterval, endOfWeek, format, isSameDay, parse, startOfWeek } from 'date-fns';
2324

2425
interface Props {
@@ -37,6 +38,10 @@ export default function Page({ params }: Props) {
3738
const { date: _date } = useFilterStore();
3839
const date = useMemo(() => _date || new Date(), [_date]);
3940

41+
const [cols, setCols] = useState(() =>
42+
getGridCols(typeof window !== 'undefined' ? window.innerWidth : 1200),
43+
);
44+
4045
const {
4146
isDragging,
4247
dragStart,
@@ -79,13 +84,19 @@ export default function Page({ params }: Props) {
7984
});
8085
}, [roomId]);
8186

87+
useEffect(() => {
88+
const onResize = () => setCols(getGridCols(window.innerWidth));
89+
window.addEventListener('resize', onResize);
90+
return () => window.removeEventListener('resize', onResize);
91+
}, []);
92+
8293
if (isApiProcessing || !room || !reservations) return null;
8394

8495
return (
85-
<div className="flex max-h-[calc(100dvh-80px-32px)] w-full flex-col rounded-2xl bg-white p-4">
96+
<div className="flex max-h-[calc(100dvh-80px-32px)] min-h-[calc(100dvh-64px)] w-full flex-col bg-white p-4 md:rounded-2xl">
8697
<TableSummary date={date} dates={dates} room={room} />
8798
<TableContainer handleDragEnd={handleDragEnd}>
88-
{dates.map((date) => (
99+
{dates.slice(0, cols).map((date) => (
89100
<div key={date.getTime()} className="relative">
90101
<TableCurrentBar date={date} />
91102

‎src/app/auth/layout.tsx‎

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,32 @@
22

33
import { ReactNode } from 'react';
44

5-
import { useRouter } from 'next/navigation';
6-
75
import { BottomCloud, TopCloud } from '@/app/auth/_component/cloud';
86
import { IconDescription } from '@/app/auth/_component/icon-description';
97
import OnboardImage from '@/app/auth/_component/onboard-image';
108

119
import { KeySquare, Pointer } from 'iconsax-react';
12-
import { Magnet, Undo2 } from 'lucide-react';
10+
import { Magnet } from 'lucide-react';
1311

1412
interface LayoutProps {
1513
children: ReactNode;
1614
}
1715

1816
export default function Layout({ children }: LayoutProps) {
19-
const router = useRouter();
20-
2117
return (
2218
<div className="relative h-[100dvh] w-full overflow-x-clip">
2319
<TopCloud className="absolute top-0 left-0 w-[700px]" />
2420
<BottomCloud className="absolute -right-4 bottom-0 w-[700px]" />
2521

2622
<div className="absolute z-10 flex h-full w-full items-center justify-center">
27-
<div className="grid max-w-[1200px] grid-cols-2 rounded-2xl bg-white/70">
23+
<div className="max-w-[1200px] grid-cols-2 rounded-2xl bg-white/70 lg:grid">
2824
<section
29-
className="m-2 flex flex-col gap-18 rounded-2xl px-6 py-9"
25+
className="m-2 hidden flex-col gap-18 rounded-2xl px-6 pt-20 pb-10 lg:flex"
3026
style={{
3127
background:
3228
'linear-gradient(155deg, #4E51FF 4.98%, #7070F9 21.56%, #9C97F1 42.63%, rgba(61, 162, 255, 0.20) 86.1%, rgba(61, 162, 255, 0.11) 98.2%)',
3329
}}
3430
>
35-
<div
36-
className="subtitle2-pretendard flex cursor-pointer items-center gap-2 text-white"
37-
onClick={router.back}
38-
>
39-
<Undo2 />
40-
<p>뒤로 돌아가기</p>
41-
</div>
42-
4331
<div className="flex flex-col gap-10 px-8">
4432
<h1 className="font-nanum text-3xl leading-12 font-extrabold text-white">
4533
카페 도서관 눈치게임은 그만,
@@ -68,7 +56,7 @@ export default function Layout({ children }: LayoutProps) {
6856
<OnboardImage className="w-[370px] self-center" />
6957
</section>
7058

71-
<section className="flex flex-col gap-10 px-28 py-12">
59+
<section className="flex flex-col gap-10 px-10 py-12 md:px-28">
7260
<p className="font-work-sans text-classpick-500 text-2xl font-black tracking-[-1.5px]">
7361
ClassPick
7462
</p>

‎src/app/client-layout.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export default function Layout({ children }: LayoutProps) {
7373
) : (
7474
<NuqsAdapter>
7575
<Header />
76-
<main className="flex gap-3.5 p-4">
76+
<main className="flex gap-3.5 md:p-4">
7777
<SideBar />
7878
{children}
7979
</main>

‎src/app/error.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ interface Props {
1212

1313
export default function Page({ reset }: Props) {
1414
return (
15-
<div className="flex w-full flex-col items-center justify-center gap-4 rounded-2xl bg-white p-4">
15+
<div className="flex h-[100dvh] w-full flex-col items-center justify-center gap-4 bg-white p-4">
1616
<h1 className="text-8xl font-bold">500</h1>
1717
<h2 className="text-2xl font-bold">오류가 발생했습니다</h2>
1818
<p className="text-neutral-500">페이지를 불러오던 중 오류가 발생했습니다.</p>

‎src/app/my-page/_component/info-card/index.tsx‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export default function InfoCard({ reservations }: InfoCardProps) {
3333
if (!user) return null;
3434

3535
return (
36-
<div className="flex flex-col gap-9 rounded-2xl bg-white p-6">
36+
<div className="flex flex-col gap-9 rounded-b-2xl bg-white p-6 md:rounded-2xl">
3737
<section className="flex justify-between">
3838
<button
3939
className="border-classpick-500 w-fit cursor-pointer rounded-full border p-2"
@@ -49,7 +49,7 @@ export default function InfoCard({ reservations }: InfoCardProps) {
4949
</button>
5050
</section>
5151

52-
<section className="flex gap-9">
52+
<section className="flex flex-col gap-2 lg:flex-row lg:gap-8">
5353
<div className="flex flex-col gap-2">
5454
<h2 className="title1-nanum text-primary-gray-600">마이페이지</h2>
5555
<h2 className="body1-nanum text-primary-gray-600">예약내역</h2>
@@ -74,7 +74,7 @@ export default function InfoCard({ reservations }: InfoCardProps) {
7474

7575
<div className="text-red h-full border-l border-zinc-500/10" />
7676

77-
<div className="flex gap-5">
77+
<div className="flex gap-8 self-center lg:gap-5">
7878
<div className="flex flex-col items-center gap-1">
7979
<p className="caption1-nanum text-primary-gray-600">총 예약 수</p>
8080
<p className="title1-nanum text-primary-gray-600">{totalReservations}</p>

‎src/app/my-page/_component/reservation-card/index.tsx‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export default function ReservationCard({ reservations, setReservations }: Reser
3030
});
3131

3232
return (
33-
<div className="scrollbar-none flex h-full max-h-[calc(100dvh-80px-180px-40px)] flex-col gap-6 overflow-y-auto rounded-2xl bg-white p-8 pb-4">
33+
<div className="scrollbar-none flex h-full max-h-[calc(100dvh-80px-180px-180px)] min-h-[calc(100dvh-64px-330px)] flex-col gap-6 overflow-y-auto rounded-t-2xl bg-white p-8 pb-4 md:min-h-auto md:rounded-2xl lg:max-h-[calc(100dvh-80px-180px-40px)]">
3434
<div className="flex justify-between">
3535
<div className="flex w-full flex-col gap-2">
3636
<div className="flex items-center gap-2">
@@ -71,17 +71,18 @@ export default function ReservationCard({ reservations, setReservations }: Reser
7171
<CardLayout reservations={reservations} setReservations={setReservations} />
7272
)
7373
) : (
74-
<div className="my-auto flex w-fit items-center gap-20 self-center rounded-2xl bg-gray-50 py-4 pr-24 pl-4">
74+
<div className="my-auto flex w-fit flex-col items-center gap-6 self-center rounded-2xl bg-gray-50 px-10 py-4 md:flex-row md:gap-20 md:pr-24 md:pl-4">
7575
<Image
7676
src={EmptyReservationsImage}
7777
alt="empty-reservations"
7878
width={200}
7979
height={200}
8080
priority
81+
className="size-[160px] md:size-[200px]"
8182
/>
8283

83-
<div className="flex flex-col gap-6">
84-
<div className="flex flex-col gap-2">
84+
<div className="flex w-full flex-col items-center gap-6">
85+
<div className="flex flex-col items-center gap-2">
8586
<h2 className="title1-nanum text-zinc-800">예약한 강의실이 없습니다</h2>
8687
<h2 className="body1-nanum text-zinc-800">
8788
아직 예약 신청한 경험이 없네요.
@@ -91,7 +92,7 @@ export default function ReservationCard({ reservations, setReservations }: Reser
9192
</div>
9293
<Link
9394
href="/"
94-
className="body2-nanum bg-classpick-500 w-fit rounded-full px-8 py-4 text-base font-extrabold text-white"
95+
className="body2-nanum bg-classpick-500 w-fit rounded-full px-8 py-4 text-sm font-extrabold text-white"
9596
>
9697
나에게 맞는 강의실 예약하러 가기
9798
</Link>

0 commit comments

Comments
 (0)