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
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
"use client";

import { Fragment, ReactNode } from "react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { Icon } from "@/components";
import { ADMIN_NAV_SECTIONS } from "../../_constants/ADMIN_NAV_SECTIONS";
import { AdminLogoutButton } from "../_internal";
Expand Down Expand Up @@ -36,16 +39,31 @@ interface AdminSectionNavItemProps {
}

const AdminSectionNavItem = ({ label, items, footer }: AdminSectionNavItemProps) => {
const pathname = usePathname();

const isCurrent = (href: string) =>
pathname !== null && (pathname === href || pathname.startsWith(`${href}/`));

return (
<section aria-label={label} className="flex flex-col gap-[2px] px-5 py-6">
<section aria-label={label} className="flex flex-col gap-[2px] px-5 py-6 pc:py-4">
<h2 className="text-body2-regular text-layout-body-default">{label}</h2>

<ul>
{items.map(({ href, title }) => (
<li key={href}>
<Link href={href} className="flex items-center justify-between py-[10px]">
<span className="text-body1-semibold text-neutral-strong-default">{title}</span>
<Icon name="ArrowRightSmall" size={24} className="text-neutral-strong-default" />
<Link
href={href}
aria-current={isCurrent(href) ? "page" : undefined}
className="group flex items-center justify-between py-[10px] pc:-mx-3 pc:rounded-[10px] pc:px-3 pc:transition-colors pc:hover:bg-flatGray-25 pc:aria-[current=page]:bg-fill-brand-subtle-default"
>
<span className="text-body1-semibold text-neutral-strong-default pc:group-aria-[current=page]:text-brand-normal-default">
{title}
</span>
<Icon
name="ArrowRightSmall"
size={24}
className="text-neutral-strong-default pc:hidden"
/>
</Link>
</li>
))}
Expand Down
29 changes: 23 additions & 6 deletions src/app/(admin)/admin/_components/AdminProfile/AdminProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,31 @@ const AdminProfile = () => {
const { email, nickname, profileImg } = data?.result || {};

return (
<header className="flex items-center justify-between px-5 py-[30px]">
<header className="flex items-center justify-between px-5 py-[30px] pc:flex-col pc:items-stretch pc:gap-5">
{isLoading ? (
<SkeletonAdminProfile />
) : (
<div className="flex items-center gap-6">
<ProfileAvatar src={profileImg} alt={nickname} size={60} priority />
<div>
<p className="text-body1-semibold text-layout-header-default">{nickname}</p>
<span className="text-body2-regular text-layout-body-default">{email}</span>
<div className="flex items-center gap-6 pc:min-w-0 pc:gap-4">
<ProfileAvatar
src={profileImg}
alt={nickname}
size={60}
priority
className="pc:shrink-0"
/>
<div className="pc:min-w-0">
<p
title={nickname}
className="text-body1-semibold text-layout-header-default pc:truncate"
>
{nickname}
</p>
<span
title={email}
className="text-body2-regular text-layout-body-default pc:block pc:truncate"
>
{email}
</span>
</div>
</div>
)}
Expand All @@ -29,6 +45,7 @@ const AdminProfile = () => {
aria-label="관리자 프로필 수정"
variant="outlined"
size="small"
className="pc:w-full"
>
프로필 수정
</Button>
Expand Down
23 changes: 23 additions & 0 deletions src/app/(admin)/admin/_components/AdminSidebar/AdminSidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import AdminMenuSection from "../AdminMenuSection/AdminMenuSection";
import AdminProfile from "../AdminProfile/AdminProfile";

/**
* PC 화면에서 모든 관리자 화면 왼쪽에 고정되는 사이드바입니다.
*
* @remarks
* - PC 미만에서는 렌더만 하고 숨기며, 그 크기에서는 `/admin` 메인이 같은 프로필과 메뉴를 보여줍니다.
*/

const AdminSidebar = () => {
return (
<aside
aria-label="관리자 사이드바"
className="hidden pc:sticky pc:top-0 pc:flex pc:h-dvh pc:w-[320px] pc:shrink-0 pc:flex-col pc:overflow-y-auto pc:border-r pc:border-divider-default"
>
<AdminProfile />
<AdminMenuSection />
</aside>
);
};

export default AdminSidebar;
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const SkeletonAdminProfile = () => {
return (
<div className="flex items-center gap-6">
<div className="flex items-center gap-6 pc:gap-4">
<div className="skeleton-animation size-[60px] rounded-full" />
<div className="flex flex-col gap-2">
<div className="skeleton-animation h-5 w-[70px] rounded-full" />
Expand Down
1 change: 1 addition & 0 deletions src/app/(admin)/admin/_components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export { default as AdminSearch } from "./AdminSearch/AdminSearch";
export { default as AdminReportsItem } from "./AdminReportsItem/AdminReportsItem";
export { default as AdminDetailSection } from "./AdminDetailSection/AdminDetailSection";
export { default as AdminDropdown } from "./AdminDropdown/AdminDropdown";
export { default as AdminSidebar } from "./AdminSidebar/AdminSidebar";
8 changes: 7 additions & 1 deletion src/app/(admin)/admin/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ReactNode } from "react";
import type { Metadata } from "next";
import { AdminSidebar } from "./_components";

export const metadata: Metadata = {
title: {
Expand Down Expand Up @@ -34,7 +35,12 @@ export const metadata: Metadata = {
};

const layout = ({ children }: { children: ReactNode }) => {
return children;
return (
<div className="pc:flex">
<AdminSidebar />
<div className="pc:min-w-0 pc:flex-1">{children}</div>
</div>
);
};

export default layout;
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const NoticeEditForm = ({ noticeId }: NoticeEditFormProps) => {
<CategoryInput />
<ContentInput />
<NoticeEditImageSection helpText={IMAGE_HELP_TEXT} />
<div className="sticky bottom-0 w-full max-w-[764px] border-t border-divider-default bg-white">
<div className="sticky bottom-0 w-full max-w-[764px] border-t border-divider-default bg-white pc:max-w-none">
<WriteActionSection disabled={isSubmitDisabled} />
</div>
</form>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const NoticeWriteForm = ({ methods }: { methods: UseFormReturn<NoticeWriteFormVa
<CategoryInput />
<ContentInput />
<WriteImageSection helpText={IMAGE_HELP_TEXT} />
<div className="sticky bottom-0 w-full max-w-[764px] border-t border-divider-default bg-white">
<div className="sticky bottom-0 w-full max-w-[764px] border-t border-divider-default bg-white pc:max-w-none">
<WriteActionSection disabled={isSubmitDisabled} />
</div>
</form>
Expand Down
10 changes: 8 additions & 2 deletions src/app/(admin)/admin/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,14 @@ const page = async () => {
<div className="h-base">
<h1 className="sr-only">관리자 페이지</h1>

<AdminProfile />
<AdminMenuSection />
<div className="pc:hidden">
<AdminProfile />
<AdminMenuSection />
</div>

<p className="hidden py-[160px] text-body1-regular text-layout-body-default pc:flex-center">
왼쪽 메뉴에서 관리할 항목을 선택해 주세요.
</p>
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const AdminLoginForm = () => {

return (
<form onSubmit={onSubmitLogin}>
<div className="flex min-h-dvh w-full gap-12 px-4 py-[64px] flex-col-center tablet:px-[80px]">
<div className="flex min-h-dvh w-full gap-12 px-4 py-[64px] flex-col-center tablet:px-[80px] pc:mx-auto pc:max-w-[480px] pc:px-0">
<div className="flex w-full flex-col items-center gap-10">
<Icon name="Logo" size={120} title="찾아줘! 관리자" />

Expand Down
2 changes: 1 addition & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export default function RootLayout({

return (
<html lang="ko" className={pretendard.variable}>
<body className="mx-auto max-w-[768px] border-x-2 flex-col-center">
<body className="mx-auto max-w-[768px] border-x-2 flex-col-center pc:max-w-none pc:border-x-0">
<AppProviders>
<main className="w-full flex-1">{children}</main>
</AppProviders>
Expand Down
4 changes: 3 additions & 1 deletion src/components/layout/DetailHeader/DetailHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { cn } from "@/utils";
* - `"use client"`이며 `next/navigation`의 `useRouter`로 뒤로가기 동작을 처리합니다.
* - `onBack`이 있으면 뒤로 버튼은 그만 호출하고, 없으면 `sessionStorage`의 `__fmi_history_count`를 보고 `router.back()` 또는 `/`로 이동합니다.
* - `fixed` 헤더 아래 콘텐츠가 가리지 않도록 동일 높이의 자리 표시 `div`를 둡니다.
* - PC에서는 사이드바 옆 본문 폭을 따라가도록 `sticky`로 바뀌고 자리 표시 `div`는 숨깁니다.
* - 오른쪽 액션은 `DetailHeaderParts`(저장, 검색, 즐겨찾기, 메뉴 등)를 `children`으로 넣는 패턴을 씁니다.
*
* @author hyungjun
Expand Down Expand Up @@ -81,6 +82,7 @@ const DetailHeader = ({ title = "", children, onBack, onBeforeBack }: DetailHead
<header
className={cn(
"fixed top-0 z-30 mx-auto flex w-full max-w-[764px] items-center justify-between bg-white px-5 pt-[var(--safe-area-top)]",
"pc:sticky pc:max-w-none pc:border-b pc:border-divider-default",
HEADER_HEIGHT
)}
>
Expand All @@ -101,7 +103,7 @@ const DetailHeader = ({ title = "", children, onBack, onBeforeBack }: DetailHead
</div>
)}
</header>
<div className={HEADER_HEIGHT} aria-hidden />
<div className={cn(HEADER_HEIGHT, "pc:hidden")} aria-hidden />
</>
);
};
Expand Down
Loading