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
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:
@@ -8,14 +8,17 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const { isAuthenticated } = useAuthentik()
|
const { isAuthenticated } = useAuthentik()
|
||||||
const { inicializar } = useColorCustomization()
|
const { inicializar, getCurrentColors } = useColorCustomization()
|
||||||
|
|
||||||
// Inicializar personalización de colores
|
// Inicializar personalización de colores
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
inicializar()
|
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({
|
useHead({
|
||||||
link: [
|
link: [
|
||||||
{ rel: 'manifest', href: '/manifest.webmanifest' },
|
{ rel: 'manifest', href: '/manifest.webmanifest' },
|
||||||
@@ -23,7 +26,7 @@ useHead({
|
|||||||
{ rel: 'apple-touch-icon', href: '/apple-touch-icon.png' }
|
{ rel: 'apple-touch-icon', href: '/apple-touch-icon.png' }
|
||||||
],
|
],
|
||||||
meta: [
|
meta: [
|
||||||
{ name: 'theme-color', content: '#00DC82' },
|
{ name: 'theme-color', content: themeColor },
|
||||||
{ name: 'mobile-web-app-capable', content: 'yes' },
|
{ name: 'mobile-web-app-capable', content: 'yes' },
|
||||||
{ name: 'apple-mobile-web-app-capable', content: 'yes' },
|
{ name: 'apple-mobile-web-app-capable', content: 'yes' },
|
||||||
{ name: 'apple-mobile-web-app-status-bar-style', content: 'default' }
|
{ name: 'apple-mobile-web-app-status-bar-style', content: 'default' }
|
||||||
|
|||||||
@@ -40,33 +40,22 @@ export const useCatacion = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const sesionClonada = JSON.parse(JSON.stringify(sesionActiva.value)) as SesionCatacion
|
const muestra = sesionActiva.value.muestras.find(m => m.muestraId === muestraId)
|
||||||
const indexMuestra = sesionClonada.muestras.findIndex(m => m.muestraId === muestraId)
|
|
||||||
|
|
||||||
if (indexMuestra === -1) {
|
if (!muestra) {
|
||||||
throw new Error(`Muestra con ID ${muestraId} no encontrada`)
|
throw new Error(`Muestra con ID ${muestraId} no encontrada`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualizar muestra
|
// Actualizar muestra directamente (mutación)
|
||||||
const muestraActual = sesionClonada.muestras[indexMuestra]
|
Object.assign(muestra, muestraActualizada)
|
||||||
if (!muestraActual) {
|
|
||||||
throw new Error(`Muestra con ID ${muestraId} no encontrada`)
|
|
||||||
}
|
|
||||||
|
|
||||||
sesionClonada.muestras[indexMuestra] = {
|
|
||||||
...muestraActual,
|
|
||||||
...muestraActualizada,
|
|
||||||
} as Muestra
|
|
||||||
|
|
||||||
// Recalcular puntaje final si hay cambios en intensidades
|
// Recalcular puntaje final si hay cambios en intensidades
|
||||||
if (muestraActualizada.intensidades) {
|
if (muestraActualizada.intensidades) {
|
||||||
const muestraFinal = sesionClonada.muestras[indexMuestra]
|
muestra.puntajeFinal = calcularPuntajeFinal(muestra)
|
||||||
if (muestraFinal) {
|
|
||||||
sesionClonada.muestras[indexMuestra]!.puntajeFinal = calcularPuntajeFinal(muestraFinal)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await actualizar(sesionClonada)
|
// Guardar en IndexedDB
|
||||||
|
await actualizar(sesionActiva.value)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error al actualizar muestra:', err)
|
console.error('Error al actualizar muestra:', err)
|
||||||
throw err
|
throw err
|
||||||
@@ -87,32 +76,20 @@ export const useCatacion = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const sesionClonada = JSON.parse(JSON.stringify(sesionActiva.value)) as SesionCatacion
|
const muestra = sesionActiva.value.muestras.find(m => m.muestraId === muestraId)
|
||||||
const indexMuestra = sesionClonada.muestras.findIndex(m => m.muestraId === muestraId)
|
|
||||||
|
|
||||||
if (indexMuestra === -1) {
|
if (!muestra) {
|
||||||
throw new Error(`Muestra con ID ${muestraId} no encontrada`)
|
throw new Error(`Muestra con ID ${muestraId} no encontrada`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualizar valor de intensidad
|
// Actualizar valor de intensidad directamente (mutación)
|
||||||
const muestraActual = sesionClonada.muestras[indexMuestra]
|
muestra.intensidades[parametro][tipo] = valor
|
||||||
if (!muestraActual) {
|
|
||||||
throw new Error(`Muestra con ID ${muestraId} no encontrada`)
|
|
||||||
}
|
|
||||||
|
|
||||||
const intensidadActual = muestraActual.intensidades[parametro]
|
|
||||||
sesionClonada.muestras[indexMuestra]!.intensidades[parametro] = {
|
|
||||||
...intensidadActual,
|
|
||||||
[tipo]: valor,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recalcular puntaje final
|
// Recalcular puntaje final
|
||||||
const muestraFinal = sesionClonada.muestras[indexMuestra]
|
muestra.puntajeFinal = calcularPuntajeFinal(muestra)
|
||||||
if (muestraFinal) {
|
|
||||||
sesionClonada.muestras[indexMuestra]!.puntajeFinal = calcularPuntajeFinal(muestraFinal)
|
|
||||||
}
|
|
||||||
|
|
||||||
await actualizar(sesionClonada)
|
// Guardar en IndexedDB (pasa la sesión actual, no un clon)
|
||||||
|
await actualizar(sesionActiva.value)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error al actualizar intensidad:', err)
|
console.error('Error al actualizar intensidad:', err)
|
||||||
throw err
|
throw err
|
||||||
@@ -208,8 +185,7 @@ export const useCatacion = () => {
|
|||||||
const obtenerMuestra = (muestraId: number): Muestra | null => {
|
const obtenerMuestra = (muestraId: number): Muestra | null => {
|
||||||
if (!sesionActiva.value) return null
|
if (!sesionActiva.value) return null
|
||||||
const muestra = sesionActiva.value.muestras.find(m => m.muestraId === muestraId)
|
const muestra = sesionActiva.value.muestras.find(m => m.muestraId === muestraId)
|
||||||
if (!muestra) return null
|
return muestra || null
|
||||||
return JSON.parse(JSON.stringify(muestra)) as Muestra
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -295,7 +271,7 @@ export const useCatacion = () => {
|
|||||||
const estadisticasSesion = computed(() => {
|
const estadisticasSesion = computed(() => {
|
||||||
if (!sesionActiva.value) return null
|
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 totalMuestras = muestras.length
|
||||||
const muestrasCompletas = muestras.filter(esMuestraCompleta).length
|
const muestrasCompletas = muestras.filter(esMuestraCompleta).length
|
||||||
const promedioCompletitud = muestras.reduce((acc, m) => acc + porcentajeCompletitud(m), 0) / totalMuestras
|
const promedioCompletitud = muestras.reduce((acc, m) => acc + porcentajeCompletitud(m), 0) / totalMuestras
|
||||||
|
|||||||
@@ -299,7 +299,8 @@ export const useIndexedDB = () => {
|
|||||||
cargando.value = true
|
cargando.value = true
|
||||||
error.value = null
|
error.value = null
|
||||||
await updateSession(sesion)
|
await updateSession(sesion)
|
||||||
sesionActiva.value = sesion
|
// NO reemplazar el objeto completo para mantener las referencias de Vue
|
||||||
|
// sesionActiva.value = sesion
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
error.value = err as Error
|
error.value = err as Error
|
||||||
console.error('Error al actualizar sesión:', err)
|
console.error('Error al actualizar sesión:', err)
|
||||||
@@ -339,7 +340,7 @@ export const useIndexedDB = () => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
// Estado
|
// Estado
|
||||||
sesionActiva: readonly(sesionActiva),
|
sesionActiva, // No readonly para permitir mutaciones directas
|
||||||
cargando: readonly(cargando),
|
cargando: readonly(cargando),
|
||||||
error: readonly(error),
|
error: readonly(error),
|
||||||
tieneSecion,
|
tieneSecion,
|
||||||
|
|||||||
Reference in New Issue
Block a user