Teren-app/resources/js/Components/PersonInfo/PhoneUpdateForm.vue
Simon Pocrnjič b7fa2d261b changes UI
2025-11-04 18:53:23 +01:00

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>