261 lines
6.4 KiB
Svelte
261 lines
6.4 KiB
Svelte
<script lang="ts">
|
|
import { Button } from "$lib/components/ui/button";
|
|
import * as Dialog from "$lib/components/ui/dialog";
|
|
import { Input } from "$lib/components/ui/input";
|
|
import { Label } from "$lib/components/ui/label";
|
|
import { createPackage, updatePackage, type Package} from "$lib/api/dashboard/a76/general_catalogs/packages";
|
|
import { companyStore } from "$lib/stores/company.svelte";
|
|
|
|
let {
|
|
open = $bindable(false),
|
|
item = null,
|
|
onSuccess
|
|
}: {
|
|
open: boolean;
|
|
item?: Package | null;
|
|
onSuccess?: () => void;
|
|
} = $props();
|
|
|
|
// Determinar si es modo edición o creación
|
|
const isEdit = $derived(!!item);
|
|
const title = $derived(isEdit ? "Editar Bulto" : "Nuevo Bulto");
|
|
|
|
// Estado del formulario
|
|
let formData = $state({
|
|
key: item?.key || '',
|
|
description_es: item?.description_es || '',
|
|
description_en: item?.description_en || '',
|
|
weight_unit: item?.weight_unit || null,
|
|
plurals: item?.plurals || '',
|
|
plural_in: item?.plural_in || '',
|
|
code_ace: item?.code_ace || '',
|
|
code_aamex: item?.code_aamex || ''
|
|
});
|
|
|
|
let loading = $state(false);
|
|
let error = $state<string | null>(null);
|
|
|
|
// Resetear formulario cuando cambia el item
|
|
$effect(() => {
|
|
if (item) {
|
|
formData = {
|
|
key: item.key,
|
|
description_es: item.description_es || '',
|
|
description_en: item.description_en || '',
|
|
weight_unit: item.weight_unit,
|
|
plurals: item.plurals || '',
|
|
plural_in: item.plural_in || '',
|
|
code_ace: item.code_ace || '',
|
|
code_aamex: item.code_aamex || ''
|
|
};
|
|
} else {
|
|
formData = {
|
|
key: '',
|
|
description_es: '',
|
|
description_en: '',
|
|
weight_unit: null,
|
|
plurals: '',
|
|
plural_in: '',
|
|
code_ace: '',
|
|
code_aamex: ''
|
|
};
|
|
}
|
|
});
|
|
|
|
async function handleSubmit() {
|
|
error = null;
|
|
loading = true;
|
|
|
|
try {
|
|
const companyId = companyStore.activeCompany?.id;
|
|
if (!companyId) {
|
|
throw new Error('No hay una compañía seleccionada');
|
|
}
|
|
|
|
// Validación básica
|
|
if (!formData.key.trim()) {
|
|
throw new Error('La clave es requerida');
|
|
}
|
|
|
|
if (formData.key.length > 5) {
|
|
throw new Error('La clave no puede tener más de 5 caracteres');
|
|
}
|
|
|
|
// Preparar datos
|
|
const dataToSend = {
|
|
key: formData.key.trim(),
|
|
description_es: formData.description_es.trim() || null,
|
|
description_en: formData.description_en.trim() || null,
|
|
weight_unit: formData.weight_unit,
|
|
plurals: formData.plurals.trim() || null,
|
|
plural_in: formData.plural_in.trim() || null,
|
|
code_ace: formData.code_ace.trim() || null,
|
|
code_aamex: formData.code_aamex.trim() || null
|
|
};
|
|
|
|
let response;
|
|
if (isEdit && item) {
|
|
response = await updatePackage(item.id, dataToSend, companyId);
|
|
} else {
|
|
response = await createPackage(dataToSend, companyId);
|
|
}
|
|
|
|
if (response.error) {
|
|
throw new Error(response.error);
|
|
}
|
|
|
|
// Cerrar diálogo y notificar éxito
|
|
open = false;
|
|
if (onSuccess) {
|
|
onSuccess();
|
|
}
|
|
} catch (e) {
|
|
error = e instanceof Error ? e.message : 'Error al guardar el bulto';
|
|
} finally {
|
|
loading = false;
|
|
}
|
|
}
|
|
|
|
function handleCancel() {
|
|
open = false;
|
|
error = null;
|
|
}
|
|
</script>
|
|
|
|
<Dialog.Root bind:open>
|
|
<Dialog.Content class="max-w-2xl max-h-[90vh] overflow-y-auto">
|
|
<Dialog.Header>
|
|
<Dialog.Title>{title}</Dialog.Title>
|
|
<Dialog.Description>
|
|
{isEdit ? 'Modifica los datos del bulto' : 'Completa los datos para crear un nuevo bulto'}
|
|
</Dialog.Description>
|
|
</Dialog.Header>
|
|
|
|
<form onsubmit={(e) => { e.preventDefault(); handleSubmit(); }} class="space-y-4">
|
|
{#if error}
|
|
<div class="rounded-md bg-destructive/15 p-3 text-sm text-destructive">
|
|
{error}
|
|
</div>
|
|
{/if}
|
|
|
|
<div class="grid gap-4">
|
|
<!-- Clave -->
|
|
<div class="grid gap-2">
|
|
<Label for="key">
|
|
Clave <span class="text-destructive">*</span>
|
|
</Label>
|
|
<Input
|
|
id="key"
|
|
bind:value={formData.key}
|
|
placeholder="Ej: CAJA"
|
|
maxlength={5}
|
|
required
|
|
disabled={isEdit}
|
|
/>
|
|
<p class="text-xs text-muted-foreground">
|
|
Máximo 5 caracteres. {isEdit ? 'No se puede modificar en edición.' : ''}
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Descripciones -->
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<div class="grid gap-2">
|
|
<Label for="description_es">Descripción (Español)</Label>
|
|
<Input
|
|
id="description_es"
|
|
bind:value={formData.description_es}
|
|
placeholder="Ej: Caja de cartón"
|
|
maxlength={40}
|
|
/>
|
|
</div>
|
|
|
|
<div class="grid gap-2">
|
|
<Label for="description_en">Descripción (Inglés)</Label>
|
|
<Input
|
|
id="description_en"
|
|
bind:value={formData.description_en}
|
|
placeholder="Ej: Cardboard box"
|
|
maxlength={40}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Peso Unitario -->
|
|
<div class="grid gap-2">
|
|
<Label for="weight_unit">Peso Unitario</Label>
|
|
<Input
|
|
id="weight_unit"
|
|
type="number"
|
|
step="0.00000001"
|
|
bind:value={formData.weight_unit}
|
|
placeholder="0.00"
|
|
/>
|
|
<p class="text-xs text-muted-foreground">
|
|
Peso unitario del bulto (hasta 8 decimales)
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Plurales -->
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<div class="grid gap-2">
|
|
<Label for="plurals">Plural</Label>
|
|
<Input
|
|
id="plurals"
|
|
bind:value={formData.plurals}
|
|
placeholder="Ej: CAJS"
|
|
maxlength={4}
|
|
/>
|
|
</div>
|
|
|
|
<div class="grid gap-2">
|
|
<Label for="plural_in">Plural (Inglés)</Label>
|
|
<Input
|
|
id="plural_in"
|
|
bind:value={formData.plural_in}
|
|
placeholder="Ej: BOXS"
|
|
maxlength={4}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Códigos -->
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<div class="grid gap-2">
|
|
<Label for="code_ace">Código ACE</Label>
|
|
<Input
|
|
id="code_ace"
|
|
bind:value={formData.code_ace}
|
|
placeholder="Código ACE"
|
|
maxlength={4}
|
|
/>
|
|
</div>
|
|
|
|
<div class="grid gap-2">
|
|
<Label for="code_aamex">Código AAMEX</Label>
|
|
<Input
|
|
id="code_aamex"
|
|
bind:value={formData.code_aamex}
|
|
placeholder="Código AAMEX"
|
|
maxlength={9}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<Dialog.Footer>
|
|
<Button
|
|
type="button"
|
|
variant="outline"
|
|
onclick={handleCancel}
|
|
disabled={loading}
|
|
>
|
|
Cancelar
|
|
</Button>
|
|
<Button type="submit" disabled={loading}>
|
|
{loading ? 'Guardando...' : isEdit ? 'Actualizar' : 'Crear'}
|
|
</Button>
|
|
</Dialog.Footer>
|
|
</form>
|
|
</Dialog.Content>
|
|
</Dialog.Root>
|