transaction list api
This commit is contained in:
@@ -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>
|
||||
Reference in New Issue
Block a user