Merge branch 'dev'
This commit is contained in:
@@ -6,10 +6,14 @@ import { setActivePinia, createPinia } from 'pinia'
|
|||||||
const { pushMock } = vi.hoisted(() => ({ pushMock: vi.fn() }))
|
const { pushMock } = vi.hoisted(() => ({ pushMock: vi.fn() }))
|
||||||
vi.mock('vue-router', () => ({ useRouter: () => ({ push: pushMock }) }))
|
vi.mock('vue-router', () => ({ useRouter: () => ({ push: pushMock }) }))
|
||||||
|
|
||||||
|
// 아이디 로그인 플로우 검증용 — 운영에선 숨김(ID_LOGIN_ENABLED=false)이지만 로직은 유지되므로 켜서 테스트
|
||||||
|
vi.mock('@/config/features', () => ({ ID_LOGIN_ENABLED: true }))
|
||||||
|
|
||||||
vi.mock('@/api/authApi', () => ({
|
vi.mock('@/api/authApi', () => ({
|
||||||
authApi: {
|
authApi: {
|
||||||
login: vi.fn(),
|
login: vi.fn(),
|
||||||
signupEnabled: vi.fn(() => Promise.resolve({ enabled: true })),
|
signupEnabled: vi.fn(() => Promise.resolve({ enabled: true })),
|
||||||
|
googleClientId: vi.fn(() => Promise.resolve({ clientId: '' })),
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { useAuthStore } from '@/stores/auth'
|
|||||||
import { useUiStore } from '@/stores/ui'
|
import { useUiStore } from '@/stores/ui'
|
||||||
import { authApi } from '@/api/authApi'
|
import { authApi } from '@/api/authApi'
|
||||||
import { isNativeGoogle, nativeGoogleIdToken } from '@/native/googleAuth'
|
import { isNativeGoogle, nativeGoogleIdToken } from '@/native/googleAuth'
|
||||||
|
import { ID_LOGIN_ENABLED } from '@/config/features'
|
||||||
|
|
||||||
const auth = useAuthStore()
|
const auth = useAuthStore()
|
||||||
const ui = useUiStore()
|
const ui = useUiStore()
|
||||||
@@ -173,7 +174,7 @@ onUnmounted(() => window.removeEventListener('keydown', onKeydown))
|
|||||||
<button class="close" type="button" aria-label="닫기" @click="ui.closeLogin()">×</button>
|
<button class="close" type="button" aria-label="닫기" @click="ui.closeLogin()">×</button>
|
||||||
<h2>로그인</h2>
|
<h2>로그인</h2>
|
||||||
|
|
||||||
<form class="form" @submit.prevent="handleLogin">
|
<form v-if="ID_LOGIN_ENABLED" class="form" @submit.prevent="handleLogin">
|
||||||
<input v-model="form.loginId" type="text" placeholder="아이디" autocomplete="username" :disabled="loading" />
|
<input v-model="form.loginId" type="text" placeholder="아이디" autocomplete="username" :disabled="loading" />
|
||||||
<input v-model="form.password" type="password" placeholder="비밀번호" autocomplete="current-password" :disabled="loading" />
|
<input v-model="form.password" type="password" placeholder="비밀번호" autocomplete="current-password" :disabled="loading" />
|
||||||
<label class="remember">
|
<label class="remember">
|
||||||
@@ -187,7 +188,7 @@ onUnmounted(() => window.removeEventListener('keydown', onKeydown))
|
|||||||
|
|
||||||
<!-- 구글 로그인 — 서버에 클라이언트 ID 가 설정된 경우에만 노출 -->
|
<!-- 구글 로그인 — 서버에 클라이언트 ID 가 설정된 경우에만 노출 -->
|
||||||
<div v-show="googleClientId" class="google-wrap">
|
<div v-show="googleClientId" class="google-wrap">
|
||||||
<div class="divider"><span>또는</span></div>
|
<div v-if="ID_LOGIN_ENABLED" class="divider"><span>또는</span></div>
|
||||||
<!-- 앱(안드로이드): 네이티브 버튼 / 웹·PC: GIS 렌더 버튼 -->
|
<!-- 앱(안드로이드): 네이티브 버튼 / 웹·PC: GIS 렌더 버튼 -->
|
||||||
<button
|
<button
|
||||||
v-if="isNative"
|
v-if="isNative"
|
||||||
@@ -211,7 +212,7 @@ onUnmounted(() => window.removeEventListener('keydown', onKeydown))
|
|||||||
네이버로 로그인 (준비 중)
|
네이버로 로그인 (준비 중)
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<p class="links">
|
<p v-if="ID_LOGIN_ENABLED" class="links">
|
||||||
<template v-if="ui.signupEnabled">
|
<template v-if="ui.signupEnabled">
|
||||||
계정이 없으신가요?
|
계정이 없으신가요?
|
||||||
<a href="#" @click.prevent="goSignup">회원가입</a>
|
<a href="#" @click.prevent="goSignup">회원가입</a>
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
// 로그인 방식 기능 플래그.
|
||||||
|
// 구글 로그인만 운영하므로 아이디 로그인 폼 / 회원가입 UI 를 숨긴다.
|
||||||
|
// 백엔드(/api/auth/login, /api/auth/signup)는 비상용으로 그대로 유지 —
|
||||||
|
// 되돌리려면 이 값을 true 로 바꾸면 아이디 로그인/회원가입이 다시 노출된다.
|
||||||
|
export const ID_LOGIN_ENABLED = false
|
||||||
@@ -4,6 +4,7 @@ import { RouterLink } from 'vue-router'
|
|||||||
import { useAuthStore } from '@/stores/auth'
|
import { useAuthStore } from '@/stores/auth'
|
||||||
import { useUiStore } from '@/stores/ui'
|
import { useUiStore } from '@/stores/ui'
|
||||||
import { accountApi } from '@/api/accountApi'
|
import { accountApi } from '@/api/accountApi'
|
||||||
|
import { ID_LOGIN_ENABLED } from '@/config/features'
|
||||||
|
|
||||||
const auth = useAuthStore()
|
const auth = useAuthStore()
|
||||||
const ui = useUiStore()
|
const ui = useUiStore()
|
||||||
@@ -296,9 +297,9 @@ onMounted(load)
|
|||||||
<p class="tagline">슬림하게 관리하는 가계부 · 자산 · 예산</p>
|
<p class="tagline">슬림하게 관리하는 가계부 · 자산 · 예산</p>
|
||||||
<div class="cta">
|
<div class="cta">
|
||||||
<button type="button" class="btn primary" @click="ui.openLogin('/account')">로그인</button>
|
<button type="button" class="btn primary" @click="ui.openLogin('/account')">로그인</button>
|
||||||
<button v-if="ui.signupEnabled" type="button" class="btn" @click="ui.openSignup()">회원가입</button>
|
<button v-if="ID_LOGIN_ENABLED && ui.signupEnabled" type="button" class="btn" @click="ui.openSignup()">회원가입</button>
|
||||||
</div>
|
</div>
|
||||||
<p class="cta-note">{{ ui.signupEnabled ? '로그인하면 나의 가계부 요약을 볼 수 있어요.' : '현재 회원가입이 제한되어 있습니다.' }}</p>
|
<p class="cta-note">{{ !ID_LOGIN_ENABLED || ui.signupEnabled ? '로그인하면 나의 가계부 요약을 볼 수 있어요.' : '현재 회원가입이 제한되어 있습니다.' }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul class="features">
|
<ul class="features">
|
||||||
|
|||||||
Reference in New Issue
Block a user