- 로그인 유지: Capacitor Preferences 로 토큰 영속화(앱 재실행 시 로그아웃 방지), 시작 시 세션 복원 후 마운트 - 내역 추가: 계좌 종류(계좌/카드/대출/증권) 콤보 선택 → 해당 종류만 목록에 - 가계부 내역: 일별 그룹 + 일 수입/지출 합계, 항목은 분류·계좌·금액 / 메모·태그(2줄), per-row 날짜 제거 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+37
-11
@@ -1,30 +1,56 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref, computed } from 'vue'
|
||||
import { Preferences } from '@capacitor/preferences'
|
||||
import { authApi } from '@/api/authApi'
|
||||
|
||||
// 세션은 Redis(서버) + localStorage(클라이언트) 양쪽에 보관한다.
|
||||
// 세션 토큰은 Capacitor Preferences(네이티브 영속 저장 / 웹은 localStorage)로 보관한다.
|
||||
// http.js 요청 인터셉터가 동기로 읽을 수 있도록 localStorage 에도 미러링한다.
|
||||
const TOKEN_KEY = 'token'
|
||||
const USER_KEY = 'auth_user'
|
||||
|
||||
export const useAuthStore = defineStore('auth', () => {
|
||||
const token = ref(localStorage.getItem(TOKEN_KEY) || '')
|
||||
const user = ref(safeParse(localStorage.getItem(USER_KEY)))
|
||||
const token = ref('')
|
||||
const user = ref(null)
|
||||
const ready = ref(false)
|
||||
|
||||
const isAuthenticated = computed(() => !!token.value)
|
||||
|
||||
function persist() {
|
||||
// localStorage 동기화 (http.js 가 동기로 토큰을 읽음)
|
||||
function mirrorLocal() {
|
||||
if (token.value) localStorage.setItem(TOKEN_KEY, token.value)
|
||||
else localStorage.removeItem(TOKEN_KEY)
|
||||
|
||||
if (user.value) localStorage.setItem(USER_KEY, JSON.stringify(user.value))
|
||||
else localStorage.removeItem(USER_KEY)
|
||||
}
|
||||
|
||||
async function persist() {
|
||||
mirrorLocal()
|
||||
if (token.value) await Preferences.set({ key: TOKEN_KEY, value: token.value })
|
||||
else await Preferences.remove({ key: TOKEN_KEY })
|
||||
if (user.value) await Preferences.set({ key: USER_KEY, value: JSON.stringify(user.value) })
|
||||
else await Preferences.remove({ key: USER_KEY })
|
||||
}
|
||||
|
||||
// 앱/웹 시작 시 저장된 세션 복원 (자동 로그인). main.js 에서 mount 전 await.
|
||||
async function restore() {
|
||||
try {
|
||||
const t = (await Preferences.get({ key: TOKEN_KEY })).value || localStorage.getItem(TOKEN_KEY) || ''
|
||||
const uRaw = (await Preferences.get({ key: USER_KEY })).value || localStorage.getItem(USER_KEY)
|
||||
token.value = t
|
||||
user.value = safeParse(uRaw)
|
||||
mirrorLocal()
|
||||
} catch {
|
||||
// 무시 — 비로그인 상태로 시작
|
||||
} finally {
|
||||
ready.value = true
|
||||
}
|
||||
}
|
||||
|
||||
async function login(loginId, password, rememberMe = false) {
|
||||
const res = await authApi.login({ loginId, password, rememberMe })
|
||||
token.value = res.token
|
||||
user.value = res.member
|
||||
persist()
|
||||
await persist()
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -36,7 +62,7 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
async function fetchMe() {
|
||||
const me = await authApi.me()
|
||||
user.value = { ...(user.value || {}), ...me }
|
||||
persist()
|
||||
await persist()
|
||||
return me
|
||||
}
|
||||
|
||||
@@ -46,16 +72,16 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
} catch {
|
||||
// 서버 세션이 이미 만료됐어도 클라이언트는 정리
|
||||
}
|
||||
clear()
|
||||
await clear()
|
||||
}
|
||||
|
||||
function clear() {
|
||||
async function clear() {
|
||||
token.value = ''
|
||||
user.value = null
|
||||
persist()
|
||||
await persist()
|
||||
}
|
||||
|
||||
return { token, user, isAuthenticated, login, signup, fetchMe, logout, clear }
|
||||
return { token, user, ready, isAuthenticated, restore, login, signup, fetchMe, logout, clear }
|
||||
})
|
||||
|
||||
function safeParse(value) {
|
||||
|
||||
Reference in New Issue
Block a user