Merge branch 'dev'
Deploy / deploy (push) Failing after 14m4s
CI / build (push) Failing after 15m32s

This commit is contained in:
ByungCheol
2026-06-27 23:19:30 +09:00
5 changed files with 56 additions and 37 deletions
+3 -3
View File
@@ -823,9 +823,8 @@ onMounted(async () => {
<template>
<section class="account">
<header class="account-head">
<span class="pending-wrap"><span v-if="pendingCount" class="pending-count">확인 필요 {{ pendingCount }}</span></span>
<IconBtn icon="plus" title="내역 추가" variant="primary" @click="openCreate" />
<header v-if="pendingCount" class="account-head">
<span class="pending-count">확인 필요 {{ pendingCount }}</span>
</header>
<Transition name="fade"><p v-if="flashMsg" class="flash">{{ flashMsg }}</p></Transition>
@@ -856,6 +855,7 @@ onMounted(async () => {
icon="filter" title="검색·필터" class="filter-toggle"
:variant="hasFilter ? 'primary' : 'default'" @click="filterOpen = !filterOpen"
/>
<IconBtn icon="plus" title="내역 추가" variant="primary" @click="openCreate" />
</div>
<div v-if="filterOpen" class="filter-bar">
+1 -6
View File
@@ -242,16 +242,11 @@ onMounted(() => {
<template>
<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">
<IconBtn icon="chevronLeft" title="이전 달" size="sm" @click="prevMonth" />
<span class="period">{{ periodLabel }}</span>
<IconBtn icon="chevronRight" title="다음 달" size="sm" @click="nextMonth" />
<IconBtn icon="plus" title="예산 추가" variant="primary" @click="openCreate" />
</div>
<!-- 예상 수입 vs 예산 -->
+13 -5
View File
@@ -182,17 +182,15 @@ onBeforeUnmount(destroySortables)
<template>
<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>
<div class="tabs-row">
<div class="tabs">
<button type="button" :class="{ active: activeType === 'EXPENSE' }" @click="activeType = 'EXPENSE'">지출 분류</button>
<button type="button" :class="{ active: activeType === 'INCOME' }" @click="activeType = 'INCOME'">수입 분류</button>
</div>
<button type="button" class="text-btn" @click="importDefaults">기본 분류 불러오기</button>
</div>
<form class="new-cat" @submit.prevent="addCategory">
<select v-model="newParent" class="parent-sel" title="대분류 선택">
@@ -296,6 +294,16 @@ button.danger {
border-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 {
display: flex;
gap: 0.25rem;
+8 -4
View File
@@ -238,13 +238,11 @@ onMounted(load)
<template>
<section class="recur">
<header class="head" style="justify-content: flex-end">
<div class="head-actions">
<p class="hint">등록한 주기에 맞춰 가계부 진입 자동으로 <b>확인 필요</b> 내역이 생성됩니다(중복 없이). 가계부에서 실제 결제·이체를 확인한 <b>확인</b> 눌러 확정하세요.</p>
<div class="recur-actions">
<IconBtn icon="refresh" title="지금 반영" @click="runNow" />
<IconBtn icon="plus" title="고정 지출 추가" variant="primary" @click="openCreate" />
</div>
</header>
<p class="hint">등록한 주기에 맞춰 가계부 진입 자동으로 <b>확인 필요</b> 내역이 생성됩니다(중복 없이). 가계부에서 실제 결제·이체를 확인한 <b>확인</b> 눌러 확정하세요.</p>
<p v-if="error" class="msg error">{{ error }}</p>
<p v-if="loading" class="msg">불러오는 중...</p>
@@ -412,6 +410,12 @@ h1 {
opacity: 0.7;
margin: 0.5rem 0 1rem;
}
.recur-actions {
display: flex;
justify-content: flex-end;
gap: 0.5rem;
margin-bottom: 1rem;
}
button {
padding: 0.45rem 0.85rem;
border: 1px solid var(--color-border);
+19 -7
View File
@@ -4,7 +4,7 @@ import { useRoute, useRouter } from 'vue-router'
import { boardApi } from '@/api/boardApi'
import { formatRelative } from '@/utils/datetime'
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'
const route = useRoute()
@@ -14,7 +14,6 @@ const isAdmin = computed(() => auth.user?.role === 'ADMIN')
// 현재 게시판(카테고리)
const category = computed(() => route.params.category || DEFAULT_BOARD)
const boardTitle = computed(() => boardLabel(category.value))
const posts = ref([])
const tags = ref([])
@@ -128,11 +127,8 @@ onMounted(loadTags)
<template>
<section class="board">
<header class="board-head" style="justify-content: flex-end">
<IconBtn icon="edit" title="글쓰기" variant="primary" @click="router.push(`/board/${category}/write`)" />
</header>
<div v-if="tags.length" class="tag-filter">
<div class="list-top">
<div class="tag-filter">
<button
v-for="t in tags"
:key="t"
@@ -142,6 +138,8 @@ onMounted(loadTags)
@click="filterByTag(t)"
>{{ t }}</button>
</div>
<IconBtn icon="edit" title="글쓰기" variant="primary" @click="router.push(`/board/${category}/write`)" />
</div>
<!-- 검색 적용 표시 -->
<div v-if="activeKeyword" class="active-search">
@@ -247,6 +245,20 @@ button:disabled {
opacity: 0.5;
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 {
display: flex;
flex-wrap: wrap;