New report system and views

This commit is contained in:
Simon Pocrnjič
2026-01-02 12:32:20 +01:00
parent 9fc5b54b8a
commit 703b52ff59
67 changed files with 8255 additions and 2794 deletions
+132 -67
View File
@@ -1,103 +1,168 @@
<script setup>
import AppLayout from '@/Layouts/AppLayout.vue'
import { useForm } from '@inertiajs/vue3'
import { computed, watch } from 'vue'
import AppLayout from "@/Layouts/AppLayout.vue";
import { useForm } from "@inertiajs/vue3";
import { computed, watch } from "vue";
import AppCard from "@/Components/app/ui/card/AppCard.vue";
import CardTitle from "@/Components/ui/card/CardTitle.vue";
import { Wallet } from "lucide-vue-next";
import { Button } from "@/Components/ui/button";
import { Input } from "@/Components/ui/input";
import InputLabel from "@/Components/InputLabel.vue";
import { Checkbox } from "@/Components/ui/checkbox";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/Components/ui/select";
const props = defineProps({
setting: Object,
decisions: Array,
actions: Array,
})
});
const form = useForm({
default_currency: props.setting?.default_currency ?? 'EUR',
default_currency: props.setting?.default_currency ?? "EUR",
create_activity_on_payment: !!props.setting?.create_activity_on_payment,
default_action_id: props.setting?.default_action_id ?? null,
default_decision_id: props.setting?.default_decision_id ?? null,
activity_note_template: props.setting?.activity_note_template ?? 'Prejeto plačilo: {amount} {currency}',
})
activity_note_template:
props.setting?.activity_note_template ?? "Prejeto plačilo: {amount} {currency}",
});
const filteredDecisions = computed(() => {
const actionId = form.default_action_id
if (!actionId) return []
const action = props.actions?.find(a => a.id === actionId)
if (!action || !action.decision_ids) return []
const ids = new Set(action.decision_ids)
return (props.decisions || []).filter(d => ids.has(d.id))
})
const actionId = form.default_action_id;
if (!actionId) return [];
const action = props.actions?.find((a) => a.id === actionId);
if (!action || !action.decision_ids) return [];
const ids = new Set(action.decision_ids);
return (props.decisions || []).filter((d) => ids.has(d.id));
});
watch(() => form.default_action_id, (newVal) => {
if (!newVal) {
form.default_decision_id = null
} else {
// If current decision not in filtered list, clear it
const ids = new Set((filteredDecisions.value || []).map(d => d.id))
if (!ids.has(form.default_decision_id)) {
form.default_decision_id = null
watch(
() => form.default_action_id,
(newVal) => {
if (!newVal) {
form.default_decision_id = null;
} else {
// If current decision not in filtered list, clear it
const ids = new Set((filteredDecisions.value || []).map((d) => d.id));
if (!ids.has(form.default_decision_id)) {
form.default_decision_id = null;
}
}
}
})
);
const submit = () => {
form.put(route('settings.payment.update'), {
form.put(route("settings.payment.update"), {
preserveScroll: true,
})
}
});
};
</script>
<template>
<AppLayout title="Nastavitve plačil">
<template #header></template>
<div class="max-w-3xl mx-auto p-6">
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
<h1 class="text-xl font-semibold text-gray-900">Nastavitve plačil</h1>
<div class="mt-6 grid gap-6">
<div>
<label class="block text-sm text-gray-700 mb-1">Privzeta valuta</label>
<input type="text" maxlength="3" v-model="form.default_currency" class="w-40 rounded border-gray-300" />
<div v-if="form.errors.default_currency" class="text-sm text-red-600 mt-1">{{ form.errors.default_currency }}</div>
</div>
<div>
<label class="inline-flex items-center gap-2">
<input type="checkbox" v-model="form.create_activity_on_payment" />
<span class="text-sm text-gray-700">Ustvari aktivnost ob dodanem plačilu</span>
</label>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label class="block text-sm text-gray-700 mb-1">Privzeto dejanje</label>
<select v-model="form.default_action_id" class="w-full rounded border-gray-300">
<option :value="null"> Brez </option>
<option v-for="a in actions" :key="a.id" :value="a.id">{{ a.name }}</option>
</select>
<div v-if="form.errors.default_action_id" class="text-sm text-red-600 mt-1">{{ form.errors.default_action_id }}</div>
<AppCard
title=""
padding="none"
class="p-0! gap-0"
header-class="py-3! px-4 gap-0 text-muted-foreground"
body-class=""
>
<template #header>
<div class="flex items-center gap-2">
<Wallet :size="18" />
<CardTitle class="uppercase">Nastavitve plačil</CardTitle>
</div>
</template>
<div class="space-y-6 p-4 border-t">
<div>
<label class="block text-sm text-gray-700 mb-1">Privzeta odločitev</label>
<select v-model="form.default_decision_id" class="w-full rounded border-gray-300" :disabled="!form.default_action_id">
<option :value="null"> Najprej izberite dejanje </option>
<option v-for="d in filteredDecisions" :key="d.id" :value="d.id">{{ d.name }}</option>
</select>
<div v-if="form.errors.default_decision_id" class="text-sm text-red-600 mt-1">{{ form.errors.default_decision_id }}</div>
<InputLabel for="currency">Privzeta valuta</InputLabel>
<Input
id="currency"
v-model="form.default_currency"
maxlength="3"
class="w-40"
/>
<div v-if="form.errors.default_currency" class="text-sm text-red-600 mt-1">
{{ form.errors.default_currency }}
</div>
</div>
</div>
<div>
<label class="block text-sm text-gray-700 mb-1">Predloga opombe aktivnosti</label>
<input type="text" v-model="form.activity_note_template" class="w-full rounded border-gray-300" />
<p class="text-xs text-gray-500 mt-1">Podprti žetoni: {amount}, {currency}</p>
<div v-if="form.errors.activity_note_template" class="text-sm text-red-600 mt-1">{{ form.errors.activity_note_template }}</div>
</div>
<div class="flex items-center gap-2">
<Checkbox id="create-activity" v-model="form.create_activity_on_payment" />
<InputLabel for="create-activity" class="text-sm font-normal cursor-pointer">
Ustvari aktivnost ob dodanem plačilu
</InputLabel>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<InputLabel for="default-action">Privzeto dejanje</InputLabel>
<Select v-model="form.default_action_id">
<SelectTrigger id="default-action">
<SelectValue placeholder="— Brez —" />
</SelectTrigger>
<SelectContent>
<SelectItem :value="null"> Brez </SelectItem>
<SelectItem v-for="a in actions" :key="a.id" :value="a.id">{{
a.name
}}</SelectItem>
</SelectContent>
</Select>
<div v-if="form.errors.default_action_id" class="text-sm text-red-600 mt-1">
{{ form.errors.default_action_id }}
</div>
</div>
<div>
<InputLabel for="default-decision">Privzeta odločitev</InputLabel>
<Select
v-model="form.default_decision_id"
:disabled="!form.default_action_id"
>
<SelectTrigger id="default-decision">
<SelectValue placeholder="— Najprej izberite dejanje —" />
</SelectTrigger>
<SelectContent>
<SelectItem :value="null"> Najprej izberite dejanje </SelectItem>
<SelectItem v-for="d in filteredDecisions" :key="d.id" :value="d.id">{{
d.name
}}</SelectItem>
</SelectContent>
</Select>
<div
v-if="form.errors.default_decision_id"
class="text-sm text-red-600 mt-1"
>
{{ form.errors.default_decision_id }}
</div>
</div>
</div>
<div>
<InputLabel for="note-template">Predloga opombe aktivnosti</InputLabel>
<Input id="note-template" v-model="form.activity_note_template" />
<p class="text-xs text-gray-500 mt-1">Podprti žetoni: {amount}, {currency}</p>
<div
v-if="form.errors.activity_note_template"
class="text-sm text-red-600 mt-1"
>
{{ form.errors.activity_note_template }}
</div>
</div>
<div class="flex justify-end gap-2">
<button type="button" class="px-4 py-2 rounded bg-gray-200 hover:bg-gray-300" @click="form.reset()">Ponastavi</button>
<button type="button" class="px-4 py-2 rounded bg-indigo-600 text-white hover:bg-indigo-700" :disabled="form.processing" @click="submit">Shrani</button>
<Button variant="outline" @click="form.reset()">Ponastavi</Button>
<Button @click="submit" :disabled="form.processing">Shrani</Button>
</div>
</div>
</div>
</AppCard>
</div>
</AppLayout>
</template>