From 206e81ef05d993615a08d25afb092d97b464d2fd Mon Sep 17 00:00:00 2001 From: acazares Date: Sun, 2 Nov 2025 14:20:30 -0600 Subject: [PATCH] feat(auth): synchronize access token from cookies to localStorage if not present refactor(dashboard): create dynamic columns for CodePedimentoRegimen with onSuccess callback feat(dashboard): implement create, edit, and delete dialogs for CodePedimentoRegimen feat(dialogs): add reusable dialog components for confirmation and details display style(alert-dialog): improve styling and structure for alert dialog components style(dialog): enhance styling and structure for dialog components --- .../code_pedimento_regimens/dto.py | 2 +- frontend/src/lib/api.ts | 34 ++- frontend/src/lib/auth.ts | 13 +- .../code_pedimento_regimens/columns.ts | 137 ++++++------ .../create-edit-dialog.svelte | 200 ++++++++++++++++++ .../data-table-actions.svelte | 44 +++- .../delete-dialog.svelte | 118 +++++++++++ .../details-dialog.svelte | 84 ++++++++ .../alert-dialog/alert-dialog-action.svelte | 18 ++ .../alert-dialog/alert-dialog-cancel.svelte | 18 ++ .../alert-dialog/alert-dialog-content.svelte | 27 +++ .../alert-dialog-description.svelte | 17 ++ .../alert-dialog/alert-dialog-footer.svelte | 20 ++ .../alert-dialog/alert-dialog-header.svelte | 20 ++ .../alert-dialog/alert-dialog-overlay.svelte | 20 ++ .../ui/alert-dialog/alert-dialog-title.svelte | 17 ++ .../alert-dialog/alert-dialog-trigger.svelte | 7 + .../lib/components/ui/alert-dialog/index.ts | 39 ++++ .../components/ui/dialog/dialog-close.svelte | 7 + .../ui/dialog/dialog-content.svelte | 43 ++++ .../ui/dialog/dialog-description.svelte | 17 ++ .../components/ui/dialog/dialog-footer.svelte | 20 ++ .../components/ui/dialog/dialog-header.svelte | 20 ++ .../ui/dialog/dialog-overlay.svelte | 20 ++ .../components/ui/dialog/dialog-title.svelte | 17 ++ .../ui/dialog/dialog-trigger.svelte | 7 + .../src/lib/components/ui/dialog/index.ts | 37 ++++ .../code_pedimento_regimens/+page.svelte | 23 +- 28 files changed, 969 insertions(+), 77 deletions(-) create mode 100644 frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/create-edit-dialog.svelte create mode 100644 frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/delete-dialog.svelte create mode 100644 frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/details-dialog.svelte create mode 100644 frontend/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte create mode 100644 frontend/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte create mode 100644 frontend/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte create mode 100644 frontend/src/lib/components/ui/alert-dialog/alert-dialog-description.svelte create mode 100644 frontend/src/lib/components/ui/alert-dialog/alert-dialog-footer.svelte create mode 100644 frontend/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte create mode 100644 frontend/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte create mode 100644 frontend/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte create mode 100644 frontend/src/lib/components/ui/alert-dialog/alert-dialog-trigger.svelte create mode 100644 frontend/src/lib/components/ui/alert-dialog/index.ts create mode 100644 frontend/src/lib/components/ui/dialog/dialog-close.svelte create mode 100644 frontend/src/lib/components/ui/dialog/dialog-content.svelte create mode 100644 frontend/src/lib/components/ui/dialog/dialog-description.svelte create mode 100644 frontend/src/lib/components/ui/dialog/dialog-footer.svelte create mode 100644 frontend/src/lib/components/ui/dialog/dialog-header.svelte create mode 100644 frontend/src/lib/components/ui/dialog/dialog-overlay.svelte create mode 100644 frontend/src/lib/components/ui/dialog/dialog-title.svelte create mode 100644 frontend/src/lib/components/ui/dialog/dialog-trigger.svelte create mode 100644 frontend/src/lib/components/ui/dialog/index.ts diff --git a/backend/api/v1/modules/public/reference_data/code_pedimento_regimens/dto.py b/backend/api/v1/modules/public/reference_data/code_pedimento_regimens/dto.py index 61d0e1fe..feba0810 100644 --- a/backend/api/v1/modules/public/reference_data/code_pedimento_regimens/dto.py +++ b/backend/api/v1/modules/public/reference_data/code_pedimento_regimens/dto.py @@ -3,7 +3,7 @@ from pydantic import ConfigDict from typing import Optional class CodePedimentoRegimenDTO(BaseModel): - id: int + id: Optional[int] = None pedimento_code: str = Field(..., min_length=1, max_length=3) regimen_code: Optional[str] = Field(None, min_length=1, max_length=3) type_code: Optional[str] = Field(None, min_length=1, max_length=1) diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index 8983053b..095a23c2 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -36,11 +36,31 @@ function onTokenRefreshed(token: string) { async function refreshToken(): Promise { if (!browser) return null; - const refreshTokenValue = localStorage.getItem('refresh_token'); + let refreshTokenValue = localStorage.getItem('refresh_token'); + + // Si no está en localStorage, intentar obtenerlo de las cookies if (!refreshTokenValue) { + const getCookie = (name: string): string | null => { + const value = `; ${document.cookie}`; + const parts = value.split(`; ${name}=`); + if (parts.length === 2) return parts.pop()?.split(';').shift() || null; + return null; + }; + + refreshTokenValue = getCookie('refresh_token'); + if (refreshTokenValue) { + console.log('📝 [API] Refresh token encontrado en cookies, sincronizando a localStorage'); + localStorage.setItem('refresh_token', refreshTokenValue); + } + } + + if (!refreshTokenValue) { + console.error('❌ [API] No hay refresh token disponible'); return null; } + console.log('🔄 [API] Intentando refrescar token...'); + try { const response = await fetch(`${API_BASE_URL}/v1/auth/refresh`, { method: 'POST', @@ -52,7 +72,7 @@ async function refreshToken(): Promise { }); if (!response.ok) { - console.error('❌ [API] Refresh token expirado o inválido'); + console.error('❌ [API] Refresh token expirado o inválido, status:', response.status); // Si el refresh token también está expirado, limpiar todo localStorage.removeItem('access_token'); localStorage.removeItem('refresh_token'); @@ -69,6 +89,7 @@ async function refreshToken(): Promise { } const data = await response.json(); + console.log('✅ [API] Token refrescado correctamente'); // Guardar los nuevos tokens if (data.access_token) { @@ -116,6 +137,7 @@ async function fetchApi( ): Promise> { // Si ya estamos refrescando el token, esperar if (isRefreshing && retryCount === 0) { + console.log('⏳ [API] Esperando refresh del token...'); return new Promise((resolve) => { subscribeTokenRefresh((newToken) => { resolve(fetchApi(endpoint, options, 1)); @@ -124,6 +146,10 @@ async function fetchApi( } const token = getToken(); + + if (!token && !endpoint.includes('/auth/login')) { + console.warn('⚠️ [API] No hay token disponible para', endpoint); + } const headers: Record = { 'Content-Type': 'application/json', @@ -143,6 +169,7 @@ async function fetchApi( // Si recibimos 401 o 403 y no es el endpoint de refresh, intentar refrescar el token if ((response.status === 401 || response.status === 403) && !endpoint.includes('/auth/refresh') && retryCount === 0) { + console.log('🔄 [API] Recibido 401/403, intentando refrescar token...'); isRefreshing = true; try { @@ -150,11 +177,13 @@ async function fetchApi( if (newToken) { // Token refrescado exitosamente + console.log('✅ [API] Token refrescado exitosamente'); onTokenRefreshed(newToken); isRefreshing = false; // Reintentar la petición original con el nuevo token return await fetchApi(endpoint, options, 1); } else { + console.error('❌ [API] No se pudo refrescar el token'); isRefreshing = false; // Retornar error 401 para que la capa superior lo maneje return { @@ -163,6 +192,7 @@ async function fetchApi( }; } } catch (refreshError) { + console.error('❌ [API] Error al refrescar:', refreshError); isRefreshing = false; return { error: 'Error al refrescar la sesión', diff --git a/frontend/src/lib/auth.ts b/frontend/src/lib/auth.ts index 76eca37b..17bca381 100644 --- a/frontend/src/lib/auth.ts +++ b/frontend/src/lib/auth.ts @@ -410,7 +410,18 @@ export const getToken = (): string | null => { // Si no, intentar de localStorage if (browser) { - return localStorage.getItem('access_token'); + let token = localStorage.getItem('access_token'); + + // Si no hay token en localStorage, intentar de las cookies + if (!token) { + token = getCookie('access_token'); + // Si lo encontramos en cookies, sincronizarlo a localStorage + if (token) { + localStorage.setItem('access_token', token); + } + } + + return token; } return null; diff --git a/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/columns.ts b/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/columns.ts index 7686563b..41ae7ce2 100644 --- a/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/columns.ts +++ b/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/columns.ts @@ -10,76 +10,81 @@ export type CodePedimentoRegimen = { type_code: string | null; }; -export const columns: ColumnDef[] = [ - { - accessorKey: "id", - header: "ID", - cell: ({ row }) => { - const idSnippet = createRawSnippet<[{ id: number }]>((getId) => { - const { id } = getId(); - return { - render: () => `
${id}
` - }; - }); - return renderSnippet(idSnippet, { id: row.original.id }); - } - }, - { - accessorKey: "pedimento_code", - header: "Código Pedimento", - cell: ({ row }) => { - const codeSnippet = createRawSnippet<[{ code: string }]>((getCode) => { - const { code } = getCode(); - return { - render: () => - `${code}` - }; - }); - return renderSnippet(codeSnippet, { code: row.original.pedimento_code }); - } - }, - { - accessorKey: "regimen_code", - header: "Código Régimen", - cell: ({ row }) => { - const regimenSnippet = createRawSnippet<[{ code: string | null }]>((getCode) => { - const { code } = getCode(); - if (code) { +export function createColumns(onSuccess?: () => void): ColumnDef[] { + return [ + { + accessorKey: "id", + header: "ID", + cell: ({ row }) => { + const idSnippet = createRawSnippet<[{ id: number }]>((getId) => { + const { id } = getId(); + return { + render: () => `
${id}
` + }; + }); + return renderSnippet(idSnippet, { id: row.original.id }); + } + }, + { + accessorKey: "pedimento_code", + header: "Código Pedimento", + cell: ({ row }) => { + const codeSnippet = createRawSnippet<[{ code: string }]>((getCode) => { + const { code } = getCode(); return { render: () => `${code}` }; - } - return { - render: () => `N/A` - }; - }); - return renderSnippet(regimenSnippet, { code: row.original.regimen_code }); - } - }, - { - accessorKey: "type_code", - header: "Tipo", - cell: ({ row }) => { - const typeSnippet = createRawSnippet<[{ type: string | null }]>((getType) => { - const { type } = getType(); - if (type) { + }); + return renderSnippet(codeSnippet, { code: row.original.pedimento_code }); + } + }, + { + accessorKey: "regimen_code", + header: "Código Régimen", + cell: ({ row }) => { + const regimenSnippet = createRawSnippet<[{ code: string | null }]>((getCode) => { + const { code } = getCode(); + if (code) { + return { + render: () => + `${code}` + }; + } return { - render: () => - `${type}` + render: () => `N/A` }; - } - return { - render: () => `N/A` - }; - }); - return renderSnippet(typeSnippet, { type: row.original.type_code }); + }); + return renderSnippet(regimenSnippet, { code: row.original.regimen_code }); + } + }, + { + accessorKey: "type_code", + header: "Tipo", + cell: ({ row }) => { + const typeSnippet = createRawSnippet<[{ type: string | null }]>((getType) => { + const { type } = getType(); + if (type) { + return { + render: () => + `${type}` + }; + } + return { + render: () => `N/A` + }; + }); + return renderSnippet(typeSnippet, { type: row.original.type_code }); + } + }, + { + id: "actions", + cell: ({ row }) => { + return renderComponent(DataTableActions, { item: row.original, onSuccess }); + } } - }, - { - id: "actions", - cell: ({ row }) => { - return renderComponent(DataTableActions, { item: row.original }); - } - } -]; + ]; +} + +// Mantener compatibilidad hacia atrás +export const columns = createColumns(); diff --git a/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/create-edit-dialog.svelte b/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/create-edit-dialog.svelte new file mode 100644 index 00000000..bde351be --- /dev/null +++ b/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/create-edit-dialog.svelte @@ -0,0 +1,200 @@ + + + + + + + {isEditing ? "Editar" : "Nuevo"} Código Pedimento - Régimen + + + {isEditing + ? "Modifica los datos de la relación código pedimento - régimen." + : "Completa los datos para crear una nueva relación."} + + + +
+ {#if error} +
+ {error} +
+ {/if} + +
+ + +
+ +
+ + +

Opcional

+
+ +
+ + +

Opcional

+
+ + + + + +
+
+
diff --git a/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/data-table-actions.svelte b/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/data-table-actions.svelte index 22b42007..9dc88ade 100644 --- a/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/data-table-actions.svelte +++ b/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/data-table-actions.svelte @@ -3,8 +3,37 @@ import { Button } from "$lib/components/ui/button/index.js"; import * as DropdownMenu from "$lib/components/ui/dropdown-menu/index.js"; import type { CodePedimentoRegimen } from "./columns.js"; + import CreateEditDialog from "./create-edit-dialog.svelte"; + import DetailsDialog from "./details-dialog.svelte"; + import DeleteDialog from "./delete-dialog.svelte"; - let { item }: { item: CodePedimentoRegimen } = $props(); + let { + item, + onSuccess + }: { + item: CodePedimentoRegimen; + onSuccess?: () => void; + } = $props(); + + let showDetailsDialog = $state(false); + let showEditDialog = $state(false); + let showDeleteDialog = $state(false); + + function handleCopyId() { + navigator.clipboard.writeText(item.id.toString()); + } + + function handleViewDetails() { + showDetailsDialog = true; + } + + function handleEdit() { + showEditDialog = true; + } + + function handleDelete() { + showDeleteDialog = true; + } @@ -19,14 +48,19 @@ Acciones - navigator.clipboard.writeText(item.id.toString())}> + Copiar ID - Ver detalles - Editar + Ver detalles + Editar - Eliminar + Eliminar + + + + + diff --git a/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/delete-dialog.svelte b/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/delete-dialog.svelte new file mode 100644 index 00000000..73d891e6 --- /dev/null +++ b/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/delete-dialog.svelte @@ -0,0 +1,118 @@ + + + + + + ¿Estás seguro? + +

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

+ {#if item} +
+
+ ID: + {item.id} +
+
+ Código Pedimento: + {item.pedimento_code} +
+ {#if item.regimen_code} +
+ Código Régimen: + {item.regimen_code} +
+ {/if} +
+ {/if} + {#if error} +
+ {error} +
+ {/if} +
+
+ + Cancelar + + {#if loading} + + + + + {/if} + Eliminar + + +
+
diff --git a/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/details-dialog.svelte b/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/details-dialog.svelte new file mode 100644 index 00000000..0c137903 --- /dev/null +++ b/frontend/src/lib/components/dashboard/reference_data/code_pedimento_regimens/details-dialog.svelte @@ -0,0 +1,84 @@ + + + + + + Detalles del Registro + + Información completa de la relación código pedimento - régimen + + + + {#if item} +
+
+
+ ID + {item.id} +
+ +
+ +
+
+ Código Pedimento + + {item.pedimento_code} + +
+ +
+ +
+
+ Código Régimen + {#if item.regimen_code} + + {item.regimen_code} + + {:else} + No especificado + {/if} +
+ +
+ +
+
+ Tipo + {#if item.type_code} + + {item.type_code} + + {:else} + No especificado + {/if} +
+
+
+ {/if} + + + + +
+
diff --git a/frontend/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte b/frontend/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte new file mode 100644 index 00000000..a0056912 --- /dev/null +++ b/frontend/src/lib/components/ui/alert-dialog/alert-dialog-action.svelte @@ -0,0 +1,18 @@ + + + diff --git a/frontend/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte b/frontend/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte new file mode 100644 index 00000000..a7b0cf79 --- /dev/null +++ b/frontend/src/lib/components/ui/alert-dialog/alert-dialog-cancel.svelte @@ -0,0 +1,18 @@ + + + diff --git a/frontend/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte b/frontend/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte new file mode 100644 index 00000000..6c3c6046 --- /dev/null +++ b/frontend/src/lib/components/ui/alert-dialog/alert-dialog-content.svelte @@ -0,0 +1,27 @@ + + + + + + diff --git a/frontend/src/lib/components/ui/alert-dialog/alert-dialog-description.svelte b/frontend/src/lib/components/ui/alert-dialog/alert-dialog-description.svelte new file mode 100644 index 00000000..2ec67dc2 --- /dev/null +++ b/frontend/src/lib/components/ui/alert-dialog/alert-dialog-description.svelte @@ -0,0 +1,17 @@ + + + diff --git a/frontend/src/lib/components/ui/alert-dialog/alert-dialog-footer.svelte b/frontend/src/lib/components/ui/alert-dialog/alert-dialog-footer.svelte new file mode 100644 index 00000000..f78b97ab --- /dev/null +++ b/frontend/src/lib/components/ui/alert-dialog/alert-dialog-footer.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/frontend/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte b/frontend/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte new file mode 100644 index 00000000..c8fa7625 --- /dev/null +++ b/frontend/src/lib/components/ui/alert-dialog/alert-dialog-header.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/frontend/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte b/frontend/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte new file mode 100644 index 00000000..a64ee768 --- /dev/null +++ b/frontend/src/lib/components/ui/alert-dialog/alert-dialog-overlay.svelte @@ -0,0 +1,20 @@ + + + diff --git a/frontend/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte b/frontend/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte new file mode 100644 index 00000000..7ef2b5fb --- /dev/null +++ b/frontend/src/lib/components/ui/alert-dialog/alert-dialog-title.svelte @@ -0,0 +1,17 @@ + + + diff --git a/frontend/src/lib/components/ui/alert-dialog/alert-dialog-trigger.svelte b/frontend/src/lib/components/ui/alert-dialog/alert-dialog-trigger.svelte new file mode 100644 index 00000000..b22d1d50 --- /dev/null +++ b/frontend/src/lib/components/ui/alert-dialog/alert-dialog-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/frontend/src/lib/components/ui/alert-dialog/index.ts b/frontend/src/lib/components/ui/alert-dialog/index.ts new file mode 100644 index 00000000..cc281c58 --- /dev/null +++ b/frontend/src/lib/components/ui/alert-dialog/index.ts @@ -0,0 +1,39 @@ +import { AlertDialog as AlertDialogPrimitive } from "bits-ui"; +import Trigger from "./alert-dialog-trigger.svelte"; +import Title from "./alert-dialog-title.svelte"; +import Action from "./alert-dialog-action.svelte"; +import Cancel from "./alert-dialog-cancel.svelte"; +import Footer from "./alert-dialog-footer.svelte"; +import Header from "./alert-dialog-header.svelte"; +import Overlay from "./alert-dialog-overlay.svelte"; +import Content from "./alert-dialog-content.svelte"; +import Description from "./alert-dialog-description.svelte"; + +const Root = AlertDialogPrimitive.Root; +const Portal = AlertDialogPrimitive.Portal; + +export { + Root, + Title, + Action, + Cancel, + Portal, + Footer, + Header, + Trigger, + Overlay, + Content, + Description, + // + Root as AlertDialog, + Title as AlertDialogTitle, + Action as AlertDialogAction, + Cancel as AlertDialogCancel, + Portal as AlertDialogPortal, + Footer as AlertDialogFooter, + Header as AlertDialogHeader, + Trigger as AlertDialogTrigger, + Overlay as AlertDialogOverlay, + Content as AlertDialogContent, + Description as AlertDialogDescription, +}; diff --git a/frontend/src/lib/components/ui/dialog/dialog-close.svelte b/frontend/src/lib/components/ui/dialog/dialog-close.svelte new file mode 100644 index 00000000..840b2f68 --- /dev/null +++ b/frontend/src/lib/components/ui/dialog/dialog-close.svelte @@ -0,0 +1,7 @@ + + + diff --git a/frontend/src/lib/components/ui/dialog/dialog-content.svelte b/frontend/src/lib/components/ui/dialog/dialog-content.svelte new file mode 100644 index 00000000..a647d566 --- /dev/null +++ b/frontend/src/lib/components/ui/dialog/dialog-content.svelte @@ -0,0 +1,43 @@ + + + + + + {@render children?.()} + {#if showCloseButton} + + + Close + + {/if} + + diff --git a/frontend/src/lib/components/ui/dialog/dialog-description.svelte b/frontend/src/lib/components/ui/dialog/dialog-description.svelte new file mode 100644 index 00000000..38450239 --- /dev/null +++ b/frontend/src/lib/components/ui/dialog/dialog-description.svelte @@ -0,0 +1,17 @@ + + + diff --git a/frontend/src/lib/components/ui/dialog/dialog-footer.svelte b/frontend/src/lib/components/ui/dialog/dialog-footer.svelte new file mode 100644 index 00000000..e7ff4468 --- /dev/null +++ b/frontend/src/lib/components/ui/dialog/dialog-footer.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/frontend/src/lib/components/ui/dialog/dialog-header.svelte b/frontend/src/lib/components/ui/dialog/dialog-header.svelte new file mode 100644 index 00000000..fc90cd9b --- /dev/null +++ b/frontend/src/lib/components/ui/dialog/dialog-header.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/frontend/src/lib/components/ui/dialog/dialog-overlay.svelte b/frontend/src/lib/components/ui/dialog/dialog-overlay.svelte new file mode 100644 index 00000000..f81ad833 --- /dev/null +++ b/frontend/src/lib/components/ui/dialog/dialog-overlay.svelte @@ -0,0 +1,20 @@ + + + diff --git a/frontend/src/lib/components/ui/dialog/dialog-title.svelte b/frontend/src/lib/components/ui/dialog/dialog-title.svelte new file mode 100644 index 00000000..067e55ec --- /dev/null +++ b/frontend/src/lib/components/ui/dialog/dialog-title.svelte @@ -0,0 +1,17 @@ + + + diff --git a/frontend/src/lib/components/ui/dialog/dialog-trigger.svelte b/frontend/src/lib/components/ui/dialog/dialog-trigger.svelte new file mode 100644 index 00000000..9d1e8011 --- /dev/null +++ b/frontend/src/lib/components/ui/dialog/dialog-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/frontend/src/lib/components/ui/dialog/index.ts b/frontend/src/lib/components/ui/dialog/index.ts new file mode 100644 index 00000000..dce1d9dc --- /dev/null +++ b/frontend/src/lib/components/ui/dialog/index.ts @@ -0,0 +1,37 @@ +import { Dialog as DialogPrimitive } from "bits-ui"; + +import Title from "./dialog-title.svelte"; +import Footer from "./dialog-footer.svelte"; +import Header from "./dialog-header.svelte"; +import Overlay from "./dialog-overlay.svelte"; +import Content from "./dialog-content.svelte"; +import Description from "./dialog-description.svelte"; +import Trigger from "./dialog-trigger.svelte"; +import Close from "./dialog-close.svelte"; + +const Root = DialogPrimitive.Root; +const Portal = DialogPrimitive.Portal; + +export { + Root, + Title, + Portal, + Footer, + Header, + Trigger, + Overlay, + Content, + Description, + Close, + // + Root as Dialog, + Title as DialogTitle, + Portal as DialogPortal, + Footer as DialogFooter, + Header as DialogHeader, + Trigger as DialogTrigger, + Overlay as DialogOverlay, + Content as DialogContent, + Description as DialogDescription, + Close as DialogClose, +}; diff --git a/frontend/src/routes/dashboard/reference_data/code_pedimento_regimens/+page.svelte b/frontend/src/routes/dashboard/reference_data/code_pedimento_regimens/+page.svelte index cd344faf..a72beb5f 100644 --- a/frontend/src/routes/dashboard/reference_data/code_pedimento_regimens/+page.svelte +++ b/frontend/src/routes/dashboard/reference_data/code_pedimento_regimens/+page.svelte @@ -2,7 +2,8 @@ import { onMount } from 'svelte'; import { codePedimentoRegimensApi, type CodePedimentoRegimen } from '$lib/api/dashboard/refrence_data/code_pedimento_regimens'; import DataTable from '$lib/components/dashboard/reference_data/code_pedimento_regimens/data-table.svelte'; - import { columns } from '$lib/components/dashboard/reference_data/code_pedimento_regimens/columns.js'; + import { createColumns } from '$lib/components/dashboard/reference_data/code_pedimento_regimens/columns.js'; + import CreateEditDialog from '$lib/components/dashboard/reference_data/code_pedimento_regimens/create-edit-dialog.svelte'; import * as Card from '$lib/components/ui/card'; import { Button } from '$lib/components/ui/button'; import type { PageData } from './$types'; @@ -10,6 +11,9 @@ // Los datos iniciales vienen del servidor let { data }: { data: PageData } = $props(); + + // Estado para el diálogo de crear + let showCreateDialog = $state(false); // Sincronizar token de cookies a localStorage al montar el componente onMount(() => { @@ -92,6 +96,18 @@ // Reset y recargar desde el principio window.location.reload(); } + + function handleCreateClick() { + showCreateDialog = true; + } + + function handleSuccess() { + // Recargar datos después de crear/editar/eliminar + reloadData(); + } + + // Crear columnas con el callback onSuccess + const columns = createColumns(handleSuccess);
@@ -103,7 +119,7 @@ Gestiona las relaciones entre códigos de pedimento y regímenes

-