Skip to content
Open
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
dbf4a14
responsive layout/footer
kwontaeyeonn Feb 4, 2026
4bbc5d4
fix: breakpoint change
danjee2009 Feb 4, 2026
fe5a40c
fix: searchbar error
danjee2009 Feb 5, 2026
7e38ff9
fix: fixed layout
gangmin0716 Feb 5, 2026
a6d14f9
fix: fixed layout
gangmin0716 Feb 5, 2026
59565c6
feat: Responsive layout for room
gangmin0716 Feb 6, 2026
37d33e3
Merge pull request #1 from 8bit-beep/fix/layout
gangmin0716 Feb 6, 2026
0e7696a
feat: button text apply
danjee2009 Feb 6, 2026
454cb33
merge feature:blacklist
danjee2009 Feb 6, 2026
5ef505e
feat: checkpoint responsive view
jdw09 Feb 6, 2026
7585fe6
fix: add missing AuthProvier
jdw09 Feb 6, 2026
413935b
feat: root path redirection in mobile header
jdw09 Feb 6, 2026
ee9e84d
merge: feature/checkpoint-responsive
jdw09 Feb 6, 2026
9ba88c5
fix: fixed table
gangmin0716 Feb 6, 2026
e340322
feat: mobile attend type 반응형 추가 dangerText 추가
mingious02 Feb 6, 2026
e69bef5
Merge pull request #4 from 8bit-beep/feature/room-responsive
gangmin0716 Feb 6, 2026
092f435
fix: @bds-web Btn style 누락된 거 임시로 style로 정의.
mingious02 Feb 6, 2026
cab56c0
fix: color 토큰으로 수정
mingious02 Feb 6, 2026
83ae076
Merge pull request #5 from 8bit-beep/feature/attend-types-responsive
mingious02 Feb 6, 2026
3de6fd2
fix: students page responsive
Feb 6, 2026
35cdf81
chore: remove mock data file
Feb 6, 2026
688e28d
feat: add PC student section
Feb 6, 2026
c0e4a37
Merge pull request #6 from 8bit-beep/feature/students-reponsive
yungxhi Feb 7, 2026
3897bfe
refactor: type definition format unification
jdw09 Feb 18, 2026
3a11951
refactor: resize tabbar icons and remove breakpoints in global.css
gangmin0716 Feb 18, 2026
025654d
fix: breakpoint
kwontaeyeonn Feb 20, 2026
fcaf574
fix: use Tailwind
kwontaeyeonn Feb 20, 2026
413b51b
fix: remove duplicate code
kwontaeyeonn Feb 21, 2026
99678b7
fix: convert to Tailwind, remove __next
kwontaeyeonn Feb 21, 2026
7a725f4
merge: main to feature/responsive-web
jdw09 Apr 22, 2026
b625cb8
fix: remove email in modal component
jdw09 Apr 22, 2026
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
7,097 changes: 7,097 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

418 changes: 209 additions & 209 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

