From e351a335c14022805ef3f11c8a3bf08b70395bed Mon Sep 17 00:00:00 2001 From: AnibalFu Date: Wed, 3 Jun 2026 22:27:11 -0300 Subject: [PATCH] feat: export metrics from backend --- src/common/helpers/metricsExport.ts | 100 ---------------------------- src/modules/metrics/Metrics.tsx | 27 ++++---- src/services/orders.ts | 15 ++++- 3 files changed, 27 insertions(+), 115 deletions(-) delete mode 100644 src/common/helpers/metricsExport.ts diff --git a/src/common/helpers/metricsExport.ts b/src/common/helpers/metricsExport.ts deleted file mode 100644 index 6cab0c3..0000000 --- a/src/common/helpers/metricsExport.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { - CategoryStatsPoint, - StatusDistributionPoint, - TimeSeriesPoint, -} from '@/common/interfaces/modules/metrics'; -import { MetricsStats } from '@/common/interfaces/services/metrics'; -import { ProductStats } from '@/common/interfaces/services/products'; -import { formatDate } from '@/common/helpers/dateFormat'; -import { generateCSV } from '@/lib/utils'; - -interface BuildMetricsCSVParams { - period: string; - data?: MetricsStats; - timeSeriesData: TimeSeriesPoint[]; - statusDistributionData: StatusDistributionPoint[]; - topProductsData: ProductStats[]; - categoryStatsData: CategoryStatsPoint[]; -} - -export function buildMetricsCSV({ - period, - data, - timeSeriesData, - statusDistributionData, - topProductsData, - categoryStatsData, -}: BuildMetricsCSVParams): string { - const headers = ['Sección', 'Métrica', 'Valor 1', 'Valor 2', 'Valor 3']; - const temporalEvolutionRows = - data?.orders.temporalEvolution?.map((item) => [ - 'Evolución temporal', - formatDate(item.date), - item.count, - 'Ingresos ARS', - item.revenue, - ]) ?? - timeSeriesData.map((item) => [ - 'Evolución temporal', - item.date, - item.Órdenes, - 'Ingresos ARS', - item.Ingresos, - ]); - - const rows = [ - ['Período', 'Días seleccionados', period, '', ''], - [ - 'Usuarios', - 'Registrados', - data?.users.totalUsers ?? 0, - 'Crecimiento %', - data?.users.growthRate ?? 0, - ], - [ - 'Usuarios', - 'Activos', - data?.users.activeUsers ?? 0, - 'Bloqueados', - data?.users.blockedUsers ?? 0, - ], - [ - 'Órdenes', - 'Total', - data?.orders.totalOrders ?? 0, - 'Crecimiento %', - data?.orders.totalOrdersGrowthRate ?? 0, - ], - [ - 'Órdenes', - 'Facturado ARS', - data?.orders.totalTransacted ?? 0, - 'Crecimiento %', - data?.orders.totalTransactedGrowthRate ?? 0, - ], - ...temporalEvolutionRows, - ...statusDistributionData.map((item) => [ - 'Distribución por estado', - item.label, - item.count, - '', - '', - ]), - ...topProductsData.map((item) => [ - 'Productos más vendidos', - item.title, - item.totalQuantity, - 'Ingresos ARS', - item.totalRevenue, - ]), - ...categoryStatsData.map((item) => [ - 'Categorías', - item.category, - item.Órdenes, - 'Monto ARS', - item.Monto, - ]), - ]; - - return generateCSV(headers, rows); -} diff --git a/src/modules/metrics/Metrics.tsx b/src/modules/metrics/Metrics.tsx index f52ccdb..bab1b0a 100644 --- a/src/modules/metrics/Metrics.tsx +++ b/src/modules/metrics/Metrics.tsx @@ -3,7 +3,6 @@ import { useState } from 'react'; import { toast } from 'sonner'; -import { buildMetricsCSV } from '@/common/helpers/metricsExport'; import { downloadCSV } from '@/lib/utils'; import { CategoryMetricsCharts } from '@/components/metrics/CategoryMetricsCharts'; import { KpiCards } from '@/components/metrics/KpiCards'; @@ -12,6 +11,7 @@ import { StatusDistributionChart } from '@/components/metrics/StatusDistribution import { TimeSeriesCharts } from '@/components/metrics/TimeSeriesCharts'; import { TopProductsRanking } from '@/components/metrics/TopProductsRanking'; import { useMetricsData } from '@/common/hooks/useMetricsData'; +import { ordersService } from '@/services/orders'; export default function Metrics() { const [period, setPeriod] = useState(''); @@ -24,7 +24,7 @@ export default function Metrics() { categoryStatsData, } = useMetricsData(period); - const handleExportCSV = () => { + const handleExportCSV = async () => { if (!period) { toast.error('Seleccioná un período antes de exportar.', { description: 'Debés seleccionar 7, 30 o 90 días para poder exportar los datos.', @@ -32,18 +32,17 @@ export default function Metrics() { return; } - const csv = buildMetricsCSV({ - period, - data, - timeSeriesData, - statusDistributionData, - topProductsData, - categoryStatsData, - }); - downloadCSV(csv, `bazaar-metricas-${period}-${new Date().toISOString().split('T')[0]}.csv`); - toast.success('CSV exportado', { - description: `Datos de ${period} descargados correctamente.`, - }); + try { + const csv = await ordersService.exportStatsCSV(period); + downloadCSV(csv, `bazaar-metricas-${period}-${new Date().toISOString().split('T')[0]}.csv`); + toast.success('CSV exportado', { + description: `Datos de ${period} descargados correctamente.`, + }); + } catch { + toast.error('No se pudo exportar el CSV', { + description: 'Intenta nuevamente más tarde.', + }); + } }; return ( diff --git a/src/services/orders.ts b/src/services/orders.ts index 4946e83..5282c58 100644 --- a/src/services/orders.ts +++ b/src/services/orders.ts @@ -1,4 +1,4 @@ -import Service from './base'; +import Service, { HttpError } from './base'; import secureLocalStorage from 'react-secure-storage'; import { Order, @@ -19,6 +19,19 @@ class OrdersService extends Service { ); } + async exportStatsCSV(period: string): Promise { + const token = secureLocalStorage.getItem('accessToken') as string; + const response = await fetch(`${this.baseUrl}/admin/orders/stats/export?period=${period}`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + + if (!response.ok) throw new HttpError(response.status); + + return response.text(); + } + async getOrders(params: OrderParams): Promise { const token = secureLocalStorage.getItem('accessToken') as string; const queryParams = new URLSearchParams();