PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.16
Yatra – Travel Booking & Tour Operator Software v3.0.16
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 / BookingStatusChart.tsx

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

104 lines 2.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import React from "react";
2 import {
3 PieChart,
4 Pie,
5 Cell,
6 ResponsiveContainer,
7 Tooltip,
8 Legend,
9 } from "recharts";
10
11 export interface BookingStatusPoint {
12 label: string;
13 value: number;
14 color: string;
15 }
16
17 interface BookingStatusChartProps {
18 data: BookingStatusPoint[];
19 }
20
21 const BookingStatusChart: React.FC<BookingStatusChartProps> = ({ data }) => {
22 const safeData = Array.isArray(data) ? data : [];
23
24 const total = safeData.reduce((sum, item) => sum + (item.value || 0), 0);
25 if (!safeData.length || total <= 0) {
26 return (
27 <div className="flex items-center justify-center h-[140px] text-gray-500 dark:text-gray-400">
28 No data available
29 </div>
30 );
31 }
32
33 // Enrich data with percentage for legend/tooltip
34 const chartData = safeData.map((item) => ({
35 ...item,
36 percent: total > 0 ? (item.value / total) * 100 : 0,
37 }));
38
39 const renderLegend: React.FC<any> = ({ payload }) => {
40 if (!payload || !payload.length) return null;
41 return (
42 <div className="flex flex-col gap-1 text-xs sm:text-sm ml-4">
43 {payload.map((entry: any, index: number) => {
44 const color = entry.color;
45 const label = entry.value as string;
46 const percent = entry.payload?.percent ?? 0;
47 const displayPercent = `${percent.toFixed(1)}%`;
48 return (
49 <div key={index} className="flex items-center gap-2">
50 <span
51 className="inline-block w-3 h-3 rounded"
52 style={{ backgroundColor: color }}
53 />
54 <span className="text-gray-700 dark:text-gray-300">{label}</span>
55 <span className="ml-auto font-medium text-gray-900 dark:text-white">
56 {displayPercent}
57 </span>
58 </div>
59 );
60 })}
61 </div>
62 );
63 };
64
65 return (
66 <div className="w-full" style={{ height: 180 }}>
67 <ResponsiveContainer width="100%" height="100%">
68 <PieChart>
69 <Pie
70 data={chartData}
71 dataKey="value"
72 nameKey="label"
73 cx="40%"
74 cy="50%"
75 innerRadius={50}
76 outerRadius={70}
77 paddingAngle={2}
78 >
79 {chartData.map((entry, index) => (
80 <Cell key={`cell-${index}`} fill={entry.color} />
81 ))}
82 </Pie>
83 <Tooltip
84 formatter={(_value: any, _name: any, props: any) =>
85 `${props.payload.percent.toFixed(1)}%`
86 }
87 contentStyle={{ fontFamily: "inherit", fontSize: 11 }}
88 />
89 <Legend
90 verticalAlign="middle"
91 align="right"
92 layout="vertical"
93 iconType="circle"
94 wrapperStyle={{ fontFamily: "inherit", fontSize: 11 }}
95 content={renderLegend}
96 />
97 </PieChart>
98 </ResponsiveContainer>
99 </div>
100 );
101 };
102
103 export default BookingStatusChart;
104