'use client' import React, { useEffect, useRef, useState, type FC } from 'react' import PropTypes from 'prop-types' import { choices } from '../../../scripts/tokens/choices' import { createChart, LineStyle, CrosshairMode, type LineWidth } from 'lightweight-charts' import { ChartComponent } from '../ChartComponentLightWeight' import { Bar, Doughnut, Pie, Line as LineChartJs } from 'react-chartjs-2' import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Legend, RadialBarChart, Text as TextChart, PolarAngleAxis, RadialBar } from 'recharts' import { Text } from '../../atoms' import { areaConfig, newAreaConfig } from '../ChartComponentLightWeight/chartConfig' import { fi } from 'date-fns/locale' import { getGlobalStyle } from '../../../helpers' interface ChartData { labels: string[] datasets: Array<{ label: string data: number[] backgroundColor: string[] borderColor: string[] borderWidth: number }> } interface ChartOptions { indexAxis: string elements: { bar: { borderWidth: number } } responsive: boolean plugins: { legend: { position: string } title: { display: boolean } } type: string } const dataTest: ChartData = { labels: ['enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio'], datasets: [ { label: 'ejemplo', data: [12, 19, 3, 5, 2, 3], backgroundColor: [ 'rgba(255, 99, 132, 0.2)', 'rgba(54, 162, 235, 0.2)', 'rgba(255, 206, 86, 0.2)', 'rgba(75, 192, 192, 0.2)', 'rgba(153, 102, 255, 0.2)', 'rgba(255, 159, 64, 0.2)' ], borderColor: [ 'rgba(255, 99, 132, 1)', 'rgba(54, 162, 235, 1)', 'rgba(255, 206, 86, 1)', 'rgba(75, 192, 192, 1)', 'rgba(153, 102, 255, 1)', 'rgba(255, 159, 64, 1)' ], borderWidth: 1 } ] } let width: number, height: number, gradient: CanvasGradient function getGradient (ctx: CanvasRenderingContext2D, chartArea: any) { const chartWidth = chartArea.right - chartArea.left const chartHeight = chartArea.bottom - chartArea.top if (!gradient || width !== chartWidth || height !== chartHeight) { // Crea el gradiente si no existe o si cambió el tamaño del gráfico width = chartWidth height = chartHeight gradient = ctx.createLinearGradient(0, chartArea.bottom, 0, chartArea.top) gradient.addColorStop(0, 'blue') gradient.addColorStop(0.5, 'yellow') gradient.addColorStop(1, 'red') } return gradient } const optionsTest: ChartOptions = { indexAxis: 'y', elements: { bar: { borderWidth: 2 } }, responsive: true, plugins: { legend: { position: 'right' }, title: { display: true } }, type: 'doughnut' } interface HorizontalBarChartProps { data?: ChartData options?: ChartOptions } export const HorizontalBarChart: FC = ({ data, options }) => { const chartOptions = { ...options, plugins: { ...options?.plugins }, elements: { line: { backgroundColor: (context: any) => { const { ctx, chartArea } = context.chart if (!chartArea) { // Si el área del gráfico aún no está lista, usa un color por defecto return 'rgba(0, 0, 0, 0.1)' } return getGradient(ctx, chartArea) } } } } return (
) } export const HorizontalBarChartJs: FC = ({ data, options }) => { return (
) } interface CircleProps { data?: ChartData options?: ChartOptions } export const Circle: FC = ({ data, options }) => { return (
) } Circle.propTypes = { data: PropTypes.any, options: PropTypes.any } interface DoughnutCharProps { data?: ChartData options?: ChartOptions } export const DoughnutChar: FC = ({ data, options }) => { return (
) } DoughnutChar.propTypes = { data: PropTypes.any, options: PropTypes.any } interface BarChatProps { data?: ChartData options?: ChartOptions } export const BarChat: FC = ({ data, options }) => { return (
) } BarChat.propTypes = { data: PropTypes.any, options: PropTypes.any } export const LightweightChartComponent = () => { const chartRef = useRef(null) useEffect(() => { // Crear el gráfico y asociarlo con el div const chart = createChart(chartRef.current, { width: chartRef.current.clientWidth, height: chartRef.current.clientHeight }) // Definir los datos y la serie const lineSeries = chart.addLineSeries() lineSeries.setData([ { time: 1633072800, value: 70 }, { time: 1633076400, value: 72 }, { time: 1633080000, value: 75 }, { time: 1633083600, value: 80 } ]) // Limpiar el gráfico cuando el componente se desmonte return () => { chart.remove() } }, []) return
} export const LargeChartComponent = () => { const chartRef = useRef(null) useEffect(() => { // Crear el gráfico y asociarlo con el div const chart = createChart(chartRef.current, { width: chartRef.current.clientWidth, height: chartRef.current.clientHeight, layout: { backgroundColor: '#1E1E1E', // Fondo oscuro para la sección del gráfico textColor: '#D1D4D7' // Color del texto }, grid: { vertLines: { color: '#333' // Color de las líneas verticales }, horzLines: { color: '#333' // Color de las líneas horizontales } }, crosshair: { mode: 0 // Modo de cruce (0=por defecto) }, priceScale: { borderColor: '#555' // Color de borde del eje Y (de precios) }, timeScale: { borderColor: '#555' // Color de borde del eje X (de tiempo) } }) // Crear la serie de velas const candlestickSeries = chart.addCandlestickSeries({ upColor: '#4fff00', // Color para las velas alcistas borderUpColor: '#4fff00', // Color de borde para las velas alcistas wickUpColor: '#4fff00', // Color de la mecha de las velas alcistas downColor: '#ff4976', // Color para las velas bajistas borderDownColor: '#ff4976', // Color de borde para las velas bajistas wickDownColor: '#ff4976' // Color de la mecha de las velas bajistas }) // Datos de ejemplo para las velas (formato: [tiempo, apertura, cierre, mínimo, máximo]) const candlestickData = [ { time: 1633072800, open: 40000, high: 41000, low: 39000, close: 40500 }, { time: 1633076400, open: 40500, high: 42000, low: 40000, close: 41500 }, { time: 1633080000, open: 41500, high: 42500, low: 41000, close: 42000 }, { time: 1633083600, open: 42000, high: 44000, low: 41500, close: 43000 }, { time: 1633087200, open: 43000, high: 45000, low: 42000, close: 44000 }, { time: 1633090800, open: 44000, high: 46000, low: 43000, close: 45000 }, { time: 1633094400, open: 45000, high: 47000, low: 44000, close: 46000 }, { time: 1633098000, open: 46000, high: 48000, low: 45500, close: 47000 } ] // Establecer los datos de la serie candlestickSeries.setData(candlestickData) // Suscripción para el movimiento del cruce (crosshair) chart.subscribeCrosshairMove(function (param) { if (!param || !param.time) return const price = param.seriesData.get(candlestickSeries) console.log(`Price at time ${param.time}: Open: ${price.open}, Close: ${price.close}`) }) // Limpiar el gráfico cuando el componente se desmonte return () => { chart.remove() } }, []) return (
) } export const SalesDashboardChart = () => { useEffect(() => { // Datos proporcionados const data = [ { day: 'Domingos', totalSales: 20000 }, { day: 'Lunes', totalSales: 0 }, { day: 'Martes', totalSales: 35001.8 }, { day: 'Miércoles', totalSales: 0 }, { day: 'Jueves', totalSales: 1000 }, { day: 'Viernes', totalSales: 0 }, { day: 'Sábados', totalSales: 0 } ] // Convertir los días en un arreglo de fechas o índices (timestamps para un gráfico de líneas) const chartData = data.map((item, index) => ({ time: index, // Usa un índice como "time" value: item.totalSales })) // Crear el gráfico const chart = createChart('chart-container', { width: 600, height: 400, crosshair: { mode: CrosshairMode.Normal } }) // Crear la línea de ventas const lineSeries = chart.addLineSeries({ color: '#4e73df', lineStyle: LineStyle.Solid, crosshairMarkerVisible: true, crosshairMarkerRadius: 5 }) // Establecer los datos en la serie lineSeries.setData(chartData.map((item) => ({ time: item.time, value: item.value }))) }, []) return (
) } interface StockMovementsChartProps { className?: string width?: number title?: string height?: number chartData: Array<{ date: string TotalIn: number TotalOut: number }> } export const StockMovementsChart: FC = ({ chartData, className, width = 600, height = 400, title = '' }) => { const stockOutData = chartData.map((item) => ({ time: item.date, value: item.TotalOut })) const stockInData = chartData.map((item) => ({ time: item.date, value: item.TotalIn })) const TotalAdjustment = chartData.map((item) => ({ time: item.date, value: item.TotalAdjustment })) const dataSets = [ { name: 'stock_in', data: stockInData, config: areaConfig }, { name: 'stock_out', data: stockOutData, config: areaConfig }, { name: 'total_adjustment', data: TotalAdjustment, config: { ...areaConfig, lineColor: 'rgba(187, 160, 6, 0.89)' } } ] return (
{title}
) } interface KmhGoalChartProps { current: number goal: number size?: number moneyFormat?: boolean numberFormat?: (value: number) => string bgColor?: string // Color del arco de fondo fgColor?: string // Color del arco de progreso strokeWidth?: number // Grosor del arco fontSize?: string // Tamaño de fuente para texto textColor?: string // Color del texto textWeight?: 'normal' | 'bold' | 'bolder' // Peso del texto rotateText?: boolean // Rotar el texto según el gráfico textPosition?: { x: string, y: string } // Personalización de la posición del texto showPercentage?: boolean // Mostrar o no el porcentaje orientation?: 'horizontal' | 'vertical' | 'full' // Orientación del gráfico startAngle?: number // Ángulo desde el que comienza la línea indicadora (0 a 360 grados) reverseDirection?: boolean // Invertir la dirección del gráfico strokeDasharray?: string // Personalización de la línea (opcional) ref?: React.RefObject } export const KmhGoalChart: React.FC = ({ current, goal, size = 250, moneyFormat = false, numberFormat = (value: number) => value.toString(), bgColor = '#eee', fgColor = getGlobalStyle('--color-primary-red'), strokeWidth = 15, fontSize = 'calc(10px + 1vw)', textColor = '#333', textWeight = 'bold', rotateText = false, textPosition = { x: '50%', y: '58%' }, showPercentage = true, orientation = 'horizontal', // Default to horizontal startAngle = 180, // Default starting at 180 degrees (top) reverseDirection = false, strokeDasharray = '', // Default to no dash pattern ref }) => { const radius = 100 const percentage = Math.min((current / goal) * 100, 100) // Calcular el ángulo en base al porcentaje const angle = (percentage / 100) * (orientation === 'full' ? 360 : 180) const adjustedStartAngle = reverseDirection ? startAngle + 180 : startAngle const endAngle = adjustedStartAngle - angle const polarToCartesian = (centerX: number, centerY: number, radius: number, angleInDegrees: number) => { const angleInRadians = ((angleInDegrees - 90) * Math.PI) / 180.0 return { x: centerX + radius * Math.cos(angleInRadians), y: centerY + radius * Math.sin(angleInRadians) } } const describeArc = (x: number, y: number, radius: number, startAngle: number, endAngle: number) => { const start = polarToCartesian(x, y, radius, endAngle) const end = polarToCartesian(x, y, radius, startAngle) const largeArcFlag = startAngle - endAngle <= 180 ? '0' : '1' return [ 'M', start.x, start.y, 'A', radius, radius, 0, largeArcFlag, 1, end.x, end.y ].join(' ') } const transformText = rotateText ? 'rotate(270)' : undefined return (
{/* Background arc */} {/* Foreground arc */} {/* Percentage text */} {showPercentage && ( {!isNaN(percentage) && percentage > 0 ? `${Math.round(percentage)}%` : '0%'} )} {/* Additional text */} {moneyFormat ? `${numberFormat(current)} de ${numberFormat(goal)}` : `${current} de ${goal}`}
) }