@burdenoff/microfe-tours 2026.510.112

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.
Files changed (164) hide show
  1. package/README.md +342 -0
  2. package/dist/__tests__/setup.d.ts +2 -0
  3. package/dist/__tests__/setup.d.ts.map +1 -0
  4. package/dist/constants/featureFlags.d.ts +25 -0
  5. package/dist/constants/featureFlags.d.ts.map +1 -0
  6. package/dist/constants/featureFlags.js +9 -0
  7. package/dist/constants/featureFlags.js.map +1 -0
  8. package/dist/constants/permissions.d.ts +49 -0
  9. package/dist/constants/permissions.d.ts.map +1 -0
  10. package/dist/constants/permissions.js +38 -0
  11. package/dist/constants/permissions.js.map +1 -0
  12. package/dist/dev/main.d.ts +2 -0
  13. package/dist/dev/main.d.ts.map +1 -0
  14. package/dist/generated/global-operations.d.ts +1270 -0
  15. package/dist/generated/global-operations.d.ts.map +1 -0
  16. package/dist/generated/global-operations.js +650 -0
  17. package/dist/generated/global-operations.js.map +1 -0
  18. package/dist/generated/global-types.d.ts +20448 -0
  19. package/dist/generated/global-types.d.ts.map +1 -0
  20. package/dist/generated/wspace-operations.d.ts +2 -0
  21. package/dist/generated/wspace-operations.d.ts.map +1 -0
  22. package/dist/generated/wspace-types.d.ts +53398 -0
  23. package/dist/generated/wspace-types.d.ts.map +1 -0
  24. package/dist/index.d.ts +6 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +6 -0
  27. package/dist/tours/ToursAdminRoot.d.ts +16 -0
  28. package/dist/tours/ToursAdminRoot.d.ts.map +1 -0
  29. package/dist/tours/ToursAdminRoot.js +42 -0
  30. package/dist/tours/ToursAdminRoot.js.map +1 -0
  31. package/dist/tours/ToursAdminRoutes.d.ts +12 -0
  32. package/dist/tours/ToursAdminRoutes.d.ts.map +1 -0
  33. package/dist/tours/ToursAdminRoutes.js +109 -0
  34. package/dist/tours/ToursAdminRoutes.js.map +1 -0
  35. package/dist/tours/ToursRoot.d.ts +10 -0
  36. package/dist/tours/ToursRoot.d.ts.map +1 -0
  37. package/dist/tours/ToursRoot.js +1 -0
  38. package/dist/tours/ToursRoutes.d.ts +8 -0
  39. package/dist/tours/ToursRoutes.d.ts.map +1 -0
  40. package/dist/tours/ToursUserRoot.d.ts +15 -0
  41. package/dist/tours/ToursUserRoot.d.ts.map +1 -0
  42. package/dist/tours/ToursUserRoot.js +48 -0
  43. package/dist/tours/ToursUserRoot.js.map +1 -0
  44. package/dist/tours/ToursUserRoutes.d.ts +15 -0
  45. package/dist/tours/ToursUserRoutes.d.ts.map +1 -0
  46. package/dist/tours/ToursUserRoutes.js +66 -0
  47. package/dist/tours/ToursUserRoutes.js.map +1 -0
  48. package/dist/tours/components/RouteHelpers.d.ts +33 -0
  49. package/dist/tours/components/RouteHelpers.d.ts.map +1 -0
  50. package/dist/tours/components/RouteHelpers.js +75 -0
  51. package/dist/tours/components/RouteHelpers.js.map +1 -0
  52. package/dist/tours/components/ToursAdminNavRegistrar.d.ts +25 -0
  53. package/dist/tours/components/ToursAdminNavRegistrar.d.ts.map +1 -0
  54. package/dist/tours/components/ToursAdminNavRegistrar.js +60 -0
  55. package/dist/tours/components/ToursAdminNavRegistrar.js.map +1 -0
  56. package/dist/tours/components/ui.d.ts +2 -0
  57. package/dist/tours/components/ui.d.ts.map +1 -0
  58. package/dist/tours/hooks/useMediaLibrary.d.ts +22 -0
  59. package/dist/tours/hooks/useMediaLibrary.d.ts.map +1 -0
  60. package/dist/tours/hooks/useMediaLibrary.js +82 -0
  61. package/dist/tours/hooks/useMediaLibrary.js.map +1 -0
  62. package/dist/tours/hooks/useStepSequencer.d.ts +20 -0
  63. package/dist/tours/hooks/useStepSequencer.d.ts.map +1 -0
  64. package/dist/tours/hooks/useStepSequencer.js +53 -0
  65. package/dist/tours/hooks/useStepSequencer.js.map +1 -0
  66. package/dist/tours/hooks/useTourAnalytics.d.ts +32 -0
  67. package/dist/tours/hooks/useTourAnalytics.d.ts.map +1 -0
  68. package/dist/tours/hooks/useTourAnalytics.js +70 -0
  69. package/dist/tours/hooks/useTourAnalytics.js.map +1 -0
  70. package/dist/tours/hooks/useTourBuilder.d.ts +61 -0
  71. package/dist/tours/hooks/useTourBuilder.d.ts.map +1 -0
  72. package/dist/tours/hooks/useTourBuilder.js +192 -0
  73. package/dist/tours/hooks/useTourBuilder.js.map +1 -0
  74. package/dist/tours/hooks/useTourLifecycle.d.ts +22 -0
  75. package/dist/tours/hooks/useTourLifecycle.d.ts.map +1 -0
  76. package/dist/tours/hooks/useTourLifecycle.js +28 -0
  77. package/dist/tours/hooks/useTourLifecycle.js.map +1 -0
  78. package/dist/tours/hooks/useTourPreview.d.ts +33 -0
  79. package/dist/tours/hooks/useTourPreview.d.ts.map +1 -0
  80. package/dist/tours/hooks/useTourPreview.js +70 -0
  81. package/dist/tours/hooks/useTourPreview.js.map +1 -0
  82. package/dist/tours/hooks/useToursList.d.ts +30 -0
  83. package/dist/tours/hooks/useToursList.d.ts.map +1 -0
  84. package/dist/tours/hooks/useToursList.js +49 -0
  85. package/dist/tours/hooks/useToursList.js.map +1 -0
  86. package/dist/tours/hooks/useToursPermissionAccess.d.ts +16 -0
  87. package/dist/tours/hooks/useToursPermissionAccess.d.ts.map +1 -0
  88. package/dist/tours/hooks/useToursPermissionAccess.js +9 -0
  89. package/dist/tours/hooks/useToursPermissionAccess.js.map +1 -0
  90. package/dist/tours/i18n.d.ts +172 -0
  91. package/dist/tours/i18n.d.ts.map +1 -0
  92. package/dist/tours/i18n.js +175 -0
  93. package/dist/tours/i18n.js.map +1 -0
  94. package/dist/tours/index.d.ts +21 -0
  95. package/dist/tours/index.d.ts.map +1 -0
  96. package/dist/tours/index.js +5 -0
  97. package/dist/tours/pages/AnalyticsDashboardPage.d.ts +6 -0
  98. package/dist/tours/pages/AnalyticsDashboardPage.d.ts.map +1 -0
  99. package/dist/tours/pages/AnalyticsDashboardPage.js +230 -0
  100. package/dist/tours/pages/AnalyticsDashboardPage.js.map +1 -0
  101. package/dist/tours/pages/MediaLibraryPage.d.ts +6 -0
  102. package/dist/tours/pages/MediaLibraryPage.d.ts.map +1 -0
  103. package/dist/tours/pages/MediaLibraryPage.js +195 -0
  104. package/dist/tours/pages/MediaLibraryPage.js.map +1 -0
  105. package/dist/tours/pages/MyToursPage.d.ts +11 -0
  106. package/dist/tours/pages/MyToursPage.d.ts.map +1 -0
  107. package/dist/tours/pages/MyToursPage.js +103 -0
  108. package/dist/tours/pages/MyToursPage.js.map +1 -0
  109. package/dist/tours/pages/MyToursProgressPage.d.ts +6 -0
  110. package/dist/tours/pages/MyToursProgressPage.d.ts.map +1 -0
  111. package/dist/tours/pages/MyToursProgressPage.js +142 -0
  112. package/dist/tours/pages/MyToursProgressPage.js.map +1 -0
  113. package/dist/tours/pages/SchedulerPage.d.ts +6 -0
  114. package/dist/tours/pages/SchedulerPage.d.ts.map +1 -0
  115. package/dist/tours/pages/SchedulerPage.js +231 -0
  116. package/dist/tours/pages/SchedulerPage.js.map +1 -0
  117. package/dist/tours/pages/StepEditorPage.d.ts +7 -0
  118. package/dist/tours/pages/StepEditorPage.d.ts.map +1 -0
  119. package/dist/tours/pages/StepEditorPage.js +586 -0
  120. package/dist/tours/pages/StepEditorPage.js.map +1 -0
  121. package/dist/tours/pages/SystemAnalyticsPage.d.ts +6 -0
  122. package/dist/tours/pages/SystemAnalyticsPage.d.ts.map +1 -0
  123. package/dist/tours/pages/SystemAnalyticsPage.js +155 -0
  124. package/dist/tours/pages/SystemAnalyticsPage.js.map +1 -0
  125. package/dist/tours/pages/TemplateLibraryPage.d.ts +6 -0
  126. package/dist/tours/pages/TemplateLibraryPage.d.ts.map +1 -0
  127. package/dist/tours/pages/TemplateLibraryPage.js +207 -0
  128. package/dist/tours/pages/TemplateLibraryPage.js.map +1 -0
  129. package/dist/tours/pages/TourBuilderPage.d.ts +6 -0
  130. package/dist/tours/pages/TourBuilderPage.d.ts.map +1 -0
  131. package/dist/tours/pages/TourBuilderPage.js +363 -0
  132. package/dist/tours/pages/TourBuilderPage.js.map +1 -0
  133. package/dist/tours/pages/TourPreviewPage.d.ts +6 -0
  134. package/dist/tours/pages/TourPreviewPage.d.ts.map +1 -0
  135. package/dist/tours/pages/TourPreviewPage.js +239 -0
  136. package/dist/tours/pages/TourPreviewPage.js.map +1 -0
  137. package/dist/tours/pages/ToursListPage.d.ts +6 -0
  138. package/dist/tours/pages/ToursListPage.d.ts.map +1 -0
  139. package/dist/tours/pages/ToursListPage.js +310 -0
  140. package/dist/tours/pages/ToursListPage.js.map +1 -0
  141. package/dist/tours/providers/ToursProvider.d.ts +27 -0
  142. package/dist/tours/providers/ToursProvider.d.ts.map +1 -0
  143. package/dist/tours/providers/ToursProvider.js +28 -0
  144. package/dist/tours/providers/ToursProvider.js.map +1 -0
  145. package/dist/tours/store/toursStore.d.ts +39 -0
  146. package/dist/tours/store/toursStore.d.ts.map +1 -0
  147. package/dist/tours/store/toursStore.js +143 -0
  148. package/dist/tours/store/toursStore.js.map +1 -0
  149. package/dist/tours/types/index.d.ts +350 -0
  150. package/dist/tours/types/index.d.ts.map +1 -0
  151. package/dist/tours/utils/cn.d.ts +8 -0
  152. package/dist/tours/utils/cn.d.ts.map +1 -0
  153. package/dist/tours/utils/index.d.ts +102 -0
  154. package/dist/tours/utils/index.d.ts.map +1 -0
  155. package/dist/tours/utils/index.js +28 -0
  156. package/dist/tours/utils/index.js.map +1 -0
  157. package/dist/tours/utils/joinPath.d.ts +9 -0
  158. package/dist/tours/utils/joinPath.d.ts.map +1 -0
  159. package/dist/tours/utils/joinPath.js +8 -0
  160. package/dist/tours/utils/joinPath.js.map +1 -0
  161. package/dist/utils/nativeBridge.d.ts +3 -0
  162. package/dist/utils/nativeBridge.d.ts.map +1 -0
  163. package/dist/utils/nativeBridge.js +2 -0
  164. package/package.json +114 -0
