@burdenoff/microfe-tours 2026.625.1 → 2026.625.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,62 +5,59 @@ import { useEffect as r, useRef as i } from "react";
5
5
  import { CheckCircle2 as a, Circle as o, MinusCircle as s, Play as c } from "lucide-react";
6
6
  import { jsx as l, jsxs as u } from "react/jsx-runtime";
7
7
  import { useSearchParams as d } from "react-router-dom";
8
- import { GlassCard as f } from "@burdenoff/fe-libs/ui";
9
- import { useEventBus as p } from "@burdenoff/fe-libs/shared/events";
8
+ import { GlassCard as f, GradientText as p, IllustratedEmptyState as m } from "@burdenoff/fe-libs/ui";
9
+ import { useEventBus as h } from "@burdenoff/fe-libs/shared/events";
10
10
  //#region src/tours/pages/MyToursPage.tsx
11
- var m = /^[a-zA-Z0-9_-]+$/, h = /^[a-zA-Z0-9_\-/]+$/;
12
- function g(e, t) {
13
- return e && m.test(e) ? e : t;
11
+ var g = /^[a-zA-Z0-9_-]+$/, _ = /^[a-zA-Z0-9_\-/]+$/;
12
+ function v(e, t) {
13
+ return e && g.test(e) ? e : t;
14
14
  }
15
- function _(e, t) {
16
- return e && h.test(e) ? e : t;
15
+ function y(e, t) {
16
+ return e && _.test(e) ? e : t;
17
17
  }
18
- function v() {
19
- let { tr: a } = n(), { productId: o, moduleId: s, pageId: c, workspaceId: m } = e(), [h] = d(), v = p(), b = i(!1);
18
+ function b() {
19
+ let { tr: a } = n(), { productId: o, moduleId: s, pageId: c, workspaceId: g } = e(), [_] = d(), b = h(), S = i(!1);
20
20
  r(() => {
21
- b.current || (b.current = !0, v.emit("tours.page.viewed", {
21
+ S.current || (S.current = !0, b.emit("tours.page.viewed", {
22
22
  page: "/tours",
23
23
  productId: o,
24
24
  moduleId: s,
25
25
  pageId: c,
26
- workspaceId: m
26
+ workspaceId: g
27
27
  }));
28
28
  }, [
29
- v,
29
+ b,
30
30
  o,
31
31
  s,
32
32
  c,
33
- m
33
+ g
34
34
  ]);
35
- let x = g(o, void 0) ?? g(h.get("productId"), void 0), S = g(s, void 0) ?? g(h.get("moduleId"), void 0), C = _(c, void 0) ?? _(h.get("pageId"), void 0), { data: w, loading: T } = t({
36
- variables: x ? { context: {
37
- productId: x,
38
- moduleId: S,
39
- pageId: C
35
+ let C = v(o, void 0) ?? v(_.get("productId"), void 0), w = v(s, void 0) ?? v(_.get("moduleId"), void 0), T = y(c, void 0) ?? y(_.get("pageId"), void 0), { data: E, loading: D } = t({
36
+ variables: C ? { context: {
37
+ productId: C,
38
+ moduleId: w,
39
+ pageId: T
40
40
  } } : void 0,
41
- skip: !x,
41
+ skip: !C,
42
42
  fetchPolicy: "cache-and-network"
43
- }), E = w?.toursForContext ?? [], D = T;
43
+ }), O = E?.toursForContext ?? [], k = D;
44
44
  return /* @__PURE__ */ u("div", {
45
45
  className: "space-y-4 sm:space-y-6 p-3 sm:p-6",
46
46
  children: [/* @__PURE__ */ u("div", { children: [/* @__PURE__ */ l("h1", {
47
47
  className: "text-xl sm:text-2xl font-bold text-text-primary",
48
- children: a("myTours.title")
48
+ children: /* @__PURE__ */ l(p, { children: a("myTours.title") })
49
49
  }), /* @__PURE__ */ l("p", {
50
50
  className: "text-sm sm:text-base text-text-secondary",
51
51
  children: a("myTours.subtitle")
52
- })] }), D && E.length === 0 ? /* @__PURE__ */ l("output", {
52
+ })] }), k && O.length === 0 ? /* @__PURE__ */ l("output", {
53
53
  className: "text-sm text-text-secondary",
54
54
  children: a("myTours.loading")
55
- }) : E.length === 0 ? /* @__PURE__ */ l("div", {
56
- className: "rounded-lg border border-dashed border-border-subtle p-8 text-center",
57
- children: /* @__PURE__ */ l("output", {
58
- className: "block text-sm text-text-secondary",
59
- children: a("myTours.empty")
60
- })
55
+ }) : O.length === 0 ? /* @__PURE__ */ l(m, {
56
+ illustration: "empty-generic",
57
+ title: a("myTours.empty")
61
58
  }) : /* @__PURE__ */ l("ul", {
62
59
  className: "grid gap-3 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",
63
- children: E.map((e) => /* @__PURE__ */ l("li", { children: /* @__PURE__ */ u(f, {
60
+ children: O.map((e) => /* @__PURE__ */ l("li", { children: /* @__PURE__ */ u(f, {
64
61
  treatment: "plain",
65
62
  className: "h-full p-4 flex flex-col gap-2 border-border-seam shadow-[var(--shadow-pop)]",
66
63
  children: [/* @__PURE__ */ u("div", {
@@ -68,7 +65,7 @@ function v() {
68
65
  children: [/* @__PURE__ */ l("h2", {
69
66
  className: "font-semibold text-text-primary line-clamp-2",
70
67
  children: e.name
71
- }), /* @__PURE__ */ l(y, {
68
+ }), /* @__PURE__ */ l(x, {
72
69
  status: e.myProgress?.status,
73
70
  tr: a
74
71
  })]
@@ -80,14 +77,14 @@ function v() {
80
77
  })]
81
78
  });
82
79
  }
83
- function y({ status: e, tr: t }) {
80
+ function x({ status: e, tr: t }) {
84
81
  switch (e) {
85
82
  case "COMPLETED": return /* @__PURE__ */ u("span", {
86
83
  className: "inline-flex items-center gap-1 text-xs text-success",
87
84
  children: [/* @__PURE__ */ l(a, { size: 14 }), t("myTours.status.completed")]
88
85
  });
89
86
  case "IN_PROGRESS": return /* @__PURE__ */ u("span", {
90
- className: "inline-flex items-center gap-1 text-xs text-warning",
87
+ className: "inline-flex items-center gap-1 text-xs text-warning motion-safe:animate-vc-glow-pulse",
91
88
  children: [/* @__PURE__ */ l(c, { size: 14 }), t("myTours.status.inProgress")]
92
89
  });
93
90
  case "SKIPPED":
@@ -102,6 +99,6 @@ function y({ status: e, tr: t }) {
102
99
  }
103
100
  }
104
101
  //#endregion
105
- export { v as MyToursPage };
102
+ export { b as MyToursPage };
106
103
 
107
104
  //# sourceMappingURL=MyToursPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MyToursPage.js","names":[],"sources":["../../../src/tours/pages/MyToursPage.tsx"],"sourcesContent":["import { useEffect, useRef } from 'react';\nimport { useSearchParams } from 'react-router-dom';\nimport { CheckCircle2, Circle, MinusCircle, Play } from 'lucide-react';\nimport {\n useGetToursForContextQuery,\n type GetToursForContextQuery,\n} from '../../generated/global-operations';\nimport { useToursContext } from '../providers/ToursProvider';\nimport { useToursI18n, type ToursTranslationKey } from '../i18n';\nimport { useEventBus } from '@burdenoff/fe-libs/shared/events';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\n\ntype TourSummary = GetToursForContextQuery['toursForContext'][number];\n\n// Plain slug validator for productId and moduleId.\nconst SLUG_PATTERN = /^[a-zA-Z0-9_-]+$/;\n\n// pageId is documented with path-style values like \"settings/team\" per\n// ToursRootProps — tighten to URL-safe characters only, but permit `/`.\nconst PAGE_PATH_PATTERN = /^[a-zA-Z0-9_\\-/]+$/;\n\nfunction safeSlug<T extends string | undefined>(\n raw: string | null | undefined,\n fallback: T\n): string | T {\n if (raw && SLUG_PATTERN.test(raw)) return raw;\n return fallback;\n}\n\nfunction safePageId<T extends string | undefined>(\n raw: string | null | undefined,\n fallback: T\n): string | T {\n if (raw && PAGE_PATH_PATTERN.test(raw)) return raw;\n return fallback;\n}\n\n/**\n * MyToursPage — user-facing browse for available tours.\n *\n * Lists tours returned by `toursForContext` (filtered to the current\n * product/module/page surface) and decorates each with the requesting\n * user's `TourUserProgress` status (Completed / In progress / Skipped /\n * Not started). Read-only — tours are actually played via the SDK overlay,\n * not via mutations on this page.\n */\nexport function MyToursPage() {\n const { tr } = useToursI18n();\n const {\n productId: shellProductId,\n moduleId: shellModuleId,\n pageId: shellPageId,\n workspaceId,\n } = useToursContext();\n const [searchParams] = useSearchParams();\n const eventBus = useEventBus();\n\n // Emit page view event exactly once per mount. A ref guard keeps the effect\n // semantically mount-only while satisfying exhaustive-deps with the real\n // dependency list, so we don't have to disable the lint rule.\n const pageViewedRef = useRef(false);\n useEffect(() => {\n if (pageViewedRef.current) return;\n pageViewedRef.current = true;\n eventBus.emit('tours.page.viewed', {\n page: '/tours',\n productId: shellProductId,\n moduleId: shellModuleId,\n pageId: shellPageId,\n workspaceId,\n });\n }, [eventBus, shellProductId, shellModuleId, shellPageId, workspaceId]);\n\n // Preferred source is the shell's productId prop (the host app knows\n // which product it is — \"workspaces\", \"vibecontrols\", \"bigconsole\", etc.).\n // Fall back to a query-param override for deep-link scenarios, but only\n // after passing a plain-slug validator so we never forward arbitrary\n // strings into the GraphQL variables. No hardcoded product default —\n // if neither source provides one, skip the query entirely so non-\n // workspaces integrations don't get workspaces tours.\n const productId =\n safeSlug(shellProductId, undefined) ?? safeSlug(searchParams.get('productId'), undefined);\n const moduleId =\n safeSlug(shellModuleId, undefined) ?? safeSlug(searchParams.get('moduleId'), undefined);\n const pageId =\n safePageId(shellPageId, undefined) ?? safePageId(searchParams.get('pageId'), undefined);\n\n const { data: toursData, loading: toursLoading } = useGetToursForContextQuery({\n variables: productId ? { context: { productId, moduleId, pageId } } : undefined,\n skip: !productId,\n fetchPolicy: 'cache-and-network',\n });\n\n const tours = toursData?.toursForContext ?? [];\n const isLoading = toursLoading;\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-text-primary\">{tr('myTours.title')}</h1>\n <p className=\"text-sm sm:text-base text-text-secondary\">{tr('myTours.subtitle')}</p>\n </div>\n\n {isLoading && tours.length === 0 ? (\n <output className=\"text-sm text-text-secondary\">{tr('myTours.loading')}</output>\n ) : tours.length === 0 ? (\n <div className=\"rounded-lg border border-dashed border-border-subtle p-8 text-center\">\n <output className=\"block text-sm text-text-secondary\">{tr('myTours.empty')}</output>\n </div>\n ) : (\n <ul className=\"grid gap-3 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3\">\n {tours.map((tour: TourSummary) => (\n <li key={tour.id}>\n <GlassCard\n treatment=\"plain\"\n className=\"h-full p-4 flex flex-col gap-2 border-border-seam shadow-[var(--shadow-pop)]\"\n >\n <div className=\"flex items-start justify-between gap-2\">\n <h2 className=\"font-semibold text-text-primary line-clamp-2\">{tour.name}</h2>\n <ProgressBadge status={tour.myProgress?.status} tr={tr} />\n </div>\n {tour.description ? (\n <p className=\"text-sm text-text-secondary line-clamp-3\">{tour.description}</p>\n ) : null}\n </GlassCard>\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n}\n\nfunction ProgressBadge({\n status,\n tr,\n}: {\n status: string | undefined;\n tr: (key: ToursTranslationKey) => string;\n}) {\n switch (status) {\n case 'COMPLETED':\n return (\n <span className=\"inline-flex items-center gap-1 text-xs text-success\">\n <CheckCircle2 size={14} />\n {tr('myTours.status.completed')}\n </span>\n );\n case 'IN_PROGRESS':\n return (\n <span className=\"inline-flex items-center gap-1 text-xs text-warning\">\n <Play size={14} />\n {tr('myTours.status.inProgress')}\n </span>\n );\n case 'SKIPPED':\n case 'DISMISSED':\n return (\n <span className=\"inline-flex items-center gap-1 text-xs text-text-secondary\">\n <MinusCircle size={14} />\n {tr('myTours.status.skipped')}\n </span>\n );\n default:\n return (\n <span className=\"inline-flex items-center gap-1 text-xs text-text-secondary\">\n <Circle size={14} />\n {tr('myTours.status.notStarted')}\n </span>\n );\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"MyToursPage.js","names":[],"sources":["../../../src/tours/pages/MyToursPage.tsx"],"sourcesContent":["import { useEffect, useRef } from 'react';\nimport { useSearchParams } from 'react-router-dom';\nimport { CheckCircle2, Circle, MinusCircle, Play } from 'lucide-react';\nimport {\n useGetToursForContextQuery,\n type GetToursForContextQuery,\n} from '../../generated/global-operations';\nimport { useToursContext } from '../providers/ToursProvider';\nimport { useToursI18n, type ToursTranslationKey } from '../i18n';\nimport { useEventBus } from '@burdenoff/fe-libs/shared/events';\nimport { GlassCard, GradientText, IllustratedEmptyState } from '@burdenoff/fe-libs/ui';\n\ntype TourSummary = GetToursForContextQuery['toursForContext'][number];\n\n// Plain slug validator for productId and moduleId.\nconst SLUG_PATTERN = /^[a-zA-Z0-9_-]+$/;\n\n// pageId is documented with path-style values like \"settings/team\" per\n// ToursRootProps — tighten to URL-safe characters only, but permit `/`.\nconst PAGE_PATH_PATTERN = /^[a-zA-Z0-9_\\-/]+$/;\n\nfunction safeSlug<T extends string | undefined>(\n raw: string | null | undefined,\n fallback: T\n): string | T {\n if (raw && SLUG_PATTERN.test(raw)) return raw;\n return fallback;\n}\n\nfunction safePageId<T extends string | undefined>(\n raw: string | null | undefined,\n fallback: T\n): string | T {\n if (raw && PAGE_PATH_PATTERN.test(raw)) return raw;\n return fallback;\n}\n\n/**\n * MyToursPage — user-facing browse for available tours.\n *\n * Lists tours returned by `toursForContext` (filtered to the current\n * product/module/page surface) and decorates each with the requesting\n * user's `TourUserProgress` status (Completed / In progress / Skipped /\n * Not started). Read-only — tours are actually played via the SDK overlay,\n * not via mutations on this page.\n */\nexport function MyToursPage() {\n const { tr } = useToursI18n();\n const {\n productId: shellProductId,\n moduleId: shellModuleId,\n pageId: shellPageId,\n workspaceId,\n } = useToursContext();\n const [searchParams] = useSearchParams();\n const eventBus = useEventBus();\n\n // Emit page view event exactly once per mount. A ref guard keeps the effect\n // semantically mount-only while satisfying exhaustive-deps with the real\n // dependency list, so we don't have to disable the lint rule.\n const pageViewedRef = useRef(false);\n useEffect(() => {\n if (pageViewedRef.current) return;\n pageViewedRef.current = true;\n eventBus.emit('tours.page.viewed', {\n page: '/tours',\n productId: shellProductId,\n moduleId: shellModuleId,\n pageId: shellPageId,\n workspaceId,\n });\n }, [eventBus, shellProductId, shellModuleId, shellPageId, workspaceId]);\n\n // Preferred source is the shell's productId prop (the host app knows\n // which product it is — \"workspaces\", \"vibecontrols\", \"bigconsole\", etc.).\n // Fall back to a query-param override for deep-link scenarios, but only\n // after passing a plain-slug validator so we never forward arbitrary\n // strings into the GraphQL variables. No hardcoded product default —\n // if neither source provides one, skip the query entirely so non-\n // workspaces integrations don't get workspaces tours.\n const productId =\n safeSlug(shellProductId, undefined) ?? safeSlug(searchParams.get('productId'), undefined);\n const moduleId =\n safeSlug(shellModuleId, undefined) ?? safeSlug(searchParams.get('moduleId'), undefined);\n const pageId =\n safePageId(shellPageId, undefined) ?? safePageId(searchParams.get('pageId'), undefined);\n\n const { data: toursData, loading: toursLoading } = useGetToursForContextQuery({\n variables: productId ? { context: { productId, moduleId, pageId } } : undefined,\n skip: !productId,\n fetchPolicy: 'cache-and-network',\n });\n\n const tours = toursData?.toursForContext ?? [];\n const isLoading = toursLoading;\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-text-primary\">\n <GradientText>{tr('myTours.title')}</GradientText>\n </h1>\n <p className=\"text-sm sm:text-base text-text-secondary\">{tr('myTours.subtitle')}</p>\n </div>\n\n {isLoading && tours.length === 0 ? (\n <output className=\"text-sm text-text-secondary\">{tr('myTours.loading')}</output>\n ) : tours.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-generic\"\n title={tr('myTours.empty')}\n />\n ) : (\n <ul className=\"grid gap-3 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3\">\n {tours.map((tour: TourSummary) => (\n <li key={tour.id}>\n <GlassCard\n treatment=\"plain\"\n className=\"h-full p-4 flex flex-col gap-2 border-border-seam shadow-[var(--shadow-pop)]\"\n >\n <div className=\"flex items-start justify-between gap-2\">\n <h2 className=\"font-semibold text-text-primary line-clamp-2\">{tour.name}</h2>\n <ProgressBadge status={tour.myProgress?.status} tr={tr} />\n </div>\n {tour.description ? (\n <p className=\"text-sm text-text-secondary line-clamp-3\">{tour.description}</p>\n ) : null}\n </GlassCard>\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n}\n\nfunction ProgressBadge({\n status,\n tr,\n}: {\n status: string | undefined;\n tr: (key: ToursTranslationKey) => string;\n}) {\n switch (status) {\n case 'COMPLETED':\n return (\n <span className=\"inline-flex items-center gap-1 text-xs text-success\">\n <CheckCircle2 size={14} />\n {tr('myTours.status.completed')}\n </span>\n );\n case 'IN_PROGRESS':\n return (\n <span className=\"inline-flex items-center gap-1 text-xs text-warning motion-safe:animate-vc-glow-pulse\">\n <Play size={14} />\n {tr('myTours.status.inProgress')}\n </span>\n );\n case 'SKIPPED':\n case 'DISMISSED':\n return (\n <span className=\"inline-flex items-center gap-1 text-xs text-text-secondary\">\n <MinusCircle size={14} />\n {tr('myTours.status.skipped')}\n </span>\n );\n default:\n return (\n <span className=\"inline-flex items-center gap-1 text-xs text-text-secondary\">\n <Circle size={14} />\n {tr('myTours.status.notStarted')}\n </span>\n );\n }\n}\n"],"mappings":"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"}
@@ -6,278 +6,285 @@ import { useTourLifecycle as i } from "../hooks/useTourLifecycle.js";
6
6
  import { useToursPermissionAccess as a } from "../hooks/useToursPermissionAccess.js";
7
7
  import { TOUR_PERMISSIONS as o } from "../../constants/permissions.js";
8
8
  import { useToursI18n as s } from "../i18n.js";
9
- import { isNative as c, nativeConfirm as l, nativeImpact as u, nativeNotify as d, nativeToast as f } from "../../utils/nativeBridge.js";
10
- import { useEffect as p, useState as m } from "react";
11
- import { PermissionGate as h } from "@burdenoff/fe-libs/shared/components";
12
- import { Eye as g, Grid as _, List as v, ListOrdered as y, Plus as b, Search as x, Settings as S } from "lucide-react";
13
- import { jsx as C, jsxs as w } from "react/jsx-runtime";
14
- import { useNavigate as T } from "react-router-dom";
15
- import { Button as E, CTAOverflowMenu as D, GlassCard as O } from "@burdenoff/fe-libs/ui";
9
+ import { isNative as c, nativeConfirm as ee, nativeImpact as l, nativeNotify as u, nativeToast as d } from "../../utils/nativeBridge.js";
10
+ import { useEffect as f, useState as p } from "react";
11
+ import { PermissionGate as m } from "@burdenoff/fe-libs/shared/components";
12
+ import { Eye as h, Grid as g, List as _, ListOrdered as v, Plus as y, Search as b, Settings as x } from "lucide-react";
13
+ import { jsx as S, jsxs as C } from "react/jsx-runtime";
14
+ import { useNavigate as w } from "react-router-dom";
15
+ import { AuroraBackground as T, Button as E, CTAOverflowMenu as D, GlassCard as O, GradientText as k, IllustratedEmptyState as A } from "@burdenoff/fe-libs/ui";
16
16
  //#region src/tours/pages/ToursListPage.tsx
17
- function k() {
18
- let { tr: k } = s(), A = T(), { basePath: j = "/" } = e(), { viewMode: M, tourFilter: N, toursListRevision: P, setViewMode: F, updateTourFilter: I, notifyToursListChanged: L } = t(), { hasPermission: R, isLoading: z } = a(), B = R(o.TOUR_UPDATE), V = R(o.TOUR_STEP_UPDATE), H = R(o.TOUR_READ), U = R(o.TOUR_DELETE), W = R(o.TOUR_PUBLISH), G = R(o.TOUR_ARCHIVE), K = R(o.TOUR_DUPLICATE), { tours: q, loading: ee, fetchTours: J } = r(), { publishTour: Y, unpublishTour: X, archiveTour: Z, duplicateTour: Q } = i(), [$] = n(), [te, ne] = m(""), [re, ie] = m("all");
19
- p(() => {
20
- z || J({ ...N });
17
+ function j() {
18
+ let { tr: j } = s(), M = w(), { basePath: N = "/" } = e(), { viewMode: P, tourFilter: F, toursListRevision: I, setViewMode: L, updateTourFilter: R, notifyToursListChanged: z } = t(), { hasPermission: B, isLoading: V } = a(), H = B(o.TOUR_UPDATE), U = B(o.TOUR_STEP_UPDATE), W = B(o.TOUR_READ), G = B(o.TOUR_DELETE), K = B(o.TOUR_PUBLISH), te = B(o.TOUR_ARCHIVE), q = B(o.TOUR_DUPLICATE), { tours: J, loading: Y, fetchTours: X } = r(), { publishTour: Z, unpublishTour: Q, archiveTour: ne, duplicateTour: re } = i(), [ie] = n(), [ae, oe] = p(""), [se, ce] = p("all");
19
+ f(() => {
20
+ V || X({ ...F });
21
21
  }, [
22
- J,
23
- N,
24
- P,
25
- z
22
+ X,
23
+ F,
24
+ I,
25
+ V
26
26
  ]);
27
- let ae = (e) => {
28
- ne(e), I({ search: e });
29
- }, oe = (e) => {
30
- ie(e), I({ status: e });
31
- }, se = () => {
32
- A(j.endsWith("/") ? `${j}new` : `${j}/new`);
33
- }, ce = (e) => {
27
+ let le = (e) => {
28
+ oe(e), R({ search: e });
29
+ }, ue = (e) => {
30
+ ce(e), R({ status: e });
31
+ }, $ = () => {
32
+ M(N.endsWith("/") ? `${N}new` : `${N}/new`);
33
+ }, de = (e) => {
34
34
  switch (e) {
35
- case "DRAFT": return k("toursList.statusDraft");
36
- case "PUBLISHED": return k("toursList.statusPublished");
37
- case "ARCHIVED": return k("toursList.statusArchived");
38
- case "SCHEDULED": return k("toursList.statusScheduled");
35
+ case "DRAFT": return j("toursList.statusDraft");
36
+ case "PUBLISHED": return j("toursList.statusPublished");
37
+ case "ARCHIVED": return j("toursList.statusArchived");
38
+ case "SCHEDULED": return j("toursList.statusScheduled");
39
39
  }
40
- }, le = async (e) => {
41
- u("light");
40
+ }, fe = async (e) => {
41
+ l("light");
42
42
  try {
43
- await Y(e), d("success");
43
+ await Z(e), u("success");
44
44
  } catch {
45
- d("error"), c() ? f(k("toursList.errorPublish")) : alert(k("toursList.errorPublish"));
45
+ u("error"), c() ? d(j("toursList.errorPublish")) : alert(j("toursList.errorPublish"));
46
46
  }
47
- }, ue = async (e) => {
48
- u("light");
47
+ }, pe = async (e) => {
48
+ l("light");
49
49
  try {
50
- await X(e), d("success");
50
+ await Q(e), u("success");
51
51
  } catch {
52
- d("error"), c() ? f(k("toursList.errorUnpublish")) : alert(k("toursList.errorUnpublish"));
52
+ u("error"), c() ? d(j("toursList.errorUnpublish")) : alert(j("toursList.errorUnpublish"));
53
53
  }
54
- }, de = async (e) => {
55
- u("light");
54
+ }, me = async (e) => {
55
+ l("light");
56
56
  try {
57
- await Z(e), d("success");
57
+ await ne(e), u("success");
58
58
  } catch {
59
- d("error"), c() ? f(k("toursList.errorArchive")) : alert(k("toursList.errorArchive"));
59
+ u("error"), c() ? d(j("toursList.errorArchive")) : alert(j("toursList.errorArchive"));
60
60
  }
61
- }, fe = async (e) => {
62
- u("light");
61
+ }, he = async (e) => {
62
+ l("light");
63
63
  try {
64
- await Q(e), d("success");
64
+ await re(e), u("success");
65
65
  } catch {
66
- d("error"), c() ? f(k("toursList.errorDuplicate")) : alert(k("toursList.errorDuplicate"));
66
+ u("error"), c() ? d(j("toursList.errorDuplicate")) : alert(j("toursList.errorDuplicate"));
67
67
  }
68
- }, pe = async (e) => {
69
- u("medium");
70
- let t = k("toursList.confirmDelete"), n = await l({
71
- title: k("toursList.actionDelete"),
68
+ }, ge = async (e) => {
69
+ l("medium");
70
+ let t = j("toursList.confirmDelete"), n = await ee({
71
+ title: j("toursList.actionDelete"),
72
72
  message: t,
73
- okButtonTitle: k("toursList.actionDelete")
73
+ okButtonTitle: j("toursList.actionDelete")
74
74
  });
75
75
  if (n === null ? window.confirm(t) : n) try {
76
- await $({ variables: { id: e } }), L(), d("success");
76
+ await ie({ variables: { id: e } }), z(), u("success");
77
77
  } catch {
78
- d("error"), c() ? f(k("toursList.errorDelete")) : alert(k("toursList.errorDelete"));
78
+ u("error"), c() ? d(j("toursList.errorDelete")) : alert(j("toursList.errorDelete"));
79
79
  }
80
80
  };
81
- return /* @__PURE__ */ w("div", {
81
+ return /* @__PURE__ */ C("div", {
82
82
  className: "space-y-4 sm:space-y-6 p-3 sm:p-6",
83
83
  children: [
84
- /* @__PURE__ */ w("div", {
85
- className: "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3",
86
- children: [/* @__PURE__ */ w("div", {
87
- className: "flex-1 min-w-0",
88
- children: [/* @__PURE__ */ C("h1", {
89
- className: "text-xl sm:text-2xl font-bold text-text-primary",
90
- children: k("toursList.title")
91
- }), /* @__PURE__ */ C("p", {
92
- className: "text-sm sm:text-base text-text-secondary",
93
- children: k("toursList.subtitle")
84
+ /* @__PURE__ */ C("div", {
85
+ className: "relative overflow-hidden rounded-xl",
86
+ children: [/* @__PURE__ */ S(T, { intensity: "subtle" }), /* @__PURE__ */ C("div", {
87
+ className: "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 p-1 sm:p-2",
88
+ children: [/* @__PURE__ */ C("div", {
89
+ className: "flex-1 min-w-0",
90
+ children: [/* @__PURE__ */ S("h1", {
91
+ className: "text-xl sm:text-2xl font-bold text-text-primary",
92
+ children: /* @__PURE__ */ S(k, { children: j("toursList.title") })
93
+ }), /* @__PURE__ */ S("p", {
94
+ className: "text-sm sm:text-base text-text-secondary",
95
+ children: j("toursList.subtitle")
96
+ })]
97
+ }), /* @__PURE__ */ S(m, {
98
+ permission: o.TOUR_CREATE,
99
+ children: /* @__PURE__ */ C(E, {
100
+ type: "button",
101
+ onClick: $,
102
+ className: "w-full sm:w-auto min-h-[44px]",
103
+ children: [/* @__PURE__ */ S(y, { size: 20 }), j("toursList.createTour")]
104
+ })
94
105
  })]
95
- }), /* @__PURE__ */ C(h, {
96
- permission: o.TOUR_CREATE,
97
- children: /* @__PURE__ */ w(E, {
98
- type: "button",
99
- onClick: se,
100
- className: "w-full sm:w-auto min-h-[44px]",
101
- children: [/* @__PURE__ */ C(b, { size: 20 }), k("toursList.createTour")]
102
- })
103
106
  })]
104
107
  }),
105
- /* @__PURE__ */ w("div", {
108
+ /* @__PURE__ */ C("div", {
106
109
  className: "flex flex-col sm:flex-row gap-3 sm:gap-4",
107
- children: [/* @__PURE__ */ w("div", {
110
+ children: [/* @__PURE__ */ C("div", {
108
111
  className: "flex-1 relative",
109
- children: [/* @__PURE__ */ C(x, {
112
+ children: [/* @__PURE__ */ S(b, {
110
113
  className: "absolute left-3 top-1/2 -translate-y-1/2 text-text-secondary",
111
114
  size: 20
112
- }), /* @__PURE__ */ C("input", {
115
+ }), /* @__PURE__ */ S("input", {
113
116
  type: "text",
114
- placeholder: k("toursList.searchPlaceholder"),
115
- value: te,
116
- onChange: (e) => ae(e.target.value),
117
+ placeholder: j("toursList.searchPlaceholder"),
118
+ value: ae,
119
+ onChange: (e) => le(e.target.value),
117
120
  className: "w-full pl-[3.25rem] pr-4 py-2 min-h-[44px] border border-border-subtle rounded-md bg-bg-surface text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
118
- "aria-label": k("toursList.searchPlaceholder")
121
+ "aria-label": j("toursList.searchPlaceholder")
119
122
  })]
120
- }), /* @__PURE__ */ w("div", {
123
+ }), /* @__PURE__ */ C("div", {
121
124
  className: "flex gap-2",
122
- children: [/* @__PURE__ */ w("select", {
123
- value: re,
124
- onChange: (e) => oe(e.target.value),
125
+ children: [/* @__PURE__ */ C("select", {
126
+ value: se,
127
+ onChange: (e) => ue(e.target.value),
125
128
  className: "px-4 py-2 min-h-[44px] border border-border-subtle rounded-md bg-bg-surface text-text-primary",
126
- "aria-label": k("toursList.statusAll"),
129
+ "aria-label": j("toursList.statusAll"),
127
130
  children: [
128
- /* @__PURE__ */ C("option", {
131
+ /* @__PURE__ */ S("option", {
129
132
  value: "all",
130
- children: k("toursList.statusAll")
133
+ children: j("toursList.statusAll")
131
134
  }),
132
- /* @__PURE__ */ C("option", {
135
+ /* @__PURE__ */ S("option", {
133
136
  value: "DRAFT",
134
- children: k("toursList.statusDraft")
137
+ children: j("toursList.statusDraft")
135
138
  }),
136
- /* @__PURE__ */ C("option", {
139
+ /* @__PURE__ */ S("option", {
137
140
  value: "PUBLISHED",
138
- children: k("toursList.statusPublished")
141
+ children: j("toursList.statusPublished")
139
142
  }),
140
- /* @__PURE__ */ C("option", {
143
+ /* @__PURE__ */ S("option", {
141
144
  value: "ARCHIVED",
142
- children: k("toursList.statusArchived")
145
+ children: j("toursList.statusArchived")
143
146
  }),
144
- /* @__PURE__ */ C("option", {
147
+ /* @__PURE__ */ S("option", {
145
148
  value: "SCHEDULED",
146
- children: k("toursList.statusScheduled")
149
+ children: j("toursList.statusScheduled")
147
150
  })
148
151
  ]
149
- }), /* @__PURE__ */ w("div", {
152
+ }), /* @__PURE__ */ C("div", {
150
153
  className: "flex border border-border-subtle rounded-md overflow-hidden",
151
- children: [/* @__PURE__ */ C("button", {
154
+ children: [/* @__PURE__ */ S("button", {
152
155
  type: "button",
153
- onClick: () => F("grid"),
154
- className: `px-3 py-2 min-h-[44px] ${M === "grid" ? "bg-action-primary-bg text-action-primary-text" : "bg-bg-surface text-text-primary hover:bg-accent"}`,
155
- "aria-label": k("toursList.gridView"),
156
- title: k("toursList.gridView"),
157
- children: /* @__PURE__ */ C(_, { size: 20 })
158
- }), /* @__PURE__ */ C("button", {
156
+ onClick: () => L("grid"),
157
+ className: `px-3 py-2 min-h-[44px] ${P === "grid" ? "bg-action-primary-bg text-action-primary-text" : "bg-bg-surface text-text-primary hover:bg-accent"}`,
158
+ "aria-label": j("toursList.gridView"),
159
+ title: j("toursList.gridView"),
160
+ children: /* @__PURE__ */ S(g, { size: 20 })
161
+ }), /* @__PURE__ */ S("button", {
159
162
  type: "button",
160
- onClick: () => F("list"),
161
- className: `px-3 py-2 min-h-[44px] ${M === "list" ? "bg-action-primary-bg text-action-primary-text" : "bg-bg-surface text-text-primary hover:bg-accent"}`,
162
- "aria-label": k("toursList.listView"),
163
- title: k("toursList.listView"),
164
- children: /* @__PURE__ */ C(v, { size: 20 })
163
+ onClick: () => L("list"),
164
+ className: `px-3 py-2 min-h-[44px] ${P === "list" ? "bg-action-primary-bg text-action-primary-text" : "bg-bg-surface text-text-primary hover:bg-accent"}`,
165
+ "aria-label": j("toursList.listView"),
166
+ title: j("toursList.listView"),
167
+ children: /* @__PURE__ */ S(_, { size: 20 })
165
168
  })]
166
169
  })]
167
170
  })]
168
171
  }),
169
- ee ? /* @__PURE__ */ C("div", {
172
+ Y ? /* @__PURE__ */ S("div", {
170
173
  className: "text-center py-12",
171
- children: /* @__PURE__ */ C("p", {
174
+ children: /* @__PURE__ */ S("p", {
172
175
  className: "text-sm sm:text-base text-text-secondary",
173
- children: k("toursList.loading")
176
+ children: j("toursList.loading")
174
177
  })
175
- }) : q.length > 0 ? /* @__PURE__ */ C("div", {
176
- className: M === "grid" ? "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 sm:gap-4" : "space-y-3",
177
- children: q.map((e) => {
178
- let t = e.status, n = t === "DRAFT" && W, r = t === "PUBLISHED" && W, i = t !== "ARCHIVED" && G, a = [];
178
+ }) : J.length > 0 ? /* @__PURE__ */ S("div", {
179
+ className: P === "grid" ? "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 sm:gap-4" : "space-y-3",
180
+ children: J.map((e) => {
181
+ let t = e.status, n = t === "DRAFT" && K, r = t === "PUBLISHED" && K, i = t !== "ARCHIVED" && te, a = [];
179
182
  return n && a.push({
180
- label: k("toursList.actionPublish"),
181
- onSelect: () => void le(e.id)
182
- }), r && a.push({
183
- label: k("toursList.actionUnpublish"),
184
- onSelect: () => void ue(e.id)
185
- }), K && a.push({
186
- label: k("toursList.actionDuplicate"),
183
+ label: j("toursList.actionPublish"),
187
184
  onSelect: () => void fe(e.id)
185
+ }), r && a.push({
186
+ label: j("toursList.actionUnpublish"),
187
+ onSelect: () => void pe(e.id)
188
+ }), q && a.push({
189
+ label: j("toursList.actionDuplicate"),
190
+ onSelect: () => void he(e.id)
188
191
  }), i && a.push({
189
- label: k("toursList.actionArchive"),
190
- onSelect: () => void de(e.id)
191
- }), U && a.push({
192
- label: k("toursList.actionDelete"),
193
- onSelect: () => void pe(e.id),
192
+ label: j("toursList.actionArchive"),
193
+ onSelect: () => void me(e.id)
194
+ }), G && a.push({
195
+ label: j("toursList.actionDelete"),
196
+ onSelect: () => void ge(e.id),
194
197
  intent: "destructive"
195
- }), /* @__PURE__ */ w(O, {
198
+ }), /* @__PURE__ */ C(O, {
196
199
  treatment: "plain",
197
200
  className: "p-4 border-border-seam shadow-[var(--shadow-pop)]",
198
201
  children: [
199
- /* @__PURE__ */ w("div", {
202
+ /* @__PURE__ */ C("div", {
200
203
  className: "flex items-start justify-between mb-2",
201
- children: [/* @__PURE__ */ C("h3", {
204
+ children: [/* @__PURE__ */ S("h3", {
202
205
  className: "font-semibold text-text-primary",
203
- children: B ? /* @__PURE__ */ C("button", {
206
+ children: H ? /* @__PURE__ */ S("button", {
204
207
  type: "button",
205
208
  className: "cursor-pointer hover:text-primary bg-transparent border-0 p-0 text-left font-inherit",
206
- onClick: () => A(`${j}/${e.id}/edit`),
209
+ onClick: () => M(`${N}/${e.id}/edit`),
207
210
  children: e.name
208
211
  }) : e.name
209
- }), /* @__PURE__ */ C("span", {
210
- className: `px-2 py-1 text-xs rounded-full ${e.status === "PUBLISHED" ? "bg-success/10 text-success" : e.status === "DRAFT" ? "bg-bg-sunken text-text-secondary" : "bg-warning/10 text-warning"}`,
211
- children: ce(t)
212
+ }), /* @__PURE__ */ S("span", {
213
+ className: `px-2 py-1 text-xs rounded-full ${e.status === "PUBLISHED" ? "bg-success/10 text-success motion-safe:animate-vc-glow-pulse" : e.status === "DRAFT" ? "bg-bg-sunken text-text-secondary" : "bg-warning/10 text-warning"}`,
214
+ children: de(t)
212
215
  })]
213
216
  }),
214
- e.description && /* @__PURE__ */ C("p", {
217
+ e.description && /* @__PURE__ */ S("p", {
215
218
  className: "text-sm text-text-secondary mb-3",
216
219
  children: e.description
217
220
  }),
218
- /* @__PURE__ */ w("div", {
221
+ /* @__PURE__ */ C("div", {
219
222
  className: "flex items-center justify-between text-xs text-text-secondary mb-3",
220
- children: [/* @__PURE__ */ w("span", { children: [
223
+ children: [/* @__PURE__ */ C("span", { children: [
221
224
  e.steps?.length || 0,
222
225
  " ",
223
- k("toursList.steps")
224
- ] }), /* @__PURE__ */ w("span", { children: [
226
+ j("toursList.steps")
227
+ ] }), /* @__PURE__ */ C("span", { children: [
225
228
  e.viewCount,
226
229
  " ",
227
- k("toursList.views")
230
+ j("toursList.views")
228
231
  ] })]
229
232
  }),
230
- /* @__PURE__ */ w("div", {
233
+ /* @__PURE__ */ C("div", {
231
234
  className: "flex flex-wrap items-center gap-2 pt-3 border-t border-border-seam",
232
235
  children: [
233
- V && /* @__PURE__ */ w("button", {
236
+ U && /* @__PURE__ */ C("button", {
234
237
  type: "button",
235
238
  onClick: (t) => {
236
- t.stopPropagation(), A(`${j}/${e.id}/steps`);
239
+ t.stopPropagation(), M(`${N}/${e.id}/steps`);
237
240
  },
238
241
  className: "flex-1 min-w-[6.5rem] px-3 py-2 min-h-[44px] text-xs bg-secondary text-secondary-foreground rounded hover:bg-secondary/80 flex items-center justify-center gap-1.5",
239
- title: k("toursList.editStepsTitle"),
240
- children: [/* @__PURE__ */ C(y, { size: 14 }), k("toursList.stepsButton")]
242
+ title: j("toursList.editStepsTitle"),
243
+ children: [/* @__PURE__ */ S(v, { size: 14 }), j("toursList.stepsButton")]
241
244
  }),
242
- H && /* @__PURE__ */ w("button", {
245
+ W && /* @__PURE__ */ C("button", {
243
246
  type: "button",
244
247
  onClick: (t) => {
245
- t.stopPropagation(), A(`${j}/${e.id}/preview`);
248
+ t.stopPropagation(), M(`${N}/${e.id}/preview`);
246
249
  },
247
250
  className: "flex-1 min-w-[6.5rem] px-3 py-2 min-h-[44px] text-xs border border-border-seam rounded hover:bg-accent flex items-center justify-center gap-1.5",
248
- title: k("toursList.previewTitle"),
249
- children: [/* @__PURE__ */ C(g, { size: 14 }), k("toursList.previewButton")]
251
+ title: j("toursList.previewTitle"),
252
+ children: [/* @__PURE__ */ S(h, { size: 14 }), j("toursList.previewButton")]
250
253
  }),
251
- B && /* @__PURE__ */ C("button", {
254
+ H && /* @__PURE__ */ S("button", {
252
255
  type: "button",
253
256
  onClick: (t) => {
254
- t.stopPropagation(), A(`${j}/${e.id}/edit`);
257
+ t.stopPropagation(), M(`${N}/${e.id}/edit`);
255
258
  },
256
259
  className: "p-2 min-h-[44px] min-w-[44px] text-xs border border-border-seam rounded hover:bg-accent",
257
- title: k("toursList.settingsTitle"),
258
- "aria-label": k("toursList.settingsTitle"),
259
- children: /* @__PURE__ */ C(S, { size: 14 })
260
+ title: j("toursList.settingsTitle"),
261
+ "aria-label": j("toursList.settingsTitle"),
262
+ children: /* @__PURE__ */ S(x, { size: 14 })
260
263
  }),
261
- a.length > 0 && /* @__PURE__ */ C(D, { actions: a })
264
+ a.length > 0 && /* @__PURE__ */ S(D, { actions: a })
262
265
  ]
263
266
  })
264
267
  ]
265
268
  }, e.id);
266
269
  })
267
- }) : /* @__PURE__ */ w("div", {
268
- className: "text-center py-12 border border-dashed border-border-subtle rounded-md",
269
- children: [/* @__PURE__ */ C("p", {
270
- className: "text-sm sm:text-base text-text-secondary mb-2",
271
- children: k("toursList.emptyTitle")
272
- }), /* @__PURE__ */ C("p", {
273
- className: "text-xs sm:text-sm text-text-secondary",
274
- children: k("toursList.emptySubtitle")
275
- })]
270
+ }) : /* @__PURE__ */ S(A, {
271
+ illustration: "onboarding",
272
+ title: j("toursList.emptyTitle"),
273
+ description: j("toursList.emptySubtitle"),
274
+ action: /* @__PURE__ */ S(m, {
275
+ permission: o.TOUR_CREATE,
276
+ children: /* @__PURE__ */ C(E, {
277
+ type: "button",
278
+ onClick: $,
279
+ className: "min-h-[44px]",
280
+ children: [/* @__PURE__ */ S(y, { size: 20 }), j("toursList.createTour")]
281
+ })
282
+ })
276
283
  })
277
284
  ]
278
285
  });
279
286
  }
280
287
  //#endregion
281
- export { k as ToursListPage };
288
+ export { j as ToursListPage };
282
289
 
283
290
  //# sourceMappingURL=ToursListPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ToursListPage.js","names":[],"sources":["../../../src/tours/pages/ToursListPage.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { Plus, Search, Grid, List as ListIcon, ListOrdered, Eye, Settings } from 'lucide-react';\nimport { PermissionGate } from '@burdenoff/fe-libs/shared/components';\nimport { Button, GlassCard, CTAOverflowMenu, type CTAAction } from '@burdenoff/fe-libs/ui';\nimport { useToursList } from '../hooks/useToursList';\nimport { useTourLifecycle } from '../hooks/useTourLifecycle';\nimport { useToursPermissionAccess } from '../hooks/useToursPermissionAccess';\nimport { useToursStore } from '../store/toursStore';\nimport { useToursContext } from '../providers/ToursProvider';\nimport { useDeleteTourMutation } from '../../generated/global-operations';\nimport { TOUR_PERMISSIONS } from '../../constants/permissions';\nimport type { TourStatus } from '../types';\nimport type { Tour } from '../../generated/global-types';\nimport { useToursI18n } from '../i18n';\nimport {\n isNative,\n nativeConfirm,\n nativeImpact,\n nativeNotify,\n nativeToast,\n} from '../../utils/nativeBridge';\n\n/**\n * Tours list page\n * Displays all tours with filtering and search\n */\nexport function ToursListPage() {\n const { tr } = useToursI18n();\n const navigate = useNavigate();\n const { basePath = '/' } = useToursContext();\n const {\n viewMode,\n tourFilter,\n toursListRevision,\n setViewMode,\n updateTourFilter,\n notifyToursListChanged,\n } = useToursStore();\n const { hasPermission, isLoading: permissionsLoading } = useToursPermissionAccess();\n\n const canUpdateTour = hasPermission(TOUR_PERMISSIONS.TOUR_UPDATE);\n const canUpdateTourSteps = hasPermission(TOUR_PERMISSIONS.TOUR_STEP_UPDATE);\n const canPreviewTour = hasPermission(TOUR_PERMISSIONS.TOUR_READ);\n const canDeleteTour = hasPermission(TOUR_PERMISSIONS.TOUR_DELETE);\n const canPublishTour = hasPermission(TOUR_PERMISSIONS.TOUR_PUBLISH);\n const canArchiveTour = hasPermission(TOUR_PERMISSIONS.TOUR_ARCHIVE);\n const canDuplicateTour = hasPermission(TOUR_PERMISSIONS.TOUR_DUPLICATE);\n\n // Fetch tours (includes both workspace-specific and global tours)\n const { tours, loading, fetchTours } = useToursList();\n\n const { publishTour, unpublishTour, archiveTour, duplicateTour } = useTourLifecycle();\n const [deleteTourMutation] = useDeleteTourMutation();\n\n const [searchQuery, setSearchQuery] = useState('');\n const [statusFilter, setStatusFilter] = useState<TourStatus | 'all'>('all');\n\n // Fetch tours when filter changes. The list page is also the user-facing\n // tour browser, so backend permissions remain authoritative for actions while\n // normal users can still see published tours returned by the API.\n useEffect(() => {\n if (permissionsLoading) return;\n fetchTours({ ...tourFilter });\n }, [fetchTours, tourFilter, toursListRevision, permissionsLoading]);\n\n const handleSearch = (query: string) => {\n setSearchQuery(query);\n updateTourFilter({ search: query });\n };\n\n const handleStatusFilter = (status: TourStatus | 'all') => {\n setStatusFilter(status);\n updateTourFilter({ status });\n };\n\n const handleCreateTour = () => {\n const newPath = basePath.endsWith('/') ? `${basePath}new` : `${basePath}/new`;\n navigate(newPath);\n };\n\n const getStatusLabel = (status: TourStatus) => {\n switch (status) {\n case 'DRAFT':\n return tr('toursList.statusDraft');\n case 'PUBLISHED':\n return tr('toursList.statusPublished');\n case 'ARCHIVED':\n return tr('toursList.statusArchived');\n case 'SCHEDULED':\n return tr('toursList.statusScheduled');\n }\n };\n\n const handlePublish = async (id: string) => {\n nativeImpact('light');\n try {\n await publishTour(id);\n void nativeNotify('success');\n } catch {\n void nativeNotify('error');\n if (isNative()) void nativeToast(tr('toursList.errorPublish'));\n else alert(tr('toursList.errorPublish'));\n }\n };\n\n const handleUnpublish = async (id: string) => {\n nativeImpact('light');\n try {\n await unpublishTour(id);\n void nativeNotify('success');\n } catch {\n void nativeNotify('error');\n if (isNative()) void nativeToast(tr('toursList.errorUnpublish'));\n else alert(tr('toursList.errorUnpublish'));\n }\n };\n\n const handleArchive = async (id: string) => {\n nativeImpact('light');\n try {\n await archiveTour(id);\n void nativeNotify('success');\n } catch {\n void nativeNotify('error');\n if (isNative()) void nativeToast(tr('toursList.errorArchive'));\n else alert(tr('toursList.errorArchive'));\n }\n };\n\n const handleDuplicate = async (id: string) => {\n nativeImpact('light');\n try {\n await duplicateTour(id);\n void nativeNotify('success');\n } catch {\n void nativeNotify('error');\n if (isNative()) void nativeToast(tr('toursList.errorDuplicate'));\n else alert(tr('toursList.errorDuplicate'));\n }\n };\n\n const handleDelete = async (id: string) => {\n nativeImpact('medium');\n const confirmMsg = tr('toursList.confirmDelete');\n const nativeResult = await nativeConfirm({\n title: tr('toursList.actionDelete'),\n message: confirmMsg,\n okButtonTitle: tr('toursList.actionDelete'),\n });\n const confirmed = nativeResult === null ? window.confirm(confirmMsg) : nativeResult;\n if (!confirmed) return;\n try {\n await deleteTourMutation({ variables: { id } });\n notifyToursListChanged();\n void nativeNotify('success');\n } catch {\n void nativeNotify('error');\n if (isNative()) void nativeToast(tr('toursList.errorDelete'));\n else alert(tr('toursList.errorDelete'));\n }\n };\n\n return (\n <div className=\"space-y-4 sm:space-y-6 p-3 sm:p-6\">\n {/* Header */}\n <div className=\"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-text-primary\">{tr('toursList.title')}</h1>\n <p className=\"text-sm sm:text-base text-text-secondary\">{tr('toursList.subtitle')}</p>\n </div>\n <PermissionGate permission={TOUR_PERMISSIONS.TOUR_CREATE}>\n <Button\n type=\"button\"\n onClick={handleCreateTour}\n className=\"w-full sm:w-auto min-h-[44px]\"\n >\n <Plus size={20} />\n {tr('toursList.createTour')}\n </Button>\n </PermissionGate>\n </div>\n\n {/* Filters and Search */}\n <div className=\"flex flex-col sm:flex-row gap-3 sm:gap-4\">\n {/* Search */}\n <div className=\"flex-1 relative\">\n <Search\n className=\"absolute left-3 top-1/2 -translate-y-1/2 text-text-secondary\"\n size={20}\n />\n <input\n type=\"text\"\n placeholder={tr('toursList.searchPlaceholder')}\n value={searchQuery}\n onChange={(e) => handleSearch(e.target.value)}\n className=\"w-full pl-[3.25rem] pr-4 py-2 min-h-[44px] border border-border-subtle rounded-md bg-bg-surface text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n aria-label={tr('toursList.searchPlaceholder')}\n />\n </div>\n\n {/* Status Filter */}\n <div className=\"flex gap-2\">\n <select\n value={statusFilter}\n onChange={(e) => handleStatusFilter(e.target.value as TourStatus | 'all')}\n className=\"px-4 py-2 min-h-[44px] border border-border-subtle rounded-md bg-bg-surface text-text-primary\"\n aria-label={tr('toursList.statusAll')}\n >\n <option value=\"all\">{tr('toursList.statusAll')}</option>\n <option value=\"DRAFT\">{tr('toursList.statusDraft')}</option>\n <option value=\"PUBLISHED\">{tr('toursList.statusPublished')}</option>\n <option value=\"ARCHIVED\">{tr('toursList.statusArchived')}</option>\n <option value=\"SCHEDULED\">{tr('toursList.statusScheduled')}</option>\n </select>\n\n {/* View Mode Toggle */}\n <div className=\"flex border border-border-subtle rounded-md overflow-hidden\">\n <button\n type=\"button\"\n onClick={() => setViewMode('grid')}\n className={`px-3 py-2 min-h-[44px] ${\n viewMode === 'grid'\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-surface text-text-primary hover:bg-accent'\n }`}\n aria-label={tr('toursList.gridView')}\n title={tr('toursList.gridView')}\n >\n <Grid size={20} />\n </button>\n <button\n type=\"button\"\n onClick={() => setViewMode('list')}\n className={`px-3 py-2 min-h-[44px] ${\n viewMode === 'list'\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-surface text-text-primary hover:bg-accent'\n }`}\n aria-label={tr('toursList.listView')}\n title={tr('toursList.listView')}\n >\n <ListIcon size={20} />\n </button>\n </div>\n </div>\n </div>\n\n {/* Tours List */}\n {loading ? (\n <div className=\"text-center py-12\">\n <p className=\"text-sm sm:text-base text-text-secondary\">{tr('toursList.loading')}</p>\n </div>\n ) : tours.length > 0 ? (\n <div\n className={\n viewMode === 'grid'\n ? 'grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 sm:gap-4'\n : 'space-y-3'\n }\n >\n {tours.map((tour: Tour) => {\n const status = tour.status as TourStatus;\n const canShowPublishAction = status === 'DRAFT' && canPublishTour;\n const canShowUnpublishAction = status === 'PUBLISHED' && canPublishTour;\n const canShowArchiveAction = status !== 'ARCHIVED' && canArchiveTour;\n\n const overflowActions: CTAAction[] = [];\n if (canShowPublishAction) {\n overflowActions.push({\n label: tr('toursList.actionPublish'),\n onSelect: () => void handlePublish(tour.id),\n });\n }\n if (canShowUnpublishAction) {\n overflowActions.push({\n label: tr('toursList.actionUnpublish'),\n onSelect: () => void handleUnpublish(tour.id),\n });\n }\n if (canDuplicateTour) {\n overflowActions.push({\n label: tr('toursList.actionDuplicate'),\n onSelect: () => void handleDuplicate(tour.id),\n });\n }\n if (canShowArchiveAction) {\n overflowActions.push({\n label: tr('toursList.actionArchive'),\n onSelect: () => void handleArchive(tour.id),\n });\n }\n if (canDeleteTour) {\n overflowActions.push({\n label: tr('toursList.actionDelete'),\n onSelect: () => void handleDelete(tour.id),\n intent: 'destructive',\n });\n }\n\n return (\n <GlassCard\n key={tour.id}\n treatment=\"plain\"\n className=\"p-4 border-border-seam shadow-[var(--shadow-pop)]\"\n >\n <div className=\"flex items-start justify-between mb-2\">\n <h3 className=\"font-semibold text-text-primary\">\n {canUpdateTour ? (\n <button\n type=\"button\"\n className=\"cursor-pointer hover:text-primary bg-transparent border-0 p-0 text-left font-inherit\"\n onClick={() => navigate(`${basePath}/${tour.id}/edit`)}\n >\n {tour.name}\n </button>\n ) : (\n tour.name\n )}\n </h3>\n <span\n className={`px-2 py-1 text-xs rounded-full ${\n tour.status === 'PUBLISHED'\n ? 'bg-success/10 text-success'\n : tour.status === 'DRAFT'\n ? 'bg-bg-sunken text-text-secondary'\n : 'bg-warning/10 text-warning'\n }`}\n >\n {getStatusLabel(status)}\n </span>\n </div>\n {tour.description && (\n <p className=\"text-sm text-text-secondary mb-3\">{tour.description}</p>\n )}\n <div className=\"flex items-center justify-between text-xs text-text-secondary mb-3\">\n <span>\n {tour.steps?.length || 0} {tr('toursList.steps')}\n </span>\n <span>\n {tour.viewCount} {tr('toursList.views')}\n </span>\n </div>\n {/* Quick Actions */}\n <div className=\"flex flex-wrap items-center gap-2 pt-3 border-t border-border-seam\">\n {canUpdateTourSteps && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n navigate(`${basePath}/${tour.id}/steps`);\n }}\n className=\"flex-1 min-w-[6.5rem] px-3 py-2 min-h-[44px] text-xs bg-secondary text-secondary-foreground rounded hover:bg-secondary/80 flex items-center justify-center gap-1.5\"\n title={tr('toursList.editStepsTitle')}\n >\n <ListOrdered size={14} />\n {tr('toursList.stepsButton')}\n </button>\n )}\n {canPreviewTour && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n navigate(`${basePath}/${tour.id}/preview`);\n }}\n className=\"flex-1 min-w-[6.5rem] px-3 py-2 min-h-[44px] text-xs border border-border-seam rounded hover:bg-accent flex items-center justify-center gap-1.5\"\n title={tr('toursList.previewTitle')}\n >\n <Eye size={14} />\n {tr('toursList.previewButton')}\n </button>\n )}\n {canUpdateTour && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n navigate(`${basePath}/${tour.id}/edit`);\n }}\n className=\"p-2 min-h-[44px] min-w-[44px] text-xs border border-border-seam rounded hover:bg-accent\"\n title={tr('toursList.settingsTitle')}\n aria-label={tr('toursList.settingsTitle')}\n >\n <Settings size={14} />\n </button>\n )}\n {/* Lifecycle actions collapsed into the overflow menu */}\n {overflowActions.length > 0 && (\n <CTAOverflowMenu actions={overflowActions} />\n )}\n </div>\n </GlassCard>\n );\n })}\n </div>\n ) : (\n <div className=\"text-center py-12 border border-dashed border-border-subtle rounded-md\">\n <p className=\"text-sm sm:text-base text-text-secondary mb-2\">\n {tr('toursList.emptyTitle')}\n </p>\n <p className=\"text-xs sm:text-sm text-text-secondary\">\n {tr('toursList.emptySubtitle')}\n </p>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA2BA,SAAgB,IAAgB;CAC9B,IAAM,EAAE,UAAO,GAAc,EACvB,IAAW,GAAa,EACxB,EAAE,cAAW,QAAQ,GAAiB,EACtC,EACJ,aACA,eACA,sBACA,gBACA,qBACA,8BACE,GAAe,EACb,EAAE,kBAAe,WAAW,MAAuB,GAA0B,EAE7E,IAAgB,EAAc,EAAiB,YAAY,EAC3D,IAAqB,EAAc,EAAiB,iBAAiB,EACrE,IAAiB,EAAc,EAAiB,UAAU,EAC1D,IAAgB,EAAc,EAAiB,YAAY,EAC3D,IAAiB,EAAc,EAAiB,aAAa,EAC7D,IAAiB,EAAc,EAAiB,aAAa,EAC7D,IAAmB,EAAc,EAAiB,eAAe,EAGjE,EAAE,UAAO,aAAS,kBAAe,GAAc,EAE/C,EAAE,gBAAa,kBAAe,gBAAa,qBAAkB,GAAkB,EAC/E,CAAC,KAAsB,GAAuB,EAE9C,CAAC,IAAa,MAAkB,EAAS,GAAG,EAC5C,CAAC,IAAc,MAAmB,EAA6B,MAAM;AAK3E,SAAgB;AACV,OACJ,EAAW,EAAE,GAAG,GAAY,CAAC;IAC5B;EAAC;EAAY;EAAY;EAAmB;EAAmB,CAAC;CAEnE,IAAM,MAAgB,MAAkB;AAEtC,EADA,GAAe,EAAM,EACrB,EAAiB,EAAE,QAAQ,GAAO,CAAC;IAG/B,MAAsB,MAA+B;AAEzD,EADA,GAAgB,EAAO,EACvB,EAAiB,EAAE,WAAQ,CAAC;IAGxB,WAAyB;AAE7B,IADgB,EAAS,SAAS,IAAI,GAAG,GAAG,EAAS,OAAO,GAAG,EAAS,MACvD;IAGb,MAAkB,MAAuB;AAC7C,UAAQ,GAAR;GACE,KAAK,QACH,QAAO,EAAG,wBAAwB;GACpC,KAAK,YACH,QAAO,EAAG,4BAA4B;GACxC,KAAK,WACH,QAAO,EAAG,2BAA2B;GACvC,KAAK,YACH,QAAO,EAAG,4BAA4B;;IAItC,KAAgB,OAAO,MAAe;AAC1C,IAAa,QAAQ;AACrB,MAAI;AAEG,GADL,MAAM,EAAY,EAAG,EAChB,EAAa,UAAU;UACtB;AAEN,GADK,EAAa,QAAQ,EACtB,GAAU,GAAO,EAAY,EAAG,yBAAyB,CAAC,GACzD,MAAM,EAAG,yBAAyB,CAAC;;IAItC,KAAkB,OAAO,MAAe;AAC5C,IAAa,QAAQ;AACrB,MAAI;AAEG,GADL,MAAM,EAAc,EAAG,EAClB,EAAa,UAAU;UACtB;AAEN,GADK,EAAa,QAAQ,EACtB,GAAU,GAAO,EAAY,EAAG,2BAA2B,CAAC,GAC3D,MAAM,EAAG,2BAA2B,CAAC;;IAIxC,KAAgB,OAAO,MAAe;AAC1C,IAAa,QAAQ;AACrB,MAAI;AAEG,GADL,MAAM,EAAY,EAAG,EAChB,EAAa,UAAU;UACtB;AAEN,GADK,EAAa,QAAQ,EACtB,GAAU,GAAO,EAAY,EAAG,yBAAyB,CAAC,GACzD,MAAM,EAAG,yBAAyB,CAAC;;IAItC,KAAkB,OAAO,MAAe;AAC5C,IAAa,QAAQ;AACrB,MAAI;AAEG,GADL,MAAM,EAAc,EAAG,EAClB,EAAa,UAAU;UACtB;AAEN,GADK,EAAa,QAAQ,EACtB,GAAU,GAAO,EAAY,EAAG,2BAA2B,CAAC,GAC3D,MAAM,EAAG,2BAA2B,CAAC;;IAIxC,KAAe,OAAO,MAAe;AACzC,IAAa,SAAS;EACtB,IAAM,IAAa,EAAG,0BAA0B,EAC1C,IAAe,MAAM,EAAc;GACvC,OAAO,EAAG,yBAAyB;GACnC,SAAS;GACT,eAAe,EAAG,yBAAyB;GAC5C,CAAC;AACgB,YAAiB,OAAO,OAAO,QAAQ,EAAW,GAAG,EAEvE,KAAI;AAGG,GAFL,MAAM,EAAmB,EAAE,WAAW,EAAE,OAAI,EAAE,CAAC,EAC/C,GAAwB,EACnB,EAAa,UAAU;UACtB;AAEN,GADK,EAAa,QAAQ,EACtB,GAAU,GAAO,EAAY,EAAG,wBAAwB,CAAC,GACxD,MAAM,EAAG,wBAAwB,CAAC;;;AAI3C,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GAEE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,MAAD;MAAI,WAAU;gBAAmD,EAAG,kBAAkB;MAAM,CAAA,EAC5F,kBAAC,KAAD;MAAG,WAAU;gBAA4C,EAAG,qBAAqB;MAAK,CAAA,CAClF;QACN,kBAAC,GAAD;KAAgB,YAAY,EAAiB;eAC3C,kBAAC,GAAD;MACE,MAAK;MACL,SAAS;MACT,WAAU;gBAHZ,CAKE,kBAAC,GAAD,EAAM,MAAM,IAAM,CAAA,EACjB,EAAG,uBAAuB,CACpB;;KACM,CAAA,CACb;;GAGN,kBAAC,OAAD;IAAK,WAAU;cAAf,CAEE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MACE,WAAU;MACV,MAAM;MACN,CAAA,EACF,kBAAC,SAAD;MACE,MAAK;MACL,aAAa,EAAG,8BAA8B;MAC9C,OAAO;MACP,WAAW,MAAM,GAAa,EAAE,OAAO,MAAM;MAC7C,WAAU;MACV,cAAY,EAAG,8BAA8B;MAC7C,CAAA,CACE;QAGN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,UAAD;MACE,OAAO;MACP,WAAW,MAAM,GAAmB,EAAE,OAAO,MAA4B;MACzE,WAAU;MACV,cAAY,EAAG,sBAAsB;gBAJvC;OAME,kBAAC,UAAD;QAAQ,OAAM;kBAAO,EAAG,sBAAsB;QAAU,CAAA;OACxD,kBAAC,UAAD;QAAQ,OAAM;kBAAS,EAAG,wBAAwB;QAAU,CAAA;OAC5D,kBAAC,UAAD;QAAQ,OAAM;kBAAa,EAAG,4BAA4B;QAAU,CAAA;OACpE,kBAAC,UAAD;QAAQ,OAAM;kBAAY,EAAG,2BAA2B;QAAU,CAAA;OAClE,kBAAC,UAAD;QAAQ,OAAM;kBAAa,EAAG,4BAA4B;QAAU,CAAA;OAC7D;SAGT,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,UAAD;OACE,MAAK;OACL,eAAe,EAAY,OAAO;OAClC,WAAW,0BACT,MAAa,SACT,kDACA;OAEN,cAAY,EAAG,qBAAqB;OACpC,OAAO,EAAG,qBAAqB;iBAE/B,kBAAC,GAAD,EAAM,MAAM,IAAM,CAAA;OACX,CAAA,EACT,kBAAC,UAAD;OACE,MAAK;OACL,eAAe,EAAY,OAAO;OAClC,WAAW,0BACT,MAAa,SACT,kDACA;OAEN,cAAY,EAAG,qBAAqB;OACpC,OAAO,EAAG,qBAAqB;iBAE/B,kBAAC,GAAD,EAAU,MAAM,IAAM,CAAA;OACf,CAAA,CACL;QACF;OACF;;GAGL,KACC,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,KAAD;KAAG,WAAU;eAA4C,EAAG,oBAAoB;KAAK,CAAA;IACjF,CAAA,GACJ,EAAM,SAAS,IACjB,kBAAC,OAAD;IACE,WACE,MAAa,SACT,kEACA;cAGL,EAAM,KAAK,MAAe;KACzB,IAAM,IAAS,EAAK,QACd,IAAuB,MAAW,WAAW,GAC7C,IAAyB,MAAW,eAAe,GACnD,IAAuB,MAAW,cAAc,GAEhD,IAA+B,EAAE;AAiCvC,YAhCI,KACF,EAAgB,KAAK;MACnB,OAAO,EAAG,0BAA0B;MACpC,gBAAgB,KAAK,GAAc,EAAK,GAAG;MAC5C,CAAC,EAEA,KACF,EAAgB,KAAK;MACnB,OAAO,EAAG,4BAA4B;MACtC,gBAAgB,KAAK,GAAgB,EAAK,GAAG;MAC9C,CAAC,EAEA,KACF,EAAgB,KAAK;MACnB,OAAO,EAAG,4BAA4B;MACtC,gBAAgB,KAAK,GAAgB,EAAK,GAAG;MAC9C,CAAC,EAEA,KACF,EAAgB,KAAK;MACnB,OAAO,EAAG,0BAA0B;MACpC,gBAAgB,KAAK,GAAc,EAAK,GAAG;MAC5C,CAAC,EAEA,KACF,EAAgB,KAAK;MACnB,OAAO,EAAG,yBAAyB;MACnC,gBAAgB,KAAK,GAAa,EAAK,GAAG;MAC1C,QAAQ;MACT,CAAC,EAIF,kBAAC,GAAD;MAEE,WAAU;MACV,WAAU;gBAHZ;OAKE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,MAAD;SAAI,WAAU;mBACX,IACC,kBAAC,UAAD;UACE,MAAK;UACL,WAAU;UACV,eAAe,EAAS,GAAG,EAAS,GAAG,EAAK,GAAG,OAAO;oBAErD,EAAK;UACC,CAAA,GAET,EAAK;SAEJ,CAAA,EACL,kBAAC,QAAD;SACE,WAAW,kCACT,EAAK,WAAW,cACZ,+BACA,EAAK,WAAW,UACd,qCACA;mBAGP,GAAe,EAAO;SAClB,CAAA,CACH;;OACL,EAAK,eACJ,kBAAC,KAAD;QAAG,WAAU;kBAAoC,EAAK;QAAgB,CAAA;OAExE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD,EAAA,UAAA;SACG,EAAK,OAAO,UAAU;SAAE;SAAE,EAAG,kBAAkB;SAC3C,EAAA,CAAA,EACP,kBAAC,QAAD,EAAA,UAAA;SACG,EAAK;SAAU;SAAE,EAAG,kBAAkB;SAClC,EAAA,CAAA,CACH;;OAEN,kBAAC,OAAD;QAAK,WAAU;kBAAf;SACG,KACC,kBAAC,UAAD;UACE,MAAK;UACL,UAAU,MAAM;AAEd,WADA,EAAE,iBAAiB,EACnB,EAAS,GAAG,EAAS,GAAG,EAAK,GAAG,QAAQ;;UAE1C,WAAU;UACV,OAAO,EAAG,2BAA2B;oBAPvC,CASE,kBAAC,GAAD,EAAa,MAAM,IAAM,CAAA,EACxB,EAAG,wBAAwB,CACrB;;SAEV,KACC,kBAAC,UAAD;UACE,MAAK;UACL,UAAU,MAAM;AAEd,WADA,EAAE,iBAAiB,EACnB,EAAS,GAAG,EAAS,GAAG,EAAK,GAAG,UAAU;;UAE5C,WAAU;UACV,OAAO,EAAG,yBAAyB;oBAPrC,CASE,kBAAC,GAAD,EAAK,MAAM,IAAM,CAAA,EAChB,EAAG,0BAA0B,CACvB;;SAEV,KACC,kBAAC,UAAD;UACE,MAAK;UACL,UAAU,MAAM;AAEd,WADA,EAAE,iBAAiB,EACnB,EAAS,GAAG,EAAS,GAAG,EAAK,GAAG,OAAO;;UAEzC,WAAU;UACV,OAAO,EAAG,0BAA0B;UACpC,cAAY,EAAG,0BAA0B;oBAEzC,kBAAC,GAAD,EAAU,MAAM,IAAM,CAAA;UACf,CAAA;SAGV,EAAgB,SAAS,KACxB,kBAAC,GAAD,EAAiB,SAAS,GAAmB,CAAA;SAE3C;;OACI;QA1FL,EAAK,GA0FA;MAEd;IACE,CAAA,GAEN,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,KAAD;KAAG,WAAU;eACV,EAAG,uBAAuB;KACzB,CAAA,EACJ,kBAAC,KAAD;KAAG,WAAU;eACV,EAAG,0BAA0B;KAC5B,CAAA,CACA;;GAEJ"}
1
+ {"version":3,"file":"ToursListPage.js","names":[],"sources":["../../../src/tours/pages/ToursListPage.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { Plus, Search, Grid, List as ListIcon, ListOrdered, Eye, Settings } from 'lucide-react';\nimport { PermissionGate } from '@burdenoff/fe-libs/shared/components';\nimport {\n AuroraBackground,\n Button,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n CTAOverflowMenu,\n type CTAAction,\n} from '@burdenoff/fe-libs/ui';\nimport { useToursList } from '../hooks/useToursList';\nimport { useTourLifecycle } from '../hooks/useTourLifecycle';\nimport { useToursPermissionAccess } from '../hooks/useToursPermissionAccess';\nimport { useToursStore } from '../store/toursStore';\nimport { useToursContext } from '../providers/ToursProvider';\nimport { useDeleteTourMutation } from '../../generated/global-operations';\nimport { TOUR_PERMISSIONS } from '../../constants/permissions';\nimport type { TourStatus } from '../types';\nimport type { Tour } from '../../generated/global-types';\nimport { useToursI18n } from '../i18n';\nimport {\n isNative,\n nativeConfirm,\n nativeImpact,\n nativeNotify,\n nativeToast,\n} from '../../utils/nativeBridge';\n\n/**\n * Tours list page\n * Displays all tours with filtering and search\n */\nexport function ToursListPage() {\n const { tr } = useToursI18n();\n const navigate = useNavigate();\n const { basePath = '/' } = useToursContext();\n const {\n viewMode,\n tourFilter,\n toursListRevision,\n setViewMode,\n updateTourFilter,\n notifyToursListChanged,\n } = useToursStore();\n const { hasPermission, isLoading: permissionsLoading } = useToursPermissionAccess();\n\n const canUpdateTour = hasPermission(TOUR_PERMISSIONS.TOUR_UPDATE);\n const canUpdateTourSteps = hasPermission(TOUR_PERMISSIONS.TOUR_STEP_UPDATE);\n const canPreviewTour = hasPermission(TOUR_PERMISSIONS.TOUR_READ);\n const canDeleteTour = hasPermission(TOUR_PERMISSIONS.TOUR_DELETE);\n const canPublishTour = hasPermission(TOUR_PERMISSIONS.TOUR_PUBLISH);\n const canArchiveTour = hasPermission(TOUR_PERMISSIONS.TOUR_ARCHIVE);\n const canDuplicateTour = hasPermission(TOUR_PERMISSIONS.TOUR_DUPLICATE);\n\n // Fetch tours (includes both workspace-specific and global tours)\n const { tours, loading, fetchTours } = useToursList();\n\n const { publishTour, unpublishTour, archiveTour, duplicateTour } = useTourLifecycle();\n const [deleteTourMutation] = useDeleteTourMutation();\n\n const [searchQuery, setSearchQuery] = useState('');\n const [statusFilter, setStatusFilter] = useState<TourStatus | 'all'>('all');\n\n // Fetch tours when filter changes. The list page is also the user-facing\n // tour browser, so backend permissions remain authoritative for actions while\n // normal users can still see published tours returned by the API.\n useEffect(() => {\n if (permissionsLoading) return;\n fetchTours({ ...tourFilter });\n }, [fetchTours, tourFilter, toursListRevision, permissionsLoading]);\n\n const handleSearch = (query: string) => {\n setSearchQuery(query);\n updateTourFilter({ search: query });\n };\n\n const handleStatusFilter = (status: TourStatus | 'all') => {\n setStatusFilter(status);\n updateTourFilter({ status });\n };\n\n const handleCreateTour = () => {\n const newPath = basePath.endsWith('/') ? `${basePath}new` : `${basePath}/new`;\n navigate(newPath);\n };\n\n const getStatusLabel = (status: TourStatus) => {\n switch (status) {\n case 'DRAFT':\n return tr('toursList.statusDraft');\n case 'PUBLISHED':\n return tr('toursList.statusPublished');\n case 'ARCHIVED':\n return tr('toursList.statusArchived');\n case 'SCHEDULED':\n return tr('toursList.statusScheduled');\n }\n };\n\n const handlePublish = async (id: string) => {\n nativeImpact('light');\n try {\n await publishTour(id);\n void nativeNotify('success');\n } catch {\n void nativeNotify('error');\n if (isNative()) void nativeToast(tr('toursList.errorPublish'));\n else alert(tr('toursList.errorPublish'));\n }\n };\n\n const handleUnpublish = async (id: string) => {\n nativeImpact('light');\n try {\n await unpublishTour(id);\n void nativeNotify('success');\n } catch {\n void nativeNotify('error');\n if (isNative()) void nativeToast(tr('toursList.errorUnpublish'));\n else alert(tr('toursList.errorUnpublish'));\n }\n };\n\n const handleArchive = async (id: string) => {\n nativeImpact('light');\n try {\n await archiveTour(id);\n void nativeNotify('success');\n } catch {\n void nativeNotify('error');\n if (isNative()) void nativeToast(tr('toursList.errorArchive'));\n else alert(tr('toursList.errorArchive'));\n }\n };\n\n const handleDuplicate = async (id: string) => {\n nativeImpact('light');\n try {\n await duplicateTour(id);\n void nativeNotify('success');\n } catch {\n void nativeNotify('error');\n if (isNative()) void nativeToast(tr('toursList.errorDuplicate'));\n else alert(tr('toursList.errorDuplicate'));\n }\n };\n\n const handleDelete = async (id: string) => {\n nativeImpact('medium');\n const confirmMsg = tr('toursList.confirmDelete');\n const nativeResult = await nativeConfirm({\n title: tr('toursList.actionDelete'),\n message: confirmMsg,\n okButtonTitle: tr('toursList.actionDelete'),\n });\n const confirmed = nativeResult === null ? window.confirm(confirmMsg) : nativeResult;\n if (!confirmed) return;\n try {\n await deleteTourMutation({ variables: { id } });\n notifyToursListChanged();\n void nativeNotify('success');\n } catch {\n void nativeNotify('error');\n if (isNative()) void nativeToast(tr('toursList.errorDelete'));\n else alert(tr('toursList.errorDelete'));\n }\n };\n\n return (\n <div className=\"space-y-4 sm:space-y-6 p-3 sm:p-6\">\n {/* Header */}\n <div className=\"relative overflow-hidden rounded-xl\">\n <AuroraBackground intensity=\"subtle\" />\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 p-1 sm:p-2\">\n <div className=\"flex-1 min-w-0\">\n <h1 className=\"text-xl sm:text-2xl font-bold text-text-primary\">\n <GradientText>{tr('toursList.title')}</GradientText>\n </h1>\n <p className=\"text-sm sm:text-base text-text-secondary\">{tr('toursList.subtitle')}</p>\n </div>\n <PermissionGate permission={TOUR_PERMISSIONS.TOUR_CREATE}>\n <Button\n type=\"button\"\n onClick={handleCreateTour}\n className=\"w-full sm:w-auto min-h-[44px]\"\n >\n <Plus size={20} />\n {tr('toursList.createTour')}\n </Button>\n </PermissionGate>\n </div>\n </div>\n\n {/* Filters and Search */}\n <div className=\"flex flex-col sm:flex-row gap-3 sm:gap-4\">\n {/* Search */}\n <div className=\"flex-1 relative\">\n <Search\n className=\"absolute left-3 top-1/2 -translate-y-1/2 text-text-secondary\"\n size={20}\n />\n <input\n type=\"text\"\n placeholder={tr('toursList.searchPlaceholder')}\n value={searchQuery}\n onChange={(e) => handleSearch(e.target.value)}\n className=\"w-full pl-[3.25rem] pr-4 py-2 min-h-[44px] border border-border-subtle rounded-md bg-bg-surface text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n aria-label={tr('toursList.searchPlaceholder')}\n />\n </div>\n\n {/* Status Filter */}\n <div className=\"flex gap-2\">\n <select\n value={statusFilter}\n onChange={(e) => handleStatusFilter(e.target.value as TourStatus | 'all')}\n className=\"px-4 py-2 min-h-[44px] border border-border-subtle rounded-md bg-bg-surface text-text-primary\"\n aria-label={tr('toursList.statusAll')}\n >\n <option value=\"all\">{tr('toursList.statusAll')}</option>\n <option value=\"DRAFT\">{tr('toursList.statusDraft')}</option>\n <option value=\"PUBLISHED\">{tr('toursList.statusPublished')}</option>\n <option value=\"ARCHIVED\">{tr('toursList.statusArchived')}</option>\n <option value=\"SCHEDULED\">{tr('toursList.statusScheduled')}</option>\n </select>\n\n {/* View Mode Toggle */}\n <div className=\"flex border border-border-subtle rounded-md overflow-hidden\">\n <button\n type=\"button\"\n onClick={() => setViewMode('grid')}\n className={`px-3 py-2 min-h-[44px] ${\n viewMode === 'grid'\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-surface text-text-primary hover:bg-accent'\n }`}\n aria-label={tr('toursList.gridView')}\n title={tr('toursList.gridView')}\n >\n <Grid size={20} />\n </button>\n <button\n type=\"button\"\n onClick={() => setViewMode('list')}\n className={`px-3 py-2 min-h-[44px] ${\n viewMode === 'list'\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-surface text-text-primary hover:bg-accent'\n }`}\n aria-label={tr('toursList.listView')}\n title={tr('toursList.listView')}\n >\n <ListIcon size={20} />\n </button>\n </div>\n </div>\n </div>\n\n {/* Tours List */}\n {loading ? (\n <div className=\"text-center py-12\">\n <p className=\"text-sm sm:text-base text-text-secondary\">{tr('toursList.loading')}</p>\n </div>\n ) : tours.length > 0 ? (\n <div\n className={\n viewMode === 'grid'\n ? 'grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 sm:gap-4'\n : 'space-y-3'\n }\n >\n {tours.map((tour: Tour) => {\n const status = tour.status as TourStatus;\n const canShowPublishAction = status === 'DRAFT' && canPublishTour;\n const canShowUnpublishAction = status === 'PUBLISHED' && canPublishTour;\n const canShowArchiveAction = status !== 'ARCHIVED' && canArchiveTour;\n\n const overflowActions: CTAAction[] = [];\n if (canShowPublishAction) {\n overflowActions.push({\n label: tr('toursList.actionPublish'),\n onSelect: () => void handlePublish(tour.id),\n });\n }\n if (canShowUnpublishAction) {\n overflowActions.push({\n label: tr('toursList.actionUnpublish'),\n onSelect: () => void handleUnpublish(tour.id),\n });\n }\n if (canDuplicateTour) {\n overflowActions.push({\n label: tr('toursList.actionDuplicate'),\n onSelect: () => void handleDuplicate(tour.id),\n });\n }\n if (canShowArchiveAction) {\n overflowActions.push({\n label: tr('toursList.actionArchive'),\n onSelect: () => void handleArchive(tour.id),\n });\n }\n if (canDeleteTour) {\n overflowActions.push({\n label: tr('toursList.actionDelete'),\n onSelect: () => void handleDelete(tour.id),\n intent: 'destructive',\n });\n }\n\n return (\n <GlassCard\n key={tour.id}\n treatment=\"plain\"\n className=\"p-4 border-border-seam shadow-[var(--shadow-pop)]\"\n >\n <div className=\"flex items-start justify-between mb-2\">\n <h3 className=\"font-semibold text-text-primary\">\n {canUpdateTour ? (\n <button\n type=\"button\"\n className=\"cursor-pointer hover:text-primary bg-transparent border-0 p-0 text-left font-inherit\"\n onClick={() => navigate(`${basePath}/${tour.id}/edit`)}\n >\n {tour.name}\n </button>\n ) : (\n tour.name\n )}\n </h3>\n <span\n className={`px-2 py-1 text-xs rounded-full ${\n tour.status === 'PUBLISHED'\n ? 'bg-success/10 text-success motion-safe:animate-vc-glow-pulse'\n : tour.status === 'DRAFT'\n ? 'bg-bg-sunken text-text-secondary'\n : 'bg-warning/10 text-warning'\n }`}\n >\n {getStatusLabel(status)}\n </span>\n </div>\n {tour.description && (\n <p className=\"text-sm text-text-secondary mb-3\">{tour.description}</p>\n )}\n <div className=\"flex items-center justify-between text-xs text-text-secondary mb-3\">\n <span>\n {tour.steps?.length || 0} {tr('toursList.steps')}\n </span>\n <span>\n {tour.viewCount} {tr('toursList.views')}\n </span>\n </div>\n {/* Quick Actions */}\n <div className=\"flex flex-wrap items-center gap-2 pt-3 border-t border-border-seam\">\n {canUpdateTourSteps && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n navigate(`${basePath}/${tour.id}/steps`);\n }}\n className=\"flex-1 min-w-[6.5rem] px-3 py-2 min-h-[44px] text-xs bg-secondary text-secondary-foreground rounded hover:bg-secondary/80 flex items-center justify-center gap-1.5\"\n title={tr('toursList.editStepsTitle')}\n >\n <ListOrdered size={14} />\n {tr('toursList.stepsButton')}\n </button>\n )}\n {canPreviewTour && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n navigate(`${basePath}/${tour.id}/preview`);\n }}\n className=\"flex-1 min-w-[6.5rem] px-3 py-2 min-h-[44px] text-xs border border-border-seam rounded hover:bg-accent flex items-center justify-center gap-1.5\"\n title={tr('toursList.previewTitle')}\n >\n <Eye size={14} />\n {tr('toursList.previewButton')}\n </button>\n )}\n {canUpdateTour && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n navigate(`${basePath}/${tour.id}/edit`);\n }}\n className=\"p-2 min-h-[44px] min-w-[44px] text-xs border border-border-seam rounded hover:bg-accent\"\n title={tr('toursList.settingsTitle')}\n aria-label={tr('toursList.settingsTitle')}\n >\n <Settings size={14} />\n </button>\n )}\n {/* Lifecycle actions collapsed into the overflow menu */}\n {overflowActions.length > 0 && (\n <CTAOverflowMenu actions={overflowActions} />\n )}\n </div>\n </GlassCard>\n );\n })}\n </div>\n ) : (\n <IllustratedEmptyState\n illustration=\"onboarding\"\n title={tr('toursList.emptyTitle')}\n description={tr('toursList.emptySubtitle')}\n action={\n <PermissionGate permission={TOUR_PERMISSIONS.TOUR_CREATE}>\n <Button type=\"button\" onClick={handleCreateTour} className=\"min-h-[44px]\">\n <Plus size={20} />\n {tr('toursList.createTour')}\n </Button>\n </PermissionGate>\n }\n />\n )}\n </div>\n );\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-tours",
3
- "version": "2026.625.1",
3
+ "version": "2026.625.2",
4
4
  "description": "Burdenoff Tours Microfrontend - Complete product tours and onboarding interface",
5
5
  "type": "module",
6
6
  "files": [
@@ -43,7 +43,7 @@
43
43
  },
44
44
  "dependencies": {
45
45
  "@apollo/client": "^3.12.0",
46
- "@burdenoff/fe-libs": "2026.625.2",
46
+ "@burdenoff/fe-libs": "2026.625.3",
47
47
  "@tanstack/react-query": "^5.90.16",
48
48
  "clsx": "^2.1.1",
49
49
  "graphql": "^16.10.0",