PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.17
Yatra – Travel Booking & Tour Operator Software v3.0.17
3.0.17 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 All 85 releases
yatra / assets / dist / js / ApplicableTripSelector-BZ25j59n.js

ApplicableTripSelector-BZ25j59n.js in Yatra – Travel Booking & Tour Operator Software 3.0.17, at assets/dist/js/ApplicableTripSelector-BZ25j59n.js

262 lines 11.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { r as reactExports, u as useQuery, j as jsxRuntimeExports, aP as Search, E as Loader2, ay as X } from "./react-vendor-CithbthY.js";
2 import { _ as __, I as Input, a as apiClient } from "./index-Dec_weLB.js";
3 import { S as Select, B as Button } from "../../admin/dist/js/app.js";
4 const toTripOption = (item) => {
5 const id = Number((item == null ? void 0 : item.id) || 0);
6 const label = (item == null ? void 0 : item.title) || (item == null ? void 0 : item.name) || (item == null ? void 0 : item.slug) || `Trip #${id}`;
7 return { id, label };
8 };
9 const ApplicableTripSelector = ({
10 value,
11 onValueChange,
12 selectedTripIds,
13 onTripIdsChange,
14 description = __(
15 "Control whether this applies to all trips or only selected trips."
16 ),
17 placeholder = __("Click to select trips..."),
18 helperText = __("Only the selected trips will be eligible."),
19 disabled = false
20 }) => {
21 const [showDropdown, setShowDropdown] = reactExports.useState(false);
22 const [searchTerm, setSearchTerm] = reactExports.useState("");
23 const [debouncedSearch, setDebouncedSearch] = reactExports.useState("");
24 reactExports.useEffect(() => {
25 const timer = setTimeout(() => {
26 setDebouncedSearch(searchTerm);
27 }, 300);
28 return () => clearTimeout(timer);
29 }, [searchTerm]);
30 const {
31 data: trips = [],
32 isLoading,
33 isFetching
34 } = useQuery({
35 queryKey: ["applicable-trips", debouncedSearch],
36 queryFn: async () => {
37 var _a;
38 const params = { per_page: 100 };
39 if (debouncedSearch.trim()) {
40 params.search = debouncedSearch.trim();
41 }
42 const response = await apiClient.get("/trips", { params });
43 const items = ((_a = response == null ? void 0 : response.data) == null ? void 0 : _a.data) || (response == null ? void 0 : response.data) || response || [];
44 return Array.isArray(items) ? items.map(toTripOption) : [];
45 },
46 enabled: value === "specific_trips",
47 staleTime: 5 * 60 * 1e3
48 });
49 const { data: selectedTripsData = [] } = useQuery({
50 queryKey: ["selected-trips", selectedTripIds],
51 queryFn: async () => {
52 var _a;
53 if (selectedTripIds.length === 0) return [];
54 try {
55 const response = await apiClient.get("/trips", {
56 params: {
57 per_page: 100,
58 include: selectedTripIds.join(",")
59 // Try to include specific IDs
60 }
61 });
62 const items = ((_a = response == null ? void 0 : response.data) == null ? void 0 : _a.data) || (response == null ? void 0 : response.data) || response || [];
63 const trips2 = Array.isArray(items) ? items.map(toTripOption) : [];
64 return trips2;
65 } catch (error) {
66 console.warn("List API failed, trying individual calls:", error);
67 const results = await Promise.all(
68 selectedTripIds.map(async (id) => {
69 try {
70 const response = await apiClient.get(`/trips/${id}`);
71 if (response == null ? void 0 : response.data) {
72 const trip = toTripOption(response.data);
73 return trip;
74 }
75 } catch (error2) {
76 console.warn(`Failed to fetch trip ${id}:`, error2);
77 }
78 return { id, label: `Trip #${id}` };
79 })
80 );
81 return results;
82 }
83 },
84 enabled: selectedTripIds.length > 0,
85 staleTime: 10 * 60 * 1e3
86 // Cache for 10 minutes
87 });
88 const tripLookup = reactExports.useMemo(() => {
89 const map = /* @__PURE__ */ new Map();
90 trips.forEach((trip) => {
91 map.set(trip.id, trip.label);
92 });
93 selectedTripsData.forEach((trip) => {
94 map.set(trip.id, trip.label);
95 });
96 return map;
97 }, [trips, selectedTripsData]);
98 const selectedChips = reactExports.useMemo(() => {
99 const chips = selectedTripIds.map((id) => ({
100 id,
101 label: tripLookup.get(id) || `Trip #${id}`
102 }));
103 return chips;
104 }, [selectedTripIds, tripLookup]);
105 const toggleTrip = (tripId, checked) => {
106 if (checked) {
107 if (!selectedTripIds.includes(tripId)) {
108 onTripIdsChange([...selectedTripIds, tripId]);
109 }
110 } else {
111 onTripIdsChange(selectedTripIds.filter((id) => id !== tripId));
112 }
113 };
114 const clearTrips = (e) => {
115 e == null ? void 0 : e.stopPropagation();
116 onTripIdsChange([]);
117 };
118 const handleModeChange = (newValue) => {
119 onValueChange(newValue);
120 if (newValue === "all" && selectedTripIds.length > 0) {
121 onTripIdsChange([]);
122 }
123 };
124 return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3", children: [
125 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
126 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400 mb-2", children: description }),
127 /* @__PURE__ */ jsxRuntimeExports.jsxs(
128 Select,
129 {
130 value,
131 onChange: (e) => handleModeChange(e.target.value),
132 disabled,
133 children: [
134 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "all", children: __("All Trips") }),
135 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "specific_trips", children: __("Specific Trips") })
136 ]
137 }
138 )
139 ] }),
140 value === "specific_trips" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2 relative", children: [
141 /* @__PURE__ */ jsxRuntimeExports.jsx(
142 "div",
143 {
144 className: `border border-gray-300 dark:border-gray-600 rounded-lg p-2 cursor-pointer hover:border-gray-400 dark:hover:border-gray-500 bg-white dark:bg-gray-800 ${disabled ? "opacity-70 cursor-not-allowed" : ""}`,
145 onClick: () => !disabled && setShowDropdown((prev) => !prev),
146 children: selectedChips.length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [
147 selectedChips.map((chip) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
148 "span",
149 {
150 className: "inline-flex items-center justify-center gap-1 px-2 py-1.5 text-[11px] font-medium bg-blue-50 text-blue-700 border border-blue-100 rounded-full h-6 min-w-[24px]",
151 children: [
152 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", children: chip.label }),
153 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[9px] text-gray-500 font-normal flex-shrink-0", children: [
154 "#",
155 chip.id
156 ] }),
157 /* @__PURE__ */ jsxRuntimeExports.jsx(
158 "button",
159 {
160 type: "button",
161 onClick: (e) => {
162 e.stopPropagation();
163 toggleTrip(chip.id, false);
164 },
165 className: "hover:text-blue-600 text-[10px] flex-shrink-0 leading-none",
166 children: "×"
167 }
168 )
169 ]
170 },
171 chip.id
172 )),
173 /* @__PURE__ */ jsxRuntimeExports.jsx(
174 Button,
175 {
176 type: "button",
177 variant: "ghost",
178 size: "sm",
179 onClick: clearTrips,
180 className: "text-xs text-red-500 hover:text-red-600 px-2 py-0 h-6 flex items-center",
181 children: __("Clear")
182 }
183 )
184 ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm text-gray-500 dark:text-gray-400", children: placeholder })
185 }
186 ),
187 helperText && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: helperText }),
188 showDropdown && !disabled && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "absolute z-50 w-full mt-1 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-lg shadow-lg", children: [
189 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-2 border-b border-gray-200 dark:border-gray-700", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative", children: [
190 /* @__PURE__ */ jsxRuntimeExports.jsx(
191 Input,
192 {
193 type: "text",
194 value: searchTerm,
195 onChange: (e) => setSearchTerm(e.target.value),
196 placeholder: __("Search trips..."),
197 className: "pl-8"
198 }
199 ),
200 /* @__PURE__ */ jsxRuntimeExports.jsx(Search, { className: "w-4 h-4 text-gray-400 absolute left-2.5 top-1/2 -translate-y-1/2" }),
201 isFetching && /* @__PURE__ */ jsxRuntimeExports.jsx(Loader2, { className: "w-4 h-4 animate-spin text-gray-400 absolute right-2 top-1/2 -translate-y-1/2" })
202 ] }) }),
203 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "max-h-64 overflow-y-auto", children: isLoading ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-4 text-center text-sm text-gray-500 dark:text-gray-400", children: [
204 /* @__PURE__ */ jsxRuntimeExports.jsx(Loader2, { className: "w-5 h-5 animate-spin mx-auto mb-2" }),
205 __("Loading trips...")
206 ] }) : trips.length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "divide-y divide-gray-100 dark:divide-gray-700", children: trips.map((trip) => {
207 const checked = selectedTripIds.includes(trip.id);
208 return /* @__PURE__ */ jsxRuntimeExports.jsxs(
209 "label",
210 {
211 className: "flex items-center gap-3 px-3 py-2 cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700/40",
212 onClick: (e) => e.stopPropagation(),
213 children: [
214 /* @__PURE__ */ jsxRuntimeExports.jsx(
215 "input",
216 {
217 type: "checkbox",
218 checked,
219 onChange: (e) => toggleTrip(trip.id, e.target.checked),
220 className: "w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
221 }
222 ),
223 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 text-sm text-gray-900 dark:text-white truncate", children: trip.label }),
224 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs text-gray-400 dark:text-gray-500", children: [
225 "#",
226 trip.id
227 ] })
228 ]
229 },
230 trip.id
231 );
232 }) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-4 text-center text-sm text-gray-500 dark:text-gray-400", children: searchTerm ? __("No trips found") : __("No trips available") }) }),
233 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-2 border-t border-gray-200 dark:border-gray-700 flex items-center justify-between", children: [
234 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs text-gray-500 dark:text-gray-400", children: [
235 selectedTripIds.length,
236 " ",
237 __("selected")
238 ] }),
239 /* @__PURE__ */ jsxRuntimeExports.jsxs(
240 Button,
241 {
242 type: "button",
243 variant: "ghost",
244 size: "sm",
245 onClick: () => setShowDropdown(false),
246 className: "text-xs",
247 children: [
248 /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "w-4 h-4 mr-1" }),
249 __("Close")
250 ]
251 }
252 )
253 ] })
254 ] })
255 ] })
256 ] });
257 };
258 export {
259 ApplicableTripSelector as A
260 };
261 //# sourceMappingURL=ApplicableTripSelector-BZ25j59n.js.map
262