- 가계부: 내역 추가 → month-nav(검색·필터 옆), 헤더는 pending 있을 때만 - 예산: 예산 추가 → month-nav(월 변경 옆) - 고정지출: 지금 반영/추가 → 안내문구 아래 - 커뮤니티: 글쓰기 → 태그 필터와 같은 줄(list-top) - 분류 관리: 기본 분류 불러오기 → 지출/수입 탭과 같은 줄(tabs-row) - 미사용 boardTitle/boardLabel 정리 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -823,9 +823,8 @@ onMounted(async () => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section class="account">
|
<section class="account">
|
||||||
<header class="account-head">
|
<header v-if="pendingCount" class="account-head">
|
||||||
<span class="pending-wrap"><span v-if="pendingCount" class="pending-count">확인 필요 {{ pendingCount }}건</span></span>
|
<span class="pending-count">확인 필요 {{ pendingCount }}건</span>
|
||||||
<IconBtn icon="plus" title="내역 추가" variant="primary" @click="openCreate" />
|
|
||||||
</header>
|
</header>
|
||||||
<Transition name="fade"><p v-if="flashMsg" class="flash">{{ flashMsg }}</p></Transition>
|
<Transition name="fade"><p v-if="flashMsg" class="flash">{{ flashMsg }}</p></Transition>
|
||||||
|
|
||||||
@@ -856,6 +855,7 @@ onMounted(async () => {
|
|||||||
icon="filter" title="검색·필터" class="filter-toggle"
|
icon="filter" title="검색·필터" class="filter-toggle"
|
||||||
:variant="hasFilter ? 'primary' : 'default'" @click="filterOpen = !filterOpen"
|
:variant="hasFilter ? 'primary' : 'default'" @click="filterOpen = !filterOpen"
|
||||||
/>
|
/>
|
||||||
|
<IconBtn icon="plus" title="내역 추가" variant="primary" @click="openCreate" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="filterOpen" class="filter-bar">
|
<div v-if="filterOpen" class="filter-bar">
|
||||||
|
|||||||
@@ -242,16 +242,11 @@ onMounted(() => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section class="budget">
|
<section class="budget">
|
||||||
<header class="head" style="justify-content: flex-end">
|
|
||||||
<div class="head-actions">
|
|
||||||
<IconBtn icon="plus" title="예산 추가" variant="primary" @click="openCreate" />
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<div class="month-nav">
|
<div class="month-nav">
|
||||||
<IconBtn icon="chevronLeft" title="이전 달" size="sm" @click="prevMonth" />
|
<IconBtn icon="chevronLeft" title="이전 달" size="sm" @click="prevMonth" />
|
||||||
<span class="period">{{ periodLabel }}</span>
|
<span class="period">{{ periodLabel }}</span>
|
||||||
<IconBtn icon="chevronRight" title="다음 달" size="sm" @click="nextMonth" />
|
<IconBtn icon="chevronRight" title="다음 달" size="sm" @click="nextMonth" />
|
||||||
|
<IconBtn icon="plus" title="예산 추가" variant="primary" @click="openCreate" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 월 예상 수입 vs 총 예산 -->
|
<!-- 월 예상 수입 vs 총 예산 -->
|
||||||
|
|||||||
@@ -182,17 +182,15 @@ onBeforeUnmount(destroySortables)
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section class="cat">
|
<section class="cat">
|
||||||
<header class="head" style="justify-content: flex-end">
|
|
||||||
<div class="head-actions">
|
|
||||||
<button type="button" class="text-btn" @click="importDefaults">기본 분류 불러오기</button>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
<p class="hint">내역·예산에서 선택할 분류를 관리합니다. <b>대분류 아래 소분류</b>로 묶을 수 있고(2단계), 예산·통계는 소분류 기준입니다. 이름을 바꾸면 기존 내역·예산에도 반영됩니다.</p>
|
<p class="hint">내역·예산에서 선택할 분류를 관리합니다. <b>대분류 아래 소분류</b>로 묶을 수 있고(2단계), 예산·통계는 소분류 기준입니다. 이름을 바꾸면 기존 내역·예산에도 반영됩니다.</p>
|
||||||
|
|
||||||
|
<div class="tabs-row">
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
<button type="button" :class="{ active: activeType === 'EXPENSE' }" @click="activeType = 'EXPENSE'">지출 분류</button>
|
<button type="button" :class="{ active: activeType === 'EXPENSE' }" @click="activeType = 'EXPENSE'">지출 분류</button>
|
||||||
<button type="button" :class="{ active: activeType === 'INCOME' }" @click="activeType = 'INCOME'">수입 분류</button>
|
<button type="button" :class="{ active: activeType === 'INCOME' }" @click="activeType = 'INCOME'">수입 분류</button>
|
||||||
</div>
|
</div>
|
||||||
|
<button type="button" class="text-btn" @click="importDefaults">기본 분류 불러오기</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<form class="new-cat" @submit.prevent="addCategory">
|
<form class="new-cat" @submit.prevent="addCategory">
|
||||||
<select v-model="newParent" class="parent-sel" title="대분류 선택">
|
<select v-model="newParent" class="parent-sel" title="대분류 선택">
|
||||||
@@ -296,6 +294,16 @@ button.danger {
|
|||||||
border-color: #c0392b;
|
border-color: #c0392b;
|
||||||
color: #c0392b;
|
color: #c0392b;
|
||||||
}
|
}
|
||||||
|
.tabs-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 0.75rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
.tabs-row .tabs {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
.tabs {
|
.tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.25rem;
|
gap: 0.25rem;
|
||||||
|
|||||||
@@ -238,13 +238,11 @@ onMounted(load)
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section class="recur">
|
<section class="recur">
|
||||||
<header class="head" style="justify-content: flex-end">
|
<p class="hint">등록한 주기에 맞춰 가계부 진입 시 자동으로 <b>‘확인 필요’</b> 내역이 생성됩니다(중복 없이). 가계부에서 실제 결제·이체를 확인한 뒤 <b>‘확인’</b>을 눌러 확정하세요.</p>
|
||||||
<div class="head-actions">
|
<div class="recur-actions">
|
||||||
<IconBtn icon="refresh" title="지금 반영" @click="runNow" />
|
<IconBtn icon="refresh" title="지금 반영" @click="runNow" />
|
||||||
<IconBtn icon="plus" title="고정 지출 추가" variant="primary" @click="openCreate" />
|
<IconBtn icon="plus" title="고정 지출 추가" variant="primary" @click="openCreate" />
|
||||||
</div>
|
</div>
|
||||||
</header>
|
|
||||||
<p class="hint">등록한 주기에 맞춰 가계부 진입 시 자동으로 <b>‘확인 필요’</b> 내역이 생성됩니다(중복 없이). 가계부에서 실제 결제·이체를 확인한 뒤 <b>‘확인’</b>을 눌러 확정하세요.</p>
|
|
||||||
|
|
||||||
<p v-if="error" class="msg error">{{ error }}</p>
|
<p v-if="error" class="msg error">{{ error }}</p>
|
||||||
<p v-if="loading" class="msg">불러오는 중...</p>
|
<p v-if="loading" class="msg">불러오는 중...</p>
|
||||||
@@ -412,6 +410,12 @@ h1 {
|
|||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
margin: 0.5rem 0 1rem;
|
margin: 0.5rem 0 1rem;
|
||||||
}
|
}
|
||||||
|
.recur-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
button {
|
button {
|
||||||
padding: 0.45rem 0.85rem;
|
padding: 0.45rem 0.85rem;
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid var(--color-border);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { useRoute, useRouter } from 'vue-router'
|
|||||||
import { boardApi } from '@/api/boardApi'
|
import { boardApi } from '@/api/boardApi'
|
||||||
import { formatRelative } from '@/utils/datetime'
|
import { formatRelative } from '@/utils/datetime'
|
||||||
import { useAuthStore } from '@/stores/auth'
|
import { useAuthStore } from '@/stores/auth'
|
||||||
import { boardLabel, DEFAULT_BOARD } from '@/constants/boards'
|
import { DEFAULT_BOARD } from '@/constants/boards'
|
||||||
import IconBtn from '@/components/ui/IconBtn.vue'
|
import IconBtn from '@/components/ui/IconBtn.vue'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
@@ -14,7 +14,6 @@ const isAdmin = computed(() => auth.user?.role === 'ADMIN')
|
|||||||
|
|
||||||
// 현재 게시판(카테고리)
|
// 현재 게시판(카테고리)
|
||||||
const category = computed(() => route.params.category || DEFAULT_BOARD)
|
const category = computed(() => route.params.category || DEFAULT_BOARD)
|
||||||
const boardTitle = computed(() => boardLabel(category.value))
|
|
||||||
|
|
||||||
const posts = ref([])
|
const posts = ref([])
|
||||||
const tags = ref([])
|
const tags = ref([])
|
||||||
@@ -128,11 +127,8 @@ onMounted(loadTags)
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<section class="board">
|
<section class="board">
|
||||||
<header class="board-head" style="justify-content: flex-end">
|
<div class="list-top">
|
||||||
<IconBtn icon="edit" title="글쓰기" variant="primary" @click="router.push(`/board/${category}/write`)" />
|
<div class="tag-filter">
|
||||||
</header>
|
|
||||||
|
|
||||||
<div v-if="tags.length" class="tag-filter">
|
|
||||||
<button
|
<button
|
||||||
v-for="t in tags"
|
v-for="t in tags"
|
||||||
:key="t"
|
:key="t"
|
||||||
@@ -142,6 +138,8 @@ onMounted(loadTags)
|
|||||||
@click="filterByTag(t)"
|
@click="filterByTag(t)"
|
||||||
>{{ t }}</button>
|
>{{ t }}</button>
|
||||||
</div>
|
</div>
|
||||||
|
<IconBtn icon="edit" title="글쓰기" variant="primary" @click="router.push(`/board/${category}/write`)" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 검색 적용 표시 -->
|
<!-- 검색 적용 표시 -->
|
||||||
<div v-if="activeKeyword" class="active-search">
|
<div v-if="activeKeyword" class="active-search">
|
||||||
@@ -247,6 +245,20 @@ button:disabled {
|
|||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
.list-top {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 0.75rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
.list-top .tag-filter {
|
||||||
|
flex: 1;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
.list-top > .icon-btn {
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
.tag-filter {
|
.tag-filter {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|||||||
Reference in New Issue
Block a user