Feat: Agregar estructura PWA Nuxt4 y configuración de desarrollo
Configuración PWA: - Agregar estructura completa de Nuxt4 para PWA - Configurar .env.example con variables de entorno - Preparar aplicación para instalación offline Configuración Claude Code: - Agregar .claude/ con settings y hooks - Configurar entorno de desarrollo con Claude CI/CD: - Agregar .gitea/workflows para Gitea Actions - Preparar pipeline de despliegue automático Docker: - Actualizar docker-compose.yml con servicios PWA - Configurar networking entre servicios Git: - Actualizar .gitignore para excluir archivos de build - Ignorar node_modules y archivos temporales
This commit is contained in:
112
nuxt4/app/components/auth/GroupCheckButton.vue
Normal file
112
nuxt4/app/components/auth/GroupCheckButton.vue
Normal file
@@ -0,0 +1,112 @@
|
||||
<template>
|
||||
<UButton
|
||||
:color="color"
|
||||
:size="size"
|
||||
:variant="variant"
|
||||
:loading="loading"
|
||||
@click="handleClick"
|
||||
class="group-check-button"
|
||||
>
|
||||
<template #leading>
|
||||
<UIcon :name="icon" />
|
||||
</template>
|
||||
<slot>{{ label }}</slot>
|
||||
</UButton>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { ButtonColor, ButtonVariant, ButtonSize } from '#ui/types'
|
||||
|
||||
interface Props {
|
||||
groupName: string
|
||||
label?: string
|
||||
icon?: string
|
||||
color?: ButtonColor
|
||||
variant?: ButtonVariant
|
||||
size?: ButtonSize
|
||||
verifyBackend?: boolean
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
label: 'Verificar Grupo',
|
||||
icon: 'i-heroicons-shield-check',
|
||||
color: 'primary',
|
||||
variant: 'soft',
|
||||
size: 'lg',
|
||||
verifyBackend: false
|
||||
})
|
||||
|
||||
const { hasGroup, checkGroupBackend } = useAuthentik()
|
||||
const toast = useToast()
|
||||
const loading = ref(false)
|
||||
|
||||
const handleClick = async () => {
|
||||
loading.value = true
|
||||
|
||||
try {
|
||||
if (props.verifyBackend) {
|
||||
// Verificación backend
|
||||
const hasAccess = await checkGroupBackend(props.groupName)
|
||||
|
||||
if (hasAccess) {
|
||||
toast.add({
|
||||
title: 'Acceso Permitido (Backend)',
|
||||
description: `Perteneces al grupo: ${props.groupName}`,
|
||||
color: 'success',
|
||||
icon: 'i-heroicons-check-circle'
|
||||
})
|
||||
} else {
|
||||
toast.add({
|
||||
title: 'Acceso Denegado (Backend)',
|
||||
description: `No perteneces al grupo: ${props.groupName}`,
|
||||
color: 'error',
|
||||
icon: 'i-heroicons-x-circle'
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// Verificación frontend
|
||||
const hasAccess = hasGroup(props.groupName)
|
||||
|
||||
if (hasAccess) {
|
||||
toast.add({
|
||||
title: 'Acceso Permitido (Frontend)',
|
||||
description: `Perteneces al grupo: ${props.groupName}`,
|
||||
color: 'success',
|
||||
icon: 'i-heroicons-check-circle'
|
||||
})
|
||||
} else {
|
||||
toast.add({
|
||||
title: 'Acceso Denegado (Frontend)',
|
||||
description: `No perteneces al grupo: ${props.groupName}`,
|
||||
color: 'error',
|
||||
icon: 'i-heroicons-x-circle'
|
||||
})
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
toast.add({
|
||||
title: 'Error de Verificación',
|
||||
description: 'No se pudo verificar el grupo',
|
||||
color: 'error',
|
||||
icon: 'i-heroicons-exclamation-triangle'
|
||||
})
|
||||
console.error('Group check error:', error)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.group-check-button {
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.group-check-button:hover {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.group-check-button:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user