All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m10s
629 lines
20 KiB
Vue
629 lines
20 KiB
Vue
<template>
|
||
<UModal
|
||
v-model:open="isOpen"
|
||
:dismissible="false"
|
||
:ui="{
|
||
overlay: 'modal-overlay',
|
||
content: 'cata-bg cata-outline-box',
|
||
header: 'cata-bg',
|
||
body: 'cata-bg',
|
||
footer: 'cata-bg',
|
||
title: 'cata-text'
|
||
}"
|
||
>
|
||
<!-- Trigger (slot por defecto) -->
|
||
<slot />
|
||
|
||
<!-- Título personalizado -->
|
||
<template #title>
|
||
<span class="cata-text">{{ tituloModal }}</span>
|
||
</template>
|
||
|
||
<!-- Contenido del modal -->
|
||
<template #body>
|
||
<div class="space-y-4">
|
||
<!-- Paso 1: Ingresar puntaje total deseado -->
|
||
<div v-if="paso === 1" class="space-y-3">
|
||
<!-- Input de Sumatoria Afectiva -->
|
||
<div>
|
||
<label class="block text-xs cata-text opacity-75 mb-1 text-center">
|
||
Sumatoria Afectiva
|
||
</label>
|
||
<UInputNumber
|
||
v-model="puntajeDeseado"
|
||
:min="8"
|
||
:max="72"
|
||
:step="1"
|
||
placeholder="8-72"
|
||
class="w-full cata-input-number"
|
||
variant="outline"
|
||
:ui="{
|
||
base: 'cata-input text-center text-lg',
|
||
}"
|
||
@update:model-value="onSumatoriaChangeFromButtons"
|
||
@blur="onSumatoriaBlur"
|
||
/>
|
||
</div>
|
||
|
||
<!-- Input de SCAA Score -->
|
||
<div>
|
||
<label class="block text-xs cata-text opacity-75 mb-1 text-center">
|
||
SCAA Score
|
||
</label>
|
||
<UInputNumber
|
||
v-model="scaaDeseado"
|
||
:min="scaaMin"
|
||
:max="scaaMax"
|
||
:step="0.25"
|
||
placeholder="58.00-100.00"
|
||
class="w-full cata-input-number"
|
||
variant="outline"
|
||
:ui="{
|
||
base: 'cata-input text-center text-lg',
|
||
}"
|
||
:format-options="{ minimumFractionDigits: 2, maximumFractionDigits: 2 }"
|
||
@update:model-value="onScaaChangeFromButtons"
|
||
@blur="onScaaBlur"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Paso 2: Seleccionar categorías que sobresalen o palidecen -->
|
||
<div v-if="paso === 2">
|
||
<!-- Subtítulo con icono y contador -->
|
||
<div class="flex items-center gap-2 mb-3 cata-text font-medium">
|
||
<UIcon
|
||
:name="multiploMasCercano < puntajeDeseado ? 'i-heroicons-arrow-up-circle' : 'i-heroicons-arrow-down-circle'"
|
||
class="w-5 h-5"
|
||
:style="{ color: 'var(--cata-primary)' }"
|
||
/>
|
||
<span>{{ multiploMasCercano < puntajeDeseado ? 'Sobresale' : 'Palidece' }}</span>
|
||
<span class="ml-auto opacity-60">{{ categoriasSeleccionadas.length }}/{{ diferencia }}</span>
|
||
</div>
|
||
|
||
<div class="space-y-2">
|
||
<button
|
||
v-for="cat in categoriasDisponibles"
|
||
:key="cat.key"
|
||
type="button"
|
||
:class="[
|
||
'w-full px-3 py-2 rounded-md transition-all text-left flex items-center gap-2',
|
||
'cata-outline-box',
|
||
categoriasSeleccionadas.includes(cat.key)
|
||
? 'selected-category'
|
||
: ''
|
||
]"
|
||
:disabled="!categoriasSeleccionadas.includes(cat.key) && categoriasSeleccionadas.length >= diferencia"
|
||
@click="toggleCategoria(cat.key)"
|
||
>
|
||
<UIcon :name="cat.icon" class="w-4 h-4" :style="{ color: cat.color }" />
|
||
<span class="cata-text">{{ cat.label }}</span>
|
||
<UIcon
|
||
v-if="categoriasSeleccionadas.includes(cat.key)"
|
||
:name="multiploMasCercano < puntajeDeseado ? 'i-heroicons-arrow-up-circle-solid' : 'i-heroicons-arrow-down-circle-solid'"
|
||
class="w-5 h-5 ml-auto"
|
||
:style="{ color: cat.color }"
|
||
/>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Paso 3: Vista previa con ResumenMuestra (solo en modo calculadora) -->
|
||
<div v-if="paso === 3">
|
||
<div class="space-y-4">
|
||
<!-- Inputs de penalizaciones -->
|
||
<div class="grid grid-cols-2 gap-3">
|
||
<div>
|
||
<label class="block text-xs cata-text opacity-75 mb-1">
|
||
Tazas No Uniformes
|
||
</label>
|
||
<UInputNumber
|
||
v-model="tazasNoUniformes"
|
||
:min="0"
|
||
:max="5"
|
||
:step="1"
|
||
placeholder="0-5"
|
||
class="w-full cata-input-number"
|
||
variant="outline"
|
||
:ui="{
|
||
base: 'cata-input text-center',
|
||
}"
|
||
/>
|
||
<p class="text-xs cata-text opacity-60 mt-1 text-center">
|
||
-2 puntos cada una
|
||
</p>
|
||
</div>
|
||
|
||
<div>
|
||
<label class="block text-xs cata-text opacity-75 mb-1">
|
||
Tazas Defectuosas
|
||
</label>
|
||
<UInputNumber
|
||
v-model="tazasDefectuosas"
|
||
:min="0"
|
||
:max="5"
|
||
:step="1"
|
||
placeholder="0-5"
|
||
class="w-full cata-input-number"
|
||
variant="outline"
|
||
:ui="{
|
||
base: 'cata-input text-center',
|
||
}"
|
||
/>
|
||
<p class="text-xs cata-text opacity-60 mt-1 text-center">
|
||
-4 puntos cada una
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Resumen de la muestra expandido -->
|
||
<div class="mt-4">
|
||
<CataResumenMuestraExpandido :muestra="muestraGenerica" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<!-- Footer con botones -->
|
||
<template #footer>
|
||
<div class="flex items-center justify-between w-full">
|
||
<!-- Puntaje target a la izquierda -->
|
||
<div v-if="paso === 2 || paso === 3" class="flex items-center gap-2 cata-text font-semibold">
|
||
<UIcon name="i-lucide-target" class="w-5 h-5" :style="{ color: 'var(--cata-primary)' }" />
|
||
<span>Σ {{ puntajeDeseado }}</span>
|
||
</div>
|
||
<div v-else></div>
|
||
|
||
<!-- Botones a la derecha -->
|
||
<div class="flex items-center gap-2">
|
||
<!-- Botón Volver (pasos 2 y 3) -->
|
||
<button
|
||
v-if="paso === 2 || paso === 3"
|
||
class="cata-button px-4 py-2"
|
||
@click="pasoAnterior"
|
||
>
|
||
Volver
|
||
</button>
|
||
|
||
<!-- Botón Cancelar (solo paso 1) -->
|
||
<button
|
||
v-if="paso === 1"
|
||
class="cata-button px-4 py-2"
|
||
@click="cerrar"
|
||
>
|
||
Cancelar
|
||
</button>
|
||
|
||
<!-- Botón Continuar (paso 1) -->
|
||
<button
|
||
v-if="paso === 1"
|
||
class="cata-button px-4 py-2"
|
||
:disabled="!puntajeValido"
|
||
:class="{ 'opacity-50 cursor-not-allowed': !puntajeValido }"
|
||
@click="siguientePaso"
|
||
>
|
||
Continuar
|
||
</button>
|
||
|
||
<!-- Botón Aplicar/Continuar (paso 2) -->
|
||
<button
|
||
v-if="paso === 2"
|
||
class="cata-button px-4 py-2"
|
||
:disabled="categoriasSeleccionadas.length !== diferencia"
|
||
:class="{ 'opacity-50 cursor-not-allowed': categoriasSeleccionadas.length !== diferencia }"
|
||
@click="siguientePasoOAplicar"
|
||
>
|
||
{{ modo === 'calculadora' ? 'Continuar' : 'Aplicar' }}
|
||
</button>
|
||
|
||
<!-- Botón Cerrar (paso 3 - solo modo calculadora) -->
|
||
<button
|
||
v-if="paso === 3"
|
||
class="cata-button px-4 py-2"
|
||
@click="cerrar"
|
||
>
|
||
Cerrar
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
</UModal>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import type { Muestra, IntensidadValor } from '~/types/catacion'
|
||
import { scaaASumatoriaAfectiva, sumatoriaAfectivaASCAA, redondearA025 } from '~/types/catacion'
|
||
|
||
interface Props {
|
||
modelValue: boolean
|
||
muestra?: Muestra
|
||
modo?: 'calculadora' | 'asignacion'
|
||
}
|
||
|
||
const props = withDefaults(defineProps<Props>(), {
|
||
modo: 'asignacion',
|
||
})
|
||
|
||
const emit = defineEmits<{
|
||
'update:modelValue': [value: boolean]
|
||
'aplicar': [puntajes: Record<string, number>]
|
||
}>()
|
||
|
||
// Categorías disponibles
|
||
const categoriasDisponibles = [
|
||
{ key: 'fragancia', label: 'Fragancia', icon: 'i-lucide-flower-2', color: '#8B7AB8' },
|
||
{ key: 'aroma', label: 'Aroma', icon: 'i-lucide-wind', color: '#26A69A' },
|
||
{ key: 'sabor', label: 'Sabor', icon: 'i-lucide-candy', color: '#E53935' },
|
||
{ key: 'saborResidual', label: 'Sabor Residual', icon: 'i-lucide-timer', color: '#F57C00' },
|
||
{ key: 'acidez', label: 'Acidez', icon: 'i-lucide-citrus', color: '#FDD835' },
|
||
{ key: 'dulzor', label: 'Dulzor', icon: 'i-lucide-cookie', color: '#EC407A' },
|
||
{ key: 'sensacionBoca', label: 'Sensación en Boca', icon: 'i-lucide-droplets', color: '#1E88E5' },
|
||
{ key: 'impresionGlobal', label: 'Impresión Global', icon: 'i-lucide-star', color: '#00ACC1' },
|
||
]
|
||
|
||
// Estado del modal
|
||
const isOpen = computed({
|
||
get: () => props.modelValue,
|
||
set: (value) => emit('update:modelValue', value),
|
||
})
|
||
|
||
// Estado del formulario
|
||
const paso = ref(1)
|
||
const puntajeDeseado = ref<number>(40)
|
||
const scaaDeseado = ref<number>(sumatoriaAfectivaASCAA(40))
|
||
const categoriasSeleccionadas = ref<string[]>([])
|
||
|
||
// Estado de penalizaciones (paso 3)
|
||
const tazasNoUniformes = ref<number>(0)
|
||
const tazasDefectuosas = ref<number>(0)
|
||
|
||
// Flag para evitar loops infinitos en la sincronización
|
||
const actualizandoInput = ref(false)
|
||
|
||
// Título del modal según el modo
|
||
const tituloModal = computed(() => {
|
||
return props.modo === 'calculadora' ? 'Calculadora SCAA Score' : 'Asignación Rápida de Puntajes'
|
||
})
|
||
|
||
// Límites de SCAA Score (basados en sumatoria afectiva 8-72)
|
||
// 8 categorías × 1 punto mínimo = 8
|
||
// 8 categorías × 9 puntos máximo = 72
|
||
const scaaMin = sumatoriaAfectivaASCAA(8)
|
||
const scaaMax = sumatoriaAfectivaASCAA(72)
|
||
|
||
// Resetear estado cuando el modal se abre
|
||
watch(isOpen, (newValue) => {
|
||
if (newValue) {
|
||
paso.value = 1
|
||
puntajeDeseado.value = 40
|
||
scaaDeseado.value = sumatoriaAfectivaASCAA(40)
|
||
categoriasSeleccionadas.value = []
|
||
tazasNoUniformes.value = 0
|
||
tazasDefectuosas.value = 0
|
||
}
|
||
})
|
||
|
||
// Crear muestra genérica para vista previa (modo calculadora)
|
||
const muestraGenerica = computed<Muestra>(() => {
|
||
// Primero calculamos los puntajes afectivos
|
||
const puntajes: Record<string, number> = {}
|
||
const puntajeBase = multiploMasCercano.value / 8
|
||
const ajuste = multiploMasCercano.value < puntajeDeseado.value ? 1 : -1
|
||
|
||
categoriasDisponibles.forEach(cat => {
|
||
const esSeleccionada = categoriasSeleccionadas.value.includes(cat.key)
|
||
puntajes[cat.key] = puntajeBase + (esSeleccionada ? ajuste : 0)
|
||
})
|
||
|
||
// Crear objeto de intensidades
|
||
const intensidades: Muestra['intensidades'] = {
|
||
fragancia: { descriptiva: null, afectiva: puntajes.fragancia || puntajeBase },
|
||
aroma: { descriptiva: null, afectiva: puntajes.aroma || puntajeBase },
|
||
sabor: { descriptiva: null, afectiva: puntajes.sabor || puntajeBase },
|
||
saborResidual: { descriptiva: null, afectiva: puntajes.saborResidual || puntajeBase },
|
||
acidez: { descriptiva: null, afectiva: puntajes.acidez || puntajeBase },
|
||
dulzor: { descriptiva: null, afectiva: puntajes.dulzor || puntajeBase },
|
||
sensacionBoca: { descriptiva: null, afectiva: puntajes.sensacionBoca || puntajeBase },
|
||
impresionGlobal: { descriptiva: null, afectiva: puntajes.impresionGlobal || puntajeBase },
|
||
}
|
||
|
||
// Crear arrays de tazas con defectos según las cantidades
|
||
const tazasNoUniformesArray: number[] = []
|
||
const tazasDefectuosasArray: number[] = []
|
||
|
||
for (let i = 1; i <= tazasNoUniformes.value; i++) {
|
||
tazasNoUniformesArray.push(i)
|
||
}
|
||
|
||
for (let i = 1; i <= tazasDefectuosas.value; i++) {
|
||
tazasDefectuosasArray.push(i)
|
||
}
|
||
|
||
return {
|
||
muestraId: 1,
|
||
nombre: 'Muestra de Ejemplo',
|
||
intensidades,
|
||
fraganciaAromaNotas: { categorias: [], subcategorias: [], notaEspecifica: null },
|
||
saborNotas: { categorias: [], subcategorias: [], notaEspecifica: null },
|
||
tazasNoUniformes: tazasNoUniformesArray,
|
||
tazasDefectuosas: tazasDefectuosasArray,
|
||
defecto: null,
|
||
sensacionEnBoca: null,
|
||
gustosPredominantes: [],
|
||
otrasNotas: '',
|
||
puntajeFinal: 0,
|
||
}
|
||
})
|
||
|
||
// Handler para cuando se modifica Sumatoria Afectiva usando botones +/-
|
||
const onSumatoriaChangeFromButtons = (newValue: number | null) => {
|
||
if (actualizandoInput.value) return
|
||
if (newValue === null || newValue === undefined) return
|
||
|
||
actualizandoInput.value = true
|
||
|
||
// El valor ya viene validado por UInputNumber (min/max/step)
|
||
puntajeDeseado.value = newValue
|
||
|
||
// Actualizar SCAA Score automáticamente
|
||
scaaDeseado.value = sumatoriaAfectivaASCAA(puntajeDeseado.value)
|
||
|
||
actualizandoInput.value = false
|
||
}
|
||
|
||
// Handler para cuando se pierde el foco en Sumatoria Afectiva (escritura manual)
|
||
const onSumatoriaBlur = () => {
|
||
if (actualizandoInput.value) return
|
||
|
||
actualizandoInput.value = true
|
||
|
||
// Si el valor es inválido (NaN, null, undefined), resetear a default
|
||
if (!puntajeDeseado.value || isNaN(puntajeDeseado.value)) {
|
||
puntajeDeseado.value = 40
|
||
}
|
||
|
||
// Redondear a entero
|
||
puntajeDeseado.value = Math.round(puntajeDeseado.value)
|
||
|
||
// Validar rango (solo después de redondear)
|
||
if (puntajeDeseado.value < 8) puntajeDeseado.value = 8
|
||
if (puntajeDeseado.value > 72) puntajeDeseado.value = 72
|
||
|
||
// Actualizar SCAA Score
|
||
scaaDeseado.value = sumatoriaAfectivaASCAA(puntajeDeseado.value)
|
||
|
||
actualizandoInput.value = false
|
||
}
|
||
|
||
// Handler para cuando se modifica SCAA Score usando botones +/-
|
||
const onScaaChangeFromButtons = (newValue: number | null) => {
|
||
if (actualizandoInput.value) return
|
||
if (newValue === null || newValue === undefined) return
|
||
|
||
actualizandoInput.value = true
|
||
|
||
// El valor ya viene validado por UInputNumber (min/max/step)
|
||
scaaDeseado.value = newValue
|
||
|
||
// Convertir a Sumatoria Afectiva
|
||
const sumatoriaCalculada = scaaASumatoriaAfectiva(scaaDeseado.value)
|
||
|
||
// Redondear al entero más cercano
|
||
const sumatoriaRedondeada = Math.round(sumatoriaCalculada)
|
||
|
||
// Asegurar rango válido
|
||
puntajeDeseado.value = Math.max(8, Math.min(72, sumatoriaRedondeada))
|
||
|
||
// Recalcular SCAA Score con el valor redondeado
|
||
scaaDeseado.value = sumatoriaAfectivaASCAA(puntajeDeseado.value)
|
||
|
||
actualizandoInput.value = false
|
||
}
|
||
|
||
// Handler para cuando se pierde el foco en SCAA Score (escritura manual)
|
||
const onScaaBlur = () => {
|
||
if (actualizandoInput.value) return
|
||
|
||
actualizandoInput.value = true
|
||
|
||
// Si el valor es inválido (NaN, null, undefined), resetear a default
|
||
if (!scaaDeseado.value || isNaN(scaaDeseado.value)) {
|
||
scaaDeseado.value = sumatoriaAfectivaASCAA(40)
|
||
}
|
||
|
||
// Redondear al múltiplo de 0.25 más cercano
|
||
scaaDeseado.value = redondearA025(scaaDeseado.value)
|
||
|
||
// Validar rango (solo después de redondear)
|
||
if (scaaDeseado.value < scaaMin) scaaDeseado.value = scaaMin
|
||
if (scaaDeseado.value > scaaMax) scaaDeseado.value = scaaMax
|
||
|
||
// Convertir a Sumatoria Afectiva
|
||
const sumatoriaCalculada = scaaASumatoriaAfectiva(scaaDeseado.value)
|
||
|
||
// Redondear al entero más cercano (sumatoria afectiva debe ser entero)
|
||
const sumatoriaRedondeada = Math.round(sumatoriaCalculada)
|
||
|
||
// Asegurar rango válido
|
||
puntajeDeseado.value = Math.max(8, Math.min(72, sumatoriaRedondeada))
|
||
|
||
// Recalcular SCAA Score con el valor redondeado (ya aplicará redondeo a 0.25)
|
||
scaaDeseado.value = sumatoriaAfectivaASCAA(puntajeDeseado.value)
|
||
|
||
actualizandoInput.value = false
|
||
}
|
||
|
||
// Cálculos
|
||
const puntajeValido = computed(() => {
|
||
return puntajeDeseado.value >= 8 && puntajeDeseado.value <= 72
|
||
})
|
||
|
||
const multiploMasCercano = computed(() => {
|
||
if (!puntajeValido.value) return 0
|
||
|
||
const valorActual = puntajeDeseado.value
|
||
const multiploInferior = Math.floor(valorActual / 8) * 8
|
||
const multiploSuperior = Math.ceil(valorActual / 8) * 8
|
||
|
||
const distInferior = Math.abs(valorActual - multiploInferior)
|
||
const distSuperior = Math.abs(valorActual - multiploSuperior)
|
||
|
||
// Si las distancias son iguales, elegir el mayor
|
||
if (distInferior === distSuperior) {
|
||
return multiploSuperior
|
||
}
|
||
|
||
return distInferior < distSuperior ? multiploInferior : multiploSuperior
|
||
})
|
||
|
||
const puntajeBase = computed(() => {
|
||
return multiploMasCercano.value / 8
|
||
})
|
||
|
||
const diferencia = computed(() => {
|
||
return Math.abs(puntajeDeseado.value - multiploMasCercano.value)
|
||
})
|
||
|
||
// Métodos
|
||
const siguientePaso = () => {
|
||
if (!puntajeValido.value) return
|
||
|
||
// Si el múltiplo es exacto (diferencia = 0)
|
||
if (diferencia.value === 0) {
|
||
if (props.modo === 'calculadora') {
|
||
// En modo calculadora, ir directo al paso 3
|
||
paso.value = 3
|
||
} else {
|
||
// En modo asignación, aplicar directamente
|
||
aplicarAsignacionDirecta()
|
||
}
|
||
} else {
|
||
// Hay diferencia, ir al paso 2
|
||
paso.value = 2
|
||
}
|
||
}
|
||
|
||
const pasoAnterior = () => {
|
||
if (paso.value > 1) {
|
||
paso.value--
|
||
}
|
||
}
|
||
|
||
const siguientePasoOAplicar = () => {
|
||
if (categoriasSeleccionadas.value.length !== diferencia.value) return
|
||
|
||
if (props.modo === 'calculadora') {
|
||
// En modo calculadora, ir al paso 3
|
||
paso.value = 3
|
||
} else {
|
||
// En modo asignación, aplicar
|
||
aplicarAsignacion()
|
||
}
|
||
}
|
||
|
||
const toggleCategoria = (key: string) => {
|
||
const index = categoriasSeleccionadas.value.indexOf(key)
|
||
if (index >= 0) {
|
||
categoriasSeleccionadas.value.splice(index, 1)
|
||
} else {
|
||
if (categoriasSeleccionadas.value.length < diferencia.value) {
|
||
categoriasSeleccionadas.value.push(key)
|
||
}
|
||
}
|
||
}
|
||
|
||
const aplicarAsignacionDirecta = () => {
|
||
const puntajes: Record<string, number> = {}
|
||
|
||
categoriasDisponibles.forEach(cat => {
|
||
puntajes[cat.key] = puntajeBase.value
|
||
})
|
||
|
||
emit('aplicar', puntajes)
|
||
cerrar()
|
||
}
|
||
|
||
const aplicarAsignacion = () => {
|
||
if (categoriasSeleccionadas.value.length !== diferencia.value) return
|
||
|
||
const puntajes: Record<string, number> = {}
|
||
const ajuste = multiploMasCercano.value < puntajeDeseado.value ? 1 : -1
|
||
|
||
categoriasDisponibles.forEach(cat => {
|
||
const esSeleccionada = categoriasSeleccionadas.value.includes(cat.key)
|
||
puntajes[cat.key] = puntajeBase.value + (esSeleccionada ? ajuste : 0)
|
||
})
|
||
|
||
emit('aplicar', puntajes)
|
||
cerrar()
|
||
}
|
||
|
||
const cerrar = () => {
|
||
isOpen.value = false
|
||
}
|
||
</script>
|
||
|
||
<style>
|
||
.modal-overlay {
|
||
background-color: var(--cata-bg) !important;
|
||
opacity: 0.95 !important;
|
||
backdrop-filter: blur(16px);
|
||
-webkit-backdrop-filter: blur(16px);
|
||
}
|
||
|
||
/* Estilos para UInputNumber para que respete los colores del usuario */
|
||
:deep(.cata-input-number input) {
|
||
background-color: var(--cata-bg) !important;
|
||
color: var(--cata-text) !important;
|
||
border-color: color-mix(in srgb, var(--cata-primary) 30%, transparent) !important;
|
||
}
|
||
|
||
:deep(.cata-input-number input:focus) {
|
||
border-color: var(--cata-primary) !important;
|
||
outline: none !important;
|
||
box-shadow: 0 0 0 1px var(--cata-primary) !important;
|
||
}
|
||
|
||
:deep(.cata-input-number input::placeholder) {
|
||
color: color-mix(in srgb, var(--cata-text) 50%, transparent) !important;
|
||
}
|
||
|
||
/* Botones de incremento/decremento */
|
||
:deep(.cata-input-number button) {
|
||
color: var(--cata-primary) !important;
|
||
transition: all 0.2s ease;
|
||
}
|
||
|
||
:deep(.cata-input-number button:hover) {
|
||
color: var(--cata-primary) !important;
|
||
opacity: 0.8;
|
||
}
|
||
|
||
:deep(.cata-input-number button:active) {
|
||
transform: scale(0.95);
|
||
}
|
||
|
||
/* Modo oscuro */
|
||
.dark :deep(.cata-input-number input) {
|
||
background-color: var(--cata-bg) !important;
|
||
border-color: color-mix(in srgb, var(--cata-primary) 40%, transparent) !important;
|
||
}
|
||
|
||
.dark :deep(.cata-input-number input:focus) {
|
||
box-shadow: 0 0 0 1px var(--cata-primary), 0 0 8px color-mix(in srgb, var(--cata-primary) 30%, transparent) !important;
|
||
}
|
||
</style>
|
||
|
||
<style scoped>
|
||
.selected-category {
|
||
background-color: color-mix(in srgb, var(--cata-primary) 10%, transparent);
|
||
border-color: var(--cata-primary);
|
||
}
|
||
|
||
.dark .selected-category {
|
||
background-color: color-mix(in srgb, var(--cata-primary) 15%, transparent);
|
||
box-shadow: 0 0 8px color-mix(in srgb, var(--cata-primary) 20%, transparent);
|
||
}
|
||
</style>
|