Fix: Refactorizar sensaciones en boca y hacer checkboxes ultra compactos
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m7s

CAMBIOS EN SENSACIONES EN BOCA:
- Reducir opciones a solo 5: Áspero, Aceitoso, Metálico, Deja seca la boca, Suave
- Cambiar de selección múltiple a selección única
- Actualizar tipo de sensacionEnBoca: SensacionBoca[] → SensacionBoca | null

CAMBIOS EN CHECKBOXES (sensaciones y gustos):
- Hacer checkboxes tan compactos como subcategorías de SelectorFamilia
- Usar flex-wrap en todos los breakpoints (eliminar grid en desktop)
- Dimensiones ultra compactas:
  * Desktop: min-height 32px, padding 0.375rem 0.5rem, font-size 0.75rem
  * Mobile: min-height 28px, padding 0.25rem 0.375rem, font-size 0.6875rem
  * Touch: min-height 36px para dispositivos táctiles

ARCHIVOS MODIFICADOS:
- app/types/catacion.ts: Actualizar SensacionBoca y SENSACIONES_BOCA
- app/composables/useCatacion.ts: Cambiar actualizarSensacionBoca a selección única
- app/components/cata/FormularioMuestra.vue: UI compacta y selección única
- app/components/cata/ResumenMuestra.vue: Adaptar a sensacionEnBoca única
This commit is contained in:
2025-10-18 16:55:37 -06:00
parent 4a927c57d4
commit 816a3e860a
4 changed files with 18 additions and 64 deletions

View File

