@burdenoff/microfe-tours 2026.1014.1 → 2026.1114.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants/featureFlags.d.ts +24 -0
- package/dist/constants/featureFlags.js +1 -2
- package/dist/constants/featureFlags.js.map +1 -1
- package/dist/constants/permissions.d.ts +48 -0
- package/dist/constants/permissions.js +1 -2
- package/dist/constants/permissions.js.map +1 -1
- package/dist/dev/main.d.ts +0 -0
- package/dist/generated/global-operations.d.ts +1318 -0
- package/dist/generated/global-operations.js +2 -3
- package/dist/generated/global-operations.js.map +1 -1
- package/dist/generated/global-types.d.ts +26469 -0
- package/dist/generated/wspace-operations.d.ts +1 -0
- package/dist/generated/wspace-types.d.ts +108647 -0
- package/dist/index.d.ts +5 -0
- package/dist/test/happydom.d.ts +1 -0
- package/dist/test/testing-library.d.ts +1 -0
- package/dist/tours/ToursAdminRoot.d.ts +14 -0
- package/dist/tours/ToursAdminRoot.js +14 -13
- package/dist/tours/ToursAdminRoot.js.map +1 -1
- package/dist/tours/ToursAdminRoutes.d.ts +11 -0
- package/dist/tours/ToursAdminRoutes.js +12 -13
- package/dist/tours/ToursAdminRoutes.js.map +1 -1
- package/dist/tours/ToursRoot.d.ts +9 -0
- package/dist/tours/ToursRoot.js +1 -1
- package/dist/tours/ToursUserRoot.d.ts +13 -0
- package/dist/tours/ToursUserRoot.js +14 -13
- package/dist/tours/ToursUserRoot.js.map +1 -1
- package/dist/tours/ToursUserRoutes.d.ts +14 -0
- package/dist/tours/ToursUserRoutes.js +13 -13
- package/dist/tours/ToursUserRoutes.js.map +1 -1
- package/dist/tours/components/MarkdownEditor.d.ts +12 -0
- package/dist/tours/components/MarkdownEditor.js +1 -2
- package/dist/tours/components/MarkdownEditor.js.map +1 -1
- package/dist/tours/components/RouteHelpers.d.ts +31 -0
- package/dist/tours/components/RouteHelpers.js +1 -2
- package/dist/tours/components/RouteHelpers.js.map +1 -1
- package/dist/tours/components/ToursAdminNavRegistrar.d.ts +23 -0
- package/dist/tours/components/ToursAdminNavRegistrar.js +4 -3
- package/dist/tours/components/ToursAdminNavRegistrar.js.map +1 -1
- package/dist/tours/hooks/useMediaLibrary.d.ts +20 -0
- package/dist/tours/hooks/useMediaLibrary.js +1 -2
- package/dist/tours/hooks/useMediaLibrary.js.map +1 -1
- package/dist/tours/hooks/useStepSequencer.d.ts +18 -0
- package/dist/tours/hooks/useStepSequencer.js +16 -13
- package/dist/tours/hooks/useStepSequencer.js.map +1 -1
- package/dist/tours/hooks/useTourAnalytics.d.ts +30 -0
- package/dist/tours/hooks/useTourAnalytics.js +1 -2
- package/dist/tours/hooks/useTourAnalytics.js.map +1 -1
- package/dist/tours/hooks/useTourBuilder.d.ts +59 -0
- package/dist/tours/hooks/useTourBuilder.js +10 -6
- package/dist/tours/hooks/useTourBuilder.js.map +1 -1
- package/dist/tours/hooks/useTourLifecycle.d.ts +21 -0
- package/dist/tours/hooks/useTourLifecycle.js +4 -5
- package/dist/tours/hooks/useTourLifecycle.js.map +1 -1
- package/dist/tours/hooks/useTourPreview.d.ts +31 -0
- package/dist/tours/hooks/useTourPreview.js +5 -6
- package/dist/tours/hooks/useTourPreview.js.map +1 -1
- package/dist/tours/hooks/useToursList.d.ts +15 -0
- package/dist/tours/hooks/useToursList.js +1 -2
- package/dist/tours/hooks/useToursList.js.map +1 -1
- package/dist/tours/hooks/useToursPermissionAccess.d.ts +15 -0
- package/dist/tours/hooks/useToursPermissionAccess.js +1 -2
- package/dist/tours/hooks/useToursPermissionAccess.js.map +1 -1
- package/dist/tours/i18n.d.ts +413 -0
- package/dist/tours/i18n.js +1 -2
- package/dist/tours/i18n.js.map +1 -1
- package/dist/tours/index.d.ts +21 -0
- package/dist/tours/index.js +6 -5
- package/dist/tours/pages/AnalyticsDashboardPage.d.ts +5 -0
- package/dist/tours/pages/AnalyticsDashboardPage.js +6 -7
- package/dist/tours/pages/AnalyticsDashboardPage.js.map +1 -1
- package/dist/tours/pages/MediaLibraryPage.d.ts +5 -0
- package/dist/tours/pages/MediaLibraryPage.js +10 -11
- package/dist/tours/pages/MediaLibraryPage.js.map +1 -1
- package/dist/tours/pages/MyToursPage.d.ts +10 -0
- package/dist/tours/pages/MyToursPage.js +5 -6
- package/dist/tours/pages/MyToursPage.js.map +1 -1
- package/dist/tours/pages/MyToursProgressPage.d.ts +5 -0
- package/dist/tours/pages/MyToursProgressPage.js +5 -6
- package/dist/tours/pages/MyToursProgressPage.js.map +1 -1
- package/dist/tours/pages/SchedulerPage.d.ts +5 -0
- package/dist/tours/pages/SchedulerPage.js +10 -11
- package/dist/tours/pages/SchedulerPage.js.map +1 -1
- package/dist/tours/pages/StepEditorPage.d.ts +6 -0
- package/dist/tours/pages/StepEditorPage.js +302 -309
- package/dist/tours/pages/StepEditorPage.js.map +1 -1
- package/dist/tours/pages/SystemAnalyticsPage.d.ts +5 -0
- package/dist/tours/pages/SystemAnalyticsPage.js +1 -2
- package/dist/tours/pages/SystemAnalyticsPage.js.map +1 -1
- package/dist/tours/pages/TemplateLibraryPage.d.ts +5 -0
- package/dist/tours/pages/TemplateLibraryPage.js +15 -16
- package/dist/tours/pages/TemplateLibraryPage.js.map +1 -1
- package/dist/tours/pages/TourBuilderPage.d.ts +1 -0
- package/dist/tours/pages/TourBuilderPage.js +273 -300
- package/dist/tours/pages/TourBuilderPage.js.map +1 -1
- package/dist/tours/pages/TourPreviewPage.d.ts +5 -0
- package/dist/tours/pages/TourPreviewPage.js +9 -10
- package/dist/tours/pages/TourPreviewPage.js.map +1 -1
- package/dist/tours/pages/ToursListPage.d.ts +5 -0
- package/dist/tours/pages/ToursListPage.js +157 -157
- package/dist/tours/pages/ToursListPage.js.map +1 -1
- package/dist/tours/providers/ToursProvider.d.ts +25 -0
- package/dist/tours/providers/ToursProvider.js +1 -2
- package/dist/tours/providers/ToursProvider.js.map +1 -1
- package/dist/tours/store/toursStore.d.ts +40 -0
- package/dist/tours/store/toursStore.js +5 -6
- package/dist/tours/store/toursStore.js.map +1 -1
- package/dist/tours/telemetry.d.ts +7 -0
- package/dist/tours/telemetry.js +1 -2
- package/dist/tours/telemetry.js.map +1 -1
- package/dist/tours/types/index.d.ts +348 -0
- package/dist/tours/utils/index.d.ts +28 -0
- package/dist/tours/utils/index.js +3 -4
- package/dist/tours/utils/index.js.map +1 -1
- package/dist/tours/utils/joinPath.d.ts +8 -0
- package/dist/tours/utils/joinPath.js +1 -2
- package/dist/tours/utils/joinPath.js.map +1 -1
- package/dist/utils/nativeBridge.d.ts +2 -0
- package/dist/utils/nativeBridge.js +1 -2
- package/package.json +62 -51
|
@@ -1,292 +1,292 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { isNative as c, nativeConfirm as
|
|
10
|
-
import { useEffect as
|
|
11
|
-
import { Markdown as
|
|
12
|
-
import { Eye as
|
|
13
|
-
import { jsx as
|
|
14
|
-
import { useNavigate as
|
|
15
|
-
import { AuroraBackground as
|
|
16
|
-
|
|
17
|
-
function
|
|
18
|
-
let { tr:
|
|
19
|
-
|
|
20
|
-
|
|
1
|
+
import { useToursList as e } from "../hooks/useToursList.js";
|
|
2
|
+
import { useTourLifecycle as t } from "../hooks/useTourLifecycle.js";
|
|
3
|
+
import { useToursPermissionAccess as n } from "../hooks/useToursPermissionAccess.js";
|
|
4
|
+
import { useToursStore as r } from "../store/toursStore.js";
|
|
5
|
+
import { useToursContext as i } from "../providers/ToursProvider.js";
|
|
6
|
+
import { useDeleteTourMutation as a } from "../../generated/global-operations.js";
|
|
7
|
+
import { TOUR_PERMISSIONS as o } from "../../constants/permissions.js";
|
|
8
|
+
import { useToursI18n as s } from "../i18n.js";
|
|
9
|
+
import { isNative as c, nativeConfirm as l, nativeImpact as u, nativeNotify as d, nativeToast as f } from "../../utils/nativeBridge.js";
|
|
10
|
+
import { useEffect as p, useState as m } from "react";
|
|
11
|
+
import { Markdown as h, PermissionGate as g } from "@burdenoff/fe-libs/shared/components";
|
|
12
|
+
import { Eye as _, Grid as v, List as y, ListOrdered as b, Plus as x, Search as S, Settings as C } from "lucide-react";
|
|
13
|
+
import { jsx as w, jsxs as T } from "react/jsx-runtime";
|
|
14
|
+
import { useNavigate as E } from "react-router";
|
|
15
|
+
import { AuroraBackground as D, Button as O, CTAOverflowMenu as ee, GlassCard as k, GradientText as te, IllustratedEmptyState as A, PagePurpose as j } from "@burdenoff/fe-libs/ui";
|
|
16
|
+
// src/tours/pages/ToursListPage.tsx
|
|
17
|
+
function M() {
|
|
18
|
+
let { tr: M } = s(), N = E(), { basePath: P = "/" } = i(), { viewMode: F, tourFilter: I, toursListRevision: L, setViewMode: R, updateTourFilter: z, notifyToursListChanged: B } = r(), { hasPermission: V, isLoading: H } = n(), U = V(o.TOUR_UPDATE), W = V(o.TOUR_STEP_UPDATE), G = V(o.TOUR_READ), K = V(o.TOUR_DELETE), q = V(o.TOUR_PUBLISH), J = V(o.TOUR_ARCHIVE), Y = V(o.TOUR_DUPLICATE), { tours: X, loading: Z, fetchTours: Q } = e(), { publishTour: ne, unpublishTour: re, archiveTour: ie, duplicateTour: ae } = t(), [oe] = a(), [se, ce] = m(""), [le, ue] = m("all");
|
|
19
|
+
p(() => {
|
|
20
|
+
H || Q({ ...I });
|
|
21
21
|
}, [
|
|
22
|
-
|
|
23
|
-
F,
|
|
22
|
+
Q,
|
|
24
23
|
I,
|
|
25
|
-
|
|
24
|
+
L,
|
|
25
|
+
H
|
|
26
26
|
]);
|
|
27
|
-
let
|
|
28
|
-
|
|
27
|
+
let de = (e) => {
|
|
28
|
+
ce(e), z({ search: e });
|
|
29
|
+
}, fe = (e) => {
|
|
30
|
+
ue(e), z({ status: e });
|
|
31
|
+
}, $ = () => {
|
|
32
|
+
let e = P.endsWith("/") ? `${P}new` : `${P}/new`;
|
|
33
|
+
N(e);
|
|
29
34
|
}, pe = (e) => {
|
|
30
|
-
de(e), R({ status: e });
|
|
31
|
-
}, Q = () => {
|
|
32
|
-
M(N.endsWith("/") ? `${N}new` : `${N}/new`);
|
|
33
|
-
}, me = (e) => {
|
|
34
35
|
switch (e) {
|
|
35
|
-
case "DRAFT": return
|
|
36
|
-
case "PUBLISHED": return
|
|
37
|
-
case "ARCHIVED": return
|
|
38
|
-
case "SCHEDULED": return
|
|
36
|
+
case "DRAFT": return M("toursList.statusDraft");
|
|
37
|
+
case "PUBLISHED": return M("toursList.statusPublished");
|
|
38
|
+
case "ARCHIVED": return M("toursList.statusArchived");
|
|
39
|
+
case "SCHEDULED": return M("toursList.statusScheduled");
|
|
39
40
|
}
|
|
40
|
-
},
|
|
41
|
-
|
|
41
|
+
}, me = async (e) => {
|
|
42
|
+
u("light");
|
|
42
43
|
try {
|
|
43
|
-
await
|
|
44
|
+
await ne(e), d("success");
|
|
44
45
|
} catch {
|
|
45
|
-
|
|
46
|
+
d("error"), c() ? f(M("toursList.errorPublish")) : alert(M("toursList.errorPublish"));
|
|
46
47
|
}
|
|
47
|
-
},
|
|
48
|
-
|
|
48
|
+
}, he = async (e) => {
|
|
49
|
+
u("light");
|
|
49
50
|
try {
|
|
50
|
-
await
|
|
51
|
+
await re(e), d("success");
|
|
51
52
|
} catch {
|
|
52
|
-
|
|
53
|
+
d("error"), c() ? f(M("toursList.errorUnpublish")) : alert(M("toursList.errorUnpublish"));
|
|
53
54
|
}
|
|
54
55
|
}, ge = async (e) => {
|
|
55
|
-
|
|
56
|
+
u("light");
|
|
56
57
|
try {
|
|
57
|
-
await
|
|
58
|
+
await ie(e), d("success");
|
|
58
59
|
} catch {
|
|
59
|
-
|
|
60
|
+
d("error"), c() ? f(M("toursList.errorArchive")) : alert(M("toursList.errorArchive"));
|
|
60
61
|
}
|
|
61
62
|
}, _e = async (e) => {
|
|
62
|
-
|
|
63
|
+
u("light");
|
|
63
64
|
try {
|
|
64
|
-
await
|
|
65
|
+
await ae(e), d("success");
|
|
65
66
|
} catch {
|
|
66
|
-
|
|
67
|
+
d("error"), c() ? f(M("toursList.errorDuplicate")) : alert(M("toursList.errorDuplicate"));
|
|
67
68
|
}
|
|
68
69
|
}, ve = async (e) => {
|
|
69
|
-
|
|
70
|
-
let t =
|
|
71
|
-
title:
|
|
70
|
+
u("medium");
|
|
71
|
+
let t = M("toursList.confirmDelete"), n = await l({
|
|
72
|
+
title: M("toursList.actionDelete"),
|
|
72
73
|
message: t,
|
|
73
|
-
okButtonTitle:
|
|
74
|
+
okButtonTitle: M("toursList.actionDelete")
|
|
74
75
|
});
|
|
75
76
|
if (n === null ? window.confirm(t) : n) try {
|
|
76
|
-
await
|
|
77
|
+
await oe({ variables: { id: e } }), B(), d("success");
|
|
77
78
|
} catch {
|
|
78
|
-
|
|
79
|
+
d("error"), c() ? f(M("toursList.errorDelete")) : alert(M("toursList.errorDelete"));
|
|
79
80
|
}
|
|
80
81
|
};
|
|
81
|
-
return /* @__PURE__ */
|
|
82
|
+
return /* @__PURE__ */ T("div", {
|
|
82
83
|
className: "space-y-4 sm:space-y-6 p-3 sm:p-6",
|
|
83
84
|
children: [
|
|
84
|
-
/* @__PURE__ */
|
|
85
|
+
/* @__PURE__ */ T("div", {
|
|
85
86
|
className: "relative overflow-hidden rounded-xl",
|
|
86
|
-
children: [/* @__PURE__ */
|
|
87
|
+
children: [/* @__PURE__ */ w(D, { intensity: "subtle" }), /* @__PURE__ */ T("div", {
|
|
87
88
|
className: "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 p-1 sm:p-2",
|
|
88
|
-
children: [/* @__PURE__ */
|
|
89
|
+
children: [/* @__PURE__ */ T("div", {
|
|
89
90
|
className: "flex-1 min-w-0",
|
|
90
|
-
children: [/* @__PURE__ */
|
|
91
|
+
children: [/* @__PURE__ */ w("h1", {
|
|
91
92
|
className: "text-xl sm:text-2xl font-bold text-text-primary",
|
|
92
|
-
children: /* @__PURE__ */
|
|
93
|
-
}), /* @__PURE__ */
|
|
93
|
+
children: /* @__PURE__ */ w(te, { children: M("toursList.title") })
|
|
94
|
+
}), /* @__PURE__ */ w("p", {
|
|
94
95
|
className: "text-sm sm:text-base text-text-secondary",
|
|
95
|
-
children:
|
|
96
|
+
children: M("toursList.subtitle")
|
|
96
97
|
})]
|
|
97
|
-
}), /* @__PURE__ */
|
|
98
|
-
permission:
|
|
99
|
-
children: /* @__PURE__ */
|
|
98
|
+
}), /* @__PURE__ */ w(g, {
|
|
99
|
+
permission: o.TOUR_CREATE,
|
|
100
|
+
children: /* @__PURE__ */ T(O, {
|
|
100
101
|
type: "button",
|
|
101
|
-
onClick:
|
|
102
|
+
onClick: $,
|
|
102
103
|
className: "w-full sm:w-auto min-h-[44px]",
|
|
103
|
-
children: [/* @__PURE__ */
|
|
104
|
+
children: [/* @__PURE__ */ w(x, { size: 20 }), M("toursList.createTour")]
|
|
104
105
|
})
|
|
105
106
|
})]
|
|
106
107
|
})]
|
|
107
108
|
}),
|
|
108
|
-
/* @__PURE__ */
|
|
109
|
-
/* @__PURE__ */
|
|
109
|
+
/* @__PURE__ */ w(j, { children: M("toursList.purpose") }),
|
|
110
|
+
/* @__PURE__ */ T("div", {
|
|
110
111
|
className: "flex flex-col sm:flex-row gap-3 sm:gap-4",
|
|
111
|
-
children: [/* @__PURE__ */
|
|
112
|
+
children: [/* @__PURE__ */ T("div", {
|
|
112
113
|
className: "flex-1 relative",
|
|
113
|
-
children: [/* @__PURE__ */
|
|
114
|
+
children: [/* @__PURE__ */ w(S, {
|
|
114
115
|
className: "absolute left-3 top-1/2 -translate-y-1/2 text-text-secondary",
|
|
115
116
|
size: 20
|
|
116
|
-
}), /* @__PURE__ */
|
|
117
|
+
}), /* @__PURE__ */ w("input", {
|
|
117
118
|
type: "text",
|
|
118
|
-
placeholder:
|
|
119
|
-
value:
|
|
120
|
-
onChange: (e) =>
|
|
119
|
+
placeholder: M("toursList.searchPlaceholder"),
|
|
120
|
+
value: se,
|
|
121
|
+
onChange: (e) => de(e.target.value),
|
|
121
122
|
className: "w-full pl-[3.25rem] pr-4 py-2 min-h-[44px] border border-border-subtle rounded-md bg-bg-surface text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
|
|
122
|
-
"aria-label":
|
|
123
|
+
"aria-label": M("toursList.searchPlaceholder")
|
|
123
124
|
})]
|
|
124
|
-
}), /* @__PURE__ */
|
|
125
|
+
}), /* @__PURE__ */ T("div", {
|
|
125
126
|
className: "flex gap-2",
|
|
126
|
-
children: [/* @__PURE__ */
|
|
127
|
-
value:
|
|
128
|
-
onChange: (e) =>
|
|
127
|
+
children: [/* @__PURE__ */ T("select", {
|
|
128
|
+
value: le,
|
|
129
|
+
onChange: (e) => fe(e.target.value),
|
|
129
130
|
className: "px-4 py-2 min-h-[44px] border border-border-subtle rounded-md bg-bg-surface text-text-primary scheme-normal dark:scheme-dark [&_option]:bg-bg-surface [&_option]:text-text-primary",
|
|
130
|
-
"aria-label":
|
|
131
|
+
"aria-label": M("toursList.statusAll"),
|
|
131
132
|
children: [
|
|
132
|
-
/* @__PURE__ */
|
|
133
|
+
/* @__PURE__ */ w("option", {
|
|
133
134
|
value: "all",
|
|
134
|
-
children:
|
|
135
|
+
children: M("toursList.statusAll")
|
|
135
136
|
}),
|
|
136
|
-
/* @__PURE__ */
|
|
137
|
+
/* @__PURE__ */ w("option", {
|
|
137
138
|
value: "DRAFT",
|
|
138
|
-
children:
|
|
139
|
+
children: M("toursList.statusDraft")
|
|
139
140
|
}),
|
|
140
|
-
/* @__PURE__ */
|
|
141
|
+
/* @__PURE__ */ w("option", {
|
|
141
142
|
value: "PUBLISHED",
|
|
142
|
-
children:
|
|
143
|
+
children: M("toursList.statusPublished")
|
|
143
144
|
}),
|
|
144
|
-
/* @__PURE__ */
|
|
145
|
+
/* @__PURE__ */ w("option", {
|
|
145
146
|
value: "ARCHIVED",
|
|
146
|
-
children:
|
|
147
|
+
children: M("toursList.statusArchived")
|
|
147
148
|
}),
|
|
148
|
-
/* @__PURE__ */
|
|
149
|
+
/* @__PURE__ */ w("option", {
|
|
149
150
|
value: "SCHEDULED",
|
|
150
|
-
children:
|
|
151
|
+
children: M("toursList.statusScheduled")
|
|
151
152
|
})
|
|
152
153
|
]
|
|
153
|
-
}), /* @__PURE__ */
|
|
154
|
+
}), /* @__PURE__ */ T("div", {
|
|
154
155
|
className: "flex border border-border-subtle rounded-md overflow-hidden",
|
|
155
|
-
children: [/* @__PURE__ */
|
|
156
|
+
children: [/* @__PURE__ */ w("button", {
|
|
156
157
|
type: "button",
|
|
157
|
-
onClick: () =>
|
|
158
|
-
className: `px-3 py-2 min-h-[44px] ${
|
|
159
|
-
"aria-label":
|
|
160
|
-
title:
|
|
161
|
-
children: /* @__PURE__ */
|
|
162
|
-
}), /* @__PURE__ */
|
|
158
|
+
onClick: () => R("grid"),
|
|
159
|
+
className: `px-3 py-2 min-h-[44px] ${F === "grid" ? "bg-action-primary-bg text-action-primary-text" : "bg-bg-surface text-text-primary hover:bg-accent"}`,
|
|
160
|
+
"aria-label": M("toursList.gridView"),
|
|
161
|
+
title: M("toursList.gridView"),
|
|
162
|
+
children: /* @__PURE__ */ w(v, { size: 20 })
|
|
163
|
+
}), /* @__PURE__ */ w("button", {
|
|
163
164
|
type: "button",
|
|
164
|
-
onClick: () =>
|
|
165
|
-
className: `px-3 py-2 min-h-[44px] ${
|
|
166
|
-
"aria-label":
|
|
167
|
-
title:
|
|
168
|
-
children: /* @__PURE__ */
|
|
165
|
+
onClick: () => R("list"),
|
|
166
|
+
className: `px-3 py-2 min-h-[44px] ${F === "list" ? "bg-action-primary-bg text-action-primary-text" : "bg-bg-surface text-text-primary hover:bg-accent"}`,
|
|
167
|
+
"aria-label": M("toursList.listView"),
|
|
168
|
+
title: M("toursList.listView"),
|
|
169
|
+
children: /* @__PURE__ */ w(y, { size: 20 })
|
|
169
170
|
})]
|
|
170
171
|
})]
|
|
171
172
|
})]
|
|
172
173
|
}),
|
|
173
|
-
|
|
174
|
+
Z ? /* @__PURE__ */ w("div", {
|
|
174
175
|
className: "text-center py-12",
|
|
175
|
-
children: /* @__PURE__ */
|
|
176
|
+
children: /* @__PURE__ */ w("p", {
|
|
176
177
|
className: "text-sm sm:text-base text-text-secondary",
|
|
177
|
-
children:
|
|
178
|
+
children: M("toursList.loading")
|
|
178
179
|
})
|
|
179
|
-
}) :
|
|
180
|
-
className:
|
|
181
|
-
children:
|
|
182
|
-
let t = e.status, n = t === "DRAFT" &&
|
|
180
|
+
}) : X.length > 0 ? /* @__PURE__ */ w("div", {
|
|
181
|
+
className: F === "grid" ? "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 sm:gap-4" : "space-y-3",
|
|
182
|
+
children: X.map((e) => {
|
|
183
|
+
let t = e.status, n = t === "DRAFT" && q, r = t === "PUBLISHED" && q, i = t !== "ARCHIVED" && J, a = [];
|
|
183
184
|
return n && a.push({
|
|
184
|
-
label:
|
|
185
|
-
onSelect: () => void
|
|
185
|
+
label: M("toursList.actionPublish"),
|
|
186
|
+
onSelect: () => void me(e.id)
|
|
186
187
|
}), r && a.push({
|
|
187
|
-
label:
|
|
188
|
-
onSelect: () => void
|
|
189
|
-
}),
|
|
190
|
-
label:
|
|
188
|
+
label: M("toursList.actionUnpublish"),
|
|
189
|
+
onSelect: () => void he(e.id)
|
|
190
|
+
}), Y && a.push({
|
|
191
|
+
label: M("toursList.actionDuplicate"),
|
|
191
192
|
onSelect: () => void _e(e.id)
|
|
192
193
|
}), i && a.push({
|
|
193
|
-
label:
|
|
194
|
+
label: M("toursList.actionArchive"),
|
|
194
195
|
onSelect: () => void ge(e.id)
|
|
195
|
-
}),
|
|
196
|
-
label:
|
|
196
|
+
}), K && a.push({
|
|
197
|
+
label: M("toursList.actionDelete"),
|
|
197
198
|
onSelect: () => void ve(e.id),
|
|
198
199
|
intent: "destructive"
|
|
199
|
-
}), /* @__PURE__ */
|
|
200
|
+
}), /* @__PURE__ */ T(k, {
|
|
200
201
|
treatment: "plain",
|
|
201
202
|
className: "p-4 border-border-seam shadow-[var(--shadow-pop)]",
|
|
202
203
|
children: [
|
|
203
|
-
/* @__PURE__ */
|
|
204
|
+
/* @__PURE__ */ T("div", {
|
|
204
205
|
className: "flex items-start justify-between mb-2",
|
|
205
|
-
children: [/* @__PURE__ */
|
|
206
|
+
children: [/* @__PURE__ */ w("h3", {
|
|
206
207
|
className: "font-semibold text-text-primary",
|
|
207
|
-
children:
|
|
208
|
+
children: U ? /* @__PURE__ */ w("button", {
|
|
208
209
|
type: "button",
|
|
209
210
|
className: "cursor-pointer hover:text-primary bg-transparent border-0 p-0 text-left font-inherit",
|
|
210
|
-
onClick: () =>
|
|
211
|
+
onClick: () => N(`${P}/${e.id}/edit`),
|
|
211
212
|
children: e.name
|
|
212
213
|
}) : e.name
|
|
213
|
-
}), /* @__PURE__ */
|
|
214
|
+
}), /* @__PURE__ */ w("span", {
|
|
214
215
|
className: `px-2 py-1 text-xs rounded-full ${e.status === "PUBLISHED" ? "bg-success/10 text-success motion-safe:animate-vc-glow-pulse" : e.status === "DRAFT" ? "bg-bg-sunken text-text-secondary" : "bg-warning/10 text-warning"}`,
|
|
215
|
-
children:
|
|
216
|
+
children: pe(t)
|
|
216
217
|
})]
|
|
217
218
|
}),
|
|
218
|
-
e.description && /* @__PURE__ */
|
|
219
|
+
e.description && /* @__PURE__ */ w(h, {
|
|
219
220
|
inline: !0,
|
|
220
221
|
className: "text-sm text-text-secondary mb-3",
|
|
221
222
|
children: e.description
|
|
222
223
|
}),
|
|
223
|
-
/* @__PURE__ */
|
|
224
|
+
/* @__PURE__ */ T("div", {
|
|
224
225
|
className: "flex items-center justify-between text-xs text-text-secondary mb-3",
|
|
225
|
-
children: [/* @__PURE__ */
|
|
226
|
+
children: [/* @__PURE__ */ T("span", { children: [
|
|
226
227
|
e.steps?.length || 0,
|
|
227
228
|
" ",
|
|
228
|
-
|
|
229
|
-
] }), /* @__PURE__ */
|
|
229
|
+
M("toursList.steps")
|
|
230
|
+
] }), /* @__PURE__ */ T("span", { children: [
|
|
230
231
|
e.viewCount,
|
|
231
232
|
" ",
|
|
232
|
-
|
|
233
|
+
M("toursList.views")
|
|
233
234
|
] })]
|
|
234
235
|
}),
|
|
235
|
-
/* @__PURE__ */
|
|
236
|
+
/* @__PURE__ */ T("div", {
|
|
236
237
|
className: "flex flex-wrap items-center gap-2 pt-3 border-t border-border-seam",
|
|
237
238
|
children: [
|
|
238
|
-
|
|
239
|
+
W && /* @__PURE__ */ T("button", {
|
|
239
240
|
type: "button",
|
|
240
241
|
onClick: (t) => {
|
|
241
|
-
t.stopPropagation(),
|
|
242
|
+
t.stopPropagation(), N(`${P}/${e.id}/steps`);
|
|
242
243
|
},
|
|
243
244
|
className: "flex-1 min-w-[6.5rem] px-3 py-2 min-h-[44px] text-xs bg-secondary text-secondary-foreground rounded hover:bg-secondary/80 flex items-center justify-center gap-1.5",
|
|
244
|
-
title:
|
|
245
|
-
children: [/* @__PURE__ */
|
|
245
|
+
title: M("toursList.editStepsTitle"),
|
|
246
|
+
children: [/* @__PURE__ */ w(b, { size: 14 }), M("toursList.stepsButton")]
|
|
246
247
|
}),
|
|
247
|
-
|
|
248
|
+
G && /* @__PURE__ */ T("button", {
|
|
248
249
|
type: "button",
|
|
249
250
|
onClick: (t) => {
|
|
250
|
-
t.stopPropagation(),
|
|
251
|
+
t.stopPropagation(), N(`${P}/${e.id}/preview`);
|
|
251
252
|
},
|
|
252
253
|
className: "flex-1 min-w-[6.5rem] px-3 py-2 min-h-[44px] text-xs border border-border-seam rounded hover:bg-accent flex items-center justify-center gap-1.5",
|
|
253
|
-
title:
|
|
254
|
-
children: [/* @__PURE__ */
|
|
254
|
+
title: M("toursList.previewTitle"),
|
|
255
|
+
children: [/* @__PURE__ */ w(_, { size: 14 }), M("toursList.previewButton")]
|
|
255
256
|
}),
|
|
256
|
-
|
|
257
|
+
U && /* @__PURE__ */ w("button", {
|
|
257
258
|
type: "button",
|
|
258
259
|
onClick: (t) => {
|
|
259
|
-
t.stopPropagation(),
|
|
260
|
+
t.stopPropagation(), N(`${P}/${e.id}/edit`);
|
|
260
261
|
},
|
|
261
262
|
className: "p-2 min-h-[44px] min-w-[44px] text-xs border border-border-seam rounded hover:bg-accent",
|
|
262
|
-
title:
|
|
263
|
-
"aria-label":
|
|
264
|
-
children: /* @__PURE__ */ C
|
|
263
|
+
title: M("toursList.settingsTitle"),
|
|
264
|
+
"aria-label": M("toursList.settingsTitle"),
|
|
265
|
+
children: /* @__PURE__ */ w(C, { size: 14 })
|
|
265
266
|
}),
|
|
266
|
-
a.length > 0 && /* @__PURE__ */
|
|
267
|
+
a.length > 0 && /* @__PURE__ */ w(ee, { actions: a })
|
|
267
268
|
]
|
|
268
269
|
})
|
|
269
270
|
]
|
|
270
271
|
}, e.id);
|
|
271
272
|
})
|
|
272
|
-
}) : /* @__PURE__ */
|
|
273
|
+
}) : /* @__PURE__ */ w(A, {
|
|
273
274
|
illustration: "onboarding",
|
|
274
|
-
title:
|
|
275
|
-
description:
|
|
276
|
-
action: /* @__PURE__ */
|
|
277
|
-
permission:
|
|
278
|
-
children: /* @__PURE__ */
|
|
275
|
+
title: M("toursList.emptyTitle"),
|
|
276
|
+
description: M("toursList.emptySubtitle"),
|
|
277
|
+
action: /* @__PURE__ */ w(g, {
|
|
278
|
+
permission: o.TOUR_CREATE,
|
|
279
|
+
children: /* @__PURE__ */ T(O, {
|
|
279
280
|
type: "button",
|
|
280
|
-
onClick:
|
|
281
|
+
onClick: $,
|
|
281
282
|
className: "min-h-[44px]",
|
|
282
|
-
children: [/* @__PURE__ */
|
|
283
|
+
children: [/* @__PURE__ */ w(x, { size: 20 }), M("toursList.createTour")]
|
|
283
284
|
})
|
|
284
285
|
})
|
|
285
286
|
})
|
|
286
287
|
]
|
|
287
288
|
});
|
|
288
289
|
}
|
|
289
|
-
|
|
290
|
-
export { j as ToursListPage };
|
|
290
|
+
export { M as ToursListPage };
|
|
291
291
|
|
|
292
292
|
//# sourceMappingURL=ToursListPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToursListPage.js","names":[],"sources":["../../../src/tours/pages/ToursListPage.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { useNavigate } from 'react-router';\nimport { Plus, Search, Grid, List as ListIcon, ListOrdered, Eye, Settings } from 'lucide-react';\nimport { Markdown, PermissionGate } from '@burdenoff/fe-libs/shared/components';\nimport {\n AuroraBackground,\n Button,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n PagePurpose,\n CTAOverflowMenu,\n type CTAAction,\n} from '@burdenoff/fe-libs/ui';\nimport { useToursList } from '../hooks/useToursList';\nimport { useTourLifecycle } from '../hooks/useTourLifecycle';\nimport { useToursPermissionAccess } from '../hooks/useToursPermissionAccess';\nimport { useToursStore } from '../store/toursStore';\nimport { useToursContext } from '../providers/ToursProvider';\nimport { useDeleteTourMutation } from '../../generated/global-operations';\nimport { TOUR_PERMISSIONS } from '../../constants/permissions';\nimport type { TourStatus } from '../types';\nimport type { Tour } from '../../generated/global-types';\nimport { useToursI18n } from '../i18n';\nimport {\n isNative,\n nativeConfirm,\n nativeImpact,\n nativeNotify,\n nativeToast,\n} from '../../utils/nativeBridge';\n\n/**\n * Tours list page\n * Displays all tours with filtering and search\n */\nexport function ToursListPage() {\n const { tr } = useToursI18n();\n const navigate = useNavigate();\n const { basePath = '/' } = useToursContext();\n const {\n viewMode,\n tourFilter,\n toursListRevision,\n setViewMode,\n updateTourFilter,\n notifyToursListChanged,\n } = useToursStore();\n const { hasPermission, isLoading: permissionsLoading } = useToursPermissionAccess();\n\n const canUpdateTour = hasPermission(TOUR_PERMISSIONS.TOUR_UPDATE);\n const canUpdateTourSteps = hasPermission(TOUR_PERMISSIONS.TOUR_STEP_UPDATE);\n const canPreviewTour = hasPermission(TOUR_PERMISSIONS.TOUR_READ);\n const canDeleteTour = hasPermission(TOUR_PERMISSIONS.TOUR_DELETE);\n const canPublishTour = hasPermission(TOUR_PERMISSIONS.TOUR_PUBLISH);\n const canArchiveTour = hasPermission(TOUR_PERMISSIONS.TOUR_ARCHIVE);\n const canDuplicateTour = hasPermission(TOUR_PERMISSIONS.TOUR_DUPLICATE);\n\n // Fetch tours (includes both workspace-specific and global tours)\n const { tours, loading, fetchTours } = useToursList();\n\n const { publishTour, unpublishTour, archiveTour, duplicateTour } = useTourLifecycle();\n const [deleteTourMutation] = useDeleteTourMutation();\n\n const [searchQuery, setSearchQuery] = useState('');\n const [statusFilter, setStatusFilter] = useState<TourStatus | 'all'>('all');\n\n // Fetch tours when filter changes. The list page is also the user-facing\n // tour browser, so backend permissions remain authoritative for actions while\n // normal users can still see published tours returned by the API.\n useEffect(() => {\n if (permissionsLoading) return;\n fetchTours({ ...tourFilter });\n }, [fetchTours, tourFilter, toursListRevision, permissionsLoading]);\n\n const handleSearch = (query: string) => {\n setSearchQuery(query);\n updateTourFilter({ search: query });\n };\n\n const handleStatusFilter = (status: TourStatus | 'all') => {\n setStatusFilter(status);\n updateTourFilter({ status });\n };\n\n const handleCreateTour = () => {\n const newPath = basePath.endsWith('/') ? `${basePath}new` : `${basePath}/new`;\n navigate(newPath);\n };\n\n const getStatusLabel = (status: TourStatus) => {\n switch (status) {\n case 'DRAFT':\n return tr('toursList.statusDraft');\n case 'PUBLISHED':\n return tr('toursList.statusPublished');\n case 'ARCHIVED':\n return tr('toursList.statusArchived');\n case 'SCHEDULED':\n return tr('toursList.statusScheduled');\n }\n };\n\n const handlePublish = async (id: string) => {\n nativeImpact('light');\n try {\n await publishTour(id);\n void nativeNotify('success');\n } catch {\n void nativeNotify('error');\n if (isNative()) void nativeToast(tr('toursList.errorPublish'));\n else alert(tr('toursList.errorPublish'));\n }\n };\n\n const handleUnpublish = async (id: string) => {\n nativeImpact('light');\n try {\n await unpublishTour(id);\n void nativeNotify('success');\n } catch {\n void nativeNotify('error');\n if (isNative()) void nativeToast(tr('toursList.errorUnpublish'));\n else alert(tr('toursList.errorUnpublish'));\n }\n };\n\n const handleArchive = async (id: string) => {\n nativeImpact('light');\n try {\n await archiveTour(id);\n void nativeNotify('success');\n } catch {\n void nativeNotify('error');\n if (isNative()) void nativeToast(tr('toursList.errorArchive'));\n else alert(tr('toursList.errorArchive'));\n }\n };\n\n const handleDuplicate = async (id: string) => {\n nativeImpact('light');\n try {\n await duplicateTour(id);\n void nativeNotify('success');\n } catch {\n void nativeNotify('error');\n if (isNative()) void nativeToast(tr('toursList.errorDuplicate'));\n else alert(tr('toursList.errorDuplicate'));\n }\n };\n\n const handleDelete = async (id: string) => {\n nativeImpact('medium');\n const confirmMsg = tr('toursList.confirmDelete');\n const nativeResult = await nativeConfirm({\n title: tr('toursList.actionDelete'),\n message: confirmMsg,\n okButtonTitle: tr('toursList.actionDelete'),\n });\n const confirmed = nativeResult === null ? window.confirm(confirmMsg) : nativeResult;\n if (!confirmed) return;\n try {\n await deleteTourMutation({ variables: { id } });\n notifyToursListChanged();\n void nativeNotify('success');\n } catch {\n void nativeNotify('error');\n if (isNative()) void nativeToast(tr('toursList.errorDelete'));\n else alert(tr('toursList.errorDelete'));\n }\n };\n\n return (\n <div className=\"space-y-4 sm:space-y-6 p-3 sm:p-6\">\n {/* Header */}\n <div className=\"relative overflow-hidden rounded-xl\">\n <AuroraBackground intensity=\"subtle\" />\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 p-1 sm:p-2\">\n <div className=\"flex-1 min-w-0\">\n <h1 className=\"text-xl sm:text-2xl font-bold text-text-primary\">\n <GradientText>{tr('toursList.title')}</GradientText>\n </h1>\n <p className=\"text-sm sm:text-base text-text-secondary\">{tr('toursList.subtitle')}</p>\n </div>\n <PermissionGate permission={TOUR_PERMISSIONS.TOUR_CREATE}>\n <Button\n type=\"button\"\n onClick={handleCreateTour}\n className=\"w-full sm:w-auto min-h-[44px]\"\n >\n <Plus size={20} />\n {tr('toursList.createTour')}\n </Button>\n </PermissionGate>\n </div>\n </div>\n\n <PagePurpose>{tr('toursList.purpose')}</PagePurpose>\n\n {/* Filters and Search */}\n <div className=\"flex flex-col sm:flex-row gap-3 sm:gap-4\">\n {/* Search */}\n <div className=\"flex-1 relative\">\n <Search\n className=\"absolute left-3 top-1/2 -translate-y-1/2 text-text-secondary\"\n size={20}\n />\n <input\n type=\"text\"\n placeholder={tr('toursList.searchPlaceholder')}\n value={searchQuery}\n onChange={(e) => handleSearch(e.target.value)}\n className=\"w-full pl-[3.25rem] pr-4 py-2 min-h-[44px] border border-border-subtle rounded-md bg-bg-surface text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n aria-label={tr('toursList.searchPlaceholder')}\n />\n </div>\n\n {/* Status Filter */}\n <div className=\"flex gap-2\">\n <select\n value={statusFilter}\n onChange={(e) => handleStatusFilter(e.target.value as TourStatus | 'all')}\n className=\"px-4 py-2 min-h-[44px] border border-border-subtle rounded-md bg-bg-surface text-text-primary scheme-normal dark:scheme-dark [&_option]:bg-bg-surface [&_option]:text-text-primary\"\n aria-label={tr('toursList.statusAll')}\n >\n <option value=\"all\">{tr('toursList.statusAll')}</option>\n <option value=\"DRAFT\">{tr('toursList.statusDraft')}</option>\n <option value=\"PUBLISHED\">{tr('toursList.statusPublished')}</option>\n <option value=\"ARCHIVED\">{tr('toursList.statusArchived')}</option>\n <option value=\"SCHEDULED\">{tr('toursList.statusScheduled')}</option>\n </select>\n\n {/* View Mode Toggle */}\n <div className=\"flex border border-border-subtle rounded-md overflow-hidden\">\n <button\n type=\"button\"\n onClick={() => setViewMode('grid')}\n className={`px-3 py-2 min-h-[44px] ${\n viewMode === 'grid'\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-surface text-text-primary hover:bg-accent'\n }`}\n aria-label={tr('toursList.gridView')}\n title={tr('toursList.gridView')}\n >\n <Grid size={20} />\n </button>\n <button\n type=\"button\"\n onClick={() => setViewMode('list')}\n className={`px-3 py-2 min-h-[44px] ${\n viewMode === 'list'\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-surface text-text-primary hover:bg-accent'\n }`}\n aria-label={tr('toursList.listView')}\n title={tr('toursList.listView')}\n >\n <ListIcon size={20} />\n </button>\n </div>\n </div>\n </div>\n\n {/* Tours List */}\n {loading ? (\n <div className=\"text-center py-12\">\n <p className=\"text-sm sm:text-base text-text-secondary\">{tr('toursList.loading')}</p>\n </div>\n ) : tours.length > 0 ? (\n <div\n className={\n viewMode === 'grid'\n ? 'grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 sm:gap-4'\n : 'space-y-3'\n }\n >\n {tours.map((tour: Tour) => {\n const status = tour.status as TourStatus;\n const canShowPublishAction = status === 'DRAFT' && canPublishTour;\n const canShowUnpublishAction = status === 'PUBLISHED' && canPublishTour;\n const canShowArchiveAction = status !== 'ARCHIVED' && canArchiveTour;\n\n const overflowActions: CTAAction[] = [];\n if (canShowPublishAction) {\n overflowActions.push({\n label: tr('toursList.actionPublish'),\n onSelect: () => void handlePublish(tour.id),\n });\n }\n if (canShowUnpublishAction) {\n overflowActions.push({\n label: tr('toursList.actionUnpublish'),\n onSelect: () => void handleUnpublish(tour.id),\n });\n }\n if (canDuplicateTour) {\n overflowActions.push({\n label: tr('toursList.actionDuplicate'),\n onSelect: () => void handleDuplicate(tour.id),\n });\n }\n if (canShowArchiveAction) {\n overflowActions.push({\n label: tr('toursList.actionArchive'),\n onSelect: () => void handleArchive(tour.id),\n });\n }\n if (canDeleteTour) {\n overflowActions.push({\n label: tr('toursList.actionDelete'),\n onSelect: () => void handleDelete(tour.id),\n intent: 'destructive',\n });\n }\n\n return (\n <GlassCard\n key={tour.id}\n treatment=\"plain\"\n className=\"p-4 border-border-seam shadow-[var(--shadow-pop)]\"\n >\n <div className=\"flex items-start justify-between mb-2\">\n <h3 className=\"font-semibold text-text-primary\">\n {canUpdateTour ? (\n <button\n type=\"button\"\n className=\"cursor-pointer hover:text-primary bg-transparent border-0 p-0 text-left font-inherit\"\n onClick={() => navigate(`${basePath}/${tour.id}/edit`)}\n >\n {tour.name}\n </button>\n ) : (\n tour.name\n )}\n </h3>\n <span\n className={`px-2 py-1 text-xs rounded-full ${\n tour.status === 'PUBLISHED'\n ? 'bg-success/10 text-success motion-safe:animate-vc-glow-pulse'\n : tour.status === 'DRAFT'\n ? 'bg-bg-sunken text-text-secondary'\n : 'bg-warning/10 text-warning'\n }`}\n >\n {getStatusLabel(status)}\n </span>\n </div>\n {tour.description && (\n <Markdown inline className=\"text-sm text-text-secondary mb-3\">\n {tour.description}\n </Markdown>\n )}\n <div className=\"flex items-center justify-between text-xs text-text-secondary mb-3\">\n <span>\n {tour.steps?.length || 0} {tr('toursList.steps')}\n </span>\n <span>\n {tour.viewCount} {tr('toursList.views')}\n </span>\n </div>\n {/* Quick Actions */}\n <div className=\"flex flex-wrap items-center gap-2 pt-3 border-t border-border-seam\">\n {canUpdateTourSteps && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n navigate(`${basePath}/${tour.id}/steps`);\n }}\n className=\"flex-1 min-w-[6.5rem] px-3 py-2 min-h-[44px] text-xs bg-secondary text-secondary-foreground rounded hover:bg-secondary/80 flex items-center justify-center gap-1.5\"\n title={tr('toursList.editStepsTitle')}\n >\n <ListOrdered size={14} />\n {tr('toursList.stepsButton')}\n </button>\n )}\n {canPreviewTour && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n navigate(`${basePath}/${tour.id}/preview`);\n }}\n className=\"flex-1 min-w-[6.5rem] px-3 py-2 min-h-[44px] text-xs border border-border-seam rounded hover:bg-accent flex items-center justify-center gap-1.5\"\n title={tr('toursList.previewTitle')}\n >\n <Eye size={14} />\n {tr('toursList.previewButton')}\n </button>\n )}\n {canUpdateTour && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n navigate(`${basePath}/${tour.id}/edit`);\n }}\n className=\"p-2 min-h-[44px] min-w-[44px] text-xs border border-border-seam rounded hover:bg-accent\"\n title={tr('toursList.settingsTitle')}\n aria-label={tr('toursList.settingsTitle')}\n >\n <Settings size={14} />\n </button>\n )}\n {/* Lifecycle actions collapsed into the overflow menu */}\n {overflowActions.length > 0 && <CTAOverflowMenu actions={overflowActions} />}\n </div>\n </GlassCard>\n );\n })}\n </div>\n ) : (\n <IllustratedEmptyState\n illustration=\"onboarding\"\n title={tr('toursList.emptyTitle')}\n description={tr('toursList.emptySubtitle')}\n action={\n <PermissionGate permission={TOUR_PERMISSIONS.TOUR_CREATE}>\n <Button type=\"button\" onClick={handleCreateTour} className=\"min-h-[44px]\">\n <Plus size={20} />\n {tr('toursList.createTour')}\n </Button>\n </PermissionGate>\n }\n />\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAoCA,SAAgB,IAAgB;CAC9B,IAAM,EAAE,UAAO,GAAc,EACvB,IAAW,GAAa,EACxB,EAAE,cAAW,QAAQ,GAAiB,EACtC,EACJ,aACA,eACA,sBACA,gBACA,qBACA,8BACE,GAAe,EACb,EAAE,kBAAe,WAAW,MAAuB,GAA0B,EAE7E,IAAgB,EAAc,EAAiB,YAAY,EAC3D,IAAqB,EAAc,EAAiB,iBAAiB,EACrE,IAAiB,EAAc,EAAiB,UAAU,EAC1D,IAAgB,EAAc,EAAiB,YAAY,EAC3D,IAAiB,EAAc,EAAiB,aAAa,EAC7D,IAAiB,EAAc,EAAiB,aAAa,EAC7D,IAAmB,EAAc,EAAiB,eAAe,EAGjE,EAAE,UAAO,YAAS,kBAAe,GAAc,EAE/C,EAAE,iBAAa,mBAAe,iBAAa,sBAAkB,GAAkB,EAC/E,CAAC,MAAsB,GAAuB,EAE9C,CAAC,IAAa,MAAkB,EAAS,GAAG,EAC5C,CAAC,IAAc,MAAmB,EAA6B,MAAM;AAK3E,SAAgB;AACV,OACJ,EAAW,EAAE,GAAG,GAAY,CAAC;IAC5B;EAAC;EAAY;EAAY;EAAmB;EAAmB,CAAC;CAEnE,IAAM,MAAgB,MAAkB;AAEtC,EADA,GAAe,EAAM,EACrB,EAAiB,EAAE,QAAQ,GAAO,CAAC;IAG/B,MAAsB,MAA+B;AAEzD,EADA,GAAgB,EAAO,EACvB,EAAiB,EAAE,WAAQ,CAAC;IAGxB,UAAyB;AAE7B,IADgB,EAAS,SAAS,IAAI,GAAG,GAAG,EAAS,OAAO,GAAG,EAAS,MACvD;IAGb,MAAkB,MAAuB;AAC7C,UAAQ,GAAR;GACE,KAAK,QACH,QAAO,EAAG,wBAAwB;GACpC,KAAK,YACH,QAAO,EAAG,4BAA4B;GACxC,KAAK,WACH,QAAO,EAAG,2BAA2B;GACvC,KAAK,YACH,QAAO,EAAG,4BAA4B;;IAItC,KAAgB,OAAO,MAAe;AAC1C,IAAa,QAAQ;AACrB,MAAI;AAEG,GADL,MAAM,GAAY,EAAG,EAChB,EAAa,UAAU;UACtB;AAEN,GADK,EAAa,QAAQ,EACtB,GAAU,GAAO,EAAY,EAAG,yBAAyB,CAAC,GACzD,MAAM,EAAG,yBAAyB,CAAC;;IAItC,IAAkB,OAAO,MAAe;AAC5C,IAAa,QAAQ;AACrB,MAAI;AAEG,GADL,MAAM,GAAc,EAAG,EAClB,EAAa,UAAU;UACtB;AAEN,GADK,EAAa,QAAQ,EACtB,GAAU,GAAO,EAAY,EAAG,2BAA2B,CAAC,GAC3D,MAAM,EAAG,2BAA2B,CAAC;;IAIxC,KAAgB,OAAO,MAAe;AAC1C,IAAa,QAAQ;AACrB,MAAI;AAEG,GADL,MAAM,GAAY,EAAG,EAChB,EAAa,UAAU;UACtB;AAEN,GADK,EAAa,QAAQ,EACtB,GAAU,GAAO,EAAY,EAAG,yBAAyB,CAAC,GACzD,MAAM,EAAG,yBAAyB,CAAC;;IAItC,KAAkB,OAAO,MAAe;AAC5C,IAAa,QAAQ;AACrB,MAAI;AAEG,GADL,MAAM,GAAc,EAAG,EAClB,EAAa,UAAU;UACtB;AAEN,GADK,EAAa,QAAQ,EACtB,GAAU,GAAO,EAAY,EAAG,2BAA2B,CAAC,GAC3D,MAAM,EAAG,2BAA2B,CAAC;;IAIxC,KAAe,OAAO,MAAe;AACzC,IAAa,SAAS;EACtB,IAAM,IAAa,EAAG,0BAA0B,EAC1C,IAAe,MAAM,GAAc;GACvC,OAAO,EAAG,yBAAyB;GACnC,SAAS;GACT,eAAe,EAAG,yBAAyB;GAC5C,CAAC;AACgB,YAAiB,OAAO,OAAO,QAAQ,EAAW,GAAG,EAEvE,KAAI;AAGG,GAFL,MAAM,GAAmB,EAAE,WAAW,EAAE,OAAI,EAAE,CAAC,EAC/C,GAAwB,EACnB,EAAa,UAAU;UACtB;AAEN,GADK,EAAa,QAAQ,EACtB,GAAU,GAAO,EAAY,EAAG,wBAAwB,CAAC,GACxD,MAAM,EAAG,wBAAwB,CAAC;;;AAI3C,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GAEE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD,EAAkB,WAAU,UAAW,CAAA,EACvC,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,MAAD;OAAI,WAAU;iBACZ,kBAAC,IAAD,EAAA,UAAe,EAAG,kBAAkB,EAAgB,CAAA;OACjD,CAAA,EACL,kBAAC,KAAD;OAAG,WAAU;iBAA4C,EAAG,qBAAqB;OAAK,CAAA,CAClF;SACN,kBAAC,GAAD;MAAgB,YAAY,EAAiB;gBAC3C,kBAAC,GAAD;OACE,MAAK;OACL,SAAS;OACT,WAAU;iBAHZ,CAKE,kBAAC,GAAD,EAAM,MAAM,IAAM,CAAA,EACjB,EAAG,uBAAuB,CACpB;;MACM,CAAA,CACb;OACF;;GAEN,kBAAC,GAAD,EAAA,UAAc,EAAG,oBAAoB,EAAe,CAAA;GAGpD,kBAAC,OAAD;IAAK,WAAU;cAAf,CAEE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MACE,WAAU;MACV,MAAM;MACN,CAAA,EACF,kBAAC,SAAD;MACE,MAAK;MACL,aAAa,EAAG,8BAA8B;MAC9C,OAAO;MACP,WAAW,MAAM,GAAa,EAAE,OAAO,MAAM;MAC7C,WAAU;MACV,cAAY,EAAG,8BAA8B;MAC7C,CAAA,CACE;QAGN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,UAAD;MACE,OAAO;MACP,WAAW,MAAM,GAAmB,EAAE,OAAO,MAA4B;MACzE,WAAU;MACV,cAAY,EAAG,sBAAsB;gBAJvC;OAME,kBAAC,UAAD;QAAQ,OAAM;kBAAO,EAAG,sBAAsB;QAAU,CAAA;OACxD,kBAAC,UAAD;QAAQ,OAAM;kBAAS,EAAG,wBAAwB;QAAU,CAAA;OAC5D,kBAAC,UAAD;QAAQ,OAAM;kBAAa,EAAG,4BAA4B;QAAU,CAAA;OACpE,kBAAC,UAAD;QAAQ,OAAM;kBAAY,EAAG,2BAA2B;QAAU,CAAA;OAClE,kBAAC,UAAD;QAAQ,OAAM;kBAAa,EAAG,4BAA4B;QAAU,CAAA;OAC7D;SAGT,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,UAAD;OACE,MAAK;OACL,eAAe,EAAY,OAAO;OAClC,WAAW,0BACT,MAAa,SACT,kDACA;OAEN,cAAY,EAAG,qBAAqB;OACpC,OAAO,EAAG,qBAAqB;iBAE/B,kBAAC,GAAD,EAAM,MAAM,IAAM,CAAA;OACX,CAAA,EACT,kBAAC,UAAD;OACE,MAAK;OACL,eAAe,EAAY,OAAO;OAClC,WAAW,0BACT,MAAa,SACT,kDACA;OAEN,cAAY,EAAG,qBAAqB;OACpC,OAAO,EAAG,qBAAqB;iBAE/B,kBAAC,GAAD,EAAU,MAAM,IAAM,CAAA;OACf,CAAA,CACL;QACF;OACF;;GAGL,IACC,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,KAAD;KAAG,WAAU;eAA4C,EAAG,oBAAoB;KAAK,CAAA;IACjF,CAAA,GACJ,EAAM,SAAS,IACjB,kBAAC,OAAD;IACE,WACE,MAAa,SACT,kEACA;cAGL,EAAM,KAAK,MAAe;KACzB,IAAM,IAAS,EAAK,QACd,IAAuB,MAAW,WAAW,GAC7C,IAAyB,MAAW,eAAe,GACnD,IAAuB,MAAW,cAAc,GAEhD,IAA+B,EAAE;AAiCvC,YAhCI,KACF,EAAgB,KAAK;MACnB,OAAO,EAAG,0BAA0B;MACpC,gBAAgB,KAAK,GAAc,EAAK,GAAG;MAC5C,CAAC,EAEA,KACF,EAAgB,KAAK;MACnB,OAAO,EAAG,4BAA4B;MACtC,gBAAgB,KAAK,EAAgB,EAAK,GAAG;MAC9C,CAAC,EAEA,KACF,EAAgB,KAAK;MACnB,OAAO,EAAG,4BAA4B;MACtC,gBAAgB,KAAK,GAAgB,EAAK,GAAG;MAC9C,CAAC,EAEA,KACF,EAAgB,KAAK;MACnB,OAAO,EAAG,0BAA0B;MACpC,gBAAgB,KAAK,GAAc,EAAK,GAAG;MAC5C,CAAC,EAEA,KACF,EAAgB,KAAK;MACnB,OAAO,EAAG,yBAAyB;MACnC,gBAAgB,KAAK,GAAa,EAAK,GAAG;MAC1C,QAAQ;MACT,CAAC,EAIF,kBAAC,GAAD;MAEE,WAAU;MACV,WAAU;gBAHZ;OAKE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,MAAD;SAAI,WAAU;mBACX,IACC,kBAAC,UAAD;UACE,MAAK;UACL,WAAU;UACV,eAAe,EAAS,GAAG,EAAS,GAAG,EAAK,GAAG,OAAO;oBAErD,EAAK;UACC,CAAA,GAET,EAAK;SAEJ,CAAA,EACL,kBAAC,QAAD;SACE,WAAW,kCACT,EAAK,WAAW,cACZ,iEACA,EAAK,WAAW,UACd,qCACA;mBAGP,GAAe,EAAO;SAClB,CAAA,CACH;;OACL,EAAK,eACJ,kBAAC,GAAD;QAAU,QAAA;QAAO,WAAU;kBACxB,EAAK;QACG,CAAA;OAEb,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD,EAAA,UAAA;SACG,EAAK,OAAO,UAAU;SAAE;SAAE,EAAG,kBAAkB;SAC3C,EAAA,CAAA,EACP,kBAAC,QAAD,EAAA,UAAA;SACG,EAAK;SAAU;SAAE,EAAG,kBAAkB;SAClC,EAAA,CAAA,CACH;;OAEN,kBAAC,OAAD;QAAK,WAAU;kBAAf;SACG,KACC,kBAAC,UAAD;UACE,MAAK;UACL,UAAU,MAAM;AAEd,WADA,EAAE,iBAAiB,EACnB,EAAS,GAAG,EAAS,GAAG,EAAK,GAAG,QAAQ;;UAE1C,WAAU;UACV,OAAO,EAAG,2BAA2B;oBAPvC,CASE,kBAAC,GAAD,EAAa,MAAM,IAAM,CAAA,EACxB,EAAG,wBAAwB,CACrB;;SAEV,KACC,kBAAC,UAAD;UACE,MAAK;UACL,UAAU,MAAM;AAEd,WADA,EAAE,iBAAiB,EACnB,EAAS,GAAG,EAAS,GAAG,EAAK,GAAG,UAAU;;UAE5C,WAAU;UACV,OAAO,EAAG,yBAAyB;oBAPrC,CASE,kBAAC,GAAD,EAAK,MAAM,IAAM,CAAA,EAChB,EAAG,0BAA0B,CACvB;;SAEV,KACC,kBAAC,UAAD;UACE,MAAK;UACL,UAAU,MAAM;AAEd,WADA,EAAE,iBAAiB,EACnB,EAAS,GAAG,EAAS,GAAG,EAAK,GAAG,OAAO;;UAEzC,WAAU;UACV,OAAO,EAAG,0BAA0B;UACpC,cAAY,EAAG,0BAA0B;oBAEzC,kBAAC,GAAD,EAAU,MAAM,IAAM,CAAA;UACf,CAAA;SAGV,EAAgB,SAAS,KAAK,kBAAC,IAAD,EAAiB,SAAS,GAAmB,CAAA;SACxE;;OACI;QA1FL,EAAK,GA0FA;MAEd;IACE,CAAA,GAEN,kBAAC,GAAD;IACE,cAAa;IACb,OAAO,EAAG,uBAAuB;IACjC,aAAa,EAAG,0BAA0B;IAC1C,QACE,kBAAC,GAAD;KAAgB,YAAY,EAAiB;eAC3C,kBAAC,GAAD;MAAQ,MAAK;MAAS,SAAS;MAAkB,WAAU;gBAA3D,CACE,kBAAC,GAAD,EAAM,MAAM,IAAM,CAAA,EACjB,EAAG,uBAAuB,CACpB;;KACM,CAAA;IAEnB,CAAA;GAEA"}
|
|
1
|
+
{"version":3,"file":"ToursListPage.js","names":["ListIcon","ToursListPage","useToursI18n","navigate","useNavigate","useToursContext","useToursStore","permissionsLoading","useToursPermissionAccess","canUpdateTour","hasPermission","TOUR_PERMISSIONS","canUpdateTourSteps","canPreviewTour","canDeleteTour","canPublishTour","canArchiveTour","canDuplicateTour","useToursList","useTourLifecycle","deleteTourMutation","useDeleteTourMutation","searchQuery","setSearchQuery","useState","statusFilter","setStatusFilter","fetchTours","tourFilter","toursListRevision","handleSearch","query","updateTourFilter","handleStatusFilter","status","handleCreateTour","newPath","basePath","getStatusLabel","tr","handlePublish","publishTour","id","nativeNotify","isNative","nativeToast","handleUnpublish","unpublishTour","handleArchive","archiveTour","handleDuplicate","duplicateTour","handleDelete","confirmMsg","nativeResult","nativeConfirm","notifyToursListChanged","AuroraBackground","GradientText","PermissionGate","Button","Plus","PagePurpose","Search","setViewMode","viewMode","Grid","List","loading","tours","tour","canShowPublishAction","canShowUnpublishAction","canShowArchiveAction","overflowActions","GlassCard","Markdown","e","ListOrdered","Eye","Settings","CTAOverflowMenu","IllustratedEmptyState"],"sources":["../../../src/tours/pages/ToursListPage.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { useNavigate } from 'react-router';\nimport { Plus, Search, Grid, List as ListIcon, ListOrdered, Eye, Settings } from 'lucide-react';\nimport { Markdown, PermissionGate } from '@burdenoff/fe-libs/shared/components';\nimport {\n AuroraBackground,\n Button,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n PagePurpose,\n CTAOverflowMenu,\n type CTAAction,\n} from '@burdenoff/fe-libs/ui';\nimport { useToursList } from '../hooks/useToursList';\nimport { useTourLifecycle } from '../hooks/useTourLifecycle';\nimport { useToursPermissionAccess } from '../hooks/useToursPermissionAccess';\nimport { useToursStore } from '../store/toursStore';\nimport { useToursContext } from '../providers/ToursProvider';\nimport { useDeleteTourMutation } from '../../generated/global-operations';\nimport { TOUR_PERMISSIONS } from '../../constants/permissions';\nimport type { TourStatus } from '../types';\nimport type { Tour } from '../../generated/global-types';\nimport { useToursI18n } from '../i18n';\nimport {\n isNative,\n nativeConfirm,\n nativeImpact,\n nativeNotify,\n nativeToast,\n} from '../../utils/nativeBridge';\n\n/**\n * Tours list page\n * Displays all tours with filtering and search\n */\nexport function ToursListPage() {\n const { tr } = useToursI18n();\n const navigate = useNavigate();\n const { basePath = '/' } = useToursContext();\n const {\n viewMode,\n tourFilter,\n toursListRevision,\n setViewMode,\n updateTourFilter,\n notifyToursListChanged,\n } = useToursStore();\n const { hasPermission, isLoading: permissionsLoading } = useToursPermissionAccess();\n\n const canUpdateTour = hasPermission(TOUR_PERMISSIONS.TOUR_UPDATE);\n const canUpdateTourSteps = hasPermission(TOUR_PERMISSIONS.TOUR_STEP_UPDATE);\n const canPreviewTour = hasPermission(TOUR_PERMISSIONS.TOUR_READ);\n const canDeleteTour = hasPermission(TOUR_PERMISSIONS.TOUR_DELETE);\n const canPublishTour = hasPermission(TOUR_PERMISSIONS.TOUR_PUBLISH);\n const canArchiveTour = hasPermission(TOUR_PERMISSIONS.TOUR_ARCHIVE);\n const canDuplicateTour = hasPermission(TOUR_PERMISSIONS.TOUR_DUPLICATE);\n\n // Fetch tours (includes both workspace-specific and global tours)\n const { tours, loading, fetchTours } = useToursList();\n\n const { publishTour, unpublishTour, archiveTour, duplicateTour } = useTourLifecycle();\n const [deleteTourMutation] = useDeleteTourMutation();\n\n const [searchQuery, setSearchQuery] = useState('');\n const [statusFilter, setStatusFilter] = useState<TourStatus | 'all'>('all');\n\n // Fetch tours when filter changes. The list page is also the user-facing\n // tour browser, so backend permissions remain authoritative for actions while\n // normal users can still see published tours returned by the API.\n useEffect(() => {\n if (permissionsLoading) return;\n fetchTours({ ...tourFilter });\n }, [fetchTours, tourFilter, toursListRevision, permissionsLoading]);\n\n const handleSearch = (query: string) => {\n setSearchQuery(query);\n updateTourFilter({ search: query });\n };\n\n const handleStatusFilter = (status: TourStatus | 'all') => {\n setStatusFilter(status);\n updateTourFilter({ status });\n };\n\n const handleCreateTour = () => {\n const newPath = basePath.endsWith('/') ? `${basePath}new` : `${basePath}/new`;\n navigate(newPath);\n };\n\n const getStatusLabel = (status: TourStatus) => {\n switch (status) {\n case 'DRAFT':\n return tr('toursList.statusDraft');\n case 'PUBLISHED':\n return tr('toursList.statusPublished');\n case 'ARCHIVED':\n return tr('toursList.statusArchived');\n case 'SCHEDULED':\n return tr('toursList.statusScheduled');\n }\n };\n\n const handlePublish = async (id: string) => {\n nativeImpact('light');\n try {\n await publishTour(id);\n void nativeNotify('success');\n } catch {\n void nativeNotify('error');\n if (isNative()) void nativeToast(tr('toursList.errorPublish'));\n else alert(tr('toursList.errorPublish'));\n }\n };\n\n const handleUnpublish = async (id: string) => {\n nativeImpact('light');\n try {\n await unpublishTour(id);\n void nativeNotify('success');\n } catch {\n void nativeNotify('error');\n if (isNative()) void nativeToast(tr('toursList.errorUnpublish'));\n else alert(tr('toursList.errorUnpublish'));\n }\n };\n\n const handleArchive = async (id: string) => {\n nativeImpact('light');\n try {\n await archiveTour(id);\n void nativeNotify('success');\n } catch {\n void nativeNotify('error');\n if (isNative()) void nativeToast(tr('toursList.errorArchive'));\n else alert(tr('toursList.errorArchive'));\n }\n };\n\n const handleDuplicate = async (id: string) => {\n nativeImpact('light');\n try {\n await duplicateTour(id);\n void nativeNotify('success');\n } catch {\n void nativeNotify('error');\n if (isNative()) void nativeToast(tr('toursList.errorDuplicate'));\n else alert(tr('toursList.errorDuplicate'));\n }\n };\n\n const handleDelete = async (id: string) => {\n nativeImpact('medium');\n const confirmMsg = tr('toursList.confirmDelete');\n const nativeResult = await nativeConfirm({\n title: tr('toursList.actionDelete'),\n message: confirmMsg,\n okButtonTitle: tr('toursList.actionDelete'),\n });\n const confirmed = nativeResult === null ? window.confirm(confirmMsg) : nativeResult;\n if (!confirmed) return;\n try {\n await deleteTourMutation({ variables: { id } });\n notifyToursListChanged();\n void nativeNotify('success');\n } catch {\n void nativeNotify('error');\n if (isNative()) void nativeToast(tr('toursList.errorDelete'));\n else alert(tr('toursList.errorDelete'));\n }\n };\n\n return (\n <div className=\"space-y-4 sm:space-y-6 p-3 sm:p-6\">\n {/* Header */}\n <div className=\"relative overflow-hidden rounded-xl\">\n <AuroraBackground intensity=\"subtle\" />\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 p-1 sm:p-2\">\n <div className=\"flex-1 min-w-0\">\n <h1 className=\"text-xl sm:text-2xl font-bold text-text-primary\">\n <GradientText>{tr('toursList.title')}</GradientText>\n </h1>\n <p className=\"text-sm sm:text-base text-text-secondary\">{tr('toursList.subtitle')}</p>\n </div>\n <PermissionGate permission={TOUR_PERMISSIONS.TOUR_CREATE}>\n <Button\n type=\"button\"\n onClick={handleCreateTour}\n className=\"w-full sm:w-auto min-h-[44px]\"\n >\n <Plus size={20} />\n {tr('toursList.createTour')}\n </Button>\n </PermissionGate>\n </div>\n </div>\n\n <PagePurpose>{tr('toursList.purpose')}</PagePurpose>\n\n {/* Filters and Search */}\n <div className=\"flex flex-col sm:flex-row gap-3 sm:gap-4\">\n {/* Search */}\n <div className=\"flex-1 relative\">\n <Search\n className=\"absolute left-3 top-1/2 -translate-y-1/2 text-text-secondary\"\n size={20}\n />\n <input\n type=\"text\"\n placeholder={tr('toursList.searchPlaceholder')}\n value={searchQuery}\n onChange={(e) => handleSearch(e.target.value)}\n className=\"w-full pl-[3.25rem] pr-4 py-2 min-h-[44px] border border-border-subtle rounded-md bg-bg-surface text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n aria-label={tr('toursList.searchPlaceholder')}\n />\n </div>\n\n {/* Status Filter */}\n <div className=\"flex gap-2\">\n <select\n value={statusFilter}\n onChange={(e) => handleStatusFilter(e.target.value as TourStatus | 'all')}\n className=\"px-4 py-2 min-h-[44px] border border-border-subtle rounded-md bg-bg-surface text-text-primary scheme-normal dark:scheme-dark [&_option]:bg-bg-surface [&_option]:text-text-primary\"\n aria-label={tr('toursList.statusAll')}\n >\n <option value=\"all\">{tr('toursList.statusAll')}</option>\n <option value=\"DRAFT\">{tr('toursList.statusDraft')}</option>\n <option value=\"PUBLISHED\">{tr('toursList.statusPublished')}</option>\n <option value=\"ARCHIVED\">{tr('toursList.statusArchived')}</option>\n <option value=\"SCHEDULED\">{tr('toursList.statusScheduled')}</option>\n </select>\n\n {/* View Mode Toggle */}\n <div className=\"flex border border-border-subtle rounded-md overflow-hidden\">\n <button\n type=\"button\"\n onClick={() => setViewMode('grid')}\n className={`px-3 py-2 min-h-[44px] ${\n viewMode === 'grid'\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-surface text-text-primary hover:bg-accent'\n }`}\n aria-label={tr('toursList.gridView')}\n title={tr('toursList.gridView')}\n >\n <Grid size={20} />\n </button>\n <button\n type=\"button\"\n onClick={() => setViewMode('list')}\n className={`px-3 py-2 min-h-[44px] ${\n viewMode === 'list'\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-surface text-text-primary hover:bg-accent'\n }`}\n aria-label={tr('toursList.listView')}\n title={tr('toursList.listView')}\n >\n <ListIcon size={20} />\n </button>\n </div>\n </div>\n </div>\n\n {/* Tours List */}\n {loading ? (\n <div className=\"text-center py-12\">\n <p className=\"text-sm sm:text-base text-text-secondary\">{tr('toursList.loading')}</p>\n </div>\n ) : tours.length > 0 ? (\n <div\n className={\n viewMode === 'grid'\n ? 'grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 sm:gap-4'\n : 'space-y-3'\n }\n >\n {tours.map((tour: Tour) => {\n const status = tour.status as TourStatus;\n const canShowPublishAction = status === 'DRAFT' && canPublishTour;\n const canShowUnpublishAction = status === 'PUBLISHED' && canPublishTour;\n const canShowArchiveAction = status !== 'ARCHIVED' && canArchiveTour;\n\n const overflowActions: CTAAction[] = [];\n if (canShowPublishAction) {\n overflowActions.push({\n label: tr('toursList.actionPublish'),\n onSelect: () => void handlePublish(tour.id),\n });\n }\n if (canShowUnpublishAction) {\n overflowActions.push({\n label: tr('toursList.actionUnpublish'),\n onSelect: () => void handleUnpublish(tour.id),\n });\n }\n if (canDuplicateTour) {\n overflowActions.push({\n label: tr('toursList.actionDuplicate'),\n onSelect: () => void handleDuplicate(tour.id),\n });\n }\n if (canShowArchiveAction) {\n overflowActions.push({\n label: tr('toursList.actionArchive'),\n onSelect: () => void handleArchive(tour.id),\n });\n }\n if (canDeleteTour) {\n overflowActions.push({\n label: tr('toursList.actionDelete'),\n onSelect: () => void handleDelete(tour.id),\n intent: 'destructive',\n });\n }\n\n return (\n <GlassCard\n key={tour.id}\n treatment=\"plain\"\n className=\"p-4 border-border-seam shadow-[var(--shadow-pop)]\"\n >\n <div className=\"flex items-start justify-between mb-2\">\n <h3 className=\"font-semibold text-text-primary\">\n {canUpdateTour ? (\n <button\n type=\"button\"\n className=\"cursor-pointer hover:text-primary bg-transparent border-0 p-0 text-left font-inherit\"\n onClick={() => navigate(`${basePath}/${tour.id}/edit`)}\n >\n {tour.name}\n </button>\n ) : (\n tour.name\n )}\n </h3>\n <span\n className={`px-2 py-1 text-xs rounded-full ${\n tour.status === 'PUBLISHED'\n ? 'bg-success/10 text-success motion-safe:animate-vc-glow-pulse'\n : tour.status === 'DRAFT'\n ? 'bg-bg-sunken text-text-secondary'\n : 'bg-warning/10 text-warning'\n }`}\n >\n {getStatusLabel(status)}\n </span>\n </div>\n {tour.description && (\n <Markdown inline className=\"text-sm text-text-secondary mb-3\">\n {tour.description}\n </Markdown>\n )}\n <div className=\"flex items-center justify-between text-xs text-text-secondary mb-3\">\n <span>\n {tour.steps?.length || 0} {tr('toursList.steps')}\n </span>\n <span>\n {tour.viewCount} {tr('toursList.views')}\n </span>\n </div>\n {/* Quick Actions */}\n <div className=\"flex flex-wrap items-center gap-2 pt-3 border-t border-border-seam\">\n {canUpdateTourSteps && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n navigate(`${basePath}/${tour.id}/steps`);\n }}\n className=\"flex-1 min-w-[6.5rem] px-3 py-2 min-h-[44px] text-xs bg-secondary text-secondary-foreground rounded hover:bg-secondary/80 flex items-center justify-center gap-1.5\"\n title={tr('toursList.editStepsTitle')}\n >\n <ListOrdered size={14} />\n {tr('toursList.stepsButton')}\n </button>\n )}\n {canPreviewTour && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n navigate(`${basePath}/${tour.id}/preview`);\n }}\n className=\"flex-1 min-w-[6.5rem] px-3 py-2 min-h-[44px] text-xs border border-border-seam rounded hover:bg-accent flex items-center justify-center gap-1.5\"\n title={tr('toursList.previewTitle')}\n >\n <Eye size={14} />\n {tr('toursList.previewButton')}\n </button>\n )}\n {canUpdateTour && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n navigate(`${basePath}/${tour.id}/edit`);\n }}\n className=\"p-2 min-h-[44px] min-w-[44px] text-xs border border-border-seam rounded hover:bg-accent\"\n title={tr('toursList.settingsTitle')}\n aria-label={tr('toursList.settingsTitle')}\n >\n <Settings size={14} />\n </button>\n )}\n {/* Lifecycle actions collapsed into the overflow menu */}\n {overflowActions.length > 0 && <CTAOverflowMenu actions={overflowActions} />}\n </div>\n </GlassCard>\n );\n })}\n </div>\n ) : (\n <IllustratedEmptyState\n illustration=\"onboarding\"\n title={tr('toursList.emptyTitle')}\n description={tr('toursList.emptySubtitle')}\n action={\n <PermissionGate permission={TOUR_PERMISSIONS.TOUR_CREATE}>\n <Button type=\"button\" onClick={handleCreateTour} className=\"min-h-[44px]\">\n <Plus size={20} />\n {tr('toursList.createTour')}\n </Button>\n </PermissionGate>\n }\n />\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { ToursRootProps, ToursVariant } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Context value for Tours microfrontend.
|
|
5
|
+
*
|
|
6
|
+
* Carries the ToursRoot props plus a resolved `variant` (always set; defaults
|
|
7
|
+
* to "admin" when the caller did not specify one). Pages can read `variant`
|
|
8
|
+
* to branch UI affordances (e.g., the user surface should never attempt
|
|
9
|
+
* admin-only queries).
|
|
10
|
+
*/
|
|
11
|
+
type ToursContextValue = ToursRootProps & {
|
|
12
|
+
variant: ToursVariant;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Hook to access Tours context.
|
|
16
|
+
*/
|
|
17
|
+
export declare const useToursContext: () => ToursContextValue;
|
|
18
|
+
/**
|
|
19
|
+
* Provider component for Tours microfrontend.
|
|
20
|
+
* Sets up routing, context, and global-scoped permission checking.
|
|
21
|
+
*/
|
|
22
|
+
export declare function ToursProvider({ children, ...props }: ToursRootProps & {
|
|
23
|
+
children: ReactNode;
|
|
24
|
+
}): import('react').JSX.Element;
|
|
25
|
+
export {};
|