diff --git a/src/views/account/AccountWalletView.vue b/src/views/account/AccountWalletView.vue index 3028055..6a29137 100644 --- a/src/views/account/AccountWalletView.vue +++ b/src/views/account/AccountWalletView.vue @@ -37,10 +37,47 @@ const form = reactive({ const submitting = ref(false) const formError = ref(null) -// 드롭다운(계좌별 내역) +// 드롭다운(계좌별 내역) — 월별로 표시 const expandedId = ref(null) const entriesByWallet = reactive({}) const loadingEntries = ref(false) +const entryMonth = reactive({}) // 계좌별 선택 월(YYYY-MM) + +function currentYm() { + const d = new Date() + return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}` +} +function ymLabel(ym) { + return ym ? ym.replace('-', '.') : '' +} +// 데이터가 있는 월 목록(오름차순) +function monthList(w) { + const set = new Set((entriesByWallet[w.id] || []).map((e) => (e.entryDate || '').slice(0, 7)).filter(Boolean)) + return [...set].sort() +} +function monthEntries(w) { + const ym = entryMonth[w.id] + return (entriesByWallet[w.id] || []).filter((e) => (e.entryDate || '').slice(0, 7) === ym) +} +function monthSum(w) { + return monthEntries(w).reduce((s, e) => s + effectAmount(e, w.id), 0) +} +function canPrev(w) { + return monthList(w).indexOf(entryMonth[w.id]) > 0 +} +function canNext(w) { + const ms = monthList(w) + const i = ms.indexOf(entryMonth[w.id]) + return i >= 0 && i < ms.length - 1 +} +// 데이터가 있는 월 사이로만 이동(빈 달 건너뜀) +function shiftMonth(w, delta) { + const ms = monthList(w) + if (!ms.length) return + const i = ms.indexOf(entryMonth[w.id]) + const j = Math.min(ms.length - 1, Math.max(0, (i === -1 ? ms.length - 1 : i) + delta)) + entryMonth[w.id] = ms[j] +} const isLiability = (t) => t === 'CARD' || t === 'LOAN' @@ -109,6 +146,9 @@ async function toggleExpand(w) { loadingEntries.value = true try { entriesByWallet[w.id] = await accountApi.walletEntries(w.id) + // 기본 선택 월 = 내역이 있는 가장 최근 월(없으면 이번 달) + const ms = monthList(w) + entryMonth[w.id] = ms.length ? ms[ms.length - 1] : currentYm() } catch { entriesByWallet[w.id] = [] } finally { @@ -366,15 +406,27 @@ onBeforeUnmount(() => sortable?.destroy()) @@ -576,6 +628,45 @@ button.primary { font-size: 0.78rem; margin: 0; } +.month-nav { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.3rem 0 0.4rem; + border-bottom: 1px solid var(--color-border); + margin-bottom: 0.3rem; +} +.mn-btn { + width: 1.8rem; + height: 1.8rem; + border: 1px solid var(--color-border); + border-radius: 4px; + background: var(--color-background-soft); + color: var(--color-text); + cursor: pointer; + line-height: 1; +} +.mn-btn:disabled { + opacity: 0.35; + cursor: not-allowed; +} +.mn-label { + font-weight: 700; + font-size: 0.9rem; + min-width: 4.2rem; + text-align: center; +} +.mn-sum { + margin-left: auto; + font-size: 0.82rem; + font-weight: 600; +} +.mn-sum.pos { + color: #2e7d32; +} +.mn-sum.neg { + color: #c0392b; +} .drop-list { list-style: none; }