Simplify ledger summary and nav icons
This commit is contained in:
1
assets/icons/account_balance_wallet.svg
Normal file
1
assets/icons/account_balance_wallet.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M200-200v-560 560Zm0 80q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v100h-80v-100H200v560h560v-100h80v100q0 33-23.5 56.5T760-120H200Zm320-160q-33 0-56.5-23.5T440-360v-240q0-33 23.5-56.5T520-680h280q33 0 56.5 23.5T880-600v240q0 33-23.5 56.5T800-280H520Zm280-80v-240H520v240h280Zm-117.5-77.5Q700-455 700-480t-17.5-42.5Q665-540 640-540t-42.5 17.5Q580-505 580-480t17.5 42.5Q615-420 640-420t42.5-17.5Z"/></svg>
|
||||
|
After Width: | Height: | Size: 555 B |
1
assets/icons/bar_chart.svg
Normal file
1
assets/icons/bar_chart.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M640-160v-280h160v280H640Zm-240 0v-640h160v640H400Zm-240 0v-440h160v440H160Z"/></svg>
|
||||
|
After Width: | Height: | Size: 201 B |
1
assets/icons/receipt_long.svg
Normal file
1
assets/icons/receipt_long.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M240-80q-50 0-85-35t-35-85v-120h120v-560l60 60 60-60 60 60 60-60 60 60 60-60 60 60 60-60 60 60 60-60v680q0 50-35 85t-85 35H240Zm480-80q17 0 28.5-11.5T760-200v-560H320v440h360v120q0 17 11.5 28.5T720-160ZM360-600v-80h240v80H360Zm0 120v-80h240v80H360Zm320-120q-17 0-28.5-11.5T640-640q0-17 11.5-28.5T680-680q17 0 28.5 11.5T720-640q0 17-11.5 28.5T680-600Zm0 120q-17 0-28.5-11.5T640-520q0-17 11.5-28.5T680-560q17 0 28.5 11.5T720-520q0 17-11.5 28.5T680-480ZM240-160h360v-80H200v40q0 17 11.5 28.5T240-160Zm-40 0v-80 80Z"/></svg>
|
||||
|
After Width: | Height: | Size: 636 B |
1
assets/icons/settings.svg
Normal file
1
assets/icons/settings.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="m370-80-16-128q-13-5-24.5-12T307-235l-119 50L78-375l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78-585l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12L590-80H370Zm70-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z"/></svg>
|
||||
|
After Width: | Height: | Size: 771 B |
@@ -26,3 +26,6 @@
|
||||
- 거래 목록의 카테고리 표시는 하위 카테고리명 중심으로 단순화했다.
|
||||
- 내역 화면 상단을 헤더, 월 요약, 주간 날짜 스트립 구조로 개편했다.
|
||||
- 방향 이동 버튼을 `assets/icons`의 SVG 화살표로 통일했다.
|
||||
- 내역 화면의 선택일 요약 박스를 제거하고 날짜별 수입/지출 금액을 주간 날짜 셀 안에 작게 표시했다.
|
||||
- 월 지출 하단 설명을 수입/차액 대신 지난달 대비 지출 비교 문구로 단순화했다.
|
||||
- 하단 네비게이션과 PC 사이드바에 SVG 메뉴 아이콘을 적용하고 활성 탭 색상을 명확하게 표시했다.
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
v-for="item in items"
|
||||
:key="item.to"
|
||||
:to="item.to"
|
||||
class="mb-2 flex min-h-12 items-center gap-3 rounded-md px-4 text-sm font-semibold text-muted"
|
||||
active-class="bg-red-50 text-red-600"
|
||||
class="mb-2 flex min-h-12 items-center gap-3 rounded-md px-4 text-sm font-semibold"
|
||||
:class="isActive(item.to) ? 'bg-red-50 text-red-600' : 'text-muted hover:bg-paper'"
|
||||
>
|
||||
<span class="text-lg leading-none">{{ item.icon }}</span>
|
||||
<span class="h-6 w-6 bg-current" :style="iconStyle(item.icon)" aria-hidden="true" />
|
||||
<span>{{ item.label }}</span>
|
||||
</NuxtLink>
|
||||
</nav>
|
||||
@@ -36,10 +36,10 @@
|
||||
v-for="item in items"
|
||||
:key="item.to"
|
||||
:to="item.to"
|
||||
class="flex min-h-14 flex-col items-center justify-center gap-0.5 text-[11px] font-medium text-muted"
|
||||
active-class="text-brand-700"
|
||||
class="flex min-h-14 flex-col items-center justify-center gap-0.5 text-[11px] font-bold"
|
||||
:class="isActive(item.to) ? 'text-red-600' : 'text-muted'"
|
||||
>
|
||||
<span class="text-lg leading-none">{{ item.icon }}</span>
|
||||
<span class="h-6 w-6 bg-current" :style="iconStyle(item.icon)" aria-hidden="true" />
|
||||
<span>{{ item.label }}</span>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
@@ -56,15 +56,31 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import assetIcon from '~/assets/icons/account_balance_wallet.svg'
|
||||
import reportIcon from '~/assets/icons/bar_chart.svg'
|
||||
import receiptIcon from '~/assets/icons/receipt_long.svg'
|
||||
import settingsIcon from '~/assets/icons/settings.svg'
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const items = [
|
||||
{ to: '/', label: '내역', icon: '≡' },
|
||||
{ to: '/stats', label: '통계', icon: '∑' },
|
||||
{ to: '/assets', label: '자산', icon: '◎' },
|
||||
{ to: '/settings', label: '설정', icon: '⚙' }
|
||||
{ to: '/', label: '내역', icon: receiptIcon },
|
||||
{ to: '/stats', label: '통계', icon: reportIcon },
|
||||
{ to: '/assets', label: '자산', icon: assetIcon },
|
||||
{ to: '/settings', label: '설정', icon: settingsIcon }
|
||||
]
|
||||
|
||||
const showNav = computed(() => route.path !== '/login')
|
||||
const showFab = computed(() => showNav.value && route.path !== '/add' && !route.path.startsWith('/transactions/'))
|
||||
|
||||
function isActive(to: string) {
|
||||
return to === '/' ? route.path === '/' : route.path.startsWith(to)
|
||||
}
|
||||
|
||||
function iconStyle(icon: string) {
|
||||
return {
|
||||
mask: `url(${icon}) center / contain no-repeat`,
|
||||
WebkitMask: `url(${icon}) center / contain no-repeat`
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -31,8 +31,7 @@
|
||||
{{ formatWon(data?.summary.expense || 0) }}
|
||||
</p>
|
||||
<p class="mt-2 text-sm font-semibold text-muted">
|
||||
수입 <span class="text-brand-700">{{ formatWon(data?.summary.income || 0) }}</span>
|
||||
· 차액 <span :class="(data?.summary.diff || 0) >= 0 ? 'text-brand-700' : 'text-red-600'">{{ formatWon(data?.summary.diff || 0) }}</span>
|
||||
{{ monthlyComparisonLabel }}
|
||||
</p>
|
||||
</div>
|
||||
<NuxtLink to="/stats" class="btn-secondary flex shrink-0 gap-2 px-3 text-xs md:px-4">
|
||||
@@ -53,7 +52,7 @@
|
||||
v-for="day in weekDays"
|
||||
:key="day.key"
|
||||
type="button"
|
||||
class="min-h-[4.75rem] rounded-md px-1 py-2"
|
||||
class="min-h-[4.35rem] rounded-md px-1 py-2"
|
||||
:class="day.key === selectedDate ? 'text-ink' : day.inMonth ? 'text-muted active:bg-paper' : 'text-slate-300'"
|
||||
@click="selectDate(day.key)"
|
||||
>
|
||||
@@ -63,26 +62,12 @@
|
||||
>
|
||||
{{ day.day }}
|
||||
</span>
|
||||
<span class="mt-1 block min-h-4 truncate text-[11px] font-bold" :class="day.key === selectedDate ? 'text-ink' : ''">
|
||||
{{ day.amountLabel }}
|
||||
<span class="mt-1 block min-h-7 space-y-0.5 text-[10px] font-bold leading-none">
|
||||
<span v-if="day.expenseLabel" class="block truncate text-red-500">{{ day.expenseLabel }}</span>
|
||||
<span v-if="day.incomeLabel" class="block truncate text-brand-700">{{ day.incomeLabel }}</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="mt-2 grid grid-cols-3 gap-2 rounded-md bg-paper px-3 py-2 text-center text-xs font-semibold">
|
||||
<div>
|
||||
<p class="text-muted">선택일 수입</p>
|
||||
<p class="mt-0.5 text-brand-700">{{ formatWon(selectedDaySummary.income) }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-muted">선택일 지출</p>
|
||||
<p class="mt-0.5 text-red-600">{{ formatWon(selectedDaySummary.expense) }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-muted">합계</p>
|
||||
<p class="mt-0.5">{{ formatWon(selectedDaySummary.diff) }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
@@ -113,9 +98,17 @@ import type { Transaction } from '~/composables/useMoney'
|
||||
const selectedDate = ref(formatDateOnly())
|
||||
const weekSwipeStartX = ref(0)
|
||||
const selectedMonth = computed(() => monthKey(parse(selectedDate.value, 'yyyy-MM-dd', new Date())))
|
||||
const previousMonth = computed(() => {
|
||||
const date = parse(selectedMonth.value, 'yyyy-MM', new Date())
|
||||
return format(addMonths(date, -1), 'yyyy-MM')
|
||||
})
|
||||
const { data } = await useFetch('/api/transactions', {
|
||||
query: { month: selectedMonth }
|
||||
})
|
||||
const { data: previousData } = await useFetch('/api/transactions', {
|
||||
key: computed(() => `transactions-previous-${previousMonth.value}`),
|
||||
query: { month: previousMonth }
|
||||
})
|
||||
const weekdays = ['일', '월', '화', '수', '목', '금', '토']
|
||||
|
||||
const groupedTransactions = computed(() => {
|
||||
@@ -146,12 +139,21 @@ const weekDays = computed(() => {
|
||||
key,
|
||||
day: format(date, 'd'),
|
||||
inMonth: monthKey(date) === selectedMonth.value,
|
||||
amountLabel: summary.expense ? shortWon(summary.expense) : summary.income ? shortWon(summary.income) : ''
|
||||
expenseLabel: summary.expense ? shortWon(summary.expense) : '',
|
||||
incomeLabel: summary.income ? shortWon(summary.income) : ''
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const selectedDaySummary = computed(() => daySummary(selectedDate.value))
|
||||
const monthlyComparisonLabel = computed(() => {
|
||||
const currentExpense = data.value?.summary.expense || 0
|
||||
const previousExpense = previousData.value?.summary.expense || 0
|
||||
const diff = previousExpense - currentExpense
|
||||
if (!previousExpense && !currentExpense) return '이번 달 지출 내역을 기다리는 중'
|
||||
if (diff > 0) return `지난달보다 ${compactWon(diff)} 덜 쓰는 중`
|
||||
if (diff < 0) return `지난달보다 ${compactWon(Math.abs(diff))} 더 쓰는 중`
|
||||
return '지난달과 같은 속도로 쓰는 중'
|
||||
})
|
||||
|
||||
function moveMonth(amount: number) {
|
||||
const date = parse(selectedDate.value, 'yyyy-MM-dd', new Date())
|
||||
@@ -192,6 +194,11 @@ function shortWon(value: number) {
|
||||
return value.toLocaleString('ko-KR')
|
||||
}
|
||||
|
||||
function compactWon(value: number) {
|
||||
if (value >= 10000) return `${Math.round(value / 10000).toLocaleString('ko-KR')}만원`
|
||||
return formatWon(value)
|
||||
}
|
||||
|
||||
function startWeekSwipe(event: TouchEvent) {
|
||||
weekSwipeStartX.value = event.changedTouches[0]?.clientX || 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user