Fix: Eliminar componentes duplicados que causaban conflicto en el build
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
- Eliminar CataResumenMuestra.vue y CataFormularioMuestra.vue duplicados - Usar componentes existentes en components/cata/ que ya se auto-registran como CataResumenMuestra y CataFormularioMuestra - Resolver conflicto de nombres en Nuxt que impedía el build
This commit is contained in:
@@ -1,447 +0,0 @@
|
||||
<template>
|
||||
<div class="formulario-muestra cata-text p-4">
|
||||
<!-- Tab: Fragancia/Aroma -->
|
||||
<div v-if="tabActiva === 'fragancia-aroma'" class="tab-content">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<!-- Fragancia -->
|
||||
<div class="campo-grupo">
|
||||
<label class="text-sm font-semibold mb-3 block cata-text">Fragancia</label>
|
||||
<div class="flex gap-3 items-center">
|
||||
<div class="flex-1">
|
||||
<label class="text-xs opacity-75 mb-1 block">Descriptiva (1-10)</label>
|
||||
<input
|
||||
v-model.number="fraganciaDescriptiva"
|
||||
type="number"
|
||||
min="1"
|
||||
max="10"
|
||||
class="cata-input w-full"
|
||||
placeholder="1-10"
|
||||
@change="actualizarFragancia"
|
||||
>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<label class="text-xs opacity-75 mb-1 block">Afectiva (1-15)</label>
|
||||
<input
|
||||
v-model.number="fraganciaAfectiva"
|
||||
type="number"
|
||||
min="1"
|
||||
max="15"
|
||||
class="cata-input w-full"
|
||||
placeholder="1-15"
|
||||
@change="actualizarFragancia"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Aroma -->
|
||||
<div class="campo-grupo">
|
||||
<label class="text-sm font-semibold mb-3 block cata-text">Aroma</label>
|
||||
<div class="flex gap-3 items-center">
|
||||
<div class="flex-1">
|
||||
<label class="text-xs opacity-75 mb-1 block">Descriptiva (1-10)</label>
|
||||
<input
|
||||
v-model.number="aromaDescriptiva"
|
||||
type="number"
|
||||
min="1"
|
||||
max="10"
|
||||
class="cata-input w-full"
|
||||
placeholder="1-10"
|
||||
@change="actualizarAroma"
|
||||
>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<label class="text-xs opacity-75 mb-1 block">Afectiva (1-15)</label>
|
||||
<input
|
||||
v-model.number="aromaAfectiva"
|
||||
type="number"
|
||||
min="1"
|
||||
max="15"
|
||||
class="cata-input w-full"
|
||||
placeholder="1-15"
|
||||
@change="actualizarAroma"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Notas de Fragancia/Aroma -->
|
||||
<div class="mt-6">
|
||||
<label class="text-sm font-semibold mb-3 block cata-text">Notas de Fragancia/Aroma</label>
|
||||
<div class="text-xs opacity-60 mb-2">Puedes escribir tus notas libremente</div>
|
||||
<textarea
|
||||
v-model="notasFraganciaAroma"
|
||||
rows="3"
|
||||
class="cata-input w-full"
|
||||
placeholder="Describe las notas de fragancia y aroma..."
|
||||
@blur="actualizarNotasFragancia"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tab: Sabor -->
|
||||
<div v-else-if="tabActiva === 'sabor'" class="tab-content">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<!-- Sabor -->
|
||||
<div class="campo-grupo">
|
||||
<label class="text-sm font-semibold mb-3 block cata-text">Sabor</label>
|
||||
<div class="flex gap-3 items-center">
|
||||
<div class="flex-1">
|
||||
<label class="text-xs opacity-75 mb-1 block">Descriptiva (1-10)</label>
|
||||
<input
|
||||
v-model.number="saborDescriptiva"
|
||||
type="number"
|
||||
min="1"
|
||||
max="10"
|
||||
class="cata-input w-full"
|
||||
placeholder="1-10"
|
||||
@change="actualizarSabor"
|
||||
>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<label class="text-xs opacity-75 mb-1 block">Afectiva (1-15)</label>
|
||||
<input
|
||||
v-model.number="saborAfectiva"
|
||||
type="number"
|
||||
min="1"
|
||||
max="15"
|
||||
class="cata-input w-full"
|
||||
placeholder="1-15"
|
||||
@change="actualizarSabor"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sabor Residual -->
|
||||
<div class="campo-grupo">
|
||||
<label class="text-sm font-semibold mb-3 block cata-text">Sabor Residual</label>
|
||||
<div class="flex gap-3 items-center">
|
||||
<div class="flex-1">
|
||||
<label class="text-xs opacity-75 mb-1 block">Descriptiva (1-10)</label>
|
||||
<input
|
||||
v-model.number="saborResidualDescriptiva"
|
||||
type="number"
|
||||
min="1"
|
||||
max="10"
|
||||
class="cata-input w-full"
|
||||
placeholder="1-10"
|
||||
@change="actualizarSaborResidual"
|
||||
>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<label class="text-xs opacity-75 mb-1 block">Afectiva (1-15)</label>
|
||||
<input
|
||||
v-model.number="saborResidualAfectiva"
|
||||
type="number"
|
||||
min="1"
|
||||
max="15"
|
||||
class="cata-input w-full"
|
||||
placeholder="1-15"
|
||||
@change="actualizarSaborResidual"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Acidez -->
|
||||
<div class="campo-grupo">
|
||||
<label class="text-sm font-semibold mb-3 block cata-text">Acidez</label>
|
||||
<div class="flex gap-3 items-center">
|
||||
<div class="flex-1">
|
||||
<label class="text-xs opacity-75 mb-1 block">Descriptiva (1-10)</label>
|
||||
<input
|
||||
v-model.number="acidezDescriptiva"
|
||||
type="number"
|
||||
min="1"
|
||||
max="10"
|
||||
class="cata-input w-full"
|
||||
placeholder="1-10"
|
||||
@change="actualizarAcidez"
|
||||
>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<label class="text-xs opacity-75 mb-1 block">Afectiva (1-15)</label>
|
||||
<input
|
||||
v-model.number="acidezAfectiva"
|
||||
type="number"
|
||||
min="1"
|
||||
max="15"
|
||||
class="cata-input w-full"
|
||||
placeholder="1-15"
|
||||
@change="actualizarAcidez"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Dulzor -->
|
||||
<div class="campo-grupo">
|
||||
<label class="text-sm font-semibold mb-3 block cata-text">Dulzor</label>
|
||||
<div class="flex gap-3 items-center">
|
||||
<div class="flex-1">
|
||||
<label class="text-xs opacity-75 mb-1 block">Descriptiva (1-10)</label>
|
||||
<input
|
||||
v-model.number="dulzorDescriptiva"
|
||||
type="number"
|
||||
min="1"
|
||||
max="10"
|
||||
class="cata-input w-full"
|
||||
placeholder="1-10"
|
||||
@change="actualizarDulzor"
|
||||
>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<label class="text-xs opacity-75 mb-1 block">Afectiva (1-15)</label>
|
||||
<input
|
||||
v-model.number="dulzorAfectiva"
|
||||
type="number"
|
||||
min="1"
|
||||
max="15"
|
||||
class="cata-input w-full"
|
||||
placeholder="1-15"
|
||||
@change="actualizarDulzor"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Notas de Sabor -->
|
||||
<div class="mt-6">
|
||||
<label class="text-sm font-semibold mb-3 block cata-text">Notas de Sabor</label>
|
||||
<div class="text-xs opacity-60 mb-2">Puedes escribir tus notas libremente</div>
|
||||
<textarea
|
||||
v-model="notasSabor"
|
||||
rows="3"
|
||||
class="cata-input w-full"
|
||||
placeholder="Describe las notas de sabor..."
|
||||
@blur="actualizarNotasSabor"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tab: Impresión Global -->
|
||||
<div v-else-if="tabActiva === 'impresion-global'" class="tab-content">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<!-- Sensación en Boca -->
|
||||
<div class="campo-grupo">
|
||||
<label class="text-sm font-semibold mb-3 block cata-text">Sensación en Boca</label>
|
||||
<div class="flex gap-3 items-center">
|
||||
<div class="flex-1">
|
||||
<label class="text-xs opacity-75 mb-1 block">Descriptiva (1-10)</label>
|
||||
<input
|
||||
v-model.number="sensacionBocaDescriptiva"
|
||||
type="number"
|
||||
min="1"
|
||||
max="10"
|
||||
class="cata-input w-full"
|
||||
placeholder="1-10"
|
||||
@change="actualizarSensacionBoca"
|
||||
>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<label class="text-xs opacity-75 mb-1 block">Afectiva (1-15)</label>
|
||||
<input
|
||||
v-model.number="sensacionBocaAfectiva"
|
||||
type="number"
|
||||
min="1"
|
||||
max="15"
|
||||
class="cata-input w-full"
|
||||
placeholder="1-15"
|
||||
@change="actualizarSensacionBoca"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Impresión Global -->
|
||||
<div class="campo-grupo">
|
||||
<label class="text-sm font-semibold mb-3 block cata-text">Impresión Global</label>
|
||||
<div class="flex gap-3 items-center">
|
||||
<div class="flex-1">
|
||||
<label class="text-xs opacity-75 mb-1 block">Descriptiva (1-10)</label>
|
||||
<input
|
||||
v-model.number="impresionGlobalDescriptiva"
|
||||
type="number"
|
||||
min="1"
|
||||
max="10"
|
||||
class="cata-input w-full"
|
||||
placeholder="1-10"
|
||||
@change="actualizarImpresionGlobal"
|
||||
>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<label class="text-xs opacity-75 mb-1 block">Afectiva (1-15)</label>
|
||||
<input
|
||||
v-model.number="impresionGlobalAfectiva"
|
||||
type="number"
|
||||
min="1"
|
||||
max="15"
|
||||
class="cata-input w-full"
|
||||
placeholder="1-15"
|
||||
@change="actualizarImpresionGlobal"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Notas Adicionales -->
|
||||
<div class="mt-6">
|
||||
<label class="text-sm font-semibold mb-3 block cata-text">Notas Adicionales</label>
|
||||
<div class="text-xs opacity-60 mb-2">Observaciones generales sobre la muestra</div>
|
||||
<textarea
|
||||
v-model="otrasNotas"
|
||||
rows="4"
|
||||
class="cata-input w-full"
|
||||
placeholder="Escribe tus observaciones generales..."
|
||||
@blur="actualizarOtrasNotas"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { Muestra } from '~/types/catacion'
|
||||
import type { TabCatacion } from '~/composables/useCatacion'
|
||||
|
||||
const props = defineProps<{
|
||||
muestra: Muestra
|
||||
tabActiva: TabCatacion
|
||||
}>()
|
||||
|
||||
const { actualizarIntensidad, actualizarFraganciaAroma, actualizarSabor, actualizarOtrasNotas: actualizarOtrasNotasComposable } = useCatacion()
|
||||
|
||||
// Valores reactivos para Fragancia
|
||||
const fraganciaDescriptiva = ref(props.muestra.intensidades.fragancia.descriptiva)
|
||||
const fraganciaAfectiva = ref(props.muestra.intensidades.fragancia.afectiva)
|
||||
const aromaDescriptiva = ref(props.muestra.intensidades.aroma.descriptiva)
|
||||
const aromaAfectiva = ref(props.muestra.intensidades.aroma.afectiva)
|
||||
|
||||
// Valores reactivos para Sabor
|
||||
const saborDescriptiva = ref(props.muestra.intensidades.sabor.descriptiva)
|
||||
const saborAfectiva = ref(props.muestra.intensidades.sabor.afectiva)
|
||||
const saborResidualDescriptiva = ref(props.muestra.intensidades.saborResidual.descriptiva)
|
||||
const saborResidualAfectiva = ref(props.muestra.intensidades.saborResidual.afectiva)
|
||||
const acidezDescriptiva = ref(props.muestra.intensidades.acidez.descriptiva)
|
||||
const acidezAfectiva = ref(props.muestra.intensidades.acidez.afectiva)
|
||||
const dulzorDescriptiva = ref(props.muestra.intensidades.dulzor.descriptiva)
|
||||
const dulzorAfectiva = ref(props.muestra.intensidades.dulzor.afectiva)
|
||||
|
||||
// Valores reactivos para Impresión Global
|
||||
const sensacionBocaDescriptiva = ref(props.muestra.intensidades.sensacionBoca.descriptiva)
|
||||
const sensacionBocaAfectiva = ref(props.muestra.intensidades.sensacionBoca.afectiva)
|
||||
const impresionGlobalDescriptiva = ref(props.muestra.intensidades.impresionGlobal.descriptiva)
|
||||
const impresionGlobalAfectiva = ref(props.muestra.intensidades.impresionGlobal.afectiva)
|
||||
|
||||
// Notas de texto
|
||||
const notasFraganciaAroma = ref(props.muestra.fraganciaAromaNotas.notaEspecifica || '')
|
||||
const notasSabor = ref(props.muestra.saborNotas.notaEspecifica || '')
|
||||
const otrasNotas = ref(props.muestra.otrasNotas)
|
||||
|
||||
// Actualizar cuando cambie la prop
|
||||
watch(() => props.muestra, (nuevaMuestra) => {
|
||||
fraganciaDescriptiva.value = nuevaMuestra.intensidades.fragancia.descriptiva
|
||||
fraganciaAfectiva.value = nuevaMuestra.intensidades.fragancia.afectiva
|
||||
aromaDescriptiva.value = nuevaMuestra.intensidades.aroma.descriptiva
|
||||
aromaAfectiva.value = nuevaMuestra.intensidades.aroma.afectiva
|
||||
|
||||
saborDescriptiva.value = nuevaMuestra.intensidades.sabor.descriptiva
|
||||
saborAfectiva.value = nuevaMuestra.intensidades.sabor.afectiva
|
||||
saborResidualDescriptiva.value = nuevaMuestra.intensidades.saborResidual.descriptiva
|
||||
saborResidualAfectiva.value = nuevaMuestra.intensidades.saborResidual.afectiva
|
||||
acidezDescriptiva.value = nuevaMuestra.intensidades.acidez.descriptiva
|
||||
acidezAfectiva.value = nuevaMuestra.intensidades.acidez.afectiva
|
||||
dulzorDescriptiva.value = nuevaMuestra.intensidades.dulzor.descriptiva
|
||||
dulzorAfectiva.value = nuevaMuestra.intensidades.dulzor.afectiva
|
||||
|
||||
sensacionBocaDescriptiva.value = nuevaMuestra.intensidades.sensacionBoca.descriptiva
|
||||
sensacionBocaAfectiva.value = nuevaMuestra.intensidades.sensacionBoca.afectiva
|
||||
impresionGlobalDescriptiva.value = nuevaMuestra.intensidades.impresionGlobal.descriptiva
|
||||
impresionGlobalAfectiva.value = nuevaMuestra.intensidades.impresionGlobal.afectiva
|
||||
|
||||
notasFraganciaAroma.value = nuevaMuestra.fraganciaAromaNotas.notaEspecifica || ''
|
||||
notasSabor.value = nuevaMuestra.saborNotas.notaEspecifica || ''
|
||||
otrasNotas.value = nuevaMuestra.otrasNotas
|
||||
}, { deep: true })
|
||||
|
||||
// Métodos de actualización
|
||||
const actualizarFragancia = async () => {
|
||||
await actualizarIntensidad(props.muestra.muestraId, 'fragancia', 'descriptiva', fraganciaDescriptiva.value)
|
||||
await actualizarIntensidad(props.muestra.muestraId, 'fragancia', 'afectiva', fraganciaAfectiva.value)
|
||||
}
|
||||
|
||||
const actualizarAroma = async () => {
|
||||
await actualizarIntensidad(props.muestra.muestraId, 'aroma', 'descriptiva', aromaDescriptiva.value)
|
||||
await actualizarIntensidad(props.muestra.muestraId, 'aroma', 'afectiva', aromaAfectiva.value)
|
||||
}
|
||||
|
||||
const actualizarSabor = async () => {
|
||||
await actualizarIntensidad(props.muestra.muestraId, 'sabor', 'descriptiva', saborDescriptiva.value)
|
||||
await actualizarIntensidad(props.muestra.muestraId, 'sabor', 'afectiva', saborAfectiva.value)
|
||||
}
|
||||
|
||||
const actualizarSaborResidual = async () => {
|
||||
await actualizarIntensidad(props.muestra.muestraId, 'saborResidual', 'descriptiva', saborResidualDescriptiva.value)
|
||||
await actualizarIntensidad(props.muestra.muestraId, 'saborResidual', 'afectiva', saborResidualAfectiva.value)
|
||||
}
|
||||
|
||||
const actualizarAcidez = async () => {
|
||||
await actualizarIntensidad(props.muestra.muestraId, 'acidez', 'descriptiva', acidezDescriptiva.value)
|
||||
await actualizarIntensidad(props.muestra.muestraId, 'acidez', 'afectiva', acidezAfectiva.value)
|
||||
}
|
||||
|
||||
const actualizarDulzor = async () => {
|
||||
await actualizarIntensidad(props.muestra.muestraId, 'dulzor', 'descriptiva', dulzorDescriptiva.value)
|
||||
await actualizarIntensidad(props.muestra.muestraId, 'dulzor', 'afectiva', dulzorAfectiva.value)
|
||||
}
|
||||
|
||||
const actualizarSensacionBoca = async () => {
|
||||
await actualizarIntensidad(props.muestra.muestraId, 'sensacionBoca', 'descriptiva', sensacionBocaDescriptiva.value)
|
||||
await actualizarIntensidad(props.muestra.muestraId, 'sensacionBoca', 'afectiva', sensacionBocaAfectiva.value)
|
||||
}
|
||||
|
||||
const actualizarImpresionGlobal = async () => {
|
||||
await actualizarIntensidad(props.muestra.muestraId, 'impresionGlobal', 'descriptiva', impresionGlobalDescriptiva.value)
|
||||
await actualizarIntensidad(props.muestra.muestraId, 'impresionGlobal', 'afectiva', impresionGlobalAfectiva.value)
|
||||
}
|
||||
|
||||
const actualizarNotasFragancia = async () => {
|
||||
await actualizarFraganciaAroma(props.muestra.muestraId, null, null, notasFraganciaAroma.value)
|
||||
}
|
||||
|
||||
const actualizarNotasSabor = async () => {
|
||||
await actualizarSabor(props.muestra.muestraId, null, null, notasSabor.value)
|
||||
}
|
||||
|
||||
const actualizarOtrasNotas = async () => {
|
||||
await actualizarOtrasNotasComposable(props.muestra.muestraId, otrasNotas.value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.campo-grupo {
|
||||
padding: 1rem;
|
||||
border-radius: 0.5rem;
|
||||
border: 1px solid color-mix(in srgb, var(--cata-primary) 20%, transparent);
|
||||
background: color-mix(in srgb, var(--cata-primary) 5%, transparent);
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
animation: fadeIn 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,132 +0,0 @@
|
||||
<template>
|
||||
<div class="resumen-muestra flex items-center justify-between gap-4 w-full">
|
||||
<!-- Información básica -->
|
||||
<div class="flex items-center gap-3 flex-1 min-w-0">
|
||||
<div class="muestra-numero cata-text font-bold text-lg">
|
||||
#{{ muestra.muestraId }}
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="muestra-nombre cata-text font-semibold truncate">
|
||||
{{ muestra.nombre }}
|
||||
</div>
|
||||
<div class="muestra-stats text-xs cata-text opacity-60 flex items-center gap-2">
|
||||
<span>Puntaje {{ muestra.puntajeFinal }}</span>
|
||||
<span class="opacity-40">•</span>
|
||||
<span>{{ porcentajeCompletitud }}% completado</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Indicadores de completitud -->
|
||||
<div class="muestra-indicadores flex items-center gap-2 text-xs">
|
||||
<!-- Fragancia/Aroma -->
|
||||
<div
|
||||
:class="[
|
||||
'indicador-badge px-2 py-1 rounded',
|
||||
tieneFraganciaAroma ? 'bg-success/20 text-success' : 'bg-muted/20 text-muted',
|
||||
]"
|
||||
title="Fragancia/Aroma"
|
||||
>
|
||||
<span class="hidden sm:inline">F:</span>
|
||||
{{ intensidadesFormatted.fragancia }}/{{ intensidadesFormatted.aroma }}
|
||||
</div>
|
||||
|
||||
<!-- Sabor -->
|
||||
<div
|
||||
:class="[
|
||||
'indicador-badge px-2 py-1 rounded',
|
||||
tieneSabor ? 'bg-success/20 text-success' : 'bg-muted/20 text-muted',
|
||||
]"
|
||||
title="Sabor"
|
||||
>
|
||||
<span class="hidden sm:inline">S:</span>
|
||||
{{ intensidadesFormatted.sabor }}/{{ intensidadesFormatted.saborResidual }}
|
||||
</div>
|
||||
|
||||
<!-- Acidez -->
|
||||
<div
|
||||
:class="[
|
||||
'indicador-badge px-2 py-1 rounded',
|
||||
tieneAcidez ? 'bg-success/20 text-success' : 'bg-muted/20 text-muted',
|
||||
]"
|
||||
title="Acidez"
|
||||
>
|
||||
<span class="hidden sm:inline">Ac:</span>
|
||||
{{ intensidadesFormatted.acidez }}/{{ intensidadesFormatted.dulzor }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Barra de progreso -->
|
||||
<div class="progreso-container hidden md:block w-24">
|
||||
<div class="progreso-bg h-2 rounded-full bg-muted/20 overflow-hidden">
|
||||
<div
|
||||
class="progreso-fill h-full bg-primary transition-all"
|
||||
:style="{ width: `${porcentajeCompletitud}%` }"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { Muestra } from '~/types/catacion'
|
||||
|
||||
const props = defineProps<{
|
||||
muestra: Muestra
|
||||
porcentajeCompletitud: number
|
||||
}>()
|
||||
|
||||
// Formatear intensidades para mostrar
|
||||
const intensidadesFormatted = computed(() => ({
|
||||
fragancia: props.muestra.intensidades.fragancia.afectiva ?? '-',
|
||||
aroma: props.muestra.intensidades.aroma.afectiva ?? '-',
|
||||
sabor: props.muestra.intensidades.sabor.afectiva ?? '-',
|
||||
saborResidual: props.muestra.intensidades.saborResidual.afectiva ?? '-',
|
||||
acidez: props.muestra.intensidades.acidez.afectiva ?? '-',
|
||||
dulzor: props.muestra.intensidades.dulzor.afectiva ?? '-',
|
||||
}))
|
||||
|
||||
// Verificar si las secciones están completas
|
||||
const tieneFraganciaAroma = computed(() =>
|
||||
props.muestra.intensidades.fragancia.afectiva !== null &&
|
||||
props.muestra.intensidades.aroma.afectiva !== null
|
||||
)
|
||||
|
||||
const tieneSabor = computed(() =>
|
||||
props.muestra.intensidades.sabor.afectiva !== null &&
|
||||
props.muestra.intensidades.saborResidual.afectiva !== null
|
||||
)
|
||||
|
||||
const tieneAcidez = computed(() =>
|
||||
props.muestra.intensidades.acidez.afectiva !== null &&
|
||||
props.muestra.intensidades.dulzor.afectiva !== null
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.resumen-muestra {
|
||||
min-height: 60px;
|
||||
}
|
||||
|
||||
.muestra-numero {
|
||||
font-size: 1.25rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.indicador-badge {
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.muestra-indicadores {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.indicador-badge {
|
||||
font-size: 0.625rem;
|
||||
padding: 0.25rem 0.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -2,12 +2,16 @@
|
||||
<div v-if="user" class="cata-user-info">
|
||||
<div class="cata-outline-box rounded-lg p-4">
|
||||
<div class="flex items-center gap-3">
|
||||
<!-- Avatar simple con inicial -->
|
||||
<div class="user-avatar cata-outline-box">
|
||||
<!-- Avatar clickeable para verificar sesión -->
|
||||
<button
|
||||
class="user-avatar cata-outline-box cursor-pointer transition-all hover:scale-105 active:scale-95"
|
||||
@click="handleCheckSession"
|
||||
title="Verificar estado de sesión"
|
||||
>
|
||||
<span class="cata-text text-xl font-semibold">
|
||||
{{ userInitial }}
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<!-- Info del usuario -->
|
||||
<div class="flex-1 min-w-0">
|
||||
@@ -19,21 +23,46 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Botón de logout compacto -->
|
||||
<button
|
||||
class="cata-button p-2 flex-shrink-0"
|
||||
@click="handleLogout"
|
||||
title="Cerrar sesión"
|
||||
>
|
||||
<UIcon name="i-lucide-log-out" class="w-4 h-4" />
|
||||
</button>
|
||||
<!-- Botones de acción -->
|
||||
<div class="flex items-center gap-2">
|
||||
<!-- Botón de cambio de tema -->
|
||||
<button
|
||||
class="cata-button p-2 flex items-center justify-center flex-shrink-0"
|
||||
@click="toggleTheme"
|
||||
:title="isDark ? 'Cambiar a modo claro' : 'Cambiar a modo oscuro'"
|
||||
>
|
||||
<UIcon :name="isDark ? 'i-lucide-sun' : 'i-lucide-moon'" class="w-4 h-4" />
|
||||
</button>
|
||||
|
||||
<!-- Botón de home -->
|
||||
<button
|
||||
class="cata-button p-2 flex items-center justify-center flex-shrink-0"
|
||||
@click="goToHome"
|
||||
title="Ir al inicio del ecosistema Nucleo"
|
||||
>
|
||||
<UIcon name="i-lucide-home" class="w-4 h-4" />
|
||||
</button>
|
||||
|
||||
<!-- Botón de logout -->
|
||||
<button
|
||||
class="cata-button p-2 flex items-center justify-center flex-shrink-0"
|
||||
@click="handleLogout"
|
||||
title="Cerrar sesión"
|
||||
>
|
||||
<UIcon name="i-lucide-log-out" class="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const { user } = useAuthentik()
|
||||
const { user, checkSessionStatus } = useAuthentik()
|
||||
const colorMode = useColorMode()
|
||||
|
||||
// Estado del tema
|
||||
const isDark = computed(() => colorMode.value === 'dark')
|
||||
|
||||
// Obtener la inicial del usuario
|
||||
const userInitial = computed(() => {
|
||||
@@ -42,6 +71,21 @@ const userInitial = computed(() => {
|
||||
return name.charAt(0).toUpperCase()
|
||||
})
|
||||
|
||||
// Cambiar tema
|
||||
const toggleTheme = () => {
|
||||
colorMode.preference = isDark.value ? 'light' : 'dark'
|
||||
}
|
||||
|
||||
// Ir al home del ecosistema
|
||||
const goToHome = () => {
|
||||
window.open('https://inicio.nucleoriofrio.com', '_blank')
|
||||
}
|
||||
|
||||
// Verificar estado de sesión
|
||||
const handleCheckSession = async () => {
|
||||
await checkSessionStatus()
|
||||
}
|
||||
|
||||
// Manejar logout
|
||||
const handleLogout = () => {
|
||||
// Redirigir al endpoint de logout de Authentik
|
||||
@@ -63,6 +107,7 @@ const handleLogout = () => {
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
background-color: color-mix(in srgb, var(--cata-primary) 5%, transparent);
|
||||
border: none;
|
||||
}
|
||||
|
||||
.dark .user-avatar {
|
||||
@@ -70,6 +115,15 @@ const handleLogout = () => {
|
||||
box-shadow: 0 0 8px color-mix(in srgb, var(--cata-primary) 20%, transparent);
|
||||
}
|
||||
|
||||
.user-avatar:hover {
|
||||
background-color: color-mix(in srgb, var(--cata-primary) 10%, transparent);
|
||||
}
|
||||
|
||||
.dark .user-avatar:hover {
|
||||
background-color: color-mix(in srgb, var(--cata-primary) 15%, transparent);
|
||||
box-shadow: 0 0 12px color-mix(in srgb, var(--cata-primary) 30%, transparent);
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 640px) {
|
||||
.user-avatar {
|
||||
|
||||
Reference in New Issue
Block a user