mirror of
https://origin.cursor.com/mrdevmx/panels.git
synced 2026-10-09 18:23:22 +00:00
Proveedor y unidad pasan a Select de catálogo (no texto libre). Subtotal, IVA y total se calculan al vuelo. El comprobante usa FileUpload de PrimeVue. Co-authored-by: alberto.martinez <alberto.martinez@mrdev.mx>
129 lines
3.6 KiB
Vue
129 lines
3.6 KiB
Vue
<template>
|
|
<Dialog
|
|
v-model:visible="visible"
|
|
:header="supplierId ? 'Editar proveedor' : 'Nuevo proveedor'"
|
|
modal
|
|
:style="{ width: '640px' }"
|
|
>
|
|
<div class="form-grid form-grid-compact">
|
|
<FormField label="Nombre comercial" required>
|
|
<InputText v-model="form.name" class="w-full" placeholder="Home Depot" />
|
|
</FormField>
|
|
<FormField label="Razón social">
|
|
<InputText v-model="form.legal_name" class="w-full" />
|
|
</FormField>
|
|
<FormField label="RFC">
|
|
<InputText v-model="form.rfc" class="w-full identifier-input" maxlength="13" placeholder="XAXX010101000" />
|
|
</FormField>
|
|
<FormField label="Teléfono">
|
|
<InputText v-model="form.phone" class="w-full" />
|
|
</FormField>
|
|
<FormField label="Correo">
|
|
<InputText v-model="form.email" class="w-full no-caps" />
|
|
</FormField>
|
|
<FormField label="Ciudad">
|
|
<InputText v-model="form.city" class="w-full" />
|
|
</FormField>
|
|
<FormField label="Domicilio" class="span-2">
|
|
<InputText v-model="form.address" class="w-full" />
|
|
</FormField>
|
|
<FormField label="Notas" class="span-2">
|
|
<Textarea v-model="form.notes" class="w-full" rows="2" auto-resize />
|
|
</FormField>
|
|
</div>
|
|
<Message v-if="error" severity="error" class="mt-3" :closable="false">{{ error }}</Message>
|
|
<template #footer>
|
|
<Button label="Cancelar" text @click="visible = false" />
|
|
<Button label="Guardar" icon="pi pi-check" :loading="saving" @click="save" />
|
|
</template>
|
|
</Dialog>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import FormField from "~/components/padron/FormField.vue";
|
|
import { displayErrorMessage } from "~/composables/api-response";
|
|
|
|
export type Supplier = {
|
|
id: number;
|
|
name: string;
|
|
legal_name?: string;
|
|
rfc?: string;
|
|
email?: string;
|
|
phone?: string;
|
|
address?: string;
|
|
city?: string;
|
|
state?: string;
|
|
postal_code?: string;
|
|
notes?: string;
|
|
status?: string;
|
|
};
|
|
|
|
const props = defineProps<{
|
|
modelValue: boolean;
|
|
supplier?: Supplier | null;
|
|
}>();
|
|
const emit = defineEmits<{
|
|
"update:modelValue": [boolean];
|
|
saved: [Supplier];
|
|
}>();
|
|
|
|
const { api } = useApi();
|
|
const visible = computed({
|
|
get: () => props.modelValue,
|
|
set: (v: boolean) => emit("update:modelValue", v),
|
|
});
|
|
|
|
const empty = () => ({
|
|
name: "",
|
|
legal_name: "",
|
|
rfc: "",
|
|
email: "",
|
|
phone: "",
|
|
address: "",
|
|
city: "",
|
|
notes: "",
|
|
});
|
|
|
|
const form = reactive(empty());
|
|
const error = ref("");
|
|
const saving = ref(false);
|
|
const supplierId = computed(() => props.supplier?.id ?? null);
|
|
|
|
watch(
|
|
() => [props.modelValue, props.supplier] as const,
|
|
([open, supplier]) => {
|
|
if (!open) return;
|
|
error.value = "";
|
|
Object.assign(form, empty(), supplier || {});
|
|
},
|
|
);
|
|
|
|
async function save() {
|
|
error.value = "";
|
|
if (!form.name.trim()) {
|
|
error.value = "El nombre del proveedor es obligatorio";
|
|
return;
|
|
}
|
|
saving.value = true;
|
|
try {
|
|
const payload = { ...form, rfc: form.rfc.trim().toUpperCase() };
|
|
const r = supplierId.value
|
|
? await api<{ supplier?: Supplier; data?: { supplier?: Supplier } }>(`/v1/suppliers/${supplierId.value}`, {
|
|
method: "PATCH",
|
|
json: payload,
|
|
})
|
|
: await api<{ supplier?: Supplier; data?: { supplier?: Supplier } }>("/v1/suppliers", {
|
|
method: "POST",
|
|
json: payload,
|
|
});
|
|
const saved = r.supplier ?? r.data?.supplier;
|
|
if (!saved) throw new Error("No se recibió el proveedor guardado");
|
|
emit("saved", saved);
|
|
visible.value = false;
|
|
} catch (e) {
|
|
error.value = displayErrorMessage((e as { data?: unknown }).data ?? e);
|
|
} finally {
|
|
saving.value = false;
|
|
}
|
|
}
|
|
</script>
|