Add a new analitycs page for production

This commit is contained in:
Urtzi Alfaro
2025-09-24 11:43:25 +02:00
parent 87310ced5f
commit 6cf8d5b935
30 changed files with 6096 additions and 4730 deletions

View File

@@ -0,0 +1,103 @@
import React from 'react';
import { Card } from '../../ui';
import { LucideIcon } from 'lucide-react';
export interface AnalyticsWidgetProps {
title: string;
subtitle?: string;
icon?: LucideIcon;
loading?: boolean;
error?: string;
className?: string;
children: React.ReactNode;
actions?: React.ReactNode;
}
export const AnalyticsWidget: React.FC<AnalyticsWidgetProps> = ({
title,
subtitle,
icon: Icon,
loading = false,
error,
className = '',
children,
actions
}) => {
if (error) {
return (
<Card className={`p-6 ${className}`}>
<div className="flex items-center justify-between mb-4">
<div className="flex items-center space-x-3">
{Icon && (
<div className="w-10 h-10 bg-red-100 dark:bg-red-900/20 rounded-lg flex items-center justify-center">
<Icon className="w-5 h-5 text-red-600 dark:text-red-400" />
</div>
)}
<div>
<h3 className="text-lg font-semibold text-[var(--text-primary)]">{title}</h3>
{subtitle && <p className="text-sm text-[var(--text-secondary)]">{subtitle}</p>}
</div>
</div>
{actions}
</div>
<div className="text-center py-8">
<div className="w-12 h-12 mx-auto bg-red-100 dark:bg-red-900/20 rounded-lg flex items-center justify-center mb-3">
{Icon && <Icon className="w-6 h-6 text-red-600 dark:text-red-400" />}
</div>
<p className="text-sm text-red-600 dark:text-red-400">Error: {error}</p>
</div>
</Card>
);
}
if (loading) {
return (
<Card className={`p-6 ${className}`}>
<div className="flex items-center justify-between mb-4">
<div className="flex items-center space-x-3">
{Icon && (
<div className="w-10 h-10 bg-[var(--bg-tertiary)] rounded-lg flex items-center justify-center">
<Icon className="w-5 h-5 text-[var(--text-tertiary)]" />
</div>
)}
<div>
<h3 className="text-lg font-semibold text-[var(--text-primary)]">{title}</h3>
{subtitle && <p className="text-sm text-[var(--text-secondary)]">{subtitle}</p>}
</div>
</div>
{actions}
</div>
<div className="animate-pulse">
<div className="h-4 bg-[var(--bg-tertiary)] rounded w-3/4 mb-3"></div>
<div className="h-4 bg-[var(--bg-tertiary)] rounded w-1/2 mb-3"></div>
<div className="h-8 bg-[var(--bg-tertiary)] rounded w-full mb-4"></div>
<div className="space-y-2">
<div className="h-4 bg-[var(--bg-tertiary)] rounded"></div>
<div className="h-4 bg-[var(--bg-tertiary)] rounded w-5/6"></div>
<div className="h-4 bg-[var(--bg-tertiary)] rounded w-4/6"></div>
</div>
</div>
</Card>
);
}
return (
<Card className={`p-6 ${className}`}>
<div className="flex items-center justify-between mb-4">
<div className="flex items-center space-x-3">
{Icon && (
<div className="w-10 h-10 bg-[var(--color-primary)]/10 rounded-lg flex items-center justify-center">
<Icon className="w-5 h-5 text-[var(--color-primary)]" />
</div>
)}
<div>
<h3 className="text-lg font-semibold text-[var(--text-primary)]">{title}</h3>
{subtitle && <p className="text-sm text-[var(--text-secondary)]">{subtitle}</p>}
</div>
</div>
{actions}
</div>
{children}
</Card>
);
};