415 lines
10 KiB
Svelte
415 lines
10 KiB
Svelte
<script lang="ts">
|
|
import { Card, CardContent } from '$lib/components/ui/card';
|
|
import { Button } from '$lib/components/ui/button';
|
|
import { Input } from '$lib/components/ui/input';
|
|
import { Label } from '$lib/components/ui/label';
|
|
import {
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableHead,
|
|
TableHeader,
|
|
TableRow
|
|
} from '$lib/components/ui/table';
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
DialogFooter
|
|
} from '$lib/components/ui/dialog';
|
|
import { Textarea } from '$lib/components/ui/textarea';
|
|
import {
|
|
Plus,
|
|
Pencil,
|
|
Trash2,
|
|
Upload,
|
|
FileText,
|
|
Search,
|
|
FolderOpen,
|
|
CheckCircle,
|
|
ChevronsLeft,
|
|
ChevronLeft,
|
|
ChevronRight,
|
|
ChevronsRight
|
|
} from 'lucide-svelte';
|
|
|
|
interface Digitalizacion {
|
|
id?: number;
|
|
linea: number;
|
|
clave: string;
|
|
documento: string;
|
|
e_document: string;
|
|
operacion: string;
|
|
observaciones: string;
|
|
}
|
|
|
|
let {
|
|
formData = $bindable({
|
|
digitalizaciones: [] as Digitalizacion[]
|
|
})
|
|
}: {
|
|
formData: {
|
|
digitalizaciones: Digitalizacion[];
|
|
};
|
|
} = $props();
|
|
|
|
// Estados para diálogo
|
|
let isDialogOpen = $state(false);
|
|
let editingIndex = $state<number | null>(null);
|
|
|
|
// Paginación
|
|
let currentPage = $state(0);
|
|
let pageSize = 10;
|
|
|
|
let currentDigitalizacion = $state<Digitalizacion>({
|
|
linea: 0,
|
|
clave: '',
|
|
documento: '',
|
|
e_document: '',
|
|
operacion: '',
|
|
observaciones: ''
|
|
});
|
|
|
|
const totalPages = $derived(
|
|
Math.ceil((formData?.digitalizaciones?.length ?? 0) / pageSize)
|
|
);
|
|
|
|
const paginatedDigitalizaciones = $derived(
|
|
formData?.digitalizaciones?.slice(
|
|
currentPage * pageSize,
|
|
(currentPage + 1) * pageSize
|
|
) ?? []
|
|
);
|
|
|
|
function openNewDigitalizacion() {
|
|
editingIndex = null;
|
|
const nextLinea = formData?.digitalizaciones?.length
|
|
? Math.max(...formData.digitalizaciones.map((d) => d.linea)) + 1
|
|
: 1;
|
|
currentDigitalizacion = {
|
|
linea: nextLinea,
|
|
clave: '',
|
|
documento: '',
|
|
e_document: '',
|
|
operacion: '',
|
|
observaciones: ''
|
|
};
|
|
isDialogOpen = true;
|
|
}
|
|
|
|
function openEditDigitalizacion(index: number) {
|
|
if (!formData?.digitalizaciones) return;
|
|
const realIndex = currentPage * pageSize + index;
|
|
editingIndex = realIndex;
|
|
currentDigitalizacion = { ...formData.digitalizaciones[realIndex] };
|
|
isDialogOpen = true;
|
|
}
|
|
|
|
function saveDigitalizacion() {
|
|
if (!formData?.digitalizaciones) return;
|
|
if (editingIndex !== null) {
|
|
formData.digitalizaciones[editingIndex] = { ...currentDigitalizacion };
|
|
} else {
|
|
formData.digitalizaciones = [...formData.digitalizaciones, { ...currentDigitalizacion }];
|
|
}
|
|
isDialogOpen = false;
|
|
}
|
|
|
|
function deleteDigitalizacion(index: number) {
|
|
if (!formData?.digitalizaciones) return;
|
|
const realIndex = currentPage * pageSize + index;
|
|
if (confirm('¿Está seguro de eliminar esta digitalización?')) {
|
|
formData.digitalizaciones = formData.digitalizaciones.filter((_, i) => i !== realIndex);
|
|
// Reordenar líneas
|
|
formData.digitalizaciones = formData.digitalizaciones.map((d, idx) => ({
|
|
...d,
|
|
linea: idx + 1
|
|
}));
|
|
// Ajustar página si es necesario
|
|
if (paginatedDigitalizaciones.length === 0 && currentPage > 0) {
|
|
currentPage--;
|
|
}
|
|
}
|
|
}
|
|
|
|
function digitalizarVU() {
|
|
alert('Digitalizar en VU no implementado aún');
|
|
}
|
|
|
|
function acuseDigitalizacion() {
|
|
alert('Acuse de Digitalización no implementado aún');
|
|
}
|
|
|
|
function procesarDigitalizacion() {
|
|
alert('Procesar Digitalización no implementado aún');
|
|
}
|
|
|
|
function consultarOperacion() {
|
|
alert('Consultar Operación no implementado aún');
|
|
}
|
|
|
|
function abrirDocumento() {
|
|
alert('Abrir Documento no implementado aún');
|
|
}
|
|
|
|
function cargarEDocument() {
|
|
alert('Cargar E-Document no implementado aún');
|
|
}
|
|
|
|
function goToFirstPage() {
|
|
currentPage = 0;
|
|
}
|
|
|
|
function goToPreviousPage() {
|
|
if (currentPage > 0) currentPage--;
|
|
}
|
|
|
|
function goToNextPage() {
|
|
if (currentPage < totalPages - 1) currentPage++;
|
|
}
|
|
|
|
function goToLastPage() {
|
|
currentPage = totalPages - 1;
|
|
}
|
|
</script>
|
|
|
|
<Card>
|
|
<CardContent class="p-6 space-y-4">
|
|
<!-- Tabla de digitalizaciones -->
|
|
<div class="border rounded-lg overflow-hidden">
|
|
<Table>
|
|
<TableHeader>
|
|
<TableRow>
|
|
<TableHead class="w-[80px]">Línea</TableHead>
|
|
<TableHead>Clave</TableHead>
|
|
<TableHead>Documento</TableHead>
|
|
<TableHead>E-Document</TableHead>
|
|
<TableHead>Operación</TableHead>
|
|
<TableHead>Observaciones</TableHead>
|
|
<TableHead class="w-[100px]">Acciones</TableHead>
|
|
</TableRow>
|
|
</TableHeader>
|
|
<TableBody>
|
|
{#if !formData?.digitalizaciones || formData.digitalizaciones.length === 0}
|
|
<TableRow>
|
|
<TableCell colspan={7} class="text-center text-muted-foreground py-8">
|
|
No hay digitalizaciones registradas
|
|
</TableCell>
|
|
</TableRow>
|
|
{:else if paginatedDigitalizaciones.length === 0}
|
|
<TableRow>
|
|
<TableCell colspan={7} class="text-center text-muted-foreground py-8">
|
|
No hay datos en esta página
|
|
</TableCell>
|
|
</TableRow>
|
|
{:else}
|
|
{#each paginatedDigitalizaciones as digitalizacion, index}
|
|
<TableRow>
|
|
<TableCell class="font-medium">{digitalizacion.linea}</TableCell>
|
|
<TableCell>{digitalizacion.clave}</TableCell>
|
|
<TableCell>{digitalizacion.documento}</TableCell>
|
|
<TableCell>{digitalizacion.e_document}</TableCell>
|
|
<TableCell>{digitalizacion.operacion}</TableCell>
|
|
<TableCell class="max-w-[200px] truncate" title={digitalizacion.observaciones}>
|
|
{digitalizacion.observaciones}
|
|
</TableCell>
|
|
<TableCell>
|
|
<div class="flex gap-1">
|
|
<Button
|
|
size="sm"
|
|
variant="ghost"
|
|
onclick={() => openEditDigitalizacion(index)}
|
|
>
|
|
<Pencil size={14} />
|
|
</Button>
|
|
<Button size="sm" variant="ghost" onclick={() => deleteDigitalizacion(index)}>
|
|
<Trash2 size={14} />
|
|
</Button>
|
|
</div>
|
|
</TableCell>
|
|
</TableRow>
|
|
{/each}
|
|
{/if}
|
|
</TableBody>
|
|
</Table>
|
|
</div>
|
|
|
|
<!-- Controles de paginación -->
|
|
{#if formData?.digitalizaciones && formData.digitalizaciones.length > 0}
|
|
<div class="flex items-center justify-center gap-2 border-t pt-3">
|
|
<Button
|
|
size="sm"
|
|
variant="outline"
|
|
onclick={goToFirstPage}
|
|
disabled={currentPage === 0}
|
|
class="w-8 h-8 p-0"
|
|
>
|
|
<ChevronsLeft size={16} />
|
|
</Button>
|
|
<Button
|
|
size="sm"
|
|
variant="outline"
|
|
onclick={goToPreviousPage}
|
|
disabled={currentPage === 0}
|
|
class="w-8 h-8 p-0"
|
|
>
|
|
<ChevronLeft size={16} />
|
|
</Button>
|
|
<span class="text-sm text-muted-foreground px-2">
|
|
Página {currentPage + 1} de {totalPages || 1}
|
|
</span>
|
|
<Button
|
|
size="sm"
|
|
variant="outline"
|
|
onclick={goToNextPage}
|
|
disabled={currentPage >= totalPages - 1}
|
|
class="w-8 h-8 p-0"
|
|
>
|
|
<ChevronRight size={16} />
|
|
</Button>
|
|
<Button
|
|
size="sm"
|
|
variant="outline"
|
|
onclick={goToLastPage}
|
|
disabled={currentPage >= totalPages - 1}
|
|
class="w-8 h-8 p-0"
|
|
>
|
|
<ChevronsRight size={16} />
|
|
</Button>
|
|
</div>
|
|
{/if}
|
|
|
|
<!-- Botones de acción -->
|
|
<div class="flex flex-wrap gap-2 border-t pt-4">
|
|
<Button size="sm" variant="outline" onclick={digitalizarVU}>
|
|
<Upload class="mr-1.5" size={14} />
|
|
Digitalizar en VU
|
|
</Button>
|
|
<Button size="sm" variant="outline" onclick={acuseDigitalizacion}>
|
|
<CheckCircle class="mr-1.5" size={14} />
|
|
Acuse de Digitalización
|
|
</Button>
|
|
<Button size="sm" variant="outline" onclick={procesarDigitalizacion}>
|
|
<FileText class="mr-1.5" size={14} />
|
|
Procesar Digitalización
|
|
</Button>
|
|
<Button size="sm" onclick={openNewDigitalizacion}>
|
|
<Plus class="mr-1.5" size={14} />
|
|
Nuevo
|
|
</Button>
|
|
<Button
|
|
size="sm"
|
|
variant="outline"
|
|
disabled={formData?.digitalizaciones?.length === 0}
|
|
onclick={() => {
|
|
if (paginatedDigitalizaciones[0]) openEditDigitalizacion(0);
|
|
}}
|
|
>
|
|
<Pencil class="mr-1.5" size={14} />
|
|
Editar
|
|
</Button>
|
|
<Button
|
|
size="sm"
|
|
variant="destructive"
|
|
disabled={formData?.digitalizaciones?.length === 0}
|
|
onclick={() => {
|
|
if (paginatedDigitalizaciones[0]) deleteDigitalizacion(0);
|
|
}}
|
|
>
|
|
<Trash2 class="mr-1.5" size={14} />
|
|
Borrar
|
|
</Button>
|
|
<Button size="sm" variant="outline" onclick={consultarOperacion}>
|
|
<Search class="mr-1.5" size={14} />
|
|
Consultar Operación
|
|
</Button>
|
|
<Button size="sm" variant="outline" onclick={abrirDocumento}>
|
|
<FolderOpen class="mr-1.5" size={14} />
|
|
Abrir Documento
|
|
</Button>
|
|
<Button size="sm" variant="outline" onclick={cargarEDocument}>
|
|
<Upload class="mr-1.5" size={14} />
|
|
Cargar E-Document
|
|
</Button>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<!-- Dialog para Digitalización -->
|
|
<Dialog bind:open={isDialogOpen}>
|
|
<DialogContent class="max-w-2xl">
|
|
<DialogHeader>
|
|
<DialogTitle>
|
|
{editingIndex !== null ? 'Editar Digitalización' : 'Nueva Digitalización'}
|
|
</DialogTitle>
|
|
</DialogHeader>
|
|
|
|
<div class="grid gap-4 py-4">
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<div class="space-y-2">
|
|
<Label for="linea">Línea *</Label>
|
|
<Input
|
|
id="linea"
|
|
type="number"
|
|
bind:value={currentDigitalizacion.linea}
|
|
placeholder="1"
|
|
readonly
|
|
/>
|
|
</div>
|
|
<div class="space-y-2">
|
|
<Label for="clave">Clave *</Label>
|
|
<Input id="clave" bind:value={currentDigitalizacion.clave} placeholder="Clave" />
|
|
</div>
|
|
</div>
|
|
|
|
<div class="space-y-2">
|
|
<Label for="documento">Documento *</Label>
|
|
<Input
|
|
id="documento"
|
|
bind:value={currentDigitalizacion.documento}
|
|
placeholder="Nombre o tipo del documento"
|
|
/>
|
|
</div>
|
|
|
|
<div class="space-y-2">
|
|
<Label for="e_document">E-Document</Label>
|
|
<Input
|
|
id="e_document"
|
|
bind:value={currentDigitalizacion.e_document}
|
|
placeholder="Referencia del documento electrónico"
|
|
/>
|
|
</div>
|
|
|
|
<div class="space-y-2">
|
|
<Label for="operacion">Operación</Label>
|
|
<Input
|
|
id="operacion"
|
|
bind:value={currentDigitalizacion.operacion}
|
|
placeholder="Tipo de operación"
|
|
/>
|
|
</div>
|
|
|
|
<div class="space-y-2">
|
|
<Label for="observaciones">Observaciones</Label>
|
|
<Textarea
|
|
id="observaciones"
|
|
bind:value={currentDigitalizacion.observaciones}
|
|
placeholder="Observaciones adicionales"
|
|
rows={3}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<DialogFooter>
|
|
<Button variant="outline" onclick={() => (isDialogOpen = false)}>Cancelar</Button>
|
|
<Button
|
|
onclick={saveDigitalizacion}
|
|
disabled={!currentDigitalizacion.clave || !currentDigitalizacion.documento}
|
|
>
|
|
{editingIndex !== null ? 'Actualizar' : 'Guardar'}
|
|
</Button>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|