Add database diagnostic export
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m29s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m29s
This commit is contained in:
@@ -161,6 +161,23 @@ const authFetch = async (path: string, options: RequestInit = {}): Promise<Respo
|
||||
return response;
|
||||
};
|
||||
|
||||
export const downloadDatabaseDiagnostic = async (): Promise<void> => {
|
||||
const response = await authFetch('/admin/database-diagnostic', { cache: 'no-store' });
|
||||
const data = await response.json().catch(() => null);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(data?.error || 'Não foi possível exportar o diagnóstico do banco.');
|
||||
}
|
||||
|
||||
const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json;charset=utf-8;' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const anchor = document.createElement('a');
|
||||
anchor.href = url;
|
||||
anchor.download = `graphs-db-diagnostic-${new Date().toISOString().slice(0, 10)}.json`;
|
||||
anchor.click();
|
||||
URL.revokeObjectURL(url);
|
||||
};
|
||||
|
||||
export const fetchProductionOrders = async (
|
||||
dateRange: DateRange,
|
||||
filters?: { search?: string },
|
||||
|
||||
@@ -28,7 +28,7 @@ import DateRangePicker from '../components/DateRangePicker';
|
||||
import PaginationControls from '../components/PaginationControls';
|
||||
import ProductTypeBadge from '../components/ProductTypeBadge';
|
||||
import { classifyCutFamily } from '../analytics/cutting';
|
||||
import { adjustSupplyLotInventory, approveSupplyReceipt, consumeSupplyLotForProduction, createSupplyFabricPlan, createSupplyReceipt, deleteSupplyFabricPlan, deleteSupplyReceipt, fetchCuttingSettings, fetchProductAnalytics, fetchStock, fetchSupplySummary } from '../dataService';
|
||||
import { adjustSupplyLotInventory, approveSupplyReceipt, consumeSupplyLotForProduction, createSupplyFabricPlan, createSupplyReceipt, deleteSupplyFabricPlan, deleteSupplyReceipt, downloadDatabaseDiagnostic, fetchCuttingSettings, fetchProductAnalytics, fetchStock, fetchSupplySummary, isSuperAdmin } from '../dataService';
|
||||
import { parseProductName } from '../productParsing';
|
||||
import { resolveProductType, type ProductTypeKey } from '../productClassification';
|
||||
import { getPlanningStock } from '../planningStock';
|
||||
@@ -192,9 +192,44 @@ const ModuleCard = ({
|
||||
);
|
||||
};
|
||||
|
||||
const SuppliesHub = () => (
|
||||
const SuppliesHub = () => {
|
||||
const [isExportingDiagnostic, setIsExportingDiagnostic] = useState(false);
|
||||
const [diagnosticError, setDiagnosticError] = useState('');
|
||||
const canExportDiagnostic = isSuperAdmin();
|
||||
|
||||
const handleExportDiagnostic = async () => {
|
||||
setIsExportingDiagnostic(true);
|
||||
setDiagnosticError('');
|
||||
try {
|
||||
await downloadDatabaseDiagnostic();
|
||||
} catch (error) {
|
||||
setDiagnosticError(error instanceof Error ? error.message : 'Não foi possível exportar o diagnóstico do banco.');
|
||||
} finally {
|
||||
setIsExportingDiagnostic(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={pageClassName}>
|
||||
<Header title="Suprimentos" subtitle="Corte, estoque, malha e compras em um fluxo operacional." />
|
||||
<div className="flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between">
|
||||
<Header title="Suprimentos" subtitle="Corte, estoque, malha e compras em um fluxo operacional." />
|
||||
{canExportDiagnostic && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleExportDiagnostic}
|
||||
disabled={isExportingDiagnostic}
|
||||
className={`${buttonClassName} w-fit disabled:cursor-not-allowed disabled:opacity-60`}
|
||||
>
|
||||
<Download className="h-4 w-4" />
|
||||
{isExportingDiagnostic ? 'Exportando...' : 'Exportar diagnóstico DB'}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{diagnosticError && (
|
||||
<div className="rounded-xl border border-red-500/30 bg-red-500/10 px-4 py-3 text-sm font-bold text-red-300">
|
||||
{diagnosticError}
|
||||
</div>
|
||||
)}
|
||||
<div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
|
||||
<ModuleCard title="Planejamento Operacional" description="Prioridades de reposição, compra e revisão calculadas por demanda, estoque e cobertura." icon={PackageSearch} to="/supplies/current-planning" />
|
||||
<ModuleCard title="Planejamento de Corte" description="Ruptura por cor e tamanho, montagem do corte e prioridade por cobertura." icon={Scissors} to="/cutting" />
|
||||
@@ -204,7 +239,8 @@ const SuppliesHub = () => (
|
||||
<ModuleCard title="Necessidade de Compra" description="Itens abaixo do mínimo e necessidade projetada para compra." icon={BarChart3} to="/supplies/purchase-needs" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
};
|
||||
|
||||
const getRangeDays = (range: DateRange) => {
|
||||
const start = new Date(range.start);
|
||||
|
||||
Reference in New Issue
Block a user