logout e integracion con authentik completa
All checks were successful
deploy-analiticaNucleo / deploy (push) Successful in 36s
All checks were successful
deploy-analiticaNucleo / deploy (push) Successful in 36s
This commit is contained in:
@@ -2,7 +2,14 @@
|
|||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"chrome-devtools": {
|
"chrome-devtools": {
|
||||||
"command": "npx",
|
"command": "npx",
|
||||||
"args": ["-y", "chrome-devtools-mcp@latest"]
|
"args": [
|
||||||
|
"-y",
|
||||||
|
"chrome-devtools-mcp@latest"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"context7": {
|
||||||
|
"type": "http",
|
||||||
|
"url": "https://mcp.context7.com/mcp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,21 +1,71 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const { user, loading, fetchUser, logout } = useAuth()
|
const { user, loading, fetchUser, logout } = useAuth()
|
||||||
|
|
||||||
|
// Estado para el dropdown
|
||||||
|
const isOpen = ref(false)
|
||||||
|
|
||||||
// Cargar usuario al montar
|
// Cargar usuario al montar
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
fetchUser()
|
fetchUser()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Computed para el avatar del usuario con gradiente dinámico
|
||||||
|
const userAvatar = computed(() => ({
|
||||||
|
src: user.value?.avatar_url || `https://ui-avatars.com/api/?name=${encodeURIComponent(user.value?.name || user.value?.username || 'User')}&background=random&bold=true&format=svg`,
|
||||||
|
alt: user.value?.name || user.value?.username || 'User'
|
||||||
|
}))
|
||||||
|
|
||||||
|
// Iniciales del usuario para efecto visual
|
||||||
|
const userInitials = computed(() => {
|
||||||
|
const name = user.value?.name || user.value?.username || 'U'
|
||||||
|
return name.split(' ').map(n => n[0]).join('').toUpperCase().slice(0, 2)
|
||||||
|
})
|
||||||
|
|
||||||
const items = computed(() => [
|
const items = computed(() => [
|
||||||
[{
|
[{
|
||||||
label: user.value?.email || 'Usuario',
|
label: user.value?.name || user.value?.username || 'Usuario',
|
||||||
|
description: user.value?.email,
|
||||||
|
avatar: userAvatar.value,
|
||||||
slot: 'account',
|
slot: 'account',
|
||||||
disabled: true
|
type: 'label'
|
||||||
|
}],
|
||||||
|
[{
|
||||||
|
label: 'Mi Perfil',
|
||||||
|
description: 'Ver y editar perfil',
|
||||||
|
icon: 'i-lucide-user',
|
||||||
|
iconClass: 'text-blue-500',
|
||||||
|
to: '/profile',
|
||||||
|
slot: 'profile'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Configuración',
|
||||||
|
description: 'Preferencias y ajustes',
|
||||||
|
icon: 'i-lucide-settings',
|
||||||
|
iconClass: 'text-gray-500',
|
||||||
|
to: '/settings',
|
||||||
|
slot: 'settings'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Notificaciones',
|
||||||
|
description: 'Gestionar notificaciones',
|
||||||
|
icon: 'i-lucide-bell',
|
||||||
|
iconClass: 'text-amber-500',
|
||||||
|
to: '/notifications',
|
||||||
|
slot: 'notifications',
|
||||||
|
badge: '3'
|
||||||
|
}],
|
||||||
|
[{
|
||||||
|
label: 'Ayuda y Soporte',
|
||||||
|
icon: 'i-lucide-help-circle',
|
||||||
|
iconClass: 'text-indigo-500',
|
||||||
|
to: '/help'
|
||||||
}],
|
}],
|
||||||
[{
|
[{
|
||||||
label: 'Cerrar sesión',
|
label: 'Cerrar sesión',
|
||||||
icon: 'i-heroicons-arrow-right-on-rectangle',
|
icon: 'i-lucide-log-out',
|
||||||
click: logout
|
iconClass: 'text-red-500',
|
||||||
|
color: 'error',
|
||||||
|
click: () => logout()
|
||||||
}]
|
}]
|
||||||
])
|
])
|
||||||
</script>
|
</script>
|
||||||
@@ -23,26 +73,139 @@ const items = computed(() => [
|
|||||||
<template>
|
<template>
|
||||||
<UDropdownMenu
|
<UDropdownMenu
|
||||||
v-if="user?.authenticated && !loading"
|
v-if="user?.authenticated && !loading"
|
||||||
|
v-model:open="isOpen"
|
||||||
:items="items"
|
:items="items"
|
||||||
:ui="{ item: { disabled: 'cursor-text select-text' } }"
|
:ui="{
|
||||||
:popper="{ placement: 'bottom-start' }"
|
content: 'w-72 p-2 bg-white dark:bg-gray-900 shadow-xl border border-gray-200 dark:border-gray-800 backdrop-blur-xl',
|
||||||
|
item: {
|
||||||
|
disabled: 'cursor-default select-text opacity-100',
|
||||||
|
base: 'group gap-3 rounded-xl transition-all duration-300 hover:bg-gray-50 dark:hover:bg-gray-800/50 active:scale-[0.98]',
|
||||||
|
padding: 'px-4 py-3'
|
||||||
|
},
|
||||||
|
separator: 'my-1.5',
|
||||||
|
arrow: 'before:bg-white dark:before:bg-gray-900 before:border before:border-gray-200 dark:before:border-gray-800'
|
||||||
|
}"
|
||||||
|
:popper="{ placement: 'bottom-end', offsetDistance: 12 }"
|
||||||
|
arrow
|
||||||
>
|
>
|
||||||
|
<UButton
|
||||||
|
color="neutral"
|
||||||
|
variant="ghost"
|
||||||
|
:ui="{
|
||||||
|
rounded: 'rounded-full',
|
||||||
|
padding: { sm: 'p-1' }
|
||||||
|
}"
|
||||||
|
class="relative hover:bg-gray-100/80 dark:hover:bg-gray-800/80 transition-all duration-300 hover:scale-110 active:scale-95 group"
|
||||||
|
>
|
||||||
|
<div class="relative">
|
||||||
<UAvatar
|
<UAvatar
|
||||||
:alt="user.name || user.username || 'User'"
|
v-bind="userAvatar"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
:ui="{
|
||||||
|
wrapper: 'ring-2 ring-offset-2 ring-offset-white dark:ring-offset-gray-950 ring-primary-500/30 group-hover:ring-primary-500/60 transition-all duration-300 shadow-lg group-hover:shadow-primary-500/20'
|
||||||
|
}"
|
||||||
/>
|
/>
|
||||||
|
<span
|
||||||
|
class="absolute -bottom-0.5 -right-0.5 w-3 h-3 bg-green-500 border-2 border-white dark:border-gray-950 rounded-full transition-all duration-300 group-hover:scale-110"
|
||||||
|
title="En línea"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</UButton>
|
||||||
|
|
||||||
<template #account="{ item }">
|
<template #account="{ item }">
|
||||||
<div class="text-left">
|
<div class="flex items-center gap-4 py-2 px-2 border-b border-gray-100 dark:border-gray-800 mb-1">
|
||||||
<p class="font-medium text-gray-900 dark:text-white">
|
<div class="relative">
|
||||||
{{ user.name || user.username }}
|
<UAvatar
|
||||||
</p>
|
v-bind="item.avatar"
|
||||||
<p class="text-sm text-gray-500 dark:text-gray-400 truncate">
|
size="lg"
|
||||||
|
:ui="{
|
||||||
|
wrapper: 'ring-2 ring-primary-500/40 shadow-lg'
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="absolute -bottom-1 -right-1 w-4 h-4 bg-green-500 border-2 border-white dark:border-gray-900 rounded-full"
|
||||||
|
title="En línea"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 min-w-0">
|
||||||
|
<p class="font-bold text-base text-gray-900 dark:text-white truncate mb-0.5">
|
||||||
{{ item.label }}
|
{{ item.label }}
|
||||||
</p>
|
</p>
|
||||||
|
<p class="text-xs text-gray-500 dark:text-gray-400 truncate font-medium">
|
||||||
|
{{ item.description }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #profile="{ item }">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div :class="['w-9 h-9 rounded-lg bg-blue-50 dark:bg-blue-950/30 flex items-center justify-center transition-colors duration-200 group-hover:bg-blue-100 dark:group-hover:bg-blue-950/50']">
|
||||||
|
<UIcon :name="item.icon" :class="['w-4 h-4', item.iconClass]" />
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 min-w-0">
|
||||||
|
<p class="font-semibold text-sm text-gray-900 dark:text-white">
|
||||||
|
{{ item.label }}
|
||||||
|
</p>
|
||||||
|
<p class="text-xs text-gray-500 dark:text-gray-400">
|
||||||
|
{{ item.description }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<UIcon name="i-lucide-chevron-right" class="w-4 h-4 text-gray-400 opacity-0 group-hover:opacity-100 transition-opacity duration-200" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #settings="{ item }">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div :class="['w-9 h-9 rounded-lg bg-gray-50 dark:bg-gray-800/50 flex items-center justify-center transition-colors duration-200 group-hover:bg-gray-100 dark:group-hover:bg-gray-800']">
|
||||||
|
<UIcon :name="item.icon" :class="['w-4 h-4', item.iconClass]" />
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 min-w-0">
|
||||||
|
<p class="font-semibold text-sm text-gray-900 dark:text-white">
|
||||||
|
{{ item.label }}
|
||||||
|
</p>
|
||||||
|
<p class="text-xs text-gray-500 dark:text-gray-400">
|
||||||
|
{{ item.description }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<UIcon name="i-lucide-chevron-right" class="w-4 h-4 text-gray-400 opacity-0 group-hover:opacity-100 transition-opacity duration-200" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #notifications="{ item }">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="relative">
|
||||||
|
<div :class="['w-9 h-9 rounded-lg bg-amber-50 dark:bg-amber-950/30 flex items-center justify-center transition-colors duration-200 group-hover:bg-amber-100 dark:group-hover:bg-amber-950/50']">
|
||||||
|
<UIcon :name="item.icon" :class="['w-4 h-4', item.iconClass]" />
|
||||||
|
</div>
|
||||||
|
<span v-if="item.badge" class="absolute -top-1 -right-1 w-5 h-5 bg-red-500 text-white text-[10px] font-bold rounded-full flex items-center justify-center ring-2 ring-white dark:ring-gray-900">
|
||||||
|
{{ item.badge }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 min-w-0">
|
||||||
|
<p class="font-semibold text-sm text-gray-900 dark:text-white">
|
||||||
|
{{ item.label }}
|
||||||
|
</p>
|
||||||
|
<p class="text-xs text-gray-500 dark:text-gray-400">
|
||||||
|
{{ item.description }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<UIcon name="i-lucide-chevron-right" class="w-4 h-4 text-gray-400 opacity-0 group-hover:opacity-100 transition-opacity duration-200" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</UDropdownMenu>
|
</UDropdownMenu>
|
||||||
|
|
||||||
<USkeleton v-else-if="loading" class="h-8 w-8" :ui="{ rounded: 'rounded-full' }" />
|
<div
|
||||||
|
v-else-if="loading"
|
||||||
|
class="relative"
|
||||||
|
>
|
||||||
|
<USkeleton
|
||||||
|
class="h-9 w-9"
|
||||||
|
:ui="{
|
||||||
|
rounded: 'rounded-full',
|
||||||
|
background: 'bg-gradient-to-br from-gray-200 to-gray-300 dark:from-gray-700 dark:to-gray-800'
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
<div class="absolute inset-0 rounded-full bg-gradient-to-br from-primary-500/20 to-transparent animate-pulse" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -47,27 +47,182 @@
|
|||||||
class="gap-1"
|
class="gap-1"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<UNavigationMenu
|
|
||||||
:collapsed="isCollapsed"
|
|
||||||
:items="navigationSecondary"
|
|
||||||
orientation="vertical"
|
|
||||||
class="mt-auto gap-1"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #footer="{ collapsed: isCollapsed }">
|
<template #footer="{ collapsed: isCollapsed }">
|
||||||
|
<div v-if="user?.authenticated && !loading" class="space-y-3">
|
||||||
|
<!-- User Profile Section -->
|
||||||
|
<div
|
||||||
|
v-if="!isCollapsed"
|
||||||
|
class="p-0 space-y-2"
|
||||||
|
>
|
||||||
|
<!-- User Info Card -->
|
||||||
|
<div class="px-3 py-2.5 bg-gradient-to-br from-primary-50/50 to-transparent dark:from-primary-950/20 dark:to-transparent rounded-lg border border-primary-100/60 dark:border-primary-900/40">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="relative flex-shrink-0">
|
||||||
|
<UAvatar
|
||||||
|
v-bind="userAvatar"
|
||||||
|
size="md"
|
||||||
|
:ui="{
|
||||||
|
wrapper: 'ring-2 ring-primary-400/50 dark:ring-primary-500/40 shadow-sm'
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="absolute -bottom-0.5 -right-0.5 w-3 h-3 bg-green-500 border-2 border-white dark:border-gray-950 rounded-full shadow-sm"
|
||||||
|
title="En línea"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 min-w-0">
|
||||||
|
<p class="font-semibold text-sm text-gray-900 dark:text-white truncate leading-tight">
|
||||||
|
{{ user.name || user.username }}
|
||||||
|
</p>
|
||||||
|
<p class="text-xs text-gray-500 dark:text-gray-400 truncate mt-0.5">
|
||||||
|
{{ user.email }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Quick Actions -->
|
||||||
|
<div class="space-y-1">
|
||||||
<UButton
|
<UButton
|
||||||
:avatar="{ src: 'https://avatars.githubusercontent.com/u/12011070?v=4' }"
|
to="/profile"
|
||||||
:label="isCollapsed ? undefined : 'Equipo Núcleo'"
|
|
||||||
color="neutral"
|
color="neutral"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
class="w-full justify-start"
|
size="sm"
|
||||||
:block="isCollapsed"
|
block
|
||||||
|
class="justify-start gap-2.5 hover:bg-primary-50/80 dark:hover:bg-primary-950/30 transition-all duration-200"
|
||||||
|
:ui="{
|
||||||
|
rounded: 'rounded-lg',
|
||||||
|
padding: { sm: 'px-2.5 py-2' }
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
|
<template #leading>
|
||||||
|
<div class="w-7 h-7 rounded-md bg-blue-50 dark:bg-blue-950/30 flex items-center justify-center flex-shrink-0">
|
||||||
|
<UIcon name="i-lucide-user" class="size-3.5 text-blue-600 dark:text-blue-400" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<span class="text-sm font-medium text-gray-700 dark:text-gray-300">Mi Perfil</span>
|
||||||
|
</UButton>
|
||||||
|
|
||||||
|
<UButton
|
||||||
|
to="/settings"
|
||||||
|
color="neutral"
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
block
|
||||||
|
class="justify-start gap-2.5 hover:bg-primary-50/80 dark:hover:bg-primary-950/30 transition-all duration-200"
|
||||||
|
:ui="{
|
||||||
|
rounded: 'rounded-lg',
|
||||||
|
padding: { sm: 'px-2.5 py-2' }
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template #leading>
|
||||||
|
<div class="w-7 h-7 rounded-md bg-gray-50 dark:bg-gray-800/50 flex items-center justify-center flex-shrink-0">
|
||||||
|
<UIcon name="i-lucide-settings" class="size-3.5 text-gray-600 dark:text-gray-400" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<span class="text-sm font-medium text-gray-700 dark:text-gray-300">Configuración</span>
|
||||||
|
</UButton>
|
||||||
|
|
||||||
|
<UButton
|
||||||
|
to="/notifications"
|
||||||
|
color="neutral"
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
block
|
||||||
|
class="justify-start gap-2.5 hover:bg-primary-50/80 dark:hover:bg-primary-950/30 transition-all duration-200"
|
||||||
|
:ui="{
|
||||||
|
rounded: 'rounded-lg',
|
||||||
|
padding: { sm: 'px-2.5 py-2' }
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template #leading>
|
||||||
|
<div class="w-7 h-7 rounded-md bg-amber-50 dark:bg-amber-950/30 flex items-center justify-center relative flex-shrink-0">
|
||||||
|
<UIcon name="i-lucide-bell" class="size-3.5 text-amber-600 dark:text-amber-400" />
|
||||||
|
<span class="absolute -top-0.5 -right-0.5 w-2 h-2 bg-red-500 rounded-full ring-1 ring-white dark:ring-gray-900" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<span class="text-sm font-medium text-gray-700 dark:text-gray-300">Notificaciones</span>
|
||||||
<template #trailing>
|
<template #trailing>
|
||||||
<UIcon name="i-lucide-log-out" class="size-4" />
|
<UBadge color="red" variant="solid" size="xs" class="ml-auto">3</UBadge>
|
||||||
</template>
|
</template>
|
||||||
</UButton>
|
</UButton>
|
||||||
|
|
||||||
|
<div class="pt-2 mt-1.5 border-t border-gray-200/60 dark:border-gray-800/60">
|
||||||
|
<UButton
|
||||||
|
color="neutral"
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
block
|
||||||
|
class="justify-start gap-2.5 hover:bg-red-50/80 dark:hover:bg-red-950/30 transition-all duration-200 group"
|
||||||
|
:ui="{
|
||||||
|
rounded: 'rounded-lg',
|
||||||
|
padding: { sm: 'px-2.5 py-2' }
|
||||||
|
}"
|
||||||
|
@click="logout"
|
||||||
|
>
|
||||||
|
<template #leading>
|
||||||
|
<div class="w-7 h-7 rounded-md bg-red-50 dark:bg-red-950/30 flex items-center justify-center flex-shrink-0 group-hover:bg-red-100 dark:group-hover:bg-red-950/50 transition-colors">
|
||||||
|
<UIcon name="i-lucide-log-out" class="size-3.5 text-red-600 dark:text-red-400" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<span class="text-sm font-medium text-red-600 dark:text-red-400">Cerrar sesión</span>
|
||||||
|
</UButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Collapsed View -->
|
||||||
|
<div v-else class="flex flex-col items-center gap-3">
|
||||||
|
<div class="relative group">
|
||||||
|
<UButton
|
||||||
|
color="neutral"
|
||||||
|
variant="ghost"
|
||||||
|
square
|
||||||
|
class="relative hover:bg-primary-50/50 dark:hover:bg-primary-950/20 transition-all duration-200"
|
||||||
|
:ui="{ rounded: 'rounded-lg' }"
|
||||||
|
>
|
||||||
|
<div class="relative">
|
||||||
|
<UAvatar
|
||||||
|
v-bind="userAvatar"
|
||||||
|
size="sm"
|
||||||
|
:ui="{
|
||||||
|
wrapper: 'ring-2 ring-primary-400/40 dark:ring-primary-500/30 group-hover:ring-primary-500/60 transition-all duration-200 shadow-sm'
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="absolute -bottom-0.5 -right-0.5 w-2.5 h-2.5 bg-green-500 border-2 border-white dark:border-gray-950 rounded-full shadow-sm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</UButton>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="w-full h-px bg-gray-200/50 dark:bg-gray-800/50" />
|
||||||
|
|
||||||
|
<UButton
|
||||||
|
@click="logout"
|
||||||
|
color="neutral"
|
||||||
|
variant="ghost"
|
||||||
|
square
|
||||||
|
class="hover:bg-red-50 dark:hover:bg-red-950/20 transition-all duration-200"
|
||||||
|
:ui="{ rounded: 'rounded-lg' }"
|
||||||
|
>
|
||||||
|
<UIcon name="i-lucide-log-out" class="size-4 text-red-600 dark:text-red-400" />
|
||||||
|
</UButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Loading State -->
|
||||||
|
<div v-else-if="loading">
|
||||||
|
<div v-if="!isCollapsed" class="space-y-2">
|
||||||
|
<USkeleton class="h-14 w-full" :ui="{ rounded: 'rounded-lg', background: 'bg-gray-200/60 dark:bg-gray-800/60' }" />
|
||||||
|
<USkeleton class="h-28 w-full" :ui="{ rounded: 'rounded-lg', background: 'bg-gray-200/60 dark:bg-gray-800/60' }" />
|
||||||
|
</div>
|
||||||
|
<div v-else class="flex flex-col items-center gap-3">
|
||||||
|
<USkeleton class="h-9 w-9" :ui="{ rounded: 'rounded-lg', background: 'bg-gray-200/60 dark:bg-gray-800/60' }" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</UDashboardSidebar>
|
</UDashboardSidebar>
|
||||||
</template>
|
</template>
|
||||||
@@ -127,18 +282,16 @@ const navigationPrimary = computed<NavigationMenuItem[]>(() => [
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
const navigationSecondary: NavigationMenuItem[] = [
|
const { user, loading, fetchUser, logout } = useAuth()
|
||||||
{
|
|
||||||
label: 'Documentación',
|
// Cargar usuario al montar
|
||||||
icon: 'i-lucide-book-open',
|
onMounted(() => {
|
||||||
to: 'https://ui.nuxt.com',
|
fetchUser()
|
||||||
target: '_blank'
|
})
|
||||||
},
|
|
||||||
{
|
// Computed para el avatar del usuario
|
||||||
label: 'Repositorio',
|
const userAvatar = computed(() => ({
|
||||||
icon: 'i-lucide-github',
|
src: user.value?.avatar_url || `https://ui-avatars.com/api/?name=${encodeURIComponent(user.value?.name || user.value?.username || 'User')}&background=3b82f6&color=fff&bold=true&format=svg`,
|
||||||
to: 'https://gitea.nucleoriofrio.com/nucleo000/analiticaNucleo',
|
alt: user.value?.name || user.value?.username || 'User'
|
||||||
target: '_blank'
|
}))
|
||||||
}
|
|
||||||
]
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -25,8 +25,18 @@ export const useAuth = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const logout = () => {
|
const logout = () => {
|
||||||
// Authentik maneja el logout, redirigir a la URL de logout
|
// Limpiar estado local
|
||||||
window.location.href = '/outpost.goauthentik.io/sign_out'
|
user.value = null
|
||||||
|
loading.value = false
|
||||||
|
|
||||||
|
// Obtener configuración de Authentik desde variables de entorno
|
||||||
|
const config = useRuntimeConfig()
|
||||||
|
const authentikUrl = config.public.authentikUrl || 'https://authentik.nucleoriofrio.com'
|
||||||
|
const appSlug = config.public.authentikAppSlug || 'devserver'
|
||||||
|
|
||||||
|
// Redirigir al endpoint de logout de Authentik con el slug de la aplicación
|
||||||
|
// Esto cierra la sesión completa de Authentik (OIDC end-session)
|
||||||
|
window.location.href = `${authentikUrl}/application/o/${appSlug}/end-session/`
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
82
nuxt4-app/app/error.vue
Normal file
82
nuxt4-app/app/error.vue
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { NuxtError } from '#app'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
error: NuxtError
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const handleError = () => clearError({ redirect: '/' })
|
||||||
|
|
||||||
|
const errorMessage = computed(() => {
|
||||||
|
if (props.error.statusCode === 404) {
|
||||||
|
return {
|
||||||
|
title: 'Página no encontrada',
|
||||||
|
description: 'Lo sentimos, la página que buscas no existe o ha sido movida.',
|
||||||
|
icon: 'i-lucide-file-question'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
title: 'Error del servidor',
|
||||||
|
description: 'Ha ocurrido un error inesperado. Por favor, intenta nuevamente.',
|
||||||
|
icon: 'i-lucide-alert-circle'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<UDashboardLayout>
|
||||||
|
<UDashboardPanel grow>
|
||||||
|
<div class="flex items-center justify-center min-h-screen p-4">
|
||||||
|
<div class="text-center max-w-md mx-auto space-y-6">
|
||||||
|
<!-- Error Icon -->
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<div class="w-20 h-20 rounded-full bg-red-50 dark:bg-red-950/30 flex items-center justify-center">
|
||||||
|
<UIcon :name="errorMessage.icon" class="size-10 text-red-600 dark:text-red-400" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Error Code -->
|
||||||
|
<div>
|
||||||
|
<h1 class="text-6xl font-bold text-gray-900 dark:text-white mb-2">
|
||||||
|
{{ error.statusCode || '500' }}
|
||||||
|
</h1>
|
||||||
|
<h2 class="text-2xl font-semibold text-gray-700 dark:text-gray-300 mb-3">
|
||||||
|
{{ errorMessage.title }}
|
||||||
|
</h2>
|
||||||
|
<p class="text-gray-600 dark:text-gray-400">
|
||||||
|
{{ errorMessage.description }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Error Details (dev mode) -->
|
||||||
|
<div v-if="error.message && $config.public.dev" class="mt-4 p-4 bg-gray-50 dark:bg-gray-900 rounded-lg text-left">
|
||||||
|
<p class="text-xs font-mono text-gray-600 dark:text-gray-400 break-all">
|
||||||
|
{{ error.message }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Actions -->
|
||||||
|
<div class="flex flex-col sm:flex-row gap-3 justify-center mt-8">
|
||||||
|
<UButton
|
||||||
|
to="/"
|
||||||
|
color="primary"
|
||||||
|
size="lg"
|
||||||
|
icon="i-lucide-home"
|
||||||
|
>
|
||||||
|
Ir al inicio
|
||||||
|
</UButton>
|
||||||
|
<UButton
|
||||||
|
color="neutral"
|
||||||
|
variant="outline"
|
||||||
|
size="lg"
|
||||||
|
icon="i-lucide-refresh-ccw"
|
||||||
|
@click="handleError"
|
||||||
|
>
|
||||||
|
Intentar nuevamente
|
||||||
|
</UButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</UDashboardPanel>
|
||||||
|
</UDashboardLayout>
|
||||||
|
</template>
|
||||||
150
nuxt4-app/app/pages/notifications.vue
Normal file
150
nuxt4-app/app/pages/notifications.vue
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
definePageMeta({
|
||||||
|
middleware: 'auth'
|
||||||
|
})
|
||||||
|
|
||||||
|
// Mock notifications for preview
|
||||||
|
const mockNotifications = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
type: 'info',
|
||||||
|
title: 'Nueva actualización disponible',
|
||||||
|
message: 'Se ha lanzado una nueva versión del sistema con mejoras de rendimiento.',
|
||||||
|
time: '2 horas',
|
||||||
|
read: false,
|
||||||
|
icon: 'i-lucide-info',
|
||||||
|
color: 'blue'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
type: 'warning',
|
||||||
|
title: 'Mantenimiento programado',
|
||||||
|
message: 'El sistema estará en mantenimiento el próximo domingo de 2:00 AM a 4:00 AM.',
|
||||||
|
time: '1 día',
|
||||||
|
read: false,
|
||||||
|
icon: 'i-lucide-alert-triangle',
|
||||||
|
color: 'amber'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
type: 'success',
|
||||||
|
title: 'Reporte generado',
|
||||||
|
message: 'Tu reporte mensual ha sido generado exitosamente.',
|
||||||
|
time: '3 días',
|
||||||
|
read: true,
|
||||||
|
icon: 'i-lucide-check-circle',
|
||||||
|
color: 'green'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<UDashboardLayout>
|
||||||
|
<UDashboardPanel grow>
|
||||||
|
<UDashboardNavbar
|
||||||
|
title="Notificaciones"
|
||||||
|
description="Mantente al día con las últimas actualizaciones y alertas"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<UDashboardPanelContent>
|
||||||
|
<div class="max-w-4xl mx-auto space-y-8">
|
||||||
|
<!-- Coming Soon Banner -->
|
||||||
|
<UCard>
|
||||||
|
<div class="text-center py-12 space-y-6">
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<div class="w-24 h-24 rounded-full bg-amber-50 dark:bg-amber-950/30 flex items-center justify-center relative">
|
||||||
|
<UIcon name="i-lucide-bell" class="size-12 text-amber-600 dark:text-amber-400" />
|
||||||
|
<span class="absolute -top-1 -right-1 w-6 h-6 bg-red-500 text-white text-xs font-bold rounded-full flex items-center justify-center ring-4 ring-white dark:ring-gray-900">
|
||||||
|
3
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h2 class="text-3xl font-bold text-gray-900 dark:text-white mb-2">
|
||||||
|
Página en construcción
|
||||||
|
</h2>
|
||||||
|
<p class="text-lg text-gray-600 dark:text-gray-400 mb-4">
|
||||||
|
Estamos trabajando en esta funcionalidad
|
||||||
|
</p>
|
||||||
|
<p class="text-sm text-gray-500 dark:text-gray-500 max-w-md mx-auto">
|
||||||
|
Pronto podrás gestionar tus notificaciones, configurar alertas personalizadas y mantenerte informado sobre eventos importantes del sistema.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-center gap-3">
|
||||||
|
<UButton
|
||||||
|
to="/"
|
||||||
|
color="primary"
|
||||||
|
icon="i-lucide-home"
|
||||||
|
>
|
||||||
|
Volver al inicio
|
||||||
|
</UButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</UCard>
|
||||||
|
|
||||||
|
<!-- Notifications Preview -->
|
||||||
|
<UCard>
|
||||||
|
<template #header>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">
|
||||||
|
Vista previa de notificaciones
|
||||||
|
</h3>
|
||||||
|
<UBadge color="red" variant="solid" size="sm">
|
||||||
|
{{ mockNotifications.filter(n => !n.read).length }} nuevas
|
||||||
|
</UBadge>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div class="space-y-3">
|
||||||
|
<div
|
||||||
|
v-for="notification in mockNotifications"
|
||||||
|
:key="notification.id"
|
||||||
|
:class="[
|
||||||
|
'p-4 rounded-lg border transition-colors',
|
||||||
|
notification.read
|
||||||
|
? 'bg-gray-50/50 dark:bg-gray-800/50 border-gray-200 dark:border-gray-700'
|
||||||
|
: 'bg-white dark:bg-gray-900 border-gray-300 dark:border-gray-600'
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<div class="flex gap-3">
|
||||||
|
<div :class="[
|
||||||
|
'w-10 h-10 rounded-lg flex items-center justify-center flex-shrink-0',
|
||||||
|
`bg-${notification.color}-50 dark:bg-${notification.color}-950/30`
|
||||||
|
]">
|
||||||
|
<UIcon
|
||||||
|
:name="notification.icon"
|
||||||
|
:class="[
|
||||||
|
'size-5',
|
||||||
|
`text-${notification.color}-600 dark:text-${notification.color}-400`
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 min-w-0">
|
||||||
|
<div class="flex items-start justify-between gap-2">
|
||||||
|
<h4 :class="[
|
||||||
|
'font-semibold text-sm',
|
||||||
|
notification.read
|
||||||
|
? 'text-gray-600 dark:text-gray-400'
|
||||||
|
: 'text-gray-900 dark:text-white'
|
||||||
|
]">
|
||||||
|
{{ notification.title }}
|
||||||
|
</h4>
|
||||||
|
<span class="text-xs text-gray-500 dark:text-gray-500 flex-shrink-0">
|
||||||
|
hace {{ notification.time }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p class="text-sm text-gray-600 dark:text-gray-400 mt-1">
|
||||||
|
{{ notification.message }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</UCard>
|
||||||
|
</div>
|
||||||
|
</UDashboardPanelContent>
|
||||||
|
</UDashboardPanel>
|
||||||
|
</UDashboardLayout>
|
||||||
|
</template>
|
||||||
93
nuxt4-app/app/pages/profile.vue
Normal file
93
nuxt4-app/app/pages/profile.vue
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
const { user } = useAuth()
|
||||||
|
|
||||||
|
definePageMeta({
|
||||||
|
middleware: 'auth'
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<UDashboardLayout>
|
||||||
|
<UDashboardPanel grow>
|
||||||
|
<UDashboardNavbar
|
||||||
|
title="Mi Perfil"
|
||||||
|
description="Gestiona tu información personal y preferencias de cuenta"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<UDashboardPanelContent>
|
||||||
|
<div class="max-w-4xl mx-auto space-y-8">
|
||||||
|
<!-- Coming Soon Banner -->
|
||||||
|
<UCard>
|
||||||
|
<div class="text-center py-12 space-y-6">
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<div class="w-24 h-24 rounded-full bg-blue-50 dark:bg-blue-950/30 flex items-center justify-center">
|
||||||
|
<UIcon name="i-lucide-user" class="size-12 text-blue-600 dark:text-blue-400" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h2 class="text-3xl font-bold text-gray-900 dark:text-white mb-2">
|
||||||
|
Página en construcción
|
||||||
|
</h2>
|
||||||
|
<p class="text-lg text-gray-600 dark:text-gray-400 mb-4">
|
||||||
|
Estamos trabajando en esta funcionalidad
|
||||||
|
</p>
|
||||||
|
<p class="text-sm text-gray-500 dark:text-gray-500 max-w-md mx-auto">
|
||||||
|
Pronto podrás gestionar tu perfil, actualizar tu información personal, cambiar tu foto de perfil y más.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-center gap-3">
|
||||||
|
<UButton
|
||||||
|
to="/"
|
||||||
|
color="primary"
|
||||||
|
icon="i-lucide-home"
|
||||||
|
>
|
||||||
|
Volver al inicio
|
||||||
|
</UButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</UCard>
|
||||||
|
|
||||||
|
<!-- Current User Info Preview -->
|
||||||
|
<UCard v-if="user">
|
||||||
|
<template #header>
|
||||||
|
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">
|
||||||
|
Información actual del usuario
|
||||||
|
</h3>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div class="space-y-4">
|
||||||
|
<div>
|
||||||
|
<label class="text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||||
|
Nombre de usuario
|
||||||
|
</label>
|
||||||
|
<p class="mt-1 text-gray-900 dark:text-white">
|
||||||
|
{{ user.username || 'No especificado' }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label class="text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||||
|
Nombre completo
|
||||||
|
</label>
|
||||||
|
<p class="mt-1 text-gray-900 dark:text-white">
|
||||||
|
{{ user.name || 'No especificado' }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label class="text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||||
|
Email
|
||||||
|
</label>
|
||||||
|
<p class="mt-1 text-gray-900 dark:text-white">
|
||||||
|
{{ user.email || 'No especificado' }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</UCard>
|
||||||
|
</div>
|
||||||
|
</UDashboardPanelContent>
|
||||||
|
</UDashboardPanel>
|
||||||
|
</UDashboardLayout>
|
||||||
|
</template>
|
||||||
120
nuxt4-app/app/pages/settings.vue
Normal file
120
nuxt4-app/app/pages/settings.vue
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
definePageMeta({
|
||||||
|
middleware: 'auth'
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<UDashboardLayout>
|
||||||
|
<UDashboardPanel grow>
|
||||||
|
<UDashboardNavbar
|
||||||
|
title="Configuración"
|
||||||
|
description="Personaliza tu experiencia y preferencias del sistema"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<UDashboardPanelContent>
|
||||||
|
<div class="max-w-4xl mx-auto space-y-8">
|
||||||
|
<!-- Coming Soon Banner -->
|
||||||
|
<UCard>
|
||||||
|
<div class="text-center py-12 space-y-6">
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<div class="w-24 h-24 rounded-full bg-gray-50 dark:bg-gray-800/50 flex items-center justify-center">
|
||||||
|
<UIcon name="i-lucide-settings" class="size-12 text-gray-600 dark:text-gray-400" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h2 class="text-3xl font-bold text-gray-900 dark:text-white mb-2">
|
||||||
|
Página en construcción
|
||||||
|
</h2>
|
||||||
|
<p class="text-lg text-gray-600 dark:text-gray-400 mb-4">
|
||||||
|
Estamos trabajando en esta funcionalidad
|
||||||
|
</p>
|
||||||
|
<p class="text-sm text-gray-500 dark:text-gray-500 max-w-md mx-auto">
|
||||||
|
Pronto podrás configurar tus preferencias de visualización, notificaciones, privacidad y más opciones del sistema.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-center gap-3">
|
||||||
|
<UButton
|
||||||
|
to="/"
|
||||||
|
color="primary"
|
||||||
|
icon="i-lucide-home"
|
||||||
|
>
|
||||||
|
Volver al inicio
|
||||||
|
</UButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</UCard>
|
||||||
|
|
||||||
|
<!-- Settings Preview -->
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
<UCard>
|
||||||
|
<template #header>
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="w-10 h-10 rounded-lg bg-blue-50 dark:bg-blue-950/30 flex items-center justify-center">
|
||||||
|
<UIcon name="i-lucide-palette" class="size-5 text-blue-600 dark:text-blue-400" />
|
||||||
|
</div>
|
||||||
|
<h3 class="font-semibold text-gray-900 dark:text-white">
|
||||||
|
Apariencia
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<p class="text-sm text-gray-600 dark:text-gray-400">
|
||||||
|
Tema, colores y personalización visual
|
||||||
|
</p>
|
||||||
|
</UCard>
|
||||||
|
|
||||||
|
<UCard>
|
||||||
|
<template #header>
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="w-10 h-10 rounded-lg bg-amber-50 dark:bg-amber-950/30 flex items-center justify-center">
|
||||||
|
<UIcon name="i-lucide-bell" class="size-5 text-amber-600 dark:text-amber-400" />
|
||||||
|
</div>
|
||||||
|
<h3 class="font-semibold text-gray-900 dark:text-white">
|
||||||
|
Notificaciones
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<p class="text-sm text-gray-600 dark:text-gray-400">
|
||||||
|
Gestión de alertas y comunicaciones
|
||||||
|
</p>
|
||||||
|
</UCard>
|
||||||
|
|
||||||
|
<UCard>
|
||||||
|
<template #header>
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="w-10 h-10 rounded-lg bg-green-50 dark:bg-green-950/30 flex items-center justify-center">
|
||||||
|
<UIcon name="i-lucide-shield" class="size-5 text-green-600 dark:text-green-400" />
|
||||||
|
</div>
|
||||||
|
<h3 class="font-semibold text-gray-900 dark:text-white">
|
||||||
|
Privacidad
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<p class="text-sm text-gray-600 dark:text-gray-400">
|
||||||
|
Control de datos y seguridad
|
||||||
|
</p>
|
||||||
|
</UCard>
|
||||||
|
|
||||||
|
<UCard>
|
||||||
|
<template #header>
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<div class="w-10 h-10 rounded-lg bg-purple-50 dark:bg-purple-950/30 flex items-center justify-center">
|
||||||
|
<UIcon name="i-lucide-globe" class="size-5 text-purple-600 dark:text-purple-400" />
|
||||||
|
</div>
|
||||||
|
<h3 class="font-semibold text-gray-900 dark:text-white">
|
||||||
|
Idioma y región
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<p class="text-sm text-gray-600 dark:text-gray-400">
|
||||||
|
Preferencias de localización
|
||||||
|
</p>
|
||||||
|
</UCard>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</UDashboardPanelContent>
|
||||||
|
</UDashboardPanel>
|
||||||
|
</UDashboardLayout>
|
||||||
|
</template>
|
||||||
@@ -164,6 +164,10 @@ export default defineNuxtConfig({
|
|||||||
url: process.env.SUPABASE_URL || process.env.NEXT_PUBLIC_SUPABASE_URL,
|
url: process.env.SUPABASE_URL || process.env.NEXT_PUBLIC_SUPABASE_URL,
|
||||||
serviceRoleKey:
|
serviceRoleKey:
|
||||||
process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
|
process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
|
||||||
|
},
|
||||||
|
public: {
|
||||||
|
authentikUrl: process.env.NUXT_PUBLIC_AUTHENTIK_URL || '',
|
||||||
|
authentikAppSlug: process.env.NUXT_PUBLIC_AUTHENTIK_APP_SLUG || ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user