header.vue 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. <template>
  2. <header class="user--header">
  3. <div class="header--wrap">
  4. <NuxtLink to="/" class="header--logo"><i class="logo"></i><h1>파이럿존</h1></NuxtLink>
  5. <button v-if="isLoggedIn" type="button" @click="handleLogout">로그아웃</button>
  6. <NuxtLink v-else to="/login" class="header--login-link">로그인</NuxtLink>
  7. </div>
  8. <AppAlertModal
  9. v-model="confirmModal"
  10. type="confirm"
  11. icon-type="info"
  12. title="로그아웃"
  13. message="로그아웃 하시겠습니까?"
  14. confirm-text="로그아웃"
  15. cancel-text="취소"
  16. @confirm="doLogout"
  17. />
  18. </header>
  19. </template>
  20. <script setup>
  21. import { ref, onMounted } from 'vue'
  22. import { useRouter } from 'vue-router'
  23. import AppAlertModal from '~/components/AppAlertModal.vue'
  24. const router = useRouter()
  25. const { post } = useApi()
  26. const isLoggedIn = ref(false)
  27. const confirmModal = ref(false)
  28. const checkAuth = () => {
  29. const token = localStorage.getItem('user_token') || sessionStorage.getItem('user_token')
  30. const expires = localStorage.getItem('user_token_expires') || sessionStorage.getItem('user_token_expires')
  31. isLoggedIn.value = !!(token && expires && new Date(expires.replace(' ', 'T')) > new Date())
  32. }
  33. const handleLogout = () => {
  34. confirmModal.value = true
  35. }
  36. const clearAuth = () => {
  37. ['user_token', 'user_token_expires', 'user', 'auto_login'].forEach((k) => {
  38. localStorage.removeItem(k)
  39. sessionStorage.removeItem(k)
  40. })
  41. }
  42. const doLogout = async () => {
  43. const token = localStorage.getItem('user_token') || sessionStorage.getItem('user_token')
  44. // 백엔드 토큰 삭제 (실패해도 무시 — 클라이언트 정리는 무조건 진행)
  45. if (token) {
  46. try {
  47. await post('/users/logout', null, {
  48. headers: { Authorization: `Bearer ${token}` }
  49. })
  50. } catch (e) {
  51. console.warn('[Logout] API failed but proceeding:', e)
  52. }
  53. }
  54. clearAuth()
  55. isLoggedIn.value = false
  56. router.push('/login')
  57. }
  58. onMounted(() => {
  59. checkAuth()
  60. // 다른 탭에서 로그인/아웃 시 동기화
  61. window.addEventListener('storage', checkAuth)
  62. })
  63. </script>