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.
275 lines
9.7 KiB
TypeScript
275 lines
9.7 KiB
TypeScript
import React from 'react';
|
|
import { Package, AlertCircle, Thermometer, Clock } from 'lucide-react';
|
|
import { Card, Input, SettingSection, SettingRow } from '../../../../../components/ui';
|
|
import type { InventorySettings } from '../../../../../api/types/settings';
|
|
|
|
interface InventorySettingsCardProps {
|
|
settings: InventorySettings;
|
|
onChange: (settings: InventorySettings) => void;
|
|
disabled?: boolean;
|
|
}
|
|
|
|
const InventorySettingsCard: React.FC<InventorySettingsCardProps> = ({
|
|
settings,
|
|
onChange,
|
|
disabled = false,
|
|
}) => {
|
|
const handleChange = (field: keyof InventorySettings) => (
|
|
e: React.ChangeEvent<HTMLInputElement>
|
|
) => {
|
|
const value = e.target.type === 'checkbox' ? e.target.checked :
|
|
e.target.type === 'number' ? parseFloat(e.target.value) :
|
|
e.target.value;
|
|
onChange({ ...settings, [field]: value });
|
|
};
|
|
|
|
const handleToggleChange = (field: keyof InventorySettings) => (checked: boolean) => {
|
|
onChange({ ...settings, [field]: checked });
|
|
};
|
|
|
|
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">
|
|
<Input
|
|
type="number"
|
|
label="Umbral de Stock Bajo"
|
|
value={settings.low_stock_threshold}
|
|
onChange={handleChange('low_stock_threshold')}
|
|
disabled={disabled}
|
|
min={1}
|
|
max={1000}
|
|
step={1}
|
|
placeholder="10"
|
|
/>
|
|
|
|
<Input
|
|
type="number"
|
|
label="Punto de Reorden"
|
|
value={settings.reorder_point}
|
|
onChange={handleChange('reorder_point')}
|
|
disabled={disabled}
|
|
min={1}
|
|
max={1000}
|
|
step={1}
|
|
placeholder="20"
|
|
/>
|
|
|
|
<Input
|
|
type="number"
|
|
label="Cantidad de Reorden"
|
|
value={settings.reorder_quantity}
|
|
onChange={handleChange('reorder_quantity')}
|
|
disabled={disabled}
|
|
min={1}
|
|
max={1000}
|
|
step={1}
|
|
placeholder="50"
|
|
/>
|
|
</div>
|
|
</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">
|
|
<Input
|
|
type="number"
|
|
label="Días para 'Próximo a Caducar'"
|
|
value={settings.expiring_soon_days}
|
|
onChange={handleChange('expiring_soon_days')}
|
|
disabled={disabled}
|
|
min={1}
|
|
max={30}
|
|
step={1}
|
|
placeholder="7"
|
|
/>
|
|
|
|
<Input
|
|
type="number"
|
|
label="Días para Alerta de Caducidad"
|
|
value={settings.expiration_warning_days}
|
|
onChange={handleChange('expiration_warning_days')}
|
|
disabled={disabled}
|
|
min={1}
|
|
max={14}
|
|
step={1}
|
|
placeholder="3"
|
|
/>
|
|
|
|
<Input
|
|
type="number"
|
|
label="Umbral de Calidad (0-10)"
|
|
value={settings.quality_score_threshold}
|
|
onChange={handleChange('quality_score_threshold')}
|
|
disabled={disabled}
|
|
min={0}
|
|
max={10}
|
|
step={0.1}
|
|
placeholder="8.0"
|
|
/>
|
|
</div>
|
|
</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 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 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 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 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>
|
|
</SettingSection>
|
|
);
|
|
};
|
|
|
|
export default InventorySettingsCard;
|