Fix: Resolver todos los errores de TypeScript

ERRORES RESUELTOS:

1. Colores de botones inválidos → colores válidos:
   - 'orange' → 'warning' (BackendVerificationButton)
   - 'purple' → 'primary' (FrontendVerificationButton)
   - 'red' → 'error' (CheckAuthentikAdminsButton)
   - 'blue' → 'info' (CheckGrupoPruebaButton)
   - 'green' → 'success' (CheckLvl0Button)
   - 'gray' → 'neutral' (CheckPublicAccessButton, UserMetadata)

2. Tipos no exportados en Nuxt UI v4:
   - Removidos imports: ButtonColor, ButtonVariant, ButtonSize
   - Reemplazados con tipos literales inline
   - Removido 'none' de variant (no válido en v4)

3. Subcategoria puede ser null:
   - FormularioMuestra: tipo cambiado a Exclude<Subcategoria, null>
   - sesion.vue: agregado ?? 'null' para key y guards para null

4. process.client no definido:
   - useCatacion.ts: process.client → import.meta.client (2 lugares)
   - Nuxt 4 usa import.meta.client en lugar de process.client

5. process.env en nuxt.config.ts:
   - Removido process.env.NUXT_PUBLIC_AUTHENTIK_URL
   - Nuxt runtimeConfig lee automáticamente de .env
   - Solo valor por defecto necesario

6. Propiedades no válidas en PWA manifest:
   - Removido: capture_links (no existe en ManifestOptions)
   - Removido: url_handlers (no existe en ManifestOptions)
   - Removido: handle_links (no existe en ManifestOptions)

7. Toast props no válidas:
   - Removido: timeout (no existe en Toast type)
   - BackendVerificationButton y FrontendVerificationButton

RESULTADO:
 npx nuxi typecheck pasa sin errores
 Solo warnings de @nuxt/content (no críticos)
This commit is contained in:
2025-10-19 03:14:14 -06:00
parent 6994114d91
commit 599cb24f8d
13 changed files with 23 additions and 34 deletions

View File

@@ -1,6 +1,6 @@
<template> <template>
<UButton <UButton
color="orange" color="warning"
size="lg" size="lg"
variant="outline" variant="outline"
:loading="loading" :loading="loading"
@@ -39,9 +39,8 @@ const handleClick = async () => {
title: 'Verificación Backend', title: 'Verificación Backend',
description: `Usuario: ${response.user.username} description: `Usuario: ${response.user.username}
Grupos (${groupCount}): ${groupList}`, Grupos (${groupCount}): ${groupList}`,
color: 'orange', color: 'warning',
icon: 'i-heroicons-server-stack', icon: 'i-heroicons-server-stack'
timeout: 5000
}) })
} else { } else {
toast.add({ toast.add({

View File

@@ -3,7 +3,7 @@
group-name="authentik Admins" group-name="authentik Admins"
label="Authentik Admins" label="Authentik Admins"
icon="i-heroicons-shield-check" icon="i-heroicons-shield-check"
color="red" color="error"
variant="soft" variant="soft"
:verify-backend="verifyBackend" :verify-backend="verifyBackend"
/> />

View File

@@ -3,7 +3,7 @@
group-name="grupo-prueba" group-name="grupo-prueba"
label="Grupo Prueba" label="Grupo Prueba"
icon="i-heroicons-beaker" icon="i-heroicons-beaker"
color="blue" color="info"
variant="soft" variant="soft"
:verify-backend="verifyBackend" :verify-backend="verifyBackend"
/> />

View File

@@ -3,7 +3,7 @@
group-name="lvl0" group-name="lvl0"
label="Level 0" label="Level 0"
icon="i-heroicons-key" icon="i-heroicons-key"
color="green" color="success"
variant="soft" variant="soft"
:verify-backend="verifyBackend" :verify-backend="verifyBackend"
/> />

View File

@@ -3,7 +3,7 @@
group-name="public-access" group-name="public-access"
label="Acceso Público" label="Acceso Público"
icon="i-heroicons-globe-alt" icon="i-heroicons-globe-alt"
color="gray" color="neutral"
variant="soft" variant="soft"
:verify-backend="verifyBackend" :verify-backend="verifyBackend"
/> />

View File

@@ -1,6 +1,6 @@
<template> <template>
<UButton <UButton
color="purple" color="primary"
size="lg" size="lg"
variant="outline" variant="outline"
@click="handleClick" @click="handleClick"
@@ -35,9 +35,8 @@ const handleClick = () => {
title: 'Verificación Frontend', title: 'Verificación Frontend',
description: `Usuario: ${user.value.username} description: `Usuario: ${user.value.username}
Grupos (${groupCount}): ${groupList}`, Grupos (${groupCount}): ${groupList}`,
color: 'purple', color: 'primary',
icon: 'i-heroicons-check-badge', icon: 'i-heroicons-check-badge'
timeout: 5000
}) })
} }
</script> </script>

View File

@@ -15,15 +15,13 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import type { ButtonColor, ButtonVariant, ButtonSize } from '#ui/types'
interface Props { interface Props {
groupName: string groupName: string
label?: string label?: string
icon?: string icon?: string
color?: ButtonColor color?: 'primary' | 'secondary' | 'success' | 'info' | 'warning' | 'error' | 'neutral'
variant?: ButtonVariant variant?: 'solid' | 'outline' | 'soft' | 'ghost' | 'link' | 'subtle'
size?: ButtonSize size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'
verifyBackend?: boolean verifyBackend?: boolean
} }