@@ -0,0 +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 CheckCircle,\n AlertCircle,\n} from 'lucide-react';\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-muted\">\n <div className=\"text-center\">\n <h2 className=\"text-lg font-semibold text-foreground mb-2\">\n {tr('tourPreview.accessDeniedTitle')}\n </h2>\n <p className=\"text-sm text-muted-foreground\">{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-muted\">\n <p className=\"text-muted-foreground\">{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-muted\">\n {/* Header */}\n <div className=\"border-b border-border bg-background p-4 flex items-center gap-4\">\n <button onClick={handleBack} className=\"p-2 hover:bg-accent rounded-md\">\n <ArrowLeft size={20} />\n </button>\n <div className=\"flex-1\">\n <h1 className=\"text-lg font-semibold\">\n {tour?.name} - {tr('tourPreview.previewSuffix')}\n </h1>\n {isPreviewActive && (\n <p className=\"text-sm text-muted-foreground\">\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 rounded-md overflow-hidden\">\n {(['mobile', 'tablet', 'desktop'] as const).map((device) => (\n <button\n key={device}\n onClick={() => changeDevice(device)}\n className={`px-3 py-2 ${\n devicePreview === device\n ? 'bg-primary text-primary-foreground'\n : 'bg-background 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 onClick={startPreview}\n disabled={!validationResults?.valid}\n className=\"px-4 py-2 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 disabled:opacity-50\"\n >\n {tr('tourPreview.startPreview')}\n </button>\n ) : (\n <button\n onClick={stopPreview}\n className=\"px-4 py-2 border border-border rounded-md hover:bg-accent flex items-center gap-2\"\n >\n <X size={20} />\n {tr('tourPreview.stopPreview')}\n </button>\n )}\n </div>\n\n {/* Validation Results */}\n {validationResults && !validationResults.valid && (\n <div className=\"bg-destructive/10 border-b border-destructive px-6 py-3\">\n <div className=\"flex items-start gap-3\">\n <AlertCircle className=\"text-destructive flex-shrink-0 mt-0.5\" size={20} />\n <div className=\"flex-1\">\n <h3 className=\"font-semibold text-destructive mb-1\">\n {tr('tourPreview.validationErrorsTitle')}\n </h3>\n <ul className=\"list-disc list-inside space-y-1\">\n {validationResults.errors.map((error, index) => (\n <li key={index} className=\"text-sm text-destructive\">\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-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, index) => (\n <li key={index} 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-6 overflow-auto\">\n <div\n className={`bg-background border-2 rounded-lg shadow-xl overflow-hidden ${\n devicePreview === 'mobile'\n ? 'w-[375px] h-[667px]'\n : devicePreview === 'tablet'\n ? 'w-[768px] h-[1024px]'\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-8\">\n {/* Simulated Tour Tooltip */}\n <div className=\"max-w-md border border-border rounded-lg shadow-lg bg-card p-6\">\n <h3 className=\"text-lg font-semibold mb-3\">{currentStep.title}</h3>\n <p className=\"text-sm text-muted-foreground mb-4 whitespace-pre-wrap\">\n {currentStep.content}\n </p>\n <div className=\"flex gap-2\">\n <button\n onClick={previousStep}\n disabled={!canGoPrevious}\n className=\"px-3 py-1 border border-border rounded-md hover:bg-accent disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n <ChevronLeft size={16} />\n </button>\n <button\n onClick={nextStep}\n disabled={!canGoNext}\n className=\"flex-1 px-3 py-1 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {canGoNext ? tr('tourPreview.next') : tr('tourPreview.finish')}\n </button>\n </div>\n </div>\n </div>\n ) : (\n <div className=\"h-full flex items-center justify-center text-muted-foreground\">\n <div className=\"text-center\">\n <CheckCircle className=\"mx-auto mb-4\" size={48} />\n <p className=\"mb-2\">{tr('tourPreview.readyTitle')}</p>\n <p className=\"text-sm\">{tr('tourPreview.readyHint')}</p>\n </div>\n </div>\n )}\n </div>\n </div>\n\n {/* Footer Controls */}\n {isPreviewActive && (\n <div className=\"border-t border-border bg-background p-4 flex items-center justify-center gap-4\">\n <button\n onClick={previousStep}\n disabled={!canGoPrevious}\n className=\"px-4 py-2 border border-border 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-muted-foreground\">\n {currentStepIndex + 1} / {totalSteps}\n </div>\n <button\n onClick={nextStep}\n disabled={!canGoNext}\n className=\"px-4 py-2 border border-border 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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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Tours list page
3
+ * Displays all tours with filtering and search
4
+ */
5
+ export declare function ToursListPage(): import("react/jsx-runtime").JSX.Element;
6
+ //# sourceMappingURL=ToursListPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToursListPage.d.ts","sourceRoot":"","sources":["../../../src/tours/pages/ToursListPage.tsx"],"names":[],"mappings":"AA+BA;;;GAGG;AACH,wBAAgB,aAAa,4CA6a5B"}
@@ -0,0 +1,310 @@
1
+ import { useToursContext as e } from "../providers/ToursProvider.js";
2
+ import { useDeleteTourMutation as t } from "../../generated/global-operations.js";
3
+ import { useToursList as n } from "../hooks/useToursList.js";
4
+ import { useTourLifecycle as r } from "../hooks/useTourLifecycle.js";
5
+ import { useToursPermissionAccess as i } from "../hooks/useToursPermissionAccess.js";
6
+ import { useToursStore as a } from "../store/toursStore.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, useRef as m, useState as h } from "react";
11
+ import { PermissionGate as g } from "@burdenoff/fe-libs/shared/components";
12
+ import { Eye as _, Grid as ee, List as v, ListOrdered as y, MoreVertical as b, Plus as te, Search as ne, Settings as re } from "lucide-react";
13
+ import { jsx as x, jsxs as S } from "react/jsx-runtime";
14
+ import { useNavigate as C } from "react-router-dom";
15
+ //#region src/tours/pages/ToursListPage.tsx
16
+ function w() {
17
+ let { tr: w } = s(), T = C(), { basePath: E = "/" } = e(), { viewMode: D, tourFilter: O, setViewMode: k, updateTourFilter: A } = a(), { hasPermission: j, isLoading: M } = i(), N = j(o.TOUR_UPDATE), P = j(o.TOUR_STEP_UPDATE), F = j(o.TOUR_DELETE), I = j(o.TOUR_PUBLISH), L = j(o.TOUR_ARCHIVE), R = j(o.TOUR_DUPLICATE), { tours: z, loading: B, fetchTours: V } = n(), { publishTour: H, unpublishTour: U, archiveTour: W, duplicateTour: G } = r(), [K] = t(), [ie, q] = h(""), [J, Y] = h("all"), [X, Z] = h(null), Q = m(null);
18
+ p(() => {
19
+ M || V({ ...O });
20
+ }, [
21
+ V,
22
+ O,
23
+ M
24
+ ]);
25
+ let ae = (e) => {
26
+ q(e), A({ search: e });
27
+ }, oe = (e) => {
28
+ Y(e), A({ status: e });
29
+ }, se = () => {
30
+ T(E.endsWith("/") ? `${E}new` : `${E}/new`);
31
+ }, $ = () => V({ ...O }), ce = (e) => {
32
+ switch (e) {
33
+ case "DRAFT": return w("toursList.statusDraft");
34
+ case "PUBLISHED": return w("toursList.statusPublished");
35
+ case "ARCHIVED": return w("toursList.statusArchived");
36
+ case "SCHEDULED": return w("toursList.statusScheduled");
37
+ }
38
+ }, le = async (e) => {
39
+ Z(null), u("light");
40
+ try {
41
+ await H(e), d("success"), $();
42
+ } catch {
43
+ d("error"), c() ? f(w("toursList.errorPublish")) : alert(w("toursList.errorPublish"));
44
+ }
45
+ }, ue = async (e) => {
46
+ Z(null), u("light");
47
+ try {
48
+ await U(e), d("success"), $();
49
+ } catch {
50
+ d("error"), c() ? f(w("toursList.errorUnpublish")) : alert(w("toursList.errorUnpublish"));
51
+ }
52
+ }, de = async (e) => {
53
+ Z(null), u("light");
54
+ try {
55
+ await W(e), d("success"), $();
56
+ } catch {
57
+ d("error"), c() ? f(w("toursList.errorArchive")) : alert(w("toursList.errorArchive"));
58
+ }
59
+ }, fe = async (e) => {
60
+ Z(null), u("light");
61
+ try {
62
+ await G(e), d("success"), $();
63
+ } catch {
64
+ d("error"), c() ? f(w("toursList.errorDuplicate")) : alert(w("toursList.errorDuplicate"));
65
+ }
66
+ }, pe = async (e) => {
67
+ Z(null), u("medium");
68
+ let t = w("toursList.confirmDelete"), n = await l({
69
+ title: w("toursList.actionDelete"),
70
+ message: t,
71
+ okButtonTitle: w("toursList.actionDelete")
72
+ });
73
+ if (n === null ? window.confirm(t) : n) try {
74
+ await K({ variables: { id: e } }), d("success"), $();
75
+ } catch {
76
+ d("error"), c() ? f(w("toursList.errorDelete")) : alert(w("toursList.errorDelete"));
77
+ }
78
+ };
79
+ return p(() => {
80
+ let e = (e) => {
81
+ Q.current && !Q.current.contains(e.target) && Z(null);
82
+ };
83
+ return X && document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
84
+ }, [X]), /* @__PURE__ */ S("div", {
85
+ className: "space-y-4 sm:space-y-6 p-3 sm:p-6",
86
+ children: [
87
+ /* @__PURE__ */ S("div", {
88
+ className: "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3",
89
+ children: [/* @__PURE__ */ S("div", {
90
+ className: "flex-1 min-w-0",
91
+ children: [/* @__PURE__ */ x("h1", {
92
+ className: "text-xl sm:text-2xl font-bold text-foreground",
93
+ children: w("toursList.title")
94
+ }), /* @__PURE__ */ x("p", {
95
+ className: "text-sm sm:text-base text-muted-foreground",
96
+ children: w("toursList.subtitle")
97
+ })]
98
+ }), /* @__PURE__ */ x(g, {
99
+ permission: o.TOUR_CREATE,
100
+ children: /* @__PURE__ */ S("button", {
101
+ onClick: se,
102
+ className: "w-full sm:w-auto px-4 py-2 min-h-[44px] bg-primary text-primary-foreground rounded-md hover:bg-primary/90 active:bg-primary/80 flex items-center justify-center gap-2",
103
+ children: [/* @__PURE__ */ x(te, { size: 20 }), w("toursList.createTour")]
104
+ })
105
+ })]
106
+ }),
107
+ /* @__PURE__ */ S("div", {
108
+ className: "flex flex-col sm:flex-row gap-3 sm:gap-4",
109
+ children: [/* @__PURE__ */ S("div", {
110
+ className: "flex-1 relative",
111
+ children: [/* @__PURE__ */ x(ne, {
112
+ className: "absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground",
113
+ size: 20
114
+ }), /* @__PURE__ */ x("input", {
115
+ type: "text",
116
+ placeholder: w("toursList.searchPlaceholder"),
117
+ value: ie,
118
+ onChange: (e) => ae(e.target.value),
119
+ className: "w-full pl-[3.25rem] pr-4 py-2 min-h-[44px] border border-border rounded-md bg-background text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
120
+ })]
121
+ }), /* @__PURE__ */ S("div", {
122
+ className: "flex gap-2",
123
+ children: [/* @__PURE__ */ S("select", {
124
+ value: J,
125
+ onChange: (e) => oe(e.target.value),
126
+ className: "px-4 py-2 min-h-[44px] border border-border rounded-md bg-background text-foreground",
127
+ children: [
128
+ /* @__PURE__ */ x("option", {
129
+ value: "all",
130
+ children: w("toursList.statusAll")
131
+ }),
132
+ /* @__PURE__ */ x("option", {
133
+ value: "DRAFT",
134
+ children: w("toursList.statusDraft")
135
+ }),
136
+ /* @__PURE__ */ x("option", {
137
+ value: "PUBLISHED",
138
+ children: w("toursList.statusPublished")
139
+ }),
140
+ /* @__PURE__ */ x("option", {
141
+ value: "ARCHIVED",
142
+ children: w("toursList.statusArchived")
143
+ }),
144
+ /* @__PURE__ */ x("option", {
145
+ value: "SCHEDULED",
146
+ children: w("toursList.statusScheduled")
147
+ })
148
+ ]
149
+ }), /* @__PURE__ */ S("div", {
150
+ className: "flex border border-border rounded-md overflow-hidden",
151
+ children: [/* @__PURE__ */ x("button", {
152
+ onClick: () => k("grid"),
153
+ className: `px-3 py-2 min-h-[44px] ${D === "grid" ? "bg-primary text-primary-foreground" : "bg-background text-foreground hover:bg-accent"}`,
154
+ "aria-label": w("toursList.gridView"),
155
+ title: w("toursList.gridView"),
156
+ children: /* @__PURE__ */ x(ee, { size: 20 })
157
+ }), /* @__PURE__ */ x("button", {
158
+ onClick: () => k("list"),
159
+ className: `px-3 py-2 min-h-[44px] ${D === "list" ? "bg-primary text-primary-foreground" : "bg-background text-foreground hover:bg-accent"}`,
160
+ "aria-label": w("toursList.listView"),
161
+ title: w("toursList.listView"),
162
+ children: /* @__PURE__ */ x(v, { size: 20 })
163
+ })]
164
+ })]
165
+ })]
166
+ }),
167
+ B ? /* @__PURE__ */ x("div", {
168
+ className: "text-center py-12",
169
+ children: /* @__PURE__ */ x("p", {
170
+ className: "text-sm sm:text-base text-muted-foreground",
171
+ children: w("toursList.loading")
172
+ })
173
+ }) : z.length > 0 ? /* @__PURE__ */ x("div", {
174
+ className: D === "grid" ? "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 sm:gap-4" : "space-y-3",
175
+ children: z.map((e) => {
176
+ let t = e.status, n = t === "DRAFT" && I, r = t === "PUBLISHED" && I, i = t !== "ARCHIVED" && L, a = n || r || R || i || F;
177
+ return /* @__PURE__ */ S("div", {
178
+ className: "border border-border rounded-md p-4 bg-card hover:shadow-md transition-shadow",
179
+ children: [
180
+ /* @__PURE__ */ S("div", {
181
+ className: "flex items-start justify-between mb-2",
182
+ children: [/* @__PURE__ */ x("h3", {
183
+ className: `font-semibold text-foreground ${N ? "cursor-pointer hover:text-primary" : ""}`,
184
+ onClick: () => {
185
+ N && T(`${E}/${e.id}/edit`);
186
+ },
187
+ children: e.name
188
+ }), /* @__PURE__ */ x("span", {
189
+ className: `px-2 py-1 text-xs rounded-full ${e.status === "PUBLISHED" ? "bg-success/10 text-success" : e.status === "DRAFT" ? "bg-muted text-muted-foreground" : "bg-warning/10 text-warning"}`,
190
+ children: ce(t)
191
+ })]
192
+ }),
193
+ e.description && /* @__PURE__ */ x("p", {
194
+ className: "text-sm text-muted-foreground mb-3",
195
+ children: e.description
196
+ }),
197
+ /* @__PURE__ */ S("div", {
198
+ className: "flex items-center justify-between text-xs text-muted-foreground mb-3",
199
+ children: [/* @__PURE__ */ S("span", { children: [
200
+ e.steps?.length || 0,
201
+ " ",
202
+ w("toursList.steps")
203
+ ] }), /* @__PURE__ */ S("span", { children: [
204
+ e.viewCount,
205
+ " ",
206
+ w("toursList.views")
207
+ ] })]
208
+ }),
209
+ /* @__PURE__ */ S("div", {
210
+ className: "flex items-center gap-2 pt-3 border-t border-border",
211
+ children: [
212
+ P && /* @__PURE__ */ S("button", {
213
+ onClick: (t) => {
214
+ t.stopPropagation(), T(`${E}/${e.id}/steps`);
215
+ },
216
+ className: "flex-1 px-3 py-1.5 text-xs bg-secondary text-secondary-foreground rounded hover:bg-secondary/80 flex items-center justify-center gap-1.5",
217
+ title: w("toursList.editStepsTitle"),
218
+ children: [/* @__PURE__ */ x(y, { size: 14 }), w("toursList.stepsButton")]
219
+ }),
220
+ /* @__PURE__ */ S("button", {
221
+ onClick: (t) => {
222
+ t.stopPropagation(), T(`${E}/${e.id}/preview`);
223
+ },
224
+ className: "flex-1 px-3 py-1.5 text-xs border border-border rounded hover:bg-accent flex items-center justify-center gap-1.5",
225
+ title: w("toursList.previewTitle"),
226
+ children: [/* @__PURE__ */ x(_, { size: 14 }), w("toursList.previewButton")]
227
+ }),
228
+ N && /* @__PURE__ */ x("button", {
229
+ onClick: (t) => {
230
+ t.stopPropagation(), T(`${E}/${e.id}/edit`);
231
+ },
232
+ className: "px-2 py-1.5 text-xs border border-border rounded hover:bg-accent",
233
+ title: w("toursList.settingsTitle"),
234
+ "aria-label": w("toursList.settingsTitle"),
235
+ children: /* @__PURE__ */ x(re, { size: 14 })
236
+ }),
237
+ a && /* @__PURE__ */ S("div", {
238
+ className: "relative",
239
+ ref: X === e.id ? Q : void 0,
240
+ children: [/* @__PURE__ */ x("button", {
241
+ onClick: (t) => {
242
+ t.stopPropagation(), Z(X === e.id ? null : e.id);
243
+ },
244
+ className: "px-2 py-1.5 text-xs border border-border rounded hover:bg-accent",
245
+ title: w("toursList.moreActionsTitle"),
246
+ "aria-label": w("toursList.moreActionsTitle"),
247
+ children: /* @__PURE__ */ x(b, { size: 14 })
248
+ }), X === e.id && /* @__PURE__ */ S("div", {
249
+ className: "absolute right-0 top-full mt-1 w-40 bg-card border border-border rounded-md shadow-lg z-10",
250
+ children: [
251
+ n && /* @__PURE__ */ x("button", {
252
+ onClick: (t) => {
253
+ t.stopPropagation(), le(e.id);
254
+ },
255
+ className: "w-full text-left px-3 py-2 text-xs hover:bg-accent",
256
+ children: w("toursList.actionPublish")
257
+ }),
258
+ r && /* @__PURE__ */ x("button", {
259
+ onClick: (t) => {
260
+ t.stopPropagation(), ue(e.id);
261
+ },
262
+ className: "w-full text-left px-3 py-2 text-xs hover:bg-accent",
263
+ children: w("toursList.actionUnpublish")
264
+ }),
265
+ R && /* @__PURE__ */ x("button", {
266
+ onClick: (t) => {
267
+ t.stopPropagation(), fe(e.id);
268
+ },
269
+ className: "w-full text-left px-3 py-2 text-xs hover:bg-accent",
270
+ children: w("toursList.actionDuplicate")
271
+ }),
272
+ i && /* @__PURE__ */ x("button", {
273
+ onClick: (t) => {
274
+ t.stopPropagation(), de(e.id);
275
+ },
276
+ className: "w-full text-left px-3 py-2 text-xs hover:bg-accent",
277
+ children: w("toursList.actionArchive")
278
+ }),
279
+ F && /* @__PURE__ */ x("button", {
280
+ onClick: (t) => {
281
+ t.stopPropagation(), pe(e.id);
282
+ },
283
+ className: "w-full text-left px-3 py-2 text-xs text-destructive hover:bg-destructive/10",
284
+ children: w("toursList.actionDelete")
285
+ })
286
+ ]
287
+ })]
288
+ })
289
+ ]
290
+ })
291
+ ]
292
+ }, e.id);
293
+ })
294
+ }) : /* @__PURE__ */ S("div", {
295
+ className: "text-center py-12 border border-dashed border-border rounded-md",
296
+ children: [/* @__PURE__ */ x("p", {
297
+ className: "text-sm sm:text-base text-muted-foreground mb-2",
298
+ children: w("toursList.emptyTitle")
299
+ }), /* @__PURE__ */ x("p", {
300
+ className: "text-xs sm:text-sm text-muted-foreground",
301
+ children: w("toursList.emptySubtitle")
302
+ })]
303
+ })
304
+ ]
305
+ });
306
+ }
307
+ //#endregion
308
+ export { w as ToursListPage };
309
+
310
+ //# sourceMappingURL=ToursListPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToursListPage.js","names":[],"sources":["../../../src/tours/pages/ToursListPage.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport {\n Plus,\n Search,\n Grid,\n List as ListIcon,\n ListOrdered,\n Eye,\n Settings,\n MoreVertical,\n} from 'lucide-react';\nimport { PermissionGate } from '@burdenoff/fe-libs/shared/components';\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 { viewMode, tourFilter, setViewMode, updateTourFilter } = 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 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 const [openMenuId, setOpenMenuId] = useState<string | null>(null);\n const menuRef = useRef<HTMLDivElement>(null);\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, 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 refreshTours = () => fetchTours({ ...tourFilter });\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 setOpenMenuId(null);\n nativeImpact('light');\n try {\n await publishTour(id);\n void nativeNotify('success');\n refreshTours();\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 setOpenMenuId(null);\n nativeImpact('light');\n try {\n await unpublishTour(id);\n void nativeNotify('success');\n refreshTours();\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 setOpenMenuId(null);\n nativeImpact('light');\n try {\n await archiveTour(id);\n void nativeNotify('success');\n refreshTours();\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 setOpenMenuId(null);\n nativeImpact('light');\n try {\n await duplicateTour(id);\n void nativeNotify('success');\n refreshTours();\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 setOpenMenuId(null);\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 void nativeNotify('success');\n refreshTours();\n } catch {\n void nativeNotify('error');\n if (isNative()) void nativeToast(tr('toursList.errorDelete'));\n else alert(tr('toursList.errorDelete'));\n }\n };\n\n // Close dropdown when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(event.target as Node)) {\n setOpenMenuId(null);\n }\n };\n if (openMenuId) {\n document.addEventListener('mousedown', handleClickOutside);\n }\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, [openMenuId]);\n\n return (\n <div className=\"space-y-4 sm:space-y-6 p-3 sm:p-6\">\n {/* Header */}\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3\">\n <div className=\"flex-1 min-w-0\">\n <h1 className=\"text-xl sm:text-2xl font-bold text-foreground\">{tr('toursList.title')}</h1>\n <p className=\"text-sm sm:text-base text-muted-foreground\">{tr('toursList.subtitle')}</p>\n </div>\n <PermissionGate permission={TOUR_PERMISSIONS.TOUR_CREATE}>\n <button\n onClick={handleCreateTour}\n className=\"w-full sm:w-auto px-4 py-2 min-h-[44px] bg-primary text-primary-foreground rounded-md hover:bg-primary/90 active:bg-primary/80 flex items-center justify-center gap-2\"\n >\n <Plus size={20} />\n {tr('toursList.createTour')}\n </button>\n </PermissionGate>\n </div>\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-muted-foreground\"\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 rounded-md bg-background text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring\"\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 rounded-md bg-background text-foreground\"\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 rounded-md overflow-hidden\">\n <button\n onClick={() => setViewMode('grid')}\n className={`px-3 py-2 min-h-[44px] ${\n viewMode === 'grid'\n ? 'bg-primary text-primary-foreground'\n : 'bg-background text-foreground 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 onClick={() => setViewMode('list')}\n className={`px-3 py-2 min-h-[44px] ${\n viewMode === 'list'\n ? 'bg-primary text-primary-foreground'\n : 'bg-background text-foreground 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-muted-foreground\">{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 const hasMoreActions =\n canShowPublishAction ||\n canShowUnpublishAction ||\n canDuplicateTour ||\n canShowArchiveAction ||\n canDeleteTour;\n\n return (\n <div\n key={tour.id}\n className=\"border border-border rounded-md p-4 bg-card hover:shadow-md transition-shadow\"\n >\n <div className=\"flex items-start justify-between mb-2\">\n <h3\n className={`font-semibold text-foreground ${\n canUpdateTour ? 'cursor-pointer hover:text-primary' : ''\n }`}\n onClick={() => {\n if (canUpdateTour) navigate(`${basePath}/${tour.id}/edit`);\n }}\n >\n {tour.name}\n </h3>\n <span\n className={`px-2 py-1 text-xs rounded-full ${\n tour.status === 'PUBLISHED'\n ? 'bg-success/10 text-success'\n : tour.status === 'DRAFT'\n ? 'bg-muted text-muted-foreground'\n : 'bg-warning/10 text-warning'\n }`}\n >\n {getStatusLabel(status)}\n </span>\n </div>\n {tour.description && (\n <p className=\"text-sm text-muted-foreground mb-3\">{tour.description}</p>\n )}\n <div className=\"flex items-center justify-between text-xs text-muted-foreground 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 items-center gap-2 pt-3 border-t border-border\">\n {canUpdateTourSteps && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n navigate(`${basePath}/${tour.id}/steps`);\n }}\n className=\"flex-1 px-3 py-1.5 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 <button\n onClick={(e) => {\n e.stopPropagation();\n navigate(`${basePath}/${tour.id}/preview`);\n }}\n className=\"flex-1 px-3 py-1.5 text-xs border border-border 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 {canUpdateTour && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n navigate(`${basePath}/${tour.id}/edit`);\n }}\n className=\"px-2 py-1.5 text-xs border border-border rounded hover:bg-accent\"\n title={tr('toursList.settingsTitle')}\n aria-label={tr('toursList.settingsTitle')}\n >\n <Settings size={14} />\n </button>\n )}\n {/* More Actions Dropdown */}\n {hasMoreActions && (\n <div className=\"relative\" ref={openMenuId === tour.id ? menuRef : undefined}>\n <button\n onClick={(e) => {\n e.stopPropagation();\n setOpenMenuId(openMenuId === tour.id ? null : tour.id);\n }}\n className=\"px-2 py-1.5 text-xs border border-border rounded hover:bg-accent\"\n title={tr('toursList.moreActionsTitle')}\n aria-label={tr('toursList.moreActionsTitle')}\n >\n <MoreVertical size={14} />\n </button>\n {openMenuId === tour.id && (\n <div className=\"absolute right-0 top-full mt-1 w-40 bg-card border border-border rounded-md shadow-lg z-10\">\n {canShowPublishAction && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n handlePublish(tour.id);\n }}\n className=\"w-full text-left px-3 py-2 text-xs hover:bg-accent\"\n >\n {tr('toursList.actionPublish')}\n </button>\n )}\n {canShowUnpublishAction && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n handleUnpublish(tour.id);\n }}\n className=\"w-full text-left px-3 py-2 text-xs hover:bg-accent\"\n >\n {tr('toursList.actionUnpublish')}\n </button>\n )}\n {canDuplicateTour && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n handleDuplicate(tour.id);\n }}\n className=\"w-full text-left px-3 py-2 text-xs hover:bg-accent\"\n >\n {tr('toursList.actionDuplicate')}\n </button>\n )}\n {canShowArchiveAction && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n handleArchive(tour.id);\n }}\n className=\"w-full text-left px-3 py-2 text-xs hover:bg-accent\"\n >\n {tr('toursList.actionArchive')}\n </button>\n )}\n {canDeleteTour && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n handleDelete(tour.id);\n }}\n className=\"w-full text-left px-3 py-2 text-xs text-destructive hover:bg-destructive/10\"\n >\n {tr('toursList.actionDelete')}\n </button>\n )}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n })}\n </div>\n ) : (\n <div className=\"text-center py-12 border border-dashed border-border rounded-md\">\n <p className=\"text-sm sm:text-base text-muted-foreground mb-2\">\n {tr('toursList.emptyTitle')}\n </p>\n <p className=\"text-xs sm:text-sm text-muted-foreground\">\n {tr('toursList.emptySubtitle')}\n </p>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { ReactNode } from 'react';
2
+ import { ToursRootProps, ToursVariant } from '../types';
3
+
4
+ /**
5
+ * Context value for Tours microfrontend.
6
+ *
7
+ * Carries the ToursRoot props plus a resolved `variant` (always set; defaults
8
+ * to "admin" when the caller did not specify one). Pages can read `variant`
9
+ * to branch UI affordances (e.g., the user surface should never attempt
10
+ * admin-only queries).
11
+ */
12
+ type ToursContextValue = ToursRootProps & {
13
+ variant: ToursVariant;
14
+ };
15
+ /**
16
+ * Hook to access Tours context.
17
+ */
18
+ export declare const useToursContext: () => ToursContextValue;
19
+ /**
20
+ * Provider component for Tours microfrontend.
21
+ * Sets up routing, context, and global-scoped permission checking.
22
+ */
23
+ export declare function ToursProvider({ children, ...props }: ToursRootProps & {
24
+ children: ReactNode;
25
+ }): import("react/jsx-runtime").JSX.Element;
26
+ export {};
27
+ //# sourceMappingURL=ToursProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToursProvider.d.ts","sourceRoot":"","sources":["../../../src/tours/providers/ToursProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGlE,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7D;;;;;;;GAOG;AACH,KAAK,iBAAiB,GAAG,cAAc,GAAG;IAAE,OAAO,EAAE,YAAY,CAAA;CAAE,CAAC;AAIpE;;GAEG;AACH,eAAO,MAAM,eAAe,yBAM3B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,cAAc,GAAG;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,2CAyB7F"}
@@ -0,0 +1,28 @@
1
+ import { createContext as e, useContext as t } from "react";
2
+ import { jsx as n } from "react/jsx-runtime";
3
+ import { MemoryRouter as r } from "react-router-dom";
4
+ import { PermissionProvider as i } from "@burdenoff/fe-libs/shared/providers/shell";
5
+ //#region src/tours/providers/ToursProvider.tsx
6
+ var a = e(null), o = () => {
7
+ let e = t(a);
8
+ if (!e) throw Error("useToursContext must be used within ToursProvider");
9
+ return e;
10
+ };
11
+ function s({ children: e, ...t }) {
12
+ let o = {
13
+ ...t,
14
+ variant: t.variant ?? "admin"
15
+ }, s = t.tenantId ?? t.organizationId ?? t.workspaceId ?? null, c = /* @__PURE__ */ n(a.Provider, {
16
+ value: o,
17
+ children: /* @__PURE__ */ n(i, {
18
+ scopeId: s,
19
+ gateway: "global",
20
+ children: e
21
+ })
22
+ });
23
+ return t.basePath ? c : /* @__PURE__ */ n(r, { children: c });
24
+ }
25
+ //#endregion
26
+ export { s as ToursProvider, o as useToursContext };
27
+
28
+ //# sourceMappingURL=ToursProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToursProvider.js","names":[],"sources":["../../../src/tours/providers/ToursProvider.tsx"],"sourcesContent":["import { createContext, useContext, type ReactNode } from 'react';\nimport { MemoryRouter } from 'react-router-dom';\nimport { PermissionProvider } from '@burdenoff/fe-libs/shared/providers/shell';\nimport type { ToursRootProps, ToursVariant } from '../types';\n\n/**\n * Context value for Tours microfrontend.\n *\n * Carries the ToursRoot props plus a resolved `variant` (always set; defaults\n * to \"admin\" when the caller did not specify one). Pages can read `variant`\n * to branch UI affordances (e.g., the user surface should never attempt\n * admin-only queries).\n */\ntype ToursContextValue = ToursRootProps & { variant: ToursVariant };\n\nconst ToursContext = createContext<ToursContextValue | null>(null);\n\n/**\n * Hook to access Tours context.\n */\nexport const useToursContext = () => {\n const context = useContext(ToursContext);\n if (!context) {\n throw new Error('useToursContext must be used within ToursProvider');\n }\n return context;\n};\n\n/**\n * Provider component for Tours microfrontend.\n * Sets up routing, context, and global-scoped permission checking.\n */\nexport function ToursProvider({ children, ...props }: ToursRootProps & { children: ReactNode }) {\n // No useMemo here: `props` is a fresh object on every parent render (spread\n // from the shell's JSX), so any memo keyed on `props` would re-create the\n // value every render and defeat itself. Consumer re-rendering is governed\n // by the shell anyway; keeping this lean avoids a false sense of stability.\n const contextValue: ToursContextValue = { ...props, variant: props.variant ?? 'admin' };\n const permissionScopeId = props.tenantId ?? props.organizationId ?? props.workspaceId ?? null;\n\n const coreProviders = (\n <ToursContext.Provider value={contextValue}>\n <PermissionProvider scopeId={permissionScopeId} gateway=\"global\">\n {children}\n </PermissionProvider>\n </ToursContext.Provider>\n );\n\n // When integrated into a shell (basePath provided), the shell already has a router\n // so we don't create another one. When standalone (no basePath), use MemoryRouter.\n if (props.basePath) {\n // Integrated mode: shell already has BrowserRouter, don't create nested router\n return coreProviders;\n }\n\n // Standalone mode: create MemoryRouter for independent operation\n return <MemoryRouter>{coreProviders}</MemoryRouter>;\n}\n"],"mappings":";;;;;AAeA,IAAM,IAAe,EAAwC,KAAK,EAKrD,UAAwB;CACnC,IAAM,IAAU,EAAW,EAAa;AACxC,KAAI,CAAC,EACH,OAAU,MAAM,oDAAoD;AAEtE,QAAO;;AAOT,SAAgB,EAAc,EAAE,aAAU,GAAG,KAAmD;CAK9F,IAAM,IAAkC;EAAE,GAAG;EAAO,SAAS,EAAM,WAAW;EAAS,EACjF,IAAoB,EAAM,YAAY,EAAM,kBAAkB,EAAM,eAAe,MAEnF,IACJ,kBAAC,EAAa,UAAd;EAAuB,OAAO;YAC5B,kBAAC,GAAD;GAAoB,SAAS;GAAmB,SAAQ;GACrD;GACkB,CAAA;EACC,CAAA;AAW1B,QANI,EAAM,WAED,IAIF,kBAAC,GAAD,EAAA,UAAe,GAA6B,CAAA"}
@@ -0,0 +1,39 @@
1
+ import { Tour, TourStep, TourMedia, TourFilters, ValidationError, ToursViewMode, DeviceType } from '../types';
2
+
3
+ interface ToursState {
4
+ selectedTour: Tour | null;
5
+ selectedStep: TourStep | null;
6
+ viewMode: ToursViewMode;
7
+ devicePreview: DeviceType;
8
+ tourFilter: TourFilters;
9
+ stepSequence: TourStep[];
10
+ isDirty: boolean;
11
+ validationErrors: ValidationError[];
12
+ selectedMedia: TourMedia[];
13
+ uploadProgress: Record<string, number>;
14
+ sidebarOpen: boolean;
15
+ setSelectedTour: (tour: Tour | null) => void;
16
+ setSelectedStep: (step: TourStep | null) => void;
17
+ setViewMode: (mode: ToursViewMode) => void;
18
+ setDevicePreview: (device: DeviceType) => void;
19
+ toggleSidebar: () => void;
20
+ setSidebarOpen: (open: boolean) => void;
21
+ updateTourFilter: (filter: Partial<TourFilters>) => void;
22
+ resetTourFilter: () => void;
23
+ updateStepSequence: (steps: TourStep[]) => void;
24
+ reorderSteps: (startIndex: number, endIndex: number) => void;
25
+ addStep: (step: Partial<TourStep>) => void;
26
+ removeStep: (stepId: string) => void;
27
+ updateStep: (stepId: string, updates: Partial<TourStep>) => void;
28
+ setDirty: (dirty: boolean) => void;
29
+ validateTour: () => ValidationError[];
30
+ clearValidationErrors: () => void;
31
+ selectMedia: (media: TourMedia) => void;
32
+ unselectMedia: (mediaId: string) => void;
33
+ clearSelectedMedia: () => void;
34
+ updateUploadProgress: (fileId: string, progress: number) => void;
35
+ removeUploadProgress: (fileId: string) => void;
36
+ }
37
+ export declare const useToursStore: import('zustand').UseBoundStore<import('zustand').StoreApi<ToursState>>;
38
+ export {};
39
+ //# sourceMappingURL=toursStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toursStore.d.ts","sourceRoot":"","sources":["../../../src/tours/store/toursStore.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,IAAI,EACJ,QAAQ,EACR,SAAS,EACT,WAAW,EACX,eAAe,EACf,aAAa,EACb,UAAU,EACX,MAAM,UAAU,CAAC;AAElB,UAAU,UAAU;IAElB,YAAY,EAAE,IAAI,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC9B,QAAQ,EAAE,aAAa,CAAC;IACxB,aAAa,EAAE,UAAU,CAAC;IAG1B,UAAU,EAAE,WAAW,CAAC;IAGxB,YAAY,EAAE,QAAQ,EAAE,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB,EAAE,eAAe,EAAE,CAAC;IAGpC,aAAa,EAAE,SAAS,EAAE,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAGvC,WAAW,EAAE,OAAO,CAAC;IAGrB,eAAe,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,CAAC;IAC7C,eAAe,EAAE,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAC;IACjD,WAAW,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IAC3C,gBAAgB,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IAC/C,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,cAAc,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAGxC,gBAAgB,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IACzD,eAAe,EAAE,MAAM,IAAI,CAAC;IAG5B,kBAAkB,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,IAAI,CAAC;IAChD,YAAY,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7D,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;IAC3C,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;IAGjE,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,YAAY,EAAE,MAAM,eAAe,EAAE,CAAC;IACtC,qBAAqB,EAAE,MAAM,IAAI,CAAC;IAGlC,WAAW,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IACxC,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAC/B,oBAAoB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACjE,oBAAoB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CAChD;AAYD,eAAO,MAAM,aAAa,yEA4KvB,CAAC"}