diff --git a/frontend/src/lib/api/dashboard/refrence_data/containers.ts b/frontend/src/lib/api/dashboard/refrence_data/containers.ts new file mode 100644 index 00000000..1bd2a7fc --- /dev/null +++ b/frontend/src/lib/api/dashboard/refrence_data/containers.ts @@ -0,0 +1,69 @@ +/** + * API Client para Containers + * Gestiona las operaciones CRUD para los contenedores + */ +import { api } from '$lib/api'; + +export interface Container { + key: string; + description: string; +} + +export interface ContainerListResponse { + items: Container[]; + total: number; + page: number; + page_size: number; +} + +export interface CreateContainerData { + key: string; + description: string; +} + +export interface UpdateContainerData { + key?: string; + description?: string; +} + +/** + * API para Containers + */ +export const containersApi = { + /** + * Lista todos los containers con paginación + * @param page - Número de página (por defecto 1) + * @param pageSize - Tamaño de página (por defecto 50) + */ + list: (page = 1, pageSize = 50) => + api.get( + `/v1/containers?page=${page}&page_size=${pageSize}` + ), + + /** + * Obtiene un container por ID + * @param key - ID del container + */ + get: (key: number) => api.get(`/v1/containers/${key}`), + + /** + * Crea un nuevo container + * @param data - Datos del container a crear + */ + create: (data: CreateContainerData) => + api.post('/v1/containers', data), + + /** + * Actualiza un container existente + * @param key - ID del container a actualizar + * @param data - Datos a actualizar + */ + update: (key: number, data: UpdateContainerData) => + api.put(`/v1/containers/${key}`, data), + + /** + * Elimina un container + * @param key - ID del container a eliminar + */ + delete: (key: number) => api.delete(`/v1/containers/${key}`) +}; diff --git a/frontend/src/lib/components/dashboard/reference_data/containers/columns.ts b/frontend/src/lib/components/dashboard/reference_data/containers/columns.ts new file mode 100644 index 00000000..1af38551 --- /dev/null +++ b/frontend/src/lib/components/dashboard/reference_data/containers/columns.ts @@ -0,0 +1,50 @@ +import type { ColumnDef } from "@tanstack/table-core"; +import { renderComponent, renderSnippet } from "$lib/components/ui/data-table/index.js"; +import { createRawSnippet } from "svelte"; +import DataTableActions from "./data-table-actions.svelte"; + +export type Container = { + key: string; + description: string; +}; + +export function createColumns(onSuccess?: () => void): ColumnDef[] { + return [ + { + accessorKey: "key", + header: "Código", + cell: ({ row }) => { + const codeSnippet = createRawSnippet<[{ code: string }]>((getCode) => { + const { code } = getCode(); + return { + render: () => + `${code}` + }; + }); + return renderSnippet(codeSnippet, { code: row.original.key }); + } + }, + { + accessorKey: "description", + header: "Descripción", + cell: ({ row }) => { + const descSnippet = createRawSnippet<[{ description: string }]>((getDesc) => { + const { description } = getDesc(); + return { + render: () => `
${description}
` + }; + }); + return renderSnippet(descSnippet, { description: row.original.description }); + } + }, + { + id: "actions", + cell: ({ row }) => { + return renderComponent(DataTableActions, { item: row.original, onSuccess }); + } + } + ]; +} + +// Mantener compatibilidad hacia atrás +export const columns = createColumns(); diff --git a/frontend/src/lib/components/dashboard/reference_data/containers/create-edit-dialog.svelte b/frontend/src/lib/components/dashboard/reference_data/containers/create-edit-dialog.svelte new file mode 100644 index 00000000..75aec764 --- /dev/null +++ b/frontend/src/lib/components/dashboard/reference_data/containers/create-edit-dialog.svelte @@ -0,0 +1,184 @@ + + + + + + + {isEditing ? "Editar" : "Nuevo"} Contenedor + + + {isEditing + ? "Modifica los datos del contenedor." + : "Completa los datos para crear un nuevo contenedor."} + + + +
+ {#if error} +
+ {error} +
+ {/if} + +
+ + +
+ +
+ + +
+ + + + + +
+
+
diff --git a/frontend/src/lib/components/dashboard/reference_data/containers/data-table-actions.svelte b/frontend/src/lib/components/dashboard/reference_data/containers/data-table-actions.svelte new file mode 100644 index 00000000..f23c31c8 --- /dev/null +++ b/frontend/src/lib/components/dashboard/reference_data/containers/data-table-actions.svelte @@ -0,0 +1,66 @@ + + + + + {#snippet child({ props })} + + {/snippet} + + + + Acciones + + Copiar ID + + + + Ver detalles + Editar + + Eliminar + + + + + + + diff --git a/frontend/src/lib/components/dashboard/reference_data/containers/data-table.svelte b/frontend/src/lib/components/dashboard/reference_data/containers/data-table.svelte new file mode 100644 index 00000000..ef98de23 --- /dev/null +++ b/frontend/src/lib/components/dashboard/reference_data/containers/data-table.svelte @@ -0,0 +1,123 @@ + + +
+
+ + + {#each table.getHeaderGroups() as headerGroup (headerGroup.id)} + + {#each headerGroup.headers as header (header.id)} + + {#if !header.isPlaceholder} + + {/if} + + {/each} + + {/each} + + + {#each table.getRowModel().rows as row (row.id)} + + {#each row.getVisibleCells() as cell (cell.id)} + + + + {/each} + + {:else} + + + No hay resultados. + + + {/each} + + + {#if hasMore} + + +
+ {#if loading} +
+
+ Cargando más... +
+ {:else} +
+ Desplázate para cargar más +
+ {/if} +
+
+
+ {/if} +
+
+
+
diff --git a/frontend/src/lib/components/dashboard/reference_data/containers/delete-dialog.svelte b/frontend/src/lib/components/dashboard/reference_data/containers/delete-dialog.svelte new file mode 100644 index 00000000..88ddcb9b --- /dev/null +++ b/frontend/src/lib/components/dashboard/reference_data/containers/delete-dialog.svelte @@ -0,0 +1,112 @@ + + + + + + ¿Estás seguro? + +

Esta acción no se puede deshacer. Se eliminará permanentemente este contenedor:

+ {#if item} +
+
+ Código: + {item.key} +
+
+ Descripción: + {item.description} +
+
+ {/if} + {#if error} +
+ {error} +
+ {/if} +
+
+ + Cancelar + + {#if loading} + + + + + {/if} + Eliminar + + +
+
diff --git a/frontend/src/lib/components/dashboard/reference_data/containers/details-dialog.svelte b/frontend/src/lib/components/dashboard/reference_data/containers/details-dialog.svelte new file mode 100644 index 00000000..4a7a7bc6 --- /dev/null +++ b/frontend/src/lib/components/dashboard/reference_data/containers/details-dialog.svelte @@ -0,0 +1,57 @@ + + + + + + Detalles del Contenedor + + Información completa del contenedor + + + + {#if item} +
+
+
+ Código + + {item.key} + +
+ +
+ +
+
+ Descripción +

{item.description}

+
+ +
+
+ {/if} + + + + +
+
diff --git a/frontend/src/lib/components/sidebar/modules.ts b/frontend/src/lib/components/sidebar/modules.ts index 8017eb00..151628b8 100644 --- a/frontend/src/lib/components/sidebar/modules.ts +++ b/frontend/src/lib/components/sidebar/modules.ts @@ -63,7 +63,7 @@ export const sidebarData: SidebarData = { ], navMain: [ { - title: "Catalogos Generales", + title: "Catalogos Fijos", url: "/dashboard", icon: SquareTerminalIcon, items: [ @@ -72,8 +72,8 @@ export const sidebarData: SidebarData = { url: "/dashboard/reference_data/code_pedimento_regimens", }, { - title: "Reportes", - url: "#", + title: "Contenedores", + url: "/dashboard/reference_data/containers", }, ], isActive: true, diff --git a/frontend/src/lib/components/ui/switch/index.ts b/frontend/src/lib/components/ui/switch/index.ts new file mode 100644 index 00000000..f0e5fb79 --- /dev/null +++ b/frontend/src/lib/components/ui/switch/index.ts @@ -0,0 +1,7 @@ +import Root from "./switch.svelte"; + +export { + Root, + // + Root as Switch +}; diff --git a/frontend/src/lib/components/ui/switch/switch.svelte b/frontend/src/lib/components/ui/switch/switch.svelte new file mode 100644 index 00000000..5a512182 --- /dev/null +++ b/frontend/src/lib/components/ui/switch/switch.svelte @@ -0,0 +1,51 @@ + + + diff --git a/frontend/src/routes/dashboard/reference_data/containers/+page.server.ts b/frontend/src/routes/dashboard/reference_data/containers/+page.server.ts new file mode 100644 index 00000000..d63ee421 --- /dev/null +++ b/frontend/src/routes/dashboard/reference_data/containers/+page.server.ts @@ -0,0 +1,81 @@ +import type { PageServerLoad } from './$types'; + +export const load: PageServerLoad = async ({ cookies, fetch, url, parent }) => { + // Esperar a que el layout padre valide/refresque el token + await parent(); + + const token = cookies.get('access_token'); + + if (!token) { + return { + error: 'No authenticated', + items: [], + total: 0, + page: 1, + page_size: 50 + }; + } + + try { + // Obtener parámetros de paginación de la URL + const page = parseInt(url.searchParams.get('page') || '1'); + const pageSize = parseInt(url.searchParams.get('page_size') || '50'); + + // Configurar la URL de la API para SSR + let apiUrl = process.env.INTERNAL_API_URL; + if (!apiUrl) { + apiUrl = import.meta.env.VITE_API_URL; + // Reemplazar 'localhost' con 'backend' para llamadas desde el servidor (SSR) + apiUrl = apiUrl?.replace('localhost', 'backend').replace('127.0.0.1', 'backend'); + } + + // Normalizar la URL + const baseUrl = apiUrl?.endsWith('/') ? apiUrl : `${apiUrl}/`; + + const response = await fetch( + `${baseUrl}v1/containers?page=${page}&page_size=${pageSize}`, + { + headers: { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json' + } + } + ); + + if (!response.ok) { + const errorText = await response.text(); + console.error('📊 [Containers] API Error:', { + status: response.status, + statusText: response.statusText, + error: errorText + }); + + return { + error: `Error ${response.status}: ${response.statusText}`, + items: [], + total: 0, + page: page, + page_size: pageSize + }; + } + + const data = await response.json(); + + return { + items: data.items || [], + total: data.total || 0, + page: data.page || page, + page_size: data.page_size || pageSize, + error: null + }; + } catch (error) { + console.error('📊 [Containers] Load error:', error); + return { + error: 'Error loading data', + items: [], + total: 0, + page: 1, + page_size: 50 + }; + } +}; diff --git a/frontend/src/routes/dashboard/reference_data/containers/+page.svelte b/frontend/src/routes/dashboard/reference_data/containers/+page.svelte new file mode 100644 index 00000000..98af455c --- /dev/null +++ b/frontend/src/routes/dashboard/reference_data/containers/+page.svelte @@ -0,0 +1,196 @@ + + +
+ +
+
+

Contenedores

+

+ Gestiona los tipos de contenedores disponibles +

+
+ +
+ + + {#if error} + + + Error + {error} + + + {/if} + + + + +
+
+ Listado de Contenedores + + Mostrando {allItems.length} de {totalItems} registros + +
+ +
+
+ + + + +
+
+ + +