View File

@@ -58,7 +58,7 @@
> >
{{ group }} {{ group }}
</UBadge> </UBadge>
<UBadge v-if="user.groups.length === 0" color="gray" variant="soft"> <UBadge v-if="user.groups.length === 0" color="neutral" variant="soft">
Sin grupos asignados Sin grupos asignados
</UBadge> </UBadge>
</div> </div>

View File

@@ -878,13 +878,13 @@ const deberMostrarSeccion = (subcategorias: Subcategoria[]): boolean => {
} }
// Nueva función para filtrado restrictivo de sliders por tipo y categoría // Nueva función para filtrado restrictivo de sliders por tipo y categoría
const deberMostrarSlider = (tipo: 'descriptiva' | 'afectiva', categoria: Subcategoria): boolean => { const deberMostrarSlider = (tipo: 'descriptiva' | 'afectiva', categoria: Exclude<Subcategoria, null>): boolean => {
// Si no hay filtros activos, mostrar todo // Si no hay filtros activos, mostrar todo
if (!props.subcategoriasActivas || props.subcategoriasActivas.length === 0) return true if (!props.subcategoriasActivas || props.subcategoriasActivas.length === 0) return true
// Separar filtros en tipos y categorías // Separar filtros en tipos y categorías
const filtrosTipo = props.subcategoriasActivas.filter(s => s === 'descriptiva' || s === 'afectiva') const filtrosTipo = props.subcategoriasActivas.filter(s => s === 'descriptiva' || s === 'afectiva')
const filtrosCategoria = props.subcategoriasActivas.filter(s => const filtrosCategoria = props.subcategoriasActivas.filter((s): s is Exclude<Subcategoria, null> =>
s !== 'descriptiva' && s !== 'afectiva' && s !== null s !== 'descriptiva' && s !== 'afectiva' && s !== null
) )

View File

@@ -1,7 +1,7 @@
<template> <template>
<div class="selector-familia cata-fade-in"> <div class="selector-familia cata-fade-in">
<!-- Label principal --> <!-- Label principal -->
<label v-if="label" class="block text-sm font-medium mb-3 cata-text"> <label v-if="label" class="block text-sm font-medium mt-2 cata-text">
{{ label }} {{ label }}
<span v-if="required" class="text-error">*</span> <span v-if="required" class="text-error">*</span>
</label> </label>

View File

@@ -32,7 +32,7 @@ export const useCatacion = () => {
// Cargar subcategorías desde localStorage // Cargar subcategorías desde localStorage
const cargarSubcategoriasDesdeStorage = (): SubcategoriasPorTab => { const cargarSubcategoriasDesdeStorage = (): SubcategoriasPorTab => {
if (process.client) { if (import.meta.client) {
try { try {
const stored = localStorage.getItem(STORAGE_KEY_SUBCATEGORIAS) const stored = localStorage.getItem(STORAGE_KEY_SUBCATEGORIAS)
if (stored) { if (stored) {
@@ -63,7 +63,7 @@ export const useCatacion = () => {
*/ */
const actualizarSubcategorias = (subcategorias: Subcategoria[]) => { const actualizarSubcategorias = (subcategorias: Subcategoria[]) => {
subcategoriasPorTab.value[tabActiva.value] = subcategorias subcategoriasPorTab.value[tabActiva.value] = subcategorias
if (process.client) { if (import.meta.client) {
try { try {
localStorage.setItem(STORAGE_KEY_SUBCATEGORIAS, JSON.stringify(subcategoriasPorTab.value)) localStorage.setItem(STORAGE_KEY_SUBCATEGORIAS, JSON.stringify(subcategoriasPorTab.value))
} catch (err) { } catch (err) {

View File

@@ -132,12 +132,12 @@
<div class="flex flex-wrap gap-1 py-1.5"> <div class="flex flex-wrap gap-1 py-1.5">
<button <button
v-for="subcategoria in subcategoriasDisponibles" v-for="subcategoria in subcategoriasDisponibles"
:key="subcategoria.value" :key="subcategoria.value ?? 'null'"
:class="[ :class="[
'subcategoria-chip', 'subcategoria-chip',
{ 'subcategoria-chip-active': subcategoriasActivas.includes(subcategoria.value) }, { 'subcategoria-chip-active': subcategoria.value && subcategoriasActivas.includes(subcategoria.value) },
]" ]"
@click="toggleSubcategoria(subcategoria.value)" @click="subcategoria.value && toggleSubcategoria(subcategoria.value)"
> >
{{ subcategoria.label }} {{ subcategoria.label }}
</button> </button>

View File

@@ -16,7 +16,7 @@ export default defineNuxtConfig({
runtimeConfig: { runtimeConfig: {
public: { public: {
authentikUrl: process.env.NUXT_PUBLIC_AUTHENTIK_URL || 'https://authentik.nucleoriofrio.com' authentikUrl: 'https://authentik.nucleoriofrio.com'
} }
}, },
@@ -42,13 +42,6 @@ export default defineNuxtConfig({
launch_handler: { launch_handler: {
client_mode: 'navigate-existing' client_mode: 'navigate-existing'
}, },
// Capturar todos los enlaces que apunten a esta app
capture_links: 'existing-client-navigate',
// URL handling - nuevo estándar para manejar links a esta PWA
handle_links: 'preferred',
url_handlers: [
{ origin: 'https://riocata.nucleoriofrio.com' }
],
icons: [ icons: [
{ {
src: '/icon-72x72.png', src: '/icon-72x72.png',