Skip to content
Merged
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
2 changes: 0 additions & 2 deletions web/src/app/(landing)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import LandingHeader from "@/components/LandingHeader";
import LandingFooter from "@/components/LandingFooter";

export default function LandingLayout({
children,
Expand All @@ -10,7 +9,6 @@ export default function LandingLayout({
<div className="min-h-screen flex flex-col">
<LandingHeader />
<main className="flex-1">{children}</main>
<LandingFooter />
</div>
);
}
30 changes: 16 additions & 14 deletions web/src/app/admin/course/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,23 +49,23 @@ export default function AdminCoursesPage() {
};

return (
<div className="mx-auto w-full max-w-7xl px-6 py-12 lg:px-8 lg:py-16">
<div className="mx-auto w-full max-w-7xl px-4 py-8 sm:px-6 sm:py-12 lg:px-8 lg:py-16">
<div className="flex flex-col gap-8">
<header className="flex items-center justify-between">
<div>
<h1 className="text-3xl font-bold tracking-tight text-foreground sm:text-4xl">
<header className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
<div className="min-w-0">
<h1 className="text-2xl font-bold tracking-tight text-foreground sm:text-3xl lg:text-4xl">
강의 관리
</h1>
<p className="mt-2 text-lg text-muted-foreground">
<p className="mt-1.5 text-sm text-muted-foreground sm:text-base lg:text-lg">
교육 콘텐츠를 검색하고 관리합니다.
</p>
</div>
<Button
className="flex items-center gap-2"
className="flex shrink-0 items-center justify-center gap-2 self-start sm:self-auto"
onClick={openCreateModal}
>
<Plus className="mr-2 h-4 w-4" />
<span>강의 추가</span>
<Plus className="h-4 w-4 shrink-0" />
<span className="truncate">강의 추가</span>
</Button>
</header>

Expand All @@ -77,19 +77,21 @@ export default function AdminCoursesPage() {
<CourseListForm onSubmit={updateRequest} />
</div>

<div className="flex-1 flex flex-col gap-4">
<div className="flex flex-col gap-4 flex-1 min-w-0">
{isLoading ? (
<ListTableSkeleton columnCount={4} rowCount={8} />
) : error ? (
<p className="text-center text-destructive">
강의 목록을 불러오는 중 오류가 발생했습니다.
</p>
) : courses?.length ? (
<CourseListTable
courses={courses ?? []}
onUpdate={openUpdateModal}
onDelete={handleDelete}
/>
<div className="min-w-0 overflow-x-auto rounded-lg border border-border">
<CourseListTable
courses={courses ?? []}
onUpdate={openUpdateModal}
onDelete={handleDelete}
/>
</div>
) : (
<p className="text-center text-muted-foreground">강의가 없습니다.</p>
)}
Expand Down
3 changes: 0 additions & 3 deletions web/src/app/admin/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import AdminHeader from "@/components/admin/Header";
import AdminFooter from "@/components/admin/Footer";
//

export default function AdminLayout({ children }: { children: React.ReactNode }) {
return (
<div className="min-h-screen flex flex-col">
<AdminHeader />
<main className="flex-1 flex flex-col">{children}</main>
<AdminFooter />
</div>
);
}
51 changes: 27 additions & 24 deletions web/src/app/admin/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useScheduleStatusStats } from "@/hooks/admin/useSchedule";
import { useUserRoleStats } from "@/hooks/admin/useUser";
import { ScheduleStatus } from "@/schemas/schedule/schedule-status";
import { UserRole } from "@/schemas/user/user-role";
import { Button } from "@/components/ui/button";

export default function AdminPage() {
const {
Expand All @@ -26,8 +27,8 @@ export default function AdminPage() {

if (isLoading) {
return (
<div className="container mx-auto py-8 px-4 max-w-4xl">
<h1 className="text-2xl font-bold text-foreground mb-6">관리자 대시보드</h1>
<div className="mx-auto w-full max-w-4xl px-4 py-8 sm:px-6 lg:px-8">
<h1 className="mb-6 text-2xl font-bold text-foreground sm:text-3xl">관리자 대시보드</h1>
<div className="flex flex-col gap-6">
<StatsListSkeleton />
<StatsListSkeleton />
Expand All @@ -38,33 +39,35 @@ export default function AdminPage() {

if (isError) {
return (
<div className="container mx-auto py-8 px-4 max-w-4xl">
<h1 className="text-2xl font-bold text-foreground mb-6">관리자 대시보드</h1>
<div className="rounded-lg border border-muted-foreground/30 bg-muted/30 p-6">
<p className="text-foreground font-medium mb-2">
<div className="mx-auto w-full max-w-4xl px-4 py-8 sm:px-6 lg:px-8">
<h1 className="mb-6 text-2xl font-bold text-foreground sm:text-3xl">관리자 대시보드</h1>
<div className="rounded-lg border border-muted-foreground/30 bg-muted/30 p-4 sm:p-6">
<p className="mb-2 font-medium text-foreground">
데이터를 불러오는 중 오류가 발생했습니다.
</p>
<p className="text-sm text-muted-foreground mb-4">
<p className="mb-4 text-sm text-muted-foreground">
잠시 후 다시 시도해주세요.
</p>
<div className="flex gap-2">
<div className="flex flex-wrap gap-2">
{isScheduleStatusError && (
<button
<Button
type="button"
variant="secondary"
size="sm"
onClick={() => refetchScheduleStatus()}
className="rounded-md bg-foreground px-4 py-2 text-background hover:bg-foreground/90 text-sm"
>
스케줄 통계 다시 시도
</button>
</Button>
)}
{isUserRoleError && (
<button
<Button
type="button"
variant="secondary"
size="sm"
onClick={() => refetchUserRole()}
className="rounded-md bg-foreground px-4 py-2 text-background hover:bg-foreground/90 text-sm"
>
사용자 통계 다시 시도
</button>
</Button>
)}
</div>
</div>
Expand All @@ -73,32 +76,32 @@ export default function AdminPage() {
}

return (
<div className="container mx-auto py-8 px-4 max-w-4xl">
<h1 className="text-2xl font-bold text-foreground mb-6">관리자 대시보드</h1>
<div className="mx-auto w-full max-w-4xl px-4 py-8 sm:px-6 lg:px-8">
<h1 className="mb-6 text-2xl font-bold text-foreground sm:text-3xl">관리자 대시보드</h1>

<div className="flex flex-col gap-6">
{/* 사용자 통계 */}
{userRoleStats ? (
<section>
<h2 className="text-base font-semibold text-foreground mb-3">사용자 통계</h2>
<section className="min-w-0">
<h2 className="mb-3 text-base font-semibold text-foreground">사용자 통계</h2>
<StatsList<UserRole> stats={userRoleStats} unit="명" />
</section>
) : (
<section>
<h2 className="text-base font-semibold text-foreground mb-3">사용자 통계</h2>
<section className="min-w-0">
<h2 className="mb-3 text-base font-semibold text-foreground">사용자 통계</h2>
<p className="text-muted-foreground">데이터를 불러올 수 없습니다.</p>
</section>
)}

{/* 스케줄 통계 */}
{scheduleStatusStats ? (
<section>
<h2 className="text-base font-semibold text-foreground mb-3">스케줄 통계</h2>
<section className="min-w-0">
<h2 className="mb-3 text-base font-semibold text-foreground">스케줄 통계</h2>
<StatsList<ScheduleStatus> stats={scheduleStatusStats} unit="건" />
</section>
) : (
<section>
<h2 className="text-base font-semibold text-foreground mb-3">스케줄 통계</h2>
<section className="min-w-0">
<h2 className="mb-3 text-base font-semibold text-foreground">스케줄 통계</h2>
<p className="text-muted-foreground">데이터를 불러올 수 없습니다.</p>
</section>
)}
Expand Down
28 changes: 15 additions & 13 deletions web/src/app/admin/schedule/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,42 +39,44 @@ export default function AdminSchedulesPage() {
};

return (
<div className="mx-auto w-full max-w-7xl px-6 py-12 lg:px-8 lg:py-16">
<div className="mx-auto w-full max-w-7xl px-4 py-8 sm:px-6 sm:py-12 lg:px-8 lg:py-16">
<div className="flex flex-col gap-8">
<header className="flex items-center justify-between">
<div>
<h1 className="text-3xl font-bold tracking-tight text-foreground sm:text-4xl">
<header className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
<div className="min-w-0">
<h1 className="text-2xl font-bold tracking-tight text-foreground sm:text-3xl lg:text-4xl">
스케줄 관리
</h1>
<p className="mt-2 text-lg text-muted-foreground">
<p className="mt-1.5 text-sm text-muted-foreground sm:text-base lg:text-lg">
사용자 스케줄을 검색하고 관리합니다.
</p>
</div>
<Button
className="flex items-center gap-2"
className="flex shrink-0 items-center justify-center gap-2 self-start sm:self-auto"
onClick={openCreateModal}
>
<Plus className="mr-2 h-4 w-4" />
<span>스케줄 추가</span>
<Plus className="h-4 w-4 shrink-0" />
<span className="truncate">스케줄 추가</span>
</Button>
</header>

<div className="w-full">
<ScheduleListForm onSubmit={updateRequest} />
</div>

<div className="flex-1 flex flex-col gap-4">
<div className="flex flex-col gap-4 flex-1 min-w-0">
{isLoading ? (
<ListTableSkeleton columnCount={5} rowCount={8} />
) : error ? (
<p className="text-center text-destructive">
스케줄 목록을 불러오는 중 오류가 발생했습니다.
</p>
) : schedules?.length ? (
<ScheduleListTable
schedules={schedules ?? []}
onUpdate={openUpdateModal}
/>
<div className="min-w-0 overflow-x-auto rounded-lg border border-border">
<ScheduleListTable
schedules={schedules ?? []}
onUpdate={openUpdateModal}
/>
</div>
) : (
<p className="text-center text-muted-foreground">스케줄이 없습니다.</p>
)}
Expand Down
22 changes: 12 additions & 10 deletions web/src/app/admin/user/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,39 +39,41 @@ export default function AdminUsersPage() {
};

return (
<div className="mx-auto w-full max-w-7xl px-6 py-12 lg:px-8 lg:py-16">
<div className="mx-auto w-full max-w-7xl px-4 py-8 sm:px-6 sm:py-12 lg:px-8 lg:py-16">
<div className="flex flex-col gap-8">
<header className="flex items-center justify-between">
<div>
<h1 className="text-3xl font-bold tracking-tight text-foreground sm:text-4xl">
<header className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
<div className="min-w-0">
<h1 className="text-2xl font-bold tracking-tight text-foreground sm:text-3xl lg:text-4xl">
사용자 관리
</h1>
<p className="mt-2 text-lg text-muted-foreground">
<p className="mt-1.5 text-sm text-muted-foreground sm:text-base lg:text-lg">
서비스 사용자를 검색하고 관리합니다.
</p>
</div>
<Button
className="flex items-center gap-2"
className="flex shrink-0 items-center justify-center gap-2 self-start sm:self-auto"
onClick={openCreateModal}
>
<Plus className="mr-2 h-4 w-4" />
<span>사용자 추가</span>
<Plus className="h-4 w-4 shrink-0" />
<span className="truncate">사용자 추가</span>
</Button>
</header>

<div className="w-full">
<UserListForm onSubmit={updateRequest} />
</div>

<div className="flex-1 flex flex-col gap-4">
<div className="flex flex-col gap-4 flex-1 min-w-0">
{isLoading ? (
<ListTableSkeleton columnCount={5} rowCount={8} />
) : error ? (
<p className="text-center text-destructive">
사용자 목록을 불러오는 중 오류가 발생했습니다.
</p>
) : users?.length ? (
<UserListTable users={users ?? []} onUpdate={openUpdateModal} />
<div className="min-w-0 overflow-x-auto rounded-lg border border-border">
<UserListTable users={users ?? []} onUpdate={openUpdateModal} />
</div>
) : (
<p className="text-center text-muted-foreground">사용자가 없습니다.</p>
)}
Expand Down
9 changes: 0 additions & 9 deletions web/src/components/LandingFooter.tsx

This file was deleted.

9 changes: 0 additions & 9 deletions web/src/components/admin/Footer.tsx

This file was deleted.

5 changes: 1 addition & 4 deletions web/src/components/admin/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@ export default function AdminHeader() {
<header className="sticky top-0 z-40 flex w-full justify-center border-b bg-background pt-[env(safe-area-inset-top)]">
<div className="flex h-16 w-full max-w-7xl items-center justify-between px-4 sm:px-6 lg:px-8">
<div className="flex items-center gap-2">
<HeaderNavSheet
navItems={[...NAV_ITEMS]}
getIsActive={getIsActive}
/>
<HeaderNavSheet navItems={NAV_ITEMS} getIsActive={getIsActive} />
<Link href="/" className="flex items-center space-x-2">
<BookOpen className="h-6 w-6" />
<h1 className="font-bold">NexLang</h1>
Expand Down
28 changes: 0 additions & 28 deletions web/src/components/admin/Sidebar.tsx

This file was deleted.

Loading