Преглед изворни кода

+ 로그아웃 엑션 수정

송용우 пре 4 месеци
родитељ
комит
a565ada8f5
4 измењених фајлова са 165 додато и 18 уклоњено
  1. 90 3
      .cursor/rules/api-rule.mdc
  2. 33 13
      composables/useLogout.js
  3. 20 1
      stores/detail.js
  4. 22 1
      stores/vendors.js

+ 90 - 3
.cursor/rules/api-rule.mdc

@@ -1,7 +1,91 @@
----
-alwaysApply: true
----
+# API & Store Rules
 
+## Pinia Store Rules
+
+### 1. Setup Syntax Store Reset 구현
+- Setup 문법(`defineStore(() => {...})`)으로 작성된 store는 자동 `$reset()`이 제공되지 않음
+- 반드시 수동으로 `reset()` 함수를 구현해야 함
+```typescript
+// Good
+export const useMyStore = defineStore('myStore', () => {
+  const data = ref([])
+  const loading = ref(false)
+  
+  // 수동으로 reset 함수 구현
+  function reset() {
+    data.value = []
+    loading.value = false
+  }
+  
+  return {
+    data,
+    loading,
+    reset  // reset 함수 반환 필수
+  }
+})
+
+// Bad - reset 함수 없음
+export const useMyStore = defineStore('myStore', () => {
+  const data = ref([])
+  return { data }
+})
+```
+
+### 2. Reset 함수 구현 가이드
+- 모든 state를 초기값으로 되돌리는 로직 포함
+- 중첩된 객체의 경우 깊은 복사 고려
+- persist 옵션이 있는 경우 저장소 데이터도 정리
+```typescript
+function reset() {
+  // 단순 값 초기화
+  simpleValue.value = null
+  
+  // 객체 초기화
+  objectValue.value = {
+    prop1: '',
+    prop2: 0
+  }
+  
+  // 배열 초기화
+  arrayValue.value = []
+  
+  // 중첩 객체 초기화
+  complexValue.value = JSON.parse(JSON.stringify(DEFAULT_STATE))
+}
+```
+
+### 3. Store 초기화 호출 방식
+- Setup 문법 store: `store.reset()`
+- Options 문법 store: `store.$reset()`
+```typescript
+// Setup store
+const setupStore = useSetupStore()
+setupStore.reset()  // O
+setupStore.$reset() // X - 에러 발생
+
+// Options store
+const optionsStore = useOptionsStore()
+optionsStore.$reset() // O
+```
+
+### 4. Store 초기화 시점
+- 로그아웃
+- 사용자 전환
+- 주요 상태 변경
+- 에러 복구
+```typescript
+async function logout() {
+  // 모든 store 초기화
+  authStore.setLogout()
+  setupStore.reset()     // Setup syntax
+  optionsStore.$reset()  // Options syntax
+  
+  // 로컬 스토리지 정리
+  localStorage.clear()
+}
+```
+
+## API Rules
 
 - api 서버는 코드이그나이터4 베이스의 벡엔드 기술로 구현되어있으며
   기존 문서에사용되는 양식을 지키며 구현
