store/resources/js/components/admin/manage/orders/CustomerQuickCreateModal.vue

122 lines
4.0 KiB
Vue

<script setup lang="ts">
import { Save } from '@lucide/vue';
import { reactive, ref } from 'vue';
import { toast } from 'vue-sonner';
import { PhoneNumberInput } from '@/components/form/phone-number-input';
import { Button } from '@/components/ui/button';
import {
Dialog,
DialogContent,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';
import {
Field,
FieldError,
FieldGroup,
FieldLabel,
FieldSet,
} from '@/components/ui/field';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import { apiFetch } from '@/lib/api';
import { FIELD_LIMITS } from '@/lib/field-limits';
const open = defineModel<boolean>('open', { default: false });
const emit = defineEmits<{
created: [customer: { id: number; name: string }];
}>();
const processing = ref(false);
const errors = reactive<Record<string, string>>({});
const form = reactive({
name: '',
phone_number: '',
address: '',
});
function resetForm() {
form.name = '';
form.phone_number = '';
form.address = '';
Object.keys(errors).forEach((key) => delete errors[key]);
}
async function submit() {
Object.keys(errors).forEach((key) => delete errors[key]);
processing.value = true;
try {
const customer = await apiFetch<{ id: number; name: string }>('/admin/master/customers/api', {
method: 'POST',
body: JSON.stringify({
name: form.name,
phone_number: form.phone_number || null,
address: form.address || null,
}),
});
emit('created', customer);
open.value = false;
resetForm();
toast.success('Pelanggan berhasil ditambahkan.');
} catch (error) {
const message = error instanceof Error ? error.message : 'Gagal menyimpan data.';
if (message.includes('nama')) {
errors.name = message;
} else {
toast.error(message);
}
} finally {
processing.value = false;
}
}
</script>
<template>
<Dialog v-model:open="open">
<DialogContent class="sm:max-w-md">
<DialogHeader>
<DialogTitle>Tambah Pelanggan</DialogTitle>
</DialogHeader>
<form @submit.prevent="submit">
<FieldGroup>
<FieldSet class="grid gap-4">
<Field>
<FieldLabel for="quick-customer-name" required>Nama</FieldLabel>
<Input id="quick-customer-name" v-model="form.name" type="text"
placeholder="Contoh: Budi Santoso" autofocus :maxlength="FIELD_LIMITS.name" />
<FieldError v-if="errors.name" :errors="[errors.name]" />
</Field>
<Field>
<FieldLabel for="quick-customer-phone">Nomor Telepon</FieldLabel>
<PhoneNumberInput id="quick-customer-phone" v-model="form.phone_number"
placeholder="Contoh: 08123456789" />
</Field>
<Field>
<FieldLabel for="quick-customer-address">Alamat</FieldLabel>
<Textarea id="quick-customer-address" v-model="form.address" rows="3"
placeholder="Contoh: Jl. Mawar No. 12, Surabaya" />
</Field>
</FieldSet>
</FieldGroup>
<DialogFooter class="mt-6">
<Button type="button" variant="outline" :disabled="processing" @click="open = false">
Batal
</Button>
<Button type="submit" :disabled="processing">
<Save class="size-4" />
{{ processing ? 'Menyimpan...' : 'Simpan' }}
</Button>
</DialogFooter>
</form>
</DialogContent>
</Dialog>
</template>