transaction list api

This commit is contained in:
Sirttas
2026-05-31 21:54:56 +02:00
parent 457d2a5161
commit 47ee14319d
6 changed files with 266 additions and 9 deletions
+147
View File
@@ -0,0 +1,147 @@
<script setup lang="ts">
import {computed, ref} from "vue";
import {storeToRefs} from "pinia";
import {isCombined, Ledger, LedgerType, LedgerTypes, useLedgersStore} from "./ledger";
import {Modal} from "@/components";
import LedgerLabel from "./LedgerLabel.vue";
import {PlusIcon, TrashIcon} from '@heroicons/vue/24/outline';
import LedgerSelect from "@/ledger/LedgerSelect.vue";
interface Props {
ledgerId?: string;
}
const props = defineProps<Props>();
const ledgersStore = useLedgersStore();
const {ledgers} = storeToRefs(ledgersStore);
const {findById, findAllById, createMain, createCombined, updateMain, updateCombined} = ledgersStore;
const modalOpen = ref<boolean>(false);
const type = ref<LedgerType>(LedgerTypes.Main);
const name = ref("");
const members = ref<Ledger[]>([]);
const selectedLedger = ref<Ledger>();
const availableLedgers = computed(() => ledgers.value
.filter((ledger) => selectedLedger.value === ledger)
.filter(l => !members.value.includes(l)));
const addMember = () => {
if (selectedLedger.value && !members.value.includes(selectedLedger.value)) {
members.value = [...members.value, selectedLedger.value];
selectedLedger.value = undefined;
}
}
const open = () => {
const ledger = isCreating.value ? undefined : findById(props.ledgerId);
if (ledger) {
type.value = ledger.type;
name.value = ledger.name;
members.value = isCombined(ledger) ? findAllById(ledger.memberLedgerIds) : [];
} else {
type.value = LedgerTypes.Main;
name.value = "";
members.value = [];
}
modalOpen.value = true;
}
const canSave = computed(() => name.value.trim().length > 0);
const isCreating = computed(() => props.ledgerId === undefined || props.ledgerId.length === 0);
const title = computed(() => {
if (isCreating.value) {
return `Creating ${type.value === LedgerTypes.Main ? 'Main' : 'Combined'} Ledger`
}
return `Updating ${name.value}`
})
const create = () => {
if (type.value === LedgerTypes.Main) {
createMain({name: name.value})
} else {
createCombined({name: name.value, memberLedgerIds: members.value.map(l => l.ledgerId)})
}
}
const update = () => {
if (type.value === LedgerTypes.Main) {
updateMain(props.ledgerId, {name: name.value})
} else {
updateCombined(props.ledgerId, {name: name.value, memberLedgerIds: members.value.map(l => l.ledgerId)})
}
}
const save = () => {
if (!canSave.value) {
return;
}
if (isCreating.value) {
create();
} else {
update();
}
modalOpen.value = false;
}
defineExpose({ open });
</script>
<template>
<Modal v-model:open="modalOpen">
<div class="bg-slate-800 rounded pb-4 w-96">
<span class="m-2">{{ title }}</span>
<hr />
<div class="mt-4">
<div class="flex justify-center">
<div class="flex bg-slate-600 rounded-s-md p-1">
<button class="switch" :class="{active: type === LedgerTypes.Main}" @click="type = LedgerTypes.Main">Main</button>
</div>
<div class="switch flex bg-slate-600 rounded-e-md p-1">
<button class="switch" :class="{active: type === LedgerTypes.Combined}" @click="type = LedgerTypes.Combined">Combined</button>
</div>
</div>
<div class="m-4">
Name:
<div class="flex">
<input type="text" class="flex grow" v-model="name" />
</div>
</div>
</div>
<div v-if="type === LedgerTypes.Combined" class="ms-4 mb-4">
Member Ledgers:
<div v-for="ledger in members" :key="ledger.ledgerId" class="flex">
<LedgerLabel class="flex grow mb-2" :ledger="ledger" />
<div class="flex justify-end me-4 ms-2">
<button class="btn-icon" @click="members = members.filter(m => m !== ledger)"><TrashIcon /></button>
</div>
</div>
<div v-if="availableLedgers.length" class="flex">
<LedgerSelect v-model="selectedLedger" class="grow" :ledgers="availableLedgers" />
<div class="flex justify-end me-4 ms-2">
<button class="btn-icon" @click="addMember"><PlusIcon /></button>
</div>
</div>
</div>
<div class="flex justify-end">
<button class="me-4" @click="save" :disabled="!canSave">Save</button>
</div>
</div>
</Modal>
</template>
<style scoped>
@reference "tailwindcss";
button.switch {
@apply flex items-center px-4 rounded-md bg-slate-600;
&.active {
@apply bg-emerald-500;
}
}
</style>