@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,142 @@
1
+ import { useToursContext as e } from "../providers/ToursProvider.js";
2
+ import { useGetUserTourProgressesQuery as t } from "../../generated/global-operations.js";
3
+ import { useToursI18n as n } from "../i18n.js";
4
+ import { useEffect as r, useMemo as i } from "react";
5
+ import { CheckCircle2 as a, HelpCircle as o, MinusCircle as s, Play as c } from "lucide-react";
6
+ import { jsx as l, jsxs as u } from "react/jsx-runtime";
7
+ import { useEventBus as d } from "@burdenoff/fe-libs/shared/events";
8
+ //#region src/tours/pages/MyToursProgressPage.tsx
9
+ function f() {
10
+ let { tr: f } = n(), { currentUser: m, productId: h, moduleId: g, pageId: _, workspaceId: v } = e(), y = d();
11
+ r(() => {
12
+ y.emit("tours.page.viewed", {
13
+ page: "/tours/progress",
14
+ productId: h,
15
+ moduleId: g,
16
+ pageId: _,
17
+ workspaceId: v
18
+ });
19
+ }, []);
20
+ let { data: b, loading: x } = t({
21
+ variables: {
22
+ userId: m?.id,
23
+ pagination: {
24
+ limit: 100,
25
+ offset: 0
26
+ }
27
+ },
28
+ skip: !m?.id,
29
+ fetchPolicy: "cache-and-network"
30
+ }), S = i(() => {
31
+ let e = {
32
+ IN_PROGRESS: [],
33
+ COMPLETED: [],
34
+ SKIPPED: [],
35
+ OTHER: []
36
+ }, t = (b?.userTourProgresses ?? []).filter((e) => !(h && e.tour.productId !== h || g && e.tour.moduleId && e.tour.moduleId !== g || _ && e.tour.pageId && e.tour.pageId !== _));
37
+ for (let n of t) n.status === "COMPLETED" ? e.COMPLETED.push(n) : n.status === "IN_PROGRESS" ? e.IN_PROGRESS.push(n) : n.status === "SKIPPED" || n.status === "DISMISSED" ? e.SKIPPED.push(n) : e.OTHER.push(n);
38
+ return e;
39
+ }, [
40
+ b,
41
+ h,
42
+ g,
43
+ _
44
+ ]);
45
+ return /* @__PURE__ */ u("div", {
46
+ className: "space-y-4 sm:space-y-6 p-3 sm:p-6",
47
+ children: [/* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("h1", {
48
+ className: "text-xl sm:text-2xl font-bold text-foreground",
49
+ children: f("myToursProgress.title")
50
+ }), /* @__PURE__ */ l("p", {
51
+ className: "text-sm sm:text-base text-muted-foreground",
52
+ children: f("myToursProgress.subtitle")
53
+ })] }), x && (b?.userTourProgresses?.length ?? 0) === 0 ? /* @__PURE__ */ l("div", {
54
+ className: "text-sm text-muted-foreground",
55
+ role: "status",
56
+ "aria-live": "polite",
57
+ children: f("myToursProgress.loading")
58
+ }) : /* @__PURE__ */ u("div", {
59
+ className: "space-y-6",
60
+ children: [
61
+ /* @__PURE__ */ l(p, {
62
+ title: f("myToursProgress.inProgress"),
63
+ icon: /* @__PURE__ */ l(c, {
64
+ size: 16,
65
+ className: "text-warning"
66
+ }),
67
+ rows: S.IN_PROGRESS,
68
+ emptyText: f("myToursProgress.emptyInProgress")
69
+ }),
70
+ /* @__PURE__ */ l(p, {
71
+ title: f("myToursProgress.completed"),
72
+ icon: /* @__PURE__ */ l(a, {
73
+ size: 16,
74
+ className: "text-success"
75
+ }),
76
+ rows: S.COMPLETED,
77
+ emptyText: f("myToursProgress.emptyCompleted")
78
+ }),
79
+ /* @__PURE__ */ l(p, {
80
+ title: f("myToursProgress.skipped"),
81
+ icon: /* @__PURE__ */ l(s, {
82
+ size: 16,
83
+ className: "text-muted-foreground"
84
+ }),
85
+ rows: S.SKIPPED,
86
+ emptyText: f("myToursProgress.emptySkipped")
87
+ }),
88
+ S.OTHER.length > 0 ? /* @__PURE__ */ l(p, {
89
+ title: f("myToursProgress.other"),
90
+ icon: /* @__PURE__ */ l(o, {
91
+ size: 16,
92
+ className: "text-muted-foreground"
93
+ }),
94
+ rows: S.OTHER,
95
+ emptyText: f("myToursProgress.emptyOther")
96
+ }) : null
97
+ ]
98
+ })]
99
+ });
100
+ }
101
+ function p({ title: e, icon: t, rows: n, emptyText: r }) {
102
+ return /* @__PURE__ */ u("section", {
103
+ className: "space-y-2",
104
+ children: [/* @__PURE__ */ u("h2", {
105
+ className: "flex items-center gap-2 text-sm font-semibold text-foreground",
106
+ children: [
107
+ t,
108
+ e,
109
+ /* @__PURE__ */ u("span", {
110
+ className: "text-xs text-muted-foreground font-normal",
111
+ children: [
112
+ "(",
113
+ n.length,
114
+ ")"
115
+ ]
116
+ })
117
+ ]
118
+ }), n.length === 0 ? /* @__PURE__ */ l("p", {
119
+ className: "text-sm text-muted-foreground",
120
+ role: "status",
121
+ "aria-live": "polite",
122
+ children: r
123
+ }) : /* @__PURE__ */ l("ul", {
124
+ className: "divide-y divide-border rounded-md border border-border",
125
+ children: n.map((e) => /* @__PURE__ */ u("li", {
126
+ className: "flex items-center justify-between gap-3 p-3",
127
+ children: [/* @__PURE__ */ l("span", {
128
+ className: "text-sm text-foreground line-clamp-1",
129
+ children: e.tour.name
130
+ }), e.lastViewedAt ? /* @__PURE__ */ l("time", {
131
+ className: "text-xs text-muted-foreground",
132
+ dateTime: e.lastViewedAt,
133
+ children: new Date(e.lastViewedAt).toLocaleDateString()
134
+ }) : null]
135
+ }, e.id))
136
+ })]
137
+ });
138
+ }
139
+ //#endregion
140
+ export { f as MyToursProgressPage };
141
+
142
+ //# sourceMappingURL=MyToursProgressPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MyToursProgressPage.js","names":[],"sources":["../../../src/tours/pages/MyToursProgressPage.tsx"],"sourcesContent":["import { useMemo, useEffect } from 'react';\nimport { CheckCircle2, HelpCircle, MinusCircle, Play } from 'lucide-react';\nimport { useGetUserTourProgressesQuery } from '../../generated/global-operations';\nimport { useToursContext } from '../providers/ToursProvider';\nimport { useToursI18n } from '../i18n';\nimport { useEventBus } from '@burdenoff/fe-libs/shared/events';\n\ntype ProgressGroup = 'IN_PROGRESS' | 'COMPLETED' | 'SKIPPED' | 'OTHER';\n\ntype ProgressRow = {\n id: string;\n status: string;\n tour: { id: string; name: string; productId?: string; moduleId?: string; pageId?: string };\n lastViewedAt?: string | null;\n};\n\n/**\n * MyToursProgressPage — user-facing read-only view of the current user's\n * tour interactions, grouped by status (In progress / Completed / Skipped).\n */\nexport function MyToursProgressPage() {\n const { tr } = useToursI18n();\n const {\n currentUser,\n productId: shellProductId,\n moduleId: shellModuleId,\n pageId: shellPageId,\n workspaceId,\n } = useToursContext();\n const eventBus = useEventBus();\n\n // Emit page view event on mount\n useEffect(() => {\n eventBus.emit('tours.page.viewed', {\n page: '/tours/progress',\n productId: shellProductId,\n moduleId: shellModuleId,\n pageId: shellPageId,\n workspaceId,\n });\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n const { data, loading } = useGetUserTourProgressesQuery({\n variables: { userId: currentUser?.id, pagination: { limit: 100, offset: 0 } },\n skip: !currentUser?.id,\n fetchPolicy: 'cache-and-network',\n });\n\n const grouped = useMemo(() => {\n const result: Record<ProgressGroup, NonNullable<typeof data>['userTourProgresses']> = {\n IN_PROGRESS: [],\n COMPLETED: [],\n SKIPPED: [],\n OTHER: [],\n };\n // Filter the raw progress list to the shell's product/module/page context\n // so a user's vibecontrols session doesn't see workspaces / bigconsole\n // progress rows. `userTourProgresses` returns everything scoped by userId;\n // this MFE is mounted per-shell so we narrow to what the shell advertises.\n // When the shell didn't supply a filter, the corresponding level is not\n // checked (e.g., no shellModuleId → accept any moduleId).\n const rows = (data?.userTourProgresses ?? []).filter((row: ProgressRow) => {\n if (shellProductId && row.tour.productId !== shellProductId) return false;\n if (shellModuleId && row.tour.moduleId && row.tour.moduleId !== shellModuleId) return false;\n if (shellPageId && row.tour.pageId && row.tour.pageId !== shellPageId) return false;\n return true;\n });\n for (const row of rows) {\n if (row.status === 'COMPLETED') result.COMPLETED.push(row);\n else if (row.status === 'IN_PROGRESS') result.IN_PROGRESS.push(row);\n else if (row.status === 'SKIPPED' || row.status === 'DISMISSED') result.SKIPPED.push(row);\n // Unknown / future status values fall through here so nothing is\n // silently dropped if the backend introduces a new state.\n else result.OTHER.push(row);\n }\n return result;\n }, [data, shellProductId, shellModuleId, shellPageId]);\n\n return (\n <div className=\"space-y-4 sm:space-y-6 p-3 sm:p-6\">\n <div>\n <h1 className=\"text-xl sm:text-2xl font-bold text-foreground\">\n {tr('myToursProgress.title')}\n </h1>\n <p className=\"text-sm sm:text-base text-muted-foreground\">\n {tr('myToursProgress.subtitle')}\n </p>\n </div>\n\n {loading && (data?.userTourProgresses?.length ?? 0) === 0 ? (\n <div className=\"text-sm text-muted-foreground\" role=\"status\" aria-live=\"polite\">\n {tr('myToursProgress.loading')}\n </div>\n ) : (\n <div className=\"space-y-6\">\n <ProgressSection\n title={tr('myToursProgress.inProgress')}\n icon={<Play size={16} className=\"text-warning\" />}\n rows={grouped.IN_PROGRESS}\n emptyText={tr('myToursProgress.emptyInProgress')}\n />\n <ProgressSection\n title={tr('myToursProgress.completed')}\n icon={<CheckCircle2 size={16} className=\"text-success\" />}\n rows={grouped.COMPLETED}\n emptyText={tr('myToursProgress.emptyCompleted')}\n />\n <ProgressSection\n title={tr('myToursProgress.skipped')}\n icon={<MinusCircle size={16} className=\"text-muted-foreground\" />}\n rows={grouped.SKIPPED}\n emptyText={tr('myToursProgress.emptySkipped')}\n />\n {grouped.OTHER.length > 0 ? (\n <ProgressSection\n title={tr('myToursProgress.other')}\n icon={<HelpCircle size={16} className=\"text-muted-foreground\" />}\n rows={grouped.OTHER}\n emptyText={tr('myToursProgress.emptyOther')}\n />\n ) : null}\n </div>\n )}\n </div>\n );\n}\n\nfunction ProgressSection({\n title,\n icon,\n rows,\n emptyText,\n}: {\n title: string;\n icon: React.ReactNode;\n rows: Array<{ id: string; tour: { id: string; name: string }; lastViewedAt?: string | null }>;\n emptyText: string;\n}) {\n return (\n <section className=\"space-y-2\">\n <h2 className=\"flex items-center gap-2 text-sm font-semibold text-foreground\">\n {icon}\n {title}\n <span className=\"text-xs text-muted-foreground font-normal\">({rows.length})</span>\n </h2>\n {rows.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\" role=\"status\" aria-live=\"polite\">\n {emptyText}\n </p>\n ) : (\n <ul className=\"divide-y divide-border rounded-md border border-border\">\n {rows.map((row) => (\n <li key={row.id} className=\"flex items-center justify-between gap-3 p-3\">\n <span className=\"text-sm text-foreground line-clamp-1\">{row.tour.name}</span>\n {row.lastViewedAt ? (\n <time className=\"text-xs text-muted-foreground\" dateTime={row.lastViewedAt}>\n {new Date(row.lastViewedAt).toLocaleDateString()}\n </time>\n ) : null}\n </li>\n ))}\n </ul>\n )}\n </section>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Tour scheduler page
3
+ * Configure tour scheduling and recurrence
4
+ */
5
+ export declare function SchedulerPage(): import("react/jsx-runtime").JSX.Element;
6
+ //# sourceMappingURL=SchedulerPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SchedulerPage.d.ts","sourceRoot":"","sources":["../../../src/tours/pages/SchedulerPage.tsx"],"names":[],"mappings":"AAYA;;;GAGG;AACH,wBAAgB,aAAa,4CA4P5B"}
@@ -0,0 +1,231 @@
1
+ import { useToursContext as e } from "../providers/ToursProvider.js";
2
+ import { useCreateTourScheduleMutation as t, useGetTourSchedulesQuery as n } from "../../generated/global-operations.js";
3
+ import { useToursPermissionAccess as r } from "../hooks/useToursPermissionAccess.js";
4
+ import { TOUR_PERMISSIONS as i } from "../../constants/permissions.js";
5
+ import { useCallback as a, useState as o } from "react";
6
+ import { PermissionGate as s } from "@burdenoff/fe-libs/shared/components";
7
+ import { ArrowLeft as c, Calendar as l, Clock as u, Save as d } from "lucide-react";
8
+ import { jsx as f, jsxs as p } from "react/jsx-runtime";
9
+ import { useNavigate as m, useParams as h } from "react-router-dom";
10
+ import { useI18n as g } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
11
+ //#region src/tours/pages/SchedulerPage.tsx
12
+ function _() {
13
+ let { t: _ } = g(), v = a((e, t) => {
14
+ let n = _(e);
15
+ return n === e ? t : n;
16
+ }, [_]), { tourId: y } = h(), b = m(), { basePath: x = "/" } = e(), { hasPermission: S } = r(), C = S(i.TOUR_SCHEDULE_CREATE), w = S(i.TOUR_SCHEDULE_LIST), [T, E] = o({
17
+ startDate: "",
18
+ endDate: "",
19
+ recurrencePattern: "DAILY",
20
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
21
+ isActive: !0
22
+ }), [D, O] = o(!1), [k] = t(), { data: A } = n({
23
+ variables: { tourId: y },
24
+ skip: !y || !w
25
+ }), j = A?.tourSchedules ?? [], M = async (e) => {
26
+ if (e.preventDefault(), y) {
27
+ O(!0);
28
+ try {
29
+ let e = T.recurrencePattern === "DAILY" ? "FREQ=DAILY" : T.recurrencePattern === "WEEKLY" ? "FREQ=WEEKLY" : T.recurrencePattern === "MONTHLY" ? "FREQ=MONTHLY" : void 0;
30
+ await k({
31
+ variables: { input: {
32
+ tourId: y,
33
+ startDate: new Date(T.startDate).toISOString(),
34
+ endDate: T.endDate ? new Date(T.endDate).toISOString() : void 0,
35
+ recurrenceRule: e,
36
+ timezone: T.timezone
37
+ } },
38
+ refetchQueries: ["GetTourSchedules"]
39
+ }), b(`${x}/${y}/edit`);
40
+ } catch (e) {
41
+ console.error("Failed to create schedule:", e);
42
+ } finally {
43
+ O(!1);
44
+ }
45
+ }
46
+ }, N = () => {
47
+ b(`${x}/${y}/edit`);
48
+ };
49
+ return /* @__PURE__ */ p("div", {
50
+ className: "space-y-6 p-6 max-w-3xl mx-auto",
51
+ children: [
52
+ /* @__PURE__ */ p("div", {
53
+ className: "flex items-center gap-4",
54
+ children: [/* @__PURE__ */ f("button", {
55
+ onClick: N,
56
+ className: "p-2 hover:bg-accent rounded-md",
57
+ children: /* @__PURE__ */ f(c, { size: 20 })
58
+ }), /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("h1", {
59
+ className: "text-2xl font-bold",
60
+ children: v("tourScheduler.title", "Schedule Tour")
61
+ }), /* @__PURE__ */ f("p", {
62
+ className: "text-sm text-muted-foreground",
63
+ children: v("tourScheduler.subtitle", "Configure when this tour should be activated")
64
+ })] })]
65
+ }),
66
+ j.length > 0 && /* @__PURE__ */ p("div", {
67
+ className: "border border-border rounded-md p-6 bg-card",
68
+ children: [/* @__PURE__ */ f("h2", {
69
+ className: "text-lg font-semibold mb-4",
70
+ children: v("tourScheduler.existingSchedules", "Existing Schedules")
71
+ }), /* @__PURE__ */ f("div", {
72
+ className: "space-y-2",
73
+ children: j.map((e) => /* @__PURE__ */ p("div", {
74
+ className: "flex items-center justify-between p-3 border border-border rounded-md",
75
+ children: [/* @__PURE__ */ p("div", { children: [/* @__PURE__ */ p("div", {
76
+ className: "text-sm font-medium",
77
+ children: [new Date(e.startDate).toLocaleDateString(), e.endDate ? ` — ${new Date(e.endDate).toLocaleDateString()}` : ` — ${v("tourScheduler.noEndDate", "No end date")}`]
78
+ }), /* @__PURE__ */ p("div", {
79
+ className: "text-xs text-muted-foreground",
80
+ children: [
81
+ e.recurrenceRule || v("tourScheduler.oneTime", "One-time"),
82
+ " ·",
83
+ " ",
84
+ e.timezone,
85
+ e.isActive ? ` · ${v("tourScheduler.active", "Active")}` : ` · ${v("tourScheduler.inactive", "Inactive")}`
86
+ ]
87
+ })] }), /* @__PURE__ */ p("div", {
88
+ className: "text-xs text-muted-foreground",
89
+ children: [
90
+ v("tourScheduler.runs", "Runs"),
91
+ ": ",
92
+ e.executionCount
93
+ ]
94
+ })]
95
+ }, e.id))
96
+ })]
97
+ }),
98
+ /* @__PURE__ */ p("form", {
99
+ onSubmit: M,
100
+ className: "space-y-6",
101
+ children: [
102
+ /* @__PURE__ */ p("div", {
103
+ className: "border border-border rounded-md p-6 bg-card",
104
+ children: [/* @__PURE__ */ p("h2", {
105
+ className: "text-lg font-semibold mb-4 flex items-center gap-2",
106
+ children: [/* @__PURE__ */ f(l, { size: 20 }), v("tourScheduler.sectionDateRange", "Date Range")]
107
+ }), /* @__PURE__ */ p("div", {
108
+ className: "space-y-4",
109
+ children: [/* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
110
+ className: "block text-sm font-medium mb-2",
111
+ children: v("tourScheduler.labelStartDate", "Start Date *")
112
+ }), /* @__PURE__ */ f("input", {
113
+ type: "datetime-local",
114
+ value: T.startDate,
115
+ onChange: (e) => E({
116
+ ...T,
117
+ startDate: e.target.value
118
+ }),
119
+ className: "w-full px-3 py-2 border border-border rounded-md bg-background",
120
+ required: !0
121
+ })] }), /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
122
+ className: "block text-sm font-medium mb-2",
123
+ children: v("tourScheduler.labelEndDate", "End Date (Optional)")
124
+ }), /* @__PURE__ */ f("input", {
125
+ type: "datetime-local",
126
+ value: T.endDate,
127
+ onChange: (e) => E({
128
+ ...T,
129
+ endDate: e.target.value
130
+ }),
131
+ className: "w-full px-3 py-2 border border-border rounded-md bg-background"
132
+ })] })]
133
+ })]
134
+ }),
135
+ /* @__PURE__ */ p("div", {
136
+ className: "border border-border rounded-md p-6 bg-card",
137
+ children: [/* @__PURE__ */ p("h2", {
138
+ className: "text-lg font-semibold mb-4 flex items-center gap-2",
139
+ children: [/* @__PURE__ */ f(u, { size: 20 }), v("tourScheduler.sectionRecurrence", "Recurrence")]
140
+ }), /* @__PURE__ */ p("div", {
141
+ className: "space-y-4",
142
+ children: [/* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
143
+ className: "block text-sm font-medium mb-2",
144
+ children: v("tourScheduler.labelRecurrencePattern", "Recurrence Pattern")
145
+ }), /* @__PURE__ */ p("select", {
146
+ value: T.recurrencePattern,
147
+ onChange: (e) => E({
148
+ ...T,
149
+ recurrencePattern: e.target.value
150
+ }),
151
+ className: "w-full px-3 py-2 border border-border rounded-md bg-background",
152
+ children: [
153
+ /* @__PURE__ */ f("option", {
154
+ value: "DAILY",
155
+ children: v("tourScheduler.recurrenceDaily", "Daily")
156
+ }),
157
+ /* @__PURE__ */ f("option", {
158
+ value: "WEEKLY",
159
+ children: v("tourScheduler.recurrenceWeekly", "Weekly")
160
+ }),
161
+ /* @__PURE__ */ f("option", {
162
+ value: "MONTHLY",
163
+ children: v("tourScheduler.recurrenceMonthly", "Monthly")
164
+ }),
165
+ /* @__PURE__ */ f("option", {
166
+ value: "CUSTOM",
167
+ children: v("tourScheduler.recurrenceCustom", "Custom")
168
+ })
169
+ ]
170
+ })] }), /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
171
+ className: "block text-sm font-medium mb-2",
172
+ children: v("tourScheduler.labelTimezone", "Timezone")
173
+ }), /* @__PURE__ */ f("input", {
174
+ type: "text",
175
+ value: T.timezone,
176
+ onChange: (e) => E({
177
+ ...T,
178
+ timezone: e.target.value
179
+ }),
180
+ className: "w-full px-3 py-2 border border-border rounded-md bg-background",
181
+ readOnly: !0
182
+ })] })]
183
+ })]
184
+ }),
185
+ /* @__PURE__ */ f("div", {
186
+ className: "border border-border rounded-md p-6 bg-card",
187
+ children: /* @__PURE__ */ p("label", {
188
+ className: "flex items-center gap-3 cursor-pointer",
189
+ children: [/* @__PURE__ */ f("input", {
190
+ type: "checkbox",
191
+ checked: T.isActive,
192
+ onChange: (e) => E({
193
+ ...T,
194
+ isActive: e.target.checked
195
+ }),
196
+ className: "w-5 h-5 rounded"
197
+ }), /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("div", {
198
+ className: "font-medium",
199
+ children: v("tourScheduler.statusActiveLabel", "Active")
200
+ }), /* @__PURE__ */ f("div", {
201
+ className: "text-sm text-muted-foreground",
202
+ children: v("tourScheduler.statusActiveDescription", "Enable this schedule immediately after creation")
203
+ })] })]
204
+ })
205
+ }),
206
+ /* @__PURE__ */ p("div", {
207
+ className: "flex gap-3",
208
+ children: [/* @__PURE__ */ f("button", {
209
+ type: "button",
210
+ onClick: N,
211
+ className: "flex-1 px-4 py-2 border border-border rounded-md hover:bg-accent",
212
+ children: v("tourScheduler.cancel", "Cancel")
213
+ }), /* @__PURE__ */ f(s, {
214
+ permission: i.TOUR_SCHEDULE_CREATE,
215
+ children: /* @__PURE__ */ p("button", {
216
+ type: "submit",
217
+ disabled: D || !C,
218
+ className: "flex-1 px-4 py-2 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 disabled:opacity-50 flex items-center justify-center gap-2",
219
+ children: [/* @__PURE__ */ f(d, { size: 20 }), D ? v("tourScheduler.creating", "Creating...") : v("tourScheduler.createSchedule", "Create Schedule")]
220
+ })
221
+ })]
222
+ })
223
+ ]
224
+ })
225
+ ]
226
+ });
227
+ }
228
+ //#endregion
229
+ export { _ as SchedulerPage };
230
+
231
+ //# sourceMappingURL=SchedulerPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SchedulerPage.js","names":[],"sources":["../../../src/tours/pages/SchedulerPage.tsx"],"sourcesContent":["import { useCallback, useState } from 'react';\nimport { useParams, useNavigate } from 'react-router-dom';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { Calendar, Clock, ArrowLeft, Save } from 'lucide-react';\nimport { PermissionGate } from '@burdenoff/fe-libs/shared/components';\nimport { useToursPermissionAccess } from '../hooks/useToursPermissionAccess';\nimport { useToursContext } from '../providers/ToursProvider';\nimport { TOUR_PERMISSIONS } from '../../constants/permissions';\nimport type { RecurrencePattern } from '../types';\nimport { useCreateTourScheduleMutation } from '../../generated/global-operations';\nimport { useGetTourSchedulesQuery } from '../../generated/global-operations';\n\n/**\n * Tour scheduler page\n * Configure tour scheduling and recurrence\n */\nexport function SchedulerPage() {\n const { t } = useI18n();\n const tr = useCallback(\n (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n },\n [t]\n );\n const { tourId } = useParams();\n const navigate = useNavigate();\n const { basePath = '/' } = useToursContext();\n const { hasPermission } = useToursPermissionAccess();\n const canCreateSchedule = hasPermission(TOUR_PERMISSIONS.TOUR_SCHEDULE_CREATE);\n const canListSchedules = hasPermission(TOUR_PERMISSIONS.TOUR_SCHEDULE_LIST);\n\n const [scheduleData, setScheduleData] = useState({\n startDate: '',\n endDate: '',\n recurrencePattern: 'DAILY' as RecurrencePattern,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n isActive: true,\n });\n\n const [saving, setSaving] = useState(false);\n\n const [createSchedule] = useCreateTourScheduleMutation();\n const { data: schedulesData } = useGetTourSchedulesQuery({\n variables: { tourId: tourId! },\n skip: !tourId || !canListSchedules,\n });\n const existingSchedules = schedulesData?.tourSchedules ?? [];\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n if (!tourId) return;\n setSaving(true);\n try {\n // Convert recurrence pattern to RFC 5545 recurrence rule\n const recurrenceRule =\n scheduleData.recurrencePattern === 'DAILY'\n ? 'FREQ=DAILY'\n : scheduleData.recurrencePattern === 'WEEKLY'\n ? 'FREQ=WEEKLY'\n : scheduleData.recurrencePattern === 'MONTHLY'\n ? 'FREQ=MONTHLY'\n : undefined;\n\n await createSchedule({\n variables: {\n input: {\n tourId,\n startDate: new Date(scheduleData.startDate).toISOString(),\n endDate: scheduleData.endDate\n ? new Date(scheduleData.endDate).toISOString()\n : undefined,\n recurrenceRule,\n timezone: scheduleData.timezone,\n },\n },\n refetchQueries: ['GetTourSchedules'],\n });\n navigate(`${basePath}/${tourId}/edit`);\n } catch (error) {\n console.error('Failed to create schedule:', error);\n } finally {\n setSaving(false);\n }\n };\n\n const handleBack = () => {\n navigate(`${basePath}/${tourId}/edit`);\n };\n\n return (\n <div className=\"space-y-6 p-6 max-w-3xl mx-auto\">\n {/* Header */}\n <div className=\"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>\n <h1 className=\"text-2xl font-bold\">{tr('tourScheduler.title', 'Schedule Tour')}</h1>\n <p className=\"text-sm text-muted-foreground\">\n {tr('tourScheduler.subtitle', 'Configure when this tour should be activated')}\n </p>\n </div>\n </div>\n\n {/* Existing Schedules */}\n {existingSchedules.length > 0 && (\n <div className=\"border border-border rounded-md p-6 bg-card\">\n <h2 className=\"text-lg font-semibold mb-4\">\n {tr('tourScheduler.existingSchedules', 'Existing Schedules')}\n </h2>\n <div className=\"space-y-2\">\n {existingSchedules.map((schedule: (typeof existingSchedules)[number]) => (\n <div\n key={schedule.id}\n className=\"flex items-center justify-between p-3 border border-border rounded-md\"\n >\n <div>\n <div className=\"text-sm font-medium\">\n {new Date(schedule.startDate).toLocaleDateString()}\n {schedule.endDate\n ? ` — ${new Date(schedule.endDate).toLocaleDateString()}`\n : ` — ${tr('tourScheduler.noEndDate', 'No end date')}`}\n </div>\n <div className=\"text-xs text-muted-foreground\">\n {schedule.recurrenceRule || tr('tourScheduler.oneTime', 'One-time')} ·{' '}\n {schedule.timezone}\n {schedule.isActive\n ? ` · ${tr('tourScheduler.active', 'Active')}`\n : ` · ${tr('tourScheduler.inactive', 'Inactive')}`}\n </div>\n </div>\n <div className=\"text-xs text-muted-foreground\">\n {tr('tourScheduler.runs', 'Runs')}: {schedule.executionCount}\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Form */}\n <form onSubmit={handleSubmit} className=\"space-y-6\">\n {/* Date Range */}\n <div className=\"border border-border rounded-md p-6 bg-card\">\n <h2 className=\"text-lg font-semibold mb-4 flex items-center gap-2\">\n <Calendar size={20} />\n {tr('tourScheduler.sectionDateRange', 'Date Range')}\n </h2>\n\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium mb-2\">\n {tr('tourScheduler.labelStartDate', 'Start Date *')}\n </label>\n <input\n type=\"datetime-local\"\n value={scheduleData.startDate}\n onChange={(e) => setScheduleData({ ...scheduleData, startDate: e.target.value })}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background\"\n required\n />\n </div>\n\n <div>\n <label className=\"block text-sm font-medium mb-2\">\n {tr('tourScheduler.labelEndDate', 'End Date (Optional)')}\n </label>\n <input\n type=\"datetime-local\"\n value={scheduleData.endDate}\n onChange={(e) => setScheduleData({ ...scheduleData, endDate: e.target.value })}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background\"\n />\n </div>\n </div>\n </div>\n\n {/* Recurrence */}\n <div className=\"border border-border rounded-md p-6 bg-card\">\n <h2 className=\"text-lg font-semibold mb-4 flex items-center gap-2\">\n <Clock size={20} />\n {tr('tourScheduler.sectionRecurrence', 'Recurrence')}\n </h2>\n\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium mb-2\">\n {tr('tourScheduler.labelRecurrencePattern', 'Recurrence Pattern')}\n </label>\n <select\n value={scheduleData.recurrencePattern}\n onChange={(e) =>\n setScheduleData({\n ...scheduleData,\n recurrencePattern: e.target.value as RecurrencePattern,\n })\n }\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background\"\n >\n <option value=\"DAILY\">{tr('tourScheduler.recurrenceDaily', 'Daily')}</option>\n <option value=\"WEEKLY\">{tr('tourScheduler.recurrenceWeekly', 'Weekly')}</option>\n <option value=\"MONTHLY\">{tr('tourScheduler.recurrenceMonthly', 'Monthly')}</option>\n <option value=\"CUSTOM\">{tr('tourScheduler.recurrenceCustom', 'Custom')}</option>\n </select>\n </div>\n\n <div>\n <label className=\"block text-sm font-medium mb-2\">\n {tr('tourScheduler.labelTimezone', 'Timezone')}\n </label>\n <input\n type=\"text\"\n value={scheduleData.timezone}\n onChange={(e) => setScheduleData({ ...scheduleData, timezone: e.target.value })}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background\"\n readOnly\n />\n </div>\n </div>\n </div>\n\n {/* Status */}\n <div className=\"border border-border rounded-md p-6 bg-card\">\n <label className=\"flex items-center gap-3 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={scheduleData.isActive}\n onChange={(e) => setScheduleData({ ...scheduleData, isActive: e.target.checked })}\n className=\"w-5 h-5 rounded\"\n />\n <div>\n <div className=\"font-medium\">{tr('tourScheduler.statusActiveLabel', 'Active')}</div>\n <div className=\"text-sm text-muted-foreground\">\n {tr(\n 'tourScheduler.statusActiveDescription',\n 'Enable this schedule immediately after creation'\n )}\n </div>\n </div>\n </label>\n </div>\n\n {/* Actions */}\n <div className=\"flex gap-3\">\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"flex-1 px-4 py-2 border border-border rounded-md hover:bg-accent\"\n >\n {tr('tourScheduler.cancel', 'Cancel')}\n </button>\n <PermissionGate permission={TOUR_PERMISSIONS.TOUR_SCHEDULE_CREATE}>\n <button\n type=\"submit\"\n disabled={saving || !canCreateSchedule}\n className=\"flex-1 px-4 py-2 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 disabled:opacity-50 flex items-center justify-center gap-2\"\n >\n <Save size={20} />\n {saving\n ? tr('tourScheduler.creating', 'Creating...')\n : tr('tourScheduler.createSchedule', 'Create Schedule')}\n </button>\n </PermissionGate>\n </div>\n </form>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Step editor page
3
+ * Manage tour steps with sequencer and editor
4
+ * Responsive: sidebar drawer on mobile, side panel on desktop
5
+ */
6
+ export declare function StepEditorPage(): import("react/jsx-runtime").JSX.Element;
7
+ //# sourceMappingURL=StepEditorPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StepEditorPage.d.ts","sourceRoot":"","sources":["../../../src/tours/pages/StepEditorPage.tsx"],"names":[],"mappings":"AAwBA;;;;GAIG;AACH,wBAAgB,cAAc,4CA6nB7B"}