PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.6
Yatra – Travel Booking & Tour Operator Software v3.0.6
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 / dashboard / RecentBookings.tsx

RecentBookings.tsx in Yatra – Travel Booking & Tour Operator Software 3.0.6, at resources/js/components/dashboard/RecentBookings.tsx

146 lines 4.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Recent Bookings Widget
3 * Displays recent bookings list
4 */
5
6 import React from "react";
7 import { __ } from "../../lib/i18n";
8 import { Card, CardContent, CardHeader, CardTitle } from "../ui/card";
9 import { Badge } from "../ui/badge";
10 import { Calendar, User, ArrowRight } from "lucide-react";
11 import { formatYatraMoney } from "../../lib/currency-display";
12
13 interface Booking {
14 id: number;
15 booking_id: string;
16 customer_name: string;
17 trip_title: string;
18 booking_date: string;
19 total_amount: number;
20 status: "confirmed" | "pending" | "cancelled" | "completed";
21 }
22
23 interface RecentBookingsProps {
24 bookings: Booking[];
25 loading?: boolean;
26 onView?: (booking: Booking) => void;
27 }
28
29 /**
30 * Recent Bookings Widget
31 */
32 export const RecentBookings: React.FC<RecentBookingsProps> = ({
33 bookings,
34 loading = false,
35 onView,
36 }) => {
37 const formatDate = (dateString: string) => {
38 return new Date(dateString).toLocaleDateString("en-US", {
39 month: "short",
40 day: "numeric",
41 year: "numeric",
42 });
43 };
44
45 const globalCurrency = (window as any)?.yatraAdmin?.currency || "USD";
46 const formatCurrency = (amount: number) =>
47 formatYatraMoney(Number(amount) || 0, globalCurrency, {
48 zeroAsUnknown: false,
49 });
50
51 const getStatusColor = (status: string) => {
52 switch (status) {
53 case "confirmed":
54 return "bg-green-100 text-green-700 dark:bg-green-900/20 dark:text-green-400";
55 case "pending":
56 return "bg-yellow-100 text-yellow-700 dark:bg-yellow-900/20 dark:text-yellow-400";
57 case "cancelled":
58 return "bg-red-100 text-red-700 dark:bg-red-900/20 dark:text-red-400";
59 case "completed":
60 return "bg-blue-100 text-blue-700 dark:bg-blue-900/20 dark:text-blue-400";
61 default:
62 return "bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-400";
63 }
64 };
65
66 if (loading) {
67 return (
68 <Card>
69 <CardHeader>
70 <CardTitle>{__("Recent Bookings", "yatra")}</CardTitle>
71 </CardHeader>
72 <CardContent>
73 <div className="text-sm text-gray-500 dark:text-gray-400">
74 {__("Loading...", "yatra")}
75 </div>
76 </CardContent>
77 </Card>
78 );
79 }
80
81 return (
82 <Card>
83 <CardHeader>
84 <CardTitle>{__("Recent Bookings", "yatra")}</CardTitle>
85 </CardHeader>
86 <CardContent>
87 {bookings && bookings.length > 0 ? (
88 <div className="space-y-2">
89 {bookings.slice(0, 5).map((booking) => (
90 <div
91 key={booking.id}
92 className="p-3 rounded-lg border border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-700/50 transition-colors cursor-pointer group"
93 onClick={() => onView && onView(booking)}
94 >
95 <div className="flex items-start justify-between mb-2">
96 <div className="flex-1 min-w-0">
97 <div className="flex items-center gap-2 mb-1">
98 <h4 className="text-sm font-medium text-gray-900 dark:text-white truncate">
99 {booking.trip_title}
100 </h4>
101 <Badge
102 className={`text-xs ${getStatusColor(booking.status)}`}
103 >
104 {booking.status}
105 </Badge>
106 </div>
107 <div className="flex items-center gap-3 text-sm text-gray-500 dark:text-gray-400">
108 <div className="flex items-center gap-1">
109 <User className="w-3 h-3" />
110 <span className="truncate">
111 {booking.customer_name}
112 </span>
113 </div>
114 <div className="flex items-center gap-1">
115 <Calendar className="w-3 h-3" />
116 <span>{formatDate(booking.booking_date)}</span>
117 </div>
118 </div>
119 </div>
120 <div className="flex items-center gap-2 ml-2">
121 <div className="text-right">
122 <p className="text-sm font-semibold text-gray-900 dark:text-white">
123 {formatCurrency(booking.total_amount)}
124 </p>
125 <p className="text-xs text-gray-500 dark:text-gray-400">
126 {booking.booking_id}
127 </p>
128 </div>
129 <ArrowRight className="w-4 h-4 text-gray-400 group-hover:text-gray-600 dark:group-hover:text-gray-300 transition-colors" />
130 </div>
131 </div>
132 </div>
133 ))}
134 </div>
135 ) : (
136 <p className="text-sm text-gray-500 dark:text-gray-400">
137 {__("No recent bookings", "yatra")}
138 </p>
139 )}
140 </CardContent>
141 </Card>
142 );
143 };
144
145 export default RecentBookings;
146