255 lines
6.9 KiB
Vue
255 lines
6.9 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 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 {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from "@/Components/ui/select";
|
|
import { Switch } from "@/Components/ui/switch";
|
|
|
|
const props = defineProps({
|
|
show: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
person: Object,
|
|
types: Array,
|
|
id: {
|
|
type: Number,
|
|
default: 0,
|
|
},
|
|
});
|
|
|
|
const emit = defineEmits(["close"]);
|
|
|
|
const formSchema = toTypedSchema(
|
|
z.object({
|
|
nu: z.string().min(1, "Številka je obvezna."),
|
|
country_code: z.number().default(386),
|
|
type_id: z.number().nullable(),
|
|
description: z.string().optional(),
|
|
validated: z.boolean().default(false),
|
|
phone_type: z.string().nullable().optional(),
|
|
})
|
|
);
|
|
|
|
const form = useForm({
|
|
validationSchema: formSchema,
|
|
initialValues: {
|
|
nu: "",
|
|
country_code: 386,
|
|
type_id: props.types?.[0]?.id ?? null,
|
|
description: "",
|
|
validated: false,
|
|
phone_type: null,
|
|
},
|
|
});
|
|
|
|
const processing = ref(false);
|
|
|
|
const close = () => {
|
|
emit("close");
|
|
setTimeout(() => {
|
|
form.resetForm();
|
|
processing.value = false;
|
|
}, 500);
|
|
};
|
|
|
|
const resetForm = () => {
|
|
form.resetForm({
|
|
values: {
|
|
nu: "",
|
|
country_code: 386,
|
|
type_id: props.types?.[0]?.id ?? null,
|
|
description: "",
|
|
validated: false,
|
|
phone_type: null,
|
|
},
|
|
});
|
|
};
|
|
|
|
const countryOptions = [
|
|
{ value: 386, label: "+386 (Slovenija)" },
|
|
{ value: 385, label: "+385 (Hrvaška)" },
|
|
{ value: 39, label: "+39 (Italija)" },
|
|
{ value: 36, label: "+36 (Madžarska)" },
|
|
{ value: 43, label: "+43 (Avstrija)" },
|
|
{ value: 381, label: "+381 (Srbija)" },
|
|
{ value: 387, label: "+387 (Bosna in Hercegovina)" },
|
|
{ value: 382, label: "+382 (Črna gora)" },
|
|
];
|
|
|
|
const phoneTypeOptions = [
|
|
{ value: null, label: "—" },
|
|
{ value: "mobile", label: "Mobilni" },
|
|
{ value: "landline", label: "Stacionarni" },
|
|
{ value: "voip", label: "VOIP" },
|
|
];
|
|
|
|
function hydrateFromProps() {
|
|
if (props.id) {
|
|
const p = props.person?.phones?.find((x) => x.id === props.id);
|
|
if (p) {
|
|
form.setValues({
|
|
nu: p.nu || "",
|
|
country_code: p.country_code ?? 386,
|
|
type_id: p.type_id ?? (props.types?.[0]?.id ?? null),
|
|
description: p.description || "",
|
|
validated: !!p.validated,
|
|
phone_type: p.phone_type ?? null,
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
resetForm();
|
|
}
|
|
|
|
watch(() => props.id, () => hydrateFromProps(), { immediate: true });
|
|
watch(() => props.show, (val) => { if (val) hydrateFromProps(); });
|
|
|
|
const update = async () => {
|
|
processing.value = true;
|
|
const { values } = form;
|
|
|
|
router.put(
|
|
route("person.phone.update", { person: props.person, phone_id: props.id }),
|
|
values,
|
|
{
|
|
preserveScroll: true,
|
|
onSuccess: () => {
|
|
close();
|
|
resetForm();
|
|
},
|
|
onError: (errors) => {
|
|
Object.keys(errors).forEach((field) => {
|
|
const errorMessages = Array.isArray(errors[field])
|
|
? errors[field]
|
|
: [errors[field]];
|
|
form.setFieldError(field, errorMessages[0]);
|
|
});
|
|
processing.value = false;
|
|
},
|
|
onFinish: () => {
|
|
processing.value = false;
|
|
},
|
|
}
|
|
);
|
|
};
|
|
|
|
const onSubmit = form.handleSubmit(() => {
|
|
update();
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<UpdateDialog
|
|
:show="show"
|
|
title="Spremeni telefon"
|
|
confirm-text="Shrani"
|
|
:processing="processing"
|
|
@close="close"
|
|
@confirm="onSubmit"
|
|
>
|
|
<form @submit.prevent="onSubmit">
|
|
<SectionTitle class="border-b mb-4">
|
|
<template #title> Telefon </template>
|
|
</SectionTitle>
|
|
|
|
<div class="space-y-4">
|
|
<FormField v-slot="{ componentField }" name="nu">
|
|
<FormItem>
|
|
<FormLabel>Številka</FormLabel>
|
|
<FormControl>
|
|
<Input type="text" placeholder="Številka telefona" autocomplete="tel" v-bind="componentField" />
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
</FormField>
|
|
|
|
<FormField v-slot="{ value, handleChange }" name="country_code">
|
|
<FormItem>
|
|
<FormLabel>Koda države tel.</FormLabel>
|
|
<Select :model-value="value" @update:model-value="handleChange">
|
|
<FormControl>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="Izberi kodo države" />
|
|
</SelectTrigger>
|
|
</FormControl>
|
|
<SelectContent>
|
|
<SelectItem v-for="option in countryOptions" :key="option.value" :value="option.value">
|
|
{{ option.label }}
|
|
</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
<FormMessage />
|
|
</FormItem>
|
|
</FormField>
|
|
|
|
<FormField v-slot="{ value, handleChange }" name="type_id">
|
|
<FormItem>
|
|
<FormLabel>Tip</FormLabel>
|
|
<Select :model-value="value" @update:model-value="handleChange">
|
|
<FormControl>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="Izberi tip" />
|
|
</SelectTrigger>
|
|
</FormControl>
|
|
<SelectContent>
|
|
<SelectItem v-for="type in types" :key="type.id" :value="type.id">
|
|
{{ type.name }}
|
|
</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
<FormMessage />
|
|
</FormItem>
|
|
</FormField>
|
|
|
|
<FormField v-slot="{ value, handleChange }" name="phone_type">
|
|
<FormItem>
|
|
<FormLabel>Vrsta telefona (enum)</FormLabel>
|
|
<Select :model-value="value" @update:model-value="handleChange">
|
|
<FormControl>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="Izberi vrsto" />
|
|
</SelectTrigger>
|
|
</FormControl>
|
|
<SelectContent>
|
|
<SelectItem v-for="option in phoneTypeOptions" :key="option.value" :value="option.value">
|
|
{{ option.label }}
|
|
</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
<FormMessage />
|
|
</FormItem>
|
|
</FormField>
|
|
|
|
<FormField v-slot="{ value, handleChange }" name="validated">
|
|
<FormItem class="flex flex-row items-start space-x-3 space-y-0">
|
|
<FormControl>
|
|
<Switch :model-value="value" @update:model-value="handleChange" />
|
|
</FormControl>
|
|
<div class="space-y-1 leading-none">
|
|
<FormLabel class="cursor-pointer">Potrjeno</FormLabel>
|
|
</div>
|
|
</FormItem>
|
|
</FormField>
|
|
</div>
|
|
</form>
|
|
</UpdateDialog>
|
|
</template>
|