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 / assets / dist / js / RecurringRuleForm-fKEgpUir.js

RecurringRuleForm-fKEgpUir.js in Yatra – Travel Booking & Tour Operator Software 3.0.16, at assets/dist/js/RecurringRuleForm-fKEgpUir.js

2,243 lines 129.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { j as jsxRuntimeExports, v as useQueryClient, r as reactExports, u as useQuery, w as useMutation, D as ArrowLeft, O as RefreshCw, ax as Plus, ay as X, at as DollarSign, aA as AlertCircle, as as Clock, s as MapPin, aE as CheckCircle2, aR as Eye, aW as Save } from "./react-vendor-CithbthY.js";
2 import { u as useToast, g as todayYmd, _ as __, S as SearchableSelect, I as Input, t as toDateValue, a as apiClient } from "./index-Dec_weLB.js";
3 import { C as Card, f as CardHeader, d as CardContent, P as PageHeader, B as Button, g as CardTitle, S as Select, D as DatePicker, e as Badge, h as CardDescription, T as TimePicker, L as LocationPicker, A as Alert, a8 as useNavigate } from "../../admin/dist/js/app.js";
4 const RecurringRuleFormSkeleton = () => {
5 return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-6", children: [
6 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "animate-pulse", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between mb-4", children: [
7 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
8 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-8 bg-gray-200 dark:bg-gray-700 rounded w-64 mb-2" }),
9 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-96" })
10 ] }),
11 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-10 bg-gray-200 dark:bg-gray-700 rounded w-40" })
12 ] }) }),
13 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-3 gap-6", children: [
14 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "lg:col-span-2 space-y-6", children: [
15 /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [
16 /* @__PURE__ */ jsxRuntimeExports.jsx(CardHeader, { children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-6 bg-gray-200 dark:bg-gray-700 rounded w-40 animate-pulse" }) }),
17 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { className: "space-y-4", children: [
18 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4 animate-pulse", children: [
19 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
20 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-16" }),
21 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-10 bg-gray-200 dark:bg-gray-700 rounded" })
22 ] }),
23 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
24 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-24" }),
25 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-10 bg-gray-200 dark:bg-gray-700 rounded" })
26 ] })
27 ] }),
28 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2 animate-pulse", children: [
29 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-20" }),
30 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-10 bg-gray-200 dark:bg-gray-700 rounded" })
31 ] })
32 ] })
33 ] }),
34 /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [
35 /* @__PURE__ */ jsxRuntimeExports.jsx(CardHeader, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 animate-pulse", children: [
36 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-5 w-5 bg-gray-200 dark:bg-gray-700 rounded" }),
37 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-6 bg-gray-200 dark:bg-gray-700 rounded w-44" })
38 ] }) }),
39 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { className: "space-y-4", children: [
40 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "animate-pulse", children: [
41 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-28 mb-3" }),
42 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-wrap gap-2", children: [...Array(7)].map((_, i) => /* @__PURE__ */ jsxRuntimeExports.jsx(
43 "div",
44 {
45 className: "h-10 bg-gray-200 dark:bg-gray-700 rounded w-24"
46 },
47 i
48 )) })
49 ] }),
50 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4 pt-4 border-t border-gray-200 dark:border-gray-700 animate-pulse", children: [
51 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
52 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-24" }),
53 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-10 bg-gray-200 dark:bg-gray-700 rounded" })
54 ] }),
55 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
56 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-20" }),
57 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-10 bg-gray-200 dark:bg-gray-700 rounded" })
58 ] })
59 ] }),
60 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "pt-4 border-t border-gray-200 dark:border-gray-700 animate-pulse", children: [
61 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-32 mb-2" }),
62 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2 mb-2", children: [
63 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 h-10 bg-gray-200 dark:bg-gray-700 rounded" }),
64 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-10 w-10 bg-gray-200 dark:bg-gray-700 rounded" })
65 ] })
66 ] })
67 ] })
68 ] }),
69 /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [
70 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardHeader, { children: [
71 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 animate-pulse", children: [
72 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-5 w-5 bg-gray-200 dark:bg-gray-700 rounded" }),
73 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-6 bg-gray-200 dark:bg-gray-700 rounded w-44" })
74 ] }),
75 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-80 mt-2 animate-pulse" })
76 ] }),
77 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { className: "space-y-6", children: [
78 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-4 bg-gray-100 dark:bg-gray-800/50 rounded-lg animate-pulse", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
79 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-9 w-9 bg-gray-200 dark:bg-gray-700 rounded-full" }),
80 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1", children: [
81 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-40 mb-2" }),
82 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-3 bg-gray-200 dark:bg-gray-700 rounded w-72" })
83 ] })
84 ] }) }),
85 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4 animate-pulse", children: [
86 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
87 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-28" }),
88 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-10 bg-gray-200 dark:bg-gray-700 rounded" })
89 ] }),
90 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
91 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-24" }),
92 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-10 bg-gray-200 dark:bg-gray-700 rounded" })
93 ] })
94 ] }),
95 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "pt-4 border-t border-gray-200 dark:border-gray-700 animate-pulse", children: [
96 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-5 bg-gray-200 dark:bg-gray-700 rounded w-44 mb-4" }),
97 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
98 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
99 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-28" }),
100 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-10 bg-gray-200 dark:bg-gray-700 rounded" })
101 ] }),
102 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
103 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-32" }),
104 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-10 bg-gray-200 dark:bg-gray-700 rounded" })
105 ] })
106 ] })
107 ] })
108 ] })
109 ] }),
110 /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [
111 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardHeader, { children: [
112 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 animate-pulse", children: [
113 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-5 w-5 bg-gray-200 dark:bg-gray-700 rounded" }),
114 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-6 bg-gray-200 dark:bg-gray-700 rounded w-36" })
115 ] }),
116 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex gap-2 mt-2 animate-pulse", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-5 bg-gray-200 dark:bg-gray-700 rounded w-28" }) })
117 ] }),
118 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { className: "space-y-4", children: [
119 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between animate-pulse", children: [
120 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-24" }),
121 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-8 bg-gray-200 dark:bg-gray-700 rounded w-24" })
122 ] }),
123 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center py-6 bg-gray-50 dark:bg-gray-800 rounded-lg border-2 border-dashed border-gray-200 dark:border-gray-700 animate-pulse", children: [
124 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-8 w-8 bg-gray-200 dark:bg-gray-700 rounded mx-auto mb-2" }),
125 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-36 mx-auto mb-2" }),
126 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-3 bg-gray-200 dark:bg-gray-700 rounded w-64 mx-auto" })
127 ] }),
128 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4 pt-4 border-t border-gray-200 dark:border-gray-700 animate-pulse", children: [
129 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
130 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-28" }),
131 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-10 bg-gray-200 dark:bg-gray-700 rounded" })
132 ] }),
133 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
134 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-24" }),
135 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-10 bg-gray-200 dark:bg-gray-700 rounded" })
136 ] })
137 ] }),
138 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "animate-pulse", children: [
139 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-48 mb-2" }),
140 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-10 bg-gray-200 dark:bg-gray-700 rounded" })
141 ] })
142 ] })
143 ] })
144 ] }),
145 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-6", children: [
146 /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [
147 /* @__PURE__ */ jsxRuntimeExports.jsx(CardHeader, { children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-6 bg-gray-200 dark:bg-gray-700 rounded w-16 animate-pulse" }) }),
148 /* @__PURE__ */ jsxRuntimeExports.jsx(CardContent, { children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-10 bg-gray-200 dark:bg-gray-700 rounded animate-pulse" }) })
149 ] }),
150 /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [
151 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardHeader, { children: [
152 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 animate-pulse", children: [
153 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-5 w-5 bg-gray-200 dark:bg-gray-700 rounded" }),
154 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-6 bg-gray-200 dark:bg-gray-700 rounded w-20" })
155 ] }),
156 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-48 mt-2 animate-pulse" })
157 ] }),
158 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { children: [
159 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-10 bg-gray-200 dark:bg-gray-700 rounded w-full mb-4 animate-pulse" }),
160 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-2 animate-pulse", children: [...Array(5)].map((_, i) => /* @__PURE__ */ jsxRuntimeExports.jsx(
161 "div",
162 {
163 className: "h-6 bg-gray-200 dark:bg-gray-700 rounded"
164 },
165 i
166 )) })
167 ] })
168 ] }),
169 /* @__PURE__ */ jsxRuntimeExports.jsx(Card, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(CardContent, { className: "pt-6", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3 animate-pulse", children: [
170 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-10 bg-gray-200 dark:bg-gray-700 rounded" }),
171 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-10 bg-gray-200 dark:bg-gray-700 rounded" })
172 ] }) }) }),
173 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-4 bg-gray-100 dark:bg-gray-800/50 rounded-lg border border-gray-200 dark:border-gray-700 animate-pulse", children: [
174 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-24 mb-2" }),
175 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "h-12 bg-gray-200 dark:bg-gray-700 rounded" })
176 ] })
177 ] })
178 ] })
179 ] });
180 };
181 function coordFromApi(v) {
182 if (v == null || v === "") return "";
183 return String(v);
184 }
185 const isPeriod = (e) => typeof e === "object" && e !== null && "start" in e && "end" in e;
186 const excludedSortKey = (e) => isPeriod(e) ? e.start : e;
187 const excludedId = (e) => isPeriod(e) ? `${e.start}..${e.end}` : e;
188 const dayOptions = [
189 { value: 0, label: "Sunday" },
190 { value: 1, label: "Monday" },
191 { value: 2, label: "Tuesday" },
192 { value: 3, label: "Wednesday" },
193 { value: 4, label: "Thursday" },
194 { value: 5, label: "Friday" },
195 { value: 6, label: "Saturday" }
196 ];
197 const weekOptions = [
198 { value: "first", label: "First" },
199 { value: "second", label: "Second" },
200 { value: "third", label: "Third" },
201 { value: "fourth", label: "Fourth" },
202 { value: "last", label: "Last" }
203 ];
204 const RecurringRuleForm = () => {
205 var _a, _b;
206 const { navigate } = useNavigate();
207 const queryClient = useQueryClient();
208 const { showToast } = useToast();
209 const params = new URLSearchParams(window.location.search);
210 const ruleId = params.get("id");
211 const tripIdFromUrl = params.get("trip_id");
212 const isEditing = !!ruleId;
213 const [formData, setFormData] = reactExports.useState({
214 trip_id: tripIdFromUrl ? parseInt(tripIdFromUrl) : 0,
215 name: "",
216 rule_type: "weekly",
217 days_of_week: [0],
218 // Sunday by default
219 week_of_month: "first",
220 day_of_week: 0,
221 interval_days: 7,
222 start_date: todayYmd(),
223 end_date: "",
224 excluded_dates: [],
225 months: [],
226 // Empty = all months, otherwise specific months (1-12)
227 time_slots: [],
228 // For single-day trips with multiple slots
229 pricing_type: "regular",
230 // Will be updated based on trip's pricing type
231 original_price: void 0,
232 sale_price: void 0,
233 traveler_pricing: [],
234 // For traveler-based pricing
235 seats_total: 20,
236 departure_time: "",
237 arrival_time: "",
238 from_location: "",
239 to_location: "",
240 from_latitude: "",
241 from_longitude: "",
242 to_latitude: "",
243 to_longitude: "",
244 cutoff_hours: 24,
245 alert_threshold: 5,
246 status: "active"
247 });
248 const [newExcludedDate, setNewExcludedDate] = reactExports.useState("");
249 const [newExcludedStart, setNewExcludedStart] = reactExports.useState("");
250 const [newExcludedEnd, setNewExcludedEnd] = reactExports.useState("");
251 const [excludedError, setExcludedError] = reactExports.useState("");
252 const [previewData, setPreviewData] = reactExports.useState(null);
253 const [showCategorySelector, setShowCategorySelector] = reactExports.useState(false);
254 const { data: tripsData } = useQuery({
255 queryKey: ["trips", "all"],
256 queryFn: async () => {
257 const response = await apiClient.get("/trips", {
258 params: { per_page: 100, status: "publish" }
259 });
260 return {
261 trips: ((response == null ? void 0 : response.data) || []).map((trip) => {
262 const rawPriceTypes = trip.price_types;
263 const hasTravelerPricing = Array.isArray(rawPriceTypes) ? rawPriceTypes.length > 0 : false;
264 const effectivePricingType = hasTravelerPricing ? "traveler_based" : trip.pricing_type || "regular";
265 return {
266 id: Number(trip.id) || 0,
267 title: trip.title,
268 trip_type: trip.trip_type || (trip.duration_days <= 1 ? "single_day" : "multi_day"),
269 duration_days: trip.duration_days || 1,
270 starting_location: trip.starting_location,
271 ending_location: trip.ending_location,
272 pricing_type: effectivePricingType
273 };
274 })
275 };
276 }
277 });
278 const { data: travelerCategories = [] } = useQuery({
279 queryKey: ["traveler-categories"],
280 queryFn: async () => {
281 const response = await apiClient.get("/traveler-categories", {
282 params: { per_page: 100 }
283 });
284 return (response == null ? void 0 : response.data) || [];
285 }
286 });
287 const selectedTrip = tripsData == null ? void 0 : tripsData.trips.find((t) => t.id === formData.trip_id);
288 const { data: tripForLocations } = useQuery({
289 queryKey: ["trip", formData.trip_id, "recurring-rule-locations"],
290 queryFn: async () => {
291 const response = await apiClient.get(`/trips/${formData.trip_id}`);
292 return (response == null ? void 0 : response.data) || response || null;
293 },
294 enabled: formData.trip_id > 0,
295 staleTime: 5 * 60 * 1e3
296 });
297 const { data: fallbackTripData } = useQuery({
298 queryKey: ["trip", formData.trip_id, "recurring-rule-form"],
299 queryFn: async () => {
300 if (!formData.trip_id || selectedTrip) {
301 return null;
302 }
303 const response = await apiClient.get(`/trips/${formData.trip_id}`);
304 return (response == null ? void 0 : response.data) || response || null;
305 },
306 enabled: !!formData.trip_id && !selectedTrip,
307 staleTime: 5 * 60 * 1e3
308 });
309 const effectiveTrip = selectedTrip || (fallbackTripData ? {
310 id: Number(fallbackTripData.id) || formData.trip_id,
311 title: fallbackTripData.title
312 } : null);
313 const tripNameLabel = (effectiveTrip == null ? void 0 : effectiveTrip.title) || __("Unnamed Trip", "yatra");
314 let headerDescription = __(
315 "Set up automatic availability patterns for your trips",
316 "yatra"
317 );
318 if (effectiveTrip) {
319 headerDescription = `${isEditing ? __("Edit", "yatra") : __("Add", "yatra")} ${__("availability rule for", "yatra")} ${tripNameLabel} (Trip ID: ${effectiveTrip.id})`;
320 } else if (formData.trip_id) {
321 headerDescription = `${isEditing ? __("Edit", "yatra") : __("Add", "yatra")} ${__("availability rule for Trip ID:", "yatra")} ${formData.trip_id}`;
322 }
323 const isSingleDayTrip = (selectedTrip == null ? void 0 : selectedTrip.trip_type) === "single_day" || ((selectedTrip == null ? void 0 : selectedTrip.duration_days) || 1) <= 1;
324 const isTravelerBasedPricing = formData.pricing_type === "traveler_based";
325 const { data: existingRule, isLoading: isLoadingRule } = useQuery({
326 queryKey: ["recurring-availability", ruleId],
327 queryFn: async () => {
328 if (!ruleId) return null;
329 const response = await apiClient.get(`/recurring-availability/${ruleId}`);
330 return (response == null ? void 0 : response.data) || response;
331 },
332 enabled: !!ruleId
333 });
334 reactExports.useEffect(() => {
335 if (existingRule && tripsData) {
336 let daysOfWeek = [0];
337 if (existingRule.days_of_week_array && Array.isArray(existingRule.days_of_week_array)) {
338 daysOfWeek = existingRule.days_of_week_array;
339 } else if (existingRule.days_of_week) {
340 if (typeof existingRule.days_of_week === "string") {
341 daysOfWeek = existingRule.days_of_week.split(",").map(Number).filter((n) => !isNaN(n));
342 } else if (Array.isArray(existingRule.days_of_week)) {
343 daysOfWeek = existingRule.days_of_week.map(Number);
344 }
345 }
346 const ruleType = existingRule.rule_type || "weekly";
347 const tripRow = tripsData.trips.find(
348 (t) => t.id === Number(existingRule.trip_id)
349 );
350 const effectivePricingType = (tripRow == null ? void 0 : tripRow.pricing_type) || ((tripForLocations == null ? void 0 : tripForLocations.price_types) && Array.isArray(tripForLocations.price_types) && tripForLocations.price_types.length > 0 ? "traveler_based" : tripForLocations == null ? void 0 : tripForLocations.pricing_type) || "regular";
351 setFormData({
352 trip_id: existingRule.trip_id || 0,
353 name: existingRule.name || "",
354 rule_type: ruleType,
355 days_of_week: daysOfWeek.length > 0 ? daysOfWeek : [0],
356 week_of_month: existingRule.week_of_month || "first",
357 day_of_week: existingRule.day_of_week ?? 0,
358 interval_days: existingRule.interval_days || 7,
359 start_date: existingRule.start_date || todayYmd(),
360 end_date: existingRule.end_date || "",
361 excluded_dates: Array.isArray(existingRule.excluded_dates) ? existingRule.excluded_dates : [],
362 months: Array.isArray(existingRule.months) ? existingRule.months : [],
363 time_slots: Array.isArray(existingRule.time_slots) ? existingRule.time_slots : [],
364 pricing_type: effectivePricingType,
365 original_price: existingRule.original_price,
366 sale_price: existingRule.sale_price,
367 traveler_pricing: Array.isArray(existingRule.traveler_pricing) ? existingRule.traveler_pricing : [],
368 seats_total: existingRule.seats_total || 20,
369 departure_time: existingRule.departure_time || "",
370 arrival_time: existingRule.arrival_time || "",
371 from_location: existingRule.from_location || "",
372 to_location: existingRule.to_location || "",
373 from_latitude: coordFromApi(existingRule.from_latitude),
374 from_longitude: coordFromApi(existingRule.from_longitude),
375 to_latitude: coordFromApi(existingRule.to_latitude),
376 to_longitude: coordFromApi(existingRule.to_longitude),
377 cutoff_hours: existingRule.cutoff_hours || 24,
378 alert_threshold: existingRule.alert_threshold || 5,
379 status: existingRule.status || "active"
380 });
381 }
382 }, [existingRule, tripsData, tripForLocations]);
383 reactExports.useEffect(() => {
384 if (!isEditing && !existingRule) {
385 const inferred = (() => {
386 const priceTypes = tripForLocations == null ? void 0 : tripForLocations.price_types;
387 const hasTravelerPricing = Array.isArray(priceTypes) && priceTypes.length > 0;
388 return hasTravelerPricing ? "traveler_based" : (selectedTrip == null ? void 0 : selectedTrip.pricing_type) || (tripForLocations == null ? void 0 : tripForLocations.pricing_type) || "regular";
389 })();
390 setFormData((prev) => ({
391 ...prev,
392 ...selectedTrip || tripForLocations ? {
393 pricing_type: inferred
394 } : {},
395 ...tripForLocations ? {
396 from_location: prev.from_location || tripForLocations.starting_location || "",
397 to_location: prev.to_location || tripForLocations.ending_location || "",
398 from_latitude: prev.from_latitude || coordFromApi(tripForLocations.starting_latitude),
399 from_longitude: prev.from_longitude || coordFromApi(tripForLocations.starting_longitude),
400 to_latitude: prev.to_latitude || coordFromApi(tripForLocations.ending_latitude),
401 to_longitude: prev.to_longitude || coordFromApi(tripForLocations.ending_longitude)
402 } : {}
403 }));
404 }
405 }, [isEditing, selectedTrip, tripForLocations, existingRule]);
406 const createMutation = useMutation({
407 mutationFn: async (data) => {
408 return await apiClient.post("/recurring-availability", {
409 ...data,
410 days_of_week: Array.isArray(data.days_of_week) ? data.days_of_week : [],
411 // Normalize month-week selector to backend contract.
412 week_of_month: data.rule_type === "monthly" ? (data.week_of_month || "first").toLowerCase() : data.week_of_month,
413 // On create, omit empty arrays to keep payload small.
414 time_slots: data.time_slots.length > 0 ? data.time_slots : void 0,
415 traveler_pricing: data.traveler_pricing && data.traveler_pricing.length > 0 ? data.traveler_pricing : void 0
416 });
417 },
418 onSuccess: () => {
419 queryClient.invalidateQueries({ queryKey: ["recurring-availability"] });
420 showToast(__("Recurring rule created successfully", "yatra"), "success");
421 navigate({
422 subpage: "trips",
423 tab: "availability",
424 trip_id: formData.trip_id.toString()
425 });
426 },
427 onError: (error) => {
428 showToast(
429 (error == null ? void 0 : error.message) || __("Failed to create rule", "yatra"),
430 "error"
431 );
432 }
433 });
434 const updateMutation = useMutation({
435 mutationFn: async (data) => {
436 return await apiClient.put(`/recurring-availability/${ruleId}`, {
437 ...data,
438 days_of_week: Array.isArray(data.days_of_week) ? data.days_of_week : [],
439 week_of_month: data.rule_type === "monthly" ? (data.week_of_month || "first").toLowerCase() : data.week_of_month,
440 // IMPORTANT: on update, send empty arrays explicitly to clear persisted
441 // JSON columns; omitting the key leaves the old value in DB.
442 time_slots: Array.isArray(data.time_slots) ? data.time_slots : [],
443 traveler_pricing: Array.isArray(data.traveler_pricing) ? data.traveler_pricing : []
444 });
445 },
446 onSuccess: () => {
447 queryClient.invalidateQueries({ queryKey: ["recurring-availability"] });
448 showToast(__("Recurring rule updated successfully", "yatra"), "success");
449 navigate({
450 subpage: "trips",
451 tab: "availability",
452 trip_id: formData.trip_id.toString()
453 });
454 },
455 onError: (error) => {
456 showToast(
457 (error == null ? void 0 : error.message) || __("Failed to update rule", "yatra"),
458 "error"
459 );
460 }
461 });
462 const previewMutation = useMutation({
463 mutationFn: async (data) => {
464 return await apiClient.post("/recurring-availability/preview", {
465 ...data,
466 days_of_week: Array.isArray(data.days_of_week) ? data.days_of_week : [],
467 week_of_month: data.rule_type === "monthly" ? (data.week_of_month || "first").toLowerCase() : data.week_of_month,
468 time_slots: data.time_slots.length > 0 ? data.time_slots : void 0,
469 traveler_pricing: data.traveler_pricing && data.traveler_pricing.length > 0 ? data.traveler_pricing : void 0,
470 preview_limit: 20
471 });
472 },
473 onSuccess: (response) => {
474 const previewResult = (response == null ? void 0 : response.data) || response;
475 setPreviewData(previewResult);
476 },
477 onError: (error) => {
478 showToast(
479 (error == null ? void 0 : error.message) || __("Failed to generate preview", "yatra"),
480 "error"
481 );
482 }
483 });
484 const handleSubmit = (e) => {
485 e.preventDefault();
486 if (!formData.trip_id) {
487 showToast(__("Please select a trip", "yatra"), "error");
488 return;
489 }
490 if (formData.rule_type === "weekly" && formData.days_of_week.length === 0) {
491 showToast(
492 __("Please select at least one day of the week", "yatra"),
493 "error"
494 );
495 return;
496 }
497 if (isEditing) {
498 updateMutation.mutate(formData);
499 } else {
500 createMutation.mutate(formData);
501 }
502 };
503 const toggleDay = (day) => {
504 setFormData((prev) => ({
505 ...prev,
506 days_of_week: prev.days_of_week.includes(day) ? prev.days_of_week.filter((d) => d !== day) : [...prev.days_of_week, day].sort((a, b) => a - b)
507 }));
508 };
509 const sortExcluded = (list) => [...list].sort((a, b) => excludedSortKey(a).localeCompare(excludedSortKey(b)));
510 const addExcludedDate = () => {
511 if (!newExcludedDate) {
512 return;
513 }
514 const exists = formData.excluded_dates.some(
515 (e) => excludedId(e) === newExcludedDate
516 );
517 if (exists) {
518 setExcludedError(__("That date is already excluded.", "yatra"));
519 return;
520 }
521 setExcludedError("");
522 setFormData((prev) => ({
523 ...prev,
524 excluded_dates: sortExcluded([...prev.excluded_dates, newExcludedDate])
525 }));
526 setNewExcludedDate("");
527 };
528 const addExcludedPeriod = () => {
529 if (!newExcludedStart || !newExcludedEnd) {
530 return;
531 }
532 const start = newExcludedStart <= newExcludedEnd ? newExcludedStart : newExcludedEnd;
533 const end = newExcludedStart <= newExcludedEnd ? newExcludedEnd : newExcludedStart;
534 if (start === end) {
535 if (formData.excluded_dates.some((e) => excludedId(e) === start)) {
536 setExcludedError(__("That date is already excluded.", "yatra"));
537 return;
538 }
539 setExcludedError("");
540 setFormData((prev) => ({
541 ...prev,
542 excluded_dates: sortExcluded([...prev.excluded_dates, start])
543 }));
544 setNewExcludedStart("");
545 setNewExcludedEnd("");
546 return;
547 }
548 const id = `${start}..${end}`;
549 if (formData.excluded_dates.some((e) => excludedId(e) === id)) {
550 setExcludedError(__("That period is already excluded.", "yatra"));
551 return;
552 }
553 setExcludedError("");
554 setFormData((prev) => ({
555 ...prev,
556 excluded_dates: sortExcluded([...prev.excluded_dates, { start, end }])
557 }));
558 setNewExcludedStart("");
559 setNewExcludedEnd("");
560 };
561 const removeExcluded = (id) => {
562 setExcludedError("");
563 setFormData((prev) => ({
564 ...prev,
565 excluded_dates: prev.excluded_dates.filter((e) => excludedId(e) !== id)
566 }));
567 };
568 const isLoading = createMutation.isPending || updateMutation.isPending;
569 if (isEditing && isLoadingRule) {
570 return /* @__PURE__ */ jsxRuntimeExports.jsx(RecurringRuleFormSkeleton, {});
571 }
572 return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-6", children: [
573 /* @__PURE__ */ jsxRuntimeExports.jsx(
574 PageHeader,
575 {
576 title: isEditing ? __("Edit Recurring Rule", "yatra") : __("Create Recurring Rule", "yatra"),
577 description: headerDescription,
578 actions: /* @__PURE__ */ jsxRuntimeExports.jsxs(
579 Button,
580 {
581 variant: "outline",
582 onClick: () => {
583 var _a2;
584 return navigate({
585 subpage: "trips",
586 tab: "availability",
587 trip_id: ((_a2 = formData.trip_id) == null ? void 0 : _a2.toString()) || tripIdFromUrl || ""
588 });
589 },
590 children: [
591 /* @__PURE__ */ jsxRuntimeExports.jsx(ArrowLeft, { className: "w-4 h-4 mr-2" }),
592 __("Back to Availability", "yatra")
593 ]
594 }
595 )
596 }
597 ),
598 /* @__PURE__ */ jsxRuntimeExports.jsx("form", { onSubmit: handleSubmit, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-3 gap-6", children: [
599 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "lg:col-span-2 space-y-6", children: [
600 /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [
601 /* @__PURE__ */ jsxRuntimeExports.jsx(CardHeader, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(CardTitle, { children: __("Basic Information", "yatra") }) }),
602 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { className: "space-y-4", children: [
603 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
604 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
605 /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2", children: [
606 __("Trip", "yatra"),
607 " ",
608 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-500", children: "*" })
609 ] }),
610 /* @__PURE__ */ jsxRuntimeExports.jsx(
611 SearchableSelect,
612 {
613 value: ((_a = formData.trip_id) == null ? void 0 : _a.toString()) || "",
614 onChange: (value) => setFormData((prev) => {
615 var _a2;
616 return {
617 ...prev,
618 trip_id: parseInt(value) || 0,
619 // Reset pricing when trip changes and set pricing_type based on new trip
620 pricing_type: ((_a2 = tripsData == null ? void 0 : tripsData.trips.find(
621 (t) => t.id === parseInt(value)
622 )) == null ? void 0 : _a2.pricing_type) || "regular",
623 traveler_pricing: [],
624 original_price: void 0,
625 sale_price: void 0
626 };
627 }),
628 options: [
629 { value: "", label: __("-- Select Trip --", "yatra") },
630 ...(tripsData == null ? void 0 : tripsData.trips.map((trip) => ({
631 value: trip.id.toString(),
632 label: `${trip.title} (${trip.pricing_type === "traveler_based" ? "Traveler-Based" : "Regular"})`
633 }))) || []
634 ],
635 placeholder: __("Select a trip", "yatra"),
636 disabled: isEditing
637 }
638 )
639 ] }),
640 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
641 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2", children: __("Rule Name", "yatra") }),
642 /* @__PURE__ */ jsxRuntimeExports.jsx(
643 Input,
644 {
645 type: "text",
646 value: formData.name,
647 onChange: (e) => setFormData((prev) => ({
648 ...prev,
649 name: e.target.value
650 })),
651 placeholder: __("e.g., Weekend Departures", "yatra")
652 }
653 )
654 ] })
655 ] }),
656 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
657 /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2", children: [
658 __("Rule Type", "yatra"),
659 " ",
660 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-500", children: "*" })
661 ] }),
662 /* @__PURE__ */ jsxRuntimeExports.jsxs(
663 Select,
664 {
665 value: formData.rule_type,
666 onChange: (e) => setFormData((prev) => ({
667 ...prev,
668 rule_type: e.target.value
669 })),
670 children: [
671 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "weekly", children: __("Weekly (specific days)", "yatra") }),
672 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "monthly", children: __("Monthly (e.g., first Sunday)", "yatra") }),
673 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "interval", children: __("Interval (every X days)", "yatra") })
674 ]
675 }
676 )
677 ] })
678 ] })
679 ] }),
680 /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [
681 /* @__PURE__ */ jsxRuntimeExports.jsx(CardHeader, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(CardTitle, { className: "flex items-center gap-2", children: [
682 /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "w-5 h-5" }),
683 __("Recurrence Pattern", "yatra")
684 ] }) }),
685 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { className: "space-y-4", children: [
686 formData.rule_type === "weekly" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
687 /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-3", children: [
688 __("Days of Week", "yatra"),
689 " ",
690 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-500", children: "*" })
691 ] }),
692 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-wrap gap-2", children: dayOptions.map((day) => /* @__PURE__ */ jsxRuntimeExports.jsx(
693 "button",
694 {
695 type: "button",
696 onClick: () => toggleDay(day.value),
697 className: `px-4 py-2 rounded-lg text-sm font-medium transition-colors ${formData.days_of_week.includes(day.value) ? "bg-blue-600 text-white" : "bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700"}`,
698 children: day.label
699 },
700 day.value
701 )) })
702 ] }),
703 formData.rule_type === "monthly" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
704 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
705 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2", children: __("Week of Month", "yatra") }),
706 /* @__PURE__ */ jsxRuntimeExports.jsx(
707 Select,
708 {
709 value: formData.week_of_month || "first",
710 onChange: (e) => setFormData((prev) => ({
711 ...prev,
712 week_of_month: e.target.value
713 })),
714 children: weekOptions.map((week) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: week.value, children: week.label }, week.value))
715 }
716 )
717 ] }),
718 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
719 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2", children: __("Day of Week", "yatra") }),
720 /* @__PURE__ */ jsxRuntimeExports.jsx(
721 Select,
722 {
723 value: ((_b = formData.day_of_week) == null ? void 0 : _b.toString()) || "0",
724 onChange: (e) => setFormData((prev) => ({
725 ...prev,
726 day_of_week: parseInt(e.target.value)
727 })),
728 children: dayOptions.map((day) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: day.value, children: day.label }, day.value))
729 }
730 )
731 ] })
732 ] }),
733 formData.rule_type === "interval" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
734 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2", children: __("Every X Days", "yatra") }),
735 /* @__PURE__ */ jsxRuntimeExports.jsx(
736 Input,
737 {
738 type: "number",
739 min: 1,
740 max: 365,
741 value: formData.interval_days || 7,
742 onChange: (e) => setFormData((prev) => ({
743 ...prev,
744 interval_days: parseInt(e.target.value) || 7
745 }))
746 }
747 )
748 ] }),
749 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4 pt-4 border-t border-gray-200 dark:border-gray-700", children: [
750 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
751 /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2", children: [
752 __("Start Date", "yatra"),
753 " ",
754 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-500", children: "*" })
755 ] }),
756 /* @__PURE__ */ jsxRuntimeExports.jsx(
757 DatePicker,
758 {
759 value: formData.start_date,
760 onChange: (value) => setFormData((prev) => ({ ...prev, start_date: value })),
761 placeholder: __("Select start date", "yatra")
762 }
763 )
764 ] }),
765 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
766 /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2", children: [
767 __("End Date", "yatra"),
768 " ",
769 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-400", children: [
770 "(",
771 __("optional", "yatra"),
772 ")"
773 ] })
774 ] }),
775 /* @__PURE__ */ jsxRuntimeExports.jsx(
776 DatePicker,
777 {
778 value: formData.end_date || "",
779 onChange: (value) => setFormData((prev) => ({ ...prev, end_date: value })),
780 minDate: formData.start_date ? toDateValue(formData.start_date) : void 0,
781 placeholder: __("Select end date (optional)", "yatra")
782 }
783 )
784 ] })
785 ] }),
786 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "pt-4 border-t border-gray-200 dark:border-gray-700", children: [
787 /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2", children: [
788 __("Specific Months", "yatra"),
789 " ",
790 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-400", children: [
791 "(",
792 __("optional - leave empty for all months", "yatra"),
793 ")"
794 ] })
795 ] }),
796 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-2", children: [
797 { value: 1, label: __("January", "yatra") },
798 { value: 2, label: __("February", "yatra") },
799 { value: 3, label: __("March", "yatra") },
800 { value: 4, label: __("April", "yatra") },
801 { value: 5, label: __("May", "yatra") },
802 { value: 6, label: __("June", "yatra") },
803 { value: 7, label: __("July", "yatra") },
804 { value: 8, label: __("August", "yatra") },
805 { value: 9, label: __("September", "yatra") },
806 { value: 10, label: __("October", "yatra") },
807 { value: 11, label: __("November", "yatra") },
808 { value: 12, label: __("December", "yatra") }
809 ].map((month) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
810 "label",
811 {
812 className: `flex items-center justify-center px-3 py-2 rounded-md border cursor-pointer transition-colors ${formData.months.includes(month.value) ? "bg-blue-50 border-blue-500 text-blue-700 dark:bg-blue-900/20 dark:border-blue-600 dark:text-blue-300" : "border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-800"}`,
813 children: [
814 /* @__PURE__ */ jsxRuntimeExports.jsx(
815 "input",
816 {
817 type: "checkbox",
818 checked: formData.months.includes(month.value),
819 onChange: (e) => {
820 const checked = e.target.checked;
821 setFormData((prev) => ({
822 ...prev,
823 months: checked ? [...prev.months, month.value].sort(
824 (a, b) => a - b
825 ) : prev.months.filter((m) => m !== month.value)
826 }));
827 },
828 className: "sr-only"
829 }
830 ),
831 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-sm font-medium", children: month.label.slice(0, 3) })
832 ]
833 },
834 month.value
835 )) }),
836 formData.months.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-2", children: [
837 __("Selected:", "yatra"),
838 " ",
839 formData.months.length,
840 " ",
841 formData.months.length === 1 ? __("month", "yatra") : __("months", "yatra")
842 ] })
843 ] }),
844 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "pt-4 border-t border-gray-200 dark:border-gray-700", children: [
845 /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2", children: [
846 __("Excluded Dates", "yatra"),
847 " ",
848 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-400", children: [
849 "(",
850 __("holidays, etc.", "yatra"),
851 ")"
852 ] })
853 ] }),
854 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2 mb-2", children: [
855 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
856 DatePicker,
857 {
858 value: newExcludedDate,
859 onChange: (value) => setNewExcludedDate(value),
860 placeholder: __("Select date to exclude", "yatra")
861 }
862 ) }),
863 /* @__PURE__ */ jsxRuntimeExports.jsx(
864 Button,
865 {
866 type: "button",
867 variant: "outline",
868 onClick: addExcludedDate,
869 disabled: !newExcludedDate,
870 children: /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "w-4 h-4" })
871 }
872 )
873 ] }),
874 /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2 mt-4", children: [
875 __("Excluded Periods", "yatra"),
876 " ",
877 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-400", children: [
878 "(",
879 __("holiday closures, vacations", "yatra"),
880 ")"
881 ] })
882 ] }),
883 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col sm:flex-row gap-2 mb-1", children: [
884 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
885 DatePicker,
886 {
887 value: newExcludedStart,
888 onChange: (value) => setNewExcludedStart(value),
889 placeholder: __("First day", "yatra")
890 }
891 ) }),
892 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
893 DatePicker,
894 {
895 value: newExcludedEnd,
896 onChange: (value) => setNewExcludedEnd(value),
897 placeholder: __("Last day", "yatra")
898 }
899 ) }),
900 /* @__PURE__ */ jsxRuntimeExports.jsx(
901 Button,
902 {
903 type: "button",
904 variant: "outline",
905 onClick: addExcludedPeriod,
906 disabled: !newExcludedStart || !newExcludedEnd,
907 children: /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "w-4 h-4" })
908 }
909 )
910 ] }),
911 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400 mb-2", children: __(
912 "Both days are included. Every date in between is skipped by this rule.",
913 "yatra"
914 ) }),
915 excludedError && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-red-600 dark:text-red-400 mb-2", children: excludedError }),
916 formData.excluded_dates.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-wrap gap-2", children: formData.excluded_dates.map((entry) => {
917 const id = excludedId(entry);
918 const fmt = (d) => (/* @__PURE__ */ new Date(d + "T00:00:00")).toLocaleDateString("en-US", {
919 weekday: "short",
920 month: "short",
921 day: "numeric",
922 year: "numeric"
923 });
924 return /* @__PURE__ */ jsxRuntimeExports.jsxs(
925 Badge,
926 {
927 variant: "outline",
928 className: "flex items-center gap-1",
929 children: [
930 isPeriod(entry) ? `${fmt(entry.start)} → ${fmt(entry.end)}` : fmt(entry),
931 /* @__PURE__ */ jsxRuntimeExports.jsx(
932 "button",
933 {
934 type: "button",
935 onClick: () => removeExcluded(id),
936 className: "ml-1 hover:text-red-500",
937 "aria-label": __("Remove exclusion", "yatra"),
938 children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "w-3 h-3" })
939 }
940 )
941 ]
942 },
943 id
944 );
945 }) })
946 ] })
947 ] })
948 ] }),
949 /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [
950 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardHeader, { children: [
951 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardTitle, { className: "flex items-center gap-2", children: [
952 /* @__PURE__ */ jsxRuntimeExports.jsx(DollarSign, { className: "w-5 h-5" }),
953 __("Pricing & Availability", "yatra")
954 ] }),
955 /* @__PURE__ */ jsxRuntimeExports.jsx(CardDescription, { children: __(
956 "Set pricing for traveler categories and seat availability for this rule",
957 "yatra"
958 ) })
959 ] }),
960 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { className: "space-y-6", children: [
961 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-4 bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg mb-4", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-3", children: [
962 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-2 rounded-full bg-amber-100 dark:bg-amber-900/30", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
963 "svg",
964 {
965 className: "w-5 h-5 text-amber-600 dark:text-amber-400",
966 fill: "none",
967 stroke: "currentColor",
968 viewBox: "0 0 24 24",
969 children: /* @__PURE__ */ jsxRuntimeExports.jsx(
970 "path",
971 {
972 strokeLinecap: "round",
973 strokeLinejoin: "round",
974 strokeWidth: 2,
975 d: "M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
976 }
977 )
978 }
979 ) }),
980 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1", children: [
981 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium text-gray-900 dark:text-white mb-1", children: __("Pricing Override (Optional)", "yatra") }),
982 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-gray-600 dark:text-gray-400", children: __(
983 "Leave pricing fields empty to use the trip's default pricing. Fill them in only if you want to override the default pricing for dates generated by this rule.",
984 "yatra"
985 ) })
986 ] })
987 ] }) }),
988 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-4 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
989 /* @__PURE__ */ jsxRuntimeExports.jsx(
990 "div",
991 {
992 className: `p-2 rounded-full ${isTravelerBasedPricing ? "bg-green-100 dark:bg-green-900/30" : "bg-blue-100 dark:bg-blue-900/30"}`,
993 children: isTravelerBasedPricing ? /* @__PURE__ */ jsxRuntimeExports.jsx(
994 "svg",
995 {
996 className: "w-5 h-5 text-green-600 dark:text-green-400",
997 fill: "none",
998 stroke: "currentColor",
999 viewBox: "0 0 24 24",
1000 children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1001 "path",
1002 {
1003 strokeLinecap: "round",
1004 strokeLinejoin: "round",
1005 strokeWidth: 2,
1006 d: "M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"
1007 }
1008 )
1009 }
1010 ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
1011 "svg",
1012 {
1013 className: "w-5 h-5 text-blue-600 dark:text-blue-400",
1014 fill: "none",
1015 stroke: "currentColor",
1016 viewBox: "0 0 24 24",
1017 children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1018 "path",
1019 {
1020 strokeLinecap: "round",
1021 strokeLinejoin: "round",
1022 strokeWidth: 2,
1023 d: "M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
1024 }
1025 )
1026 }
1027 )
1028 }
1029 ),
1030 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1031 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium text-gray-900 dark:text-white", children: isTravelerBasedPricing ? __("Traveler-Based Pricing", "yatra") : __("Regular Pricing", "yatra") }),
1032 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-gray-600 dark:text-gray-400", children: isTravelerBasedPricing ? __(
1033 "This trip uses traveler category pricing. Set prices for each category below.",
1034 "yatra"
1035 ) : __(
1036 "This trip uses regular pricing. Set a single price for all travelers below.",
1037 "yatra"
1038 ) })
1039 ] })
1040 ] }) }),
1041 !isTravelerBasedPricing && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-4", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
1042 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1043 /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2", children: [
1044 __("Original Price", "yatra"),
1045 " ",
1046 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-400 text-xs", children: [
1047 "(",
1048 __("Optional", "yatra"),
1049 ")"
1050 ] })
1051 ] }),
1052 /* @__PURE__ */ jsxRuntimeExports.jsx(
1053 Input,
1054 {
1055 type: "number",
1056 min: 0,
1057 step: "0.01",
1058 value: formData.original_price || "",
1059 onChange: (e) => setFormData((prev) => ({
1060 ...prev,
1061 original_price: parseFloat(e.target.value) || void 0
1062 })),
1063 placeholder: "0.00"
1064 }
1065 )
1066 ] }),
1067 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1068 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2", children: __("Sale Price", "yatra") }),
1069 /* @__PURE__ */ jsxRuntimeExports.jsx(
1070 Input,
1071 {
1072 type: "number",
1073 min: 0,
1074 step: "0.01",
1075 value: formData.sale_price || "",
1076 onChange: (e) => setFormData((prev) => ({
1077 ...prev,
1078 sale_price: parseFloat(e.target.value) || void 0
1079 })),
1080 placeholder: "0.00"
1081 }
1082 ),
1083 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-1 text-xs text-gray-500", children: __("Leave empty if no discount", "yatra") })
1084 ] })
1085 ] }) }),
1086 isTravelerBasedPricing && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
1087 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1088 /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2", children: [
1089 __("Traveler Category Pricing", "yatra"),
1090 " ",
1091 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-500", children: "*" })
1092 ] }),
1093 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400 mb-4", children: __(
1094 "Add pricing for traveler categories. Categories are managed in Traveler Categories page.",
1095 "yatra"
1096 ) })
1097 ] }),
1098 (() => {
1099 const activeCategories = travelerCategories.filter(
1100 (cat) => cat.status === "active" || cat.status === "publish"
1101 );
1102 if (activeCategories.length === 0) {
1103 return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-6 border border-gray-200 dark:border-gray-700 rounded-lg text-center", children: [
1104 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-gray-600 dark:text-gray-400 mb-3", children: __(
1105 "No active traveler categories found.",
1106 "yatra"
1107 ) }),
1108 /* @__PURE__ */ jsxRuntimeExports.jsxs(
1109 Button,
1110 {
1111 type: "button",
1112 variant: "outline",
1113 onClick: () => window.location.href = "?page=yatra&subpage=traveler-categories&action=create",
1114 className: "flex items-center gap-2 mx-auto",
1115 children: [
1116 /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "w-4 h-4" }),
1117 __("Create Category", "yatra")
1118 ]
1119 }
1120 )
1121 ] });
1122 }
1123 return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
1124 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative", children: [
1125 /* @__PURE__ */ jsxRuntimeExports.jsxs(
1126 Button,
1127 {
1128 type: "button",
1129 variant: "outline",
1130 onClick: () => setShowCategorySelector(!showCategorySelector),
1131 className: "flex items-center gap-2",
1132 disabled: activeCategories.filter(
1133 (cat) => {
1134 var _a2;
1135 return !((_a2 = formData.traveler_pricing) == null ? void 0 : _a2.some(
1136 (tp) => tp.category_id === cat.id
1137 ));
1138 }
1139 ).length === 0,
1140 children: [
1141 /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "w-4 h-4" }),
1142 __("Add Pricing", "yatra")
1143 ]
1144 }
1145 ),
1146 showCategorySelector && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1147 /* @__PURE__ */ jsxRuntimeExports.jsx(
1148 "div",
1149 {
1150 className: "fixed inset-0 z-10",
1151 onClick: () => setShowCategorySelector(false)
1152 }
1153 ),
1154 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute top-full left-0 mt-2 w-full max-w-md bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg z-20 max-h-96 overflow-y-auto", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-2", children: [
1155 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs font-medium text-gray-700 dark:text-gray-300 px-3 py-2 mb-1", children: __(
1156 "Select a category to add pricing",
1157 "yatra"
1158 ) }),
1159 activeCategories.filter(
1160 (cat) => {
1161 var _a2;
1162 return !((_a2 = formData.traveler_pricing) == null ? void 0 : _a2.some(
1163 (tp) => tp.category_id === cat.id
1164 ));
1165 }
1166 ).length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-3 py-4 text-sm text-gray-500 dark:text-gray-400 text-center", children: __(
1167 "All categories have pricing added",
1168 "yatra"
1169 ) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1", children: activeCategories.filter(
1170 (cat) => {
1171 var _a2;
1172 return !((_a2 = formData.traveler_pricing) == null ? void 0 : _a2.some(
1173 (tp) => tp.category_id === cat.id
1174 ));
1175 }
1176 ).map((category) => {
1177 const minAge = category.age_min ?? category.min_age;
1178 const maxAge = category.age_max ?? category.max_age;
1179 const ageRange = minAge !== void 0 || maxAge !== void 0 ? minAge !== void 0 && maxAge !== void 0 ? `${minAge}-${maxAge} ${__("years", "yatra")}` : minAge !== void 0 ? `${minAge}+ ${__("years", "yatra")}` : maxAge !== void 0 ? `${__("Under", "yatra")} ${maxAge} ${__("years", "yatra")}` : "" : null;
1180 const categoryName = category.label || category.name || `Category ${category.id}`;
1181 return /* @__PURE__ */ jsxRuntimeExports.jsxs(
1182 "button",
1183 {
1184 type: "button",
1185 onClick: () => {
1186 setFormData((prev) => ({
1187 ...prev,
1188 traveler_pricing: [
1189 ...prev.traveler_pricing || [],
1190 {
1191 category_id: category.id,
1192 original_price: 0,
1193 sale_price: void 0
1194 }
1195 ]
1196 }));
1197 setShowCategorySelector(
1198 false
1199 );
1200 },
1201 className: "w-full text-left px-3 py-2 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors",
1202 children: [
1203 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "font-medium text-sm text-gray-900 dark:text-white", children: [
1204 categoryName,
1205 ageRange && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ml-2 text-xs font-normal text-gray-500 dark:text-gray-400", children: [
1206 "(",
1207 ageRange,
1208 ")"
1209 ] })
1210 ] }),
1211 category.description && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-gray-500 dark:text-gray-400 mt-0.5", children: category.description })
1212 ]
1213 },
1214 category.id
1215 );
1216 }) })
1217 ] }) })
1218 ] })
1219 ] }),
1220 formData.traveler_pricing && formData.traveler_pricing.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-3", children: formData.traveler_pricing.map(
1221 (pricing, index) => {
1222 const category = activeCategories.find(
1223 (cat) => cat.id === pricing.category_id
1224 );
1225 if (!category) return null;
1226 const minAge = category.age_min ?? category.min_age;
1227 const maxAge = category.age_max ?? category.max_age;
1228 const categoryName = category.label || category.name || `Category ${pricing.category_id}`;
1229 return /* @__PURE__ */ jsxRuntimeExports.jsxs(
1230 "div",
1231 {
1232 className: "p-4 border border-blue-300 dark:border-blue-700 bg-blue-50 dark:bg-blue-900/20 rounded-lg",
1233 children: [
1234 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between mb-3", children: [
1235 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1", children: [
1236 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-2 mb-1", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("h4", { className: "text-sm font-semibold text-gray-900 dark:text-white", children: [
1237 categoryName,
1238 (minAge !== void 0 || maxAge !== void 0) && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ml-2 text-xs font-normal text-gray-500 dark:text-gray-400", children: [
1239 "(",
1240 minAge !== void 0 && maxAge !== void 0 ? `${minAge}-${maxAge} ${__("years", "yatra")}` : minAge !== void 0 ? `${minAge}+ ${__("years", "yatra")}` : maxAge !== void 0 ? `${__("Under", "yatra")} ${maxAge} ${__("years", "yatra")}` : "",
1241 ")"
1242 ] })
1243 ] }) }),
1244 category.description && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-gray-600 dark:text-gray-400", children: category.description })
1245 ] }),
1246 /* @__PURE__ */ jsxRuntimeExports.jsx(
1247 "button",
1248 {
1249 type: "button",
1250 onClick: () => {
1251 const categoryIdToRemove = pricing.category_id;
1252 setFormData((prev) => ({
1253 ...prev,
1254 traveler_pricing: (prev.traveler_pricing || []).filter(
1255 (tp) => tp.category_id !== categoryIdToRemove
1256 )
1257 }));
1258 },
1259 className: "p-1 text-red-600 hover:text-red-700 hover:bg-red-50 dark:hover:bg-red-900/20 rounded transition-colors",
1260 title: __(
1261 "Remove Pricing",
1262 "yatra"
1263 ),
1264 children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "w-4 h-4" })
1265 }
1266 )
1267 ] }),
1268 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3", children: [
1269 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1270 /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "block text-xs font-medium text-gray-700 dark:text-gray-300 mb-1.5", children: [
1271 __("Original Price", "yatra"),
1272 " ",
1273 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-500", children: "*" })
1274 ] }),
1275 /* @__PURE__ */ jsxRuntimeExports.jsx(
1276 Input,
1277 {
1278 type: "number",
1279 min: 0,
1280 step: "0.01",
1281 value: pricing.original_price || "",
1282 onChange: (e) => {
1283 const newPricing = [
1284 ...formData.traveler_pricing || []
1285 ];
1286 newPricing[index].original_price = parseFloat(e.target.value) || 0;
1287 setFormData((prev) => ({
1288 ...prev,
1289 traveler_pricing: newPricing
1290 }));
1291 },
1292 placeholder: "0.00"
1293 }
1294 )
1295 ] }),
1296 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1297 /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "block text-xs font-medium text-gray-700 dark:text-gray-300 mb-1.5", children: [
1298 __("Sale Price", "yatra"),
1299 " (",
1300 __("Optional", "Optional"),
1301 ")"
1302 ] }),
1303 /* @__PURE__ */ jsxRuntimeExports.jsx(
1304 Input,
1305 {
1306 type: "number",
1307 min: 0,
1308 step: "0.01",
1309 value: pricing.sale_price || "",
1310 onChange: (e) => {
1311 const newPricing = [
1312 ...formData.traveler_pricing || []
1313 ];
1314 newPricing[index].sale_price = parseFloat(e.target.value) || void 0;
1315 setFormData((prev) => ({
1316 ...prev,
1317 traveler_pricing: newPricing
1318 }));
1319 },
1320 className: "text-sm",
1321 placeholder: "0.00"
1322 }
1323 )
1324 ] })
1325 ] })
1326 ]
1327 },
1328 pricing.category_id
1329 );
1330 }
1331 ) })
1332 ] });
1333 })()
1334 ] }),
1335 selectedTrip && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "pt-4 border-t border-gray-200 dark:border-gray-700", children: [
1336 /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "text-sm font-semibold text-gray-900 dark:text-white mb-4", children: __("Inventory Management", "yatra") }),
1337 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
1338 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1339 /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2", children: [
1340 __("Total Capacity", "yatra"),
1341 " ",
1342 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-500", children: "*" })
1343 ] }),
1344 /* @__PURE__ */ jsxRuntimeExports.jsx(
1345 Input,
1346 {
1347 type: "number",
1348 min: 1,
1349 value: formData.seats_total,
1350 onChange: (e) => setFormData((prev) => ({
1351 ...prev,
1352 seats_total: parseInt(e.target.value) || 1
1353 }))
1354 }
1355 ),
1356 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-1 text-xs text-gray-500", children: __(
1357 "Maximum number of seats available for this rule",
1358 "yatra"
1359 ) })
1360 ] }),
1361 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1362 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2", children: __("Alert Threshold", "yatra") }),
1363 /* @__PURE__ */ jsxRuntimeExports.jsx(
1364 Input,
1365 {
1366 type: "number",
1367 min: 0,
1368 value: formData.alert_threshold,
1369 onChange: (e) => setFormData((prev) => ({
1370 ...prev,
1371 alert_threshold: parseInt(e.target.value) || 0
1372 }))
1373 }
1374 ),
1375 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-1 text-xs text-gray-500", children: __(
1376 "Alert when available seats drop below this number",
1377 "yatra"
1378 ) })
1379 ] })
1380 ] })
1381 ] }),
1382 !selectedTrip && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center py-6 bg-gray-50 dark:bg-gray-800 rounded-lg", children: [
1383 /* @__PURE__ */ jsxRuntimeExports.jsx(AlertCircle, { className: "w-8 h-8 text-gray-400 mx-auto mb-2" }),
1384 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: __("Select a trip above to configure pricing", "yatra") })
1385 ] })
1386 ] })
1387 ] }),
1388 /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [
1389 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardHeader, { children: [
1390 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardTitle, { className: "flex items-center gap-2", children: [
1391 /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "w-5 h-5" }),
1392 __("Time & Location", "yatra")
1393 ] }),
1394 selectedTrip && /* @__PURE__ */ jsxRuntimeExports.jsxs(CardDescription, { children: [
1395 /* @__PURE__ */ jsxRuntimeExports.jsx(
1396 Badge,
1397 {
1398 variant: isSingleDayTrip ? "default" : "outline",
1399 className: "mr-2",
1400 children: isSingleDayTrip ? __("Single-Day Trip", "yatra") : __("Multi-Day Trip", "yatra")
1401 }
1402 ),
1403 !isSingleDayTrip && selectedTrip.duration_days && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-500", children: [
1404 "(",
1405 selectedTrip.duration_days,
1406 " ",
1407 __("days", "yatra"),
1408 ")"
1409 ] })
1410 ] })
1411 ] }),
1412 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { className: "space-y-4", children: [
1413 isSingleDayTrip && formData.trip_id > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
1414 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [
1415 /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300", children: [
1416 __("Time Slots", "yatra"),
1417 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-400 ml-1", children: [
1418 "(",
1419 __("for each recurring day", "yatra"),
1420 ")"
1421 ] })
1422 ] }),
1423 /* @__PURE__ */ jsxRuntimeExports.jsxs(
1424 Button,
1425 {
1426 type: "button",
1427 variant: "outline",
1428 size: "sm",
1429 onClick: () => setFormData((prev) => ({
1430 ...prev,
1431 time_slots: [
1432 ...prev.time_slots,
1433 {
1434 departure_time: "09:00",
1435 arrival_time: "17:00",
1436 seats: 20,
1437 price: 0,
1438 traveler_pricing: isTravelerBasedPricing ? [] : void 0
1439 }
1440 ]
1441 })),
1442 children: [
1443 /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "w-4 h-4 mr-1" }),
1444 __("Add Slot", "yatra")
1445 ]
1446 }
1447 )
1448 ] }),
1449 formData.time_slots.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center py-6 bg-gray-50 dark:bg-gray-800 rounded-lg border-2 border-dashed border-gray-200 dark:border-gray-700", children: [
1450 /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { className: "w-8 h-8 text-gray-400 mx-auto mb-2" }),
1451 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-gray-500 dark:text-gray-400 mb-2", children: __("No time slots added yet", "yatra") }),
1452 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-gray-400 dark:text-gray-500", children: __(
1453 "Add multiple time slots for tours throughout the day (e.g., morning, afternoon, evening)",
1454 "yatra"
1455 ) })
1456 ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-3", children: formData.time_slots.map((slot, index) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
1457 "div",
1458 {
1459 className: "p-4 bg-gray-50 dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700",
1460 children: [
1461 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between mb-3", children: [
1462 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: [
1463 __("Slot", "yatra"),
1464 " ",
1465 index + 1
1466 ] }),
1467 /* @__PURE__ */ jsxRuntimeExports.jsx(
1468 Button,
1469 {
1470 type: "button",
1471 variant: "ghost",
1472 size: "sm",
1473 onClick: () => setFormData((prev) => ({
1474 ...prev,
1475 time_slots: prev.time_slots.filter(
1476 (_, i) => i !== index
1477 )
1478 })),
1479 className: "text-red-500 hover:text-red-600 h-8 w-8 p-0",
1480 children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "w-4 h-4" })
1481 }
1482 )
1483 ] }),
1484 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3", children: [
1485 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-3", children: [
1486 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1487 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-xs text-gray-500 dark:text-gray-400 mb-1", children: __("Departure Time", "yatra") }),
1488 /* @__PURE__ */ jsxRuntimeExports.jsx(
1489 TimePicker,
1490 {
1491 value: slot.departure_time || "",
1492 onChange: (value) => {
1493 const newSlots = [...formData.time_slots];
1494 newSlots[index].departure_time = value;
1495 setFormData((prev) => ({
1496 ...prev,
1497 time_slots: newSlots
1498 }));
1499 },
1500 placeholder: "09:00"
1501 }
1502 )
1503 ] }),
1504 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1505 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-xs text-gray-500 dark:text-gray-400 mb-1", children: __("Arrival Time", "yatra") }),
1506 /* @__PURE__ */ jsxRuntimeExports.jsx(
1507 TimePicker,
1508 {
1509 value: slot.arrival_time || "",
1510 onChange: (value) => {
1511 const newSlots = [...formData.time_slots];
1512 newSlots[index].arrival_time = value;
1513 setFormData((prev) => ({
1514 ...prev,
1515 time_slots: newSlots
1516 }));
1517 },
1518 placeholder: "17:00"
1519 }
1520 )
1521 ] })
1522 ] }),
1523 !isTravelerBasedPricing && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3", children: [
1524 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1525 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-xs text-gray-500 dark:text-gray-400 mb-1", children: __("Seats", "yatra") }),
1526 /* @__PURE__ */ jsxRuntimeExports.jsx(
1527 Input,
1528 {
1529 type: "number",
1530 min: 1,
1531 value: slot.seats,
1532 onChange: (e) => {
1533 const newSlots = [
1534 ...formData.time_slots
1535 ];
1536 newSlots[index].seats = parseInt(e.target.value) || 1;
1537 setFormData((prev) => ({
1538 ...prev,
1539 time_slots: newSlots
1540 }));
1541 },
1542 className: "text-sm"
1543 }
1544 )
1545 ] }),
1546 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1547 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-xs text-gray-500 dark:text-gray-400 mb-1", children: __("Price", "yatra") }),
1548 /* @__PURE__ */ jsxRuntimeExports.jsx(
1549 Input,
1550 {
1551 type: "number",
1552 min: 0,
1553 step: "0.01",
1554 value: slot.price || "",
1555 onChange: (e) => {
1556 const newSlots = [
1557 ...formData.time_slots
1558 ];
1559 newSlots[index].price = parseFloat(e.target.value) || 0;
1560 setFormData((prev) => ({
1561 ...prev,
1562 time_slots: newSlots
1563 }));
1564 },
1565 className: "text-sm",
1566 placeholder: "0.00"
1567 }
1568 )
1569 ] }),
1570 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1571 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-xs text-gray-500 dark:text-gray-400 mb-1", children: __("Sale Price", "yatra") }),
1572 /* @__PURE__ */ jsxRuntimeExports.jsx(
1573 Input,
1574 {
1575 type: "number",
1576 min: 0,
1577 step: "0.01",
1578 value: slot.sale_price || "",
1579 onChange: (e) => {
1580 const newSlots = [
1581 ...formData.time_slots
1582 ];
1583 newSlots[index].sale_price = parseFloat(e.target.value) || void 0;
1584 setFormData((prev) => ({
1585 ...prev,
1586 time_slots: newSlots
1587 }));
1588 },
1589 className: "text-sm",
1590 placeholder: "0.00"
1591 }
1592 )
1593 ] })
1594 ] }),
1595 isTravelerBasedPricing && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1596 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-xs text-gray-500 dark:text-gray-400 mb-1", children: __("Seats", "yatra") }),
1597 /* @__PURE__ */ jsxRuntimeExports.jsx(
1598 Input,
1599 {
1600 type: "number",
1601 min: 1,
1602 value: slot.seats,
1603 onChange: (e) => {
1604 const newSlots = [...formData.time_slots];
1605 newSlots[index].seats = parseInt(e.target.value) || 1;
1606 setFormData((prev) => ({
1607 ...prev,
1608 time_slots: newSlots
1609 }));
1610 },
1611 className: "text-sm"
1612 }
1613 )
1614 ] })
1615 ] }),
1616 isTravelerBasedPricing && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-3 pt-3 border-t border-gray-200 dark:border-gray-700", children: [
1617 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-between mb-3", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1618 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs font-medium text-gray-700 dark:text-gray-300", children: __("Traveler Category Pricing", "yatra") }),
1619 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-0.5", children: __(
1620 "Set pricing for each traveler category for this time slot",
1621 "yatra"
1622 ) })
1623 ] }) }),
1624 (() => {
1625 const activeCategories = travelerCategories.filter(
1626 (cat) => cat.status === "active" || cat.status === "publish"
1627 );
1628 const slotTravelerPricing = slot.traveler_pricing || [];
1629 const availableCategories = activeCategories.filter(
1630 (cat) => !slotTravelerPricing.some(
1631 (tp) => tp.category_id === cat.id
1632 )
1633 );
1634 return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3", children: [
1635 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative", children: [
1636 /* @__PURE__ */ jsxRuntimeExports.jsxs(
1637 Button,
1638 {
1639 type: "button",
1640 variant: "outline",
1641 size: "sm",
1642 onClick: () => {
1643 const dropdownId = `slot-${index}-category-dropdown`;
1644 const dropdown = document.getElementById(
1645 dropdownId
1646 );
1647 if (dropdown) {
1648 dropdown.classList.toggle(
1649 "hidden"
1650 );
1651 }
1652 },
1653 disabled: availableCategories.length === 0,
1654 children: [
1655 /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "w-3 h-3 mr-1" }),
1656 __("Add Pricing", "yatra")
1657 ]
1658 }
1659 ),
1660 /* @__PURE__ */ jsxRuntimeExports.jsx(
1661 "div",
1662 {
1663 id: `slot-${index}-category-dropdown`,
1664 className: "hidden absolute top-full left-0 mt-2 w-full max-w-sm bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg z-20 max-h-64 overflow-y-auto",
1665 children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-2", children: [
1666 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs font-medium text-gray-700 dark:text-gray-300 px-3 py-2 mb-1", children: __(
1667 "Select a category to add pricing",
1668 "yatra"
1669 ) }),
1670 availableCategories.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-3 py-3 text-xs text-gray-500 dark:text-gray-400 text-center", children: __(
1671 "All categories have pricing added",
1672 "yatra"
1673 ) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-1", children: availableCategories.map(
1674 (category) => {
1675 const minAge = category.age_min ?? category.min_age;
1676 const maxAge = category.age_max ?? category.max_age;
1677 const ageRange = minAge !== void 0 || maxAge !== void 0 ? minAge !== void 0 && maxAge !== void 0 ? `${minAge}-${maxAge} ${__("years", "yatra")}` : minAge !== void 0 ? `${minAge}+ ${__("years", "yatra")}` : `${__("Under", "yatra")} ${maxAge} ${__("years", "yatra")}` : null;
1678 const categoryName = category.label || category.name || `Category ${category.id}`;
1679 return /* @__PURE__ */ jsxRuntimeExports.jsxs(
1680 "button",
1681 {
1682 type: "button",
1683 onClick: () => {
1684 const newSlots = [
1685 ...formData.time_slots
1686 ];
1687 if (!newSlots[index].traveler_pricing) {
1688 newSlots[index].traveler_pricing = [];
1689 }
1690 newSlots[index].traveler_pricing = [
1691 ...newSlots[index].traveler_pricing,
1692 {
1693 category_id: category.id,
1694 original_price: 0,
1695 sale_price: void 0
1696 }
1697 ];
1698 setFormData(
1699 (prev) => ({
1700 ...prev,
1701 time_slots: newSlots
1702 })
1703 );
1704 const dropdown = document.getElementById(
1705 `slot-${index}-category-dropdown`
1706 );
1707 if (dropdown)
1708 dropdown.classList.add(
1709 "hidden"
1710 );
1711 },
1712 className: "w-full text-left px-3 py-2 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors",
1713 children: [
1714 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "font-medium text-xs text-gray-900 dark:text-white", children: [
1715 categoryName,
1716 ageRange && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ml-2 text-xs font-normal text-gray-500 dark:text-gray-400", children: [
1717 "(",
1718 ageRange,
1719 ")"
1720 ] })
1721 ] }),
1722 category.description && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-gray-500 dark:text-gray-400 mt-0.5 truncate", children: category.description })
1723 ]
1724 },
1725 category.id
1726 );
1727 }
1728 ) })
1729 ] })
1730 }
1731 )
1732 ] }),
1733 slotTravelerPricing.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-2", children: slotTravelerPricing.map(
1734 (tp, tpIndex) => {
1735 const category = activeCategories.find(
1736 (cat) => cat.id === tp.category_id
1737 );
1738 if (!category) return null;
1739 const minAge = category.age_min ?? category.min_age;
1740 const maxAge = category.age_max ?? category.max_age;
1741 const categoryName = category.label || category.name || `Category ${tp.category_id}`;
1742 return /* @__PURE__ */ jsxRuntimeExports.jsxs(
1743 "div",
1744 {
1745 className: "p-3 border border-blue-300 dark:border-blue-700 bg-blue-50 dark:bg-blue-900/20 rounded-lg",
1746 children: [
1747 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between mb-2", children: [
1748 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs font-semibold text-gray-900 dark:text-white", children: [
1749 categoryName,
1750 (minAge !== void 0 || maxAge !== void 0) && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ml-1 text-xs font-normal text-gray-500 dark:text-gray-400", children: [
1751 "(",
1752 minAge !== void 0 && maxAge !== void 0 ? `${minAge}-${maxAge}` : minAge !== void 0 ? `${minAge}+` : `<${maxAge}`,
1753 " ",
1754 __(
1755 "years",
1756 "yatra"
1757 ),
1758 ")"
1759 ] })
1760 ] }) }),
1761 /* @__PURE__ */ jsxRuntimeExports.jsx(
1762 "button",
1763 {
1764 type: "button",
1765 onClick: () => {
1766 const categoryIdToRemove = tp.category_id;
1767 setFormData((prev) => {
1768 const newSlots = [
1769 ...prev.time_slots
1770 ];
1771 if (!newSlots[index]) {
1772 return prev;
1773 }
1774 newSlots[index] = {
1775 ...newSlots[index],
1776 traveler_pricing: (newSlots[index].traveler_pricing || []).filter(
1777 (p) => p.category_id !== categoryIdToRemove
1778 )
1779 };
1780 return {
1781 ...prev,
1782 time_slots: newSlots
1783 };
1784 });
1785 },
1786 className: "p-0.5 text-red-600 hover:text-red-700 hover:bg-red-50 dark:hover:bg-red-900/20 rounded transition-colors",
1787 children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "w-3 h-3" })
1788 }
1789 )
1790 ] }),
1791 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
1792 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1793 /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "block text-xs text-gray-600 dark:text-gray-400 mb-1", children: [
1794 __("Price", "yatra"),
1795 " ",
1796 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-red-500", children: "*" })
1797 ] }),
1798 /* @__PURE__ */ jsxRuntimeExports.jsx(
1799 Input,
1800 {
1801 type: "number",
1802 min: 0,
1803 step: "0.01",
1804 value: tp.original_price || "",
1805 onChange: (e) => {
1806 const newSlots = [
1807 ...formData.time_slots
1808 ];
1809 if (newSlots[index] && newSlots[index].traveler_pricing) {
1810 newSlots[index].traveler_pricing[tpIndex].original_price = parseFloat(
1811 e.target.value
1812 ) || 0;
1813 setFormData(
1814 (prev) => ({
1815 ...prev,
1816 time_slots: newSlots
1817 })
1818 );
1819 }
1820 },
1821 className: "text-xs",
1822 placeholder: "0.00"
1823 }
1824 )
1825 ] }),
1826 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1827 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-xs text-gray-600 dark:text-gray-400 mb-1", children: __("Sale", "yatra") }),
1828 /* @__PURE__ */ jsxRuntimeExports.jsx(
1829 Input,
1830 {
1831 type: "number",
1832 min: 0,
1833 step: "0.01",
1834 value: tp.sale_price || "",
1835 onChange: (e) => {
1836 const newSlots = [
1837 ...formData.time_slots
1838 ];
1839 if (newSlots[index] && newSlots[index].traveler_pricing) {
1840 newSlots[index].traveler_pricing[tpIndex].sale_price = parseFloat(
1841 e.target.value
1842 ) || void 0;
1843 setFormData(
1844 (prev) => ({
1845 ...prev,
1846 time_slots: newSlots
1847 })
1848 );
1849 }
1850 },
1851 className: "text-xs",
1852 placeholder: "0.00"
1853 }
1854 )
1855 ] })
1856 ] })
1857 ]
1858 },
1859 tp.category_id
1860 );
1861 }
1862 ) }),
1863 slotTravelerPricing.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-center py-3 bg-gray-100 dark:bg-gray-800 rounded border border-dashed border-gray-300 dark:border-gray-600", children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-gray-500", children: __(
1864 'Click "Add Pricing" to set prices for traveler categories',
1865 "yatra"
1866 ) }) })
1867 ] });
1868 })()
1869 ] })
1870 ]
1871 },
1872 index
1873 )) }),
1874 formData.time_slots.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "pt-4 border-t border-gray-200 dark:border-gray-700", children: [
1875 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400 mb-3", children: __(
1876 "Or use default time (applies to all generated dates):",
1877 "yatra"
1878 ) }),
1879 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
1880 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1881 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2", children: __("Default Start Time", "yatra") }),
1882 /* @__PURE__ */ jsxRuntimeExports.jsx(
1883 TimePicker,
1884 {
1885 value: formData.departure_time || "",
1886 onChange: (value) => setFormData((prev) => ({
1887 ...prev,
1888 departure_time: value
1889 })),
1890 placeholder: "09:00"
1891 }
1892 )
1893 ] }),
1894 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1895 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2", children: __("Default End Time", "yatra") }),
1896 /* @__PURE__ */ jsxRuntimeExports.jsx(
1897 TimePicker,
1898 {
1899 value: formData.arrival_time || "",
1900 onChange: (value) => setFormData((prev) => ({
1901 ...prev,
1902 arrival_time: value
1903 })),
1904 placeholder: "17:00"
1905 }
1906 )
1907 ] })
1908 ] })
1909 ] })
1910 ] }),
1911 !isSingleDayTrip && formData.trip_id > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
1912 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1913 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2", children: __("Departure Time", "yatra") }),
1914 /* @__PURE__ */ jsxRuntimeExports.jsx(
1915 TimePicker,
1916 {
1917 value: formData.departure_time || "",
1918 onChange: (value) => setFormData((prev) => ({
1919 ...prev,
1920 departure_time: value
1921 })),
1922 placeholder: "08:00"
1923 }
1924 )
1925 ] }),
1926 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1927 /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2", children: [
1928 __("Return Time", "yatra"),
1929 " ",
1930 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-gray-400", children: [
1931 "(",
1932 __("on final day", "yatra"),
1933 ")"
1934 ] })
1935 ] }),
1936 /* @__PURE__ */ jsxRuntimeExports.jsx(
1937 TimePicker,
1938 {
1939 value: formData.arrival_time || "",
1940 onChange: (value) => setFormData((prev) => ({
1941 ...prev,
1942 arrival_time: value
1943 })),
1944 placeholder: "18:00"
1945 }
1946 )
1947 ] })
1948 ] }),
1949 !formData.trip_id && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center py-6 bg-gray-50 dark:bg-gray-800 rounded-lg", children: [
1950 /* @__PURE__ */ jsxRuntimeExports.jsx(AlertCircle, { className: "w-8 h-8 text-gray-400 mx-auto mb-2" }),
1951 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: __(
1952 "Select a trip above to configure time settings",
1953 "yatra"
1954 ) })
1955 ] }),
1956 formData.trip_id > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1957 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-8 pt-4 border-t border-gray-200 dark:border-gray-700", children: [
1958 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
1959 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3 p-4 bg-gradient-to-r from-blue-50 to-indigo-50 dark:from-blue-900/20 dark:to-indigo-900/20 rounded-xl border border-blue-200 dark:border-blue-800", children: [
1960 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-10 h-10 bg-gradient-to-br from-blue-500 to-blue-600 rounded-xl flex items-center justify-center shadow-lg", children: /* @__PURE__ */ jsxRuntimeExports.jsx(MapPin, { className: "w-5 h-5 text-white" }) }),
1961 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1", children: [
1962 /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "text-base font-semibold text-blue-900 dark:text-blue-100", children: __("Starting Point", "yatra") }),
1963 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-blue-700 dark:text-blue-300", children: __("Where the journey begins", "yatra") })
1964 ] }),
1965 formData.from_latitude && formData.from_longitude && /* @__PURE__ */ jsxRuntimeExports.jsx(
1966 "div",
1967 {
1968 className: "w-2 h-2 bg-blue-500 rounded-full",
1969 title: __("Coordinates set", "yatra")
1970 }
1971 )
1972 ] }),
1973 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
1974 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: __("From location (departure)", "yatra") }),
1975 /* @__PURE__ */ jsxRuntimeExports.jsx(
1976 LocationPicker,
1977 {
1978 value: {
1979 name: formData.from_location || "",
1980 latitude: formData.from_latitude || "",
1981 longitude: formData.from_longitude || ""
1982 },
1983 onChange: (loc) => setFormData((prev) => ({
1984 ...prev,
1985 from_location: loc.name,
1986 from_latitude: loc.latitude,
1987 from_longitude: loc.longitude
1988 })),
1989 label: "",
1990 placeholder: __(
1991 "Search for starting location...",
1992 "yatra"
1993 ),
1994 helpText: "",
1995 required: false,
1996 defaultMapCenter: formData.from_latitude && formData.from_longitude ? [
1997 parseFloat(formData.from_latitude),
1998 parseFloat(formData.from_longitude)
1999 ] : (tripForLocations == null ? void 0 : tripForLocations.starting_latitude) && (tripForLocations == null ? void 0 : tripForLocations.starting_longitude) ? [
2000 parseFloat(
2001 String(
2002 tripForLocations.starting_latitude
2003 )
2004 ),
2005 parseFloat(
2006 String(
2007 tripForLocations.starting_longitude
2008 )
2009 )
2010 ] : [20, 0],
2011 defaultZoom: formData.from_latitude && formData.from_longitude ? 13 : (tripForLocations == null ? void 0 : tripForLocations.starting_latitude) && (tripForLocations == null ? void 0 : tripForLocations.starting_longitude) ? 13 : 2,
2012 mapHeight: "300px",
2013 showMapButton: false,
2014 searchLimit: 8,
2015 __,
2016 className: "",
2017 mapClassName: "rounded-lg",
2018 showManualCoordinateFields: true
2019 }
2020 ),
2021 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: __(
2022 "Default: trip starting location. Set per rule to override.",
2023 "yatra"
2024 ) })
2025 ] })
2026 ] }),
2027 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
2028 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3 p-4 bg-gradient-to-r from-green-50 to-emerald-50 dark:from-green-900/20 dark:to-emerald-900/20 rounded-xl border border-green-200 dark:border-green-800", children: [
2029 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-10 h-10 bg-gradient-to-br from-green-500 to-green-600 rounded-xl flex items-center justify-center shadow-lg", children: /* @__PURE__ */ jsxRuntimeExports.jsx(CheckCircle2, { className: "w-5 h-5 text-white" }) }),
2030 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1", children: [
2031 /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "text-base font-semibold text-green-900 dark:text-green-100", children: __("Ending Point", "yatra") }),
2032 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-green-700 dark:text-green-300", children: __("Where the journey concludes", "yatra") })
2033 ] }),
2034 formData.to_latitude && formData.to_longitude && /* @__PURE__ */ jsxRuntimeExports.jsx(
2035 "div",
2036 {
2037 className: "w-2 h-2 bg-green-500 rounded-full",
2038 title: __("Coordinates set", "yatra")
2039 }
2040 )
2041 ] }),
2042 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
2043 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: __("To location (destination)", "yatra") }),
2044 /* @__PURE__ */ jsxRuntimeExports.jsx(
2045 LocationPicker,
2046 {
2047 value: {
2048 name: formData.to_location || "",
2049 latitude: formData.to_latitude || "",
2050 longitude: formData.to_longitude || ""
2051 },
2052 onChange: (loc) => setFormData((prev) => ({
2053 ...prev,
2054 to_location: loc.name,
2055 to_latitude: loc.latitude,
2056 to_longitude: loc.longitude
2057 })),
2058 label: "",
2059 placeholder: __(
2060 "Search for ending location...",
2061 "yatra"
2062 ),
2063 helpText: "",
2064 required: false,
2065 defaultMapCenter: formData.to_latitude && formData.to_longitude ? [
2066 parseFloat(formData.to_latitude),
2067 parseFloat(formData.to_longitude)
2068 ] : (tripForLocations == null ? void 0 : tripForLocations.ending_latitude) && (tripForLocations == null ? void 0 : tripForLocations.ending_longitude) ? [
2069 parseFloat(
2070 String(
2071 tripForLocations.ending_latitude
2072 )
2073 ),
2074 parseFloat(
2075 String(
2076 tripForLocations.ending_longitude
2077 )
2078 )
2079 ] : formData.from_latitude && formData.from_longitude ? [
2080 parseFloat(formData.from_latitude),
2081 parseFloat(formData.from_longitude)
2082 ] : (tripForLocations == null ? void 0 : tripForLocations.starting_latitude) && (tripForLocations == null ? void 0 : tripForLocations.starting_longitude) ? [
2083 parseFloat(
2084 String(
2085 tripForLocations.starting_latitude
2086 )
2087 ),
2088 parseFloat(
2089 String(
2090 tripForLocations.starting_longitude
2091 )
2092 )
2093 ] : [20, 0],
2094 defaultZoom: formData.to_latitude && formData.to_longitude ? 13 : (tripForLocations == null ? void 0 : tripForLocations.ending_latitude) && (tripForLocations == null ? void 0 : tripForLocations.ending_longitude) ? 13 : formData.from_latitude && formData.from_longitude ? 13 : (tripForLocations == null ? void 0 : tripForLocations.starting_latitude) && (tripForLocations == null ? void 0 : tripForLocations.starting_longitude) ? 13 : 2,
2095 mapHeight: "300px",
2096 showMapButton: false,
2097 searchLimit: 8,
2098 __,
2099 className: "",
2100 mapClassName: "rounded-lg",
2101 showManualCoordinateFields: true
2102 }
2103 ),
2104 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: __(
2105 "Default: trip ending location. Set per rule to override.",
2106 "yatra"
2107 ) })
2108 ] })
2109 ] })
2110 ] }),
2111 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
2112 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2", children: __("Booking Cutoff (hours before)", "yatra") }),
2113 /* @__PURE__ */ jsxRuntimeExports.jsx(
2114 Input,
2115 {
2116 type: "number",
2117 min: 0,
2118 value: formData.cutoff_hours,
2119 onChange: (e) => setFormData((prev) => ({
2120 ...prev,
2121 cutoff_hours: parseInt(e.target.value) || 0
2122 }))
2123 }
2124 )
2125 ] })
2126 ] })
2127 ] })
2128 ] })
2129 ] }),
2130 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-6", children: [
2131 /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [
2132 /* @__PURE__ */ jsxRuntimeExports.jsx(CardHeader, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(CardTitle, { children: __("Status", "yatra") }) }),
2133 /* @__PURE__ */ jsxRuntimeExports.jsx(CardContent, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
2134 Select,
2135 {
2136 value: formData.status,
2137 onChange: (e) => setFormData((prev) => ({
2138 ...prev,
2139 status: e.target.value
2140 })),
2141 children: [
2142 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "active", children: __("Active", "yatra") }),
2143 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "inactive", children: __("Inactive", "yatra") })
2144 ]
2145 }
2146 ) })
2147 ] }),
2148 /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [
2149 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardHeader, { children: [
2150 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardTitle, { className: "flex items-center gap-2", children: [
2151 /* @__PURE__ */ jsxRuntimeExports.jsx(Eye, { className: "w-5 h-5" }),
2152 __("Preview", "yatra")
2153 ] }),
2154 /* @__PURE__ */ jsxRuntimeExports.jsx(CardDescription, { children: __("See which dates will be generated", "yatra") })
2155 ] }),
2156 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { children: [
2157 /* @__PURE__ */ jsxRuntimeExports.jsxs(
2158 Button,
2159 {
2160 type: "button",
2161 variant: "outline",
2162 className: "w-full mb-4",
2163 onClick: () => previewMutation.mutate(formData),
2164 disabled: previewMutation.isPending || !formData.trip_id,
2165 children: [
2166 previewMutation.isPending ? /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "w-4 h-4 mr-2 animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Eye, { className: "w-4 h-4 mr-2" }),
2167 __("Generate Preview", "yatra")
2168 ]
2169 }
2170 ),
2171 previewData && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3", children: [
2172 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between text-sm", children: [
2173 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-gray-600 dark:text-gray-400", children: __("Total dates:", "yatra") }),
2174 /* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { variant: "success", children: previewData.total })
2175 ] }),
2176 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "max-h-48 overflow-y-auto space-y-1", children: [
2177 previewData.dates && Array.isArray(previewData.dates) && previewData.dates.map((date, index) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
2178 "div",
2179 {
2180 className: "text-xs px-2 py-1 bg-gray-50 dark:bg-gray-800 rounded flex justify-between",
2181 children: [
2182 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: toDateValue(
2183 date.departure_date
2184 ).toLocaleDateString("en-US", {
2185 weekday: "short",
2186 month: "short",
2187 day: "numeric",
2188 year: "numeric"
2189 }) }),
2190 date.departure_time && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-gray-500", children: date.departure_time })
2191 ]
2192 },
2193 index
2194 )),
2195 previewData.total > 20 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-xs text-gray-500 text-center py-1", children: [
2196 "+",
2197 previewData.total - 20,
2198 " ",
2199 __("more dates", "yatra")
2200 ] })
2201 ] })
2202 ] })
2203 ] })
2204 ] }),
2205 /* @__PURE__ */ jsxRuntimeExports.jsx(Card, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(CardContent, { className: "pt-6", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3", children: [
2206 /* @__PURE__ */ jsxRuntimeExports.jsxs(Button, { type: "submit", className: "w-full", disabled: isLoading, children: [
2207 isLoading ? /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "w-4 h-4 mr-2 animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Save, { className: "w-4 h-4 mr-2" }),
2208 isEditing ? __("Update Rule", "yatra") : __("Create Rule", "yatra")
2209 ] }),
2210 /* @__PURE__ */ jsxRuntimeExports.jsx(
2211 Button,
2212 {
2213 type: "button",
2214 variant: "outline",
2215 className: "w-full",
2216 onClick: () => {
2217 var _a2;
2218 return navigate({
2219 subpage: "trips",
2220 tab: "availability",
2221 trip_id: ((_a2 = formData.trip_id) == null ? void 0 : _a2.toString()) || tripIdFromUrl || ""
2222 });
2223 },
2224 children: __("Cancel", "yatra")
2225 }
2226 )
2227 ] }) }) }),
2228 /* @__PURE__ */ jsxRuntimeExports.jsx(Alert, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ml-2", children: [
2229 /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "font-medium", children: __("How it works", "yatra") }),
2230 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-gray-600 dark:text-gray-400 mt-1", children: __(
2231 "Dates are generated automatically based on your pattern. Manually added specific dates will take priority over generated dates.",
2232 "yatra"
2233 ) })
2234 ] }) })
2235 ] })
2236 ] }) })
2237 ] });
2238 };
2239 export {
2240 RecurringRuleForm as default
2241 };
2242 //# sourceMappingURL=RecurringRuleForm-fKEgpUir.js.map
2243