@burdenoff/microfe-tours 2026.720.1 → 2026.720.2
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/tours/components/MarkdownEditor.js +144 -0
- package/dist/tours/components/MarkdownEditor.js.map +1 -0
- package/dist/tours/pages/MyToursPage.js +66 -63
- package/dist/tours/pages/MyToursPage.js.map +1 -1
- package/dist/tours/pages/StepEditorPage.js +219 -222
- package/dist/tours/pages/StepEditorPage.js.map +1 -1
- package/dist/tours/pages/TourBuilderPage.js +76 -79
- package/dist/tours/pages/TourBuilderPage.js.map +1 -1
- package/dist/tours/pages/TourPreviewPage.js +112 -111
- package/dist/tours/pages/TourPreviewPage.js.map +1 -1
- package/dist/tours/pages/ToursListPage.js +85 -84
- package/dist/tours/pages/ToursListPage.js.map +1 -1
- package/package.json +2 -2
|
@@ -6,132 +6,133 @@ import { useToursI18n as i } from "../i18n.js";
|
|
|
6
6
|
import { useTourBuilder as a } from "../hooks/useTourBuilder.js";
|
|
7
7
|
import { useTourPreview as o } from "../hooks/useTourPreview.js";
|
|
8
8
|
import { useEffect as s } from "react";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
9
|
+
import { Markdown as c } from "@burdenoff/fe-libs/shared/components";
|
|
10
|
+
import { AlertCircle as l, ArrowLeft as u, ChevronLeft as d, ChevronRight as f, Monitor as p, Smartphone as m, Tablet as h, X as g } from "lucide-react";
|
|
11
|
+
import { jsx as _, jsxs as v } from "react/jsx-runtime";
|
|
12
|
+
import { useNavigate as y, useParams as b } from "react-router-dom";
|
|
13
|
+
import { Button as x, GlassCard as S, IllustratedEmptyState as C, PagePurpose as w } from "@burdenoff/fe-libs/ui";
|
|
13
14
|
//#region src/tours/pages/TourPreviewPage.tsx
|
|
14
|
-
function
|
|
15
|
-
let { tr:
|
|
15
|
+
function T() {
|
|
16
|
+
let { tr: T } = i(), { tourId: E } = b(), D = y(), { basePath: O = "/" } = e(), { hasPermission: k } = n(), A = k(r.TOUR_READ), { tour: j, loadTour: M } = a(E), { devicePreview: N } = t(), { isPreviewActive: P, currentStepIndex: F, currentStep: I, totalSteps: L, canGoNext: R, canGoPrevious: z, validationResults: B, startPreview: V, stopPreview: H, nextStep: U, previousStep: W, changeDevice: G, validateForPreview: K } = o(j || void 0);
|
|
16
17
|
if (s(() => {
|
|
17
|
-
|
|
18
|
-
}, [
|
|
19
|
-
|
|
18
|
+
E && M(E);
|
|
19
|
+
}, [E, M]), s(() => {
|
|
20
|
+
j && K();
|
|
20
21
|
}, [
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
]), !
|
|
22
|
+
j,
|
|
23
|
+
N,
|
|
24
|
+
K
|
|
25
|
+
]), !A) return /* @__PURE__ */ _("div", {
|
|
25
26
|
className: "flex items-center justify-center h-screen bg-bg-sunken",
|
|
26
|
-
children: /* @__PURE__ */
|
|
27
|
+
children: /* @__PURE__ */ v("div", {
|
|
27
28
|
className: "text-center",
|
|
28
|
-
children: [/* @__PURE__ */
|
|
29
|
+
children: [/* @__PURE__ */ _("h2", {
|
|
29
30
|
className: "text-lg font-semibold text-text-primary mb-2",
|
|
30
|
-
children:
|
|
31
|
-
}), /* @__PURE__ */
|
|
31
|
+
children: T("tourPreview.accessDeniedTitle")
|
|
32
|
+
}), /* @__PURE__ */ _("p", {
|
|
32
33
|
className: "text-sm text-text-secondary",
|
|
33
|
-
children:
|
|
34
|
+
children: T("tourPreview.accessDeniedMessage")
|
|
34
35
|
})]
|
|
35
36
|
})
|
|
36
37
|
});
|
|
37
|
-
if (!
|
|
38
|
+
if (!j) return /* @__PURE__ */ _("div", {
|
|
38
39
|
className: "flex items-center justify-center h-screen bg-bg-sunken",
|
|
39
|
-
children: /* @__PURE__ */
|
|
40
|
+
children: /* @__PURE__ */ _("p", {
|
|
40
41
|
className: "text-text-secondary",
|
|
41
|
-
children:
|
|
42
|
+
children: T("tourPreview.loading")
|
|
42
43
|
})
|
|
43
44
|
});
|
|
44
|
-
let
|
|
45
|
-
|
|
46
|
-
},
|
|
47
|
-
mobile: /* @__PURE__ */
|
|
48
|
-
tablet: /* @__PURE__ */
|
|
49
|
-
desktop: /* @__PURE__ */
|
|
45
|
+
let q = () => {
|
|
46
|
+
D(`${O}/${E}/edit`);
|
|
47
|
+
}, J = {
|
|
48
|
+
mobile: /* @__PURE__ */ _(m, { size: 20 }),
|
|
49
|
+
tablet: /* @__PURE__ */ _(h, { size: 20 }),
|
|
50
|
+
desktop: /* @__PURE__ */ _(p, { size: 20 })
|
|
50
51
|
};
|
|
51
|
-
return /* @__PURE__ */
|
|
52
|
+
return /* @__PURE__ */ v("div", {
|
|
52
53
|
className: "flex flex-col h-screen bg-bg-sunken",
|
|
53
54
|
children: [
|
|
54
|
-
/* @__PURE__ */
|
|
55
|
+
/* @__PURE__ */ v("div", {
|
|
55
56
|
className: "border-b border-border-subtle bg-bg-surface p-3 sm:p-4 flex flex-wrap items-center gap-3 sm:gap-4",
|
|
56
57
|
children: [
|
|
57
|
-
/* @__PURE__ */
|
|
58
|
+
/* @__PURE__ */ _("button", {
|
|
58
59
|
type: "button",
|
|
59
|
-
onClick:
|
|
60
|
+
onClick: q,
|
|
60
61
|
className: "p-2 min-h-[44px] min-w-[44px] hover:bg-accent rounded-md",
|
|
61
|
-
"aria-label":
|
|
62
|
-
children: /* @__PURE__ */
|
|
62
|
+
"aria-label": T("tourBuilder.goBack"),
|
|
63
|
+
children: /* @__PURE__ */ _(u, { size: 20 })
|
|
63
64
|
}),
|
|
64
|
-
/* @__PURE__ */
|
|
65
|
+
/* @__PURE__ */ v("div", {
|
|
65
66
|
className: "flex-1 min-w-[12rem]",
|
|
66
|
-
children: [/* @__PURE__ */
|
|
67
|
+
children: [/* @__PURE__ */ v("h1", {
|
|
67
68
|
className: "text-base sm:text-lg font-semibold truncate",
|
|
68
69
|
children: [
|
|
69
|
-
|
|
70
|
+
j?.name,
|
|
70
71
|
" - ",
|
|
71
|
-
|
|
72
|
+
T("tourPreview.previewSuffix")
|
|
72
73
|
]
|
|
73
|
-
}),
|
|
74
|
+
}), P && /* @__PURE__ */ v("p", {
|
|
74
75
|
className: "text-sm text-text-secondary",
|
|
75
76
|
children: [
|
|
76
|
-
|
|
77
|
+
T("tourPreview.stepOf"),
|
|
77
78
|
" ",
|
|
78
|
-
|
|
79
|
+
F + 1,
|
|
79
80
|
" ",
|
|
80
|
-
|
|
81
|
+
T("tourPreview.stepOfConnector"),
|
|
81
82
|
" ",
|
|
82
|
-
|
|
83
|
+
L
|
|
83
84
|
]
|
|
84
85
|
})]
|
|
85
86
|
}),
|
|
86
|
-
/* @__PURE__ */
|
|
87
|
+
/* @__PURE__ */ _("div", {
|
|
87
88
|
className: "flex gap-2 border border-border-subtle rounded-md overflow-hidden",
|
|
88
89
|
children: [
|
|
89
90
|
"mobile",
|
|
90
91
|
"tablet",
|
|
91
92
|
"desktop"
|
|
92
|
-
].map((e) => /* @__PURE__ */
|
|
93
|
+
].map((e) => /* @__PURE__ */ _("button", {
|
|
93
94
|
type: "button",
|
|
94
|
-
onClick: () =>
|
|
95
|
-
className: `px-3 py-2 min-h-[44px] min-w-[44px] ${
|
|
96
|
-
title:
|
|
97
|
-
"aria-label":
|
|
98
|
-
children:
|
|
95
|
+
onClick: () => G(e),
|
|
96
|
+
className: `px-3 py-2 min-h-[44px] min-w-[44px] ${N === e ? "bg-action-primary-bg text-action-primary-text" : "bg-bg-surface hover:bg-accent"}`,
|
|
97
|
+
title: T(e === "mobile" ? "tourPreview.deviceMobile" : e === "tablet" ? "tourPreview.deviceTablet" : "tourPreview.deviceDesktop"),
|
|
98
|
+
"aria-label": T(e === "mobile" ? "tourPreview.deviceMobile" : e === "tablet" ? "tourPreview.deviceTablet" : "tourPreview.deviceDesktop"),
|
|
99
|
+
children: J[e]
|
|
99
100
|
}, e))
|
|
100
101
|
}),
|
|
101
|
-
|
|
102
|
+
P ? /* @__PURE__ */ v(x, {
|
|
102
103
|
type: "button",
|
|
103
104
|
variant: "outline",
|
|
104
|
-
onClick:
|
|
105
|
+
onClick: H,
|
|
105
106
|
className: "min-h-[44px]",
|
|
106
|
-
children: [/* @__PURE__ */ g
|
|
107
|
-
}) : /* @__PURE__ */
|
|
107
|
+
children: [/* @__PURE__ */ _(g, { size: 20 }), T("tourPreview.stopPreview")]
|
|
108
|
+
}) : /* @__PURE__ */ _(x, {
|
|
108
109
|
type: "button",
|
|
109
|
-
onClick:
|
|
110
|
-
disabled: !
|
|
110
|
+
onClick: V,
|
|
111
|
+
disabled: !B?.valid,
|
|
111
112
|
className: "min-h-[44px]",
|
|
112
|
-
children:
|
|
113
|
+
children: T("tourPreview.startPreview")
|
|
113
114
|
})
|
|
114
115
|
]
|
|
115
116
|
}),
|
|
116
|
-
/* @__PURE__ */
|
|
117
|
+
/* @__PURE__ */ _("div", {
|
|
117
118
|
className: "px-3 sm:px-6 pt-3",
|
|
118
|
-
children: /* @__PURE__ */
|
|
119
|
+
children: /* @__PURE__ */ _(w, { children: T("tourPreview.purpose") })
|
|
119
120
|
}),
|
|
120
|
-
|
|
121
|
+
B && !B.valid && /* @__PURE__ */ _("div", {
|
|
121
122
|
className: "bg-status-error-bg/10 border-b border-status-error-border px-3 sm:px-6 py-3",
|
|
122
|
-
children: /* @__PURE__ */
|
|
123
|
+
children: /* @__PURE__ */ v("div", {
|
|
123
124
|
className: "flex items-start gap-3",
|
|
124
|
-
children: [/* @__PURE__ */
|
|
125
|
+
children: [/* @__PURE__ */ _(l, {
|
|
125
126
|
className: "text-status-error-text flex-shrink-0 mt-0.5",
|
|
126
127
|
size: 20
|
|
127
|
-
}), /* @__PURE__ */
|
|
128
|
+
}), /* @__PURE__ */ v("div", {
|
|
128
129
|
className: "flex-1",
|
|
129
|
-
children: [/* @__PURE__ */
|
|
130
|
+
children: [/* @__PURE__ */ _("h3", {
|
|
130
131
|
className: "font-semibold text-status-error-text mb-1",
|
|
131
|
-
children:
|
|
132
|
-
}), /* @__PURE__ */
|
|
132
|
+
children: T("tourPreview.validationErrorsTitle")
|
|
133
|
+
}), /* @__PURE__ */ _("ul", {
|
|
133
134
|
className: "list-disc list-inside space-y-1",
|
|
134
|
-
children:
|
|
135
|
+
children: B.errors.map((e) => /* @__PURE__ */ _("li", {
|
|
135
136
|
className: "text-sm text-status-error-text",
|
|
136
137
|
children: e
|
|
137
138
|
}, e))
|
|
@@ -139,21 +140,21 @@ function w() {
|
|
|
139
140
|
})]
|
|
140
141
|
})
|
|
141
142
|
}),
|
|
142
|
-
|
|
143
|
+
B && B.warnings.length > 0 && /* @__PURE__ */ _("div", {
|
|
143
144
|
className: "bg-warning/10 border-b border-warning px-3 sm:px-6 py-3",
|
|
144
|
-
children: /* @__PURE__ */
|
|
145
|
+
children: /* @__PURE__ */ v("div", {
|
|
145
146
|
className: "flex items-start gap-3",
|
|
146
|
-
children: [/* @__PURE__ */
|
|
147
|
+
children: [/* @__PURE__ */ _(l, {
|
|
147
148
|
className: "text-warning flex-shrink-0 mt-0.5",
|
|
148
149
|
size: 20
|
|
149
|
-
}), /* @__PURE__ */
|
|
150
|
+
}), /* @__PURE__ */ v("div", {
|
|
150
151
|
className: "flex-1",
|
|
151
|
-
children: [/* @__PURE__ */
|
|
152
|
+
children: [/* @__PURE__ */ _("h3", {
|
|
152
153
|
className: "font-semibold text-warning mb-1",
|
|
153
|
-
children:
|
|
154
|
-
}), /* @__PURE__ */
|
|
154
|
+
children: T("tourPreview.warningsTitle")
|
|
155
|
+
}), /* @__PURE__ */ _("ul", {
|
|
155
156
|
className: "list-disc list-inside space-y-1",
|
|
156
|
-
children:
|
|
157
|
+
children: B.warnings.map((e) => /* @__PURE__ */ _("li", {
|
|
157
158
|
className: "text-sm text-warning",
|
|
158
159
|
children: e
|
|
159
160
|
}, e))
|
|
@@ -161,77 +162,77 @@ function w() {
|
|
|
161
162
|
})]
|
|
162
163
|
})
|
|
163
164
|
}),
|
|
164
|
-
/* @__PURE__ */
|
|
165
|
+
/* @__PURE__ */ _("div", {
|
|
165
166
|
className: "flex-1 flex items-center justify-center p-3 sm:p-6 overflow-auto",
|
|
166
|
-
children: /* @__PURE__ */
|
|
167
|
-
className: `bg-bg-surface border-2 rounded-lg shadow-xl overflow-hidden ${
|
|
168
|
-
children:
|
|
167
|
+
children: /* @__PURE__ */ _("div", {
|
|
168
|
+
className: `bg-bg-surface border-2 rounded-lg shadow-xl overflow-hidden ${N === "mobile" ? "w-[min(375px,calc(100vw-1.5rem))] h-[667px] max-h-full" : N === "tablet" ? "w-[min(768px,calc(100vw-1.5rem))] h-[1024px] max-h-full" : "w-full max-w-[1920px] h-full max-h-[1080px]"}`,
|
|
169
|
+
children: P && I ? /* @__PURE__ */ _("div", {
|
|
169
170
|
className: "h-full flex flex-col items-center justify-center p-4 sm:p-8",
|
|
170
|
-
children: /* @__PURE__ */
|
|
171
|
+
children: /* @__PURE__ */ v(S, {
|
|
171
172
|
treatment: "glass",
|
|
172
173
|
className: "max-w-md border-border-seam p-4 sm:p-6 shadow-[var(--shadow-pop)]",
|
|
173
174
|
children: [
|
|
174
|
-
/* @__PURE__ */
|
|
175
|
+
/* @__PURE__ */ _("h3", {
|
|
175
176
|
className: "text-lg font-semibold mb-3",
|
|
176
|
-
children:
|
|
177
|
-
}),
|
|
178
|
-
/* @__PURE__ */ g("p", {
|
|
179
|
-
className: "text-sm text-text-secondary mb-4 whitespace-pre-wrap",
|
|
180
|
-
children: F.content
|
|
177
|
+
children: I.title
|
|
181
178
|
}),
|
|
182
179
|
/* @__PURE__ */ _("div", {
|
|
180
|
+
className: "text-sm text-text-secondary mb-4 prose prose-sm max-w-none",
|
|
181
|
+
children: /* @__PURE__ */ _(c, { children: I.content })
|
|
182
|
+
}),
|
|
183
|
+
/* @__PURE__ */ v("div", {
|
|
183
184
|
className: "flex gap-2",
|
|
184
|
-
children: [/* @__PURE__ */
|
|
185
|
+
children: [/* @__PURE__ */ _("button", {
|
|
185
186
|
type: "button",
|
|
186
|
-
onClick:
|
|
187
|
-
disabled: !
|
|
187
|
+
onClick: W,
|
|
188
|
+
disabled: !z,
|
|
188
189
|
className: "px-3 py-2 min-h-[44px] min-w-[44px] border border-border-subtle rounded-md hover:bg-accent disabled:opacity-50 disabled:cursor-not-allowed",
|
|
189
|
-
"aria-label":
|
|
190
|
-
children: /* @__PURE__ */
|
|
191
|
-
}), /* @__PURE__ */
|
|
190
|
+
"aria-label": T("tourPreview.previous"),
|
|
191
|
+
children: /* @__PURE__ */ _(d, { size: 16 })
|
|
192
|
+
}), /* @__PURE__ */ _("button", {
|
|
192
193
|
type: "button",
|
|
193
|
-
onClick:
|
|
194
|
-
disabled: !
|
|
194
|
+
onClick: U,
|
|
195
|
+
disabled: !R,
|
|
195
196
|
className: "flex-1 px-3 py-2 min-h-[44px] bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg/90 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
196
|
-
children:
|
|
197
|
+
children: T(R ? "tourPreview.next" : "tourPreview.finish")
|
|
197
198
|
})]
|
|
198
199
|
})
|
|
199
200
|
]
|
|
200
201
|
})
|
|
201
|
-
}) : /* @__PURE__ */
|
|
202
|
+
}) : /* @__PURE__ */ _("div", {
|
|
202
203
|
className: "h-full flex items-center justify-center p-4",
|
|
203
|
-
children: /* @__PURE__ */
|
|
204
|
+
children: /* @__PURE__ */ _(C, {
|
|
204
205
|
illustration: "onboarding",
|
|
205
|
-
title:
|
|
206
|
-
description:
|
|
206
|
+
title: T("tourPreview.readyTitle"),
|
|
207
|
+
description: T("tourPreview.readyHint")
|
|
207
208
|
})
|
|
208
209
|
})
|
|
209
210
|
})
|
|
210
211
|
}),
|
|
211
|
-
|
|
212
|
+
P && /* @__PURE__ */ v("div", {
|
|
212
213
|
className: "border-t border-border-subtle bg-bg-surface p-3 sm:p-4 flex items-center justify-center gap-3 sm:gap-4",
|
|
213
214
|
children: [
|
|
214
|
-
/* @__PURE__ */
|
|
215
|
+
/* @__PURE__ */ v("button", {
|
|
215
216
|
type: "button",
|
|
216
|
-
onClick:
|
|
217
|
-
disabled: !
|
|
217
|
+
onClick: W,
|
|
218
|
+
disabled: !z,
|
|
218
219
|
className: "px-4 py-2 min-h-[44px] border border-border-subtle rounded-md hover:bg-accent disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2",
|
|
219
|
-
children: [/* @__PURE__ */
|
|
220
|
+
children: [/* @__PURE__ */ _(d, { size: 20 }), T("tourPreview.previous")]
|
|
220
221
|
}),
|
|
221
|
-
/* @__PURE__ */
|
|
222
|
+
/* @__PURE__ */ v("div", {
|
|
222
223
|
className: "text-sm text-text-secondary",
|
|
223
224
|
children: [
|
|
224
|
-
|
|
225
|
+
F + 1,
|
|
225
226
|
" / ",
|
|
226
|
-
|
|
227
|
+
L
|
|
227
228
|
]
|
|
228
229
|
}),
|
|
229
|
-
/* @__PURE__ */
|
|
230
|
+
/* @__PURE__ */ v("button", {
|
|
230
231
|
type: "button",
|
|
231
|
-
onClick:
|
|
232
|
-
disabled: !
|
|
232
|
+
onClick: U,
|
|
233
|
+
disabled: !R,
|
|
233
234
|
className: "px-4 py-2 min-h-[44px] border border-border-subtle rounded-md hover:bg-accent disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2",
|
|
234
|
-
children: [
|
|
235
|
+
children: [T("tourPreview.nextFooter"), /* @__PURE__ */ _(f, { size: 20 })]
|
|
235
236
|
})
|
|
236
237
|
]
|
|
237
238
|
})
|
|
@@ -239,6 +240,6 @@ function w() {
|
|
|
239
240
|
});
|
|
240
241
|
}
|
|
241
242
|
//#endregion
|
|
242
|
-
export {
|
|
243
|
+
export { T as TourPreviewPage };
|
|
243
244
|
|
|
244
245
|
//# sourceMappingURL=TourPreviewPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TourPreviewPage.js","names":[],"sources":["../../../src/tours/pages/TourPreviewPage.tsx"],"sourcesContent":["import { useEffect } from 'react';\nimport { useParams, useNavigate } from 'react-router-dom';\nimport {\n ArrowLeft,\n ChevronLeft,\n ChevronRight,\n X,\n Smartphone,\n Tablet,\n Monitor,\n AlertCircle,\n} from 'lucide-react';\nimport { Button, GlassCard, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { useTourPreview } from '../hooks/useTourPreview';\nimport { useTourBuilder } from '../hooks/useTourBuilder';\nimport { useToursPermissionAccess } from '../hooks/useToursPermissionAccess';\nimport { useToursContext } from '../providers/ToursProvider';\nimport { useToursStore } from '../store/toursStore';\nimport { TOUR_PERMISSIONS } from '../../constants/permissions';\nimport { useToursI18n } from '../i18n';\n\n/**\n * Tour preview page\n * Preview tour with device simulation and validation\n */\nexport function TourPreviewPage() {\n const { tr } = useToursI18n();\n const { tourId } = useParams();\n const navigate = useNavigate();\n const { basePath = '/' } = useToursContext();\n const { hasPermission } = useToursPermissionAccess();\n const canReadTour = hasPermission(TOUR_PERMISSIONS.TOUR_READ);\n const { tour, loadTour } = useTourBuilder(tourId);\n const { devicePreview } = useToursStore();\n\n const {\n isPreviewActive,\n currentStepIndex,\n currentStep,\n totalSteps,\n canGoNext,\n canGoPrevious,\n validationResults,\n startPreview,\n stopPreview,\n nextStep,\n previousStep,\n changeDevice,\n validateForPreview,\n } = useTourPreview(tour || undefined);\n\n useEffect(() => {\n if (tourId) {\n loadTour(tourId);\n }\n }, [tourId, loadTour]);\n\n useEffect(() => {\n if (tour) {\n validateForPreview();\n }\n }, [tour, devicePreview, validateForPreview]);\n\n if (!canReadTour) {\n return (\n <div className=\"flex items-center justify-center h-screen bg-bg-sunken\">\n <div className=\"text-center\">\n <h2 className=\"text-lg font-semibold text-text-primary mb-2\">\n {tr('tourPreview.accessDeniedTitle')}\n </h2>\n <p className=\"text-sm text-text-secondary\">{tr('tourPreview.accessDeniedMessage')}</p>\n </div>\n </div>\n );\n }\n\n if (!tour) {\n return (\n <div className=\"flex items-center justify-center h-screen bg-bg-sunken\">\n <p className=\"text-text-secondary\">{tr('tourPreview.loading')}</p>\n </div>\n );\n }\n\n const handleBack = () => {\n navigate(`${basePath}/${tourId}/edit`);\n };\n\n const deviceIcons = {\n mobile: <Smartphone size={20} />,\n tablet: <Tablet size={20} />,\n desktop: <Monitor size={20} />,\n };\n\n return (\n <div className=\"flex flex-col h-screen bg-bg-sunken\">\n {/* Header */}\n <div className=\"border-b border-border-subtle bg-bg-surface p-3 sm:p-4 flex flex-wrap items-center gap-3 sm:gap-4\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"p-2 min-h-[44px] min-w-[44px] hover:bg-accent rounded-md\"\n aria-label={tr('tourBuilder.goBack')}\n >\n <ArrowLeft size={20} />\n </button>\n <div className=\"flex-1 min-w-[12rem]\">\n <h1 className=\"text-base sm:text-lg font-semibold truncate\">\n {tour?.name} - {tr('tourPreview.previewSuffix')}\n </h1>\n {isPreviewActive && (\n <p className=\"text-sm text-text-secondary\">\n {tr('tourPreview.stepOf')} {currentStepIndex + 1} {tr('tourPreview.stepOfConnector')}{' '}\n {totalSteps}\n </p>\n )}\n </div>\n\n {/* Device Selector */}\n <div className=\"flex gap-2 border border-border-subtle rounded-md overflow-hidden\">\n {(['mobile', 'tablet', 'desktop'] as const).map((device) => (\n <button\n type=\"button\"\n key={device}\n onClick={() => changeDevice(device)}\n className={`px-3 py-2 min-h-[44px] min-w-[44px] ${\n devicePreview === device\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-surface hover:bg-accent'\n }`}\n title={\n device === 'mobile'\n ? tr('tourPreview.deviceMobile')\n : device === 'tablet'\n ? tr('tourPreview.deviceTablet')\n : tr('tourPreview.deviceDesktop')\n }\n aria-label={\n device === 'mobile'\n ? tr('tourPreview.deviceMobile')\n : device === 'tablet'\n ? tr('tourPreview.deviceTablet')\n : tr('tourPreview.deviceDesktop')\n }\n >\n {deviceIcons[device]}\n </button>\n ))}\n </div>\n\n {/* Preview Controls */}\n {!isPreviewActive ? (\n <Button\n type=\"button\"\n onClick={startPreview}\n disabled={!validationResults?.valid}\n className=\"min-h-[44px]\"\n >\n {tr('tourPreview.startPreview')}\n </Button>\n ) : (\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={stopPreview}\n className=\"min-h-[44px]\"\n >\n <X size={20} />\n {tr('tourPreview.stopPreview')}\n </Button>\n )}\n </div>\n\n <div className=\"px-3 sm:px-6 pt-3\">\n <PagePurpose>{tr('tourPreview.purpose')}</PagePurpose>\n </div>\n\n {/* Validation Results */}\n {validationResults && !validationResults.valid && (\n <div className=\"bg-status-error-bg/10 border-b border-status-error-border px-3 sm:px-6 py-3\">\n <div className=\"flex items-start gap-3\">\n <AlertCircle className=\"text-status-error-text flex-shrink-0 mt-0.5\" size={20} />\n <div className=\"flex-1\">\n <h3 className=\"font-semibold text-status-error-text mb-1\">\n {tr('tourPreview.validationErrorsTitle')}\n </h3>\n <ul className=\"list-disc list-inside space-y-1\">\n {validationResults.errors.map((error) => (\n <li key={error} className=\"text-sm text-status-error-text\">\n {error}\n </li>\n ))}\n </ul>\n </div>\n </div>\n </div>\n )}\n\n {/* Warnings */}\n {validationResults && validationResults.warnings.length > 0 && (\n <div className=\"bg-warning/10 border-b border-warning px-3 sm:px-6 py-3\">\n <div className=\"flex items-start gap-3\">\n <AlertCircle className=\"text-warning flex-shrink-0 mt-0.5\" size={20} />\n <div className=\"flex-1\">\n <h3 className=\"font-semibold text-warning mb-1\">{tr('tourPreview.warningsTitle')}</h3>\n <ul className=\"list-disc list-inside space-y-1\">\n {validationResults.warnings.map((warning) => (\n <li key={warning} className=\"text-sm text-warning\">\n {warning}\n </li>\n ))}\n </ul>\n </div>\n </div>\n </div>\n )}\n\n {/* Preview Area */}\n <div className=\"flex-1 flex items-center justify-center p-3 sm:p-6 overflow-auto\">\n <div\n className={`bg-bg-surface border-2 rounded-lg shadow-xl overflow-hidden ${\n devicePreview === 'mobile'\n ? 'w-[min(375px,calc(100vw-1.5rem))] h-[667px] max-h-full'\n : devicePreview === 'tablet'\n ? 'w-[min(768px,calc(100vw-1.5rem))] h-[1024px] max-h-full'\n : 'w-full max-w-[1920px] h-full max-h-[1080px]'\n }`}\n >\n {isPreviewActive && currentStep ? (\n <div className=\"h-full flex flex-col items-center justify-center p-4 sm:p-8\">\n {/* Simulated Tour Tooltip */}\n <GlassCard\n treatment=\"glass\"\n className=\"max-w-md border-border-seam p-4 sm:p-6 shadow-[var(--shadow-pop)]\"\n >\n <h3 className=\"text-lg font-semibold mb-3\">{currentStep.title}</h3>\n <p className=\"text-sm text-text-secondary mb-4 whitespace-pre-wrap\">\n {currentStep.content}\n </p>\n <div className=\"flex gap-2\">\n <button\n type=\"button\"\n onClick={previousStep}\n disabled={!canGoPrevious}\n className=\"px-3 py-2 min-h-[44px] min-w-[44px] border border-border-subtle rounded-md hover:bg-accent disabled:opacity-50 disabled:cursor-not-allowed\"\n aria-label={tr('tourPreview.previous')}\n >\n <ChevronLeft size={16} />\n </button>\n <button\n type=\"button\"\n onClick={nextStep}\n disabled={!canGoNext}\n className=\"flex-1 px-3 py-2 min-h-[44px] bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg/90 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {canGoNext ? tr('tourPreview.next') : tr('tourPreview.finish')}\n </button>\n </div>\n </GlassCard>\n </div>\n ) : (\n <div className=\"h-full flex items-center justify-center p-4\">\n <IllustratedEmptyState\n illustration=\"onboarding\"\n title={tr('tourPreview.readyTitle')}\n description={tr('tourPreview.readyHint')}\n />\n </div>\n )}\n </div>\n </div>\n\n {/* Footer Controls */}\n {isPreviewActive && (\n <div className=\"border-t border-border-subtle bg-bg-surface p-3 sm:p-4 flex items-center justify-center gap-3 sm:gap-4\">\n <button\n type=\"button\"\n onClick={previousStep}\n disabled={!canGoPrevious}\n className=\"px-4 py-2 min-h-[44px] border border-border-subtle rounded-md hover:bg-accent disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2\"\n >\n <ChevronLeft size={20} />\n {tr('tourPreview.previous')}\n </button>\n <div className=\"text-sm text-text-secondary\">\n {currentStepIndex + 1} / {totalSteps}\n </div>\n <button\n type=\"button\"\n onClick={nextStep}\n disabled={!canGoNext}\n className=\"px-4 py-2 min-h-[44px] border border-border-subtle rounded-md hover:bg-accent disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2\"\n >\n {tr('tourPreview.nextFooter')}\n <ChevronRight size={20} />\n </button>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TourPreviewPage.js","names":[],"sources":["../../../src/tours/pages/TourPreviewPage.tsx"],"sourcesContent":["import { useEffect } from 'react';\nimport { useParams, useNavigate } from 'react-router-dom';\nimport {\n ArrowLeft,\n ChevronLeft,\n ChevronRight,\n X,\n Smartphone,\n Tablet,\n Monitor,\n AlertCircle,\n} from 'lucide-react';\nimport { Markdown } from '@burdenoff/fe-libs/shared/components';\nimport { Button, GlassCard, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { useTourPreview } from '../hooks/useTourPreview';\nimport { useTourBuilder } from '../hooks/useTourBuilder';\nimport { useToursPermissionAccess } from '../hooks/useToursPermissionAccess';\nimport { useToursContext } from '../providers/ToursProvider';\nimport { useToursStore } from '../store/toursStore';\nimport { TOUR_PERMISSIONS } from '../../constants/permissions';\nimport { useToursI18n } from '../i18n';\n\n/**\n * Tour preview page\n * Preview tour with device simulation and validation\n */\nexport function TourPreviewPage() {\n const { tr } = useToursI18n();\n const { tourId } = useParams();\n const navigate = useNavigate();\n const { basePath = '/' } = useToursContext();\n const { hasPermission } = useToursPermissionAccess();\n const canReadTour = hasPermission(TOUR_PERMISSIONS.TOUR_READ);\n const { tour, loadTour } = useTourBuilder(tourId);\n const { devicePreview } = useToursStore();\n\n const {\n isPreviewActive,\n currentStepIndex,\n currentStep,\n totalSteps,\n canGoNext,\n canGoPrevious,\n validationResults,\n startPreview,\n stopPreview,\n nextStep,\n previousStep,\n changeDevice,\n validateForPreview,\n } = useTourPreview(tour || undefined);\n\n useEffect(() => {\n if (tourId) {\n loadTour(tourId);\n }\n }, [tourId, loadTour]);\n\n useEffect(() => {\n if (tour) {\n validateForPreview();\n }\n }, [tour, devicePreview, validateForPreview]);\n\n if (!canReadTour) {\n return (\n <div className=\"flex items-center justify-center h-screen bg-bg-sunken\">\n <div className=\"text-center\">\n <h2 className=\"text-lg font-semibold text-text-primary mb-2\">\n {tr('tourPreview.accessDeniedTitle')}\n </h2>\n <p className=\"text-sm text-text-secondary\">{tr('tourPreview.accessDeniedMessage')}</p>\n </div>\n </div>\n );\n }\n\n if (!tour) {\n return (\n <div className=\"flex items-center justify-center h-screen bg-bg-sunken\">\n <p className=\"text-text-secondary\">{tr('tourPreview.loading')}</p>\n </div>\n );\n }\n\n const handleBack = () => {\n navigate(`${basePath}/${tourId}/edit`);\n };\n\n const deviceIcons = {\n mobile: <Smartphone size={20} />,\n tablet: <Tablet size={20} />,\n desktop: <Monitor size={20} />,\n };\n\n return (\n <div className=\"flex flex-col h-screen bg-bg-sunken\">\n {/* Header */}\n <div className=\"border-b border-border-subtle bg-bg-surface p-3 sm:p-4 flex flex-wrap items-center gap-3 sm:gap-4\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"p-2 min-h-[44px] min-w-[44px] hover:bg-accent rounded-md\"\n aria-label={tr('tourBuilder.goBack')}\n >\n <ArrowLeft size={20} />\n </button>\n <div className=\"flex-1 min-w-[12rem]\">\n <h1 className=\"text-base sm:text-lg font-semibold truncate\">\n {tour?.name} - {tr('tourPreview.previewSuffix')}\n </h1>\n {isPreviewActive && (\n <p className=\"text-sm text-text-secondary\">\n {tr('tourPreview.stepOf')} {currentStepIndex + 1} {tr('tourPreview.stepOfConnector')}{' '}\n {totalSteps}\n </p>\n )}\n </div>\n\n {/* Device Selector */}\n <div className=\"flex gap-2 border border-border-subtle rounded-md overflow-hidden\">\n {(['mobile', 'tablet', 'desktop'] as const).map((device) => (\n <button\n type=\"button\"\n key={device}\n onClick={() => changeDevice(device)}\n className={`px-3 py-2 min-h-[44px] min-w-[44px] ${\n devicePreview === device\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-surface hover:bg-accent'\n }`}\n title={\n device === 'mobile'\n ? tr('tourPreview.deviceMobile')\n : device === 'tablet'\n ? tr('tourPreview.deviceTablet')\n : tr('tourPreview.deviceDesktop')\n }\n aria-label={\n device === 'mobile'\n ? tr('tourPreview.deviceMobile')\n : device === 'tablet'\n ? tr('tourPreview.deviceTablet')\n : tr('tourPreview.deviceDesktop')\n }\n >\n {deviceIcons[device]}\n </button>\n ))}\n </div>\n\n {/* Preview Controls */}\n {!isPreviewActive ? (\n <Button\n type=\"button\"\n onClick={startPreview}\n disabled={!validationResults?.valid}\n className=\"min-h-[44px]\"\n >\n {tr('tourPreview.startPreview')}\n </Button>\n ) : (\n <Button type=\"button\" variant=\"outline\" onClick={stopPreview} className=\"min-h-[44px]\">\n <X size={20} />\n {tr('tourPreview.stopPreview')}\n </Button>\n )}\n </div>\n\n <div className=\"px-3 sm:px-6 pt-3\">\n <PagePurpose>{tr('tourPreview.purpose')}</PagePurpose>\n </div>\n\n {/* Validation Results */}\n {validationResults && !validationResults.valid && (\n <div className=\"bg-status-error-bg/10 border-b border-status-error-border px-3 sm:px-6 py-3\">\n <div className=\"flex items-start gap-3\">\n <AlertCircle className=\"text-status-error-text flex-shrink-0 mt-0.5\" size={20} />\n <div className=\"flex-1\">\n <h3 className=\"font-semibold text-status-error-text mb-1\">\n {tr('tourPreview.validationErrorsTitle')}\n </h3>\n <ul className=\"list-disc list-inside space-y-1\">\n {validationResults.errors.map((error) => (\n <li key={error} className=\"text-sm text-status-error-text\">\n {error}\n </li>\n ))}\n </ul>\n </div>\n </div>\n </div>\n )}\n\n {/* Warnings */}\n {validationResults && validationResults.warnings.length > 0 && (\n <div className=\"bg-warning/10 border-b border-warning px-3 sm:px-6 py-3\">\n <div className=\"flex items-start gap-3\">\n <AlertCircle className=\"text-warning flex-shrink-0 mt-0.5\" size={20} />\n <div className=\"flex-1\">\n <h3 className=\"font-semibold text-warning mb-1\">{tr('tourPreview.warningsTitle')}</h3>\n <ul className=\"list-disc list-inside space-y-1\">\n {validationResults.warnings.map((warning) => (\n <li key={warning} className=\"text-sm text-warning\">\n {warning}\n </li>\n ))}\n </ul>\n </div>\n </div>\n </div>\n )}\n\n {/* Preview Area */}\n <div className=\"flex-1 flex items-center justify-center p-3 sm:p-6 overflow-auto\">\n <div\n className={`bg-bg-surface border-2 rounded-lg shadow-xl overflow-hidden ${\n devicePreview === 'mobile'\n ? 'w-[min(375px,calc(100vw-1.5rem))] h-[667px] max-h-full'\n : devicePreview === 'tablet'\n ? 'w-[min(768px,calc(100vw-1.5rem))] h-[1024px] max-h-full'\n : 'w-full max-w-[1920px] h-full max-h-[1080px]'\n }`}\n >\n {isPreviewActive && currentStep ? (\n <div className=\"h-full flex flex-col items-center justify-center p-4 sm:p-8\">\n {/* Simulated Tour Tooltip */}\n <GlassCard\n treatment=\"glass\"\n className=\"max-w-md border-border-seam p-4 sm:p-6 shadow-[var(--shadow-pop)]\"\n >\n <h3 className=\"text-lg font-semibold mb-3\">{currentStep.title}</h3>\n <div className=\"text-sm text-text-secondary mb-4 prose prose-sm max-w-none\">\n <Markdown>{currentStep.content}</Markdown>\n </div>\n <div className=\"flex gap-2\">\n <button\n type=\"button\"\n onClick={previousStep}\n disabled={!canGoPrevious}\n className=\"px-3 py-2 min-h-[44px] min-w-[44px] border border-border-subtle rounded-md hover:bg-accent disabled:opacity-50 disabled:cursor-not-allowed\"\n aria-label={tr('tourPreview.previous')}\n >\n <ChevronLeft size={16} />\n </button>\n <button\n type=\"button\"\n onClick={nextStep}\n disabled={!canGoNext}\n className=\"flex-1 px-3 py-2 min-h-[44px] bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg/90 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {canGoNext ? tr('tourPreview.next') : tr('tourPreview.finish')}\n </button>\n </div>\n </GlassCard>\n </div>\n ) : (\n <div className=\"h-full flex items-center justify-center p-4\">\n <IllustratedEmptyState\n illustration=\"onboarding\"\n title={tr('tourPreview.readyTitle')}\n description={tr('tourPreview.readyHint')}\n />\n </div>\n )}\n </div>\n </div>\n\n {/* Footer Controls */}\n {isPreviewActive && (\n <div className=\"border-t border-border-subtle bg-bg-surface p-3 sm:p-4 flex items-center justify-center gap-3 sm:gap-4\">\n <button\n type=\"button\"\n onClick={previousStep}\n disabled={!canGoPrevious}\n className=\"px-4 py-2 min-h-[44px] border border-border-subtle rounded-md hover:bg-accent disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2\"\n >\n <ChevronLeft size={20} />\n {tr('tourPreview.previous')}\n </button>\n <div className=\"text-sm text-text-secondary\">\n {currentStepIndex + 1} / {totalSteps}\n </div>\n <button\n type=\"button\"\n onClick={nextStep}\n disabled={!canGoNext}\n className=\"px-4 py-2 min-h-[44px] border border-border-subtle rounded-md hover:bg-accent disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2\"\n >\n {tr('tourPreview.nextFooter')}\n <ChevronRight size={20} />\n </button>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|