PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.13
Yatra – Travel Booking & Tour Operator Software v3.0.13
3.0.16 3.0.15 3.0.14 3.0.14.1 3.0.14.2 3.0.12 3.0.13 3.0.11 3.0.10 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.5.1 3.0.4 3.0.3 3.0.2.9 3.0.2.7 3.0.2.8 3.0.2.6 trunk 1.0.0 2.0.0 2.0.1 All 84 releases
yatra / resources / js / components / charts / SimplePieChart.tsx

SimplePieChart.tsx in Yatra – Travel Booking & Tour Operator Software 3.0.13, at resources/js/components/charts/SimplePieChart.tsx

145 lines 4.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Simple Pie Chart Component
3 * Lightweight pie/donut chart for displaying proportions
4 */
5
6 import React from "react";
7 import { __ } from "../../lib/i18n";
8
9 interface PieData {
10 label: string;
11 value: number;
12 color: string;
13 }
14
15 interface SimplePieChartProps {
16 data: PieData[];
17 title: string;
18 size?: number;
19 showLegend?: boolean;
20 donut?: boolean;
21 }
22
23 /**
24 * Simple Pie Chart Component
25 */
26 export const SimplePieChart: React.FC<SimplePieChartProps> = ({
27 data,
28 title,
29 size = 200,
30 showLegend = true,
31 donut = false,
32 }) => {
33 if (!data || data.length === 0) {
34 return (
35 <div className="flex items-center justify-center h-full text-gray-500 dark:text-gray-400">
36 {__("No data available", "yatra")}
37 </div>
38 );
39 }
40
41 const total = data.reduce((sum, item) => sum + item.value, 0);
42 if (total <= 0) {
43 return (
44 <div className="flex items-center justify-center h-full text-gray-500 dark:text-gray-400">
45 {__("No data available", "yatra")}
46 </div>
47 );
48 }
49 const center = size / 2;
50 const radius = donut ? size / 3 : size / 2 - 10;
51 const innerRadius = donut ? size / 4 : 0;
52
53 let currentAngle = -90; // Start from top
54
55 const paths = data.map((item) => {
56 const percentage = (item.value / total) * 100;
57 const angle = (item.value / total) * 360;
58 const startAngle = currentAngle;
59 const endAngle = currentAngle + angle;
60
61 // Calculate arc path
62 const startX = center + radius * Math.cos((startAngle * Math.PI) / 180);
63 const startY = center + radius * Math.sin((startAngle * Math.PI) / 180);
64 const endX = center + radius * Math.cos((endAngle * Math.PI) / 180);
65 const endY = center + radius * Math.sin((endAngle * Math.PI) / 180);
66
67 const largeArcFlag = angle > 180 ? 1 : 0;
68
69 let pathData = "";
70 if (donut && innerRadius > 0) {
71 // Donut chart
72 const innerStartX =
73 center + innerRadius * Math.cos((startAngle * Math.PI) / 180);
74 const innerStartY =
75 center + innerRadius * Math.sin((startAngle * Math.PI) / 180);
76 const innerEndX =
77 center + innerRadius * Math.cos((endAngle * Math.PI) / 180);
78 const innerEndY =
79 center + innerRadius * Math.sin((endAngle * Math.PI) / 180);
80
81 pathData = `M ${startX} ${startY} A ${radius} ${radius} 0 ${largeArcFlag} 1 ${endX} ${endY} L ${innerEndX} ${innerEndY} A ${innerRadius} ${innerRadius} 0 ${largeArcFlag} 0 ${innerStartX} ${innerStartY} Z`;
82 } else {
83 // Regular pie chart
84 pathData = `M ${center} ${center} L ${startX} ${startY} A ${radius} ${radius} 0 ${largeArcFlag} 1 ${endX} ${endY} Z`;
85 }
86
87 currentAngle += angle;
88
89 return {
90 path: pathData,
91 color: item.color,
92 label: item.label,
93 value: item.value,
94 percentage: percentage.toFixed(1),
95 };
96 });
97
98 return (
99 <div className="w-full h-full">
100 {title && (
101 <h3 className="text-sm font-medium text-gray-700 dark:text-gray-300 mb-4">
102 {title}
103 </h3>
104 )}
105 <div className="flex flex-col md:flex-row items-center gap-6">
106 <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
107 {paths.map((path, index) => (
108 <path
109 key={index}
110 d={path.path}
111 fill={path.color}
112 stroke="#fff"
113 strokeWidth="2"
114 className="hover:opacity-80 transition-opacity cursor-pointer"
115 >
116 <title>{`${path.label}: ${path.value} (${path.percentage}%)`}</title>
117 </path>
118 ))}
119 </svg>
120
121 {showLegend && (
122 <div className="flex flex-col gap-2">
123 {paths.map((path, index) => (
124 <div key={index} className="flex items-center gap-2">
125 <div
126 className="w-4 h-4 rounded"
127 style={{ backgroundColor: path.color }}
128 />
129 <span className="text-sm text-gray-700 dark:text-gray-300">
130 {path.label}
131 </span>
132 <span className="text-sm font-medium text-gray-900 dark:text-white ml-auto">
133 {path.percentage}%
134 </span>
135 </div>
136 ))}
137 </div>
138 )}
139 </div>
140 </div>
141 );
142 };
143
144 export default SimplePieChart;
145