feat: Redesign bakery and user settings pages with improved UX

Implemented a comprehensive redesign of the settings pages using Jobs To Be Done (JTBD) methodology to improve user experience, visual appeal, and discoverability.

## New Components

- **SettingRow**: Reusable component for consistent setting layouts with support for toggles, inputs, selects, and custom content
- **SettingSection**: Collapsible section component for grouping related settings with consistent styling

## Page Redesigns

### BakerySettingsPage
- Redesigned information tab with better visual hierarchy using SettingSection components
- Improved business hours UI with clearer day-by-day layout
- Enhanced header with gradient bakery icon and status indicators
- Consistent spacing and responsive design improvements
- Better visual feedback for unsaved changes

### NewProfileSettingsPage
- Unified design with bakery settings page
- Improved personal information section with SettingSection
- Better security section layout with collapsible password change form
- Enhanced privacy & data management UI
- Consistent icon usage and visual hierarchy

### InventorySettingsCard
- Replaced checkbox with toggle switch for temperature monitoring
- Progressive disclosure: temperature settings only shown when enabled
- Better visual separation between setting groups
- Improved responsive grid layouts
- Added helpful descriptions and tooltips

## Key Improvements

1. **Visual Consistency**: Both bakery and user settings now use the same design patterns and components
2. **Scannability**: Icons, badges, and clear visual hierarchy make settings easier to scan
3. **Progressive Disclosure**: Complex settings (like temperature monitoring) only show when relevant
4. **Toggle Switches**: Binary settings use toggles instead of checkboxes for better visual feedback
5. **Responsive Design**: Improved mobile and desktop layouts with better touch targets
6. **Accessibility**: Proper ARIA labels, help text, and keyboard navigation support

## JTBD Analysis Applied

- Main job: "Quickly find, understand, and change settings without mistakes"
- Sub-jobs addressed:
  - Discovery & navigation (visual grouping, icons, clear labels)
  - Configuration & adjustment (toggles, inline editing, validation)
  - Validation & confidence (help text, descriptions, visual feedback)