49 changes: 36 additions & 13 deletions src/app/(root)/attend-types/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { AttendTypeApi } from "@/entities/attend-types/api";
import CreateAttendType from "@/features/manage-attend-types/ui/CreateAttendType";
import DeleteAttendType from "@/features/manage-attend-types/ui/DeleteAttendType";
import MobileCreateAttendType from "@/features/manage-attend-types/ui/MobileCreateAttendType";
import MobileDeleteAttendType from "@/features/manage-attend-types/ui/MobileDeleteAttendType";
import OkIcon from "@/shared/icons/OkIcon";
import Section from "@/widgets/section/ui/Section";
import Table from "@/widgets/table/ui/Table";
Expand All @@ -9,18 +11,39 @@ export default async function AttendTypesPage() {
const { data } = await AttendTypeApi.getAttendTypes();

return (
<Section
title="출석 종류"
description="출석 종류를 추가해보세요!"
icon={<OkIcon size={24} />}
headerOptions={<CreateAttendType />}>
<Table
header={[{ title: "종류명" }, { title: "", width: "117px" }]}
rows={data.map((type) => [
type.name,
<DeleteAttendType key={type.id} attendTypeId={type.id} />,
])}
/>
</Section>
<div className="overflow-hidden">
<div className="w-full h-full flex xl:hidden">
<Section
title="출석 종류"
description="출석 종류를 추가해보세요!"
icon={<OkIcon size={24} />}
headerOptions={<MobileCreateAttendType />}
>
<Table
header={[{ title: "종류명" }, { title: "", width: "117px" }]}
rows={data.map((type) => [
type.name,
<MobileDeleteAttendType key={type.id} attendTypeId={type.id} />,
])}
/>
Comment thread
jdw09 marked this conversation as resolved.
</Section>
</div>
<div className="w-full h-full hidden xl:flex">
<Section
title="출석 종류"
description="출석 종류를 추가해보세요!"
icon={<OkIcon size={24} />}
headerOptions={<CreateAttendType />}
>
<Table
header={[{ title: "종류명" }, { title: "", width: "117px" }]}
rows={data.map((type) => [
type.name,
<DeleteAttendType key={type.id} attendTypeId={type.id} />,
])}
/>
</Section>
</div>
</div>
);
}
75 changes: 53 additions & 22 deletions src/app/(root)/checkpoints/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { CheckpointApi } from "@/entities/checkpoints/api";
import CreateCheckpoint from "@/features/manage-checkpoints/ui/CreateCheckpoint";
import ManageCheckpoint from "@/features/manage-checkpoints/ui/ManageCheckpoint";
import MobileManageCheckpoint from "@/features/manage-checkpoints/ui/MobileManageCheckpoint";
import CalendarIcon from "@/shared/icons/CalendarIcon";
import Section from "@/widgets/section/ui/Section";
import Table from "@/widgets/table/ui/Table";
Expand All @@ -9,27 +10,57 @@ export default async function CheckpointsPage() {
const { data } = await CheckpointApi.getCheckpoints();

return (
<Section
title="체크포인트 조정"
description="출석 시간을 수정해 보세요!"
icon={<CalendarIcon size={24} />}
headerOptions={<CreateCheckpoint />}>
<Table
header={[
{ title: "체크포인트 이름", width: "202px" },
{ title: "체크포인트 기간", width: "202px" },
{ title: "출석 가능 기간", width: "202px" },
{ title: "" },
{ title: "", width: "202px" },
]}
rows={data.map((checkpoint) => [
checkpoint.name,
`${checkpoint.startAt.slice(0, 5)} ~ ${checkpoint.endAt.slice(0, 5)}`,
`${checkpoint.attendanceStartAt.slice(0, 5)} ~ ${checkpoint.attendanceEndAt.slice(0, 5)}`,
"",
<ManageCheckpoint key={checkpoint.id} data={checkpoint} />,
])}
/>
</Section>
<div className="overflow-hidden">
<div className="w-full h-full flex xl:hidden">
<Section
title="체크포인트 조정"
description="출석 시간을 수정해 보세요!"
icon={<CalendarIcon size={24} />}
headerOptions={<CreateCheckpoint />}
>
<Table
header={[
{ title: "체크포인트 이름", width: "202px" },
{ title: "체크포인트 기간", width: "202px" },
{ title: "출석 가능 기간", width: "202px" },
{ title: "" },
{ title: "", width: "100px" },
]}
rows={data.map((checkpoint) => [
checkpoint.name,
`${checkpoint.startAt.slice(0, 5)} ~ ${checkpoint.endAt.slice(0, 5)}`,
`${checkpoint.attendanceStartAt.slice(0, 5)} ~ ${checkpoint.attendanceEndAt.slice(0, 5)}`,
"",
<MobileManageCheckpoint key={checkpoint.id} data={checkpoint} />,
])}
/>
Comment thread
jdw09 marked this conversation as resolved.
</Section>
</div>
<div className="w-full h-full hidden xl:flex ">
<Section
title="체크포인트 조정"
description="출석 시간을 수정해 보세요!"
icon={<CalendarIcon size={24} />}
headerOptions={<CreateCheckpoint />}
>
<Table
header={[
{ title: "체크포인트 이름", width: "202px" },
{ title: "체크포인트 기간", width: "202px" },
{ title: "출석 가능 기간", width: "202px" },
{ title: "" },
{ title: "", width: "202px" },
]}
rows={data.map((checkpoint) => [
checkpoint.name,
`${checkpoint.startAt.slice(0, 5)} ~ ${checkpoint.endAt.slice(0, 5)}`,
`${checkpoint.attendanceStartAt.slice(0, 5)} ~ ${checkpoint.attendanceEndAt.slice(0, 5)}`,
"",
<ManageCheckpoint key={checkpoint.id} data={checkpoint} />,
])}
/>
</Section>
</div>
</div>
);
}
12 changes: 8 additions & 4 deletions src/app/(root)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import SearchBar from "@/features/search/ui/SearchBar";
import AuthProvider from "@/shared/provider/AuthProvider";
import Header from "@/widgets/header/ui/Header";
import Sidebar from "@/widgets/sidebar/ui/Sidebar";
import Tabbar from "@/widgets/tabbar/ui/Tabbar";
import { PropsWithChildren } from "react";

