@burdenoff/microfe-tours 2026.525.3 → 2026.527.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.
@@ -63,8 +63,10 @@ var n = {
63
63
  "templateLibrary.title": "Tour Templates",
64
64
  "templateLibrary.useTemplate": "Use Template",
65
65
  "templateLibrary.usedTimes": "Used",
66
+ "tourBuilder.accessDeniedTitle": "Access Denied",
66
67
  "tourBuilder.analytics": "Analytics",
67
68
  "tourBuilder.createAndAddSteps": "Create & Add Steps",
69
+ "tourBuilder.createAccessDeniedMessage": "You do not have permission to create tours.",
68
70
  "tourBuilder.editSteps": "Edit Steps",
69
71
  "tourBuilder.errorTitle": "Error",
70
72
  "tourBuilder.goBack": "Go back",
@@ -73,6 +75,7 @@ var n = {
73
75
  "tourBuilder.labelPriority": "Priority (1-100)",
74
76
  "tourBuilder.labelProductId": "Product ID *",
75
77
  "tourBuilder.labelTriggerType": "Trigger Type",
78
+ "tourBuilder.loading": "Loading...",
76
79
  "tourBuilder.preview": "Preview",
77
80
  "tourBuilder.saving": "Saving...",
78
81
  "tourBuilder.sectionBasicInfo": "Basic Information",
@@ -94,6 +97,7 @@ var n = {
94
97
  "tourBuilder.triggerOnEvent": "On Event",
95
98
  "tourBuilder.triggerScheduled": "Scheduled",
96
99
  "tourBuilder.updateTour": "Update Tour",
100
+ "tourBuilder.updateAccessDeniedMessage": "You do not have permission to update this tour.",
97
101
  "tourBuilder.validationErrorsTitle": "Validation Errors",
98
102
  "tourPreview.accessDeniedMessage": "You do not have permission to preview this tour.",
99
103
  "tourPreview.accessDeniedTitle": "Access Denied",
@@ -1 +1 @@
1
- {"version":3,"file":"i18n.js","names":[],"sources":["../../src/tours/i18n.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\nconst toursTranslationFallbacks = {\n 'stepEditor.addFirstStep': 'Add First Step',\n 'stepEditor.addStep': 'Add Step',\n 'stepEditor.clickAddStep': 'Click \"Add Step\" to create one',\n 'stepEditor.closeSteps': 'Close steps',\n 'stepEditor.content': 'Content',\n 'stepEditor.contentPlaceholder': 'Enter step content or instructions',\n 'stepEditor.createFirstStep': 'Create your first step to get started',\n 'stepEditor.cssSelector': 'CSS Selector',\n 'stepEditor.cssSelectorPlaceholder': \"[data-tour='element-name'] or #id or .class\",\n 'stepEditor.dataTourHint': \"Use data-tour attributes like [data-tour='sidenav'] for best results\",\n 'stepEditor.deleteStep': 'Delete step',\n 'stepEditor.desktopSelector': 'Desktop Selector',\n 'stepEditor.deviceSelectorHint': 'Override the default selector for specific device types',\n 'stepEditor.deviceSpecificSelectors': 'Device-Specific Selectors (Advanced)',\n 'stepEditor.editStep': 'Edit Step',\n 'stepEditor.goBack': 'Go back',\n 'stepEditor.leaveEmptyDefault': 'Leave empty to use default',\n 'stepEditor.mobileSelector': 'Mobile Selector',\n 'stepEditor.noStepSelected': 'No step selected',\n 'stepEditor.noStepsYet': 'No steps yet',\n 'stepEditor.of': 'of',\n 'stepEditor.nextStep': 'Next step',\n 'stepEditor.placementAuto': 'Auto (recommended)',\n 'stepEditor.placementBottom': 'Bottom',\n 'stepEditor.placementCenter': 'Center (modal style)',\n 'stepEditor.placementLeft': 'Left',\n 'stepEditor.placementRight': 'Right',\n 'stepEditor.placementTop': 'Top',\n 'stepEditor.previousStep': 'Previous step',\n 'stepEditor.save': 'Save',\n 'stepEditor.saving': 'Saving...',\n 'stepEditor.selectStepToEdit': 'Select a step from the list to edit it',\n 'stepEditor.stepNumber': 'Step',\n 'stepEditor.steps': 'Steps',\n 'stepEditor.stepsCount': 'steps',\n 'stepEditor.stepsLabel': 'Steps',\n 'stepEditor.stepTitle': 'Step Title',\n 'stepEditor.stepTitlePlaceholder': 'Enter step title',\n 'stepEditor.tabletSelector': 'Tablet Selector',\n 'stepEditor.targetElement': 'target element',\n 'stepEditor.tooltipPlacement': 'Tooltip Placement',\n 'stepEditor.tourFallback': 'Tour',\n 'stepEditor.tourSteps': 'Tour Steps',\n 'stepEditor.untitled': 'Untitled',\n 'templateLibrary.adjustFilters': 'Try adjusting your filters or search query',\n 'templateLibrary.allCategories': 'All Categories',\n 'templateLibrary.categoryCustom': 'Custom',\n 'templateLibrary.categoryFeatureAnnouncement': 'Feature Announcement',\n 'templateLibrary.categoryHelp': 'Help',\n 'templateLibrary.categoryOnboarding': 'Onboarding',\n 'templateLibrary.deleteConfirm': 'Delete this template?',\n 'templateLibrary.deleteTemplate': 'Delete template',\n 'templateLibrary.loading': 'Loading templates...',\n 'templateLibrary.noTemplatesFound': 'No templates found',\n 'templateLibrary.publicOnly': 'Public only',\n 'templateLibrary.searchPlaceholder': 'Search templates...',\n 'templateLibrary.subtitle': 'Browse and use pre-built tour templates',\n 'templateLibrary.times': 'times',\n 'templateLibrary.title': 'Tour Templates',\n 'templateLibrary.useTemplate': 'Use Template',\n 'templateLibrary.usedTimes': 'Used',\n 'tourBuilder.analytics': 'Analytics',\n 'tourBuilder.createAndAddSteps': 'Create & Add Steps',\n 'tourBuilder.editSteps': 'Edit Steps',\n 'tourBuilder.errorTitle': 'Error',\n 'tourBuilder.goBack': 'Go back',\n 'tourBuilder.labelDescription': 'Description',\n 'tourBuilder.labelName': 'Tour Name *',\n 'tourBuilder.labelPriority': 'Priority (1-100)',\n 'tourBuilder.labelProductId': 'Product ID *',\n 'tourBuilder.labelTriggerType': 'Trigger Type',\n 'tourBuilder.preview': 'Preview',\n 'tourBuilder.saving': 'Saving...',\n 'tourBuilder.sectionBasicInfo': 'Basic Information',\n 'tourBuilder.sectionTriggerSettings': 'Trigger Settings',\n 'tourBuilder.seedVibeControls.button': 'Seed VibeControls user tours',\n 'tourBuilder.seedVibeControls.confirm':\n 'This will overwrite the built-in Support, Notifications, and Conversations user tours from the service seed file. Continue?',\n 'tourBuilder.seedVibeControls.description':\n 'Overwrites the built-in Support, Notifications, and Conversations user tours from the service seed file.',\n 'tourBuilder.seedVibeControls.error': 'Failed to seed VibeControls user tours.',\n 'tourBuilder.seedVibeControls.loading': 'Seeding...',\n 'tourBuilder.seedVibeControls.permissionHint':\n 'Requires tour create and update permissions. The service also enforces RBAC when the seed mutation runs.',\n 'tourBuilder.seedVibeControls.result':\n 'Seeded {{totalCount}} tours for {{productId}} in workspace {{workspaceId}}: {{createdCount}} created, {{updatedCount}} updated.',\n 'tourBuilder.seedVibeControls.title': 'Seed VibeControls user tours',\n 'tourBuilder.subtitle': 'Configure tour details and settings',\n 'tourBuilder.titleCreate': 'Create Tour',\n 'tourBuilder.titleEdit': 'Edit Tour',\n 'tourBuilder.triggerAutoAlways': 'Auto (Always)',\n 'tourBuilder.triggerAutoFirstVisit': 'Auto (First Visit)',\n 'tourBuilder.triggerManual': 'Manual',\n 'tourBuilder.triggerOnEvent': 'On Event',\n 'tourBuilder.triggerScheduled': 'Scheduled',\n 'tourBuilder.updateTour': 'Update Tour',\n 'tourBuilder.validationErrorsTitle': 'Validation Errors',\n 'tourPreview.accessDeniedMessage': 'You do not have permission to preview this tour.',\n 'tourPreview.accessDeniedTitle': 'Access Denied',\n 'tourPreview.deviceDesktop': 'Desktop preview',\n 'tourPreview.deviceMobile': 'Mobile preview',\n 'tourPreview.deviceTablet': 'Tablet preview',\n 'tourPreview.finish': 'Finish',\n 'tourPreview.loading': 'Loading tour...',\n 'tourPreview.next': 'Next',\n 'tourPreview.nextFooter': 'Next',\n 'tourPreview.previewSuffix': 'Preview',\n 'tourPreview.previous': 'Previous',\n 'tourPreview.readyHint': 'Click \"Start Preview\" to begin',\n 'tourPreview.readyTitle': 'Preview ready',\n 'tourPreview.startPreview': 'Start Preview',\n 'tourPreview.stepOf': 'Step',\n 'tourPreview.stepOfConnector': 'of',\n 'tourPreview.stopPreview': 'Stop Preview',\n 'tourPreview.validationErrorsTitle': 'Validation Errors',\n 'tourPreview.warningsTitle': 'Warnings',\n 'toursList.accessDeniedMessage': 'You do not have permission to view product tours.',\n 'toursList.accessDeniedTitle': 'Access Denied',\n 'toursList.actionArchive': 'Archive',\n 'toursList.actionDelete': 'Delete',\n 'toursList.actionDuplicate': 'Duplicate',\n 'toursList.actionPublish': 'Publish',\n 'toursList.actionUnpublish': 'Unpublish',\n 'toursList.confirmDelete': 'Are you sure you want to delete this tour?',\n 'toursList.createTour': 'Create Tour',\n 'toursList.editStepsTitle': 'Edit Steps',\n 'toursList.emptySubtitle': 'Create your first tour to get started',\n 'toursList.emptyTitle': 'No tours found',\n 'toursList.errorArchive': 'Failed to archive tour',\n 'toursList.errorDelete': 'Failed to delete tour',\n 'toursList.errorDuplicate': 'Failed to duplicate tour',\n 'toursList.errorPublish': 'Failed to publish tour',\n 'toursList.errorUnpublish': 'Failed to unpublish tour',\n 'toursList.gridView': 'Grid view',\n 'toursList.listView': 'List view',\n 'toursList.loading': 'Loading tours...',\n 'toursList.moreActionsTitle': 'More actions',\n 'toursList.previewButton': 'Preview',\n 'toursList.previewTitle': 'Preview Tour',\n 'toursList.searchPlaceholder': 'Search tours...',\n 'toursList.settingsTitle': 'Settings',\n 'toursList.statusAll': 'All Statuses',\n 'toursList.statusArchived': 'Archived',\n 'toursList.statusDraft': 'Draft',\n 'toursList.statusPublished': 'Published',\n 'toursList.statusScheduled': 'Scheduled',\n 'toursList.steps': 'steps',\n 'toursList.stepsButton': 'Steps',\n 'toursList.subtitle': 'Create and manage interactive product tours',\n 'toursList.title': 'Product Tours',\n 'toursList.views': 'views',\n\n // User-facing surface (BOFF-2391: My Tours + My Progress).\n 'myTours.title': 'My Tours',\n 'myTours.subtitle': 'Walkthroughs available in this product. Take a tour to learn a feature.',\n 'myTours.loading': 'Loading...',\n 'myTours.empty': 'No tours are available in this context yet.',\n 'myTours.status.completed': 'Completed',\n 'myTours.status.inProgress': 'In progress',\n 'myTours.status.skipped': 'Skipped',\n 'myTours.status.notStarted': 'Not started',\n 'myTours.notFoundTitle': 'Page not found',\n 'myTours.notFoundBody': \"That tour page isn't available — returning to My Tours.\",\n\n 'myToursProgress.title': 'My Progress',\n 'myToursProgress.subtitle': 'Tours you have started, completed, or skipped.',\n 'myToursProgress.loading': 'Loading...',\n 'myToursProgress.inProgress': 'In progress',\n 'myToursProgress.completed': 'Completed',\n 'myToursProgress.skipped': 'Skipped or dismissed',\n 'myToursProgress.emptyInProgress': 'No tours in progress.',\n 'myToursProgress.emptyCompleted': 'No completed tours yet.',\n 'myToursProgress.emptySkipped': 'No skipped tours.',\n 'myToursProgress.other': 'Other',\n 'myToursProgress.emptyOther': 'No tours in other states.',\n} as const;\n\nexport type ToursTranslationKey = keyof typeof toursTranslationFallbacks;\n\ntype TranslationParams = Record<string, string | number>;\n\nexport function useToursI18n() {\n const i18n = useI18n();\n // The installed fe-libs typings still expose the older 2-argument shape, but the\n // runtime provider supports fallback strings. Narrow locally so this MFE can rely\n // on fallback-backed translations without changing the shared package here.\n const translateWithFallback = i18n.t as (key: string, fallback?: string) => string;\n\n const tr = useCallback(\n (key: ToursTranslationKey, params?: TranslationParams): string => {\n const resolved = translateWithFallback(key, toursTranslationFallbacks[key]);\n\n if (!params) {\n return resolved;\n }\n\n return Object.entries(params).reduce(\n (value, [paramKey, paramValue]) => value.replace(`{{${paramKey}}}`, String(paramValue)),\n resolved\n );\n },\n [translateWithFallback]\n );\n\n return {\n ...i18n,\n tr,\n };\n}\n\nexport function getToursTranslationFallback(key: ToursTranslationKey) {\n return toursTranslationFallbacks[key];\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"i18n.js","names":[],"sources":["../../src/tours/i18n.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\nconst toursTranslationFallbacks = {\n 'stepEditor.addFirstStep': 'Add First Step',\n 'stepEditor.addStep': 'Add Step',\n 'stepEditor.clickAddStep': 'Click \"Add Step\" to create one',\n 'stepEditor.closeSteps': 'Close steps',\n 'stepEditor.content': 'Content',\n 'stepEditor.contentPlaceholder': 'Enter step content or instructions',\n 'stepEditor.createFirstStep': 'Create your first step to get started',\n 'stepEditor.cssSelector': 'CSS Selector',\n 'stepEditor.cssSelectorPlaceholder': \"[data-tour='element-name'] or #id or .class\",\n 'stepEditor.dataTourHint': \"Use data-tour attributes like [data-tour='sidenav'] for best results\",\n 'stepEditor.deleteStep': 'Delete step',\n 'stepEditor.desktopSelector': 'Desktop Selector',\n 'stepEditor.deviceSelectorHint': 'Override the default selector for specific device types',\n 'stepEditor.deviceSpecificSelectors': 'Device-Specific Selectors (Advanced)',\n 'stepEditor.editStep': 'Edit Step',\n 'stepEditor.goBack': 'Go back',\n 'stepEditor.leaveEmptyDefault': 'Leave empty to use default',\n 'stepEditor.mobileSelector': 'Mobile Selector',\n 'stepEditor.noStepSelected': 'No step selected',\n 'stepEditor.noStepsYet': 'No steps yet',\n 'stepEditor.of': 'of',\n 'stepEditor.nextStep': 'Next step',\n 'stepEditor.placementAuto': 'Auto (recommended)',\n 'stepEditor.placementBottom': 'Bottom',\n 'stepEditor.placementCenter': 'Center (modal style)',\n 'stepEditor.placementLeft': 'Left',\n 'stepEditor.placementRight': 'Right',\n 'stepEditor.placementTop': 'Top',\n 'stepEditor.previousStep': 'Previous step',\n 'stepEditor.save': 'Save',\n 'stepEditor.saving': 'Saving...',\n 'stepEditor.selectStepToEdit': 'Select a step from the list to edit it',\n 'stepEditor.stepNumber': 'Step',\n 'stepEditor.steps': 'Steps',\n 'stepEditor.stepsCount': 'steps',\n 'stepEditor.stepsLabel': 'Steps',\n 'stepEditor.stepTitle': 'Step Title',\n 'stepEditor.stepTitlePlaceholder': 'Enter step title',\n 'stepEditor.tabletSelector': 'Tablet Selector',\n 'stepEditor.targetElement': 'target element',\n 'stepEditor.tooltipPlacement': 'Tooltip Placement',\n 'stepEditor.tourFallback': 'Tour',\n 'stepEditor.tourSteps': 'Tour Steps',\n 'stepEditor.untitled': 'Untitled',\n 'templateLibrary.adjustFilters': 'Try adjusting your filters or search query',\n 'templateLibrary.allCategories': 'All Categories',\n 'templateLibrary.categoryCustom': 'Custom',\n 'templateLibrary.categoryFeatureAnnouncement': 'Feature Announcement',\n 'templateLibrary.categoryHelp': 'Help',\n 'templateLibrary.categoryOnboarding': 'Onboarding',\n 'templateLibrary.deleteConfirm': 'Delete this template?',\n 'templateLibrary.deleteTemplate': 'Delete template',\n 'templateLibrary.loading': 'Loading templates...',\n 'templateLibrary.noTemplatesFound': 'No templates found',\n 'templateLibrary.publicOnly': 'Public only',\n 'templateLibrary.searchPlaceholder': 'Search templates...',\n 'templateLibrary.subtitle': 'Browse and use pre-built tour templates',\n 'templateLibrary.times': 'times',\n 'templateLibrary.title': 'Tour Templates',\n 'templateLibrary.useTemplate': 'Use Template',\n 'templateLibrary.usedTimes': 'Used',\n 'tourBuilder.accessDeniedTitle': 'Access Denied',\n 'tourBuilder.analytics': 'Analytics',\n 'tourBuilder.createAndAddSteps': 'Create & Add Steps',\n 'tourBuilder.createAccessDeniedMessage': 'You do not have permission to create tours.',\n 'tourBuilder.editSteps': 'Edit Steps',\n 'tourBuilder.errorTitle': 'Error',\n 'tourBuilder.goBack': 'Go back',\n 'tourBuilder.labelDescription': 'Description',\n 'tourBuilder.labelName': 'Tour Name *',\n 'tourBuilder.labelPriority': 'Priority (1-100)',\n 'tourBuilder.labelProductId': 'Product ID *',\n 'tourBuilder.labelTriggerType': 'Trigger Type',\n 'tourBuilder.loading': 'Loading...',\n 'tourBuilder.preview': 'Preview',\n 'tourBuilder.saving': 'Saving...',\n 'tourBuilder.sectionBasicInfo': 'Basic Information',\n 'tourBuilder.sectionTriggerSettings': 'Trigger Settings',\n 'tourBuilder.seedVibeControls.button': 'Seed VibeControls user tours',\n 'tourBuilder.seedVibeControls.confirm':\n 'This will overwrite the built-in Support, Notifications, and Conversations user tours from the service seed file. Continue?',\n 'tourBuilder.seedVibeControls.description':\n 'Overwrites the built-in Support, Notifications, and Conversations user tours from the service seed file.',\n 'tourBuilder.seedVibeControls.error': 'Failed to seed VibeControls user tours.',\n 'tourBuilder.seedVibeControls.loading': 'Seeding...',\n 'tourBuilder.seedVibeControls.permissionHint':\n 'Requires tour create and update permissions. The service also enforces RBAC when the seed mutation runs.',\n 'tourBuilder.seedVibeControls.result':\n 'Seeded {{totalCount}} tours for {{productId}} in workspace {{workspaceId}}: {{createdCount}} created, {{updatedCount}} updated.',\n 'tourBuilder.seedVibeControls.title': 'Seed VibeControls user tours',\n 'tourBuilder.subtitle': 'Configure tour details and settings',\n 'tourBuilder.titleCreate': 'Create Tour',\n 'tourBuilder.titleEdit': 'Edit Tour',\n 'tourBuilder.triggerAutoAlways': 'Auto (Always)',\n 'tourBuilder.triggerAutoFirstVisit': 'Auto (First Visit)',\n 'tourBuilder.triggerManual': 'Manual',\n 'tourBuilder.triggerOnEvent': 'On Event',\n 'tourBuilder.triggerScheduled': 'Scheduled',\n 'tourBuilder.updateTour': 'Update Tour',\n 'tourBuilder.updateAccessDeniedMessage': 'You do not have permission to update this tour.',\n 'tourBuilder.validationErrorsTitle': 'Validation Errors',\n 'tourPreview.accessDeniedMessage': 'You do not have permission to preview this tour.',\n 'tourPreview.accessDeniedTitle': 'Access Denied',\n 'tourPreview.deviceDesktop': 'Desktop preview',\n 'tourPreview.deviceMobile': 'Mobile preview',\n 'tourPreview.deviceTablet': 'Tablet preview',\n 'tourPreview.finish': 'Finish',\n 'tourPreview.loading': 'Loading tour...',\n 'tourPreview.next': 'Next',\n 'tourPreview.nextFooter': 'Next',\n 'tourPreview.previewSuffix': 'Preview',\n 'tourPreview.previous': 'Previous',\n 'tourPreview.readyHint': 'Click \"Start Preview\" to begin',\n 'tourPreview.readyTitle': 'Preview ready',\n 'tourPreview.startPreview': 'Start Preview',\n 'tourPreview.stepOf': 'Step',\n 'tourPreview.stepOfConnector': 'of',\n 'tourPreview.stopPreview': 'Stop Preview',\n 'tourPreview.validationErrorsTitle': 'Validation Errors',\n 'tourPreview.warningsTitle': 'Warnings',\n 'toursList.accessDeniedMessage': 'You do not have permission to view product tours.',\n 'toursList.accessDeniedTitle': 'Access Denied',\n 'toursList.actionArchive': 'Archive',\n 'toursList.actionDelete': 'Delete',\n 'toursList.actionDuplicate': 'Duplicate',\n 'toursList.actionPublish': 'Publish',\n 'toursList.actionUnpublish': 'Unpublish',\n 'toursList.confirmDelete': 'Are you sure you want to delete this tour?',\n 'toursList.createTour': 'Create Tour',\n 'toursList.editStepsTitle': 'Edit Steps',\n 'toursList.emptySubtitle': 'Create your first tour to get started',\n 'toursList.emptyTitle': 'No tours found',\n 'toursList.errorArchive': 'Failed to archive tour',\n 'toursList.errorDelete': 'Failed to delete tour',\n 'toursList.errorDuplicate': 'Failed to duplicate tour',\n 'toursList.errorPublish': 'Failed to publish tour',\n 'toursList.errorUnpublish': 'Failed to unpublish tour',\n 'toursList.gridView': 'Grid view',\n 'toursList.listView': 'List view',\n 'toursList.loading': 'Loading tours...',\n 'toursList.moreActionsTitle': 'More actions',\n 'toursList.previewButton': 'Preview',\n 'toursList.previewTitle': 'Preview Tour',\n 'toursList.searchPlaceholder': 'Search tours...',\n 'toursList.settingsTitle': 'Settings',\n 'toursList.statusAll': 'All Statuses',\n 'toursList.statusArchived': 'Archived',\n 'toursList.statusDraft': 'Draft',\n 'toursList.statusPublished': 'Published',\n 'toursList.statusScheduled': 'Scheduled',\n 'toursList.steps': 'steps',\n 'toursList.stepsButton': 'Steps',\n 'toursList.subtitle': 'Create and manage interactive product tours',\n 'toursList.title': 'Product Tours',\n 'toursList.views': 'views',\n\n // User-facing surface (BOFF-2391: My Tours + My Progress).\n 'myTours.title': 'My Tours',\n 'myTours.subtitle': 'Walkthroughs available in this product. Take a tour to learn a feature.',\n 'myTours.loading': 'Loading...',\n 'myTours.empty': 'No tours are available in this context yet.',\n 'myTours.status.completed': 'Completed',\n 'myTours.status.inProgress': 'In progress',\n 'myTours.status.skipped': 'Skipped',\n 'myTours.status.notStarted': 'Not started',\n 'myTours.notFoundTitle': 'Page not found',\n 'myTours.notFoundBody': \"That tour page isn't available — returning to My Tours.\",\n\n 'myToursProgress.title': 'My Progress',\n 'myToursProgress.subtitle': 'Tours you have started, completed, or skipped.',\n 'myToursProgress.loading': 'Loading...',\n 'myToursProgress.inProgress': 'In progress',\n 'myToursProgress.completed': 'Completed',\n 'myToursProgress.skipped': 'Skipped or dismissed',\n 'myToursProgress.emptyInProgress': 'No tours in progress.',\n 'myToursProgress.emptyCompleted': 'No completed tours yet.',\n 'myToursProgress.emptySkipped': 'No skipped tours.',\n 'myToursProgress.other': 'Other',\n 'myToursProgress.emptyOther': 'No tours in other states.',\n} as const;\n\nexport type ToursTranslationKey = keyof typeof toursTranslationFallbacks;\n\ntype TranslationParams = Record<string, string | number>;\n\nexport function useToursI18n() {\n const i18n = useI18n();\n // The installed fe-libs typings still expose the older 2-argument shape, but the\n // runtime provider supports fallback strings. Narrow locally so this MFE can rely\n // on fallback-backed translations without changing the shared package here.\n const translateWithFallback = i18n.t as (key: string, fallback?: string) => string;\n\n const tr = useCallback(\n (key: ToursTranslationKey, params?: TranslationParams): string => {\n const resolved = translateWithFallback(key, toursTranslationFallbacks[key]);\n\n if (!params) {\n return resolved;\n }\n\n return Object.entries(params).reduce(\n (value, [paramKey, paramValue]) => value.replace(`{{${paramKey}}}`, String(paramValue)),\n resolved\n );\n },\n [translateWithFallback]\n );\n\n return {\n ...i18n,\n tr,\n };\n}\n\nexport function getToursTranslationFallback(key: ToursTranslationKey) {\n return toursTranslationFallbacks[key];\n}\n"],"mappings":";;;AAGA,IAAM,IAA4B;CAChC,2BAA2B;CAC3B,sBAAsB;CACtB,2BAA2B;CAC3B,yBAAyB;CACzB,sBAAsB;CACtB,iCAAiC;CACjC,8BAA8B;CAC9B,0BAA0B;CAC1B,qCAAqC;CACrC,2BAA2B;CAC3B,yBAAyB;CACzB,8BAA8B;CAC9B,iCAAiC;CACjC,sCAAsC;CACtC,uBAAuB;CACvB,qBAAqB;CACrB,gCAAgC;CAChC,6BAA6B;CAC7B,6BAA6B;CAC7B,yBAAyB;CACzB,iBAAiB;CACjB,uBAAuB;CACvB,4BAA4B;CAC5B,8BAA8B;CAC9B,8BAA8B;CAC9B,4BAA4B;CAC5B,6BAA6B;CAC7B,2BAA2B;CAC3B,2BAA2B;CAC3B,mBAAmB;CACnB,qBAAqB;CACrB,+BAA+B;CAC/B,yBAAyB;CACzB,oBAAoB;CACpB,yBAAyB;CACzB,yBAAyB;CACzB,wBAAwB;CACxB,mCAAmC;CACnC,6BAA6B;CAC7B,4BAA4B;CAC5B,+BAA+B;CAC/B,2BAA2B;CAC3B,wBAAwB;CACxB,uBAAuB;CACvB,iCAAiC;CACjC,iCAAiC;CACjC,kCAAkC;CAClC,+CAA+C;CAC/C,gCAAgC;CAChC,sCAAsC;CACtC,iCAAiC;CACjC,kCAAkC;CAClC,2BAA2B;CAC3B,oCAAoC;CACpC,8BAA8B;CAC9B,qCAAqC;CACrC,4BAA4B;CAC5B,yBAAyB;CACzB,yBAAyB;CACzB,+BAA+B;CAC/B,6BAA6B;CAC7B,iCAAiC;CACjC,yBAAyB;CACzB,iCAAiC;CACjC,yCAAyC;CACzC,yBAAyB;CACzB,0BAA0B;CAC1B,sBAAsB;CACtB,gCAAgC;CAChC,yBAAyB;CACzB,6BAA6B;CAC7B,8BAA8B;CAC9B,gCAAgC;CAChC,uBAAuB;CACvB,uBAAuB;CACvB,sBAAsB;CACtB,gCAAgC;CAChC,sCAAsC;CACtC,uCAAuC;CACvC,wCACE;CACF,4CACE;CACF,sCAAsC;CACtC,wCAAwC;CACxC,+CACE;CACF,uCACE;CACF,sCAAsC;CACtC,wBAAwB;CACxB,2BAA2B;CAC3B,yBAAyB;CACzB,iCAAiC;CACjC,qCAAqC;CACrC,6BAA6B;CAC7B,8BAA8B;CAC9B,gCAAgC;CAChC,0BAA0B;CAC1B,yCAAyC;CACzC,qCAAqC;CACrC,mCAAmC;CACnC,iCAAiC;CACjC,6BAA6B;CAC7B,4BAA4B;CAC5B,4BAA4B;CAC5B,sBAAsB;CACtB,uBAAuB;CACvB,oBAAoB;CACpB,0BAA0B;CAC1B,6BAA6B;CAC7B,wBAAwB;CACxB,yBAAyB;CACzB,0BAA0B;CAC1B,4BAA4B;CAC5B,sBAAsB;CACtB,+BAA+B;CAC/B,2BAA2B;CAC3B,qCAAqC;CACrC,6BAA6B;CAC7B,iCAAiC;CACjC,+BAA+B;CAC/B,2BAA2B;CAC3B,0BAA0B;CAC1B,6BAA6B;CAC7B,2BAA2B;CAC3B,6BAA6B;CAC7B,2BAA2B;CAC3B,wBAAwB;CACxB,4BAA4B;CAC5B,2BAA2B;CAC3B,wBAAwB;CACxB,0BAA0B;CAC1B,yBAAyB;CACzB,4BAA4B;CAC5B,0BAA0B;CAC1B,4BAA4B;CAC5B,sBAAsB;CACtB,sBAAsB;CACtB,qBAAqB;CACrB,8BAA8B;CAC9B,2BAA2B;CAC3B,0BAA0B;CAC1B,+BAA+B;CAC/B,2BAA2B;CAC3B,uBAAuB;CACvB,4BAA4B;CAC5B,yBAAyB;CACzB,6BAA6B;CAC7B,6BAA6B;CAC7B,mBAAmB;CACnB,yBAAyB;CACzB,sBAAsB;CACtB,mBAAmB;CACnB,mBAAmB;CAGnB,iBAAiB;CACjB,oBAAoB;CACpB,mBAAmB;CACnB,iBAAiB;CACjB,4BAA4B;CAC5B,6BAA6B;CAC7B,0BAA0B;CAC1B,6BAA6B;CAC7B,yBAAyB;CACzB,wBAAwB;CAExB,yBAAyB;CACzB,4BAA4B;CAC5B,2BAA2B;CAC3B,8BAA8B;CAC9B,6BAA6B;CAC7B,2BAA2B;CAC3B,mCAAmC;CACnC,kCAAkC;CAClC,gCAAgC;CAChC,yBAAyB;CACzB,8BAA8B;CAC/B;AAMD,SAAgB,IAAe;CAC7B,IAAM,IAAO,GAAS,EAIhB,IAAwB,EAAK,GAE7B,IAAK,GACR,GAA0B,MAAuC;EAChE,IAAM,IAAW,EAAsB,GAAK,EAA0B,GAAK;AAM3E,SAJK,IAIE,OAAO,QAAQ,EAAO,CAAC,QAC3B,GAAO,CAAC,GAAU,OAAgB,EAAM,QAAQ,KAAK,EAAS,KAAK,OAAO,EAAW,CAAC,EACvF,EACD,GANQ;IAQX,CAAC,EAAsB,CACxB;AAED,QAAO;EACL,GAAG;EACH;EACD"}
@@ -11,11 +11,11 @@ import { PermissionGate as l } from "@burdenoff/fe-libs/shared/components";
11
11
  import { ArrowLeft as re, BarChart3 as ie, Calendar as ae, Eye as oe, LayoutTemplate as se, ListOrdered as ce, Save as le, Sparkles as ue } from "lucide-react";
12
12
  import { Fragment as de, jsx as u, jsxs as d } from "react/jsx-runtime";
13
13
  import { useNavigate as fe, useParams as pe } from "react-router-dom";
14
- import { useGatewayClient as f } from "@burdenoff/fe-libs/shared/graphql";
15
- import { useEventBus as me } from "@burdenoff/fe-libs/shared/events";
16
- import { gql as p } from "@apollo/client/core";
14
+ import { useGatewayClient as me } from "@burdenoff/fe-libs/shared/graphql";
15
+ import { useEventBus as he } from "@burdenoff/fe-libs/shared/events";
16
+ import { gql as f } from "@apollo/client/core";
17
17
  //#region src/tours/pages/TourBuilderPage.tsx
18
- var he = 250, ge = p`
18
+ var ge = 250, _e = f`
19
19
  mutation SeedVibeControlsUserTours {
20
20
  seedVibeControlsUserTours {
21
21
  productId
@@ -33,7 +33,7 @@ var he = 250, ge = p`
33
33
  }
34
34
  }
35
35
  `;
36
- function _e(e) {
36
+ function ve(e) {
37
37
  if (!e || typeof e != "object") return null;
38
38
  let t = e, n = t.error;
39
39
  if (n instanceof Error) return n.message;
@@ -47,7 +47,7 @@ function _e(e) {
47
47
  }).filter((e) => !!e);
48
48
  return i.length > 0 ? i.join("; ") : "Seed mutation returned errors.";
49
49
  }
50
- var m = [
50
+ var p = [
51
51
  {
52
52
  productId: "vibecontrols",
53
53
  moduleId: "dashboard",
@@ -280,37 +280,38 @@ var m = [
280
280
  path: "/conversations/settings"
281
281
  }
282
282
  ];
283
- function h(e) {
283
+ function m(e) {
284
284
  return e?.trim() || void 0;
285
285
  }
286
- function g(e) {
287
- let t = h(e);
288
- return t ? m.filter((e) => e.productId === t) : [];
286
+ function h(e) {
287
+ let t = m(e);
288
+ return t ? p.filter((e) => e.productId === t) : [];
289
289
  }
290
- function ve(e) {
290
+ function ye(e) {
291
291
  let t = /* @__PURE__ */ new Map();
292
- for (let n of g(e)) (!t.get(n.moduleId) || n.isModuleHome) && t.set(n.moduleId, {
292
+ for (let n of h(e)) (!t.get(n.moduleId) || n.isModuleHome) && t.set(n.moduleId, {
293
293
  moduleId: n.moduleId,
294
294
  label: n.moduleLabel,
295
295
  path: n.path
296
296
  });
297
297
  return [...t.values()];
298
298
  }
299
- function ye(e, t) {
300
- let n = h(t);
301
- return n ? g(e).filter((e) => e.moduleId === n).map((e) => ({
299
+ function be(e, t) {
300
+ let n = m(t);
301
+ return n ? h(e).filter((e) => e.moduleId === n).map((e) => ({
302
302
  pageId: e.pageId,
303
303
  label: e.pageLabel,
304
304
  path: e.path
305
305
  })) : [];
306
306
  }
307
- function _() {
308
- let { tr: p } = ee(), { tourId: m } = pe(), h = fe(), g = e(), { basePath: _ = "/" } = g, v = me(), be = f("global"), { hasPermission: y } = r(), b = !m || m === "new", x = y(i.TOUR_CREATE), S = y(i.TOUR_UPDATE), xe = y(i.TOUR_TEMPLATE_CREATE), Se = b ? x : S, C = x && S, { tour: w, loadTour: T, createTour: Ce, updateTour: we, saving: E, validationErrors: D, error: O } = te(m), { saveAsTemplate: k } = n(), { data: A, loading: j } = t({
307
+ function g() {
308
+ let { tr: f } = ee(), { tourId: p } = pe(), m = fe(), h = e(), { basePath: g = "/" } = h, _ = he(), xe = me("global"), { hasPermission: v, isLoading: y } = r(), b = !p || p === "new", x = v(i.TOUR_CREATE), S = v(i.TOUR_UPDATE), Se = v(i.TOUR_TEMPLATE_CREATE), C = b ? x : S, w = x && S, { tour: T, loadTour: E, createTour: Ce, updateTour: we, saving: D, validationErrors: O, error: k } = te(p), { saveAsTemplate: Te } = n(), { data: A, loading: j } = t({
309
309
  variables: {
310
- limit: he,
310
+ limit: ge,
311
311
  offset: 0
312
312
  },
313
- fetchPolicy: "cache-and-network"
313
+ fetchPolicy: "cache-and-network",
314
+ skip: y || !C
314
315
  }), [M, N] = c({
315
316
  name: "",
316
317
  description: "",
@@ -324,12 +325,17 @@ function _() {
324
325
  displayOrder: 1,
325
326
  startDate: "",
326
327
  endDate: ""
327
- }), [P, F] = c(!1), [I, L] = c(!1), [R, z] = c(!1), [B, V] = c(!1), [H, U] = c(null), [W, G] = c(null), K = ne(!1), q = s(() => [...A?.platformProducts.items ?? []].sort((e, t) => e.name.localeCompare(t.name)), [A]), J = s(() => new Set(q.map((e) => e.slug)), [q]), Y = s(() => ve(M.productId), [M.productId]), X = s(() => new Set(Y.map((e) => e.moduleId)), [Y]), Z = s(() => ye(M.productId, M.moduleId), [M.moduleId, M.productId]), Q = s(() => new Set(Z.map((e) => e.pageId)), [Z]);
328
+ }), [P, F] = c(!1), [I, L] = c(!1), [R, z] = c(!1), [B, V] = c(!1), [H, U] = c(null), [W, G] = c(null), K = ne(!1), q = s(() => [...A?.platformProducts.items ?? []].sort((e, t) => e.name.localeCompare(t.name)), [A]), J = s(() => new Set(q.map((e) => e.slug)), [q]), Y = s(() => ye(M.productId), [M.productId]), X = s(() => new Set(Y.map((e) => e.moduleId)), [Y]), Z = s(() => be(M.productId, M.moduleId), [M.moduleId, M.productId]), Q = s(() => new Set(Z.map((e) => e.pageId)), [Z]);
328
329
  o(() => {
329
- m && m !== "new" && (K.current = !1, T(m));
330
- }, [m, T]), o(() => {
331
- w && !K.current && (N(w), K.current = !0);
332
- }, [w]), o(() => {
330
+ K.current || !y && C && p && p !== "new" && E(p);
331
+ }, [
332
+ C,
333
+ E,
334
+ y,
335
+ p
336
+ ]), o(() => {
337
+ T && !K.current && (N(T), K.current = !0);
338
+ }, [T]), o(() => {
333
339
  if (!M.productId || j) {
334
340
  F(!1);
335
341
  return;
@@ -363,75 +369,81 @@ function _() {
363
369
  Q,
364
370
  Z.length
365
371
  ]);
366
- let Te = !!(M.productId && !P && !J.has(M.productId)), Ee = !!(M.moduleId && !I && !X.has(M.moduleId)), De = !!(M.pageId && !R && !Q.has(M.pageId)), Oe = async (e) => {
372
+ let Ee = !!(M.productId && !P && !J.has(M.productId)), De = !!(M.moduleId && !I && !X.has(M.moduleId)), Oe = !!(M.pageId && !R && !Q.has(M.pageId)), ke = async (e) => {
367
373
  e.preventDefault();
368
374
  try {
369
- m && m !== "new" ? await we(m, M) : await Ce(M);
375
+ p && p !== "new" ? await we(p, M) : await Ce(M);
370
376
  } catch {
371
- a(v, "tour.save", g);
377
+ a(_, "tour.save", h);
372
378
  }
373
- }, ke = () => {
374
- h(`${_}/list`);
379
+ }, Ae = () => {
380
+ m(`${g}/list`);
375
381
  }, $ = (e) => {
376
382
  if (!e) return "";
377
383
  let t = new Date(e);
378
384
  return Number.isNaN(t.getTime()) ? "" : (/* @__PURE__ */ new Date(t.getTime() - t.getTimezoneOffset() * 6e4)).toISOString().slice(0, 16);
379
- }, Ae = async () => {
380
- if (!m || m === "new") return;
381
- let e = `${M.name || w?.name || "Tour"} Template`, t = window.prompt("Template name", e);
385
+ }, je = async () => {
386
+ if (!p || p === "new") return;
387
+ let e = `${M.name || T?.name || "Tour"} Template`, t = window.prompt("Template name", e);
382
388
  if (!t) return;
383
389
  let n = window.prompt("Template category (ONBOARDING, FEATURE_ANNOUNCEMENT, HELP, CUSTOM)", "ONBOARDING") || "ONBOARDING";
384
390
  try {
385
- await k(m, {
391
+ await Te(p, {
386
392
  name: t,
387
393
  description: M.description,
388
394
  category: n,
389
395
  isPublic: !1
390
- }), h(`${_}/templates`);
396
+ }), m(`${g}/templates`);
391
397
  } catch {
392
- a(v, "template.save", g);
398
+ a(_, "template.save", h);
393
399
  }
394
- }, je = async () => {
395
- if (window.confirm(p("tourBuilder.seedVibeControls.confirm"))) {
400
+ }, Me = async () => {
401
+ if (window.confirm(f("tourBuilder.seedVibeControls.confirm"))) {
396
402
  V(!0), U(null), G(null);
397
403
  try {
398
- let e = await be.mutate({ mutation: ge }), t = _e(e);
404
+ let e = await xe.mutate({ mutation: _e }), t = ve(e);
399
405
  if (t) throw Error(t);
400
406
  let n = e.data?.seedVibeControlsUserTours;
401
407
  if (!n) throw Error("Seed mutation returned no result.");
402
408
  U(n);
403
409
  } catch (e) {
404
- let t = e instanceof Error ? e.message : p("tourBuilder.seedVibeControls.error");
405
- G(t), v.emit("tours.api.failed", {
410
+ let t = e instanceof Error ? e.message : f("tourBuilder.seedVibeControls.error");
411
+ G(t), _.emit("tours.api.failed", {
406
412
  route: "/tours",
407
413
  operation: "tour.seed_vibecontrols_user_tours",
408
414
  errorMessage: t,
409
- productId: g.productId,
410
- workspaceId: g.workspaceId
415
+ productId: h.productId,
416
+ workspaceId: h.workspaceId
411
417
  }, { component: "microfe-tours" });
412
418
  } finally {
413
419
  V(!1);
414
420
  }
415
421
  }
416
422
  };
417
- return /* @__PURE__ */ d("div", {
423
+ return y ? /* @__PURE__ */ u("div", {
424
+ className: "flex h-full items-center justify-center p-3 sm:p-6",
425
+ children: /* @__PURE__ */ u("p", {
426
+ className: "text-sm text-muted-foreground",
427
+ children: f("tourBuilder.loading")
428
+ })
429
+ }) : C ? /* @__PURE__ */ d("div", {
418
430
  className: "space-y-4 sm:space-y-6 p-3 sm:p-6 max-w-4xl mx-auto",
419
431
  children: [
420
432
  /* @__PURE__ */ d("div", {
421
433
  className: "flex items-center gap-4",
422
434
  children: [/* @__PURE__ */ u("button", {
423
- onClick: ke,
435
+ onClick: Ae,
424
436
  className: "p-2 hover:bg-accent rounded-md",
425
- "aria-label": p("tourBuilder.goBack"),
437
+ "aria-label": f("tourBuilder.goBack"),
426
438
  children: /* @__PURE__ */ u(re, { size: 20 })
427
439
  }), /* @__PURE__ */ d("div", {
428
440
  className: "flex-1",
429
441
  children: [/* @__PURE__ */ u("h1", {
430
442
  className: "text-xl sm:text-2xl font-bold text-foreground",
431
- children: p(m && m !== "new" ? "tourBuilder.titleEdit" : "tourBuilder.titleCreate")
443
+ children: f(p && p !== "new" ? "tourBuilder.titleEdit" : "tourBuilder.titleCreate")
432
444
  }), /* @__PURE__ */ u("p", {
433
445
  className: "text-sm text-muted-foreground",
434
- children: p("tourBuilder.subtitle")
446
+ children: f("tourBuilder.subtitle")
435
447
  })]
436
448
  })]
437
449
  }),
@@ -444,22 +456,22 @@ function _() {
444
456
  className: "space-y-1",
445
457
  children: [/* @__PURE__ */ u("h2", {
446
458
  className: "text-lg font-semibold text-foreground",
447
- children: p("tourBuilder.seedVibeControls.title")
459
+ children: f("tourBuilder.seedVibeControls.title")
448
460
  }), /* @__PURE__ */ u("p", {
449
461
  className: "text-sm text-muted-foreground",
450
- children: p("tourBuilder.seedVibeControls.description")
462
+ children: f("tourBuilder.seedVibeControls.description")
451
463
  })]
452
464
  }), /* @__PURE__ */ d("button", {
453
465
  type: "button",
454
- onClick: () => void je(),
455
- disabled: B || !C,
466
+ onClick: () => void Me(),
467
+ disabled: B || !w,
456
468
  className: "inline-flex min-h-11 items-center justify-center gap-2 rounded-md border border-border bg-secondary px-4 py-2 text-sm font-medium text-secondary-foreground hover:bg-secondary/80 disabled:cursor-not-allowed disabled:opacity-50",
457
- children: [/* @__PURE__ */ u(ue, { size: 18 }), p(B ? "tourBuilder.seedVibeControls.loading" : "tourBuilder.seedVibeControls.button")]
469
+ children: [/* @__PURE__ */ u(ue, { size: 18 }), f(B ? "tourBuilder.seedVibeControls.loading" : "tourBuilder.seedVibeControls.button")]
458
470
  })]
459
471
  }),
460
- C ? null : /* @__PURE__ */ u("p", {
472
+ w ? null : /* @__PURE__ */ u("p", {
461
473
  className: "mt-3 text-sm text-muted-foreground",
462
- children: p("tourBuilder.seedVibeControls.permissionHint")
474
+ children: f("tourBuilder.seedVibeControls.permissionHint")
463
475
  }),
464
476
  W ? /* @__PURE__ */ u("p", {
465
477
  className: "mt-3 text-sm text-destructive",
@@ -467,7 +479,7 @@ function _() {
467
479
  }) : null,
468
480
  H ? /* @__PURE__ */ u("div", {
469
481
  className: "mt-3 rounded-md border border-border bg-background p-3 text-sm text-muted-foreground",
470
- children: p("tourBuilder.seedVibeControls.result", {
482
+ children: f("tourBuilder.seedVibeControls.result", {
471
483
  totalCount: H.totalCount,
472
484
  productId: H.productId,
473
485
  workspaceId: H.workspaceId,
@@ -478,21 +490,21 @@ function _() {
478
490
  ]
479
491
  }) : null,
480
492
  /* @__PURE__ */ d("form", {
481
- onSubmit: Oe,
493
+ onSubmit: ke,
482
494
  className: "space-y-6",
483
495
  children: [
484
496
  /* @__PURE__ */ d("div", {
485
497
  className: "border border-border rounded-md p-4 sm:p-6 bg-card",
486
498
  children: [/* @__PURE__ */ u("h2", {
487
499
  className: "text-lg font-semibold mb-4",
488
- children: p("tourBuilder.sectionBasicInfo")
500
+ children: f("tourBuilder.sectionBasicInfo")
489
501
  }), /* @__PURE__ */ d("div", {
490
502
  className: "space-y-4",
491
503
  children: [
492
504
  /* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("label", {
493
505
  className: "block text-sm font-medium mb-2",
494
506
  htmlFor: "tour-name",
495
- children: p("tourBuilder.labelName")
507
+ children: f("tourBuilder.labelName")
496
508
  }), /* @__PURE__ */ u("input", {
497
509
  id: "tour-name",
498
510
  type: "text",
@@ -507,7 +519,7 @@ function _() {
507
519
  /* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("label", {
508
520
  className: "block text-sm font-medium mb-2",
509
521
  htmlFor: "tour-description",
510
- children: p("tourBuilder.labelDescription")
522
+ children: f("tourBuilder.labelDescription")
511
523
  }), /* @__PURE__ */ u("textarea", {
512
524
  id: "tour-description",
513
525
  value: M.description || "",
@@ -522,7 +534,7 @@ function _() {
522
534
  /* @__PURE__ */ u("label", {
523
535
  className: "block text-sm font-medium mb-2",
524
536
  htmlFor: "product-id",
525
- children: p("tourBuilder.labelProductId")
537
+ children: f("tourBuilder.labelProductId")
526
538
  }),
527
539
  /* @__PURE__ */ d("select", {
528
540
  id: "product-id",
@@ -564,7 +576,7 @@ function _() {
564
576
  ")"
565
577
  ]
566
578
  }, e.id)),
567
- Te ? /* @__PURE__ */ d("option", {
579
+ Ee ? /* @__PURE__ */ d("option", {
568
580
  value: M.productId,
569
581
  children: ["Current: ", M.productId]
570
582
  }) : null,
@@ -631,7 +643,7 @@ function _() {
631
643
  ")"
632
644
  ]
633
645
  }, e.moduleId)),
634
- Ee ? /* @__PURE__ */ d("option", {
646
+ De ? /* @__PURE__ */ d("option", {
635
647
  value: M.moduleId,
636
648
  children: ["Current: ", M.moduleId]
637
649
  }) : null,
@@ -691,7 +703,7 @@ function _() {
691
703
  ")"
692
704
  ]
693
705
  }, e.pageId)),
694
- De ? /* @__PURE__ */ d("option", {
706
+ Oe ? /* @__PURE__ */ d("option", {
695
707
  value: M.pageId,
696
708
  children: ["Current: ", M.pageId]
697
709
  }) : null,
@@ -736,14 +748,14 @@ function _() {
736
748
  className: "border border-border rounded-md p-4 sm:p-6 bg-card",
737
749
  children: [/* @__PURE__ */ u("h2", {
738
750
  className: "text-lg font-semibold mb-4",
739
- children: p("tourBuilder.sectionTriggerSettings")
751
+ children: f("tourBuilder.sectionTriggerSettings")
740
752
  }), /* @__PURE__ */ d("div", {
741
753
  className: "space-y-4",
742
754
  children: [
743
755
  /* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("label", {
744
756
  className: "block text-sm font-medium mb-2",
745
757
  htmlFor: "trigger-type",
746
- children: p("tourBuilder.labelTriggerType")
758
+ children: f("tourBuilder.labelTriggerType")
747
759
  }), /* @__PURE__ */ d("select", {
748
760
  id: "trigger-type",
749
761
  value: M.triggerType || "MANUAL",
@@ -755,30 +767,30 @@ function _() {
755
767
  children: [
756
768
  /* @__PURE__ */ u("option", {
757
769
  value: "MANUAL",
758
- children: p("tourBuilder.triggerManual")
770
+ children: f("tourBuilder.triggerManual")
759
771
  }),
760
772
  /* @__PURE__ */ u("option", {
761
773
  value: "AUTO_FIRST_VISIT",
762
- children: p("tourBuilder.triggerAutoFirstVisit")
774
+ children: f("tourBuilder.triggerAutoFirstVisit")
763
775
  }),
764
776
  /* @__PURE__ */ u("option", {
765
777
  value: "AUTO_ALWAYS",
766
- children: p("tourBuilder.triggerAutoAlways")
778
+ children: f("tourBuilder.triggerAutoAlways")
767
779
  }),
768
780
  /* @__PURE__ */ u("option", {
769
781
  value: "ON_EVENT",
770
- children: p("tourBuilder.triggerOnEvent")
782
+ children: f("tourBuilder.triggerOnEvent")
771
783
  }),
772
784
  /* @__PURE__ */ u("option", {
773
785
  value: "SCHEDULED",
774
- children: p("tourBuilder.triggerScheduled")
786
+ children: f("tourBuilder.triggerScheduled")
775
787
  })
776
788
  ]
777
789
  })] }),
778
790
  /* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("label", {
779
791
  className: "block text-sm font-medium mb-2",
780
792
  htmlFor: "priority",
781
- children: p("tourBuilder.labelPriority")
793
+ children: f("tourBuilder.labelPriority")
782
794
  }), /* @__PURE__ */ u("input", {
783
795
  id: "priority",
784
796
  type: "number",
@@ -827,24 +839,24 @@ function _() {
827
839
  ]
828
840
  })]
829
841
  }),
830
- O && /* @__PURE__ */ d("div", {
842
+ k && /* @__PURE__ */ d("div", {
831
843
  className: "border border-destructive rounded-md p-4 bg-destructive/10",
832
844
  children: [/* @__PURE__ */ u("h3", {
833
845
  className: "font-semibold text-destructive mb-2",
834
- children: p("tourBuilder.errorTitle")
846
+ children: f("tourBuilder.errorTitle")
835
847
  }), /* @__PURE__ */ u("p", {
836
848
  className: "text-sm text-destructive",
837
- children: O.message
849
+ children: k.message
838
850
  })]
839
851
  }),
840
- D.length > 0 && /* @__PURE__ */ d("div", {
852
+ O.length > 0 && /* @__PURE__ */ d("div", {
841
853
  className: "border border-destructive rounded-md p-4 bg-destructive/10",
842
854
  children: [/* @__PURE__ */ u("h3", {
843
855
  className: "font-semibold text-destructive mb-2",
844
- children: p("tourBuilder.validationErrorsTitle")
856
+ children: f("tourBuilder.validationErrorsTitle")
845
857
  }), /* @__PURE__ */ u("ul", {
846
858
  className: "list-disc list-inside space-y-1",
847
- children: D.map((e, t) => /* @__PURE__ */ u("li", {
859
+ children: O.map((e, t) => /* @__PURE__ */ u("li", {
848
860
  className: "text-sm text-destructive",
849
861
  children: e.message
850
862
  }, t))
@@ -856,39 +868,39 @@ function _() {
856
868
  permission: b ? i.TOUR_CREATE : i.TOUR_UPDATE,
857
869
  children: /* @__PURE__ */ d("button", {
858
870
  type: "submit",
859
- disabled: E || !Se,
871
+ disabled: D || !C,
860
872
  className: "flex-1 min-w-[200px] 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",
861
- children: [/* @__PURE__ */ u(le, { size: 20 }), p(E ? "tourBuilder.saving" : m && m !== "new" ? "tourBuilder.updateTour" : "tourBuilder.createAndAddSteps")]
873
+ children: [/* @__PURE__ */ u(le, { size: 20 }), f(D ? "tourBuilder.saving" : p && p !== "new" ? "tourBuilder.updateTour" : "tourBuilder.createAndAddSteps")]
862
874
  })
863
- }), m && m !== "new" && /* @__PURE__ */ d(de, { children: [
875
+ }), p && p !== "new" && /* @__PURE__ */ d(de, { children: [
864
876
  /* @__PURE__ */ d("button", {
865
877
  type: "button",
866
- onClick: () => h(`${_}/${m}/steps`),
878
+ onClick: () => m(`${g}/${p}/steps`),
867
879
  className: "px-4 py-2 bg-secondary text-secondary-foreground rounded-md hover:bg-secondary/80 flex items-center gap-2",
868
880
  children: [
869
881
  /* @__PURE__ */ u(ce, { size: 20 }),
870
- p("tourBuilder.editSteps"),
871
- w?.steps && w.steps.length > 0 && /* @__PURE__ */ u("span", {
882
+ f("tourBuilder.editSteps"),
883
+ T?.steps && T.steps.length > 0 && /* @__PURE__ */ u("span", {
872
884
  className: "ml-1 px-2 py-0.5 text-xs bg-primary/20 rounded-full",
873
- children: w.steps.length
885
+ children: T.steps.length
874
886
  })
875
887
  ]
876
888
  }),
877
889
  /* @__PURE__ */ d("button", {
878
890
  type: "button",
879
- onClick: () => h(`${_}/${m}/preview`),
891
+ onClick: () => m(`${g}/${p}/preview`),
880
892
  className: "px-4 py-2 border border-border rounded-md hover:bg-accent flex items-center gap-2",
881
- children: [/* @__PURE__ */ u(oe, { size: 20 }), p("tourBuilder.preview")]
893
+ children: [/* @__PURE__ */ u(oe, { size: 20 }), f("tourBuilder.preview")]
882
894
  }),
883
895
  /* @__PURE__ */ d("button", {
884
896
  type: "button",
885
- onClick: () => h(`${_}/${m}/analytics`),
897
+ onClick: () => m(`${g}/${p}/analytics`),
886
898
  className: "px-4 py-2 border border-border rounded-md hover:bg-accent flex items-center gap-2",
887
- children: [/* @__PURE__ */ u(ie, { size: 20 }), p("tourBuilder.analytics")]
899
+ children: [/* @__PURE__ */ u(ie, { size: 20 }), f("tourBuilder.analytics")]
888
900
  }),
889
901
  /* @__PURE__ */ d("button", {
890
902
  type: "button",
891
- onClick: () => h(`${_}/${m}/schedule`),
903
+ onClick: () => m(`${g}/${p}/schedule`),
892
904
  className: "px-4 py-2 border border-border rounded-md hover:bg-accent flex items-center gap-2",
893
905
  children: [/* @__PURE__ */ u(ae, { size: 20 }), "Schedule"]
894
906
  }),
@@ -896,8 +908,8 @@ function _() {
896
908
  permission: i.TOUR_TEMPLATE_CREATE,
897
909
  children: /* @__PURE__ */ d("button", {
898
910
  type: "button",
899
- onClick: Ae,
900
- disabled: !xe,
911
+ onClick: je,
912
+ disabled: !Se,
901
913
  className: "px-4 py-2 border border-border rounded-md hover:bg-accent flex items-center gap-2 disabled:opacity-50",
902
914
  children: [/* @__PURE__ */ u(se, { size: 20 }), "Save as Template"]
903
915
  })
@@ -907,9 +919,26 @@ function _() {
907
919
  ]
908
920
  })
909
921
  ]
922
+ }) : /* @__PURE__ */ u("div", {
923
+ className: "flex h-full items-center justify-center p-3 sm:p-6",
924
+ children: /* @__PURE__ */ d("div", {
925
+ className: "text-center space-y-4",
926
+ children: [/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("h2", {
927
+ className: "text-lg font-semibold text-foreground mb-2",
928
+ children: f("tourBuilder.accessDeniedTitle")
929
+ }), /* @__PURE__ */ u("p", {
930
+ className: "text-sm text-muted-foreground",
931
+ children: f(b ? "tourBuilder.createAccessDeniedMessage" : "tourBuilder.updateAccessDeniedMessage")
932
+ })] }), /* @__PURE__ */ u("button", {
933
+ type: "button",
934
+ onClick: Ae,
935
+ className: "inline-flex items-center justify-center rounded-md border border-border px-4 py-2 text-sm font-medium text-foreground hover:bg-accent",
936
+ children: f("tourBuilder.goBack")
937
+ })]
938
+ })
910
939
  });
911
940
  }
912
941
  //#endregion
913
- export { _ as TourBuilderPage };
942
+ export { g as TourBuilderPage };
914
943
 
915
944
  //# sourceMappingURL=TourBuilderPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TourBuilderPage.js","names":[],"sources":["../../../src/tours/pages/TourBuilderPage.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useState } from 'react';\nimport { useParams, useNavigate } from 'react-router-dom';\nimport {\n Save,\n ArrowLeft,\n Eye,\n ListOrdered,\n BarChart3,\n Calendar,\n LayoutTemplate,\n Sparkles,\n} from 'lucide-react';\nimport { gql } from '@apollo/client/core';\nimport { PermissionGate } from '@burdenoff/fe-libs/shared/components';\nimport { useEventBus } from '@burdenoff/fe-libs/shared/events';\nimport { useGatewayClient } from '@burdenoff/fe-libs/shared/graphql';\nimport { useTourBuilder } from '../hooks/useTourBuilder';\nimport { useTourLifecycle } from '../hooks/useTourLifecycle';\nimport { useToursPermissionAccess } from '../hooks/useToursPermissionAccess';\nimport { useToursContext } from '../providers/ToursProvider';\nimport { TOUR_PERMISSIONS } from '../../constants/permissions';\nimport type { Tour, TourTriggerType } from '../types';\nimport { useToursI18n } from '../i18n';\nimport { emitToursApiFailed } from '../telemetry';\nimport { useGetPlatformProductsForToursQuery } from '../../generated/global-operations';\n\n// Covers the current platform catalog with room for planned products; custom slug entry remains the fallback.\nconst PLATFORM_PRODUCTS_QUERY_LIMIT = 250;\n\nconst SEED_VIBECONTROLS_USER_TOURS = gql`\n mutation SeedVibeControlsUserTours {\n seedVibeControlsUserTours {\n productId\n workspaceId\n createdCount\n updatedCount\n totalCount\n tours {\n tourId\n slug\n name\n action\n stepCount\n }\n }\n }\n`;\n\ninterface SeededUserTourResult {\n tourId: string;\n slug: string;\n name: string;\n action: string;\n stepCount: number;\n}\n\ninterface SeedVibeControlsUserToursPayload {\n productId: string;\n workspaceId: string;\n createdCount: number;\n updatedCount: number;\n totalCount: number;\n tours: SeededUserTourResult[];\n}\n\ninterface SeedVibeControlsUserToursMutation {\n seedVibeControlsUserTours: SeedVibeControlsUserToursPayload;\n}\n\nfunction getMutationErrorMessage(result: unknown): string | null {\n if (!result || typeof result !== 'object') return null;\n\n const record = result as Record<string, unknown>;\n const singleError = record.error;\n if (singleError instanceof Error) return singleError.message;\n\n const errors = record.errors;\n if (!Array.isArray(errors) || errors.length === 0) return null;\n\n const messages = errors\n .map((error) => {\n if (error instanceof Error) return error.message;\n if (!error || typeof error !== 'object') return null;\n\n const message = (error as { message?: unknown }).message;\n return typeof message === 'string' ? message : null;\n })\n .filter((message): message is string => Boolean(message));\n\n return messages.length > 0 ? messages.join('; ') : 'Seed mutation returned errors.';\n}\n\ninterface TourRouteModuleOption {\n moduleId: string;\n label: string;\n path: string;\n}\n\ninterface TourRoutePageOption {\n pageId: string;\n label: string;\n path: string;\n}\n\ninterface TourRouteCatalogEntry {\n productId: string;\n moduleId: string;\n moduleLabel: string;\n pageId: string;\n pageLabel: string;\n path: string;\n isModuleHome?: boolean;\n}\n\nconst TOUR_ROUTE_CATALOG: readonly TourRouteCatalogEntry[] = [\n {\n productId: 'vibecontrols',\n moduleId: 'dashboard',\n moduleLabel: 'Dashboard',\n pageId: 'dashboard',\n pageLabel: 'Dashboard',\n path: '/dashboard',\n isModuleHome: true,\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'home',\n pageLabel: 'Overview',\n path: '/vibecontrols',\n isModuleHome: true,\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'agents',\n pageLabel: 'Targets & Agents',\n path: '/vibecontrols/agents',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'vibes',\n pageLabel: 'Vibes',\n path: '/vibecontrols/vibes',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'sessions',\n pageLabel: 'Sessions',\n path: '/vibecontrols/sessions',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'ai',\n pageLabel: 'AI',\n path: '/vibecontrols/ai',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'catalogs',\n pageLabel: 'Catalogs',\n path: '/vibecontrols/catalogs',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'components',\n pageLabel: 'Components',\n path: '/vibecontrols/components',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'templates',\n pageLabel: 'Templates',\n path: '/vibecontrols/templates',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'actions',\n pageLabel: 'Actions',\n path: '/vibecontrols/actions',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'vibedeck',\n pageLabel: 'Decks',\n path: '/vibecontrols/vibedeck',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'calendar',\n pageLabel: 'Calendar',\n path: '/vibecontrols/calendar',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'tunnels',\n pageLabel: 'Tunnels',\n path: '/vibecontrols/tunnels',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'analytics',\n pageLabel: 'Analytics',\n path: '/vibecontrols/analytics',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'audit',\n pageLabel: 'Audit Log',\n path: '/vibecontrols/audit',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'health',\n pageLabel: 'Health',\n path: '/vibecontrols/health',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'settings',\n pageLabel: 'Settings',\n path: '/vibecontrols/settings',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'scheduler',\n moduleLabel: 'Scheduler',\n pageId: 'scheduler',\n pageLabel: 'Scheduler',\n path: '/scheduler',\n isModuleHome: true,\n },\n {\n productId: 'vibecontrols',\n moduleId: 'sandbox',\n moduleLabel: 'Sandbox',\n pageId: 'sandbox',\n pageLabel: 'Sandbox',\n path: '/sandbox',\n isModuleHome: true,\n },\n {\n productId: 'vibecontrols',\n moduleId: 'support',\n moduleLabel: 'Support',\n pageId: 'tickets',\n pageLabel: 'Tickets',\n path: '/support/tickets',\n isModuleHome: true,\n },\n {\n productId: 'vibecontrols',\n moduleId: 'support',\n moduleLabel: 'Support',\n pageId: 'knowledge-base',\n pageLabel: 'Knowledge Base',\n path: '/support/kb',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'notifications',\n moduleLabel: 'Notifications',\n pageId: 'center',\n pageLabel: 'Notification Center',\n path: '/notifications/center',\n isModuleHome: true,\n },\n {\n productId: 'vibecontrols',\n moduleId: 'notifications',\n moduleLabel: 'Notifications',\n pageId: 'history',\n pageLabel: 'History',\n path: '/notifications/history',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'notifications',\n moduleLabel: 'Notifications',\n pageId: 'preferences',\n pageLabel: 'Preferences',\n path: '/notifications/preferences',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'conversations',\n moduleLabel: 'Conversations',\n pageId: 'home',\n pageLabel: 'All Conversations',\n path: '/conversations',\n isModuleHome: true,\n },\n {\n productId: 'vibecontrols',\n moduleId: 'conversations',\n moduleLabel: 'Conversations',\n pageId: 'list',\n pageLabel: 'Conversation List',\n path: '/conversations/list',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'conversations',\n moduleLabel: 'Conversations',\n pageId: 'new',\n pageLabel: 'New Conversation',\n path: '/conversations/new',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'conversations',\n moduleLabel: 'Conversations',\n pageId: 'settings',\n pageLabel: 'Settings',\n path: '/conversations/settings',\n },\n] as const;\n\nfunction normalizeCatalogValue(value: string | null | undefined): string | undefined {\n const normalized = value?.trim();\n return normalized ? normalized : undefined;\n}\n\nfunction getRouteCatalog(productId: string | null | undefined): TourRouteCatalogEntry[] {\n const productKey = normalizeCatalogValue(productId);\n if (!productKey) return [];\n return TOUR_ROUTE_CATALOG.filter((entry) => entry.productId === productKey);\n}\n\nfunction getTourRouteModules(productId: string | null | undefined): TourRouteModuleOption[] {\n const modules = new Map<string, TourRouteModuleOption>();\n\n for (const entry of getRouteCatalog(productId)) {\n const existing = modules.get(entry.moduleId);\n if (!existing || entry.isModuleHome) {\n modules.set(entry.moduleId, {\n moduleId: entry.moduleId,\n label: entry.moduleLabel,\n path: entry.path,\n });\n }\n }\n\n return [...modules.values()];\n}\n\nfunction getTourRoutePages(\n productId: string | null | undefined,\n moduleId: string | null | undefined\n): TourRoutePageOption[] {\n const moduleKey = normalizeCatalogValue(moduleId);\n if (!moduleKey) return [];\n\n return getRouteCatalog(productId)\n .filter((entry) => entry.moduleId === moduleKey)\n .map((entry) => ({\n pageId: entry.pageId,\n label: entry.pageLabel,\n path: entry.path,\n }));\n}\n\n/**\n * Tour builder page\n * Create or edit tour metadata\n */\nexport function TourBuilderPage() {\n const { tr } = useToursI18n();\n const { tourId } = useParams();\n const navigate = useNavigate();\n const toursContext = useToursContext();\n const { basePath = '/' } = toursContext;\n const eventBus = useEventBus();\n const globalClient = useGatewayClient('global');\n const { hasPermission } = useToursPermissionAccess();\n const isNew = !tourId || tourId === 'new';\n const canCreate = hasPermission(TOUR_PERMISSIONS.TOUR_CREATE);\n const canUpdate = hasPermission(TOUR_PERMISSIONS.TOUR_UPDATE);\n const canCreateTemplate = hasPermission(TOUR_PERMISSIONS.TOUR_TEMPLATE_CREATE);\n const canSave = isNew ? canCreate : canUpdate;\n const canSeedVibeControlsUserTours = canCreate && canUpdate;\n\n const { tour, loadTour, createTour, updateTour, saving, validationErrors, error } =\n useTourBuilder(tourId);\n const { saveAsTemplate } = useTourLifecycle();\n const { data: productsData, loading: productsLoading } = useGetPlatformProductsForToursQuery({\n variables: { limit: PLATFORM_PRODUCTS_QUERY_LIMIT, offset: 0 },\n fetchPolicy: 'cache-and-network',\n });\n\n const defaultFormData = {\n name: '',\n description: '',\n productId: '',\n moduleId: '',\n pageId: '',\n isActive: true,\n status: 'DRAFT' as const,\n triggerType: 'MANUAL' as const,\n priority: 50,\n displayOrder: 1,\n startDate: '',\n endDate: '',\n };\n\n const [formData, setFormData] = useState<Partial<Tour>>(defaultFormData);\n const [customProductEntry, setCustomProductEntry] = useState(false);\n const [customModuleEntry, setCustomModuleEntry] = useState(false);\n const [customPageEntry, setCustomPageEntry] = useState(false);\n const [seedLoading, setSeedLoading] = useState(false);\n const [seedResult, setSeedResult] = useState<SeedVibeControlsUserToursPayload | null>(null);\n const [seedError, setSeedError] = useState<string | null>(null);\n\n const formInitializedRef = useRef(false);\n\n const productOptions = useMemo(() => {\n return [...(productsData?.platformProducts.items ?? [])].sort((a, b) =>\n a.name.localeCompare(b.name)\n );\n }, [productsData]);\n\n const productOptionSlugs = useMemo(\n () => new Set(productOptions.map((product) => product.slug)),\n [productOptions]\n );\n\n const moduleOptions = useMemo(\n () => getTourRouteModules(formData.productId),\n [formData.productId]\n );\n\n const moduleOptionIds = useMemo(\n () => new Set(moduleOptions.map((moduleOption) => moduleOption.moduleId)),\n [moduleOptions]\n );\n\n const pageOptions = useMemo(\n () => getTourRoutePages(formData.productId, formData.moduleId),\n [formData.moduleId, formData.productId]\n );\n\n const pageOptionIds = useMemo(\n () => new Set(pageOptions.map((pageOption) => pageOption.pageId)),\n [pageOptions]\n );\n\n useEffect(() => {\n if (tourId && tourId !== 'new') {\n formInitializedRef.current = false;\n loadTour(tourId);\n }\n }, [tourId, loadTour]);\n\n useEffect(() => {\n if (tour && !formInitializedRef.current) {\n setFormData(tour);\n formInitializedRef.current = true;\n }\n }, [tour]);\n\n useEffect(() => {\n if (!formData.productId || productsLoading) {\n setCustomProductEntry(false);\n return;\n }\n setCustomProductEntry(productOptions.length > 0 && !productOptionSlugs.has(formData.productId));\n }, [formData.productId, productOptionSlugs, productOptions.length, productsLoading]);\n\n useEffect(() => {\n if (!formData.productId || !formData.moduleId) {\n setCustomModuleEntry(false);\n return;\n }\n setCustomModuleEntry(moduleOptions.length === 0 || !moduleOptionIds.has(formData.moduleId));\n }, [formData.moduleId, formData.productId, moduleOptionIds, moduleOptions.length]);\n\n useEffect(() => {\n if (!formData.productId || !formData.pageId) {\n setCustomPageEntry(false);\n return;\n }\n setCustomPageEntry(pageOptions.length === 0 || !pageOptionIds.has(formData.pageId));\n }, [formData.pageId, formData.productId, pageOptionIds, pageOptions.length]);\n\n const showCurrentProductOption = Boolean(\n formData.productId && !customProductEntry && !productOptionSlugs.has(formData.productId)\n );\n const showCurrentModuleOption = Boolean(\n formData.moduleId && !customModuleEntry && !moduleOptionIds.has(formData.moduleId)\n );\n const showCurrentPageOption = Boolean(\n formData.pageId && !customPageEntry && !pageOptionIds.has(formData.pageId)\n );\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n try {\n if (tourId && tourId !== 'new') {\n await updateTour(tourId, formData);\n } else {\n await createTour(formData);\n }\n } catch {\n emitToursApiFailed(eventBus, 'tour.save', toursContext);\n }\n };\n\n const handleBack = () => {\n navigate(`${basePath}/list`);\n };\n\n const formatDateTimeLocal = (value?: string) => {\n if (!value) return '';\n\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) {\n return '';\n }\n\n return new Date(date.getTime() - date.getTimezoneOffset() * 60000).toISOString().slice(0, 16);\n };\n\n const handleSaveTemplate = async () => {\n if (!tourId || tourId === 'new') return;\n\n const defaultName = `${formData.name || tour?.name || 'Tour'} Template`;\n const name = window.prompt('Template name', defaultName);\n if (!name) return;\n\n const category =\n window.prompt(\n 'Template category (ONBOARDING, FEATURE_ANNOUNCEMENT, HELP, CUSTOM)',\n 'ONBOARDING'\n ) || 'ONBOARDING';\n\n try {\n await saveAsTemplate(tourId, {\n name,\n description: formData.description,\n category,\n isPublic: false,\n });\n navigate(`${basePath}/templates`);\n } catch {\n emitToursApiFailed(eventBus, 'template.save', toursContext);\n }\n };\n\n const handleSeedVibeControlsUserTours = async () => {\n const confirmed = window.confirm(tr('tourBuilder.seedVibeControls.confirm'));\n if (!confirmed) return;\n\n setSeedLoading(true);\n setSeedResult(null);\n setSeedError(null);\n\n try {\n const result = await globalClient.mutate<SeedVibeControlsUserToursMutation>({\n mutation: SEED_VIBECONTROLS_USER_TOURS,\n });\n\n const mutationErrorMessage = getMutationErrorMessage(result);\n if (mutationErrorMessage) {\n throw new Error(mutationErrorMessage);\n }\n\n const payload = result.data?.seedVibeControlsUserTours;\n if (!payload) {\n throw new Error('Seed mutation returned no result.');\n }\n\n setSeedResult(payload);\n } catch (seedMutationError) {\n const errorMessage =\n seedMutationError instanceof Error\n ? seedMutationError.message\n : tr('tourBuilder.seedVibeControls.error');\n setSeedError(errorMessage);\n eventBus.emit(\n 'tours.api.failed',\n {\n route: '/tours',\n operation: 'tour.seed_vibecontrols_user_tours',\n errorMessage,\n productId: toursContext.productId,\n workspaceId: toursContext.workspaceId,\n },\n { component: 'microfe-tours' }\n );\n } finally {\n setSeedLoading(false);\n }\n };\n\n return (\n <div className=\"space-y-4 sm:space-y-6 p-3 sm:p-6 max-w-4xl mx-auto\">\n {/* Header */}\n <div className=\"flex items-center gap-4\">\n <button\n onClick={handleBack}\n className=\"p-2 hover:bg-accent rounded-md\"\n aria-label={tr('tourBuilder.goBack')}\n >\n <ArrowLeft size={20} />\n </button>\n <div className=\"flex-1\">\n <h1 className=\"text-xl sm:text-2xl font-bold text-foreground\">\n {tourId && tourId !== 'new'\n ? tr('tourBuilder.titleEdit')\n : tr('tourBuilder.titleCreate')}\n </h1>\n <p className=\"text-sm text-muted-foreground\">{tr('tourBuilder.subtitle')}</p>\n </div>\n </div>\n\n {isNew ? (\n <div className=\"rounded-md border border-border bg-card p-4 sm:p-6\">\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"space-y-1\">\n <h2 className=\"text-lg font-semibold text-foreground\">\n {tr('tourBuilder.seedVibeControls.title')}\n </h2>\n <p className=\"text-sm text-muted-foreground\">\n {tr('tourBuilder.seedVibeControls.description')}\n </p>\n </div>\n <button\n type=\"button\"\n onClick={() => void handleSeedVibeControlsUserTours()}\n disabled={seedLoading || !canSeedVibeControlsUserTours}\n className=\"inline-flex min-h-11 items-center justify-center gap-2 rounded-md border border-border bg-secondary px-4 py-2 text-sm font-medium text-secondary-foreground hover:bg-secondary/80 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <Sparkles size={18} />\n {seedLoading\n ? tr('tourBuilder.seedVibeControls.loading')\n : tr('tourBuilder.seedVibeControls.button')}\n </button>\n </div>\n {!canSeedVibeControlsUserTours ? (\n <p className=\"mt-3 text-sm text-muted-foreground\">\n {tr('tourBuilder.seedVibeControls.permissionHint')}\n </p>\n ) : null}\n {seedError ? <p className=\"mt-3 text-sm text-destructive\">{seedError}</p> : null}\n {seedResult ? (\n <div className=\"mt-3 rounded-md border border-border bg-background p-3 text-sm text-muted-foreground\">\n {tr('tourBuilder.seedVibeControls.result', {\n totalCount: seedResult.totalCount,\n productId: seedResult.productId,\n workspaceId: seedResult.workspaceId,\n createdCount: seedResult.createdCount,\n updatedCount: seedResult.updatedCount,\n })}\n </div>\n ) : null}\n </div>\n ) : null}\n\n {/* Form */}\n <form onSubmit={handleSubmit} className=\"space-y-6\">\n {/* Basic Info */}\n <div className=\"border border-border rounded-md p-4 sm:p-6 bg-card\">\n <h2 className=\"text-lg font-semibold mb-4\">{tr('tourBuilder.sectionBasicInfo')}</h2>\n\n <div className=\"space-y-4\">\n {/* Name */}\n <div>\n <label className=\"block text-sm font-medium mb-2\" htmlFor=\"tour-name\">\n {tr('tourBuilder.labelName')}\n </label>\n <input\n id=\"tour-name\"\n type=\"text\"\n value={formData.name || ''}\n onChange={(e) => setFormData({ ...formData, name: e.target.value })}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground\"\n required\n />\n </div>\n\n {/* Description */}\n <div>\n <label className=\"block text-sm font-medium mb-2\" htmlFor=\"tour-description\">\n {tr('tourBuilder.labelDescription')}\n </label>\n <textarea\n id=\"tour-description\"\n value={formData.description || ''}\n onChange={(e) => setFormData({ ...formData, description: e.target.value })}\n rows={3}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground\"\n />\n </div>\n\n {/* Product ID */}\n <div>\n <label className=\"block text-sm font-medium mb-2\" htmlFor=\"product-id\">\n {tr('tourBuilder.labelProductId')}\n </label>\n <select\n id=\"product-id\"\n value={customProductEntry ? '__custom__' : formData.productId || ''}\n onChange={(e) => {\n if (e.target.value === '__custom__') {\n setCustomProductEntry(true);\n setFormData({\n ...formData,\n productId: '',\n moduleId: undefined,\n pageId: undefined,\n });\n return;\n }\n\n setCustomProductEntry(false);\n setCustomModuleEntry(false);\n setCustomPageEntry(false);\n setFormData({\n ...formData,\n productId: e.target.value,\n moduleId: undefined,\n pageId: undefined,\n });\n }}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground\"\n required\n >\n <option value=\"\">Select product</option>\n {productsLoading ? <option disabled>Loading products...</option> : null}\n {productOptions.map((product) => (\n <option key={product.id} value={product.slug}>\n {product.name} ({product.slug})\n </option>\n ))}\n {showCurrentProductOption ? (\n <option value={formData.productId}>Current: {formData.productId}</option>\n ) : null}\n <option value=\"__custom__\">Custom product slug</option>\n </select>\n {customProductEntry ? (\n <input\n id=\"product-id-custom\"\n type=\"text\"\n value={formData.productId || ''}\n onChange={(e) =>\n setFormData({\n ...formData,\n productId: e.target.value,\n moduleId: undefined,\n pageId: undefined,\n })\n }\n className=\"mt-2 w-full px-3 py-2 border border-border rounded-md bg-background text-foreground\"\n placeholder=\"vibecontrols\"\n required\n />\n ) : null}\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label className=\"block text-sm font-medium mb-2\" htmlFor=\"module-id\">\n Module ID\n </label>\n <select\n id=\"module-id\"\n value={customModuleEntry ? '__custom__' : formData.moduleId || ''}\n onChange={(e) => {\n if (e.target.value === '__custom__') {\n setCustomModuleEntry(true);\n setFormData({ ...formData, moduleId: '', pageId: undefined });\n return;\n }\n\n setCustomModuleEntry(false);\n setCustomPageEntry(false);\n setFormData({\n ...formData,\n moduleId: e.target.value || undefined,\n pageId: undefined,\n });\n }}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground\"\n disabled={!formData.productId}\n >\n <option value=\"\">All modules</option>\n {moduleOptions.map((moduleOption) => (\n <option key={moduleOption.moduleId} value={moduleOption.moduleId}>\n {moduleOption.label} ({moduleOption.moduleId})\n </option>\n ))}\n {showCurrentModuleOption ? (\n <option value={formData.moduleId}>Current: {formData.moduleId}</option>\n ) : null}\n <option value=\"__custom__\">Custom module ID</option>\n </select>\n {customModuleEntry ? (\n <input\n id=\"module-id-custom\"\n type=\"text\"\n value={formData.moduleId || ''}\n onChange={(e) =>\n setFormData({\n ...formData,\n moduleId: e.target.value || undefined,\n pageId: undefined,\n })\n }\n className=\"mt-2 w-full px-3 py-2 border border-border rounded-md bg-background text-foreground\"\n placeholder=\"vibecontrols\"\n />\n ) : null}\n </div>\n\n <div>\n <label className=\"block text-sm font-medium mb-2\" htmlFor=\"page-id\">\n Page ID\n </label>\n <select\n id=\"page-id\"\n value={customPageEntry ? '__custom__' : formData.pageId || ''}\n onChange={(e) => {\n if (e.target.value === '__custom__') {\n setCustomPageEntry(true);\n setFormData({ ...formData, pageId: '' });\n return;\n }\n\n setCustomPageEntry(false);\n setFormData({ ...formData, pageId: e.target.value || undefined });\n }}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground\"\n disabled={!formData.productId}\n >\n <option value=\"\">All pages</option>\n {pageOptions.map((pageOption) => (\n <option key={pageOption.pageId} value={pageOption.pageId}>\n {pageOption.label} ({pageOption.pageId})\n </option>\n ))}\n {showCurrentPageOption ? (\n <option value={formData.pageId}>Current: {formData.pageId}</option>\n ) : null}\n <option value=\"__custom__\">Custom page ID</option>\n </select>\n {customPageEntry ? (\n <input\n id=\"page-id-custom\"\n type=\"text\"\n value={formData.pageId || ''}\n onChange={(e) =>\n setFormData({ ...formData, pageId: e.target.value || undefined })\n }\n className=\"mt-2 w-full px-3 py-2 border border-border rounded-md bg-background text-foreground\"\n placeholder=\"agents\"\n />\n ) : null}\n </div>\n </div>\n\n <label className=\"flex items-center gap-3 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={formData.isActive ?? true}\n onChange={(e) => setFormData({ ...formData, isActive: e.target.checked })}\n className=\"w-4 h-4 rounded\"\n />\n <span className=\"text-sm font-medium\">Active</span>\n </label>\n </div>\n </div>\n\n {/* Trigger Settings */}\n <div className=\"border border-border rounded-md p-4 sm:p-6 bg-card\">\n <h2 className=\"text-lg font-semibold mb-4\">{tr('tourBuilder.sectionTriggerSettings')}</h2>\n\n <div className=\"space-y-4\">\n {/* Trigger Type */}\n <div>\n <label className=\"block text-sm font-medium mb-2\" htmlFor=\"trigger-type\">\n {tr('tourBuilder.labelTriggerType')}\n </label>\n <select\n id=\"trigger-type\"\n value={formData.triggerType || 'MANUAL'}\n onChange={(e) =>\n setFormData({ ...formData, triggerType: e.target.value as TourTriggerType })\n }\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground\"\n >\n <option value=\"MANUAL\">{tr('tourBuilder.triggerManual')}</option>\n <option value=\"AUTO_FIRST_VISIT\">{tr('tourBuilder.triggerAutoFirstVisit')}</option>\n <option value=\"AUTO_ALWAYS\">{tr('tourBuilder.triggerAutoAlways')}</option>\n <option value=\"ON_EVENT\">{tr('tourBuilder.triggerOnEvent')}</option>\n <option value=\"SCHEDULED\">{tr('tourBuilder.triggerScheduled')}</option>\n </select>\n </div>\n\n {/* Priority */}\n <div>\n <label className=\"block text-sm font-medium mb-2\" htmlFor=\"priority\">\n {tr('tourBuilder.labelPriority')}\n </label>\n <input\n id=\"priority\"\n type=\"number\"\n min=\"1\"\n max=\"100\"\n value={formData.priority || 50}\n onChange={(e) => {\n const priority = Number.parseInt(e.target.value, 10) || 50;\n setFormData({ ...formData, priority });\n }}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground\"\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label className=\"block text-sm font-medium mb-2\" htmlFor=\"tour-start-date\">\n Start Date\n </label>\n <input\n id=\"tour-start-date\"\n type=\"datetime-local\"\n value={formatDateTimeLocal(formData.startDate)}\n onChange={(e) =>\n setFormData({\n ...formData,\n startDate: e.target.value\n ? new Date(e.target.value).toISOString()\n : undefined,\n })\n }\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground\"\n />\n </div>\n\n <div>\n <label className=\"block text-sm font-medium mb-2\" htmlFor=\"tour-end-date\">\n End Date\n </label>\n <input\n id=\"tour-end-date\"\n type=\"datetime-local\"\n value={formatDateTimeLocal(formData.endDate)}\n onChange={(e) =>\n setFormData({\n ...formData,\n endDate: e.target.value ? new Date(e.target.value).toISOString() : undefined,\n })\n }\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground\"\n />\n </div>\n </div>\n </div>\n </div>\n\n {/* API Error */}\n {error && (\n <div className=\"border border-destructive rounded-md p-4 bg-destructive/10\">\n <h3 className=\"font-semibold text-destructive mb-2\">{tr('tourBuilder.errorTitle')}</h3>\n <p className=\"text-sm text-destructive\">{error.message}</p>\n </div>\n )}\n\n {/* Validation Errors */}\n {validationErrors.length > 0 && (\n <div className=\"border border-destructive rounded-md p-4 bg-destructive/10\">\n <h3 className=\"font-semibold text-destructive mb-2\">\n {tr('tourBuilder.validationErrorsTitle')}\n </h3>\n <ul className=\"list-disc list-inside space-y-1\">\n {validationErrors.map((err, index) => (\n <li key={index} className=\"text-sm text-destructive\">\n {err.message}\n </li>\n ))}\n </ul>\n </div>\n )}\n\n {/* Actions */}\n <div className=\"flex flex-wrap gap-3\">\n <PermissionGate\n permission={isNew ? TOUR_PERMISSIONS.TOUR_CREATE : TOUR_PERMISSIONS.TOUR_UPDATE}\n >\n <button\n type=\"submit\"\n disabled={saving || !canSave}\n className=\"flex-1 min-w-[200px] 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('tourBuilder.saving')\n : tourId && tourId !== 'new'\n ? tr('tourBuilder.updateTour')\n : tr('tourBuilder.createAndAddSteps')}\n </button>\n </PermissionGate>\n {tourId && tourId !== 'new' && (\n <>\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/${tourId}/steps`)}\n className=\"px-4 py-2 bg-secondary text-secondary-foreground rounded-md hover:bg-secondary/80 flex items-center gap-2\"\n >\n <ListOrdered size={20} />\n {tr('tourBuilder.editSteps')}\n {tour?.steps && tour.steps.length > 0 && (\n <span className=\"ml-1 px-2 py-0.5 text-xs bg-primary/20 rounded-full\">\n {tour.steps.length}\n </span>\n )}\n </button>\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/${tourId}/preview`)}\n className=\"px-4 py-2 border border-border rounded-md hover:bg-accent flex items-center gap-2\"\n >\n <Eye size={20} />\n {tr('tourBuilder.preview')}\n </button>\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/${tourId}/analytics`)}\n className=\"px-4 py-2 border border-border rounded-md hover:bg-accent flex items-center gap-2\"\n >\n <BarChart3 size={20} />\n {tr('tourBuilder.analytics')}\n </button>\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/${tourId}/schedule`)}\n className=\"px-4 py-2 border border-border rounded-md hover:bg-accent flex items-center gap-2\"\n >\n <Calendar size={20} />\n Schedule\n </button>\n <PermissionGate permission={TOUR_PERMISSIONS.TOUR_TEMPLATE_CREATE}>\n <button\n type=\"button\"\n onClick={handleSaveTemplate}\n disabled={!canCreateTemplate}\n className=\"px-4 py-2 border border-border rounded-md hover:bg-accent flex items-center gap-2 disabled:opacity-50\"\n >\n <LayoutTemplate size={20} />\n Save as Template\n </button>\n </PermissionGate>\n </>\n )}\n </div>\n </form>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AA2BA,IAAM,KAAgC,KAEhC,KAA+B,CAAG;;;;;;;;;;;;;;;;;;AAwCxC,SAAS,GAAwB,GAAgC;AAC/D,KAAI,CAAC,KAAU,OAAO,KAAW,SAAU,QAAO;CAElD,IAAM,IAAS,GACT,IAAc,EAAO;AAC3B,KAAI,aAAuB,MAAO,QAAO,EAAY;CAErD,IAAM,IAAS,EAAO;AACtB,KAAI,CAAC,MAAM,QAAQ,EAAO,IAAI,EAAO,WAAW,EAAG,QAAO;CAE1D,IAAM,IAAW,EACd,KAAK,MAAU;AACd,MAAI,aAAiB,MAAO,QAAO,EAAM;AACzC,MAAI,CAAC,KAAS,OAAO,KAAU,SAAU,QAAO;EAEhD,IAAM,IAAW,EAAgC;AACjD,SAAO,OAAO,KAAY,WAAW,IAAU;GAC/C,CACD,QAAQ,MAA+B,EAAQ,EAAS;AAE3D,QAAO,EAAS,SAAS,IAAI,EAAS,KAAK,KAAK,GAAG;;AAyBrD,IAAM,IAAuD;CAC3D;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACN,cAAc;EACf;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACN,cAAc;EACf;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACN,cAAc;EACf;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACN,cAAc;EACf;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACN,cAAc;EACf;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACN,cAAc;EACf;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACN,cAAc;EACf;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAA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"}
1
+ {"version":3,"file":"TourBuilderPage.js","names":[],"sources":["../../../src/tours/pages/TourBuilderPage.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useState } from 'react';\nimport { useParams, useNavigate } from 'react-router-dom';\nimport {\n Save,\n ArrowLeft,\n Eye,\n ListOrdered,\n BarChart3,\n Calendar,\n LayoutTemplate,\n Sparkles,\n} from 'lucide-react';\nimport { gql } from '@apollo/client/core';\nimport { PermissionGate } from '@burdenoff/fe-libs/shared/components';\nimport { useEventBus } from '@burdenoff/fe-libs/shared/events';\nimport { useGatewayClient } from '@burdenoff/fe-libs/shared/graphql';\nimport { useTourBuilder } from '../hooks/useTourBuilder';\nimport { useTourLifecycle } from '../hooks/useTourLifecycle';\nimport { useToursPermissionAccess } from '../hooks/useToursPermissionAccess';\nimport { useToursContext } from '../providers/ToursProvider';\nimport { TOUR_PERMISSIONS } from '../../constants/permissions';\nimport type { Tour, TourTriggerType } from '../types';\nimport { useToursI18n } from '../i18n';\nimport { emitToursApiFailed } from '../telemetry';\nimport { useGetPlatformProductsForToursQuery } from '../../generated/global-operations';\n\n// Covers the current platform catalog with room for planned products; custom slug entry remains the fallback.\nconst PLATFORM_PRODUCTS_QUERY_LIMIT = 250;\n\nconst SEED_VIBECONTROLS_USER_TOURS = gql`\n mutation SeedVibeControlsUserTours {\n seedVibeControlsUserTours {\n productId\n workspaceId\n createdCount\n updatedCount\n totalCount\n tours {\n tourId\n slug\n name\n action\n stepCount\n }\n }\n }\n`;\n\ninterface SeededUserTourResult {\n tourId: string;\n slug: string;\n name: string;\n action: string;\n stepCount: number;\n}\n\ninterface SeedVibeControlsUserToursPayload {\n productId: string;\n workspaceId: string;\n createdCount: number;\n updatedCount: number;\n totalCount: number;\n tours: SeededUserTourResult[];\n}\n\ninterface SeedVibeControlsUserToursMutation {\n seedVibeControlsUserTours: SeedVibeControlsUserToursPayload;\n}\n\nfunction getMutationErrorMessage(result: unknown): string | null {\n if (!result || typeof result !== 'object') return null;\n\n const record = result as Record<string, unknown>;\n const singleError = record.error;\n if (singleError instanceof Error) return singleError.message;\n\n const errors = record.errors;\n if (!Array.isArray(errors) || errors.length === 0) return null;\n\n const messages = errors\n .map((error) => {\n if (error instanceof Error) return error.message;\n if (!error || typeof error !== 'object') return null;\n\n const message = (error as { message?: unknown }).message;\n return typeof message === 'string' ? message : null;\n })\n .filter((message): message is string => Boolean(message));\n\n return messages.length > 0 ? messages.join('; ') : 'Seed mutation returned errors.';\n}\n\ninterface TourRouteModuleOption {\n moduleId: string;\n label: string;\n path: string;\n}\n\ninterface TourRoutePageOption {\n pageId: string;\n label: string;\n path: string;\n}\n\ninterface TourRouteCatalogEntry {\n productId: string;\n moduleId: string;\n moduleLabel: string;\n pageId: string;\n pageLabel: string;\n path: string;\n isModuleHome?: boolean;\n}\n\nconst TOUR_ROUTE_CATALOG: readonly TourRouteCatalogEntry[] = [\n {\n productId: 'vibecontrols',\n moduleId: 'dashboard',\n moduleLabel: 'Dashboard',\n pageId: 'dashboard',\n pageLabel: 'Dashboard',\n path: '/dashboard',\n isModuleHome: true,\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'home',\n pageLabel: 'Overview',\n path: '/vibecontrols',\n isModuleHome: true,\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'agents',\n pageLabel: 'Targets & Agents',\n path: '/vibecontrols/agents',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'vibes',\n pageLabel: 'Vibes',\n path: '/vibecontrols/vibes',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'sessions',\n pageLabel: 'Sessions',\n path: '/vibecontrols/sessions',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'ai',\n pageLabel: 'AI',\n path: '/vibecontrols/ai',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'catalogs',\n pageLabel: 'Catalogs',\n path: '/vibecontrols/catalogs',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'components',\n pageLabel: 'Components',\n path: '/vibecontrols/components',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'templates',\n pageLabel: 'Templates',\n path: '/vibecontrols/templates',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'actions',\n pageLabel: 'Actions',\n path: '/vibecontrols/actions',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'vibedeck',\n pageLabel: 'Decks',\n path: '/vibecontrols/vibedeck',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'calendar',\n pageLabel: 'Calendar',\n path: '/vibecontrols/calendar',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'tunnels',\n pageLabel: 'Tunnels',\n path: '/vibecontrols/tunnels',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'analytics',\n pageLabel: 'Analytics',\n path: '/vibecontrols/analytics',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'audit',\n pageLabel: 'Audit Log',\n path: '/vibecontrols/audit',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'health',\n pageLabel: 'Health',\n path: '/vibecontrols/health',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'vibecontrols',\n moduleLabel: 'VibeControls',\n pageId: 'settings',\n pageLabel: 'Settings',\n path: '/vibecontrols/settings',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'scheduler',\n moduleLabel: 'Scheduler',\n pageId: 'scheduler',\n pageLabel: 'Scheduler',\n path: '/scheduler',\n isModuleHome: true,\n },\n {\n productId: 'vibecontrols',\n moduleId: 'sandbox',\n moduleLabel: 'Sandbox',\n pageId: 'sandbox',\n pageLabel: 'Sandbox',\n path: '/sandbox',\n isModuleHome: true,\n },\n {\n productId: 'vibecontrols',\n moduleId: 'support',\n moduleLabel: 'Support',\n pageId: 'tickets',\n pageLabel: 'Tickets',\n path: '/support/tickets',\n isModuleHome: true,\n },\n {\n productId: 'vibecontrols',\n moduleId: 'support',\n moduleLabel: 'Support',\n pageId: 'knowledge-base',\n pageLabel: 'Knowledge Base',\n path: '/support/kb',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'notifications',\n moduleLabel: 'Notifications',\n pageId: 'center',\n pageLabel: 'Notification Center',\n path: '/notifications/center',\n isModuleHome: true,\n },\n {\n productId: 'vibecontrols',\n moduleId: 'notifications',\n moduleLabel: 'Notifications',\n pageId: 'history',\n pageLabel: 'History',\n path: '/notifications/history',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'notifications',\n moduleLabel: 'Notifications',\n pageId: 'preferences',\n pageLabel: 'Preferences',\n path: '/notifications/preferences',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'conversations',\n moduleLabel: 'Conversations',\n pageId: 'home',\n pageLabel: 'All Conversations',\n path: '/conversations',\n isModuleHome: true,\n },\n {\n productId: 'vibecontrols',\n moduleId: 'conversations',\n moduleLabel: 'Conversations',\n pageId: 'list',\n pageLabel: 'Conversation List',\n path: '/conversations/list',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'conversations',\n moduleLabel: 'Conversations',\n pageId: 'new',\n pageLabel: 'New Conversation',\n path: '/conversations/new',\n },\n {\n productId: 'vibecontrols',\n moduleId: 'conversations',\n moduleLabel: 'Conversations',\n pageId: 'settings',\n pageLabel: 'Settings',\n path: '/conversations/settings',\n },\n] as const;\n\nfunction normalizeCatalogValue(value: string | null | undefined): string | undefined {\n const normalized = value?.trim();\n return normalized ? normalized : undefined;\n}\n\nfunction getRouteCatalog(productId: string | null | undefined): TourRouteCatalogEntry[] {\n const productKey = normalizeCatalogValue(productId);\n if (!productKey) return [];\n return TOUR_ROUTE_CATALOG.filter((entry) => entry.productId === productKey);\n}\n\nfunction getTourRouteModules(productId: string | null | undefined): TourRouteModuleOption[] {\n const modules = new Map<string, TourRouteModuleOption>();\n\n for (const entry of getRouteCatalog(productId)) {\n const existing = modules.get(entry.moduleId);\n if (!existing || entry.isModuleHome) {\n modules.set(entry.moduleId, {\n moduleId: entry.moduleId,\n label: entry.moduleLabel,\n path: entry.path,\n });\n }\n }\n\n return [...modules.values()];\n}\n\nfunction getTourRoutePages(\n productId: string | null | undefined,\n moduleId: string | null | undefined\n): TourRoutePageOption[] {\n const moduleKey = normalizeCatalogValue(moduleId);\n if (!moduleKey) return [];\n\n return getRouteCatalog(productId)\n .filter((entry) => entry.moduleId === moduleKey)\n .map((entry) => ({\n pageId: entry.pageId,\n label: entry.pageLabel,\n path: entry.path,\n }));\n}\n\n/**\n * Tour builder page\n * Create or edit tour metadata\n */\nexport function TourBuilderPage() {\n const { tr } = useToursI18n();\n const { tourId } = useParams();\n const navigate = useNavigate();\n const toursContext = useToursContext();\n const { basePath = '/' } = toursContext;\n const eventBus = useEventBus();\n const globalClient = useGatewayClient('global');\n const { hasPermission, isLoading: permissionsLoading } = useToursPermissionAccess();\n const isNew = !tourId || tourId === 'new';\n const canCreate = hasPermission(TOUR_PERMISSIONS.TOUR_CREATE);\n const canUpdate = hasPermission(TOUR_PERMISSIONS.TOUR_UPDATE);\n const canCreateTemplate = hasPermission(TOUR_PERMISSIONS.TOUR_TEMPLATE_CREATE);\n const canSave = isNew ? canCreate : canUpdate;\n const canSeedVibeControlsUserTours = canCreate && canUpdate;\n\n const { tour, loadTour, createTour, updateTour, saving, validationErrors, error } =\n useTourBuilder(tourId);\n const { saveAsTemplate } = useTourLifecycle();\n const { data: productsData, loading: productsLoading } = useGetPlatformProductsForToursQuery({\n variables: { limit: PLATFORM_PRODUCTS_QUERY_LIMIT, offset: 0 },\n fetchPolicy: 'cache-and-network',\n skip: permissionsLoading || !canSave,\n });\n\n const defaultFormData = {\n name: '',\n description: '',\n productId: '',\n moduleId: '',\n pageId: '',\n isActive: true,\n status: 'DRAFT' as const,\n triggerType: 'MANUAL' as const,\n priority: 50,\n displayOrder: 1,\n startDate: '',\n endDate: '',\n };\n\n const [formData, setFormData] = useState<Partial<Tour>>(defaultFormData);\n const [customProductEntry, setCustomProductEntry] = useState(false);\n const [customModuleEntry, setCustomModuleEntry] = useState(false);\n const [customPageEntry, setCustomPageEntry] = useState(false);\n const [seedLoading, setSeedLoading] = useState(false);\n const [seedResult, setSeedResult] = useState<SeedVibeControlsUserToursPayload | null>(null);\n const [seedError, setSeedError] = useState<string | null>(null);\n\n const formInitializedRef = useRef(false);\n\n const productOptions = useMemo(() => {\n return [...(productsData?.platformProducts.items ?? [])].sort((a, b) =>\n a.name.localeCompare(b.name)\n );\n }, [productsData]);\n\n const productOptionSlugs = useMemo(\n () => new Set(productOptions.map((product) => product.slug)),\n [productOptions]\n );\n\n const moduleOptions = useMemo(\n () => getTourRouteModules(formData.productId),\n [formData.productId]\n );\n\n const moduleOptionIds = useMemo(\n () => new Set(moduleOptions.map((moduleOption) => moduleOption.moduleId)),\n [moduleOptions]\n );\n\n const pageOptions = useMemo(\n () => getTourRoutePages(formData.productId, formData.moduleId),\n [formData.moduleId, formData.productId]\n );\n\n const pageOptionIds = useMemo(\n () => new Set(pageOptions.map((pageOption) => pageOption.pageId)),\n [pageOptions]\n );\n\n useEffect(() => {\n if (formInitializedRef.current) return;\n if (!permissionsLoading && canSave && tourId && tourId !== 'new') {\n loadTour(tourId);\n }\n }, [canSave, loadTour, permissionsLoading, tourId]);\n\n useEffect(() => {\n if (tour && !formInitializedRef.current) {\n setFormData(tour);\n formInitializedRef.current = true;\n }\n }, [tour]);\n\n useEffect(() => {\n if (!formData.productId || productsLoading) {\n setCustomProductEntry(false);\n return;\n }\n setCustomProductEntry(productOptions.length > 0 && !productOptionSlugs.has(formData.productId));\n }, [formData.productId, productOptionSlugs, productOptions.length, productsLoading]);\n\n useEffect(() => {\n if (!formData.productId || !formData.moduleId) {\n setCustomModuleEntry(false);\n return;\n }\n setCustomModuleEntry(moduleOptions.length === 0 || !moduleOptionIds.has(formData.moduleId));\n }, [formData.moduleId, formData.productId, moduleOptionIds, moduleOptions.length]);\n\n useEffect(() => {\n if (!formData.productId || !formData.pageId) {\n setCustomPageEntry(false);\n return;\n }\n setCustomPageEntry(pageOptions.length === 0 || !pageOptionIds.has(formData.pageId));\n }, [formData.pageId, formData.productId, pageOptionIds, pageOptions.length]);\n\n const showCurrentProductOption = Boolean(\n formData.productId && !customProductEntry && !productOptionSlugs.has(formData.productId)\n );\n const showCurrentModuleOption = Boolean(\n formData.moduleId && !customModuleEntry && !moduleOptionIds.has(formData.moduleId)\n );\n const showCurrentPageOption = Boolean(\n formData.pageId && !customPageEntry && !pageOptionIds.has(formData.pageId)\n );\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n try {\n if (tourId && tourId !== 'new') {\n await updateTour(tourId, formData);\n } else {\n await createTour(formData);\n }\n } catch {\n emitToursApiFailed(eventBus, 'tour.save', toursContext);\n }\n };\n\n const handleBack = () => {\n navigate(`${basePath}/list`);\n };\n\n const formatDateTimeLocal = (value?: string) => {\n if (!value) return '';\n\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) {\n return '';\n }\n\n return new Date(date.getTime() - date.getTimezoneOffset() * 60000).toISOString().slice(0, 16);\n };\n\n const handleSaveTemplate = async () => {\n if (!tourId || tourId === 'new') return;\n\n const defaultName = `${formData.name || tour?.name || 'Tour'} Template`;\n const name = window.prompt('Template name', defaultName);\n if (!name) return;\n\n const category =\n window.prompt(\n 'Template category (ONBOARDING, FEATURE_ANNOUNCEMENT, HELP, CUSTOM)',\n 'ONBOARDING'\n ) || 'ONBOARDING';\n\n try {\n await saveAsTemplate(tourId, {\n name,\n description: formData.description,\n category,\n isPublic: false,\n });\n navigate(`${basePath}/templates`);\n } catch {\n emitToursApiFailed(eventBus, 'template.save', toursContext);\n }\n };\n\n const handleSeedVibeControlsUserTours = async () => {\n const confirmed = window.confirm(tr('tourBuilder.seedVibeControls.confirm'));\n if (!confirmed) return;\n\n setSeedLoading(true);\n setSeedResult(null);\n setSeedError(null);\n\n try {\n const result = await globalClient.mutate<SeedVibeControlsUserToursMutation>({\n mutation: SEED_VIBECONTROLS_USER_TOURS,\n });\n\n const mutationErrorMessage = getMutationErrorMessage(result);\n if (mutationErrorMessage) {\n throw new Error(mutationErrorMessage);\n }\n\n const payload = result.data?.seedVibeControlsUserTours;\n if (!payload) {\n throw new Error('Seed mutation returned no result.');\n }\n\n setSeedResult(payload);\n } catch (seedMutationError) {\n const errorMessage =\n seedMutationError instanceof Error\n ? seedMutationError.message\n : tr('tourBuilder.seedVibeControls.error');\n setSeedError(errorMessage);\n eventBus.emit(\n 'tours.api.failed',\n {\n route: '/tours',\n operation: 'tour.seed_vibecontrols_user_tours',\n errorMessage,\n productId: toursContext.productId,\n workspaceId: toursContext.workspaceId,\n },\n { component: 'microfe-tours' }\n );\n } finally {\n setSeedLoading(false);\n }\n };\n\n if (permissionsLoading) {\n return (\n <div className=\"flex h-full items-center justify-center p-3 sm:p-6\">\n <p className=\"text-sm text-muted-foreground\">{tr('tourBuilder.loading')}</p>\n </div>\n );\n }\n\n if (!canSave) {\n return (\n <div className=\"flex h-full items-center justify-center p-3 sm:p-6\">\n <div className=\"text-center space-y-4\">\n <div>\n <h2 className=\"text-lg font-semibold text-foreground mb-2\">\n {tr('tourBuilder.accessDeniedTitle')}\n </h2>\n <p className=\"text-sm text-muted-foreground\">\n {isNew\n ? tr('tourBuilder.createAccessDeniedMessage')\n : tr('tourBuilder.updateAccessDeniedMessage')}\n </p>\n </div>\n <button\n type=\"button\"\n onClick={handleBack}\n className=\"inline-flex items-center justify-center rounded-md border border-border px-4 py-2 text-sm font-medium text-foreground hover:bg-accent\"\n >\n {tr('tourBuilder.goBack')}\n </button>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-4 sm:space-y-6 p-3 sm:p-6 max-w-4xl mx-auto\">\n {/* Header */}\n <div className=\"flex items-center gap-4\">\n <button\n onClick={handleBack}\n className=\"p-2 hover:bg-accent rounded-md\"\n aria-label={tr('tourBuilder.goBack')}\n >\n <ArrowLeft size={20} />\n </button>\n <div className=\"flex-1\">\n <h1 className=\"text-xl sm:text-2xl font-bold text-foreground\">\n {tourId && tourId !== 'new'\n ? tr('tourBuilder.titleEdit')\n : tr('tourBuilder.titleCreate')}\n </h1>\n <p className=\"text-sm text-muted-foreground\">{tr('tourBuilder.subtitle')}</p>\n </div>\n </div>\n\n {isNew ? (\n <div className=\"rounded-md border border-border bg-card p-4 sm:p-6\">\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"space-y-1\">\n <h2 className=\"text-lg font-semibold text-foreground\">\n {tr('tourBuilder.seedVibeControls.title')}\n </h2>\n <p className=\"text-sm text-muted-foreground\">\n {tr('tourBuilder.seedVibeControls.description')}\n </p>\n </div>\n <button\n type=\"button\"\n onClick={() => void handleSeedVibeControlsUserTours()}\n disabled={seedLoading || !canSeedVibeControlsUserTours}\n className=\"inline-flex min-h-11 items-center justify-center gap-2 rounded-md border border-border bg-secondary px-4 py-2 text-sm font-medium text-secondary-foreground hover:bg-secondary/80 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <Sparkles size={18} />\n {seedLoading\n ? tr('tourBuilder.seedVibeControls.loading')\n : tr('tourBuilder.seedVibeControls.button')}\n </button>\n </div>\n {!canSeedVibeControlsUserTours ? (\n <p className=\"mt-3 text-sm text-muted-foreground\">\n {tr('tourBuilder.seedVibeControls.permissionHint')}\n </p>\n ) : null}\n {seedError ? <p className=\"mt-3 text-sm text-destructive\">{seedError}</p> : null}\n {seedResult ? (\n <div className=\"mt-3 rounded-md border border-border bg-background p-3 text-sm text-muted-foreground\">\n {tr('tourBuilder.seedVibeControls.result', {\n totalCount: seedResult.totalCount,\n productId: seedResult.productId,\n workspaceId: seedResult.workspaceId,\n createdCount: seedResult.createdCount,\n updatedCount: seedResult.updatedCount,\n })}\n </div>\n ) : null}\n </div>\n ) : null}\n\n {/* Form */}\n <form onSubmit={handleSubmit} className=\"space-y-6\">\n {/* Basic Info */}\n <div className=\"border border-border rounded-md p-4 sm:p-6 bg-card\">\n <h2 className=\"text-lg font-semibold mb-4\">{tr('tourBuilder.sectionBasicInfo')}</h2>\n\n <div className=\"space-y-4\">\n {/* Name */}\n <div>\n <label className=\"block text-sm font-medium mb-2\" htmlFor=\"tour-name\">\n {tr('tourBuilder.labelName')}\n </label>\n <input\n id=\"tour-name\"\n type=\"text\"\n value={formData.name || ''}\n onChange={(e) => setFormData({ ...formData, name: e.target.value })}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground\"\n required\n />\n </div>\n\n {/* Description */}\n <div>\n <label className=\"block text-sm font-medium mb-2\" htmlFor=\"tour-description\">\n {tr('tourBuilder.labelDescription')}\n </label>\n <textarea\n id=\"tour-description\"\n value={formData.description || ''}\n onChange={(e) => setFormData({ ...formData, description: e.target.value })}\n rows={3}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground\"\n />\n </div>\n\n {/* Product ID */}\n <div>\n <label className=\"block text-sm font-medium mb-2\" htmlFor=\"product-id\">\n {tr('tourBuilder.labelProductId')}\n </label>\n <select\n id=\"product-id\"\n value={customProductEntry ? '__custom__' : formData.productId || ''}\n onChange={(e) => {\n if (e.target.value === '__custom__') {\n setCustomProductEntry(true);\n setFormData({\n ...formData,\n productId: '',\n moduleId: undefined,\n pageId: undefined,\n });\n return;\n }\n\n setCustomProductEntry(false);\n setCustomModuleEntry(false);\n setCustomPageEntry(false);\n setFormData({\n ...formData,\n productId: e.target.value,\n moduleId: undefined,\n pageId: undefined,\n });\n }}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground\"\n required\n >\n <option value=\"\">Select product</option>\n {productsLoading ? <option disabled>Loading products...</option> : null}\n {productOptions.map((product) => (\n <option key={product.id} value={product.slug}>\n {product.name} ({product.slug})\n </option>\n ))}\n {showCurrentProductOption ? (\n <option value={formData.productId}>Current: {formData.productId}</option>\n ) : null}\n <option value=\"__custom__\">Custom product slug</option>\n </select>\n {customProductEntry ? (\n <input\n id=\"product-id-custom\"\n type=\"text\"\n value={formData.productId || ''}\n onChange={(e) =>\n setFormData({\n ...formData,\n productId: e.target.value,\n moduleId: undefined,\n pageId: undefined,\n })\n }\n className=\"mt-2 w-full px-3 py-2 border border-border rounded-md bg-background text-foreground\"\n placeholder=\"vibecontrols\"\n required\n />\n ) : null}\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label className=\"block text-sm font-medium mb-2\" htmlFor=\"module-id\">\n Module ID\n </label>\n <select\n id=\"module-id\"\n value={customModuleEntry ? '__custom__' : formData.moduleId || ''}\n onChange={(e) => {\n if (e.target.value === '__custom__') {\n setCustomModuleEntry(true);\n setFormData({ ...formData, moduleId: '', pageId: undefined });\n return;\n }\n\n setCustomModuleEntry(false);\n setCustomPageEntry(false);\n setFormData({\n ...formData,\n moduleId: e.target.value || undefined,\n pageId: undefined,\n });\n }}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground\"\n disabled={!formData.productId}\n >\n <option value=\"\">All modules</option>\n {moduleOptions.map((moduleOption) => (\n <option key={moduleOption.moduleId} value={moduleOption.moduleId}>\n {moduleOption.label} ({moduleOption.moduleId})\n </option>\n ))}\n {showCurrentModuleOption ? (\n <option value={formData.moduleId}>Current: {formData.moduleId}</option>\n ) : null}\n <option value=\"__custom__\">Custom module ID</option>\n </select>\n {customModuleEntry ? (\n <input\n id=\"module-id-custom\"\n type=\"text\"\n value={formData.moduleId || ''}\n onChange={(e) =>\n setFormData({\n ...formData,\n moduleId: e.target.value || undefined,\n pageId: undefined,\n })\n }\n className=\"mt-2 w-full px-3 py-2 border border-border rounded-md bg-background text-foreground\"\n placeholder=\"vibecontrols\"\n />\n ) : null}\n </div>\n\n <div>\n <label className=\"block text-sm font-medium mb-2\" htmlFor=\"page-id\">\n Page ID\n </label>\n <select\n id=\"page-id\"\n value={customPageEntry ? '__custom__' : formData.pageId || ''}\n onChange={(e) => {\n if (e.target.value === '__custom__') {\n setCustomPageEntry(true);\n setFormData({ ...formData, pageId: '' });\n return;\n }\n\n setCustomPageEntry(false);\n setFormData({ ...formData, pageId: e.target.value || undefined });\n }}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground\"\n disabled={!formData.productId}\n >\n <option value=\"\">All pages</option>\n {pageOptions.map((pageOption) => (\n <option key={pageOption.pageId} value={pageOption.pageId}>\n {pageOption.label} ({pageOption.pageId})\n </option>\n ))}\n {showCurrentPageOption ? (\n <option value={formData.pageId}>Current: {formData.pageId}</option>\n ) : null}\n <option value=\"__custom__\">Custom page ID</option>\n </select>\n {customPageEntry ? (\n <input\n id=\"page-id-custom\"\n type=\"text\"\n value={formData.pageId || ''}\n onChange={(e) =>\n setFormData({ ...formData, pageId: e.target.value || undefined })\n }\n className=\"mt-2 w-full px-3 py-2 border border-border rounded-md bg-background text-foreground\"\n placeholder=\"agents\"\n />\n ) : null}\n </div>\n </div>\n\n <label className=\"flex items-center gap-3 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={formData.isActive ?? true}\n onChange={(e) => setFormData({ ...formData, isActive: e.target.checked })}\n className=\"w-4 h-4 rounded\"\n />\n <span className=\"text-sm font-medium\">Active</span>\n </label>\n </div>\n </div>\n\n {/* Trigger Settings */}\n <div className=\"border border-border rounded-md p-4 sm:p-6 bg-card\">\n <h2 className=\"text-lg font-semibold mb-4\">{tr('tourBuilder.sectionTriggerSettings')}</h2>\n\n <div className=\"space-y-4\">\n {/* Trigger Type */}\n <div>\n <label className=\"block text-sm font-medium mb-2\" htmlFor=\"trigger-type\">\n {tr('tourBuilder.labelTriggerType')}\n </label>\n <select\n id=\"trigger-type\"\n value={formData.triggerType || 'MANUAL'}\n onChange={(e) =>\n setFormData({ ...formData, triggerType: e.target.value as TourTriggerType })\n }\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground\"\n >\n <option value=\"MANUAL\">{tr('tourBuilder.triggerManual')}</option>\n <option value=\"AUTO_FIRST_VISIT\">{tr('tourBuilder.triggerAutoFirstVisit')}</option>\n <option value=\"AUTO_ALWAYS\">{tr('tourBuilder.triggerAutoAlways')}</option>\n <option value=\"ON_EVENT\">{tr('tourBuilder.triggerOnEvent')}</option>\n <option value=\"SCHEDULED\">{tr('tourBuilder.triggerScheduled')}</option>\n </select>\n </div>\n\n {/* Priority */}\n <div>\n <label className=\"block text-sm font-medium mb-2\" htmlFor=\"priority\">\n {tr('tourBuilder.labelPriority')}\n </label>\n <input\n id=\"priority\"\n type=\"number\"\n min=\"1\"\n max=\"100\"\n value={formData.priority || 50}\n onChange={(e) => {\n const priority = Number.parseInt(e.target.value, 10) || 50;\n setFormData({ ...formData, priority });\n }}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground\"\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label className=\"block text-sm font-medium mb-2\" htmlFor=\"tour-start-date\">\n Start Date\n </label>\n <input\n id=\"tour-start-date\"\n type=\"datetime-local\"\n value={formatDateTimeLocal(formData.startDate)}\n onChange={(e) =>\n setFormData({\n ...formData,\n startDate: e.target.value\n ? new Date(e.target.value).toISOString()\n : undefined,\n })\n }\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground\"\n />\n </div>\n\n <div>\n <label className=\"block text-sm font-medium mb-2\" htmlFor=\"tour-end-date\">\n End Date\n </label>\n <input\n id=\"tour-end-date\"\n type=\"datetime-local\"\n value={formatDateTimeLocal(formData.endDate)}\n onChange={(e) =>\n setFormData({\n ...formData,\n endDate: e.target.value ? new Date(e.target.value).toISOString() : undefined,\n })\n }\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground\"\n />\n </div>\n </div>\n </div>\n </div>\n\n {/* API Error */}\n {error && (\n <div className=\"border border-destructive rounded-md p-4 bg-destructive/10\">\n <h3 className=\"font-semibold text-destructive mb-2\">{tr('tourBuilder.errorTitle')}</h3>\n <p className=\"text-sm text-destructive\">{error.message}</p>\n </div>\n )}\n\n {/* Validation Errors */}\n {validationErrors.length > 0 && (\n <div className=\"border border-destructive rounded-md p-4 bg-destructive/10\">\n <h3 className=\"font-semibold text-destructive mb-2\">\n {tr('tourBuilder.validationErrorsTitle')}\n </h3>\n <ul className=\"list-disc list-inside space-y-1\">\n {validationErrors.map((err, index) => (\n <li key={index} className=\"text-sm text-destructive\">\n {err.message}\n </li>\n ))}\n </ul>\n </div>\n )}\n\n {/* Actions */}\n <div className=\"flex flex-wrap gap-3\">\n <PermissionGate\n permission={isNew ? TOUR_PERMISSIONS.TOUR_CREATE : TOUR_PERMISSIONS.TOUR_UPDATE}\n >\n <button\n type=\"submit\"\n disabled={saving || !canSave}\n className=\"flex-1 min-w-[200px] 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('tourBuilder.saving')\n : tourId && tourId !== 'new'\n ? tr('tourBuilder.updateTour')\n : tr('tourBuilder.createAndAddSteps')}\n </button>\n </PermissionGate>\n {tourId && tourId !== 'new' && (\n <>\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/${tourId}/steps`)}\n className=\"px-4 py-2 bg-secondary text-secondary-foreground rounded-md hover:bg-secondary/80 flex items-center gap-2\"\n >\n <ListOrdered size={20} />\n {tr('tourBuilder.editSteps')}\n {tour?.steps && tour.steps.length > 0 && (\n <span className=\"ml-1 px-2 py-0.5 text-xs bg-primary/20 rounded-full\">\n {tour.steps.length}\n </span>\n )}\n </button>\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/${tourId}/preview`)}\n className=\"px-4 py-2 border border-border rounded-md hover:bg-accent flex items-center gap-2\"\n >\n <Eye size={20} />\n {tr('tourBuilder.preview')}\n </button>\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/${tourId}/analytics`)}\n className=\"px-4 py-2 border border-border rounded-md hover:bg-accent flex items-center gap-2\"\n >\n <BarChart3 size={20} />\n {tr('tourBuilder.analytics')}\n </button>\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/${tourId}/schedule`)}\n className=\"px-4 py-2 border border-border rounded-md hover:bg-accent flex items-center gap-2\"\n >\n <Calendar size={20} />\n Schedule\n </button>\n <PermissionGate permission={TOUR_PERMISSIONS.TOUR_TEMPLATE_CREATE}>\n <button\n type=\"button\"\n onClick={handleSaveTemplate}\n disabled={!canCreateTemplate}\n className=\"px-4 py-2 border border-border rounded-md hover:bg-accent flex items-center gap-2 disabled:opacity-50\"\n >\n <LayoutTemplate size={20} />\n Save as Template\n </button>\n </PermissionGate>\n </>\n )}\n </div>\n </form>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AA2BA,IAAM,KAAgC,KAEhC,KAA+B,CAAG;;;;;;;;;;;;;;;;;;AAwCxC,SAAS,GAAwB,GAAgC;AAC/D,KAAI,CAAC,KAAU,OAAO,KAAW,SAAU,QAAO;CAElD,IAAM,IAAS,GACT,IAAc,EAAO;AAC3B,KAAI,aAAuB,MAAO,QAAO,EAAY;CAErD,IAAM,IAAS,EAAO;AACtB,KAAI,CAAC,MAAM,QAAQ,EAAO,IAAI,EAAO,WAAW,EAAG,QAAO;CAE1D,IAAM,IAAW,EACd,KAAK,MAAU;AACd,MAAI,aAAiB,MAAO,QAAO,EAAM;AACzC,MAAI,CAAC,KAAS,OAAO,KAAU,SAAU,QAAO;EAEhD,IAAM,IAAW,EAAgC;AACjD,SAAO,OAAO,KAAY,WAAW,IAAU;GAC/C,CACD,QAAQ,MAA+B,EAAQ,EAAS;AAE3D,QAAO,EAAS,SAAS,IAAI,EAAS,KAAK,KAAK,GAAG;;AAyBrD,IAAM,IAAuD;CAC3D;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACN,cAAc;EACf;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACN,cAAc;EACf;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACN,cAAc;EACf;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACN,cAAc;EACf;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACN,cAAc;EACf;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACN,cAAc;EACf;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACP;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAAW;EACX,MAAM;EACN,cAAc;EACf;CACD;EACE,WAAW;EACX,UAAU;EACV,aAAa;EACb,QAAQ;EACR,WAA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"}
@@ -9,62 +9,62 @@ import { useToursI18n as s } from "../i18n.js";
9
9
  import { isNative as c, nativeConfirm as l, nativeImpact as u, nativeNotify as d, nativeToast as f } from "../../utils/nativeBridge.js";
10
10
  import { useEffect as p, useRef as m, useState as h } from "react";
11
11
  import { PermissionGate as g } from "@burdenoff/fe-libs/shared/components";
12
- import { Eye as _, Grid as v, List as y, ListOrdered as ee, MoreVertical as te, Plus as ne, Search as b, Settings as x } from "lucide-react";
12
+ import { Eye as _, Grid as v, List as y, ListOrdered as b, MoreVertical as ee, Plus as te, Search as ne, Settings as x } from "lucide-react";
13
13
  import { jsx as S, jsxs as C } from "react/jsx-runtime";
14
14
  import { useNavigate as w } from "react-router-dom";
15
15
  //#region src/tours/pages/ToursListPage.tsx
16
16
  function T() {
17
- let { tr: T } = s(), E = w(), { basePath: D = "/" } = e(), { viewMode: O, tourFilter: k, toursListRevision: A, setViewMode: j, updateTourFilter: M, notifyToursListChanged: N } = t(), { hasPermission: P, isLoading: F } = a(), I = P(o.TOUR_UPDATE), L = P(o.TOUR_STEP_UPDATE), R = P(o.TOUR_DELETE), z = P(o.TOUR_PUBLISH), B = P(o.TOUR_ARCHIVE), V = P(o.TOUR_DUPLICATE), { tours: H, loading: U, fetchTours: W } = r(), { publishTour: G, unpublishTour: K, archiveTour: re, duplicateTour: q } = i(), [J] = n(), [Y, X] = h(""), [ie, ae] = h("all"), [Z, Q] = h(null), $ = m(null);
17
+ let { tr: T } = s(), E = w(), { basePath: D = "/" } = e(), { viewMode: O, tourFilter: k, toursListRevision: A, setViewMode: j, updateTourFilter: M, notifyToursListChanged: N } = t(), { hasPermission: P, isLoading: F } = a(), I = P(o.TOUR_UPDATE), L = P(o.TOUR_STEP_UPDATE), R = P(o.TOUR_READ), z = P(o.TOUR_DELETE), B = P(o.TOUR_PUBLISH), V = P(o.TOUR_ARCHIVE), H = P(o.TOUR_DUPLICATE), { tours: U, loading: W, fetchTours: G } = r(), { publishTour: K, unpublishTour: re, archiveTour: q, duplicateTour: J } = i(), [Y] = n(), [X, ie] = h(""), [ae, oe] = h("all"), [Z, Q] = h(null), $ = m(null);
18
18
  p(() => {
19
- F || W({ ...k });
19
+ F || G({ ...k });
20
20
  }, [
21
- W,
21
+ G,
22
22
  k,
23
23
  A,
24
24
  F
25
25
  ]);
26
- let oe = (e) => {
27
- X(e), M({ search: e });
28
- }, se = (e) => {
29
- ae(e), M({ status: e });
30
- }, ce = () => {
26
+ let se = (e) => {
27
+ ie(e), M({ search: e });
28
+ }, ce = (e) => {
29
+ oe(e), M({ status: e });
30
+ }, le = () => {
31
31
  E(D.endsWith("/") ? `${D}new` : `${D}/new`);
32
- }, le = (e) => {
32
+ }, ue = (e) => {
33
33
  switch (e) {
34
34
  case "DRAFT": return T("toursList.statusDraft");
35
35
  case "PUBLISHED": return T("toursList.statusPublished");
36
36
  case "ARCHIVED": return T("toursList.statusArchived");
37
37
  case "SCHEDULED": return T("toursList.statusScheduled");
38
38
  }
39
- }, ue = async (e) => {
39
+ }, de = async (e) => {
40
40
  Q(null), u("light");
41
41
  try {
42
- await G(e), d("success");
42
+ await K(e), d("success");
43
43
  } catch {
44
44
  d("error"), c() ? f(T("toursList.errorPublish")) : alert(T("toursList.errorPublish"));
45
45
  }
46
- }, de = async (e) => {
46
+ }, fe = async (e) => {
47
47
  Q(null), u("light");
48
48
  try {
49
- await K(e), d("success");
49
+ await re(e), d("success");
50
50
  } catch {
51
51
  d("error"), c() ? f(T("toursList.errorUnpublish")) : alert(T("toursList.errorUnpublish"));
52
52
  }
53
- }, fe = async (e) => {
53
+ }, pe = async (e) => {
54
54
  Q(null), u("light");
55
55
  try {
56
- await re(e), d("success");
56
+ await q(e), d("success");
57
57
  } catch {
58
58
  d("error"), c() ? f(T("toursList.errorArchive")) : alert(T("toursList.errorArchive"));
59
59
  }
60
- }, pe = async (e) => {
60
+ }, me = async (e) => {
61
61
  Q(null), u("light");
62
62
  try {
63
- await q(e), d("success");
63
+ await J(e), d("success");
64
64
  } catch {
65
65
  d("error"), c() ? f(T("toursList.errorDuplicate")) : alert(T("toursList.errorDuplicate"));
66
66
  }
67
- }, me = async (e) => {
67
+ }, he = async (e) => {
68
68
  Q(null), u("medium");
69
69
  let t = T("toursList.confirmDelete"), n = await l({
70
70
  title: T("toursList.actionDelete"),
@@ -72,7 +72,7 @@ function T() {
72
72
  okButtonTitle: T("toursList.actionDelete")
73
73
  });
74
74
  if (n === null ? window.confirm(t) : n) try {
75
- await J({ variables: { id: e } }), N(), d("success");
75
+ await Y({ variables: { id: e } }), N(), d("success");
76
76
  } catch {
77
77
  d("error"), c() ? f(T("toursList.errorDelete")) : alert(T("toursList.errorDelete"));
78
78
  }
@@ -99,9 +99,9 @@ function T() {
99
99
  }), /* @__PURE__ */ S(g, {
100
100
  permission: o.TOUR_CREATE,
101
101
  children: /* @__PURE__ */ C("button", {
102
- onClick: ce,
102
+ onClick: le,
103
103
  className: "w-full sm:w-auto px-4 py-2 min-h-[44px] bg-primary text-primary-foreground rounded-md hover:bg-primary/90 active:bg-primary/80 flex items-center justify-center gap-2",
104
- children: [/* @__PURE__ */ S(ne, { size: 20 }), T("toursList.createTour")]
104
+ children: [/* @__PURE__ */ S(te, { size: 20 }), T("toursList.createTour")]
105
105
  })
106
106
  })]
107
107
  }),
@@ -109,21 +109,21 @@ function T() {
109
109
  className: "flex flex-col sm:flex-row gap-3 sm:gap-4",
110
110
  children: [/* @__PURE__ */ C("div", {
111
111
  className: "flex-1 relative",
112
- children: [/* @__PURE__ */ S(b, {
112
+ children: [/* @__PURE__ */ S(ne, {
113
113
  className: "absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground",
114
114
  size: 20
115
115
  }), /* @__PURE__ */ S("input", {
116
116
  type: "text",
117
117
  placeholder: T("toursList.searchPlaceholder"),
118
- value: Y,
119
- onChange: (e) => oe(e.target.value),
118
+ value: X,
119
+ onChange: (e) => se(e.target.value),
120
120
  className: "w-full pl-[3.25rem] pr-4 py-2 min-h-[44px] border border-border rounded-md bg-background text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
121
121
  })]
122
122
  }), /* @__PURE__ */ C("div", {
123
123
  className: "flex gap-2",
124
124
  children: [/* @__PURE__ */ C("select", {
125
- value: ie,
126
- onChange: (e) => se(e.target.value),
125
+ value: ae,
126
+ onChange: (e) => ce(e.target.value),
127
127
  className: "px-4 py-2 min-h-[44px] border border-border rounded-md bg-background text-foreground",
128
128
  children: [
129
129
  /* @__PURE__ */ S("option", {
@@ -165,16 +165,16 @@ function T() {
165
165
  })]
166
166
  })]
167
167
  }),
168
- U ? /* @__PURE__ */ S("div", {
168
+ W ? /* @__PURE__ */ S("div", {
169
169
  className: "text-center py-12",
170
170
  children: /* @__PURE__ */ S("p", {
171
171
  className: "text-sm sm:text-base text-muted-foreground",
172
172
  children: T("toursList.loading")
173
173
  })
174
- }) : H.length > 0 ? /* @__PURE__ */ S("div", {
174
+ }) : U.length > 0 ? /* @__PURE__ */ S("div", {
175
175
  className: O === "grid" ? "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 sm:gap-4" : "space-y-3",
176
- children: H.map((e) => {
177
- let t = e.status, n = t === "DRAFT" && z, r = t === "PUBLISHED" && z, i = t !== "ARCHIVED" && B, a = n || r || V || i || R;
176
+ children: U.map((e) => {
177
+ let t = e.status, n = t === "DRAFT" && B, r = t === "PUBLISHED" && B, i = t !== "ARCHIVED" && V, a = n || r || H || i || z;
178
178
  return /* @__PURE__ */ C("div", {
179
179
  className: "border border-border rounded-md p-4 bg-card hover:shadow-md transition-shadow",
180
180
  children: [
@@ -188,7 +188,7 @@ function T() {
188
188
  children: e.name
189
189
  }), /* @__PURE__ */ S("span", {
190
190
  className: `px-2 py-1 text-xs rounded-full ${e.status === "PUBLISHED" ? "bg-success/10 text-success" : e.status === "DRAFT" ? "bg-muted text-muted-foreground" : "bg-warning/10 text-warning"}`,
191
- children: le(t)
191
+ children: ue(t)
192
192
  })]
193
193
  }),
194
194
  e.description && /* @__PURE__ */ S("p", {
@@ -216,9 +216,9 @@ function T() {
216
216
  },
217
217
  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",
218
218
  title: T("toursList.editStepsTitle"),
219
- children: [/* @__PURE__ */ S(ee, { size: 14 }), T("toursList.stepsButton")]
219
+ children: [/* @__PURE__ */ S(b, { size: 14 }), T("toursList.stepsButton")]
220
220
  }),
221
- /* @__PURE__ */ C("button", {
221
+ R && /* @__PURE__ */ C("button", {
222
222
  onClick: (t) => {
223
223
  t.stopPropagation(), E(`${D}/${e.id}/preview`);
224
224
  },
@@ -245,41 +245,41 @@ function T() {
245
245
  className: "px-2 py-2 min-h-[44px] min-w-[44px] text-xs border border-border rounded hover:bg-accent",
246
246
  title: T("toursList.moreActionsTitle"),
247
247
  "aria-label": T("toursList.moreActionsTitle"),
248
- children: /* @__PURE__ */ S(te, { size: 14 })
248
+ children: /* @__PURE__ */ S(ee, { size: 14 })
249
249
  }), Z === e.id && /* @__PURE__ */ C("div", {
250
250
  className: "absolute right-0 top-full mt-1 w-40 bg-card border border-border rounded-md shadow-lg z-10",
251
251
  children: [
252
252
  n && /* @__PURE__ */ S("button", {
253
253
  onClick: (t) => {
254
- t.stopPropagation(), ue(e.id);
254
+ t.stopPropagation(), de(e.id);
255
255
  },
256
256
  className: "w-full text-left px-3 py-2 min-h-[44px] text-xs hover:bg-accent",
257
257
  children: T("toursList.actionPublish")
258
258
  }),
259
259
  r && /* @__PURE__ */ S("button", {
260
260
  onClick: (t) => {
261
- t.stopPropagation(), de(e.id);
261
+ t.stopPropagation(), fe(e.id);
262
262
  },
263
263
  className: "w-full text-left px-3 py-2 min-h-[44px] text-xs hover:bg-accent",
264
264
  children: T("toursList.actionUnpublish")
265
265
  }),
266
- V && /* @__PURE__ */ S("button", {
266
+ H && /* @__PURE__ */ S("button", {
267
267
  onClick: (t) => {
268
- t.stopPropagation(), pe(e.id);
268
+ t.stopPropagation(), me(e.id);
269
269
  },
270
270
  className: "w-full text-left px-3 py-2 min-h-[44px] text-xs hover:bg-accent",
271
271
  children: T("toursList.actionDuplicate")
272
272
  }),
273
273
  i && /* @__PURE__ */ S("button", {
274
274
  onClick: (t) => {
275
- t.stopPropagation(), fe(e.id);
275
+ t.stopPropagation(), pe(e.id);
276
276
  },
277
277
  className: "w-full text-left px-3 py-2 min-h-[44px] text-xs hover:bg-accent",
278
278
  children: T("toursList.actionArchive")
279
279
  }),
280
- R && /* @__PURE__ */ S("button", {
280
+ z && /* @__PURE__ */ S("button", {
281
281
  onClick: (t) => {
282
- t.stopPropagation(), me(e.id);
282
+ t.stopPropagation(), he(e.id);
283
283
  },
284
284
  className: "w-full text-left px-3 py-2 min-h-[44px] text-xs text-destructive hover:bg-destructive/10",
285
285
  children: T("toursList.actionDelete")
@@ -1 +1 @@
1
- {"version":3,"file":"ToursListPage.js","names":[],"sources":["../../../src/tours/pages/ToursListPage.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport {\n Plus,\n Search,\n Grid,\n List as ListIcon,\n ListOrdered,\n Eye,\n Settings,\n MoreVertical,\n} from 'lucide-react';\nimport { PermissionGate } from '@burdenoff/fe-libs/shared/components';\nimport { useToursList } from '../hooks/useToursList';\nimport { useTourLifecycle } from '../hooks/useTourLifecycle';\nimport { useToursPermissionAccess } from '../hooks/useToursPermissionAccess';\nimport { useToursStore } from '../store/toursStore';\nimport { useToursContext } from '../providers/ToursProvider';\nimport { useDeleteTourMutation } from '../../generated/global-operations';\nimport { TOUR_PERMISSIONS } from '../../constants/permissions';\nimport type { TourStatus } from '../types';\nimport type { Tour } from '../../generated/global-types';\nimport { useToursI18n } from '../i18n';\nimport {\n isNative,\n nativeConfirm,\n nativeImpact,\n nativeNotify,\n nativeToast,\n} from '../../utils/nativeBridge';\n\n/**\n * Tours list page\n * Displays all tours with filtering and search\n */\nexport function ToursListPage() {\n const { tr } = useToursI18n();\n const navigate = useNavigate();\n const { basePath = '/' } = useToursContext();\n const {\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 canDeleteTour = hasPermission(TOUR_PERMISSIONS.TOUR_DELETE);\n const canPublishTour = hasPermission(TOUR_PERMISSIONS.TOUR_PUBLISH);\n const canArchiveTour = hasPermission(TOUR_PERMISSIONS.TOUR_ARCHIVE);\n const canDuplicateTour = hasPermission(TOUR_PERMISSIONS.TOUR_DUPLICATE);\n\n // Fetch tours (includes both workspace-specific and global tours)\n const { tours, loading, fetchTours } = useToursList();\n\n const { publishTour, unpublishTour, archiveTour, duplicateTour } = useTourLifecycle();\n const [deleteTourMutation] = useDeleteTourMutation();\n\n const [searchQuery, setSearchQuery] = useState('');\n const [statusFilter, setStatusFilter] = useState<TourStatus | 'all'>('all');\n const [openMenuId, setOpenMenuId] = useState<string | null>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n\n // Fetch tours when filter changes. The list page is also the user-facing\n // tour browser, so backend permissions remain authoritative for actions while\n // normal users can still see published tours returned by the API.\n useEffect(() => {\n if (permissionsLoading) return;\n fetchTours({ ...tourFilter });\n }, [fetchTours, tourFilter, 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 setOpenMenuId(null);\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 setOpenMenuId(null);\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 setOpenMenuId(null);\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 setOpenMenuId(null);\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 setOpenMenuId(null);\n nativeImpact('medium');\n const confirmMsg = tr('toursList.confirmDelete');\n const nativeResult = await nativeConfirm({\n title: tr('toursList.actionDelete'),\n message: confirmMsg,\n okButtonTitle: tr('toursList.actionDelete'),\n });\n const confirmed = nativeResult === null ? window.confirm(confirmMsg) : nativeResult;\n if (!confirmed) return;\n try {\n await deleteTourMutation({ variables: { id } });\n 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 // Close dropdown when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(event.target as Node)) {\n setOpenMenuId(null);\n }\n };\n if (openMenuId) {\n document.addEventListener('mousedown', handleClickOutside);\n }\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, [openMenuId]);\n\n return (\n <div className=\"space-y-4 sm:space-y-6 p-3 sm:p-6\">\n {/* Header */}\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3\">\n <div className=\"flex-1 min-w-0\">\n <h1 className=\"text-xl sm:text-2xl font-bold text-foreground\">{tr('toursList.title')}</h1>\n <p className=\"text-sm sm:text-base text-muted-foreground\">{tr('toursList.subtitle')}</p>\n </div>\n <PermissionGate permission={TOUR_PERMISSIONS.TOUR_CREATE}>\n <button\n onClick={handleCreateTour}\n className=\"w-full sm:w-auto px-4 py-2 min-h-[44px] bg-primary text-primary-foreground rounded-md hover:bg-primary/90 active:bg-primary/80 flex items-center justify-center gap-2\"\n >\n <Plus size={20} />\n {tr('toursList.createTour')}\n </button>\n </PermissionGate>\n </div>\n\n {/* Filters and Search */}\n <div className=\"flex flex-col sm:flex-row gap-3 sm:gap-4\">\n {/* Search */}\n <div className=\"flex-1 relative\">\n <Search\n className=\"absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground\"\n size={20}\n />\n <input\n type=\"text\"\n placeholder={tr('toursList.searchPlaceholder')}\n value={searchQuery}\n onChange={(e) => handleSearch(e.target.value)}\n className=\"w-full pl-[3.25rem] pr-4 py-2 min-h-[44px] border border-border rounded-md bg-background text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring\"\n />\n </div>\n\n {/* Status Filter */}\n <div className=\"flex gap-2\">\n <select\n value={statusFilter}\n onChange={(e) => handleStatusFilter(e.target.value as TourStatus | 'all')}\n className=\"px-4 py-2 min-h-[44px] border border-border rounded-md bg-background text-foreground\"\n >\n <option value=\"all\">{tr('toursList.statusAll')}</option>\n <option value=\"DRAFT\">{tr('toursList.statusDraft')}</option>\n <option value=\"PUBLISHED\">{tr('toursList.statusPublished')}</option>\n <option value=\"ARCHIVED\">{tr('toursList.statusArchived')}</option>\n <option value=\"SCHEDULED\">{tr('toursList.statusScheduled')}</option>\n </select>\n\n {/* View Mode Toggle */}\n <div className=\"flex border border-border rounded-md overflow-hidden\">\n <button\n onClick={() => setViewMode('grid')}\n className={`px-3 py-2 min-h-[44px] ${\n viewMode === 'grid'\n ? 'bg-primary text-primary-foreground'\n : 'bg-background text-foreground hover:bg-accent'\n }`}\n aria-label={tr('toursList.gridView')}\n title={tr('toursList.gridView')}\n >\n <Grid size={20} />\n </button>\n <button\n onClick={() => setViewMode('list')}\n className={`px-3 py-2 min-h-[44px] ${\n viewMode === 'list'\n ? 'bg-primary text-primary-foreground'\n : 'bg-background text-foreground hover:bg-accent'\n }`}\n aria-label={tr('toursList.listView')}\n title={tr('toursList.listView')}\n >\n <ListIcon size={20} />\n </button>\n </div>\n </div>\n </div>\n\n {/* Tours List */}\n {loading ? (\n <div className=\"text-center py-12\">\n <p className=\"text-sm sm:text-base text-muted-foreground\">{tr('toursList.loading')}</p>\n </div>\n ) : tours.length > 0 ? (\n <div\n className={\n viewMode === 'grid'\n ? 'grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 sm:gap-4'\n : 'space-y-3'\n }\n >\n {tours.map((tour: Tour) => {\n const status = tour.status as TourStatus;\n const canShowPublishAction = status === 'DRAFT' && canPublishTour;\n const canShowUnpublishAction = status === 'PUBLISHED' && canPublishTour;\n const canShowArchiveAction = status !== 'ARCHIVED' && canArchiveTour;\n const hasMoreActions =\n canShowPublishAction ||\n canShowUnpublishAction ||\n canDuplicateTour ||\n canShowArchiveAction ||\n canDeleteTour;\n\n return (\n <div\n key={tour.id}\n className=\"border border-border rounded-md p-4 bg-card hover:shadow-md transition-shadow\"\n >\n <div className=\"flex items-start justify-between mb-2\">\n <h3\n className={`font-semibold text-foreground ${\n canUpdateTour ? 'cursor-pointer hover:text-primary' : ''\n }`}\n onClick={() => {\n if (canUpdateTour) navigate(`${basePath}/${tour.id}/edit`);\n }}\n >\n {tour.name}\n </h3>\n <span\n className={`px-2 py-1 text-xs rounded-full ${\n tour.status === 'PUBLISHED'\n ? 'bg-success/10 text-success'\n : tour.status === 'DRAFT'\n ? 'bg-muted text-muted-foreground'\n : 'bg-warning/10 text-warning'\n }`}\n >\n {getStatusLabel(status)}\n </span>\n </div>\n {tour.description && (\n <p className=\"text-sm text-muted-foreground mb-3\">{tour.description}</p>\n )}\n <div className=\"flex items-center justify-between text-xs text-muted-foreground mb-3\">\n <span>\n {tour.steps?.length || 0} {tr('toursList.steps')}\n </span>\n <span>\n {tour.viewCount} {tr('toursList.views')}\n </span>\n </div>\n {/* Quick Actions */}\n <div className=\"flex flex-wrap items-center gap-2 pt-3 border-t border-border\">\n {canUpdateTourSteps && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n navigate(`${basePath}/${tour.id}/steps`);\n }}\n className=\"flex-1 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 <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 rounded hover:bg-accent flex items-center justify-center gap-1.5\"\n title={tr('toursList.previewTitle')}\n >\n <Eye size={14} />\n {tr('toursList.previewButton')}\n </button>\n {canUpdateTour && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n navigate(`${basePath}/${tour.id}/edit`);\n }}\n className=\"px-2 py-2 min-h-[44px] min-w-[44px] text-xs border border-border rounded hover:bg-accent\"\n title={tr('toursList.settingsTitle')}\n aria-label={tr('toursList.settingsTitle')}\n >\n <Settings size={14} />\n </button>\n )}\n {/* More Actions Dropdown */}\n {hasMoreActions && (\n <div className=\"relative\" ref={openMenuId === tour.id ? menuRef : undefined}>\n <button\n onClick={(e) => {\n e.stopPropagation();\n setOpenMenuId(openMenuId === tour.id ? null : tour.id);\n }}\n className=\"px-2 py-2 min-h-[44px] min-w-[44px] text-xs border border-border rounded hover:bg-accent\"\n title={tr('toursList.moreActionsTitle')}\n aria-label={tr('toursList.moreActionsTitle')}\n >\n <MoreVertical size={14} />\n </button>\n {openMenuId === tour.id && (\n <div className=\"absolute right-0 top-full mt-1 w-40 bg-card border border-border rounded-md shadow-lg z-10\">\n {canShowPublishAction && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n handlePublish(tour.id);\n }}\n className=\"w-full text-left px-3 py-2 min-h-[44px] text-xs hover:bg-accent\"\n >\n {tr('toursList.actionPublish')}\n </button>\n )}\n {canShowUnpublishAction && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n handleUnpublish(tour.id);\n }}\n className=\"w-full text-left px-3 py-2 min-h-[44px] text-xs hover:bg-accent\"\n >\n {tr('toursList.actionUnpublish')}\n </button>\n )}\n {canDuplicateTour && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n handleDuplicate(tour.id);\n }}\n className=\"w-full text-left px-3 py-2 min-h-[44px] text-xs hover:bg-accent\"\n >\n {tr('toursList.actionDuplicate')}\n </button>\n )}\n {canShowArchiveAction && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n handleArchive(tour.id);\n }}\n className=\"w-full text-left px-3 py-2 min-h-[44px] text-xs hover:bg-accent\"\n >\n {tr('toursList.actionArchive')}\n </button>\n )}\n {canDeleteTour && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n handleDelete(tour.id);\n }}\n className=\"w-full text-left px-3 py-2 min-h-[44px] text-xs text-destructive hover:bg-destructive/10\"\n >\n {tr('toursList.actionDelete')}\n </button>\n )}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n })}\n </div>\n ) : (\n <div className=\"text-center py-12 border border-dashed border-border rounded-md\">\n <p className=\"text-sm sm:text-base text-muted-foreground mb-2\">\n {tr('toursList.emptyTitle')}\n </p>\n <p className=\"text-xs sm:text-sm text-muted-foreground\">\n {tr('toursList.emptySubtitle')}\n </p>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ToursListPage.js","names":[],"sources":["../../../src/tours/pages/ToursListPage.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport {\n Plus,\n Search,\n Grid,\n List as ListIcon,\n ListOrdered,\n Eye,\n Settings,\n MoreVertical,\n} from 'lucide-react';\nimport { PermissionGate } from '@burdenoff/fe-libs/shared/components';\nimport { useToursList } from '../hooks/useToursList';\nimport { useTourLifecycle } from '../hooks/useTourLifecycle';\nimport { useToursPermissionAccess } from '../hooks/useToursPermissionAccess';\nimport { useToursStore } from '../store/toursStore';\nimport { useToursContext } from '../providers/ToursProvider';\nimport { useDeleteTourMutation } from '../../generated/global-operations';\nimport { TOUR_PERMISSIONS } from '../../constants/permissions';\nimport type { TourStatus } from '../types';\nimport type { Tour } from '../../generated/global-types';\nimport { useToursI18n } from '../i18n';\nimport {\n isNative,\n nativeConfirm,\n nativeImpact,\n nativeNotify,\n nativeToast,\n} from '../../utils/nativeBridge';\n\n/**\n * Tours list page\n * Displays all tours with filtering and search\n */\nexport function ToursListPage() {\n const { tr } = useToursI18n();\n const navigate = useNavigate();\n const { basePath = '/' } = useToursContext();\n const {\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 const [openMenuId, setOpenMenuId] = useState<string | null>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n\n // Fetch tours when filter changes. The list page is also the user-facing\n // tour browser, so backend permissions remain authoritative for actions while\n // normal users can still see published tours returned by the API.\n useEffect(() => {\n if (permissionsLoading) return;\n fetchTours({ ...tourFilter });\n }, [fetchTours, tourFilter, 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 setOpenMenuId(null);\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 setOpenMenuId(null);\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 setOpenMenuId(null);\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 setOpenMenuId(null);\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 setOpenMenuId(null);\n nativeImpact('medium');\n const confirmMsg = tr('toursList.confirmDelete');\n const nativeResult = await nativeConfirm({\n title: tr('toursList.actionDelete'),\n message: confirmMsg,\n okButtonTitle: tr('toursList.actionDelete'),\n });\n const confirmed = nativeResult === null ? window.confirm(confirmMsg) : nativeResult;\n if (!confirmed) return;\n try {\n await deleteTourMutation({ variables: { id } });\n 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 // Close dropdown when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(event.target as Node)) {\n setOpenMenuId(null);\n }\n };\n if (openMenuId) {\n document.addEventListener('mousedown', handleClickOutside);\n }\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, [openMenuId]);\n\n return (\n <div className=\"space-y-4 sm:space-y-6 p-3 sm:p-6\">\n {/* Header */}\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3\">\n <div className=\"flex-1 min-w-0\">\n <h1 className=\"text-xl sm:text-2xl font-bold text-foreground\">{tr('toursList.title')}</h1>\n <p className=\"text-sm sm:text-base text-muted-foreground\">{tr('toursList.subtitle')}</p>\n </div>\n <PermissionGate permission={TOUR_PERMISSIONS.TOUR_CREATE}>\n <button\n onClick={handleCreateTour}\n className=\"w-full sm:w-auto px-4 py-2 min-h-[44px] bg-primary text-primary-foreground rounded-md hover:bg-primary/90 active:bg-primary/80 flex items-center justify-center gap-2\"\n >\n <Plus size={20} />\n {tr('toursList.createTour')}\n </button>\n </PermissionGate>\n </div>\n\n {/* Filters and Search */}\n <div className=\"flex flex-col sm:flex-row gap-3 sm:gap-4\">\n {/* Search */}\n <div className=\"flex-1 relative\">\n <Search\n className=\"absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground\"\n size={20}\n />\n <input\n type=\"text\"\n placeholder={tr('toursList.searchPlaceholder')}\n value={searchQuery}\n onChange={(e) => handleSearch(e.target.value)}\n className=\"w-full pl-[3.25rem] pr-4 py-2 min-h-[44px] border border-border rounded-md bg-background text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring\"\n />\n </div>\n\n {/* Status Filter */}\n <div className=\"flex gap-2\">\n <select\n value={statusFilter}\n onChange={(e) => handleStatusFilter(e.target.value as TourStatus | 'all')}\n className=\"px-4 py-2 min-h-[44px] border border-border rounded-md bg-background text-foreground\"\n >\n <option value=\"all\">{tr('toursList.statusAll')}</option>\n <option value=\"DRAFT\">{tr('toursList.statusDraft')}</option>\n <option value=\"PUBLISHED\">{tr('toursList.statusPublished')}</option>\n <option value=\"ARCHIVED\">{tr('toursList.statusArchived')}</option>\n <option value=\"SCHEDULED\">{tr('toursList.statusScheduled')}</option>\n </select>\n\n {/* View Mode Toggle */}\n <div className=\"flex border border-border rounded-md overflow-hidden\">\n <button\n onClick={() => setViewMode('grid')}\n className={`px-3 py-2 min-h-[44px] ${\n viewMode === 'grid'\n ? 'bg-primary text-primary-foreground'\n : 'bg-background text-foreground hover:bg-accent'\n }`}\n aria-label={tr('toursList.gridView')}\n title={tr('toursList.gridView')}\n >\n <Grid size={20} />\n </button>\n <button\n onClick={() => setViewMode('list')}\n className={`px-3 py-2 min-h-[44px] ${\n viewMode === 'list'\n ? 'bg-primary text-primary-foreground'\n : 'bg-background text-foreground hover:bg-accent'\n }`}\n aria-label={tr('toursList.listView')}\n title={tr('toursList.listView')}\n >\n <ListIcon size={20} />\n </button>\n </div>\n </div>\n </div>\n\n {/* Tours List */}\n {loading ? (\n <div className=\"text-center py-12\">\n <p className=\"text-sm sm:text-base text-muted-foreground\">{tr('toursList.loading')}</p>\n </div>\n ) : tours.length > 0 ? (\n <div\n className={\n viewMode === 'grid'\n ? 'grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 sm:gap-4'\n : 'space-y-3'\n }\n >\n {tours.map((tour: Tour) => {\n const status = tour.status as TourStatus;\n const canShowPublishAction = status === 'DRAFT' && canPublishTour;\n const canShowUnpublishAction = status === 'PUBLISHED' && canPublishTour;\n const canShowArchiveAction = status !== 'ARCHIVED' && canArchiveTour;\n const hasMoreActions =\n canShowPublishAction ||\n canShowUnpublishAction ||\n canDuplicateTour ||\n canShowArchiveAction ||\n canDeleteTour;\n\n return (\n <div\n key={tour.id}\n className=\"border border-border rounded-md p-4 bg-card hover:shadow-md transition-shadow\"\n >\n <div className=\"flex items-start justify-between mb-2\">\n <h3\n className={`font-semibold text-foreground ${\n canUpdateTour ? 'cursor-pointer hover:text-primary' : ''\n }`}\n onClick={() => {\n if (canUpdateTour) navigate(`${basePath}/${tour.id}/edit`);\n }}\n >\n {tour.name}\n </h3>\n <span\n className={`px-2 py-1 text-xs rounded-full ${\n tour.status === 'PUBLISHED'\n ? 'bg-success/10 text-success'\n : tour.status === 'DRAFT'\n ? 'bg-muted text-muted-foreground'\n : 'bg-warning/10 text-warning'\n }`}\n >\n {getStatusLabel(status)}\n </span>\n </div>\n {tour.description && (\n <p className=\"text-sm text-muted-foreground mb-3\">{tour.description}</p>\n )}\n <div className=\"flex items-center justify-between text-xs text-muted-foreground mb-3\">\n <span>\n {tour.steps?.length || 0} {tr('toursList.steps')}\n </span>\n <span>\n {tour.viewCount} {tr('toursList.views')}\n </span>\n </div>\n {/* Quick Actions */}\n <div className=\"flex flex-wrap items-center gap-2 pt-3 border-t border-border\">\n {canUpdateTourSteps && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n navigate(`${basePath}/${tour.id}/steps`);\n }}\n className=\"flex-1 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 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 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 onClick={(e) => {\n e.stopPropagation();\n navigate(`${basePath}/${tour.id}/edit`);\n }}\n className=\"px-2 py-2 min-h-[44px] min-w-[44px] text-xs border border-border rounded hover:bg-accent\"\n title={tr('toursList.settingsTitle')}\n aria-label={tr('toursList.settingsTitle')}\n >\n <Settings size={14} />\n </button>\n )}\n {/* More Actions Dropdown */}\n {hasMoreActions && (\n <div className=\"relative\" ref={openMenuId === tour.id ? menuRef : undefined}>\n <button\n onClick={(e) => {\n e.stopPropagation();\n setOpenMenuId(openMenuId === tour.id ? null : tour.id);\n }}\n className=\"px-2 py-2 min-h-[44px] min-w-[44px] text-xs border border-border rounded hover:bg-accent\"\n title={tr('toursList.moreActionsTitle')}\n aria-label={tr('toursList.moreActionsTitle')}\n >\n <MoreVertical size={14} />\n </button>\n {openMenuId === tour.id && (\n <div className=\"absolute right-0 top-full mt-1 w-40 bg-card border border-border rounded-md shadow-lg z-10\">\n {canShowPublishAction && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n handlePublish(tour.id);\n }}\n className=\"w-full text-left px-3 py-2 min-h-[44px] text-xs hover:bg-accent\"\n >\n {tr('toursList.actionPublish')}\n </button>\n )}\n {canShowUnpublishAction && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n handleUnpublish(tour.id);\n }}\n className=\"w-full text-left px-3 py-2 min-h-[44px] text-xs hover:bg-accent\"\n >\n {tr('toursList.actionUnpublish')}\n </button>\n )}\n {canDuplicateTour && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n handleDuplicate(tour.id);\n }}\n className=\"w-full text-left px-3 py-2 min-h-[44px] text-xs hover:bg-accent\"\n >\n {tr('toursList.actionDuplicate')}\n </button>\n )}\n {canShowArchiveAction && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n handleArchive(tour.id);\n }}\n className=\"w-full text-left px-3 py-2 min-h-[44px] text-xs hover:bg-accent\"\n >\n {tr('toursList.actionArchive')}\n </button>\n )}\n {canDeleteTour && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n handleDelete(tour.id);\n }}\n className=\"w-full text-left px-3 py-2 min-h-[44px] text-xs text-destructive hover:bg-destructive/10\"\n >\n {tr('toursList.actionDelete')}\n </button>\n )}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n })}\n </div>\n ) : (\n <div className=\"text-center py-12 border border-dashed border-border rounded-md\">\n <p className=\"text-sm sm:text-base text-muted-foreground mb-2\">\n {tr('toursList.emptyTitle')}\n </p>\n <p className=\"text-xs sm:text-sm text-muted-foreground\">\n {tr('toursList.emptySubtitle')}\n </p>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-tours",
3
- "version": "2026.525.3",
3
+ "version": "2026.527.2",
4
4
  "description": "Burdenoff Tours Microfrontend - Complete product tours and onboarding interface",
5
5
  "type": "module",
6
6
  "files": [