@@ -31,6 +31,11 @@ export function AppHeader() {
|
||||
const [indicatorLeft, setIndicatorLeft] = React.useState<number>(0);
|
||||
const [indicatorWidth, setIndicatorWidth] = React.useState<number>(0);
|
||||
const [indicatorVisible, setIndicatorVisible] = React.useState<boolean>(false);
|
||||
// 로그인 상태 확인 (전역 버튼 노출용)
|
||||
const { data: authData } = useSWR<{ user: { userId: string; nickname: string; profileImage: string | null; points: number; level: number; grade: number } | null }>(
|
||||
"/api/me",
|
||||
(u: string) => fetch(u).then((r) => r.json())
|
||||
);
|
||||
// 모바일 사이드바 열릴 때만 현재 사용자 정보를 가져옵니다(훅은 항상 동일한 순서로 호출)
|
||||
const { data: meData } = useSWR<{ user: { userId: string; nickname: string; profileImage: string | null; points: number; level: number; grade: number } | null }>(
|
||||
mobileOpen ? "/api/me" : null,
|
||||
@@ -468,13 +473,30 @@ export function AppHeader() {
|
||||
<div id="dummy" className="block"></div>
|
||||
<div className="hidden xl:flex xl:flex-1 justify-end">
|
||||
<SearchBar/>
|
||||
<Link
|
||||
href="/admin"
|
||||
className="ml-3 inline-flex items-center px-3 h-10 rounded-md border border-neutral-300 text-neutral-700 hover:bg-neutral-100"
|
||||
aria-label="어드민(임시)"
|
||||
>
|
||||
어드민(임시)
|
||||
</Link>
|
||||
{authData?.user && (
|
||||
<button
|
||||
onClick={async () => {
|
||||
try {
|
||||
await fetch("/api/auth/session", { method: "DELETE" });
|
||||
} finally {
|
||||
window.location.reload();
|
||||
}
|
||||
}}
|
||||
className="ml-3 inline-flex items-center px-3 h-10 rounded-md border border-neutral-300 text-neutral-700 hover:bg-neutral-100"
|
||||
aria-label="로그아웃"
|
||||
>
|
||||
로그아웃
|
||||
</button>
|
||||
)}
|
||||
{!authData?.user && (
|
||||
<Link
|
||||
href={`/login?next=${encodeURIComponent((pathname || "/") + (searchParams?.toString() ? `?${searchParams.toString()}` : ""))}`}
|
||||
className="ml-3 inline-flex items-center px-3 h-10 rounded-md border border-neutral-300 text-neutral-700 hover:bg-neutral-100"
|
||||
aria-label="로그인"
|
||||
>
|
||||
로그인
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
</nav>
|
||||
<div
|
||||
@@ -505,29 +527,45 @@ export function AppHeader() {
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center gap-3 animate-pulse">
|
||||
<div className="w-12 h-12 rounded-full bg-neutral-200" />
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="h-3 w-1/2 bg-neutral-200 rounded" />
|
||||
<div className="mt-2 h-3 w-1/3 bg-neutral-200 rounded" />
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="text-sm text-neutral-700">로그인이 필요합니다</div>
|
||||
<Link
|
||||
href={`/login?next=${encodeURIComponent((pathname || "/") + (searchParams?.toString() ? `?${searchParams.toString()}` : ""))}`}
|
||||
onClick={() => setMobileOpen(false)}
|
||||
className="h-9 px-3 inline-flex items-center rounded-md border border-neutral-300 text-neutral-700 hover:bg-neutral-100"
|
||||
aria-label="로그인"
|
||||
>
|
||||
로그인
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
{meData?.user && (
|
||||
<div className="mt-3 flex justify-end">
|
||||
<button
|
||||
onClick={async () => {
|
||||
try {
|
||||
await fetch("/api/auth/session", { method: "DELETE" });
|
||||
} finally {
|
||||
setMobileOpen(false);
|
||||
window.location.reload();
|
||||
}
|
||||
}}
|
||||
className="h-9 px-3 inline-flex items-center rounded-md border border-neutral-300 text-neutral-700 hover:bg-neutral-100"
|
||||
aria-label="로그아웃"
|
||||
>
|
||||
로그아웃
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
{meData?.user && (
|
||||
<div className="grid grid-cols-3 gap-2 mt-3">
|
||||
<Link href="/my-page?tab=points" onClick={() => setMobileOpen(false)} className="h-9 rounded-md border border-neutral-300 text-xs flex items-center justify-center hover:bg-neutral-100">포인트 히스토리</Link>
|
||||
<Link href="/my-page?tab=posts" onClick={() => setMobileOpen(false)} className="h-9 rounded-md border border-neutral-300 text-xs flex items-center justify-center hover:bg-neutral-100">내가 쓴 글</Link>
|
||||
<Link href="/my-page?tab=comments" onClick={() => setMobileOpen(false)} className="h-9 rounded-md border border-neutral-300 text-xs flex items-center justify-center hover:bg-neutral-100">내가 쓴 댓글</Link>
|
||||
</div>
|
||||
)}
|
||||
<div className="grid grid-cols-3 gap-2 mt-3">
|
||||
<Link href="/my-page?tab=points" onClick={() => setMobileOpen(false)} className="h-9 rounded-md border border-neutral-300 text-xs flex items-center justify-center hover:bg-neutral-100">포인트 히스토리</Link>
|
||||
<Link href="/my-page?tab=posts" onClick={() => setMobileOpen(false)} className="h-9 rounded-md border border-neutral-300 text-xs flex items-center justify-center hover:bg-neutral-100">내가 쓴 글</Link>
|
||||
<Link href="/my-page?tab=comments" onClick={() => setMobileOpen(false)} className="h-9 rounded-md border border-neutral-300 text-xs flex items-center justify-center hover:bg-neutral-100">내가 쓴 댓글</Link>
|
||||
</div>
|
||||
</div>
|
||||
<SearchBar />
|
||||
<Link
|
||||
href="/admin"
|
||||
onClick={() => setMobileOpen(false)}
|
||||
className="inline-flex items-center justify-center h-10 rounded-md border border-neutral-300 text-neutral-700 hover:bg-neutral-100"
|
||||
aria-label="어드민(임시)"
|
||||
>
|
||||
어드민(임시)
|
||||
</Link>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
{categories.map((cat) => (
|
||||
<div key={cat.id}>
|
||||
|
||||
Reference in New Issue
Block a user