75 lines
2.6 KiB
Vue
75 lines
2.6 KiB
Vue
<script setup lang="ts">
|
|
import { BarChart3, BookOpen, Check, CircleUserRound, LibraryBig, Plus } from "@lucide/vue";
|
|
import { computed, onMounted, ref } from "vue";
|
|
import { useRoute } from "vue-router";
|
|
import { createEntry } from "../data/entries";
|
|
import { useEntryStore } from "../stores/entries";
|
|
import { useAuthStore } from "../stores/auth";
|
|
import { useLedgerStore } from "../stores/ledgers";
|
|
import QuickEntryDrawer from "./QuickEntryDrawer.vue";
|
|
|
|
const route = useRoute();
|
|
const entryStore = useEntryStore();
|
|
const authStore = useAuthStore();
|
|
const ledgerStore = useLedgerStore();
|
|
const drawerOpen = ref(false);
|
|
const savedToast = ref(false);
|
|
|
|
const ledgerOptions = computed(() =>
|
|
ledgerStore.ledgers.map((ledger) => ({ id: ledger.id, name: ledger.name, color: ledger.color })),
|
|
);
|
|
|
|
onMounted(async () => {
|
|
if (!ledgerStore.loaded) await ledgerStore.loadLedgers();
|
|
});
|
|
|
|
async function saveEntry(input: {
|
|
type: "expense" | "income";
|
|
amount: number;
|
|
categoryId: string;
|
|
note: string;
|
|
occurredAt: string;
|
|
ledgerIds: string[];
|
|
}) {
|
|
const ledger = ledgerStore.currentLedger;
|
|
if (!ledger) return;
|
|
await entryStore.addEntry(createEntry({
|
|
...input,
|
|
currency: ledger.defaultCurrency,
|
|
createdBy: authStore.user?.id,
|
|
}));
|
|
drawerOpen.value = false;
|
|
savedToast.value = true;
|
|
window.setTimeout(() => (savedToast.value = false), 1800);
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<nav class="bottom-nav" aria-label="主导航">
|
|
<RouterLink to="/" :class="{ active: route.name === 'ledger' }"><BookOpen :size="20" /><span>流水</span></RouterLink>
|
|
<RouterLink to="/stats" :class="{ active: route.name === 'stats' }"><BarChart3 :size="20" /><span>统计</span></RouterLink>
|
|
<span class="nav-spacer"></span>
|
|
<RouterLink to="/ledgers" :class="{ active: route.name === 'ledgers' }"><LibraryBig :size="20" /><span>账本</span></RouterLink>
|
|
<RouterLink to="/me" :class="{ active: route.name === 'me' }"><CircleUserRound :size="20" /><span>我的</span></RouterLink>
|
|
</nav>
|
|
|
|
<button v-if="!drawerOpen" class="add-entry-button" type="button" aria-label="记一笔" title="记一笔" @click="drawerOpen = true">
|
|
<Plus :size="28" />
|
|
</button>
|
|
|
|
<Transition name="drawer">
|
|
<QuickEntryDrawer
|
|
v-if="drawerOpen && ledgerStore.currentLedger"
|
|
:ledger-id="ledgerStore.currentLedger.id"
|
|
:ledger-name="ledgerStore.currentLedger.name"
|
|
:ledger-options="ledgerOptions"
|
|
@close="drawerOpen = false"
|
|
@save="saveEntry"
|
|
/>
|
|
</Transition>
|
|
|
|
<Transition name="toast">
|
|
<div v-if="savedToast" class="saved-toast" role="status"><Check :size="17" />已记入账本</div>
|
|
</Transition>
|
|
</template>
|