@@ -3,44 +3,55 @@ import Link from 'next/link'
33import React , { ReactNode } from 'react'
44
55import { ROUTES } from '@/src/lib/constants/route'
6- import useAuthStore from '@/src/lib/context/authContext'
6+ import useAuthStore , { AuthState } from '@/src/lib/context/authContext'
77import ToggleWrapper , { useDropdown } from '@/src/lib/hooks/useToggle'
88import { cn } from '@/src/lib/utils/cn'
99import { InstallLink } from '@/src/lib/utils/install-prompt'
10- import { Nullable } from '@/src/lib/utils/typeUtils'
1110
1211import LucideIcon from '../provider/LucideIcon'
1312import { Button } from '../ui/button'
14- import Backdrop from './Backdrop'
1513import Logo from './Logo'
1614
1715const Header = ( ) : ReactNode => {
18- const { studentId, name } = useAuthStore ( )
16+ const authData = useAuthStore ( )
17+
18+ const dropdownData = useDropdown ( )
1919 return (
2020 < >
21- < MobileHeader studentId = { studentId } name = { name } className = 'flex lg:hidden' />
22- < DesktopHeader studentId = { studentId } name = { name } className = 'hidden lg:flex' />
21+ < MobileHeader dropdownData = { dropdownData } authData = { authData } className = 'flex lg:hidden' />
22+ < DesktopHeader dropdownData = { dropdownData } authData = { authData } className = 'hidden lg:flex' />
2323 </ >
2424 )
2525}
2626
2727interface HeaderProps {
28- studentId : Nullable < string >
29- name : Nullable < string >
28+ dropdownData : {
29+ refs : React . RefObject < HTMLDivElement > [ ]
30+ isOpen : boolean
31+ toggleDropdown : ( ) => void
32+ }
33+ authData : AuthState
3034 className ?: string
3135}
3236export default Header
3337
34- const DesktopHeader = ( { studentId, name, className } : HeaderProps ) => {
38+ const DesktopHeader = ( { dropdownData, authData, className } : HeaderProps ) => {
39+ const {
40+ refs : [ buttonRef , dropdownRef ] ,
41+ toggleDropdown,
42+ } = dropdownData
43+ const { studentId, name } = authData
44+
3545 let isLogin : boolean = false
3646 if ( studentId && name ) {
3747 isLogin = true
3848 }
49+
3950 const linkStyle = 'flex items-center justify-center text-lg font-bold hover:border-b hover:border-black hover:border-solid'
4051 return (
4152 < div
4253 className = { cn (
43- 'relative z-10 mt-8 flex h-16 w-[90%] max-w-[1800px] items-center justify-between gap-14 rounded-full bg-swWhite px-12 py-7' ,
54+ 'relative z-50 mt-8 flex h-16 w-[90%] max-w-[1800px] items-center justify-between gap-14 rounded-full bg-swWhite px-12 py-7' ,
4455 className ,
4556 ) }
4657 >
@@ -59,95 +70,158 @@ const DesktopHeader = ({ studentId, name, className }: HeaderProps) => {
5970 이용 수칙
6071 </ Link >
6172 </ div >
62- < div className = 'flex cursor-pointer items-center justify-center gap-8 px-3 py-1 text-lg font-bold' >
73+ < div className = 'flex h-full cursor-pointer items-center justify-center gap-8 px-3 py-1 text-lg font-bold' >
6374 < LucideIcon name = 'Bell' size = { 20 } />
6475 { ! isLogin ? (
6576 < Link href = { ROUTES . AUTH . LOGIN . url } > 로그인</ Link >
6677 ) : (
67- < span >
68- { studentId } / { name }
69- </ span >
78+ < >
79+ < div onClick = { toggleDropdown } ref = { buttonRef } className = 'flex h-full items-center justify-center' >
80+ { studentId } / { name }
81+ </ div >
82+ </ >
7083 ) }
7184 </ div >
85+ < HeaderToggleMenu
86+ authData = { authData }
87+ dropdownData = { dropdownData }
88+ className = 'absolute right-0 top-0 mr-3 mt-20 flex h-fit w-1/2 max-w-56 flex-col items-center justify-start self-end rounded-xl bg-swWhite'
89+ />
7290 </ div >
7391 )
7492}
7593
76- const MobileHeader = ( { studentId , name , className } : HeaderProps ) => {
94+ const MobileHeader = ( { dropdownData , authData , className } : HeaderProps ) => {
7795 const {
78- refs : [ buttonRef , dropdownRef ] ,
79- isOpen : isOpenMenu ,
96+ isOpen,
8097 toggleDropdown,
81- } = useDropdown ( )
98+ refs : [ buttonRef , dropdownRef ] ,
99+ } = dropdownData
100+ const { studentId, name } = authData
101+
82102 let isLogin : boolean = false
83103 if ( studentId && name ) {
84104 isLogin = true
85105 }
106+
86107 return (
87- < >
88- < div className = { cn ( 'fixed z-50 flex h-24 w-screen items-center justify-between bg-swWhite px-8 py-7' , className ) } >
89- < Link href = { ROUTES . MAIN . url } >
90- < Logo text = 'SoKK' className = 'text-4xl' />
91- </ Link >
92- { /* Todo: 버거 메뉴 만들기 */ }
93- < LucideIcon name = 'Menu' size = { 30 } className = 'cursor-pointer' onClick = { toggleDropdown } ref = { buttonRef } />
108+ < div className = { cn ( 'absolute z-50 flex h-24 w-screen items-center justify-between bg-swWhite px-8 py-7' , className ) } >
109+ < Link href = { ROUTES . MAIN . url } >
110+ < Logo text = 'SoKK' className = 'text-4xl' />
111+ </ Link >
112+ { /* Todo: 버거 메뉴 만들기 */ }
113+ < div
114+ ref = { buttonRef }
115+ onClick = { e => {
116+ toggleDropdown ( )
117+ } }
118+ >
119+ < LucideIcon name = 'Menu' size = { 30 } className = 'cursor-pointer' />
94120 </ div >
95- { isOpenMenu && < Backdrop className = 'absolute z-40 mt-24 h-[calc(100%-6rem)] w-screen' /> }
121+ { /* {isOpen && <Backdrop className='fixed top-0 z-40 h-screen w-screen' />} */ }
122+ < HeaderToggleMenu
123+ authData = { authData }
124+ dropdownData = { dropdownData }
125+ className = 'absolute right-0 top-0 z-50 mr-3 mt-28 flex h-fit w-1/2 max-w-56 flex-col items-center justify-start self-end rounded-lg bg-swWhite'
126+ />
127+ </ div >
128+ )
129+ }
96130
97- < ToggleWrapper
98- isOpen = { isOpenMenu }
99- ref = { dropdownRef }
100- className = 'absolute z-40 mr-3 mt-28 flex h-fit w-1/2 flex-col items-center justify-start self-end rounded-lg bg-swWhite'
101- >
102- < div className = 'relative flex w-4/5 flex-col items-center justify-center gap-4 border-b border-solid border-swGray py-8' >
103- < LucideIcon name = 'CircleUserRound' size = { 100 } strokeWidth = { 0.5 } />
104- { isLogin ? (
105- < >
106- < p className = 'mt-4 text-center text-xl font-medium' > { name } </ p >
107- < p className = 'text-center text-swGrayDark' > { studentId } </ p >
108- </ >
109- ) : (
110- < Link className = 'font-s relative h-12 w-4/5' href = { ROUTES . AUTH . LOGIN . url } onClick = { toggleDropdown } >
111- < Button variant = 'swLightGreen' className = 'h-full w-full' >
112- 로그인
113- </ Button >
114- </ Link >
115- ) }
116- </ div >
117-
118- < div className = 'flex w-4/5 flex-col items-center justify-start gap-6 border-b border-solid border-swGray py-8 text-lg font-semibold' >
119- < Link href = { ROUTES . SEAT . RESERVE ( - 1 ) . url } onClick = { toggleDropdown } >
120- 좌석 배정
121- </ Link >
122- < Link href = { ROUTES . SEAT . QR . STEP2 . url } className = 'flex items-center justify-center gap-2' onClick = { toggleDropdown } >
123- < LucideIcon name = 'ScanLine' size = { 24 } />
124- QR 좌석 배정
125- </ Link >
126- </ div >
131+ interface HeaderToggleMenuProps {
132+ dropdownData : {
133+ refs : React . RefObject < HTMLDivElement > [ ]
134+ isOpen : boolean
135+ toggleDropdown : ( ) => void
136+ }
137+ authData : AuthState
138+ className : string
139+ }
140+ const HeaderToggleMenu = ( { dropdownData, authData, className } : HeaderToggleMenuProps ) => {
141+ // const router = useRouter()
142+ const {
143+ isOpen,
144+ refs : [ _ , dropdownRef ] ,
145+ toggleDropdown,
146+ } = dropdownData
147+ const { studentId, name } = authData
127148
128- < div className = 'flex w-4/5 flex-col items-center justify-start gap-6 border-b border-solid border-swGray py-8 text-lg font-semibold' >
129- < Link href = { ROUTES . ROOM . RESERVE . STEP1 . url } onClick = { toggleDropdown } >
130- 스터디룸 예약
131- </ Link >
132- < Link href = { ROUTES . ROOM . HISTORY . url } onClick = { toggleDropdown } >
133- 스터디룸 예약 내역
134- </ Link >
135- </ div >
149+ let isLogin : boolean = false
150+ if ( studentId && name ) {
151+ isLogin = true
152+ }
136153
137- < div className = 'flex w-4/5 flex-col items-center justify-start gap-6 border-b border-solid border-swGray py-8 text-lg font-normal text-swGrayDark' >
138- { /* TODO: 아래 3가지 Route 추가하기*/ }
139- < Link href = { ROUTES . ETC . LOUNGE_RULES . url } onClick = { toggleDropdown } className = 'w-full text-center' >
140- 이용 수칙
141- </ Link >
142- < InstallLink className = 'w-full text-center' > 앱 다운로드</ InstallLink >
143- < Link href = { ROUTES . ETC . PERSONAL_INFO_RULES . url } target = '_blank' onClick = { toggleDropdown } className = 'w-full text-center' >
144- 개인정보 처리방침
145- </ Link >
146- < Link href = { ROUTES . ETC . SERVICE_CENTER . url } target = '_blank' onClick = { toggleDropdown } className = 'w-full text-center' >
147- 문의하기
154+ // Functions
155+ const logoutHandler = ( ) => {
156+ localStorage . removeItem ( 'authData' )
157+ toggleDropdown ( )
158+ location . reload ( )
159+ }
160+
161+ return (
162+ < ToggleWrapper isOpen = { isOpen } className = { cn ( className ) } >
163+ < div className = 'relative flex w-4/5 flex-col items-center justify-center gap-2 border-b border-solid border-swGray py-8' >
164+ < LucideIcon name = 'CircleUserRound' size = { 100 } strokeWidth = { 0.5 } />
165+ { isLogin ? (
166+ < >
167+ < p className = 'mt-4 text-center text-xl font-medium' > { name } </ p >
168+ < p className = 'text-center text-swGrayDark' > { studentId } </ p >
169+ </ >
170+ ) : (
171+ < Link className = 'font-s relative h-12 w-4/5' href = { ROUTES . AUTH . LOGIN . url } onClick = { toggleDropdown } >
172+ < Button variant = 'swLightGreen' className = 'h-full w-full' >
173+ 로그인
174+ </ Button >
148175 </ Link >
149- </ div >
150- </ ToggleWrapper >
151- </ >
176+ ) }
177+ </ div >
178+
179+ < div className = 'flex w-4/5 flex-col items-center justify-start gap-6 border-b border-solid border-swGray py-8 text-lg font-semibold' >
180+ < Link href = { ROUTES . SEAT . RESERVE ( - 1 ) . url } onClick = { toggleDropdown } >
181+ 좌석 배정
182+ </ Link >
183+ < Link href = { ROUTES . SEAT . QR . STEP2 . url } className = 'flex items-center justify-center gap-2' onClick = { toggleDropdown } >
184+ < LucideIcon name = 'ScanLine' size = { 24 } />
185+ QR 좌석 배정
186+ </ Link >
187+ </ div >
188+
189+ < div className = 'flex w-4/5 flex-col items-center justify-start gap-6 border-b border-solid border-swGray py-8 text-lg font-semibold' >
190+ < Link href = { ROUTES . ROOM . RESERVE . STEP1 . url } onClick = { toggleDropdown } >
191+ 스터디룸 예약
192+ </ Link >
193+ < Link href = { ROUTES . ROOM . HISTORY . url } onClick = { toggleDropdown } >
194+ 스터디룸 예약 내역
195+ </ Link >
196+ </ div >
197+
198+ < div className = 'flex w-4/5 flex-col items-center justify-start gap-6 py-8 text-lg font-normal text-swGrayDark' >
199+ < Link href = { ROUTES . ETC . LOUNGE_RULES . url } onClick = { toggleDropdown } className = 'w-full text-center hover:text-swBlack' >
200+ 이용 수칙
201+ </ Link >
202+ < InstallLink className = 'w-full text-center hover:text-swBlack' > 앱 다운로드</ InstallLink >
203+ < Link
204+ href = { ROUTES . ETC . PERSONAL_INFO_RULES . url }
205+ target = '_blank'
206+ onClick = { toggleDropdown }
207+ className = 'w-full text-center hover:text-swBlack'
208+ >
209+ 개인정보 처리방침
210+ </ Link >
211+ < Link
212+ href = { ROUTES . ETC . SERVICE_CENTER . url }
213+ target = '_blank'
214+ onClick = { toggleDropdown }
215+ className = 'w-full text-center hover:text-swBlack'
216+ >
217+ 문의하기
218+ </ Link >
219+ { isLogin && (
220+ < div className = 'flex w-full cursor-pointer items-center justify-center text-center hover:text-swBlack' onClick = { logoutHandler } >
221+ 로그아웃
222+ </ div >
223+ ) }
224+ </ div >
225+ </ ToggleWrapper >
152226 )
153227}
0 commit comments