export default function MainLayout({ children }: PropsWithChildren) {
return (
<div className="w-full h-screen flex items-start">
<div className="w-full h-svh flex items-start flex-col xl:flex-row overflow-hidden">
<AuthProvider />
<Sidebar />
<div className="flex-1 px-13 pt-13 flex flex-col gap-4.5">
<Header />
<main className="w-full flex-1 h-[calc(100%-147px)] xl:h-full xl:px-[70px] xl:pt-13 pb-1 xl:pb-5 flex flex-col gap-4.5 overflow-y-auto">
<SearchBar />
<main className="w-full h-[calc(100vh-114px)]">{children}</main>
</div>
{children}
</main>
<Tabbar />
</div>
);
}
68 changes: 48 additions & 20 deletions src/app/(root)/students/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { StudentApi } from "@/entities/students/api";
import FilterStudent from "@/features/filter/ui/FilterStudent";
import MobileManageStudent from "@/features/manage-students/ui/MobileManageStudent";
import ManageStudent from "@/features/manage-students/ui/ManageStudent";
import PersonIcon from "@/shared/icons/PersonIcon";
import { SearchParams } from "@/shared/types/search-params";
Expand All @@ -17,25 +18,52 @@ export default async function StudentsPage({
);

return (
<Section
title="학생 관리"
description="학생 정보를 관리해 보세요!"
icon={<PersonIcon size={24} />}
headerOptions={<FilterStudent />}>
<Table
header={[
{ title: "학번", width: "124px" },
{ title: "이름", width: "112px" },
{ title: "이메일" },
{ title: "", width: "240px" },
]}
rows={data.map((student) => [
`${student.studentInfo.grade}${student.studentInfo.classNumber}${pad(student.studentInfo.num, 2)}`,
student.username,
student.email,
<ManageStudent key={student.id} data={student} />,
])}
/>
</Section>
<div className="overflow-hidden">
<div className="w-full h-full flex xl:hidden">
<Section
title="학생 관리"
description="학생 정보를 관리해 보세요!"
icon={<PersonIcon size={24} />}
headerOptions={<FilterStudent />}>
<Table
header={[
{ title: "학번", width: "124px" },
{ title: "이름", width: "112px" },
{ title: "이메일" },
{ title: "", width: "240px" },
]}
rows={data.map((student) => [
`${student.studentInfo.grade}${student.studentInfo.classNumber}${pad(student.studentInfo.num, 2)}`,
student.username,
student.email,
<MobileManageStudent key={student.id} data={student} />,
])}
/>
Comment thread
jdw09 marked this conversation as resolved.
Outdated
</Section>
</div>

<div className="w-full h-full hidden xl:flex">
<Section
title="학생 관리"
description="학생 정보를 관리해 보세요!"
icon={<PersonIcon size={24} />}
headerOptions={<FilterStudent />}>
<Table
header={[
{ title: "학번", width: "124px" },
{ title: "이름", width: "112px" },
{ title: "이메일" },
{ title: "", width: "240px" },
]}
rows={data.map((student) => [
`${student.studentInfo.grade}${student.studentInfo.classNumber}${pad(student.studentInfo.num, 2)}`,
student.username,
student.email,
<ManageStudent key={student.id} data={student} />,
])}
/>
</Section>
</div>
</div>
);
}
2 changes: 1 addition & 1 deletion src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,4 @@
overscroll-behavior: none;
user-select: none;
font-family: "Pretendard", sans-serif;
}
}
4 changes: 4 additions & 0 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ export default function RootLayout({
<BdsRegistry>
<QueryProvider>
<ModalProvider />
<div id="__next" className="xl:pb-[56px]">
Comment thread
jdw09 marked this conversation as resolved.
Outdated
Comment thread
jdw09 marked this conversation as resolved.
Outdated
<main className="xl:pb-[90px] box-border">{children}</main>
Comment thread
jdw09 marked this conversation as resolved.
Outdated
</div>

{children}
</QueryProvider>
</BdsRegistry>
Expand Down
12 changes: 12 additions & 0 deletions src/features/manage-attend-types/ui/MobileCreateAttendType.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"use client";

import { Button, modal } from "@bds-web/ui";
import CreateAttendTypeModal from "./CreateAttendTypeModal";

const MobileCreateAttendType = () => {
return (
<Button buttonSize="medium" buttonType="primary" onClick={() => modal.open({ title: "출석 종류 추가하기", content: <CreateAttendTypeModal /> })}>출석 종류 추가</Button>
)
}

export default MobileCreateAttendType
28 changes: 28 additions & 0 deletions src/features/manage-attend-types/ui/MobileDeleteAttendType.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"use client";

import { Button, modal } from "@bds-web/ui";
import DeleteAttendTypeModal from "./DeleteAttendTypeModal";
import { colors } from "@bds-web/colors";

interface Props {
attendTypeId: number;
}

const MobileDeleteAttendType = ({ attendTypeId }: Props) => {
return (
<Button
buttonSize="small"
buttonType="text"
style={{color: colors.red.dark}} // 임시방편
onClick={() =>
modal.open({
title: "출석 종류를 삭제하시겠습니까?",
content: <DeleteAttendTypeModal attendTypeId={attendTypeId} />,
})
}>
삭제
</Button>
);
};

export default MobileDeleteAttendType;
14 changes: 14 additions & 0 deletions src/features/manage-checkpoints/ui/MobileCreateCheckpoint.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"use client";

import { Button, modal } from "@bds-web/ui";
import CreateCheckpointModal from "./CreateCheckpointModal";

const CreateCheckpoint = () => {
return (
<Button buttonSize="medium" buttonType="primary" onClick={() => modal.open({ title: "체크포인트 추가하기", content: <CreateCheckpointModal /> })}>
체크포인트 추가하기
</Button>
)
}

export default CreateCheckpoint
Comment thread
jdw09 marked this conversation as resolved.
30 changes: 30 additions & 0 deletions src/features/manage-checkpoints/ui/MobileManageCheckpoint.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"use client";

import { Button, modal } from "@bds-web/ui";
import { Checkpoint } from "@/entities/checkpoints/types";
import MobileUpdateCheckpointModal from "./MobileUpdateCheckpointModal";

interface Props {
data: Checkpoint;
}

const MobileManageCheckpoint = ({ data }: Props) => {
return (
<div className="flex gap-2">
<Button
buttonType="text"
buttonSize="small"
onClick={() =>
modal.open({
title: "체크포인트 정보 수정",
content: <MobileUpdateCheckpointModal data={data} />,
})
}
>
수정
</Button>
</div>
);
};

export default MobileManageCheckpoint;
Loading