237 lines
6.6 KiB
TypeScript
237 lines
6.6 KiB
TypeScript
import {
|
|
Calendar,
|
|
CheckCircle,
|
|
Clock,
|
|
AlertTriangle,
|
|
Zap,
|
|
Shield,
|
|
TrendingUp,
|
|
Package,
|
|
Users,
|
|
Euro,
|
|
BarChart3,
|
|
Target,
|
|
Activity,
|
|
Award
|
|
} from 'lucide-react';
|
|
import { StatsCardProps, StatsCardVariant } from './StatsCard';
|
|
|
|
// Common formatting functions
|
|
export const formatters = {
|
|
percentage: (value: string | number): string => `${value}%`,
|
|
currency: (value: string | number): string => `€${parseFloat(String(value)).toFixed(2)}`,
|
|
number: (value: string | number): string => parseFloat(String(value)).toLocaleString('es-ES'),
|
|
compact: (value: string | number): string => {
|
|
const num = parseFloat(String(value));
|
|
if (num >= 1000000) return `${(num / 1000000).toFixed(1)}M`;
|
|
if (num >= 1000) return `${(num / 1000).toFixed(1)}K`;
|
|
return num.toString();
|
|
},
|
|
};
|
|
|
|
// Icon mappings for common stat types
|
|
export const statIcons = {
|
|
target: Calendar,
|
|
completed: CheckCircle,
|
|
inProgress: Clock,
|
|
pending: AlertTriangle,
|
|
efficiency: Zap,
|
|
quality: Shield,
|
|
growth: TrendingUp,
|
|
inventory: Package,
|
|
users: Users,
|
|
revenue: Euro,
|
|
analytics: BarChart3,
|
|
goals: Target,
|
|
activity: Activity,
|
|
achievement: Award,
|
|
};
|
|
|
|
// Variant mappings for common stat types
|
|
export const statVariants: Record<string, StatsCardVariant> = {
|
|
target: 'default',
|
|
completed: 'success',
|
|
inProgress: 'info',
|
|
pending: 'warning',
|
|
efficiency: 'purple',
|
|
quality: 'success',
|
|
error: 'error',
|
|
revenue: 'success',
|
|
growth: 'success',
|
|
decline: 'error',
|
|
};
|
|
|
|
// Predefined stat configurations for common business metrics
|
|
export const businessMetrics = {
|
|
production: {
|
|
dailyTarget: (value: number): StatsCardProps => ({
|
|
title: 'Meta Diaria',
|
|
value,
|
|
icon: statIcons.target,
|
|
variant: statVariants.target,
|
|
formatValue: formatters.number,
|
|
}),
|
|
completed: (value: number): StatsCardProps => ({
|
|
title: 'Completado',
|
|
value,
|
|
icon: statIcons.completed,
|
|
variant: statVariants.completed,
|
|
formatValue: formatters.number,
|
|
}),
|
|
inProgress: (value: number): StatsCardProps => ({
|
|
title: 'En Proceso',
|
|
value,
|
|
icon: statIcons.inProgress,
|
|
variant: statVariants.inProgress,
|
|
formatValue: formatters.number,
|
|
}),
|
|
pending: (value: number): StatsCardProps => ({
|
|
title: 'Pendiente',
|
|
value,
|
|
icon: statIcons.pending,
|
|
variant: statVariants.pending,
|
|
formatValue: formatters.number,
|
|
}),
|
|
efficiency: (value: number): StatsCardProps => ({
|
|
title: 'Eficiencia',
|
|
value,
|
|
icon: statIcons.efficiency,
|
|
variant: statVariants.efficiency,
|
|
formatValue: formatters.percentage,
|
|
}),
|
|
quality: (value: number): StatsCardProps => ({
|
|
title: 'Calidad',
|
|
value,
|
|
icon: statIcons.quality,
|
|
variant: statVariants.quality,
|
|
formatValue: formatters.percentage,
|
|
}),
|
|
},
|
|
|
|
sales: {
|
|
revenue: (value: number, trend?: { value: number; direction: 'up' | 'down' | 'neutral'; label?: string }): StatsCardProps => ({
|
|
title: 'Ingresos',
|
|
value,
|
|
icon: statIcons.revenue,
|
|
variant: statVariants.revenue,
|
|
formatValue: formatters.currency,
|
|
trend,
|
|
}),
|
|
orders: (value: number, trend?: { value: number; direction: 'up' | 'down' | 'neutral'; label?: string }): StatsCardProps => ({
|
|
title: 'Pedidos',
|
|
value,
|
|
icon: statIcons.analytics,
|
|
variant: statVariants.target,
|
|
formatValue: formatters.number,
|
|
trend,
|
|
}),
|
|
customers: (value: number): StatsCardProps => ({
|
|
title: 'Clientes',
|
|
value,
|
|
icon: statIcons.users,
|
|
variant: statVariants.target,
|
|
formatValue: formatters.number,
|
|
}),
|
|
},
|
|
|
|
inventory: {
|
|
totalItems: (value: number): StatsCardProps => ({
|
|
title: 'Total Items',
|
|
value,
|
|
icon: statIcons.inventory,
|
|
variant: statVariants.target,
|
|
formatValue: formatters.number,
|
|
}),
|
|
lowStock: (value: number): StatsCardProps => ({
|
|
title: 'Stock Bajo',
|
|
value,
|
|
icon: statIcons.pending,
|
|
variant: value > 0 ? statVariants.pending : statVariants.completed,
|
|
formatValue: formatters.number,
|
|
}),
|
|
outOfStock: (value: number): StatsCardProps => ({
|
|
title: 'Sin Stock',
|
|
value,
|
|
icon: statIcons.pending,
|
|
variant: value > 0 ? statVariants.error : statVariants.completed,
|
|
formatValue: formatters.number,
|
|
}),
|
|
},
|
|
|
|
performance: {
|
|
growth: (value: number): StatsCardProps => ({
|
|
title: 'Crecimiento',
|
|
value,
|
|
icon: statIcons.growth,
|
|
variant: value >= 0 ? statVariants.growth : statVariants.decline,
|
|
formatValue: formatters.percentage,
|
|
trend: {
|
|
value: Math.abs(value),
|
|
direction: value >= 0 ? 'up' : 'down',
|
|
label: 'vs mes anterior',
|
|
},
|
|
}),
|
|
satisfaction: (value: number): StatsCardProps => ({
|
|
title: 'Satisfacción',
|
|
value,
|
|
icon: statIcons.achievement,
|
|
variant: value >= 80 ? statVariants.quality : value >= 60 ? statVariants.pending : statVariants.error,
|
|
formatValue: formatters.percentage,
|
|
}),
|
|
},
|
|
};
|
|
|
|
// Quick preset configurations for common page layouts
|
|
export const pagePresets = {
|
|
production: (data: {
|
|
dailyTarget: number;
|
|
completed: number;
|
|
inProgress: number;
|
|
pending: number;
|
|
efficiency: number;
|
|
quality: number;
|
|
}): StatsCardProps[] => [
|
|
businessMetrics.production.dailyTarget(data.dailyTarget),
|
|
businessMetrics.production.completed(data.completed),
|
|
businessMetrics.production.inProgress(data.inProgress),
|
|
businessMetrics.production.pending(data.pending),
|
|
businessMetrics.production.efficiency(data.efficiency),
|
|
businessMetrics.production.quality(data.quality),
|
|
],
|
|
|
|
sales: (data: {
|
|
revenue: number;
|
|
revenueGrowth?: number;
|
|
orders: number;
|
|
ordersGrowth?: number;
|
|
customers: number;
|
|
}): StatsCardProps[] => [
|
|
businessMetrics.sales.revenue(
|
|
data.revenue,
|
|
data.revenueGrowth ? {
|
|
value: data.revenueGrowth,
|
|
direction: data.revenueGrowth >= 0 ? 'up' : 'down',
|
|
label: '%',
|
|
} : undefined
|
|
),
|
|
businessMetrics.sales.orders(
|
|
data.orders,
|
|
data.ordersGrowth ? {
|
|
value: data.ordersGrowth,
|
|
direction: data.ordersGrowth >= 0 ? 'up' : 'down',
|
|
label: '%',
|
|
} : undefined
|
|
),
|
|
businessMetrics.sales.customers(data.customers),
|
|
],
|
|
|
|
inventory: (data: {
|
|
totalItems: number;
|
|
lowStock: number;
|
|
outOfStock: number;
|
|
}): StatsCardProps[] => [
|
|
businessMetrics.inventory.totalItems(data.totalItems),
|
|
businessMetrics.inventory.lowStock(data.lowStock),
|
|
businessMetrics.inventory.outOfStock(data.outOfStock),
|
|
],
|
|
}; |