PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.2.6
Yatra – Travel Booking & Tour Operator Software v3.0.2.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 / trips / TripsTable.tsx

TripsTable.tsx in Yatra – Travel Booking & Tour Operator Software 3.0.2.6, at resources/js/components/trips/TripsTable.tsx

203 lines 6.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Trips Table Component
3 * Modular table component for displaying trips
4 * Supports extensibility for Pro features
5 */
6
7 import React from "react";
8 import { __ } from "../../lib/i18n";
9 import { ConditionalRender } from "../ui/conditional-render";
10 import {
11 Table,
12 TableBody,
13 TableCell,
14 TableHead,
15 TableHeader,
16 TableRow,
17 } from "../ui/table";
18 import { Button } from "../ui/button";
19 import { Badge } from "../ui/badge";
20 import { Edit, Trash2, Eye } from "lucide-react";
21
22 interface Trip {
23 id: number;
24 title: string;
25 slug: string;
26 price: number;
27 status: string;
28 created_at: string;
29 bookings_count?: number;
30 featured?: boolean;
31 }
32
33 interface TripsTableProps {
34 trips: Trip[];
35 loading?: boolean;
36 onEdit?: (trip: Trip) => void;
37 onDelete?: (trip: Trip) => void;
38 onView?: (trip: Trip) => void;
39 showProFeatures?: boolean;
40 }
41
42 /**
43 * Trips Table Component
44 * Displays trips in a table format with actions
45 */
46 export const TripsTable: React.FC<TripsTableProps> = ({
47 trips,
48 loading = false,
49 onEdit,
50 onDelete,
51 onView,
52 showProFeatures = false,
53 }) => {
54 const formatDate = (dateString: string) => {
55 return new Date(dateString).toLocaleDateString();
56 };
57
58 const formatPrice = (price: number) => {
59 return `$${price.toFixed(2)}`;
60 };
61
62 const getStatusBadge = (status: string) => {
63 const statusMap: Record<
64 string,
65 {
66 variant: "default" | "success" | "warning" | "error" | "info";
67 label: string;
68 }
69 > = {
70 active: { variant: "success", label: __("Active", "yatra") },
71 draft: { variant: "default", label: __("Draft", "yatra") },
72 inactive: { variant: "error", label: __("Inactive", "yatra") },
73 pending: { variant: "warning", label: __("Pending", "yatra") },
74 };
75
76 const statusInfo = statusMap[status] || {
77 variant: "default" as const,
78 label: status,
79 };
80 return <Badge variant={statusInfo.variant}>{statusInfo.label}</Badge>;
81 };
82
83 if (loading) {
84 return (
85 <div className="p-8 text-center text-gray-500 dark:text-gray-400">
86 {__("Loading trips...", "yatra")}
87 </div>
88 );
89 }
90
91 if (trips.length === 0) {
92 return (
93 <div className="p-8 text-center text-gray-500 dark:text-gray-400">
94 {__("No trips found", "yatra")}
95 </div>
96 );
97 }
98
99 return (
100 <div className="border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden">
101 <Table>
102 <TableHeader>
103 <TableRow>
104 <TableHead>{__("Title", "yatra")}</TableHead>
105 <TableHead>{__("Slug", "yatra")}</TableHead>
106 <TableHead>{__("Price", "yatra")}</TableHead>
107 <TableHead>{__("Status", "yatra")}</TableHead>
108 {showProFeatures && (
109 <TableHead>{__("Bookings", "yatra")}</TableHead>
110 )}
111 <TableHead>{__("Created", "yatra")}</TableHead>
112 <TableHead className="text-right">
113 {__("Actions", "yatra")}
114 </TableHead>
115 </TableRow>
116 </TableHeader>
117 <TableBody>
118 {trips.map((trip) => (
119 <TableRow key={trip.id}>
120 <TableCell className="font-medium">
121 <div className="flex items-center gap-2">
122 {trip.title}
123 {trip.featured && showProFeatures && (
124 <Badge variant="info" className="text-xs">
125 {__("Featured", "yatra")}
126 </Badge>
127 )}
128 </div>
129 </TableCell>
130 <TableCell className="text-gray-500 dark:text-gray-400">
131 {trip.slug}
132 </TableCell>
133 <TableCell>{formatPrice(trip.price)}</TableCell>
134 <TableCell>{getStatusBadge(trip.status)}</TableCell>
135 {showProFeatures && (
136 <TableCell>{trip.bookings_count || 0}</TableCell>
137 )}
138 <TableCell className="text-gray-500 dark:text-gray-400">
139 {formatDate(trip.created_at)}
140 </TableCell>
141 <TableCell className="text-right">
142 <div className="flex items-center justify-end gap-2">
143 <ConditionalRender capability="yatra_view_trips">
144 {onView && (
145 <Button
146 variant="ghost"
147 size="sm"
148 onClick={() => onView(trip)}
149 aria-label={__("View trip", "yatra")}
150 >
151 <Eye className="w-4 h-4" />
152 </Button>
153 )}
154 </ConditionalRender>
155
156 <ConditionalRender capability="yatra_edit_trips">
157 {onEdit && (
158 <Button
159 variant="ghost"
160 size="sm"
161 onClick={() => onEdit(trip)}
162 aria-label={__("Edit trip", "yatra")}
163 >
164 <Edit className="w-4 h-4" />
165 </Button>
166 )}
167 </ConditionalRender>
168
169 <ConditionalRender capability="yatra_delete_trips">
170 {onDelete && (
171 <Button
172 variant="ghost"
173 size="sm"
174 onClick={() => {
175 if (
176 confirm(
177 __(
178 "Are you sure you want to delete this trip?",
179 "yatra",
180 ),
181 )
182 ) {
183 onDelete(trip);
184 }
185 }}
186 aria-label={__("Delete trip", "yatra")}
187 >
188 <Trash2 className="w-4 h-4 text-red-500" />
189 </Button>
190 )}
191 </ConditionalRender>
192 </div>
193 </TableCell>
194 </TableRow>
195 ))}
196 </TableBody>
197 </Table>
198 </div>
199 );
200 };
201
202 export default TripsTable;
203