@@ -22,10 +22,10 @@
/> />
</div> </div>
<!-- Sensaciones en Boca (selección múltiple) --> <!-- Sensaciones en Boca (selección única) -->
<div v-if="mostrarSensacionBocaOrganoleptica" class="form-section"> <div v-if="mostrarSensacionBocaOrganoleptica" class="form-section">
<label class="block text-sm font-medium mb-2 cata-text"> <label class="block text-sm font-medium mb-2 cata-text">
Sensaciones en la Boca (múltiples) Sensación en la Boca
</label> </label>
<div class="sensaciones-grid"> <div class="sensaciones-grid">
<button <button
@@ -35,9 +35,9 @@
:class="[ :class="[
'sensacion-item', 'sensacion-item',
'cata-checkbox', 'cata-checkbox',
{ 'cata-checkbox-checked': muestra.sensacionEnBoca.includes(sensacion) }, { 'cata-checkbox-checked': muestra.sensacionEnBoca === sensacion },
]" ]"
@click="toggleSensacionBoca(sensacion)" @click="seleccionarSensacionBoca(sensacion)"
> >
<span class="sensacion-text cata-text">{{ sensacion }}</span> <span class="sensacion-text cata-text">{{ sensacion }}</span>
</button> </button>
@@ -859,19 +859,10 @@ const actualizarDefecto = async (defecto: TipoDefecto) => {
await actualizarDefectoCatacion(props.muestra.muestraId, defecto) await actualizarDefectoCatacion(props.muestra.muestraId, defecto)
} }
// Toggle sensación en boca // Seleccionar sensación en boca (selección única)
const { actualizarSensacionBoca } = useCatacion() const { actualizarSensacionBoca } = useCatacion()
const toggleSensacionBoca = async (sensacion: SensacionBoca) => { const seleccionarSensacionBoca = async (sensacion: SensacionBoca) => {
const sensaciones = [...props.muestra.sensacionEnBoca] await actualizarSensacionBoca(props.muestra.muestraId, sensacion)
const index = sensaciones.indexOf(sensacion)
if (index > -1) {
sensaciones.splice(index, 1)
} else {
sensaciones.push(sensacion)
}
await actualizarSensacionBoca(props.muestra.muestraId, sensaciones)
} }
// Toggle gusto predominante // Toggle gusto predominante
@@ -951,7 +942,7 @@ watch(() => props.muestra.otrasNotas, (newVal) => {
text-align: center; text-align: center;
} }
/* Grid de sensaciones */ /* Grid de sensaciones y gustos - estilo compacto como subcategorías */
.sensaciones-grid { .sensaciones-grid {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
@@ -980,7 +971,6 @@ watch(() => props.muestra.otrasNotas, (newVal) => {
font-size: 0.75rem; font-size: 0.75rem;
} }
/* Grid de gustos */
.gustos-grid { .gustos-grid {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
@@ -1046,28 +1036,6 @@ watch(() => props.muestra.otrasNotas, (newVal) => {
} }
} }
@media (min-width: 768px) {
.sensaciones-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 0.5rem;
}
.sensacion-item {
min-height: 36px;
}
.gustos-grid {
display: grid;
grid-template-columns: repeat(5, minmax(0, 1fr));
gap: 0.5rem;
}
.gusto-item {
min-height: 36px;
}
}
/* Touch-friendly */ /* Touch-friendly */
@media (hover: none) and (pointer: coarse) { @media (hover: none) and (pointer: coarse) {
.sensacion-item { .sensacion-item {

View File

@@ -43,9 +43,9 @@
</div> </div>
<!-- Sensación en boca --> <!-- Sensación en boca -->
<div v-if="muestra.sensacionEnBoca.length > 0" class="chip"> <div v-if="muestra.sensacionEnBoca" class="chip">
<span class="chip-label">Sen:</span> <span class="chip-label">Sen:</span>
<span class="chip-value">{{ muestra.sensacionEnBoca.join(', ') }}</span> <span class="chip-value">{{ muestra.sensacionEnBoca }}</span>
</div> </div>
</template> </template>

View File

@@ -211,10 +211,10 @@ export const useCatacion = () => {
} }
/** /**
* Actualiza sensaciones en boca * Actualiza sensación en boca (selección única)
*/ */
const actualizarSensacionBoca = async (muestraId: number, sensaciones: string[]) => { const actualizarSensacionBoca = async (muestraId: number, sensacion: string | null) => {
await actualizarMuestra(muestraId, { sensacionEnBoca: sensaciones as any }) await actualizarMuestra(muestraId, { sensacionEnBoca: sensacion as any })
} }
/** /**

View File

@@ -89,17 +89,10 @@ export type TipoDefecto = 'Mohoso' | 'Fenólico' | 'Papa' | null
export type SensacionBoca = export type SensacionBoca =
| 'Áspero' | 'Áspero'
| 'Arenoso'
| 'Rugoso'
| 'Rasposo'
| 'Suave'
| 'Aterciopelado'
| 'Sedoso'
| 'Almibarado'
| 'Aceitoso' | 'Aceitoso'
| 'Metálico' | 'Metálico'
| 'Deja seca la boca' | 'Deja seca la boca'
| 'Astringente' | 'Suave'
export type GustoPredominante = 'Salado' | 'Amargo' | 'Ácido' | 'Dulce' | 'Umami' export type GustoPredominante = 'Salado' | 'Amargo' | 'Ácido' | 'Dulce' | 'Umami'
@@ -124,8 +117,8 @@ export interface Muestra {
tazasDefectuosas: number[] tazasDefectuosas: number[]
/** Tipo de defecto encontrado */ /** Tipo de defecto encontrado */
defecto: TipoDefecto defecto: TipoDefecto
/** Sensaciones en la boca (múltiples selecciones) */ /** Sensación en la boca (selección única) */
sensacionEnBoca: SensacionBoca[] sensacionEnBoca: SensacionBoca | null
/** Gustos predominantes (máximo 2, mínimo 1) */ /** Gustos predominantes (máximo 2, mínimo 1) */
gustosPredominantes: GustoPredominante[] gustosPredominantes: GustoPredominante[]
/** Notas adicionales en texto libre */ /** Notas adicionales en texto libre */
@@ -189,7 +182,7 @@ export function crearMuestraVacia(id: number): Muestra {
tazasNoUniformes: [], tazasNoUniformes: [],
tazasDefectuosas: [], tazasDefectuosas: [],
defecto: null, defecto: null,
sensacionEnBoca: [], sensacionEnBoca: null,
gustosPredominantes: [], gustosPredominantes: [],
otrasNotas: '', otrasNotas: '',
puntajeFinal: 0, puntajeFinal: 0,
@@ -285,17 +278,10 @@ export const FAMILIAS_NOTAS_ESTRUCTURA: FamiliasNotas = {
*/ */
export const SENSACIONES_BOCA: SensacionBoca[] = [ export const SENSACIONES_BOCA: SensacionBoca[] = [
'Áspero', 'Áspero',
'Arenoso',
'Rugoso',
'Rasposo',
'Suave',
'Aterciopelado',
'Sedoso',
'Almibarado',
'Aceitoso', 'Aceitoso',
'Metálico', 'Metálico',
'Deja seca la boca', 'Deja seca la boca',
'Astringente', 'Suave',
] ]
/** /**