+ )}
+
+ {/* Card Content */}
+ {!loading && !isEmpty && children}
+
+ );
+};
diff --git a/frontend/src/components/analytics/AnalyticsPageLayout.tsx b/frontend/src/components/analytics/AnalyticsPageLayout.tsx
new file mode 100644
index 00000000..aef2cff8
--- /dev/null
+++ b/frontend/src/components/analytics/AnalyticsPageLayout.tsx
@@ -0,0 +1,219 @@
+import React from 'react';
+import { Lock } from 'lucide-react';
+import { clsx } from 'clsx';
+import { PageHeader } from '../layout';
+import { Card, Button, StatsGrid, Tabs } from '../ui';
+import { ActionButton } from '../layout/PageHeader/PageHeader';
+
+export interface AnalyticsPageLayoutProps {
+ /**
+ * Page title
+ */
+ title: string;
+ /**
+ * Page description
+ */
+ description: string;
+ /**
+ * Action buttons for the page header
+ */
+ actions?: ActionButton[];
+ /**
+ * Key metrics to display in stats grid
+ */
+ stats?: Array<{
+ title: string;
+ value: number | string;
+ variant?: 'success' | 'error' | 'warning' | 'info';
+ icon?: React.ComponentType<{ className?: string }>;
+ subtitle?: string;
+ formatter?: (value: any) => string;
+ }>;
+ /**
+ * Number of columns for stats grid (4 or 6)
+ */
+ statsColumns?: 4 | 6;
+ /**
+ * Tab configuration
+ */
+ tabs?: Array<{
+ id: string;
+ label: string;
+ icon?: React.ComponentType<{ className?: string }>;
+ }>;
+ /**
+ * Active tab ID
+ */
+ activeTab?: string;
+ /**
+ * Tab change handler
+ */
+ onTabChange?: (tabId: string) => void;
+ /**
+ * Optional filters/controls section
+ */
+ filters?: React.ReactNode;
+ /**
+ * Loading state for subscription check
+ */
+ subscriptionLoading?: boolean;
+ /**
+ * Whether user has access to advanced analytics
+ */
+ hasAccess?: boolean;
+ /**
+ * Loading state for data
+ */
+ dataLoading?: boolean;
+ /**
+ * Main content (tab content)
+ */
+ children: React.ReactNode;
+ /**
+ * Custom className for container
+ */
+ className?: string;
+ /**
+ * Show mobile optimization notice
+ */
+ showMobileNotice?: boolean;
+ /**
+ * Custom mobile notice text
+ */
+ mobileNoticeText?: string;
+}
+
+/**
+ * AnalyticsPageLayout - Standardized layout for analytics pages
+ *
+ * Provides consistent structure across all analytics pages:
+ * 1. Page header with title, description, and actions
+ * 2. Optional filters/controls section
+ * 3. Key metrics (StatsGrid with 4 or 6 metrics)
+ * 4. Tab navigation
+ * 5. Tab content area
+ * 6. Subscription checks and access control
+ * 7. Loading states
+ */
+export const AnalyticsPageLayout: React.FC = ({
+ title,
+ description,
+ actions,
+ stats,
+ statsColumns = 4,
+ tabs,
+ activeTab,
+ onTabChange,
+ filters,
+ subscriptionLoading = false,
+ hasAccess = true,
+ dataLoading = false,
+ children,
+ className,
+ showMobileNotice = false,
+ mobileNoticeText,
+}) => {
+ // Show loading state while subscription data is being fetched
+ if (subscriptionLoading) {
+ return (
+
+
+
+
+
+
+ Cargando información de suscripción...
+
+
+
+
+ );
+ }
+
+ // If user doesn't have access to advanced analytics, show upgrade message
+ if (!hasAccess) {
+ return (
+
+
+
+
+
+ Funcionalidad Exclusiva para Profesionales y Empresas
+
+
+ El análisis avanzado está disponible solo para planes Professional y Enterprise.
+ Actualiza tu plan para acceder a métricas avanzadas, análisis detallados y optimización operativa.
+
- );
- }
-
- // If user doesn't have access to advanced analytics, show upgrade message
- if (!hasAdvancedAccess) {
- return (
-
-
-
-
-
-
- Funcionalidad Exclusiva para Profesionales y Empresas
-
-
- La analítica avanzada de compras está disponible solo para planes Professional y Enterprise.
- Actualiza tu plan para acceder a análisis detallados de proveedores, optimización de costos y métricas de rendimiento.
-
+
);
};
diff --git a/frontend/src/pages/app/analytics/performance/PerformanceAnalyticsPage.tsx b/frontend/src/pages/app/analytics/performance/PerformanceAnalyticsPage.tsx
index a42fcc19..05a5b0eb 100644
--- a/frontend/src/pages/app/analytics/performance/PerformanceAnalyticsPage.tsx
+++ b/frontend/src/pages/app/analytics/performance/PerformanceAnalyticsPage.tsx
@@ -7,7 +7,6 @@ import {
AlertCircle,
Download,
Calendar,
- Lock,
BarChart3,
Zap,
DollarSign,
@@ -31,8 +30,8 @@ import {
PolarAngleAxis,
PolarRadiusAxis,
} from 'recharts';
-import { Button, Card, Badge, StatsGrid, Tabs } from '../../../../components/ui';
-import { PageHeader } from '../../../../components/layout';
+import { Badge, Card } from '../../../../components/ui';
+import { AnalyticsPageLayout, AnalyticsCard } from '../../../../components/analytics';
import { useSubscription } from '../../../../api/hooks/subscription';
import { useCurrentTenant } from '../../../../stores/tenant.store';
import {
@@ -101,53 +100,6 @@ const PerformanceAnalyticsPage: React.FC = () => {
departmentsLoading ||
alertsLoading;
- // Show loading state while subscription data is being fetched
- if (subscriptionInfo.loading) {
- return (
-
-
-
-
-
-
Cargando información de suscripción...
-
-
-
- );
- }
-
- // If user doesn't have access to advanced analytics, show upgrade message
- if (!canAccessAnalytics('advanced')) {
- return (
-
-
-
-
-
- Funcionalidad Exclusiva para Profesionales y Empresas
-
-
- El análisis de rendimiento avanzado está disponible solo para planes Professional y Enterprise.
- Actualiza tu plan para acceder a métricas transversales de rendimiento, análisis de procesos integrados y optimización operativa.
-