336 lines
9.7 KiB
Vue
336 lines
9.7 KiB
Vue
<script setup>
|
|
import { ref, watch } from 'vue';
|
|
import { useForm, Field as FormField } from "vee-validate";
|
|
import { toTypedSchema } from "@vee-validate/zod";
|
|
import * as z from "zod";
|
|
import { router } from '@inertiajs/vue3';
|
|
import CreateDialog from '../Dialogs/CreateDialog.vue';
|
|
import UpdateDialog from '../Dialogs/UpdateDialog.vue';
|
|
import SectionTitle from '../SectionTitle.vue';
|
|
import {
|
|
FormControl,
|
|
FormItem,
|
|
FormLabel,
|
|
FormMessage,
|
|
} from "@/Components/ui/form";
|
|
import { Input } from "@/Components/ui/input";
|
|
import { Textarea } from "@/Components/ui/textarea";
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from "@/Components/ui/select";
|
|
|
|
const props = defineProps({
|
|
show: { type: Boolean, default: false },
|
|
person: { type: Object, required: true },
|
|
currencies: { type: Array, default: () => ['EUR'] },
|
|
edit: { type: Boolean, default: false },
|
|
id: { type: Number, default: 0 },
|
|
});
|
|
|
|
const processing = ref(false);
|
|
const errors = ref({});
|
|
const emit = defineEmits(['close']);
|
|
|
|
const initialCurrency = () => (props.currencies && props.currencies.length ? props.currencies[0] : 'EUR');
|
|
|
|
const formSchema = toTypedSchema(
|
|
z.object({
|
|
iban: z.string().optional(),
|
|
bank_name: z.string().optional(),
|
|
bic_swift: z.string().optional(),
|
|
account_number: z.string().optional(),
|
|
routing_number: z.string().optional(),
|
|
currency: z.string().default(initialCurrency()),
|
|
country_code: z.string().optional(),
|
|
holder_name: z.string().optional(),
|
|
notes: z.string().optional(),
|
|
})
|
|
);
|
|
|
|
const form = useForm({
|
|
validationSchema: formSchema,
|
|
initialValues: {
|
|
iban: '',
|
|
bank_name: '',
|
|
bic_swift: '',
|
|
account_number: '',
|
|
routing_number: '',
|
|
currency: initialCurrency(),
|
|
country_code: '',
|
|
holder_name: '',
|
|
notes: ''
|
|
},
|
|
});
|
|
|
|
const close = () => {
|
|
emit('close');
|
|
setTimeout(() => {
|
|
errors.value = {};
|
|
form.resetForm();
|
|
}, 300);
|
|
};
|
|
|
|
const resetForm = () => {
|
|
form.resetForm({
|
|
values: {
|
|
iban: '',
|
|
bank_name: '',
|
|
bic_swift: '',
|
|
account_number: '',
|
|
routing_number: '',
|
|
currency: initialCurrency(),
|
|
country_code: '',
|
|
holder_name: '',
|
|
notes: ''
|
|
}
|
|
});
|
|
};
|
|
|
|
const create = async () => {
|
|
processing.value = true;
|
|
errors.value = {};
|
|
const { values } = form;
|
|
|
|
router.post(
|
|
route('person.trr.create', props.person),
|
|
values,
|
|
{
|
|
preserveScroll: true,
|
|
onSuccess: () => {
|
|
processing.value = false;
|
|
close();
|
|
resetForm();
|
|
},
|
|
onError: (inertiaErrors) => {
|
|
errors.value = inertiaErrors || {};
|
|
// Map Inertia errors to VeeValidate field errors
|
|
Object.keys(errors.value).forEach((field) => {
|
|
const errorMessages = Array.isArray(errors.value[field])
|
|
? errors.value[field]
|
|
: [errors.value[field]];
|
|
form.setFieldError(field, errorMessages[0]);
|
|
});
|
|
processing.value = false;
|
|
},
|
|
onFinish: () => {
|
|
processing.value = false;
|
|
},
|
|
}
|
|
);
|
|
};
|
|
|
|
const update = async () => {
|
|
processing.value = true;
|
|
errors.value = {};
|
|
const { values } = form;
|
|
|
|
router.put(
|
|
route('person.trr.update', { person: props.person, trr_id: props.id }),
|
|
values,
|
|
{
|
|
preserveScroll: true,
|
|
onSuccess: () => {
|
|
processing.value = false;
|
|
close();
|
|
resetForm();
|
|
},
|
|
onError: (inertiaErrors) => {
|
|
errors.value = inertiaErrors || {};
|
|
// Map Inertia errors to VeeValidate field errors
|
|
Object.keys(errors.value).forEach((field) => {
|
|
const errorMessages = Array.isArray(errors.value[field])
|
|
? errors.value[field]
|
|
: [errors.value[field]];
|
|
form.setFieldError(field, errorMessages[0]);
|
|
});
|
|
processing.value = false;
|
|
},
|
|
onFinish: () => {
|
|
processing.value = false;
|
|
},
|
|
}
|
|
);
|
|
};
|
|
|
|
watch(
|
|
() => props.id,
|
|
(id) => {
|
|
if (props.edit && id) {
|
|
const list = props.person.trrs || props.person.bank_accounts || props.person.accounts || props.person.bankAccounts || [];
|
|
const current = list.find(a => a.id === id);
|
|
if (current) {
|
|
form.setValues({
|
|
iban: current.iban || current.account_number || current.number || '',
|
|
bank_name: current.bank_name || '',
|
|
bic_swift: current.bic_swift || '',
|
|
account_number: current.account_number || '',
|
|
routing_number: current.routing_number || '',
|
|
currency: current.currency || initialCurrency(),
|
|
country_code: current.country_code || '',
|
|
holder_name: current.holder_name || '',
|
|
notes: current.notes || ''
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
resetForm();
|
|
},
|
|
{ immediate: true }
|
|
);
|
|
|
|
watch(() => props.show, (val) => {
|
|
if (val && props.edit && props.id) {
|
|
const list = props.person.trrs || props.person.bank_accounts || props.person.accounts || props.person.bankAccounts || [];
|
|
const current = list.find(a => a.id === props.id);
|
|
if (current) {
|
|
form.setValues({
|
|
iban: current.iban || current.account_number || current.number || '',
|
|
bank_name: current.bank_name || '',
|
|
bic_swift: current.bic_swift || '',
|
|
account_number: current.account_number || '',
|
|
routing_number: current.routing_number || '',
|
|
currency: current.currency || initialCurrency(),
|
|
country_code: current.country_code || '',
|
|
holder_name: current.holder_name || '',
|
|
notes: current.notes || ''
|
|
});
|
|
}
|
|
} else if (val && !props.edit) {
|
|
resetForm();
|
|
}
|
|
});
|
|
|
|
const submit = () => (props.edit ? update() : create());
|
|
|
|
const onSubmit = form.handleSubmit(() => {
|
|
submit();
|
|
});
|
|
|
|
const onConfirm = () => {
|
|
onSubmit();
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<component
|
|
:is="edit ? UpdateDialog : CreateDialog"
|
|
:show="show"
|
|
:title="edit ? 'Spremeni TRR' : 'Dodaj TRR'"
|
|
confirm-text="Shrani"
|
|
:processing="processing"
|
|
@close="close"
|
|
@confirm="onConfirm"
|
|
>
|
|
<form @submit.prevent="onSubmit">
|
|
<SectionTitle class="border-b mb-4">
|
|
<template #title>TRR</template>
|
|
</SectionTitle>
|
|
|
|
<div class="space-y-4">
|
|
<FormField v-slot="{ componentField }" name="iban">
|
|
<FormItem>
|
|
<FormLabel>IBAN</FormLabel>
|
|
<FormControl>
|
|
<Input id="trr_iban" placeholder="IBAN" autocomplete="off" v-bind="componentField" />
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
</FormField>
|
|
|
|
<FormField v-slot="{ componentField }" name="bank_name">
|
|
<FormItem>
|
|
<FormLabel>Banka</FormLabel>
|
|
<FormControl>
|
|
<Input id="trr_bank_name" placeholder="Banka" autocomplete="organization" v-bind="componentField" />
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
</FormField>
|
|
|
|
<FormField v-slot="{ componentField }" name="bic_swift">
|
|
<FormItem>
|
|
<FormLabel>BIC / SWIFT</FormLabel>
|
|
<FormControl>
|
|
<Input id="trr_bic" placeholder="BIC / SWIFT" autocomplete="off" v-bind="componentField" />
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
</FormField>
|
|
|
|
<FormField v-slot="{ componentField }" name="account_number">
|
|
<FormItem>
|
|
<FormLabel>Številka računa</FormLabel>
|
|
<FormControl>
|
|
<Input id="trr_accnum" placeholder="Številka računa" autocomplete="off" v-bind="componentField" />
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
</FormField>
|
|
|
|
<FormField v-slot="{ componentField }" name="routing_number">
|
|
<FormItem>
|
|
<FormLabel>Usmerjevalna številka (routing)</FormLabel>
|
|
<FormControl>
|
|
<Input id="trr_route" placeholder="Routing number" autocomplete="off" v-bind="componentField" />
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
</FormField>
|
|
|
|
<FormField v-if="currencies && currencies.length" v-slot="{ value, handleChange }" name="currency">
|
|
<FormItem>
|
|
<FormLabel>Valuta</FormLabel>
|
|
<Select :model-value="value" @update:model-value="handleChange">
|
|
<FormControl>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="Izberi valuto" />
|
|
</SelectTrigger>
|
|
</FormControl>
|
|
<SelectContent>
|
|
<SelectItem v-for="c in currencies" :key="c" :value="c">
|
|
{{ c }}
|
|
</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
<FormMessage />
|
|
</FormItem>
|
|
</FormField>
|
|
|
|
<FormField v-slot="{ componentField }" name="country_code">
|
|
<FormItem>
|
|
<FormLabel>Koda države (2-znaki, npr. SI)</FormLabel>
|
|
<FormControl>
|
|
<Input id="trr_cc" placeholder="SI" autocomplete="country" v-bind="componentField" />
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
</FormField>
|
|
|
|
<FormField v-slot="{ componentField }" name="holder_name">
|
|
<FormItem>
|
|
<FormLabel>Imetnik računa</FormLabel>
|
|
<FormControl>
|
|
<Input id="trr_holder" placeholder="Imetnik računa" autocomplete="name" v-bind="componentField" />
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
</FormField>
|
|
|
|
<FormField v-slot="{ componentField }" name="notes">
|
|
<FormItem>
|
|
<FormLabel>Opombe</FormLabel>
|
|
<FormControl>
|
|
<Textarea id="trr_notes" placeholder="Opombe" v-bind="componentField" />
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
</FormField>
|
|
</div>
|
|
</form>
|
|
</component>
|
|
</template>
|