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 / WhiteLabel-DsK2IbJo.js

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

1,169 lines 50.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { v as useQueryClient, r as reactExports, u as useQuery, w as useMutation, j as jsxRuntimeExports, bO as Building2, bP as Palette, c9 as PanelLeft, ca as Layout, bb as Lock, E as Loader2, aW as Save, S as Sparkles, C as Crown, X as ExternalLink, ay as X, aT as Image, y as ChevronDown, z as ChevronRight, aR as Eye, by as EyeOff, bc as GripVertical } from "./react-vendor-CithbthY.js";
2 import { u as useToast, _ as __, I as Input, a as apiClient } from "./index-Dec_weLB.js";
3 import { aG as DEFAULT_MENU_ITEMS, aH as useWordPressMedia, P as PageHeader, C as Card, d as CardContent, B as Button, f as CardHeader, g as CardTitle, h as CardDescription, s as Label, aI as MenuIcon, aJ as ICON_MAP, I as IconPicker } from "../../admin/dist/js/app.js";
4 import { M as ModulePageSkeleton } from "./module-skeleton-CpoAoviJ.js";
5 function toPickerValue(icon) {
6 if (!icon) return null;
7 if (typeof icon === "string") return null;
8 return icon;
9 }
10 const THEME_PRESETS = [
11 {
12 label: "Light",
13 surfaces: {
14 sidebar_bg: "#ffffff",
15 sidebar_text: "#374151",
16 topbar_bg: "#ffffff",
17 topbar_text: "#111827"
18 }
19 },
20 {
21 label: "Dark",
22 surfaces: {
23 sidebar_bg: "#111827",
24 sidebar_text: "#e5e7eb",
25 topbar_bg: "#111827",
26 topbar_text: "#f9fafb"
27 }
28 },
29 {
30 label: "Midnight",
31 surfaces: {
32 sidebar_bg: "#0f172a",
33 sidebar_text: "#94a3b8",
34 topbar_bg: "#1e293b",
35 topbar_text: "#e2e8f0"
36 }
37 },
38 {
39 label: "Ocean",
40 surfaces: {
41 sidebar_bg: "#0c4a6e",
42 sidebar_text: "#e0f2fe",
43 topbar_bg: "#075985",
44 topbar_text: "#f0f9ff"
45 }
46 },
47 {
48 label: "Sand",
49 surfaces: {
50 sidebar_bg: "#fef3c7",
51 sidebar_text: "#78350f",
52 topbar_bg: "#fef9c3",
53 topbar_text: "#854d0e"
54 }
55 },
56 {
57 label: "Forest",
58 surfaces: {
59 sidebar_bg: "#064e3b",
60 sidebar_text: "#d1fae5",
61 topbar_bg: "#065f46",
62 topbar_text: "#ecfdf5"
63 }
64 }
65 ];
66 const SECTIONS = [
67 {
68 id: "brand",
69 label: "Brand Identity",
70 icon: Building2,
71 description: "Plugin name, company, URLs, and logo shown across the admin and PDFs."
72 },
73 {
74 id: "theme",
75 label: "Theme",
76 icon: Palette,
77 description: "Brand accent color, plus surface theme — sidebar and top bar background + text colors. Pick a preset or fine-tune each color."
78 },
79 {
80 id: "menu",
81 label: "Sidebar Menu",
82 icon: PanelLeft,
83 description: "Reorder, rename, re-icon, or hide entries in the Yatra sidebar."
84 },
85 {
86 id: "chrome",
87 label: "UI Chrome",
88 icon: Layout,
89 description: "Show or hide the version number, Back to WordPress link, and Join Community button."
90 }
91 ];
92 const DEFAULT_SETTINGS = {
93 plugin_name: "",
94 company_name: "",
95 website_url: "",
96 support_url: "",
97 logo_url: "",
98 primary_color: "",
99 menu_overrides: {},
100 menu_order: {},
101 ui_chrome: {},
102 theme_surfaces: {}
103 };
104 function toOrderMap(raw) {
105 if (!raw) return {};
106 if (Array.isArray(raw)) return { "": [...raw] };
107 return Object.fromEntries(
108 Object.entries(raw).map(([k, v]) => [k, Array.isArray(v) ? [...v] : []])
109 );
110 }
111 const PlanBadge = () => /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1 rounded-full bg-gradient-to-r from-purple-600 to-indigo-500 px-2.5 py-1 text-xs font-medium text-white shadow-sm", children: [
112 /* @__PURE__ */ jsxRuntimeExports.jsx(Crown, { className: "h-3 w-3" }),
113 __("Scale plan", "yatra")
114 ] });
115 const UpgradeCard = ({ meta }) => {
116 const upgradeUrl = (meta == null ? void 0 : meta.upgrade_url) || "https://wpyatra.com/pricing?module=white-label";
117 const licensePageUrl = (meta == null ? void 0 : meta.license_page_url) || "admin.php?page=yatra&subpage=license";
118 return /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { className: "max-w-3xl", children: [
119 /* @__PURE__ */ jsxRuntimeExports.jsx(CardHeader, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start gap-3", children: [
120 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rounded-md bg-amber-100 p-2 text-amber-600 dark:bg-amber-900/30 dark:text-amber-400", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Crown, { className: "h-5 w-5" }) }),
121 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1", children: [
122 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
123 /* @__PURE__ */ jsxRuntimeExports.jsx(CardTitle, { children: __("White Label", "yatra") }),
124 /* @__PURE__ */ jsxRuntimeExports.jsx(PlanBadge, {})
125 ] }),
126 /* @__PURE__ */ jsxRuntimeExports.jsx(CardDescription, { className: "mt-1", children: __(
127 "White Label is exclusive to the Scale plan (Yearly or Lifetime). Upgrade to remove all Yatra / MantraBrain references from your clients' admin.",
128 "yatra"
129 ) })
130 ] })
131 ] }) }),
132 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { className: "space-y-4", children: [
133 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-gray-600 dark:text-gray-300", children: __(
134 "Rebrand the entire Yatra plugin as your own product — admin menu, plugin list, and PDFs — and remove every reference to Yatra or MantraBrain from what your clients see.",
135 "yatra"
136 ) }),
137 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-3 pt-2", children: [
138 /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("a", { href: upgradeUrl, target: "_blank", rel: "noopener noreferrer", children: [
139 (meta == null ? void 0 : meta.is_pro_active) ? __("Upgrade to Scale", "yatra") : __("Get Yatra Pro Scale", "yatra"),
140 /* @__PURE__ */ jsxRuntimeExports.jsx(ExternalLink, { className: "ml-2 h-4 w-4" })
141 ] }) }),
142 (meta == null ? void 0 : meta.is_pro_active) && /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { variant: "outline", asChild: true, children: /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: licensePageUrl, children: __("Manage License", "yatra") }) })
143 ] })
144 ] })
145 ] });
146 };
147 const MenuRow = ({
148 slug,
149 defaultLabel,
150 defaultIconName,
151 override,
152 isSubmenu = false,
153 draggable = false,
154 isDragging = false,
155 dropPosition = null,
156 onDragStart,
157 onDragOver,
158 onDragEnd,
159 onDragLeave,
160 onDrop,
161 onPatch
162 }) => {
163 const FallbackIcon = ICON_MAP[defaultIconName] || ICON_MAP.Settings;
164 const hidden = Boolean(override.hidden);
165 return /* @__PURE__ */ jsxRuntimeExports.jsxs(
166 "div",
167 {
168 className: "relative",
169 onDragOver,
170 onDragLeave,
171 onDrop,
172 children: [
173 dropPosition === "above" && /* @__PURE__ */ jsxRuntimeExports.jsx(
174 "div",
175 {
176 className: "pointer-events-none absolute -top-1 left-0 right-0 z-10 h-1 rounded bg-blue-500 shadow",
177 "aria-hidden": "true"
178 }
179 ),
180 dropPosition === "below" && /* @__PURE__ */ jsxRuntimeExports.jsx(
181 "div",
182 {
183 className: "pointer-events-none absolute -bottom-1 left-0 right-0 z-10 h-1 rounded bg-blue-500 shadow",
184 "aria-hidden": "true"
185 }
186 ),
187 /* @__PURE__ */ jsxRuntimeExports.jsxs(
188 "div",
189 {
190 draggable,
191 onDragStart,
192 onDragEnd,
193 className: `flex items-center gap-3 rounded-md border px-3 py-2 transition-shadow ${isDragging ? "border-blue-400 bg-blue-50 opacity-60 dark:border-blue-500 dark:bg-blue-900/20" : dropPosition === "into" ? "border-blue-400 bg-blue-50 ring-2 ring-blue-400 dark:border-blue-500 dark:bg-blue-900/30" : isSubmenu ? "border-gray-100 bg-gray-50 dark:border-gray-800 dark:bg-gray-900/40" : "border-gray-200 bg-white dark:border-gray-700 dark:bg-gray-800"}`,
194 children: [
195 draggable ? /* @__PURE__ */ jsxRuntimeExports.jsx(
196 "button",
197 {
198 type: "button",
199 className: "cursor-grab touch-none text-gray-400 hover:text-gray-600 active:cursor-grabbing dark:hover:text-gray-200",
200 "aria-label": __("Drag to reorder", "yatra"),
201 onMouseDown: (e) => e.stopPropagation(),
202 children: /* @__PURE__ */ jsxRuntimeExports.jsx(GripVertical, { className: "h-4 w-4" })
203 }
204 ) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "inline-block w-4", "aria-hidden": "true" }),
205 /* @__PURE__ */ jsxRuntimeExports.jsx(
206 MenuIcon,
207 {
208 icon: override.icon,
209 fallback: FallbackIcon,
210 className: "h-4 w-4 text-gray-500"
211 }
212 ),
213 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-[140px]", children: [
214 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-medium text-gray-900 dark:text-white", children: defaultLabel }),
215 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-[10px] uppercase tracking-wide text-gray-400", children: slug })
216 ] }),
217 /* @__PURE__ */ jsxRuntimeExports.jsx(
218 Input,
219 {
220 value: override.label ?? "",
221 placeholder: defaultLabel,
222 disabled: hidden,
223 className: "max-w-[180px]",
224 onChange: (e) => onPatch({ label: e.target.value })
225 }
226 ),
227 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-w-[180px]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
228 IconPicker,
229 {
230 value: toPickerValue(override.icon),
231 onChange: (val) => onPatch({ icon: val ?? void 0 }),
232 size: "sm",
233 allowImageUpload: true,
234 allowIconSelection: true
235 }
236 ) }),
237 /* @__PURE__ */ jsxRuntimeExports.jsx(
238 "button",
239 {
240 type: "button",
241 onClick: () => onPatch({ hidden: !hidden }),
242 className: `ml-auto inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs font-medium ${hidden ? "bg-red-50 text-red-700 dark:bg-red-900/30 dark:text-red-300" : "bg-green-50 text-green-700 dark:bg-green-900/30 dark:text-green-300"}`,
243 "aria-label": hidden ? __("Show this menu item", "yatra") : __("Hide this menu item", "yatra"),
244 children: hidden ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
245 /* @__PURE__ */ jsxRuntimeExports.jsx(EyeOff, { className: "h-3 w-3" }),
246 __("Hidden", "yatra")
247 ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
248 /* @__PURE__ */ jsxRuntimeExports.jsx(Eye, { className: "h-3 w-3" }),
249 __("Visible", "yatra")
250 ] })
251 }
252 )
253 ]
254 }
255 )
256 ]
257 }
258 );
259 };
260 const WhiteLabel = () => {
261 const { showToast } = useToast();
262 const queryClient = useQueryClient();
263 const [form, setForm] = reactExports.useState(DEFAULT_SETTINGS);
264 const [activeSection, setActiveSection] = reactExports.useState("brand");
265 const [draggingSlug, setDraggingSlug] = reactExports.useState(null);
266 const [dropTarget, setDropTarget] = reactExports.useState(null);
267 const [expandedSubmenus, setExpandedSubmenus] = reactExports.useState(
268 () => new Set(DEFAULT_MENU_ITEMS.filter((m) => m.submenu).map((m) => m.slug))
269 );
270 const { openMediaLibrary } = useWordPressMedia({
271 title: __("Select brand logo", "yatra"),
272 buttonText: __("Use this image", "yatra"),
273 multiple: false,
274 library: { type: "image" }
275 });
276 const { data, isLoading } = useQuery({
277 queryKey: ["white-label-settings"],
278 queryFn: async () => {
279 const response = await apiClient.get("/white-label/settings");
280 return response;
281 }
282 });
283 reactExports.useEffect(() => {
284 if (data == null ? void 0 : data.data) {
285 setForm({
286 ...DEFAULT_SETTINGS,
287 ...data.data,
288 menu_overrides: data.data.menu_overrides ?? {},
289 menu_order: toOrderMap(data.data.menu_order),
290 ui_chrome: data.data.ui_chrome ?? {},
291 theme_surfaces: data.data.theme_surfaces ?? {}
292 });
293 }
294 }, [data]);
295 const saveMutation = useMutation({
296 mutationFn: async (payload) => {
297 const response = await apiClient.put("/white-label/settings", payload);
298 return response;
299 },
300 onSuccess: () => {
301 showToast(__("White Label settings saved.", "yatra"), "success");
302 queryClient.invalidateQueries({ queryKey: ["white-label-settings"] });
303 },
304 onError: (error) => {
305 var _a, _b;
306 const msg = ((_b = (_a = error == null ? void 0 : error.response) == null ? void 0 : _a.data) == null ? void 0 : _b.message) || __("Failed to save settings.", "yatra");
307 showToast(msg, "error");
308 }
309 });
310 const meta = data == null ? void 0 : data.meta;
311 const isAgency = Boolean(meta == null ? void 0 : meta.is_agency_active);
312 const isModuleEnabled = Boolean(meta == null ? void 0 : meta.is_module_enabled);
313 const updateField = reactExports.useCallback(
314 (key, value) => setForm((prev) => ({ ...prev, [key]: value })),
315 []
316 );
317 const updateMenuOverride = reactExports.useCallback(
318 (slug, patch) => {
319 setForm((prev) => {
320 const next = { ...prev.menu_overrides ?? {} };
321 const current = next[slug] ?? {};
322 const merged = { ...current, ...patch };
323 if (merged.label === "") delete merged.label;
324 if (merged.icon === "") delete merged.icon;
325 if (merged.hidden === false) delete merged.hidden;
326 if (Object.keys(merged).length === 0) {
327 delete next[slug];
328 } else {
329 next[slug] = merged;
330 }
331 return { ...prev, menu_overrides: next };
332 });
333 },
334 []
335 );
336 const toggleUiChrome = reactExports.useCallback((key) => {
337 setForm((prev) => {
338 const next = { ...prev.ui_chrome ?? {} };
339 if (next[key]) {
340 delete next[key];
341 } else {
342 next[key] = true;
343 }
344 return { ...prev, ui_chrome: next };
345 });
346 }, []);
347 const handlePickLogo = reactExports.useCallback(() => {
348 openMediaLibrary((attachment) => {
349 if (attachment && !Array.isArray(attachment)) {
350 updateField("logo_url", attachment.url);
351 }
352 });
353 }, [openMediaLibrary, updateField]);
354 const atoms = reactExports.useMemo(() => {
355 const list = [];
356 for (const item of DEFAULT_MENU_ITEMS) {
357 list.push({
358 key: item.slug,
359 defaultParent: "",
360 defaultLabel: item.label,
361 defaultIconName: item.iconName
362 });
363 if (item.submenu) {
364 for (const sub of item.submenu) {
365 list.push({
366 key: sub.key,
367 defaultParent: item.slug,
368 defaultLabel: sub.label,
369 defaultIconName: sub.iconName
370 });
371 }
372 }
373 }
374 return list;
375 }, []);
376 const atomMap = reactExports.useMemo(() => new Map(atoms.map((a) => [a.key, a])), [atoms]);
377 const effectiveParent = reactExports.useCallback(
378 (key) => {
379 var _a, _b, _c;
380 const ov = (_a = form.menu_overrides) == null ? void 0 : _a[key];
381 if (ov && typeof ov.parent === "string") {
382 if (ov.parent === "") return "";
383 if (((_b = atomMap.get(ov.parent)) == null ? void 0 : _b.defaultParent) === "") return ov.parent;
384 }
385 return ((_c = atomMap.get(key)) == null ? void 0 : _c.defaultParent) ?? "";
386 },
387 [form.menu_overrides, atomMap]
388 );
389 const renderRows = reactExports.useMemo(() => {
390 const orderMap = form.menu_order ?? {};
391 const groups = /* @__PURE__ */ new Map();
392 for (const atom of atoms) {
393 const parent = effectiveParent(atom.key);
394 if (parent === atom.key) continue;
395 const list = groups.get(parent) ?? [];
396 list.push(atom.key);
397 groups.set(parent, list);
398 }
399 const orderGroup = (parent, group) => {
400 const saved = orderMap[parent] ?? [];
401 if (saved.length === 0) return group;
402 const set = new Set(group);
403 const seen = /* @__PURE__ */ new Set();
404 const ordered = [];
405 for (const k of saved) {
406 if (set.has(k) && !seen.has(k)) {
407 ordered.push(k);
408 seen.add(k);
409 }
410 }
411 for (const k of group) if (!seen.has(k)) ordered.push(k);
412 return ordered;
413 };
414 const rows = [];
415 for (const topKey of orderGroup("", groups.get("") ?? [])) {
416 const topAtom = atomMap.get(topKey);
417 if (!topAtom) continue;
418 rows.push({ atom: topAtom, depth: 0, parent: "" });
419 if (expandedSubmenus.has(topKey)) {
420 for (const childKey of orderGroup(topKey, groups.get(topKey) ?? [])) {
421 const childAtom = atomMap.get(childKey);
422 if (childAtom)
423 rows.push({ atom: childAtom, depth: 1, parent: topKey });
424 }
425 }
426 }
427 return rows;
428 }, [atoms, atomMap, effectiveParent, form.menu_order, expandedSubmenus]);
429 const hasChildrenByParent = reactExports.useMemo(() => {
430 const map = /* @__PURE__ */ new Map();
431 for (const atom of atoms) {
432 const parent = effectiveParent(atom.key);
433 if (parent === "") continue;
434 map.set(parent, true);
435 }
436 return map;
437 }, [atoms, effectiveParent]);
438 const handleDragStart = reactExports.useCallback((key, e) => {
439 setDraggingSlug(key);
440 if (e.dataTransfer) {
441 e.dataTransfer.effectAllowed = "move";
442 }
443 }, []);
444 const handleRowDragOver = reactExports.useCallback(
445 (key, e) => {
446 if (!draggingSlug || draggingSlug === key) return;
447 e.preventDefault();
448 if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
449 const rect = e.currentTarget.getBoundingClientRect();
450 const y = e.clientY - rect.top;
451 const h = rect.height || 1;
452 const ratio = Math.max(0, Math.min(1, y / h));
453 const isHoveredTopLevel = effectiveParent(key) === "";
454 const draggedAtom = atomMap.get(draggingSlug);
455 const isDescendantOfDragged = draggedAtom && draggedAtom.defaultParent === "" && effectiveParent(key) === draggingSlug;
456 let position;
457 if (isHoveredTopLevel && !isDescendantOfDragged) {
458 if (ratio < 0.25) position = "above";
459 else if (ratio > 0.75) position = "below";
460 else position = "into";
461 } else {
462 position = ratio < 0.5 ? "above" : "below";
463 }
464 setDropTarget(
465 (prev) => prev && prev.key === key && prev.position === position ? prev : { key, position }
466 );
467 },
468 [draggingSlug, effectiveParent, atomMap]
469 );
470 const handleRowDragLeave = reactExports.useCallback(() => {
471 }, []);
472 const handleDragEnd = reactExports.useCallback(() => {
473 setDraggingSlug(null);
474 setDropTarget(null);
475 }, []);
476 const handleRowDrop = reactExports.useCallback(
477 (targetKey, e) => {
478 e.preventDefault();
479 const src = draggingSlug;
480 const drop = dropTarget;
481 setDraggingSlug(null);
482 setDropTarget(null);
483 if (!src || src === targetKey || !drop || drop.key !== targetKey) return;
484 const srcAtom = atomMap.get(src);
485 const targetAtom = atomMap.get(targetKey);
486 if (!srcAtom || !targetAtom) return;
487 let newParent;
488 if (drop.position === "into") {
489 if (targetAtom.defaultParent !== "") return;
490 newParent = targetKey;
491 } else {
492 newParent = effectiveParent(targetKey);
493 }
494 const parentAtom = atomMap.get(newParent);
495 if (newParent !== "" && parentAtom && parentAtom.defaultParent !== "") {
496 return;
497 }
498 if (newParent === src) return;
499 const parentEffective = newParent === "" ? "" : effectiveParent(newParent);
500 if (parentEffective === src) return;
501 setForm((prev) => {
502 const overrides = { ...prev.menu_overrides ?? {} };
503 const orderMap = toOrderMap(prev.menu_order);
504 {
505 const ov = { ...overrides[src] ?? {} };
506 if (newParent === srcAtom.defaultParent) {
507 delete ov.parent;
508 } else {
509 ov.parent = newParent;
510 }
511 if (Object.keys(ov).length === 0) {
512 delete overrides[src];
513 } else {
514 overrides[src] = ov;
515 }
516 }
517 const effectiveWithNew = (key) => {
518 var _a, _b;
519 const ov = overrides[key];
520 if (ov && typeof ov.parent === "string") {
521 if (ov.parent === "") return "";
522 if (((_a = atomMap.get(ov.parent)) == null ? void 0 : _a.defaultParent) === "") return ov.parent;
523 }
524 return ((_b = atomMap.get(key)) == null ? void 0 : _b.defaultParent) ?? "";
525 };
526 for (const [p, list] of Object.entries(orderMap)) {
527 orderMap[p] = list.filter((k) => k !== src);
528 }
529 const destGroup = atoms.filter((a) => a.key !== src && effectiveWithNew(a.key) === newParent).map((a) => a.key);
530 const existing = orderMap[newParent] ?? [];
531 const seeded = [];
532 const seen = /* @__PURE__ */ new Set();
533 for (const k of existing) {
534 if (destGroup.includes(k) && !seen.has(k)) {
535 seeded.push(k);
536 seen.add(k);
537 }
538 }
539 for (const k of destGroup) {
540 if (!seen.has(k)) seeded.push(k);
541 }
542 if (drop.position === "into") {
543 seeded.push(src);
544 } else {
545 const targetIdx = seeded.indexOf(targetKey);
546 if (targetIdx === -1) {
547 seeded.push(src);
548 } else {
549 const insertIdx = drop.position === "above" ? targetIdx : targetIdx + 1;
550 seeded.splice(insertIdx, 0, src);
551 }
552 }
553 orderMap[newParent] = seeded;
554 return {
555 ...prev,
556 menu_overrides: overrides,
557 menu_order: orderMap
558 };
559 });
560 },
561 [draggingSlug, dropTarget, atomMap, effectiveParent, atoms]
562 );
563 const toggleSubmenuExpanded = reactExports.useCallback((slug) => {
564 setExpandedSubmenus((prev) => {
565 const next = new Set(prev);
566 if (next.has(slug)) next.delete(slug);
567 else next.add(slug);
568 return next;
569 });
570 }, []);
571 if (isLoading) {
572 return /* @__PURE__ */ jsxRuntimeExports.jsx(ModulePageSkeleton, { variant: "form" });
573 }
574 if (!isAgency) {
575 return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-6", children: [
576 /* @__PURE__ */ jsxRuntimeExports.jsx(
577 PageHeader,
578 {
579 description: __("Rebrand Yatra as your own product.", "yatra")
580 }
581 ),
582 /* @__PURE__ */ jsxRuntimeExports.jsx(UpgradeCard, { meta })
583 ] });
584 }
585 const onSubmit = (e) => {
586 e.preventDefault();
587 saveMutation.mutate(form);
588 };
589 const renderBrand = () => /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [
590 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardHeader, { children: [
591 /* @__PURE__ */ jsxRuntimeExports.jsx(CardTitle, { children: __("Brand identity", "yatra") }),
592 /* @__PURE__ */ jsxRuntimeExports.jsx(CardDescription, { children: __("Shown in the admin menu, plugin list, and PDFs.", "yatra") })
593 ] }),
594 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { className: "grid gap-4 md:grid-cols-2", children: [
595 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1.5", children: [
596 /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "plugin_name", children: __("Plugin name", "yatra") }),
597 /* @__PURE__ */ jsxRuntimeExports.jsx(
598 Input,
599 {
600 id: "plugin_name",
601 value: form.plugin_name,
602 placeholder: "Yatra",
603 onChange: (e) => updateField("plugin_name", e.target.value)
604 }
605 )
606 ] }),
607 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1.5", children: [
608 /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "company_name", children: __("Company / Author", "yatra") }),
609 /* @__PURE__ */ jsxRuntimeExports.jsx(
610 Input,
611 {
612 id: "company_name",
613 value: form.company_name,
614 placeholder: "MantraBrain",
615 onChange: (e) => updateField("company_name", e.target.value)
616 }
617 )
618 ] }),
619 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1.5", children: [
620 /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "website_url", children: __("Website URL", "yatra") }),
621 /* @__PURE__ */ jsxRuntimeExports.jsx(
622 Input,
623 {
624 id: "website_url",
625 type: "url",
626 value: form.website_url,
627 placeholder: "https://your-agency.com",
628 onChange: (e) => updateField("website_url", e.target.value)
629 }
630 )
631 ] }),
632 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1.5", children: [
633 /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "support_url", children: __("Support URL", "yatra") }),
634 /* @__PURE__ */ jsxRuntimeExports.jsx(
635 Input,
636 {
637 id: "support_url",
638 type: "url",
639 value: form.support_url,
640 placeholder: "https://your-agency.com/support",
641 onChange: (e) => updateField("support_url", e.target.value)
642 }
643 )
644 ] }),
645 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1.5 md:col-span-2", children: [
646 /* @__PURE__ */ jsxRuntimeExports.jsx(Label, { htmlFor: "logo_url", children: __("Logo", "yatra") }),
647 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-start gap-3", children: [
648 form.logo_url ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative flex h-20 w-20 items-center justify-center overflow-hidden rounded-md border border-gray-200 bg-white dark:border-gray-700 dark:bg-gray-800", children: [
649 /* @__PURE__ */ jsxRuntimeExports.jsx(
650 "img",
651 {
652 src: form.logo_url,
653 alt: __("Brand logo preview", "yatra"),
654 className: "max-h-full max-w-full object-contain"
655 }
656 ),
657 /* @__PURE__ */ jsxRuntimeExports.jsx(
658 "button",
659 {
660 type: "button",
661 onClick: () => updateField("logo_url", ""),
662 className: "absolute right-1 top-1 rounded-full bg-white/90 p-0.5 text-gray-600 shadow hover:text-red-600 dark:bg-gray-900/80 dark:text-gray-300",
663 "aria-label": __("Remove logo", "yatra"),
664 children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "h-3.5 w-3.5" })
665 }
666 )
667 ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex h-20 w-20 items-center justify-center rounded-md border border-dashed border-gray-300 bg-gray-50 text-gray-400 dark:border-gray-700 dark:bg-gray-900/40", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Image, { className: "h-6 w-6" }) }),
668 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-1 min-w-0 flex-col gap-2", children: [
669 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap gap-2", children: [
670 /* @__PURE__ */ jsxRuntimeExports.jsxs(
671 Button,
672 {
673 type: "button",
674 variant: "outline",
675 onClick: handlePickLogo,
676 children: [
677 /* @__PURE__ */ jsxRuntimeExports.jsx(Image, { className: "mr-2 h-4 w-4" }),
678 form.logo_url ? __("Change logo", "yatra") : __("Choose from media library", "yatra")
679 ]
680 }
681 ),
682 form.logo_url && /* @__PURE__ */ jsxRuntimeExports.jsx(
683 Button,
684 {
685 type: "button",
686 variant: "ghost",
687 onClick: () => updateField("logo_url", ""),
688 children: __("Remove", "yatra")
689 }
690 )
691 ] }),
692 /* @__PURE__ */ jsxRuntimeExports.jsx(
693 Input,
694 {
695 id: "logo_url",
696 type: "url",
697 value: form.logo_url,
698 placeholder: "https://your-agency.com/logo.png",
699 onChange: (e) => updateField("logo_url", e.target.value)
700 }
701 ),
702 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: __(
703 "Used for the admin menu icon and PDF header. Square PNG, 64×64 or larger recommended.",
704 "yatra"
705 ) })
706 ] })
707 ] })
708 ] })
709 ] })
710 ] });
711 const renderTheme = () => {
712 const updateSurface = (key, value) => {
713 setForm((prev) => {
714 const next = { ...prev.theme_surfaces ?? {} };
715 if (value === "") {
716 delete next[key];
717 } else {
718 next[key] = value;
719 }
720 return { ...prev, theme_surfaces: next };
721 });
722 };
723 const applyPreset = (surfaces) => {
724 setForm((prev) => ({ ...prev, theme_surfaces: { ...surfaces } }));
725 };
726 const surfaceFields = [
727 {
728 key: "sidebar_bg",
729 label: __("Sidebar background", "yatra"),
730 fallback: "#ffffff"
731 },
732 {
733 key: "sidebar_text",
734 label: __("Sidebar text", "yatra"),
735 fallback: "#374151"
736 },
737 {
738 key: "topbar_bg",
739 label: __("Top bar background", "yatra"),
740 fallback: "#ffffff"
741 },
742 {
743 key: "topbar_text",
744 label: __("Top bar text", "yatra"),
745 fallback: "#111827"
746 }
747 ];
748 const hasAnySurface = Object.values(form.theme_surfaces ?? {}).some(
749 (v) => typeof v === "string" && v !== ""
750 );
751 return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
752 /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [
753 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardHeader, { children: [
754 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
755 /* @__PURE__ */ jsxRuntimeExports.jsx(Palette, { className: "h-4 w-4 text-gray-500" }),
756 /* @__PURE__ */ jsxRuntimeExports.jsx(CardTitle, { children: __("Color scheme", "yatra") })
757 ] }),
758 /* @__PURE__ */ jsxRuntimeExports.jsx(CardDescription, { children: __(
759 "Brand accent color used for buttons, active menu items, and badges across the admin.",
760 "yatra"
761 ) })
762 ] }),
763 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { children: [
764 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
765 /* @__PURE__ */ jsxRuntimeExports.jsx(
766 "input",
767 {
768 type: "color",
769 value: form.primary_color || "#2563eb",
770 onChange: (e) => updateField("primary_color", e.target.value),
771 className: "h-10 w-12 cursor-pointer rounded border border-gray-300 bg-white p-1 dark:border-gray-700 dark:bg-gray-800",
772 "aria-label": __("Pick brand accent color", "yatra")
773 }
774 ),
775 /* @__PURE__ */ jsxRuntimeExports.jsx(
776 Input,
777 {
778 value: form.primary_color,
779 placeholder: "#2563eb",
780 onChange: (e) => updateField("primary_color", e.target.value),
781 className: "max-w-[200px]"
782 }
783 ),
784 form.primary_color && /* @__PURE__ */ jsxRuntimeExports.jsx(
785 Button,
786 {
787 type: "button",
788 variant: "ghost",
789 onClick: () => updateField("primary_color", ""),
790 children: __("Reset to default", "yatra")
791 }
792 )
793 ] }),
794 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-4 flex flex-wrap gap-2", children: [
795 { label: "Yatra Blue", color: "" },
796 { label: "Emerald", color: "#10b981" },
797 { label: "Indigo", color: "#6366f1" },
798 { label: "Rose", color: "#f43f5e" },
799 { label: "Slate", color: "#475569" },
800 { label: "Amber", color: "#d97706" }
801 ].map((preset) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
802 "button",
803 {
804 type: "button",
805 onClick: () => updateField("primary_color", preset.color),
806 className: "inline-flex items-center gap-2 rounded-md border border-gray-200 px-2 py-1 text-xs text-gray-700 hover:border-gray-300 hover:bg-gray-50 dark:border-gray-700 dark:text-gray-200 dark:hover:bg-gray-800",
807 children: [
808 /* @__PURE__ */ jsxRuntimeExports.jsx(
809 "span",
810 {
811 className: "inline-block h-4 w-4 rounded-sm border border-gray-200 dark:border-gray-700",
812 style: { background: preset.color || "#2563eb" }
813 }
814 ),
815 preset.label
816 ]
817 },
818 preset.label
819 )) }),
820 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-2 text-xs text-gray-500 dark:text-gray-400", children: __("Leave blank to keep the default Yatra blue.", "yatra") })
821 ] })
822 ] }),
823 /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [
824 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardHeader, { children: [
825 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
826 /* @__PURE__ */ jsxRuntimeExports.jsx(Sparkles, { className: "h-4 w-4 text-gray-500" }),
827 /* @__PURE__ */ jsxRuntimeExports.jsx(CardTitle, { children: __("Theme", "yatra") })
828 ] }),
829 /* @__PURE__ */ jsxRuntimeExports.jsx(CardDescription, { children: __(
830 "Like a custom light/dark mode — pick a preset to repaint the sidebar and top bar in one click, or fine-tune the four colors below.",
831 "yatra"
832 ) })
833 ] }),
834 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { children: [
835 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-4 flex flex-wrap gap-2", children: [
836 THEME_PRESETS.map((preset) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
837 "button",
838 {
839 type: "button",
840 onClick: () => applyPreset(preset.surfaces),
841 className: "inline-flex items-center gap-2 rounded-md border border-gray-200 px-2 py-1 text-xs font-medium text-gray-700 hover:border-gray-300 hover:bg-gray-50 dark:border-gray-700 dark:text-gray-200 dark:hover:bg-gray-800",
842 children: [
843 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex h-4 w-4 overflow-hidden rounded-sm border border-gray-200 dark:border-gray-700", children: [
844 /* @__PURE__ */ jsxRuntimeExports.jsx(
845 "span",
846 {
847 className: "block w-1/2",
848 style: { background: preset.surfaces.sidebar_bg }
849 }
850 ),
851 /* @__PURE__ */ jsxRuntimeExports.jsx(
852 "span",
853 {
854 className: "block w-1/2",
855 style: { background: preset.surfaces.topbar_bg }
856 }
857 )
858 ] }),
859 preset.label
860 ]
861 },
862 preset.label
863 )),
864 hasAnySurface && /* @__PURE__ */ jsxRuntimeExports.jsx(
865 "button",
866 {
867 type: "button",
868 onClick: () => updateField("theme_surfaces", {}),
869 className: "inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs text-gray-500 hover:text-gray-700 dark:hover:text-gray-200",
870 children: __("Reset theme", "yatra")
871 }
872 )
873 ] }),
874 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid gap-3 md:grid-cols-2", children: surfaceFields.map(({ key, label, fallback }) => {
875 const value = (form.theme_surfaces ?? {})[key] ?? "";
876 return /* @__PURE__ */ jsxRuntimeExports.jsxs(
877 "div",
878 {
879 className: "flex items-center gap-2 rounded-md border border-gray-200 p-2 dark:border-gray-700",
880 children: [
881 /* @__PURE__ */ jsxRuntimeExports.jsx(
882 "input",
883 {
884 type: "color",
885 value: value || fallback,
886 onChange: (e) => updateSurface(key, e.target.value),
887 className: "h-9 w-10 cursor-pointer rounded border border-gray-300 bg-white p-1 dark:border-gray-600 dark:bg-gray-800",
888 "aria-label": label
889 }
890 ),
891 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [
892 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs font-medium text-gray-700 dark:text-gray-200", children: label }),
893 /* @__PURE__ */ jsxRuntimeExports.jsx(
894 Input,
895 {
896 value,
897 placeholder: fallback,
898 onChange: (e) => updateSurface(key, e.target.value),
899 className: "mt-1 max-w-full"
900 }
901 )
902 ] }),
903 value && /* @__PURE__ */ jsxRuntimeExports.jsx(
904 "button",
905 {
906 type: "button",
907 onClick: () => updateSurface(key, ""),
908 className: "text-xs text-gray-400 hover:text-red-600",
909 "aria-label": __("Clear this color", "yatra"),
910 children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "h-3.5 w-3.5" })
911 }
912 )
913 ]
914 },
915 key
916 );
917 }) }),
918 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-3 text-xs text-gray-500 dark:text-gray-400", children: __(
919 "Each color is independent — clear one to fall back to its Yatra default while keeping the others.",
920 "yatra"
921 ) })
922 ] })
923 ] })
924 ] });
925 };
926 const renderMenu = () => {
927 const hasAnyOverrides = Object.keys(form.menu_order ?? {}).length > 0 || Object.values(form.menu_overrides ?? {}).some(
928 (ov) => ov && ov.parent !== void 0
929 );
930 return /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [
931 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardHeader, { children: [
932 /* @__PURE__ */ jsxRuntimeExports.jsx(CardTitle, { children: __("Sidebar menu", "yatra") }),
933 /* @__PURE__ */ jsxRuntimeExports.jsx(CardDescription, { children: __(
934 "Drag items to reorder, nest, or promote — like the WordPress Menus screen. Drop on the top or bottom edge of a row to place above or below; drop on the middle of a top-level row to nest the item underneath. Nesting is one level deep.",
935 "yatra"
936 ) })
937 ] }),
938 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { children: [
939 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-col gap-2", children: renderRows.map((row) => {
940 var _a;
941 const ov = ((_a = form.menu_overrides) == null ? void 0 : _a[row.atom.key]) ?? {};
942 const effectiveOwnParent = effectiveParent(row.atom.key);
943 const isTopLevel = effectiveOwnParent === "";
944 const showsChildren = isTopLevel && hasChildrenByParent.has(row.atom.key);
945 const expanded = expandedSubmenus.has(row.atom.key);
946 const isDropTarget = dropTarget !== null && dropTarget.key === row.atom.key && draggingSlug !== row.atom.key;
947 return /* @__PURE__ */ jsxRuntimeExports.jsx(
948 "div",
949 {
950 style: row.depth > 0 ? { marginLeft: 32 } : void 0,
951 children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-stretch gap-1", children: [
952 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
953 MenuRow,
954 {
955 slug: row.atom.key,
956 defaultLabel: row.atom.defaultLabel,
957 defaultIconName: row.atom.defaultIconName,
958 override: ov,
959 isSubmenu: row.depth > 0,
960 draggable: true,
961 isDragging: draggingSlug === row.atom.key,
962 dropPosition: isDropTarget ? dropTarget.position : null,
963 onDragStart: (e) => handleDragStart(row.atom.key, e),
964 onDragOver: (e) => handleRowDragOver(row.atom.key, e),
965 onDragEnd: handleDragEnd,
966 onDragLeave: handleRowDragLeave,
967 onDrop: (e) => handleRowDrop(row.atom.key, e),
968 onPatch: (patch) => updateMenuOverride(row.atom.key, patch)
969 }
970 ) }),
971 showsChildren && /* @__PURE__ */ jsxRuntimeExports.jsx(
972 "button",
973 {
974 type: "button",
975 onClick: () => toggleSubmenuExpanded(row.atom.key),
976 className: "inline-flex items-center justify-center rounded-md border border-gray-200 px-2 text-gray-500 hover:bg-gray-50 dark:border-gray-700 dark:hover:bg-gray-800",
977 "aria-expanded": expanded,
978 "aria-label": __("Toggle submenu", "yatra"),
979 children: expanded ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "h-4 w-4" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "h-4 w-4" })
980 }
981 )
982 ] })
983 },
984 row.atom.key
985 );
986 }) }),
987 hasAnyOverrides && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-4 flex justify-end", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
988 Button,
989 {
990 type: "button",
991 variant: "ghost",
992 onClick: () => {
993 updateField("menu_order", {});
994 setForm((prev) => {
995 const next = { ...prev.menu_overrides ?? {} };
996 for (const [key, ov] of Object.entries(next)) {
997 if (ov && ov.parent !== void 0) {
998 const stripped = { ...ov };
999 delete stripped.parent;
1000 if (Object.keys(stripped).length === 0) {
1001 delete next[key];
1002 } else {
1003 next[key] = stripped;
1004 }
1005 }
1006 }
1007 return { ...prev, menu_overrides: next };
1008 });
1009 },
1010 children: __("Reset structure to default", "yatra")
1011 }
1012 ) })
1013 ] })
1014 ] });
1015 };
1016 const renderChrome = () => {
1017 const items = [
1018 {
1019 key: "hideVersion",
1020 label: __("Hide version number", "yatra"),
1021 description: __(
1022 'Removes the small "v3.0.4" tag shown next to the brand name in the sidebar header.',
1023 "yatra"
1024 )
1025 },
1026 {
1027 key: "hideBackToWp",
1028 label: __('Hide "Back to WordPress" link', "yatra"),
1029 description: __(
1030 "Removes the link from the top bar AND the sidebar footer so clients don't see the wp-admin escape hatch.",
1031 "yatra"
1032 )
1033 },
1034 {
1035 key: "hideJoinCommunity",
1036 label: __('Hide "Join Community" link', "yatra"),
1037 description: __(
1038 "Removes the Facebook community button from the top bar.",
1039 "yatra"
1040 )
1041 }
1042 ];
1043 return /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [
1044 /* @__PURE__ */ jsxRuntimeExports.jsxs(CardHeader, { children: [
1045 /* @__PURE__ */ jsxRuntimeExports.jsx(CardTitle, { children: __("UI chrome", "yatra") }),
1046 /* @__PURE__ */ jsxRuntimeExports.jsx(CardDescription, { children: __(
1047 "Hide or show specific pieces of admin chrome — useful when delivering the app to clients who shouldn't be reminded of the underlying platform.",
1048 "yatra"
1049 ) })
1050 ] }),
1051 /* @__PURE__ */ jsxRuntimeExports.jsx(CardContent, { className: "space-y-3", children: items.map((item) => {
1052 var _a;
1053 const checked = !((_a = form.ui_chrome) == null ? void 0 : _a[item.key]);
1054 return /* @__PURE__ */ jsxRuntimeExports.jsxs(
1055 "label",
1056 {
1057 className: "flex items-start gap-3 rounded-md border border-gray-200 p-3 dark:border-gray-700",
1058 children: [
1059 /* @__PURE__ */ jsxRuntimeExports.jsx(
1060 "input",
1061 {
1062 type: "checkbox",
1063 className: "mt-1",
1064 checked: !checked,
1065 onChange: () => toggleUiChrome(item.key),
1066 "aria-label": item.label
1067 }
1068 ),
1069 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1", children: [
1070 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm font-medium text-gray-900 dark:text-white", children: item.label }),
1071 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-gray-500 dark:text-gray-400", children: item.description })
1072 ] }),
1073 /* @__PURE__ */ jsxRuntimeExports.jsx(
1074 "span",
1075 {
1076 className: `inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[11px] font-medium ${checked ? "bg-green-50 text-green-700 dark:bg-green-900/30 dark:text-green-300" : "bg-red-50 text-red-700 dark:bg-red-900/30 dark:text-red-300"}`,
1077 children: checked ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1078 /* @__PURE__ */ jsxRuntimeExports.jsx(Eye, { className: "h-3 w-3" }),
1079 __("Visible", "yatra")
1080 ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1081 /* @__PURE__ */ jsxRuntimeExports.jsx(EyeOff, { className: "h-3 w-3" }),
1082 __("Hidden", "yatra")
1083 ] })
1084 }
1085 )
1086 ]
1087 },
1088 item.key
1089 );
1090 }) })
1091 ] });
1092 };
1093 const currentSection = SECTIONS.find((s) => s.id === activeSection) ?? SECTIONS[0];
1094 return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-6", children: [
1095 /* @__PURE__ */ jsxRuntimeExports.jsx(
1096 PageHeader,
1097 {
1098 description: __(
1099 "Replace Yatra/MantraBrain branding shown in the admin and on PDFs.",
1100 "yatra"
1101 )
1102 }
1103 ),
1104 !isModuleEnabled && /* @__PURE__ */ jsxRuntimeExports.jsx(Card, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { className: "flex items-start gap-3 py-4", children: [
1105 /* @__PURE__ */ jsxRuntimeExports.jsx(Lock, { className: "mt-0.5 h-5 w-5 text-amber-500" }),
1106 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-sm", children: [
1107 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "font-medium", children: __("Module disabled", "yatra") }),
1108 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-gray-600 dark:text-gray-300", children: __(
1109 "Your Scale license is active, but the White Label module is not enabled yet. Enable it from the Modules page so branding overrides take effect.",
1110 "yatra"
1111 ) }),
1112 /* @__PURE__ */ jsxRuntimeExports.jsx(
1113 "a",
1114 {
1115 className: "mt-1 inline-block text-sm font-medium text-blue-600 hover:underline dark:text-blue-400",
1116 href: "admin.php?page=yatra&subpage=modules",
1117 children: __("Go to Modules →", "yatra")
1118 }
1119 )
1120 ] })
1121 ] }) }),
1122 /* @__PURE__ */ jsxRuntimeExports.jsx("form", { onSubmit, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid gap-6 lg:grid-cols-[240px_1fr]", children: [
1123 /* @__PURE__ */ jsxRuntimeExports.jsxs("aside", { className: "lg:sticky lg:top-4 lg:self-start", children: [
1124 /* @__PURE__ */ jsxRuntimeExports.jsx(Card, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(CardContent, { className: "p-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("nav", { className: "flex flex-col gap-1", children: SECTIONS.map((section) => {
1125 const Icon = section.icon;
1126 const active = section.id === activeSection;
1127 return /* @__PURE__ */ jsxRuntimeExports.jsxs(
1128 "button",
1129 {
1130 type: "button",
1131 onClick: () => setActiveSection(section.id),
1132 className: `flex items-center gap-2 rounded-md px-3 py-2 text-left text-sm transition-colors ${active ? "bg-blue-50 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300" : "text-gray-700 hover:bg-gray-50 dark:text-gray-200 dark:hover:bg-gray-800"}`,
1133 children: [
1134 /* @__PURE__ */ jsxRuntimeExports.jsx(Icon, { className: "h-4 w-4 shrink-0" }),
1135 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 truncate", children: section.label })
1136 ]
1137 },
1138 section.id
1139 );
1140 }) }) }) }),
1141 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-3 px-2 text-xs text-gray-500 dark:text-gray-400", children: currentSection.description })
1142 ] }),
1143 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
1144 activeSection === "brand" && renderBrand(),
1145 activeSection === "theme" && renderTheme(),
1146 activeSection === "menu" && renderMenu(),
1147 activeSection === "chrome" && renderChrome(),
1148 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
1149 /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { type: "submit", disabled: saveMutation.isPending, children: saveMutation.isPending ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1150 /* @__PURE__ */ jsxRuntimeExports.jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
1151 __("Saving…", "yatra")
1152 ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1153 /* @__PURE__ */ jsxRuntimeExports.jsx(Save, { className: "mr-2 h-4 w-4" }),
1154 __("Save White Label settings", "yatra")
1155 ] }) }),
1156 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs text-gray-400", children: [
1157 /* @__PURE__ */ jsxRuntimeExports.jsx(Sparkles, { className: "-mt-0.5 mr-1 inline h-3 w-3" }),
1158 __("Saves all sections at once.", "yatra")
1159 ] })
1160 ] })
1161 ] })
1162 ] }) })
1163 ] });
1164 };
1165 export {
1166 WhiteLabel as default
1167 };
1168 //# sourceMappingURL=WhiteLabel-DsK2IbJo.js.map
1169