index.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. <template>
  2. <div class="admin--login">
  3. <div class="login--container">
  4. <div class="login--box">
  5. <div class="login--logo">
  6. <h1>AUDI</h1>
  7. <p class="subtitle">Admin Panel</p>
  8. </div>
  9. <form @submit.prevent="handleLogin" class="login--form">
  10. <div v-if="errorMessage" class="login--error">
  11. {{ errorMessage }}
  12. </div>
  13. <div class="form--group">
  14. <input
  15. v-model="username"
  16. type="text"
  17. placeholder="아이디"
  18. class="form--input"
  19. required
  20. :disabled="isLoading"
  21. >
  22. </div>
  23. <div class="form--group">
  24. <input
  25. v-model="password"
  26. type="password"
  27. placeholder="비밀번호"
  28. class="form--input"
  29. required
  30. :disabled="isLoading"
  31. >
  32. </div>
  33. <div class="form--options">
  34. <label class="checkbox--label">
  35. <input type="checkbox" v-model="rememberMe" :disabled="isLoading">
  36. <span>로그인 상태 유지</span>
  37. </label>
  38. <a href="#" class="forgot--password">비밀번호 찾기</a>
  39. </div>
  40. <button type="submit" class="login--button" :disabled="isLoading">
  41. {{ isLoading ? '로그인 중...' : '로그인' }}
  42. </button>
  43. </form>
  44. <div class="login--footer">
  45. <p>© 2024 Audi. All rights reserved.</p>
  46. </div>
  47. </div>
  48. </div>
  49. </div>
  50. </template>
  51. <script setup>
  52. import { ref } from 'vue'
  53. definePageMeta({
  54. layout: false,
  55. middleware: ['auth']
  56. })
  57. const { post } = useApi()
  58. const username = ref('')
  59. const password = ref('')
  60. const rememberMe = ref(false)
  61. const isLoading = ref(false)
  62. const errorMessage = ref('')
  63. const handleLogin = async () => {
  64. if (!username.value || !password.value) {
  65. errorMessage.value = '아이디와 비밀번호를 입력해주세요.'
  66. return
  67. }
  68. isLoading.value = true
  69. errorMessage.value = ''
  70. try {
  71. const { data, error } = await post('/auth/login', {
  72. username: username.value,
  73. password: password.value,
  74. remember: rememberMe.value
  75. })
  76. if (error) {
  77. errorMessage.value = error.message || '로그인에 실패했습니다.'
  78. return
  79. }
  80. // API 응답: { success: true, data: { token, admin } }
  81. if (data?.success && data?.data?.token) {
  82. console.log('[Login] 로그인 성공, 토큰 저장:', data.data.token.substring(0, 20) + '...')
  83. localStorage.setItem('admin_token', data.data.token)
  84. if (data.data.admin) {
  85. localStorage.setItem('admin_user', JSON.stringify(data.data.admin))
  86. }
  87. console.log('[Login] localStorage 확인:', localStorage.getItem('admin_token') ? '저장됨' : '저장 실패')
  88. // 로그인 성공 후 dashboard로 이동
  89. await navigateTo('/admin/dashboard')
  90. } else {
  91. errorMessage.value = data?.message || '로그인 정보가 올바르지 않습니다.'
  92. }
  93. } catch (error) {
  94. errorMessage.value = '서버 오류가 발생했습니다.'
  95. console.error('Login error:', error)
  96. } finally {
  97. isLoading.value = false
  98. }
  99. }
  100. </script>