PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.3
Yatra – Travel Booking & Tour Operator Software v3.0.3
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 2.0.10 All 83 releases
yatra / resources / js / components / reports / TaxReport.tsx

TaxReport.tsx in Yatra – Travel Booking & Tour Operator Software 3.0.3, at resources/js/components/reports/TaxReport.tsx

168 lines 5.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Tax Report Component
3 *
4 * Displays tax analytics and reporting for admin dashboard
5 *
6 * @package Yatra.Components.Reports
7 * @since 3.0.0
8 */
9
10 import React from "react";
11 import { taxService } from "../../services/TaxService";
12
13 interface TaxReportProps {
14 bookings: any[];
15 className?: string;
16 }
17
18 const TaxReport: React.FC<TaxReportProps> = ({ bookings, className = "" }) => {
19 // Calculate tax summary
20 const taxSummary = React.useMemo(() => {
21 return taxService.getTaxSummary(bookings);
22 }, [bookings]);
23
24 // Format currency
25 const formatCurrency = (amount: number, currency: string = "USD") => {
26 return new Intl.NumberFormat("en-US", {
27 style: "currency",
28 currency: currency,
29 }).format(amount);
30 };
31
32 if (taxSummary.total_bookings_with_tax === 0) {
33 return (
34 <div
35 className={`bg-white dark:bg-gray-800 rounded-lg shadow p-6 ${className}`}
36 >
37 <h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-4">
38 Tax Report
39 </h3>
40 <div className="text-center py-8 text-gray-500 dark:text-gray-400">
41 <p>No tax data available for the selected period.</p>
42 <p className="text-sm mt-2">
43 Either tax is disabled or no bookings with tax have been made.
44 </p>
45 </div>
46 </div>
47 );
48 }
49
50 return (
51 <div
52 className={`bg-white dark:bg-gray-800 rounded-lg shadow p-6 ${className}`}
53 >
54 <h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-6">
55 Tax Report
56 </h3>
57
58 {/* Summary Cards */}
59 <div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
60 <div className="bg-blue-50 dark:bg-blue-900/20 rounded-lg p-4">
61 <div className="text-sm text-blue-600 dark:text-blue-400 mb-1">
62 Total Tax Collected
63 </div>
64 <div className="text-2xl font-bold text-blue-900 dark:text-blue-100">
65 {formatCurrency(taxSummary.total_tax_collected)}
66 </div>
67 </div>
68
69 <div className="bg-green-50 dark:bg-green-900/20 rounded-lg p-4">
70 <div className="text-sm text-green-600 dark:text-green-400 mb-1">
71 Bookings with Tax
72 </div>
73 <div className="text-2xl font-bold text-green-900 dark:text-green-100">
74 {taxSummary.total_bookings_with_tax}
75 </div>
76 </div>
77
78 <div className="bg-purple-50 dark:bg-purple-900/20 rounded-lg p-4">
79 <div className="text-sm text-purple-600 dark:text-purple-400 mb-1">
80 Average Tax Rate
81 </div>
82 <div className="text-2xl font-bold text-purple-900 dark:text-purple-100">
83 {taxSummary.average_tax_rate.toFixed(2)}%
84 </div>
85 </div>
86 </div>
87
88 {/* Tax Breakdown */}
89 {Object.keys(taxSummary.tax_breakdown).length > 0 && (
90 <div>
91 <h4 className="text-md font-semibold text-gray-900 dark:text-white mb-4">
92 Tax Breakdown by Type
93 </h4>
94 <div className="space-y-3">
95 {Object.entries(taxSummary.tax_breakdown).map(([name, data]) => (
96 <div
97 key={name}
98 className="flex items-center justify-between p-3 bg-gray-50 dark:bg-gray-700/50 rounded-lg"
99 >
100 <div>
101 <div className="font-medium text-gray-900 dark:text-white">
102 {name}
103 </div>
104 <div className="text-sm text-gray-500 dark:text-gray-400">
105 {data.count} bookings • {data.average_rate.toFixed(2)}% avg
106 rate
107 </div>
108 </div>
109 <div className="text-right">
110 <div className="font-semibold text-gray-900 dark:text-white">
111 {formatCurrency(data.total_amount)}
112 </div>
113 <div className="text-sm text-gray-500 dark:text-gray-400">
114 {(
115 (data.total_amount / taxSummary.total_tax_collected) *
116 100
117 ).toFixed(1)}
118 % of total
119 </div>
120 </div>
121 </div>
122 ))}
123 </div>
124 </div>
125 )}
126
127 {/* Tax Insights */}
128 <div className="mt-6 pt-6 border-t border-gray-200 dark:border-gray-700">
129 <h4 className="text-md font-semibold text-gray-900 dark:text-white mb-3">
130 Tax Insights
131 </h4>
132 <div className="grid grid-cols-1 md:grid-cols-2 gap-4 text-sm">
133 <div className="flex items-center space-x-2">
134 <div className="w-2 h-2 bg-green-500 rounded-full"></div>
135 <span className="text-gray-600 dark:text-gray-400">
136 Tax is enabled and actively collected
137 </span>
138 </div>
139 <div className="flex items-center space-x-2">
140 <div className="w-2 h-2 bg-blue-500 rounded-full"></div>
141 <span className="text-gray-600 dark:text-gray-400">
142 {taxSummary.total_bookings_with_tax} taxable bookings this period
143 </span>
144 </div>
145 {taxSummary.average_tax_rate > 0 && (
146 <div className="flex items-center space-x-2">
147 <div className="w-2 h-2 bg-purple-500 rounded-full"></div>
148 <span className="text-gray-600 dark:text-gray-400">
149 Average tax rate: {taxSummary.average_tax_rate.toFixed(2)}%
150 </span>
151 </div>
152 )}
153 {Object.keys(taxSummary.tax_breakdown).length > 1 && (
154 <div className="flex items-center space-x-2">
155 <div className="w-2 h-2 bg-orange-500 rounded-full"></div>
156 <span className="text-gray-600 dark:text-gray-400">
157 Multiple tax types configured
158 </span>
159 </div>
160 )}
161 </div>
162 </div>
163 </div>
164 );
165 };
166
167 export default TaxReport;
168