This redesign maintains backward compatibility while significantly improving the user experience for managing bakery and personal settings.
This commit is contained in:
Claude
2025-11-14 06:34:23 +00:00
parent 9bc048d360
commit a5200bbc94
8 changed files with 868 additions and 571 deletions

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { Package, AlertCircle, Thermometer, Clock } from 'lucide-react';
import { Card, Input } from '../../../../../components/ui';
import { Card, Input, SettingSection, SettingRow } from '../../../../../components/ui';
import type { InventorySettings } from '../../../../../api/types/settings';
interface InventorySettingsCardProps {
@@ -23,21 +23,24 @@ const InventorySettingsCard: React.FC<InventorySettingsCardProps> = ({
onChange({ ...settings, [field]: value });
};
return (
<Card className="p-6">
<h3 className="text-lg font-semibold text-[var(--text-primary)] mb-6 flex items-center">
<Package className="w-5 h-5 mr-2 text-[var(--color-primary)]" />
Gestión de Inventario
</h3>
const handleToggleChange = (field: keyof InventorySettings) => (checked: boolean) => {
onChange({ ...settings, [field]: checked });
};
<div className="space-y-6">
{/* Stock Management */}
<div>
return (
<SettingSection
title="Gestión de Inventario"
description="Configure stock management, expiration tracking, and temperature monitoring"
icon={<Package className="w-5 h-5" />}
>
<div className="divide-y divide-[var(--border-primary)]">
{/* Stock Management Section */}
<div className="p-4 sm:p-6">
<h4 className="text-sm font-semibold text-[var(--text-secondary)] mb-4 flex items-center">
<Package className="w-4 h-4 mr-2" />
Control de Stock
</h4>
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4 pl-6">
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4">
<Input
type="number"
label="Umbral de Stock Bajo"
@@ -76,13 +79,13 @@ const InventorySettingsCard: React.FC<InventorySettingsCardProps> = ({
</div>
</div>
{/* Expiration Management */}
<div>
{/* Expiration Management Section */}
<div className="p-4 sm:p-6">
<h4 className="text-sm font-semibold text-[var(--text-secondary)] mb-4 flex items-center">
<Clock className="w-4 h-4 mr-2" />
Gestión de Caducidad
</h4>
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4 pl-6">
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4">
<Input
type="number"
label="Días para 'Próximo a Caducar'"
@@ -121,159 +124,150 @@ const InventorySettingsCard: React.FC<InventorySettingsCardProps> = ({
</div>
</div>
{/* Temperature Monitoring */}
<div>
<h4 className="text-sm font-semibold text-[var(--text-secondary)] mb-4 flex items-center">
<Thermometer className="w-4 h-4 mr-2" />
Monitorización de Temperatura
</h4>
<div className="space-y-4 pl-6">
<div className="flex items-center gap-2">
<input
type="checkbox"
id="temperature_monitoring_enabled"
checked={settings.temperature_monitoring_enabled}
onChange={handleChange('temperature_monitoring_enabled')}
disabled={disabled}
className="rounded border-[var(--border-primary)]"
/>
<label htmlFor="temperature_monitoring_enabled" className="text-sm text-[var(--text-secondary)]">
Habilitar monitorización de temperatura
</label>
</div>
{/* Temperature Monitoring Section */}
<div className="divide-y divide-[var(--border-primary)]">
<SettingRow
label="Monitorización de Temperatura"
description="Enable temperature tracking for inventory items"
icon={<Thermometer className="w-4 h-4" />}
type="toggle"
checked={settings.temperature_monitoring_enabled}
onToggle={handleToggleChange('temperature_monitoring_enabled')}
disabled={disabled}
helpText="When enabled, system will monitor and alert on temperature deviations"
/>
{settings.temperature_monitoring_enabled && (
<>
{/* Refrigeration */}
<div>
<label className="block text-xs font-medium text-[var(--text-tertiary)] mb-2">
Refrigeración (°C)
</label>
<div className="grid grid-cols-2 gap-4">
<Input
type="number"
label="Temperatura Mínima"
value={settings.refrigeration_temp_min}
onChange={handleChange('refrigeration_temp_min')}
disabled={disabled}
min={-5}
max={10}
step={0.5}
placeholder="1.0"
/>
<Input
type="number"
label="Temperatura Máxima"
value={settings.refrigeration_temp_max}
onChange={handleChange('refrigeration_temp_max')}
disabled={disabled}
min={-5}
max={10}
step={0.5}
placeholder="4.0"
/>
</div>
{settings.temperature_monitoring_enabled && (
<>
{/* Refrigeration Settings */}
<div className="p-4 sm:p-6 bg-[var(--bg-secondary)]">
<h5 className="text-sm font-medium text-[var(--text-secondary)] mb-4">
Refrigeración (°C)
</h5>
<div className="grid grid-cols-2 gap-4">
<Input
type="number"
label="Temperatura Mínima"
value={settings.refrigeration_temp_min}
onChange={handleChange('refrigeration_temp_min')}
disabled={disabled}
min={-5}
max={10}
step={0.5}
placeholder="1.0"
/>
<Input
type="number"
label="Temperatura Máxima"
value={settings.refrigeration_temp_max}
onChange={handleChange('refrigeration_temp_max')}
disabled={disabled}
min={-5}
max={10}
step={0.5}
placeholder="4.0"
/>
</div>
</div>
{/* Freezer */}
<div>
<label className="block text-xs font-medium text-[var(--text-tertiary)] mb-2">
Congelador (°C)
</label>
<div className="grid grid-cols-2 gap-4">
<Input
type="number"
label="Temperatura Mínima"
value={settings.freezer_temp_min}
onChange={handleChange('freezer_temp_min')}
disabled={disabled}
min={-30}
max={0}
step={1}
placeholder="-20.0"
/>
<Input
type="number"
label="Temperatura Máxima"
value={settings.freezer_temp_max}
onChange={handleChange('freezer_temp_max')}
disabled={disabled}
min={-30}
max={0}
step={1}
placeholder="-15.0"
/>
</div>
{/* Freezer Settings */}
<div className="p-4 sm:p-6 bg-[var(--bg-secondary)]">
<h5 className="text-sm font-medium text-[var(--text-secondary)] mb-4">
Congelador (°C)
</h5>
<div className="grid grid-cols-2 gap-4">
<Input
type="number"
label="Temperatura Mínima"
value={settings.freezer_temp_min}
onChange={handleChange('freezer_temp_min')}
disabled={disabled}
min={-30}
max={0}
step={1}
placeholder="-20.0"
/>
<Input
type="number"
label="Temperatura Máxima"
value={settings.freezer_temp_max}
onChange={handleChange('freezer_temp_max')}
disabled={disabled}
min={-30}
max={0}
step={1}
placeholder="-15.0"
/>
</div>
</div>
{/* Room Temperature */}
<div>
<label className="block text-xs font-medium text-[var(--text-tertiary)] mb-2">
Temperatura Ambiente (°C)
</label>
<div className="grid grid-cols-2 gap-4">
<Input
type="number"
label="Temperatura Mínima"
value={settings.room_temp_min}
onChange={handleChange('room_temp_min')}
disabled={disabled}
min={10}
max={35}
step={1}
placeholder="18.0"
/>
<Input
type="number"
label="Temperatura Máxima"
value={settings.room_temp_max}
onChange={handleChange('room_temp_max')}
disabled={disabled}
min={10}
max={35}
step={1}
placeholder="25.0"
/>
</div>
{/* Room Temperature Settings */}
<div className="p-4 sm:p-6 bg-[var(--bg-secondary)]">
<h5 className="text-sm font-medium text-[var(--text-secondary)] mb-4">
Temperatura Ambiente (°C)
</h5>
<div className="grid grid-cols-2 gap-4">
<Input
type="number"
label="Temperatura Mínima"
value={settings.room_temp_min}
onChange={handleChange('room_temp_min')}
disabled={disabled}
min={10}
max={35}
step={1}
placeholder="18.0"
/>
<Input
type="number"
label="Temperatura Máxima"
value={settings.room_temp_max}
onChange={handleChange('room_temp_max')}
disabled={disabled}
min={10}
max={35}
step={1}
placeholder="25.0"
/>
</div>
</div>
{/* Alert Timing */}
<div>
<h5 className="text-xs font-medium text-[var(--text-tertiary)] mb-2 flex items-center">
<AlertCircle className="w-3 h-3 mr-1" />
Alertas de Desviación
</h5>
<div className="grid grid-cols-2 gap-4">
<Input
type="number"
label="Desviación Normal (minutos)"
value={settings.temp_deviation_alert_minutes}
onChange={handleChange('temp_deviation_alert_minutes')}
disabled={disabled}
min={1}
max={60}
step={1}
placeholder="15"
/>
<Input
type="number"
label="Desviación Crítica (minutos)"
value={settings.critical_temp_deviation_minutes}
onChange={handleChange('critical_temp_deviation_minutes')}
disabled={disabled}
min={1}
max={30}
step={1}
placeholder="5"
/>
</div>
{/* Alert Timing */}
<div className="p-4 sm:p-6 bg-[var(--bg-secondary)]">
<h5 className="text-sm font-medium text-[var(--text-secondary)] mb-4 flex items-center">
<AlertCircle className="w-4 h-4 mr-2" />
Alertas de Desviación
</h5>
<div className="grid grid-cols-2 gap-4">
<Input
type="number"
label="Desviación Normal (minutos)"
value={settings.temp_deviation_alert_minutes}
onChange={handleChange('temp_deviation_alert_minutes')}
disabled={disabled}
min={1}
max={60}
step={1}
placeholder="15"
/>
<Input
type="number"
label="Desviación Crítica (minutos)"
value={settings.critical_temp_deviation_minutes}
onChange={handleChange('critical_temp_deviation_minutes')}
disabled={disabled}
min={1}
max={30}
step={1}
placeholder="5"
/>
</div>
</>
)}
</div>
</div>
</>
)}
</div>
</div>
</Card>
</SettingSection>
);
};