@@ -58,4 +142,7 @@ const loadData = async () => {
 - 프론트엔드 → CodeIgniter4 백엔드 직접 호출
 - useAxios()를 통한 HTTP 통신만 사용
 - 응답 형태: `res.data.success`, `res.data.data`, `res.data.message`
+- 백엔드는 직접 만들거야 다만 너가 backend-examples 폴더에 프론트와 수신할수는있는 형태의 api예제를 만들어
+- useAxios()를 통한 HTTP 통신만 사용
+- 응답 형태: `res.data.success`, `res.data.data`, `res.data.message`
 - 백엔드는 직접 만들거야 다만 너가 backend-examples 폴더에 프론트와 수신할수는있는 형태의 api예제를 만들어

+ 33 - 13
composables/useLogout.js

@@ -1,31 +1,45 @@
 import { useAuthStore } from '~/stores/auth'
 import { useVendorsStore } from '~/stores/vendors'
 import { useDetailStore } from '~/stores/detail'
-import { useRouter } from 'vue-router'
 
 export const useLogout = () => {
   const authStore = useAuthStore()
   const vendorsStore = useVendorsStore()
   const detailStore = useDetailStore()
-  const router = useRouter()
   const { $toast } = useNuxtApp()
 
+  const getLoginType = () => {
+    // 1. snsTempData에서 먼저 확인
+    if (authStore.auth.snsTempData?.logintype) {
+      return authStore.auth.snsTempData.logintype
+    }
+    
+    // 2. memberType 기반으로 판단
+    const memberType = authStore.auth.memberType?.toUpperCase()
+    switch (memberType) {
+      case 'VENDOR':
+        return 'vendor'
+      case 'INFLUENCER':
+        return 'influence'
+      default:
+        // 3. 마지막으로 companyId 존재 여부로 판단
+        return authStore.auth.companyId ? 'vendor' : 'influence'
+    }
+  }
+
   const logout = async () => {
     try {
       // 현재 로그인 타입 저장 (로그아웃 전에 미리 저장)
-      const loginType = authStore.auth.snsTempData?.logintype || 'vendor' // 기본값은 vendor
-      
-      // API 호출로 서버 세션 종료 (선택적)
-      await useAxios().post('/api/auth/logout')
+      const loginType = getLoginType()
       
       // auth store 초기화
       authStore.setLogout()
       
       // vendors store 초기화
-      vendorsStore.$reset()
+      vendorsStore.reset()
       
       // detail store 초기화  
-      detailStore.$reset()
+      detailStore.reset()
       
       // localStorage 정리
       localStorage.removeItem('authStore')
@@ -35,16 +49,22 @@ export const useLogout = () => {
       $toast.success('로그아웃되었습니다.')
       
       // 로그인 타입에 따라 적절한 페이지로 리다이렉트
-      router.push(`/?type=${loginType}`)
+      await navigateTo({
+        path: '/',
+        query: { type: loginType }
+      }, { replace: true })
     } catch (error) {
       console.error('로그아웃 중 오류 발생:', error)
       // 오류가 발생해도 로컬 상태는 정리
-      const loginType = authStore.auth.snsTempData?.logintype || 'vendor'
+      const loginType = getLoginType()
       authStore.setLogout()
-      vendorsStore.$reset()
-      detailStore.$reset()
+      vendorsStore.reset()
+      detailStore.reset()
       localStorage.clear()
-      router.push(`/?type=${loginType}`)
+      await navigateTo({
+        path: '/',
+        query: { type: loginType }
+      }, { replace: true })
     }
   }
   

+ 20 - 1
stores/detail.js

@@ -30,5 +30,24 @@ export const useDetailStore = defineStore('detailStore', () => {
     getCompanyId.value = payload
   }
 
-  return {companyId, getCompanyId, menuInfo, boardInfo, setAccountId, adminInfo}
+  function reset() {
+    companyId.value = ''
+    menuInfo.value = {
+      menuIndex : '0',
+      menuId : 'menu02',
+      pageRtName : '미디어 관리',
+      pageStatus : '0',
+    }
+    boardInfo.value = {
+      seq : '',
+      pageType : '',
+      status: '',
+    }
+    adminInfo.value = {
+      adminId : '',
+      pageType : ''
+    }
+  }
+
+  return {companyId, getCompanyId, menuInfo, boardInfo, setAccountId, adminInfo, reset}
 }, {persist: { storage: persistedState.sessionStorage,}})

+ 22 - 1
stores/vendors.js

@@ -73,6 +73,26 @@ export const useVendorsStore = defineStore('vendorsStore', () => {
     }
   }
 
+  // Reset function
+  function reset() {
+    vendors.value = []
+    currentVendor.value = null
+    loading.value = false
+    error.value = null
+    searchConditions.value = {
+      name: '',
+      category: '',
+      page: 1,
+      size: 10
+    }
+    pagination.value = {
+      currentPage: 1,
+      pageSize: 10,
+      totalCount: 0,
+      totalPages: 0
+    }
+  }
+
   // API Actions
   async function searchVendors(conditions = {}) {
     setLoading(true)
@@ -148,7 +168,8 @@ export const useVendorsStore = defineStore('vendorsStore', () => {
     updatePagination,
     resetSearch,
     searchVendors,
-    getVendorById
+    getVendorById,
+    reset
   }
 }, {
   persist: {