This commit is contained in:
Sirttas
2026-05-25 18:36:18 +02:00
parent 2d6930d38d
commit 0a2894b378
5 changed files with 44 additions and 16 deletions
+7
View File
@@ -18,6 +18,7 @@
"loglevel": "^1.8.1", "loglevel": "^1.8.1",
"loglevel-plugin-prefix": "^0.8.4", "loglevel-plugin-prefix": "^0.8.4",
"pinia": "^3.0.4", "pinia": "^3.0.4",
"sortablejs": "^1.15.7",
"vue": "^3.3.4", "vue": "^3.3.4",
"vue-router": "^5.0.7" "vue-router": "^5.0.7"
}, },
@@ -2572,6 +2573,12 @@
"dev": true, "dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/sortablejs": {
"version": "1.15.7",
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.7.tgz",
"integrity": "sha512-Kk8wLQPlS+yi1ZEf48a4+fzHa4yxjC30M/Sr2AnQu+f/MPwvvX9XjZ6OWejiz8crBsLwSq8GHqaxaET7u6ux0A==",
"license": "MIT"
},
"node_modules/source-map-js": { "node_modules/source-map-js": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+2 -1
View File
@@ -20,15 +20,16 @@
"loglevel": "^1.8.1", "loglevel": "^1.8.1",
"loglevel-plugin-prefix": "^0.8.4", "loglevel-plugin-prefix": "^0.8.4",
"pinia": "^3.0.4", "pinia": "^3.0.4",
"sortablejs": "^1.15.7",
"vue": "^3.3.4", "vue": "^3.3.4",
"vue-router": "^5.0.7" "vue-router": "^5.0.7"
}, },
"devDependencies": { "devDependencies": {
"@tailwindcss/vite": "^4.3.0",
"@types/node": "^25.8.0", "@types/node": "^25.8.0",
"@vitejs/plugin-vue": "^6.0.7", "@vitejs/plugin-vue": "^6.0.7",
"tailwindcss": "^4.3.0", "tailwindcss": "^4.3.0",
"typescript": "^6.0.3", "typescript": "^6.0.3",
"@tailwindcss/vite": "^4.3.0",
"vite": "^8.0.13", "vite": "^8.0.13",
"vite-plugin-runtime-env": "^1.0.0", "vite-plugin-runtime-env": "^1.0.0",
"vitest": "^4.1.6", "vitest": "^4.1.6",
+4 -5
View File
@@ -12,16 +12,16 @@ const ledger = defineModel<Ledger>();
const {ledgers: allLedgers} = storeToRefs(useLedgersStore()); const {ledgers: allLedgers} = storeToRefs(useLedgersStore());
const ledgersToUse = computed(() => props.ledgers || allLedgers); const ledgersToUse = computed(() => props.ledgers || allLedgers);
const legerId = computed({ const ledgerId = computed({
get: () => ledger.value?.ledgerId, get: () => ledger.value?.ledgerId,
set: value => ledger.value = ledgersToUse.value[ledgersToUse.value.findIndex(x => x.value === value)] set: value => ledger.value = ledgersToUse.value.find(l => l.ledgerId === value)
}) })
</script> </script>
<template> <template>
<select v-model="legerId" :class="{'system-ledger': ledger === systemLedger}"> <select v-model="ledgerId" :class="{'system-ledger': ledger === systemLedger}">
<option v-for="ledger in ledgersToUse" :key="ledger.ledgerId" :value="ledger.ledgerId" :class="{'system-ledger': ledger === systemLedger}">{{ ledger.name }}</option> <option v-for="l in ledgersToUse" :key="l.ledgerId" :value="l.ledgerId" :class="{'system-ledger': l === systemLedger}">{{ l.name }}</option>
</select> </select>
</template> </template>
@@ -31,5 +31,4 @@ const legerId = computed({
.system-ledger { .system-ledger {
@apply text-emerald-400; @apply text-emerald-400;
} }
</style> </style>
+1 -5
View File
@@ -34,8 +34,4 @@ const toLedger = ledgerComputed('toLedgerId')
<select class="me-2 grow" v-model="rule.rate"> <select class="me-2 grow" v-model="rule.rate">
<option v-for="rateType in ratesTypes" :key="rateType.key" :value="rateType.key">{{ rateType.name }}</option> <option v-for="rateType in ratesTypes" :key="rateType.key" :value="rateType.key">{{ rateType.name }}</option>
</select> </select>
</template> </template>
<style scoped>
</style>
+30 -5
View File
@@ -2,8 +2,9 @@
import {RuleResponse, RuleResponseRateEnum, RuleSetResponse} from "@/generated/mammon"; import {RuleResponse, RuleResponseRateEnum, RuleSetResponse} from "@/generated/mammon";
import RuleInput from "@/rules/RuleInput.vue"; import RuleInput from "@/rules/RuleInput.vue";
import {computed} from "vue"; import {computed, useTemplateRef} from "vue";
import {PlusIcon, TrashIcon} from '@heroicons/vue/24/outline'; import {Bars4Icon, PlusIcon, TrashIcon} from '@heroicons/vue/24/outline';
import {useSortable} from "@vueuse/integrations/useSortable";
const ruleSet = defineModel<RuleSetResponse>(); const ruleSet = defineModel<RuleSetResponse>();
const rules = computed<RuleResponse[]>({ const rules = computed<RuleResponse[]>({
@@ -25,16 +26,40 @@ const setRule = (index: number, rule?: RuleResponse) => {
const removeRule = (index: number) => { const removeRule = (index: number) => {
rules.value = rules.value.toSpliced(index, 1) rules.value = rules.value.toSpliced(index, 1)
} }
const sortableContainer = useTemplateRef('sortable-container')
useSortable(sortableContainer, rules, { handle: '.sortable-handle'});
</script> </script>
<template> <template>
<div class="flex-col"> <div class="flex-col">
<div class="flex items-end gap-2 mt-2" v-for="(rule, index) in rules" :key="index"> <div ref="sortable-container" class="flex-col">
<RuleInput :modelValue="rule" @update:modelValue="v => setRule(index, v)" /> <div class="flex items-end gap-2 mt-2" v-for="(rule, index) in rules" :key="index">
<button class="btn-icon" @click="removeRule(index)"><TrashIcon /></button> <span class="sortable-handle flex">
<Bars4Icon class="w-6"/>
</span>
<RuleInput :modelValue="rule" @update:modelValue="v => setRule(index, v)" />
<button class="btn-icon" @click="removeRule(index)"><TrashIcon /></button>
</div>
</div> </div>
<div class="flex justify-end mb-2 mt-2"> <div class="flex justify-end mb-2 mt-2">
<button class="btn-icon" @click="addRule"><PlusIcon /></button> <button class="btn-icon" @click="addRule"><PlusIcon /></button>
</div> </div>
</div> </div>
</template> </template>
<style scoped>
.sortable-handle {
@apply cursor-grab;
}
.sortable-chosen {
@apply cursor-grabbing;
}
.sortable-chosen .sortable-handle {
@apply cursor-grabbing;
}
</style>