1- ' use client' ;
1+ " use client" ;
22
3- import Link from 'next/link' ;
4- import { usePathname } from 'next/navigation' ;
3+ import Link from "next/link" ;
4+ import { usePathname , useRouter } from "next/navigation" ;
5+ import { useState } from "react" ;
6+ import { logout } from "@/lib/api/auth" ;
57
68export function AppSidebar ( ) {
79 const pathname = usePathname ( ) ;
10+ const router = useRouter ( ) ;
11+ const [ isLoggingOut , setIsLoggingOut ] = useState ( false ) ;
12+
13+ const handleLogout = async ( ) => {
14+ if ( isLoggingOut ) return ;
15+
16+ setIsLoggingOut ( true ) ;
17+ try {
18+ await logout ( ) ;
19+ router . push ( "/login" ) ;
20+ } catch ( error ) {
21+ alert (
22+ `ログアウトに失敗しました: ${ error instanceof Error ? error . message : "不明なエラー" } ` ,
23+ ) ;
24+ setIsLoggingOut ( false ) ;
25+ }
26+ } ;
827
928 const isActive = ( path : string ) => {
1029 return pathname === path || pathname ?. startsWith ( `${ path } /` ) ;
1130 } ;
1231
1332 const getLinkClass = ( path : string ) => {
14- const baseClass = "flex items-center p-3 transition-all duration-200 group border-4 font-sans mb-3 rounded-none" ;
15-
33+ const baseClass =
34+ "flex items-center p-3 transition-all duration-200 group border-4 font-sans mb-3 rounded-none" ;
35+
1636 if ( isActive ( path ) ) {
1737 return `${ baseClass } bg-[#FCD34D] border-black text-black shadow-[inset_4px_4px_0_rgba(0,0,0,0.2)] font-bold tracking-widest` ;
1838 }
@@ -22,72 +42,92 @@ export function AppSidebar() {
2242 return (
2343 < aside className = "fixed left-0 top-16 z-40 h-[calc(100vh-4rem)] w-64 -translate-x-full transition-transform sm:translate-x-0 bg-[#14532D] border-r-4 border-black" >
2444 < div className = "flex h-full flex-col overflow-y-auto px-4 py-8" >
25-
2645 { /* Menu Title */ }
2746 < div className = "mb-8 px-2" >
28- < h2 className = "text-xl font-bold tracking-widest text-[#4ADE80] font-sans border-b-4 border-[#4ADE80] pb-2 drop-shadow-[2px_2px_0_black]" >
29- MAIN MENU
30- </ h2 >
47+ < h2 className = "text-xl font-bold tracking-widest text-[#4ADE80] font-sans border-b-4 border-[#4ADE80] pb-2 drop-shadow-[2px_2px_0_black]" >
48+ MAIN MENU
49+ </ h2 >
3150 </ div >
3251
3352 { /* Navigation Items */ }
3453 < ul className = "space-y-4 font-bold" >
3554 { /* Home */ }
3655 < li >
37- < Link
38- href = "/dashboard"
39- className = { getLinkClass ( '/dashboard' ) }
40- >
41- < div className = "flex h-8 w-8 items-center justify-center text-xl mr-3 bg-white border-2 border-black text-black" > 🏠</ div >
56+ < Link href = "/dashboard" className = { getLinkClass ( "/dashboard" ) } >
57+ < div className = "flex h-8 w-8 items-center justify-center text-xl mr-3 bg-white border-2 border-black text-black" >
58+ 🏠
59+ </ div >
4260 < span className = "text-lg" > HOME</ span >
4361 </ Link >
4462 </ li >
45-
63+
4664 { /* Exercises */ }
4765 < li >
48- < Link
49- href = "/exercises"
50- className = { getLinkClass ( '/exercises' ) }
51- >
52- < div className = "flex h-8 w-8 items-center justify-center text-xl mr-3 bg-white border-2 border-black text-black" > ⚔️</ div >
66+ < Link href = "/exercises" className = { getLinkClass ( "/exercises" ) } >
67+ < div className = "flex h-8 w-8 items-center justify-center text-xl mr-3 bg-white border-2 border-black text-black" >
68+ ⚔️
69+ </ div >
5370 < span className = "text-lg" > QUESTS</ span >
5471 </ Link >
5572 </ li >
56-
73+
5774 { /* Grades */ }
5875 < li >
59- < Link
60- href = "/grades"
61- className = { getLinkClass ( '/grades' ) }
62- >
63- < div className = "flex h-8 w-8 items-center justify-center text-xl mr-3 bg-white border-2 border-black text-black" > 📜</ div >
76+ < Link href = "/grades" className = { getLinkClass ( "/grades" ) } >
77+ < div className = "flex h-8 w-8 items-center justify-center text-xl mr-3 bg-white border-2 border-black text-black" >
78+ 📜
79+ </ div >
6480 < span className = "text-lg" > STATS</ span >
6581 </ Link >
6682 </ li >
67-
83+
6884 { /* Rank Measurement */ }
6985 < li >
7086 < Link
7187 href = "/rank-measurement"
72- className = { getLinkClass ( ' /rank-measurement' ) }
88+ className = { getLinkClass ( " /rank-measurement" ) }
7389 >
74- < div className = "flex h-8 w-8 items-center justify-center text-xl mr-3 bg-white border-2 border-black text-black" > 🎯</ div >
90+ < div className = "flex h-8 w-8 items-center justify-center text-xl mr-3 bg-white border-2 border-black text-black" >
91+ 🎯
92+ </ div >
7593 < span className = "text-lg" > RANK</ span >
7694 </ Link >
7795 </ li >
7896 </ ul >
79-
97+
98+ { /* Logout Button */ }
99+ < div className = "mt-auto mb-4" >
100+ < button
101+ onClick = { handleLogout }
102+ disabled = { isLoggingOut }
103+ className = { `
104+ w-full flex items-center p-3 transition-all duration-200
105+ border-4 font-sans rounded-none font-bold tracking-widest text-lg
106+ ${
107+ isLoggingOut
108+ ? "bg-gray-400 border-gray-600 text-gray-700 cursor-not-allowed"
109+ : "bg-[#EF4444] border-black text-white hover:bg-[#DC2626] shadow-[4px_4px_0_black] active:shadow-none active:translate-x-1 active:translate-y-1"
110+ }
111+ ` }
112+ >
113+ < div className = "flex h-8 w-8 items-center justify-center text-xl mr-3 bg-white border-2 border-black text-black" >
114+ { isLoggingOut ? "⏳" : "🚪" }
115+ </ div >
116+ < span > { isLoggingOut ? "LOGGING OUT..." : "LOGOUT" } </ span >
117+ </ button >
118+ </ div >
119+
80120 { /* System Info Box */ }
81121 < div className = "mt-auto border-4 border-black bg-black p-4 text-[#4ADE80] font-sans text-xs tracking-wider" >
82- < p className = "mb-2 border-b border-[#4ADE80] pb-1" > SYSTEM STATUS</ p >
83- < div className = "flex justify-between mb-1" >
84- < span > ONLINE</ span >
85- < span className = "animate-pulse text-[#FCD34D]" > ●</ span >
86- </ div >
87- < div className = "flex justify-between" >
88- < span > VER.</ span >
89- < span > 2.0.26</ span >
90- </ div >
122+ < p className = "mb-2 border-b border-[#4ADE80] pb-1" > SYSTEM STATUS</ p >
123+ < div className = "flex justify-between mb-1" >
124+ < span > ONLINE</ span >
125+ < span className = "animate-pulse text-[#FCD34D]" > ●</ span >
126+ </ div >
127+ < div className = "flex justify-between" >
128+ < span > VER.</ span >
129+ < span > 2.0.26</ span >
130+ </ div >
91131 </ div >
92132 </ div >
93133 </ aside >
0 commit comments