feat: 둘러보기(데모)를 실제 화면 그대로 — 데모 모드 + API 더미 응답

- src/demo: demo.on 플래그 + DTO 형태 더미데이터 + mock API(읽기 더미/쓰기 차단)
- accountApi: Proxy 로 데모 시 읽기→더미, 쓰기→안내. 실제 뷰 그대로 렌더
- App: authed=인증||데모 → 실제 사이드바/셸 표시 + 데모 배너(로그인/나가기)
- 라우터: 데모 허용(가계부/고정/계좌/분류) 외 보호화면은 DemoLockedView(로그인 유도)
- 사이드바: 데모 시 잠금(🔒) 배지, 메뉴는 showMenu(인증||데모)
- 로그인/로그아웃 시 데모 자동 해제, 랜딩 '둘러보기'→enterDemo
- 기존 독립 DemoView 제거

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
ByungCheol
2026-06-28 07:49:37 +09:00
parent 80e1faec09
commit 4ffc01f484
10 changed files with 331 additions and 483 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ const route = useRoute()
// 라우트별 헤더 타이틀(현재 화면 이름)
const TITLES = {
home: '돈돼지 가계부',
demo: '둘러보기',
'demo-locked': '둘러보기',
'account-entries': '가계부 내역',
'account-stats': '통계',
'account-recurrings': '고정 지출',
+14 -1
View File
@@ -1,11 +1,15 @@
<script setup>
import { computed } from 'vue'
import { RouterLink } from 'vue-router'
import { useAuthStore } from '@/stores/auth'
import { useUiStore } from '@/stores/ui'
import { BOARDS } from '@/constants/boards'
import { demo } from '@/demo'
const auth = useAuthStore()
const ui = useUiStore()
// 로그인 또는 둘러보기(데모)면 메뉴 노출. 데모에선 잠금 배지를 함께 표시.
const showMenu = computed(() => auth.isAuthenticated || demo.on)
// 메뉴 아이콘 (lucide 스타일 인라인 SVG path — 하단 내비와 동일 톤). 값은 정적/신뢰 마크업.
const icons = {
@@ -33,7 +37,7 @@ const icons = {
</div>
<nav class="menu">
<!-- 가계부 영역 (홈은 하단 내비게이션으로 이동) -->
<template v-if="auth.isAuthenticated">
<template v-if="showMenu">
<RouterLink to="/account/entries" class="menu-item">
<svg class="menu-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" v-html="icons.entries" />
<span>가계부 내역</span>
@@ -41,6 +45,7 @@ const icons = {
<RouterLink to="/account/stats" class="menu-item">
<svg class="menu-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" v-html="icons.stats" />
<span>통계</span>
<span v-if="demo.on" class="lock-badge">🔒</span>
</RouterLink>
<RouterLink to="/account/recurrings" class="menu-item">
<svg class="menu-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" v-html="icons.recurrings" />
@@ -57,10 +62,12 @@ const icons = {
<RouterLink to="/account/budget" class="menu-item">
<svg class="menu-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" v-html="icons.budget" />
<span>예산 설정</span>
<span v-if="demo.on" class="lock-badge">🔒</span>
</RouterLink>
<RouterLink to="/account/tags" class="menu-item">
<svg class="menu-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" v-html="icons.tags" />
<span>태그 관리</span>
<span v-if="demo.on" class="lock-badge">🔒</span>
</RouterLink>
<!-- 게시판 영역 -->
@@ -73,6 +80,7 @@ const icons = {
>
<svg class="menu-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" v-html="icons.board" />
<span>{{ b.label }}</span>
<span v-if="demo.on" class="lock-badge">🔒</span>
</RouterLink>
</template>
@@ -169,6 +177,11 @@ const icons = {
flex: none;
opacity: 0.8;
}
.lock-badge {
margin-left: auto;
font-size: 0.72rem;
opacity: 0.55;
}
.menu-item.router-link-exact-active .menu-icon {
opacity: 1;
}