Files
bakery-ia/frontend/src/pages/app/database/ajustes/AjustesPage.tsx
2025-10-23 07:44:54 +02:00

300 lines
9.8 KiB
TypeScript

import React, { useState } from 'react';
import { Settings, Save, RotateCcw, AlertCircle, Loader } from 'lucide-react';
import { Button, Card } from '../../../../components/ui';
import { PageHeader } from '../../../../components/layout';
import { useToast } from '../../../../hooks/ui/useToast';
import { useSettings, useUpdateSettings } from '../../../../api/hooks/settings';
import { useCurrentTenant } from '../../../../stores/tenant.store';
import type {
TenantSettings,
ProcurementSettings,
InventorySettings,
ProductionSettings,
SupplierSettings,
POSSettings,
OrderSettings,
} from '../../../../api/types/settings';
import ProcurementSettingsCard from './cards/ProcurementSettingsCard';
import InventorySettingsCard from './cards/InventorySettingsCard';
import ProductionSettingsCard from './cards/ProductionSettingsCard';
import SupplierSettingsCard from './cards/SupplierSettingsCard';
import POSSettingsCard from './cards/POSSettingsCard';
import OrderSettingsCard from './cards/OrderSettingsCard';
const AjustesPage: React.FC = () => {
const { addToast } = useToast();
const currentTenant = useCurrentTenant();
const tenantId = currentTenant?.id || '';
const { data: settings, isLoading, error, isFetching } = useSettings(tenantId, {
enabled: !!tenantId,
retry: 2,
staleTime: 5 * 60 * 100,
});
// Debug logging
React.useEffect(() => {
console.log('🔍 AjustesPage - tenantId:', tenantId);
console.log('🔍 AjustesPage - settings:', settings);
console.log('🔍 AjustesPage - isLoading:', isLoading);
console.log('🔍 AjustesPage - isFetching:', isFetching);
console.log('🔍 AjustesPage - error:', error);
}, [tenantId, settings, isLoading, isFetching, error]);
const updateSettingsMutation = useUpdateSettings();
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
const [isSaving, setIsSaving] = useState(false);
// Local state for each category
const [procurementSettings, setProcurementSettings] = useState<ProcurementSettings | null>(null);
const [inventorySettings, setInventorySettings] = useState<InventorySettings | null>(null);
const [productionSettings, setProductionSettings] = useState<ProductionSettings | null>(null);
const [supplierSettings, setSupplierSettings] = useState<SupplierSettings | null>(null);
const [posSettings, setPosSettings] = useState<POSSettings | null>(null);
const [orderSettings, setOrderSettings] = useState<OrderSettings | null>(null);
// Load settings into local state when data is fetched
React.useEffect(() => {
if (settings) {
setProcurementSettings(settings.procurement_settings);
setInventorySettings(settings.inventory_settings);
setProductionSettings(settings.production_settings);
setSupplierSettings(settings.supplier_settings);
setPosSettings(settings.pos_settings);
setOrderSettings(settings.order_settings);
setHasUnsavedChanges(false);
}
}, [settings]);
const handleSaveAll = async () => {
if (!tenantId || !procurementSettings || !inventorySettings || !productionSettings ||
!supplierSettings || !posSettings || !orderSettings) {
return;
}
setIsSaving(true);
try {
await updateSettingsMutation.mutateAsync({
tenantId,
updates: {
procurement_settings: procurementSettings,
inventory_settings: inventorySettings,
production_settings: productionSettings,
supplier_settings: supplierSettings,
pos_settings: posSettings,
order_settings: orderSettings,
},
});
setHasUnsavedChanges(false);
addToast('Ajustes guardados correctamente', { type: 'success' });
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Error desconocido';
addToast(`Error al guardar ajustes: ${errorMessage}`, { type: 'error' });
} finally {
setIsSaving(false);
}
};
const handleResetAll = () => {
if (settings) {
setProcurementSettings(settings.procurement_settings);
setInventorySettings(settings.inventory_settings);
setProductionSettings(settings.production_settings);
setSupplierSettings(settings.supplier_settings);
setPosSettings(settings.pos_settings);
setOrderSettings(settings.order_settings);
setHasUnsavedChanges(false);
}
};
const handleCategoryChange = (category: string) => {
setHasUnsavedChanges(true);
};
if (isLoading || !currentTenant) {
return (
<div className="p-6 space-y-6">
<PageHeader
title="Ajustes"
description="Configura los parámetros operativos de tu panadería"
/>
<div className="flex items-center justify-center h-64">
<Loader className="w-8 h-8 animate-spin text-[var(--color-primary)]" />
<span className="ml-2 text-[var(--text-secondary)]">Cargando ajustes...</span>
</div>
</div>
);
}
if (error) {
return (
<div className="p-6 space-y-6">
<PageHeader
title="Ajustes"
description="Error al cargar los ajustes"
/>
<Card className="p-6">
<div className="text-red-600">
Error al cargar los ajustes: {error.message || 'Error desconocido'}
</div>
</Card>
</div>
);
}
return (
<div className="p-6 space-y-6 pb-32">
<PageHeader
title="Ajustes"
description="Configura los parámetros operativos de tu panadería"
/>
{/* Top Action Bar */}
<div className="flex items-center justify-between">
<div className="flex items-center gap-2 text-sm">
<Settings className="w-4 h-4 text-[var(--color-primary)]" />
<span className="text-[var(--text-secondary)]">
Ajusta los parámetros según las necesidades de tu negocio
</span>
</div>
<div className="flex gap-2">
<Button
variant="outline"
size="sm"
onClick={handleResetAll}
disabled={!hasUnsavedChanges || isSaving}
>
<RotateCcw className="w-4 h-4" />
Restablecer Todo
</Button>
<Button
variant="primary"
size="sm"
onClick={handleSaveAll}
isLoading={isSaving}
disabled={!hasUnsavedChanges}
loadingText="Guardando..."
>
<Save className="w-4 h-4" />
Guardar Cambios
</Button>
</div>
</div>
{/* Settings Categories */}
<div className="space-y-6">
{/* Procurement Settings */}
{procurementSettings && (
<ProcurementSettingsCard
settings={procurementSettings}
onChange={(newSettings) => {
setProcurementSettings(newSettings);
handleCategoryChange('procurement');
}}
disabled={isSaving}
/>
)}
{/* Inventory Settings */}
{inventorySettings && (
<InventorySettingsCard
settings={inventorySettings}
onChange={(newSettings) => {
setInventorySettings(newSettings);
handleCategoryChange('inventory');
}}
disabled={isSaving}
/>
)}
{/* Production Settings */}
{productionSettings && (
<ProductionSettingsCard
settings={productionSettings}
onChange={(newSettings) => {
setProductionSettings(newSettings);
handleCategoryChange('production');
}}
disabled={isSaving}
/>
)}
{/* Supplier Settings */}
{supplierSettings && (
<SupplierSettingsCard
settings={supplierSettings}
onChange={(newSettings) => {
setSupplierSettings(newSettings);
handleCategoryChange('supplier');
}}
disabled={isSaving}
/>
)}
{/* POS Settings */}
{posSettings && (
<POSSettingsCard
settings={posSettings}
onChange={(newSettings) => {
setPosSettings(newSettings);
handleCategoryChange('pos');
}}
disabled={isSaving}
/>
)}
{/* Order Settings */}
{orderSettings && (
<OrderSettingsCard
settings={orderSettings}
onChange={(newSettings) => {
setOrderSettings(newSettings);
handleCategoryChange('order');
}}
disabled={isSaving}
/>
)}
</div>
{/* Floating Save Banner */}
{hasUnsavedChanges && (
<div className="fixed bottom-6 right-6 z-50">
<Card className="p-4 shadow-lg border-2 border-[var(--color-primary)]">
<div className="flex items-center gap-3">
<div className="flex items-center gap-2 text-sm text-[var(--text-secondary)]">
<AlertCircle className="w-4 h-4 text-yellow-500" />
Tienes cambios sin guardar
</div>
<div className="flex gap-2">
<Button
variant="outline"
size="sm"
onClick={handleResetAll}
disabled={isSaving}
>
<RotateCcw className="w-4 h-4" />
Descartar
</Button>
<Button
variant="primary"
size="sm"
onClick={handleSaveAll}
isLoading={isSaving}
loadingText="Guardando..."
>
<Save className="w-4 h-4" />
Guardar
</Button>
</div>
</div>
</Card>
</div>
)}
</div>
);
};
export default AjustesPage;