Fix: Eliminar re-renderizados usando mutaciones directas en lugar de clonaciones
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m4s

- Modificar useIndexedDB para no reemplazar sesionActiva en actualizar()
- Modificar useCatacion para mutar directamente las propiedades
- Eliminar todas las clonaciones con JSON.parse/stringify
- Mantener referencias de objetos estables para Vue reactivity
This commit is contained in:
2025-10-18 03:36:13 -06:00
parent 9daafc2a3e
commit f17ff66613
3 changed files with 25 additions and 45 deletions

View File

@@ -8,14 +8,17 @@
<script setup lang="ts">
const { isAuthenticated } = useAuthentik()
const { inicializar } = useColorCustomization()
const { inicializar, getCurrentColors } = useColorCustomization()
// Inicializar personalización de colores
onMounted(() => {
inicializar()
})
// Configurar meta tags para PWA
// Color de tema reactivo basado en el background del tema actual
const themeColor = computed(() => getCurrentColors.value.background)
// Configurar meta tags para PWA con theme-color reactivo
useHead({
link: [
{ rel: 'manifest', href: '/manifest.webmanifest' },
@@ -23,7 +26,7 @@ useHead({
{ rel: 'apple-touch-icon', href: '/apple-touch-icon.png' }
],
meta: [
{ name: 'theme-color', content: '#00DC82' },
{ name: 'theme-color', content: themeColor },
{ name: 'mobile-web-app-capable', content: 'yes' },
{ name: 'apple-mobile-web-app-capable', content: 'yes' },
{ name: 'apple-mobile-web-app-status-bar-style', content: 'default' }

View File

@@ -40,33 +40,22 @@ export const useCatacion = () => {
}
try {
const sesionClonada = JSON.parse(JSON.stringify(sesionActiva.value)) as SesionCatacion
const indexMuestra = sesionClonada.muestras.findIndex(m => m.muestraId === muestraId)
const muestra = sesionActiva.value.muestras.find(m => m.muestraId === muestraId)
if (indexMuestra === -1) {
if (!muestra) {
throw new Error(`Muestra con ID ${muestraId} no encontrada`)
}
// Actualizar muestra
const muestraActual = sesionClonada.muestras[indexMuestra]
if (!muestraActual) {
throw new Error(`Muestra con ID ${muestraId} no encontrada`)
}
sesionClonada.muestras[indexMuestra] = {
...muestraActual,
...muestraActualizada,
} as Muestra
// Actualizar muestra directamente (mutación)
Object.assign(muestra, muestraActualizada)
// Recalcular puntaje final si hay cambios en intensidades
if (muestraActualizada.intensidades) {
const muestraFinal = sesionClonada.muestras[indexMuestra]
if (muestraFinal) {
sesionClonada.muestras[indexMuestra]!.puntajeFinal = calcularPuntajeFinal(muestraFinal)
}
muestra.puntajeFinal = calcularPuntajeFinal(muestra)
}
await actualizar(sesionClonada)
// Guardar en IndexedDB
await actualizar(sesionActiva.value)
} catch (err) {
console.error('Error al actualizar muestra:', err)
throw err
@@ -87,32 +76,20 @@ export const useCatacion = () => {
}
try {
const sesionClonada = JSON.parse(JSON.stringify(sesionActiva.value)) as SesionCatacion
const indexMuestra = sesionClonada.muestras.findIndex(m => m.muestraId === muestraId)
const muestra = sesionActiva.value.muestras.find(m => m.muestraId === muestraId)
if (indexMuestra === -1) {
if (!muestra) {
throw new Error(`Muestra con ID ${muestraId} no encontrada`)
}
// Actualizar valor de intensidad
const muestraActual = sesionClonada.muestras[indexMuestra]
if (!muestraActual) {
throw new Error(`Muestra con ID ${muestraId} no encontrada`)
}
const intensidadActual = muestraActual.intensidades[parametro]
sesionClonada.muestras[indexMuestra]!.intensidades[parametro] = {
...intensidadActual,
[tipo]: valor,
}
// Actualizar valor de intensidad directamente (mutación)
muestra.intensidades[parametro][tipo] = valor
// Recalcular puntaje final
const muestraFinal = sesionClonada.muestras[indexMuestra]
if (muestraFinal) {
sesionClonada.muestras[indexMuestra]!.puntajeFinal = calcularPuntajeFinal(muestraFinal)
}
muestra.puntajeFinal = calcularPuntajeFinal(muestra)
await actualizar(sesionClonada)
// Guardar en IndexedDB (pasa la sesión actual, no un clon)
await actualizar(sesionActiva.value)
} catch (err) {
console.error('Error al actualizar intensidad:', err)
throw err
@@ -208,8 +185,7 @@ export const useCatacion = () => {
const obtenerMuestra = (muestraId: number): Muestra | null => {
if (!sesionActiva.value) return null
const muestra = sesionActiva.value.muestras.find(m => m.muestraId === muestraId)
if (!muestra) return null
return JSON.parse(JSON.stringify(muestra)) as Muestra
return muestra || null
}
/**
@@ -295,7 +271,7 @@ export const useCatacion = () => {
const estadisticasSesion = computed(() => {
if (!sesionActiva.value) return null
const muestras = JSON.parse(JSON.stringify(sesionActiva.value.muestras)) as Muestra[]
const muestras = sesionActiva.value.muestras
const totalMuestras = muestras.length
const muestrasCompletas = muestras.filter(esMuestraCompleta).length
const promedioCompletitud = muestras.reduce((acc, m) => acc + porcentajeCompletitud(m), 0) / totalMuestras

View File

@@ -299,7 +299,8 @@ export const useIndexedDB = () => {
cargando.value = true
error.value = null
await updateSession(sesion)
sesionActiva.value = sesion
// NO reemplazar el objeto completo para mantener las referencias de Vue
// sesionActiva.value = sesion
} catch (err) {
error.value = err as Error
console.error('Error al actualizar sesión:', err)
@@ -339,7 +340,7 @@ export const useIndexedDB = () => {
return {
// Estado
sesionActiva: readonly(sesionActiva),
sesionActiva, // No readonly para permitir mutaciones directas
cargando: readonly(cargando),
error: readonly(error),
tieneSecion,