Files
plantillas-proyectos/frontend/src/lib/components/dashboard/goods/fractions/CanadianFractionDialog.svelte

181 lines
4.8 KiB
Svelte

<script lang="ts">
import * as Dialog from '$lib/components/ui/dialog';
import { Input } from '$lib/components/ui/input';
import { Label } from '$lib/components/ui/label';
import { Button } from '$lib/components/ui/button';
import { Textarea } from '$lib/components/ui/textarea';
import {
createCanadianFraction,
updateCanadianFraction,
type CanadianFraction,
type CanadianFractionCreate,
type CanadianFractionUpdate
} from '$lib/api/dashboard/general_catalogs/canadian';
import { companyStore } from '$lib/stores/company.svelte';
import { toast } from 'svelte-sonner';
import { Loader2 } from 'lucide-svelte';
let {
open = $bindable(false),
fraction = null, // If null, create mode. If set, edit mode.
onSuccess
}: {
open: boolean;
fraction?: CanadianFraction | null;
onSuccess: () => void;
} = $props();
let isLoading = $state(false);
// Form fields
let fractionCode = $state('');
let countryCode = $state('');
let description = $state('');
let unitOfMeasure = $state('');
let adValorem = $state('');
// Load data on open/fraction change
$effect(() => {
if (open) {
if (fraction) {
// Edit mode
fractionCode = fraction.fraction;
countryCode = fraction.country_code;
description = fraction.description || '';
unitOfMeasure = fraction.unit_of_measure || '';
adValorem = fraction.ad_valorem?.toString() || '';
} else {
// Create mode - reset
fractionCode = '';
countryCode = '';
description = '';
unitOfMeasure = '';
adValorem = '';
}
}
});
async function handleSubmit() {
const companyId = companyStore.activeCompany?.id;
if (!companyId) return;
// Validation
if (!fractionCode) {
toast.error('La fracción es requerida');
return;
}
if (!countryCode) {
toast.error('El código de país es requerido');
return;
}
isLoading = true;
try {
const adValoremNum = adValorem ? parseFloat(adValorem) : undefined;
if (adValorem && isNaN(adValoremNum!)) {
toast.error('El Ad Valorem debe ser un número válido');
isLoading = false;
return;
}
if (fraction) {
// Update
const updateData: CanadianFractionUpdate = {
fraction: fractionCode,
country_code: countryCode,
description,
unit_of_measure: unitOfMeasure || undefined,
ad_valorem: adValoremNum
};
await updateCanadianFraction(companyId, fraction.id, updateData);
toast.success('Fracción actualizada correctamente');
} else {
// Create
const createData: CanadianFractionCreate = {
fraction: fractionCode,
country_code: countryCode,
description,
unit_of_measure: unitOfMeasure || undefined,
ad_valorem: adValoremNum
};
await createCanadianFraction(companyId, createData);
toast.success('Fracción creada correctamente');
}
onSuccess();
open = false;
} catch (error) {
console.error('Error saving Canadian fraction:', error);
toast.error('Error al guardar la fracción');
} finally {
isLoading = false;
}
}
</script>
<Dialog.Root bind:open>
<Dialog.Content class="sm:max-w-[600px]">
<Dialog.Header>
<Dialog.Title>{fraction ? 'Editar' : 'Crear'} Fracción Canadiense</Dialog.Title>
<Dialog.Description>
{fraction
? 'Modifica los detalles de la fracción seleccionada.'
: 'Ingresa los datos para la nueva fracción.'}
</Dialog.Description>
</Dialog.Header>
<div class="grid gap-4 py-4">
<div class="grid grid-cols-2 gap-4">
<div class="space-y-2">
<Label for="fraction">Fracción</Label>
<Input
id="fraction"
bind:value={fractionCode}
placeholder="Ej. 9999999999"
maxlength={13}
/>
</div>
<div class="space-y-2">
<Label for="country_code">País (Código ISO)</Label>
<Input id="country_code" bind:value={countryCode} placeholder="Ej. CAN" maxlength={3} />
</div>
</div>
<div class="space-y-2">
<Label for="description">Descripción</Label>
<Textarea
id="description"
bind:value={description}
placeholder="Descripción de la mercancía..."
/>
</div>
<div class="grid grid-cols-2 gap-4">
<div class="space-y-2">
<Label for="unit">Unidad de Medida</Label>
<Input id="unit" bind:value={unitOfMeasure} placeholder="Ej. Kg" maxlength={5} />
</div>
<div class="space-y-2">
<Label for="ad_valorem">Ad Valorem (%)</Label>
<Input
id="ad_valorem"
type="number"
step="0.01"
bind:value={adValorem}
placeholder="0.00"
/>
</div>
</div>
</div>
<Dialog.Footer>
<Button variant="outline" onclick={() => (open = false)}>Cancelar</Button>
<Button onclick={handleSubmit} disabled={isLoading}>
{#if isLoading}
<Loader2 class="mr-2 h-4 w-4 animate-spin" />
{/if}
Guardar
</Button>
</Dialog.Footer>
</Dialog.Content>
</Dialog.Root>