Fix: Usar toRaw() para convertir Proxies de Vue antes de guardar en IndexedDB
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m4s

- Usar toRaw() + JSON.parse/stringify para deep clone sin Proxies
- No modificar modificadoEn en objeto reactivo, solo en copia
- Evitar re-renderizados innecesarios manteniendo referencias estables
This commit is contained in:
2025-10-18 03:48:43 -06:00
parent 0656f15366
commit ac98bfbc51
2 changed files with 63 additions and 10 deletions

View File

@@ -546,3 +546,52 @@
.dark .cata-toast-neutral .cata-toast-icon { .dark .cata-toast-neutral .cata-toast-icon {
color: rgb(156, 163, 175); color: rgb(156, 163, 175);
} }
/* -------------------------------------------------------------------------- */
/* SCROLLBARS PERSONALIZADAS */
/* -------------------------------------------------------------------------- */
/* Scrollbar compacta para navegadores modernos (Firefox) */
* {
scrollbar-width: thin;
scrollbar-color: color-mix(in srgb, var(--cata-primary) 40%, transparent) transparent;
}
.dark * {
scrollbar-color: color-mix(in srgb, var(--cata-primary) 60%, transparent) transparent;
}
/* Scrollbar compacta para navegadores WebKit (Chrome, Safari, Edge) */
*::-webkit-scrollbar {
width: 8px;
height: 8px;
}
*::-webkit-scrollbar-track {
background-color: transparent;
}
*::-webkit-scrollbar-thumb {
background-color: color-mix(in srgb, var(--cata-primary) 40%, transparent);
border-radius: 4px;
border: 2px solid transparent;
background-clip: padding-box;
}
*::-webkit-scrollbar-thumb:hover {
background-color: color-mix(in srgb, var(--cata-primary) 60%, transparent);
}
.dark *::-webkit-scrollbar-thumb {
background-color: color-mix(in srgb, var(--cata-primary) 60%, transparent);
}
.dark *::-webkit-scrollbar-thumb:hover {
background-color: color-mix(in srgb, var(--cata-primary) 80%, transparent);
box-shadow: 0 0 6px color-mix(in srgb, var(--cata-primary) 40%, transparent);
}
/* Scrollbar para esquinas cuando hay scroll horizontal y vertical */
*::-webkit-scrollbar-corner {
background-color: transparent;
}

View File

@@ -49,9 +49,11 @@ function openDatabase(): Promise<IDBDatabase> {
*/ */
async function saveSession(sesion: SesionCatacion): Promise<void> { async function saveSession(sesion: SesionCatacion): Promise<void> {
try { try {
// Clonar la sesión para eliminar los proxies reactivos de Vue // Usar toRaw para convertir proxies reactivos de Vue a objetos planos
// antes de guardar en IndexedDB // antes de guardar en IndexedDB, pero necesitamos clonar profundamente
const sesionClonada = JSON.parse(JSON.stringify(sesion)) as SesionCatacion // para evitar referencias a objetos reactivos
const { toRaw } = await import('vue')
const sesionPlana = JSON.parse(JSON.stringify(toRaw(sesion))) as SesionCatacion
const db = await openDatabase() const db = await openDatabase()
const transaction = db.transaction([STORE_NAME], 'readwrite') const transaction = db.transaction([STORE_NAME], 'readwrite')
@@ -66,7 +68,7 @@ async function saveSession(sesion: SesionCatacion): Promise<void> {
// Guardar la nueva sesión // Guardar la nueva sesión
await new Promise<void>((resolve, reject) => { await new Promise<void>((resolve, reject) => {
const addRequest = objectStore.add(sesionClonada) const addRequest = objectStore.add(sesionPlana)
addRequest.onsuccess = () => resolve() addRequest.onsuccess = () => resolve()
addRequest.onerror = () => reject(new Error('Error al guardar la sesión')) addRequest.onerror = () => reject(new Error('Error al guardar la sesión'))
}) })
@@ -216,19 +218,21 @@ async function deleteSession(): Promise<void> {
*/ */
async function updateSession(sesion: SesionCatacion): Promise<void> { async function updateSession(sesion: SesionCatacion): Promise<void> {
try { try {
// Actualizar timestamp de modificación // Usar toRaw para convertir proxies reactivos de Vue a objetos planos
sesion.modificadoEn = Date.now() // antes de guardar en IndexedDB, pero necesitamos clonar profundamente
// para evitar referencias a objetos reactivos
const { toRaw } = await import('vue')
const sesionPlana = JSON.parse(JSON.stringify(toRaw(sesion))) as SesionCatacion
// Clonar la sesión para eliminar los proxies reactivos de Vue // Actualizar timestamp solo en la copia, no en el objeto reactivo
// antes de guardar en IndexedDB sesionPlana.modificadoEn = Date.now()
const sesionClonada = JSON.parse(JSON.stringify(sesion)) as SesionCatacion
const db = await openDatabase() const db = await openDatabase()
const transaction = db.transaction([STORE_NAME], 'readwrite') const transaction = db.transaction([STORE_NAME], 'readwrite')
const objectStore = transaction.objectStore(STORE_NAME) const objectStore = transaction.objectStore(STORE_NAME)
await new Promise<void>((resolve, reject) => { await new Promise<void>((resolve, reject) => {
const putRequest = objectStore.put(sesionClonada) const putRequest = objectStore.put(sesionPlana)
putRequest.onsuccess = () => resolve() putRequest.onsuccess = () => resolve()
putRequest.onerror = () => reject(new Error('Error al actualizar la sesión')) putRequest.onerror = () => reject(new Error('Error al actualizar la sesión'))
}) })