rule book front
This commit is contained in:
@@ -1,57 +1,101 @@
|
||||
<script setup lang="ts">
|
||||
import {Character, CharacterLabel, useCharactersStore} from "@/characters";
|
||||
import {useRoute} from "vue-router";
|
||||
import {ref, watch, watchEffect} from "vue";
|
||||
import {useRoute, useRouter} from "vue-router";
|
||||
import {ref, watch} from "vue";
|
||||
import {useDebounceFn} from "@vueuse/core";
|
||||
import log from "loglevel";
|
||||
import {activityTypes, findByCharacterId, RuleBook, RuleInput, setCharacterRuleBook} from "@/rules";
|
||||
import {activityTypes, RuleInput, Rules, useRuleBooksStore} from "@/rules";
|
||||
import {PlusIcon, TrashIcon} from "@heroicons/vue/24/outline";
|
||||
|
||||
const {findById: findCharacterById} = useCharactersStore();
|
||||
const character = ref<Character>();
|
||||
const ruleBookId = ref<string>();
|
||||
const name = ref<string>('');
|
||||
const ledgerRefs = ref<string[]>([]);
|
||||
const rules = ref<Rules>({});
|
||||
|
||||
const ruleBook = ref<RuleBook>();
|
||||
const {findById, create, update, refresh} = useRuleBooksStore();
|
||||
const router = useRouter();
|
||||
|
||||
watchEffect(async () => {
|
||||
const characterId = character.value?.characterId;
|
||||
const save = async () => {
|
||||
if (!ruleBookId.value) {
|
||||
const created = await create({
|
||||
name: name.value,
|
||||
ledgerRefs: ledgerRefs.value,
|
||||
rules: rules.value
|
||||
})
|
||||
await router.push({ name: 'edit-rule-book', params: {ruleBookId: created.ruleBookId}})
|
||||
|
||||
if (characterId) {
|
||||
ruleBook.value = await findByCharacterId(characterId);
|
||||
}
|
||||
});
|
||||
|
||||
const save = () => {
|
||||
const characterId = character.value?.characterId;
|
||||
|
||||
if (characterId && ruleBook.value) {
|
||||
setCharacterRuleBook(characterId, ruleBook.value);
|
||||
} else {
|
||||
await update(ruleBookId.value, {
|
||||
name: name.value,
|
||||
ledgerRefs: ledgerRefs.value,
|
||||
rules: rules.value
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
watch(useRoute(), async route => {
|
||||
if (route.params.characterId) {
|
||||
const id = parseInt(typeof route.params.characterId === 'string' ? route.params.characterId : route.params.characterId[0]);
|
||||
const addLedgerRef = () => {
|
||||
ledgerRefs.value = [...ledgerRefs.value, '']
|
||||
}
|
||||
const updateLedgerRef = useDebounceFn((index: number, value: string) => {
|
||||
ledgerRefs.value[index] = value;
|
||||
}, 500);
|
||||
|
||||
character.value = await findCharacterById(id);
|
||||
log.info('Loaded character:', character.value);
|
||||
const removeLedgerRef = (index: number) => {
|
||||
ledgerRefs.value = ledgerRefs.value.toSpliced(index, 1)
|
||||
}
|
||||
|
||||
watch(useRoute(), async route => {
|
||||
if (route.params.ruleBookId) {
|
||||
const promise = refresh(); // FIXME don't call refresh
|
||||
|
||||
const id = typeof route.params.ruleBookId === 'string' ? route.params.ruleBookId : route.params.ruleBookId[0];
|
||||
|
||||
await promise;
|
||||
|
||||
const ruleBook = findById(id);
|
||||
|
||||
ruleBookId.value = id;
|
||||
name.value = ruleBook?.name ?? '';
|
||||
ledgerRefs.value = [...ruleBook?.ledgerRefs];
|
||||
rules.value = {...ruleBook?.rules}; // todo fully clone rules
|
||||
log.info('Loaded rule book:', ruleBook);
|
||||
} else {
|
||||
character.value = undefined;
|
||||
log.info('No character to load');
|
||||
ruleBookId.value = undefined;
|
||||
name.value = '';
|
||||
ledgerRefs.value = [];
|
||||
rules.value = {};
|
||||
log.info('No rule book to load');
|
||||
}
|
||||
}, { immediate: true })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="character" class="grid mb-2 mt-4">
|
||||
<div class="mb-2 border-b-1 flex">
|
||||
<CharacterLabel class="flex grow mb-2" :character="character" :size="64" />
|
||||
<div class="grid mb-2 mt-4">
|
||||
<div class="flex flex-col">
|
||||
<div class="flex grow border-b-1">
|
||||
Name:
|
||||
<input class="mb-2 ms-2" type="text" v-model="name" />
|
||||
</div>
|
||||
<div class="border-b-1">
|
||||
Ledgers References:
|
||||
<div class="flex flex-wrap items-center">
|
||||
<div class="flex items-center mb-2" v-for="(ledgerRef, index) in ledgerRefs" :key="index">
|
||||
<input class="me-1" type="text" :value="ledgerRefs[index]" @input="updateLedgerRef(index, ($event.target as HTMLInputElement).value)" />
|
||||
<button class="btn-icon me-2" @click="addLedgerRef"><TrashIcon /></button>
|
||||
</div>
|
||||
<div class="flex items-center mb-2">
|
||||
<button class="btn-icon" @click="removeLedgerRef(index)"><PlusIcon /></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col grow border-b-1" v-for="activityType in activityTypes" :key="activityType.key">
|
||||
<span>{{ activityType.name }}</span>
|
||||
<RuleInput :ledgerRefs="ledgerRefs" v-model="rules[activityType.key]" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2 justify-end flex">
|
||||
<div>
|
||||
<button @click="save">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="ruleBook" class="flex-col">
|
||||
<div class="flex-col grow border-b-1" v-for="activityType in activityTypes" :key="activityType.key">
|
||||
<span>{{ activityType.name }}</span>
|
||||
<RuleInput v-model="ruleBook.rules[activityType.key]" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user