Se agrego la forma de seleccion de clase, cliente y unidades de medida

This commit is contained in:
2026-01-07 11:36:35 -06:00
parent 7249607fd7
commit c57ddada6e
3 changed files with 275 additions and 41 deletions

View File

@@ -0,0 +1,179 @@
<script lang="ts">
import * as Dialog from "$lib/components/ui/dialog";
import { Input } from "$lib/components/ui/input";
import { Button } from "$lib/components/ui/button";
import { Search, Loader2, Scale, Check } from "lucide-svelte";
import * as Table from "$lib/components/ui/table";
import { companyStore } from '$lib/stores/company.svelte';
import { getUnitsOfMeasure, type UnitOfMeasure } from '$lib/api/dashboard/a76/general_catalogs/units-of-measure';
let {
open = $bindable(false),
onSelect
}: {
open: boolean;
onSelect: (item: UnitOfMeasure) => void;
} = $props();
let items = $state<UnitOfMeasure[]>([]);
let loading = $state(false);
let searchTerm = $state("");
let page = $state(1);
let totalPages = $state(1);
let searchTimeout: NodeJS.Timeout;
// Cargar datos al abrir
$effect(() => {
if (open && companyStore.activeCompany) {
loadData();
}
});
async function loadData() {
if (!companyStore.activeCompany) return;
loading = true;
try {
const filters = searchTerm ? { code: searchTerm } : {};
// Nota: Si tu backend soporta búsqueda por descripción, úsalo aquí.
// Por ahora asumo búsqueda por 'code' o 'description' según tu filtro backend.
const response = await getUnitsOfMeasure(page, 10, companyStore.activeCompany.id, {
q: searchTerm // Asumiendo que tu backend tiene un filtro genérico 'q' o usa 'code'/'description'
});
if (response.data) {
items = response.data.items;
totalPages = response.data.pages;
}
} catch (error) {
console.error("Error cargando unidades:", error);
} finally {
loading = false;
}
}
function handleSearch(e: Event) {
const value = (e.target as HTMLInputElement).value;
searchTerm = value;
page = 1;
clearTimeout(searchTimeout);
searchTimeout = setTimeout(() => {
loadData();
}, 500);
}
function handleSelect(item: UnitOfMeasure) {
onSelect(item);
open = false;
}
function nextPage() {
if (page < totalPages) {
page++;
loadData();
}
}
function prevPage() {
if (page > 1) {
page--;
loadData();
}
}
</script>
<Dialog.Root bind:open>
<Dialog.Content class="sm:max-w-[600px]">
<Dialog.Header>
<Dialog.Title>Seleccionar Unidad de Medida</Dialog.Title>
<Dialog.Description>
Busca y selecciona una unidad del catálogo maestro.
</Dialog.Description>
</Dialog.Header>
<div class="space-y-4 py-4">
<div class="relative">
<Search class="absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" />
<Input
placeholder="Buscar por código (KG, PZ...) o descripción..."
class="pl-8"
value={searchTerm}
oninput={handleSearch}
/>
</div>
<div class="rounded-md border h-[300px] overflow-auto relative">
{#if loading}
<div class="absolute inset-0 bg-background/50 flex items-center justify-center z-10">
<Loader2 class="h-6 w-6 animate-spin text-primary" />
</div>
{/if}
<Table.Root>
<Table.Header>
<Table.Row>
<Table.Head class="w-[80px]">Código</Table.Head>
<Table.Head>Descripción</Table.Head>
<Table.Head class="text-right w-[50px]"></Table.Head>
</Table.Row>
</Table.Header>
<Table.Body>
{#if items.length === 0 && !loading}
<Table.Row>
<Table.Cell colspan={3} class="text-center h-24 text-muted-foreground">
No se encontraron resultados
</Table.Cell>
</Table.Row>
{:else}
{#each items as item}
<Table.Row
class="cursor-pointer hover:bg-muted/50"
onclick={() => handleSelect(item)}
>
<Table.Cell class="font-mono font-bold">{item.code}</Table.Cell>
<Table.Cell>
<div class="flex flex-col">
<span>{item.description || '-'}</span>
{#if item.description_en}
<span class="text-xs text-muted-foreground">{item.description_en}</span>
{/if}
</div>
</Table.Cell>
<Table.Cell class="text-right">
<Button variant="ghost" size="icon" class="h-6 w-6">
<Check class="h-4 w-4" />
</Button>
</Table.Cell>
</Table.Row>
{/each}
{/if}
</Table.Body>
</Table.Root>
</div>
<div class="flex items-center justify-between">
<span class="text-xs text-muted-foreground">Página {page} de {totalPages}</span>
<div class="flex gap-2">
<Button
variant="outline"
size="sm"
disabled={page === 1 || loading}
onclick={prevPage}
>
Anterior
</Button>
<Button
variant="outline"
size="sm"
disabled={page >= totalPages || loading}
onclick={nextPage}
>
Siguiente
</Button>
</div>
</div>
</div>
</Dialog.Content>
</Dialog.Root>