@saasicat/ui-vue 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +47 -0
  3. package/dist/index.cjs +3776 -0
  4. package/dist/index.d.cts +2395 -0
  5. package/dist/index.d.ts +2395 -0
  6. package/dist/index.js +3659 -0
  7. package/dist/testing-e2e/admin-pages-suite.cjs +134 -0
  8. package/dist/testing-e2e/admin-pages-suite.d.cts +37 -0
  9. package/dist/testing-e2e/admin-pages-suite.d.ts +37 -0
  10. package/dist/testing-e2e/admin-pages-suite.js +109 -0
  11. package/package.json +87 -0
  12. package/src/action-registry.ts +110 -0
  13. package/src/batch-column-fetcher.ts +152 -0
  14. package/src/boot-loader.ts +60 -0
  15. package/src/components/BundleVersionPublishDialog.vue +359 -0
  16. package/src/components/BusinessTypeVersionEditorDialog.vue +417 -0
  17. package/src/components/BusinessTypeVersionPublishDialog.vue +258 -0
  18. package/src/components/FeatureGate.vue +56 -0
  19. package/src/components/KpiCard.vue +53 -0
  20. package/src/components/KvBlock.vue +36 -0
  21. package/src/components/MarketingPromotionsTab.vue +861 -0
  22. package/src/components/MfaPromptDialog.vue +104 -0
  23. package/src/components/TenantActionConfirmDialog.vue +252 -0
  24. package/src/components/VersionDiffPreview.vue +150 -0
  25. package/src/components/bundle-editor/BundleCreatePanel.vue +681 -0
  26. package/src/components/bundle-editor/BundleFeaturesEditor.vue +215 -0
  27. package/src/components/bundle-editor/BundlePlanCompatPicker.vue +316 -0
  28. package/src/components/bundle-editor/BundleQuotasEditor.vue +219 -0
  29. package/src/components/bundle-editor/BundleStatusBanner.vue +189 -0
  30. package/src/components/bundle-editor/BundleVersionInlineEditor.vue +659 -0
  31. package/src/components/bundle-editor/BundleVersionStrip.vue +207 -0
  32. package/src/components/bundle-editor/bundle-version-status.ts +164 -0
  33. package/src/components/bundle-editor/catalog-i18n.ts +85 -0
  34. package/src/components/dialogs/PilotCreateDialog.vue +780 -0
  35. package/src/components/dialogs/PilotEditDialog.vue +548 -0
  36. package/src/components/dialogs/PromoCodeCreateDialog.vue +737 -0
  37. package/src/components/dialogs/PromoCodeEditDialog.vue +859 -0
  38. package/src/components/dialogs/types.ts +126 -0
  39. package/src/components/plan/PlanCycleToggle.vue +99 -0
  40. package/src/components/plan/PlanGrid.vue +211 -0
  41. package/src/components/plan/PriceSummary.vue +293 -0
  42. package/src/components/plan/PromoCodeInput.vue +192 -0
  43. package/src/components/plan/PublicBundleGrid.vue +287 -0
  44. package/src/components/plan-cockpit/PlanCockpit.vue +993 -0
  45. package/src/components/plan-cockpit/PlanCockpitAuditLog.vue +65 -0
  46. package/src/components/plan-cockpit/PlanCockpitDiffPanel.vue +91 -0
  47. package/src/components/plan-cockpit/PlanCockpitHeader.vue +98 -0
  48. package/src/components/plan-cockpit/PlanCockpitImpactPanel.vue +99 -0
  49. package/src/components/plan-cockpit/PlanCockpitKpis.vue +57 -0
  50. package/src/components/plan-cockpit/PlanCockpitVersions.vue +226 -0
  51. package/src/components/plan-cockpit/types.ts +72 -0
  52. package/src/components/plan-create-dialog/PlanCreateDialog.vue +508 -0
  53. package/src/components/plan-detail/PlanAuditLog.vue +59 -0
  54. package/src/components/plan-detail/PlanDetail.vue +1195 -0
  55. package/src/components/plan-detail/PlanDetailHeader.vue +185 -0
  56. package/src/components/plan-detail/PlanDetailKpis.vue +57 -0
  57. package/src/components/plan-detail/PlanTerminateDialog.vue +76 -0
  58. package/src/components/plan-detail/PlanVersionDiffPanel.vue +149 -0
  59. package/src/components/plan-detail/PlanVersionsPanel.vue +255 -0
  60. package/src/components/plan-detail/types.ts +59 -0
  61. package/src/components/plan-list/PlanList.vue +1067 -0
  62. package/src/components/plan-matrix/PlanMatrix.vue +1113 -0
  63. package/src/components/plan-review/PlanReview.vue +742 -0
  64. package/src/components/plan-version-editor/PlanCatalogPreview.vue +184 -0
  65. package/src/components/plan-version-editor/PlanComponentPool.vue +272 -0
  66. package/src/components/plan-version-editor/PlanVersionBasket.vue +281 -0
  67. package/src/components/plan-version-editor/PlanVersionDiffDialog.vue +84 -0
  68. package/src/components/plan-version-editor/PlanVersionEditor.vue +1728 -0
  69. package/src/components/plan-version-editor/PlanVersionEditorHeader.vue +94 -0
  70. package/src/components/plan-version-editor/types.ts +96 -0
  71. package/src/components/wizard-stepper/WizardStepper.vue +107 -0
  72. package/src/create-admin-routes.ts +68 -0
  73. package/src/create-super-admin-app.ts +345 -0
  74. package/src/entitlement-provider.ts +36 -0
  75. package/src/feature-router-guard.ts +77 -0
  76. package/src/http-json.ts +62 -0
  77. package/src/index.ts +98 -0
  78. package/src/manifest-loader.ts +139 -0
  79. package/src/manifest-store-factory.ts +114 -0
  80. package/src/nav-builder.ts +274 -0
  81. package/src/pages-standard/AdminLayout.vue +411 -0
  82. package/src/pages-standard/AdminManifestErrorPage.vue +79 -0
  83. package/src/pages-standard/AuditPage.vue +223 -0
  84. package/src/pages-standard/BundlesPage.vue +910 -0
  85. package/src/pages-standard/BusinessTypesPage.vue +662 -0
  86. package/src/pages-standard/DashboardPage.vue +595 -0
  87. package/src/pages-standard/DiscoveryPage.vue +663 -0
  88. package/src/pages-standard/EmailHistoryPage.vue +576 -0
  89. package/src/pages-standard/MarketingCatalogPage.vue +1771 -0
  90. package/src/pages-standard/PilotsPage.vue +577 -0
  91. package/src/pages-standard/PlanVersionsPage.vue +216 -0
  92. package/src/pages-standard/PlansPage.vue +1222 -0
  93. package/src/pages-standard/PlatformEmailPage.vue +434 -0
  94. package/src/pages-standard/PromoCodeDetailPage.vue +331 -0
  95. package/src/pages-standard/PromoCodesPage.vue +589 -0
  96. package/src/pages-standard/SubscriptionsPage.vue +159 -0
  97. package/src/pages-standard/SuperAdminLoginPage.vue +299 -0
  98. package/src/pages-standard/SuperAdminSetupWizard.vue +405 -0
  99. package/src/pages-standard/TenantDetailPage.vue +432 -0
  100. package/src/pages-standard/TenantsPage.vue +732 -0
  101. package/src/pages-standard/UsersPage.vue +504 -0
  102. package/src/pages-standard/bundles-page/BundleAccordionList.vue +116 -0
  103. package/src/pages-standard/bundles-page/BundleDetailPanel.vue +193 -0
  104. package/src/pages-standard/bundles-page/BundlesFilterBar.vue +48 -0
  105. package/src/pages-standard/bundles-page/BundlesHeader.vue +67 -0
  106. package/src/pages-standard/bundles-page/BundlesKpis.vue +39 -0
  107. package/src/pages-standard/bundles-page/types.ts +15 -0
  108. package/src/pages-standard/discovery-page/CatalogEntryTransPanel.vue +246 -0
  109. package/src/pages-standard/discovery-page/DiscoveryCapList.vue +171 -0
  110. package/src/pages-standard/discovery-page/DiscoveryFeatureCard.vue +410 -0
  111. package/src/pages-standard/discovery-page/DiscoveryHeader.vue +31 -0
  112. package/src/pages-standard/discovery-page/DiscoveryKpis.vue +47 -0
  113. package/src/pages-standard/discovery-page/DiscoveryMetaBanner.vue +26 -0
  114. package/src/pages-standard/discovery-page/DiscoveryQuotaCard.vue +247 -0
  115. package/src/pages-standard/discovery-page/DiscoveryStatusControl.vue +73 -0
  116. package/src/pages-standard/discovery-page/discovery-ui.ts +166 -0
  117. package/src/pages-standard/email-history.types.ts +48 -0
  118. package/src/pages-standard/marketing-catalog/MarketingCatalogAdmin.vue +448 -0
  119. package/src/pages-standard/marketing-catalog/MarketingCatalogHeader.vue +93 -0
  120. package/src/pages-standard/marketing-catalog/MarketingCatalogPreview.vue +138 -0
  121. package/src/pages-standard/marketing-catalog/MarketingCatalogToolbar.vue +58 -0
  122. package/src/pages-standard/marketing-catalog/types.ts +43 -0
  123. package/src/pages-standard/plan-versions/PlanDiffCard.vue +132 -0
  124. package/src/pages-standard/plan-versions/PlanVersionHeader.vue +293 -0
  125. package/src/pages-standard/plan-versions/PlanVersionStatusBadge.vue +48 -0
  126. package/src/pages-standard/plan-versions/PlanVersionsAudit.vue +307 -0
  127. package/src/pages-standard/plan-versions/PlanVersionsDiff.vue +269 -0
  128. package/src/pages-standard/plan-versions/PlanVersionsKpi.vue +65 -0
  129. package/src/pages-standard/plan-versions/PlanVersionsList.vue +292 -0
  130. package/src/pages-standard/plan-versions/PlanVersionsMatrix.vue +261 -0
  131. package/src/pages-standard/plan-versions/PlanVersionsTimeline.vue +300 -0
  132. package/src/pages-standard/plan-versions/VersionDiffPreview.vue +167 -0
  133. package/src/pages-standard/plan-versions/format.ts +53 -0
  134. package/src/pages-standard/plan-versions/types.ts +33 -0
  135. package/src/pages-standard/plans-page/PlanArchiveDialog.vue +50 -0
  136. package/src/pages-standard/plans-page/PlanBundleOverview.vue +147 -0
  137. package/src/pages-standard/plans-page/PlanDiscardDraftDialog.vue +46 -0
  138. package/src/pages-standard/plans-page/PlanPublishDialog.vue +106 -0
  139. package/src/pages-standard/plans-page/PlansPageToast.vue +69 -0
  140. package/src/pages-standard/plans-page/types.ts +18 -0
  141. package/src/pages-standard/platform-email.types.ts +41 -0
  142. package/src/pages-standard/sa-theme.css +223 -0
  143. package/src/pages-standard/tenants/StatusPill.vue +62 -0
  144. package/src/pages-standard/tenants/format.ts +38 -0
  145. package/src/pages-tenant/LimitsRow.vue +67 -0
  146. package/src/pages-tenant/MySubscriptionBundlesPage.vue +604 -0
  147. package/src/pages-tenant/OnboardingConfigurator.vue +417 -0
  148. package/src/pages-tenant/PackageSnapshotPanel.vue +241 -0
  149. package/src/pages-tenant/PendingVersionBanner.vue +126 -0
  150. package/src/pages-tenant/PlanChangeWizard.vue +630 -0
  151. package/src/pages-tenant/TenantPlanSection.vue +729 -0
  152. package/src/pages-tenant/UsageBar.vue +107 -0
  153. package/src/pages-tenant/default-i18n.ts +280 -0
  154. package/src/pages-tenant/tenant-plan-section/BundlePreviewDialog.vue +304 -0
  155. package/src/pages-tenant/tenant-plan-section/TenantBundleStore.vue +323 -0
  156. package/src/pages-tenant/tenant-plan-section/TenantFeatureMatrix.vue +122 -0
  157. package/src/pages-tenant/tenant-plan-section/TenantPlanCardHeader.vue +67 -0
  158. package/src/pages-tenant/tenant-plan-section/TenantUsageGrid.vue +31 -0
  159. package/src/plan-versions-catalog.ts +368 -0
  160. package/src/platform-loaders.ts +68 -0
  161. package/src/project-page-host.ts +108 -0
  162. package/src/testing-e2e/admin-pages-suite.ts +187 -0
  163. package/src/types.ts +58 -0
  164. package/src/use-actions.ts +25 -0
  165. package/src/use-api-list.ts +151 -0
  166. package/src/use-audit-entries.ts +48 -0
  167. package/src/use-batch-columns.ts +59 -0
  168. package/src/use-bulk-publish.ts +150 -0
  169. package/src/use-bundle-versions-map.ts +112 -0
  170. package/src/use-bundles.ts +297 -0
  171. package/src/use-business-types.ts +269 -0
  172. package/src/use-catalog-entries.ts +243 -0
  173. package/src/use-discovery.ts +158 -0
  174. package/src/use-entitlement.ts +87 -0
  175. package/src/use-live-plan-versions.ts +126 -0
  176. package/src/use-manifest.ts +57 -0
  177. package/src/use-marketing-projections.ts +160 -0
  178. package/src/use-nav.ts +33 -0
  179. package/src/use-plan-editor.ts +162 -0
  180. package/src/use-plan-versions.ts +83 -0
  181. package/src/use-plans.ts +375 -0
  182. package/src/use-platform-tenant-actions.ts +286 -0
  183. package/src/use-promotions.ts +126 -0
  184. package/src/use-public-boot.ts +40 -0
  185. package/src/use-subscription-draft.ts +355 -0
  186. package/src/use-super-admin-context.ts +93 -0
  187. package/src/use-tenant-action-flow.ts +238 -0
  188. package/src/use-tenant-billing-catalog.ts +160 -0
  189. package/src/use-tenant-billing.ts +453 -0
  190. package/src/use-tenant-manifest.ts +94 -0
  191. package/src/use-tenant-subscription-bundles.ts +148 -0
  192. package/src/use-tenants.ts +61 -0
  193. package/src/version.ts +10 -0
@@ -0,0 +1,94 @@
1
+ <template>
2
+ <header class="pve-bar">
3
+ <div class="pve-bar-left">
4
+ <div class="pve-titlechip">
5
+ <span class="pve-titlechip-kicker">PLAN</span>
6
+ <span class="pve-chip pve-chip--plan">{{ planKey }}</span>
7
+ </div>
8
+ <h2 class="pve-title">
9
+ {{ editingId ? `Draft v${version} bearbeiten` : `Neue Version v${version}` }}
10
+ </h2>
11
+ <span class="pve-chip pve-chip--draft pve-chip--dot">Draft</span>
12
+ <span class="pve-bar-note">
13
+ Vorgänger wird beim Publish auf
14
+ <code class="pve-mono">{{ predecessorValidUntilHint }}</code> superseded
15
+ </span>
16
+ </div>
17
+ <div class="pve-bar-right">
18
+ <button
19
+ class="pve-btn"
20
+ type="button"
21
+ :disabled="!hasPredecessor"
22
+ :title="hasPredecessor ? undefined : 'Keine Vorgänger-Version (v1)'"
23
+ @click="$emit('showDiff')"
24
+ >
25
+ <span class="pve-ico" aria-hidden="true">
26
+ <svg
27
+ width="14"
28
+ height="14"
29
+ viewBox="0 0 24 24"
30
+ fill="none"
31
+ stroke="currentColor"
32
+ stroke-width="2"
33
+ >
34
+ <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" />
35
+ <circle cx="12" cy="12" r="3" />
36
+ </svg>
37
+ </span>
38
+ <span>Diff vs. Vorgänger</span>
39
+ </button>
40
+ <button class="pve-btn" type="button" @click="$emit('cancel')">
41
+ <span class="pve-ico" style="transform: rotate(180deg)" aria-hidden="true">
42
+ <svg
43
+ width="14"
44
+ height="14"
45
+ viewBox="0 0 24 24"
46
+ fill="none"
47
+ stroke="currentColor"
48
+ stroke-width="2"
49
+ >
50
+ <path d="M5 12h14M13 5l7 7-7 7" />
51
+ </svg>
52
+ </span>
53
+ <span>Zurück</span>
54
+ </button>
55
+ <button
56
+ class="pve-btn pve-btn--primary"
57
+ type="button"
58
+ :disabled="!canSave"
59
+ @click="$emit('save')"
60
+ >
61
+ <span>Weiter · Review</span>
62
+ <span class="pve-ico" aria-hidden="true">
63
+ <svg
64
+ width="14"
65
+ height="14"
66
+ viewBox="0 0 24 24"
67
+ fill="none"
68
+ stroke="currentColor"
69
+ stroke-width="2"
70
+ >
71
+ <path d="M5 12h14M13 5l7 7-7 7" />
72
+ </svg>
73
+ </span>
74
+ </button>
75
+ </div>
76
+ </header>
77
+ </template>
78
+
79
+ <script setup lang="ts">
80
+ defineProps<{
81
+ planKey: string;
82
+ editingId: string | null;
83
+ version: number;
84
+ predecessorValidUntilHint: string;
85
+ hasPredecessor: boolean;
86
+ canSave: boolean;
87
+ }>();
88
+
89
+ defineEmits<{
90
+ (e: 'showDiff'): void;
91
+ (e: 'cancel'): void;
92
+ (e: 'save'): void;
93
+ }>();
94
+ </script>
@@ -0,0 +1,96 @@
1
+ export interface DiscoveryFeature {
2
+ featureKey: string;
3
+ }
4
+
5
+ export interface DiscoveryQuota {
6
+ quotaKey: string;
7
+ label?: string | null;
8
+ unit?: string | null;
9
+ }
10
+
11
+ export interface BundleEntry {
12
+ bundleKey: string;
13
+ label?: string | null;
14
+ features: string[];
15
+ }
16
+
17
+ export interface FeatureMeta {
18
+ label?: string;
19
+ /** Bucket in the library pool (e.g. "Core", "Communication"). */
20
+ group?: string;
21
+ }
22
+
23
+ export interface PredecessorVersion {
24
+ version: number;
25
+ features: string[];
26
+ quotas: Record<string, number>;
27
+ monthlyNet: string;
28
+ yearlyNet: string;
29
+ /** "Valid from" of the predecessor version — the draft must start strictly after it. */
30
+ validFrom: string | null;
31
+ }
32
+
33
+ export interface EditorDiffRow {
34
+ id: string;
35
+ section: string;
36
+ label: string;
37
+ sub?: string;
38
+ from?: string;
39
+ to?: string;
40
+ bg: string;
41
+ border: string;
42
+ color: string;
43
+ sign: string;
44
+ tag: string;
45
+ }
46
+
47
+ export interface DraftForm {
48
+ version: number;
49
+ features: string[];
50
+ quotas: Record<string, number>;
51
+ monthlyNet: string;
52
+ yearlyNet: string;
53
+ changeNote: string;
54
+ marketed: boolean;
55
+ validFrom: string | null;
56
+ validUntil: string | null;
57
+ }
58
+
59
+ /**
60
+ * Save payload = DraftForm plus the persisted bundle selection. `bundles`
61
+ * is derived from the final feature list (all fully-active bundles),
62
+ * so that the persisted list is invariantly consistent with `features` —
63
+ * see `PlanVersionRow.bundles`.
64
+ */
65
+ export interface PlanVersionSavePayload extends DraftForm {
66
+ bundles: string[];
67
+ }
68
+
69
+ export type PoolTab = 'features' | 'quotas' | 'bundles';
70
+ export type PoolKind = 'feature' | 'quota' | 'bundle';
71
+ export type PreviewMode = 'desktop' | 'mobile';
72
+
73
+ export interface PoolTabItem {
74
+ id: PoolTab;
75
+ label: string;
76
+ count: number;
77
+ }
78
+
79
+ export interface FeatureGroup {
80
+ key: string;
81
+ label: string;
82
+ rows: DiscoveryFeature[];
83
+ }
84
+
85
+ export interface ChecklistItem {
86
+ id: string;
87
+ label: string;
88
+ ok: boolean;
89
+ }
90
+
91
+ export interface SelectedQuotaRow {
92
+ quotaKey: string;
93
+ label: string;
94
+ unit: string;
95
+ sub: string;
96
+ }
@@ -0,0 +1,107 @@
1
+ <template>
2
+ <div class="wz-stepper">
3
+ <template v-for="(step, i) in steps" :key="i">
4
+ <div
5
+ class="wz-step"
6
+ :class="{
7
+ 'wz-step--current': i === currentIndex,
8
+ 'wz-step--done': i < currentIndex,
9
+ }"
10
+ >
11
+ <span class="wz-step-num">
12
+ <svg
13
+ v-if="i < currentIndex"
14
+ width="11"
15
+ height="11"
16
+ viewBox="0 0 24 24"
17
+ fill="none"
18
+ stroke="currentColor"
19
+ stroke-width="3.5"
20
+ aria-hidden="true"
21
+ >
22
+ <path d="M5 13l4 4L19 7" />
23
+ </svg>
24
+ <template v-else>{{ i + 1 }}</template>
25
+ </span>
26
+ <span>{{ step.label }}</span>
27
+ </div>
28
+ <span v-if="i < steps.length - 1" class="wz-step-sep" aria-hidden="true" />
29
+ </template>
30
+ <div v-if="hint" class="wz-stepper-hint">{{ hint }}</div>
31
+ </div>
32
+ </template>
33
+
34
+ <script setup lang="ts">
35
+ // WizardStepper — generic step bar for multi-step SuperAdmin
36
+ // wizards (plan creation, bundle creation, …). Purely presentational: the host
37
+ // controls `currentIndex`; the component does not know the flow.
38
+
39
+ export interface WizardStep {
40
+ label: string;
41
+ }
42
+
43
+ defineProps<{
44
+ steps: WizardStep[];
45
+ /** 0-based index of the current step. */
46
+ currentIndex: number;
47
+ /** Optional hint text, right-aligned (e.g. "Jederzeit als Draft speicherbar"). */
48
+ hint?: string;
49
+ }>();
50
+ </script>
51
+
52
+ <style scoped>
53
+ .wz-stepper {
54
+ display: flex;
55
+ align-items: center;
56
+ gap: 6px;
57
+ padding: 14px 26px;
58
+ background: var(--sa-bg-surface);
59
+ border-bottom: 1px solid var(--sa-border);
60
+ }
61
+ .wz-step {
62
+ display: flex;
63
+ align-items: center;
64
+ gap: 8px;
65
+ padding: 6px 12px;
66
+ border-radius: 999px;
67
+ font: 500 12.5px var(--sa-font-body);
68
+ color: var(--sa-muted);
69
+ }
70
+ .wz-step--current {
71
+ background: var(--sa-heading);
72
+ color: #fff;
73
+ }
74
+ .wz-step--done {
75
+ color: var(--sa-positive);
76
+ }
77
+ .wz-step-num {
78
+ width: 20px;
79
+ height: 20px;
80
+ border-radius: 50%;
81
+ background: var(--sa-border);
82
+ color: var(--sa-muted-dark);
83
+ display: grid;
84
+ place-items: center;
85
+ font: 700 11px var(--sa-font-body);
86
+ flex: 0 0 auto;
87
+ }
88
+ .wz-step--current .wz-step-num {
89
+ background: rgba(255, 255, 255, 0.18);
90
+ color: #fff;
91
+ }
92
+ .wz-step--done .wz-step-num {
93
+ background: var(--sa-positive-soft);
94
+ color: var(--sa-positive);
95
+ }
96
+ .wz-step-sep {
97
+ width: 14px;
98
+ height: 1px;
99
+ background: var(--sa-border);
100
+ margin: 0 2px;
101
+ }
102
+ .wz-stepper-hint {
103
+ margin-left: auto;
104
+ font-size: 11px;
105
+ color: var(--sa-muted);
106
+ }
107
+ </style>
@@ -0,0 +1,68 @@
1
+ // createAdminRoutes — shared route shell for SuperAdmin apps.
2
+ //
3
+ // The structure (public `/login`, fail-closed `/admin-error`, `/admin` layout
4
+ // with `→ dashboard` redirect + `ProjectPageHost` catch-all, `/` and
5
+ // 404 redirect) is identical across all consumers. App-specific are only the
6
+ // layout/error/login components and the concrete child pages — those the app
7
+ // passes through. Replaces the ~25 lines of copied route boilerplate per app.
8
+
9
+ import type { RouteRecordRaw } from 'vue-router';
10
+
11
+ import { createProjectPageHostRoute } from './project-page-host.js';
12
+
13
+ /** Eager or lazy component loader (`() => import(...)`). */
14
+ type RouteComponent = NonNullable<RouteRecordRaw['component']>;
15
+
16
+ export interface CreateAdminRoutesOptions {
17
+ /**
18
+ * Loader for the shared login page. The app passes it through as a
19
+ * package-path import (resolved by the app bundler):
20
+ * `() => import('@saasicat/ui-vue/pages-standard/SuperAdminLoginPage.vue')`.
21
+ */
22
+ loginPage: RouteComponent;
23
+ /** Layout component for `/admin` (e.g. `() => import('@/layouts/AdminLayout.vue')`). */
24
+ adminLayout: RouteComponent;
25
+ /** Fail-closed error page for `manifestGuard.errorRoute` (`/admin-error`, public). */
26
+ adminErrorPage: RouteComponent;
27
+ /**
28
+ * App-specific pages under `/admin` (without the `→ dashboard` redirect and
29
+ * the `ProjectPageHost` catch-all — those the factory adds). Exactly the
30
+ * `children` entries that are duplicated per app today.
31
+ */
32
+ children: RouteRecordRaw[];
33
+ /** Default target of the `/admin` index redirect. Default `/admin/dashboard`. */
34
+ dashboardPath?: string;
35
+ }
36
+
37
+ export function createAdminRoutes(options: CreateAdminRoutesOptions): RouteRecordRaw[] {
38
+ return [
39
+ {
40
+ path: '/login',
41
+ name: 'login',
42
+ component: options.loginPage,
43
+ meta: { public: true },
44
+ },
45
+ {
46
+ // `meta.public: true` MUST be set, otherwise the route runs through
47
+ // the manifest guard again → redirect loop.
48
+ path: '/admin-error',
49
+ name: 'admin-error',
50
+ component: options.adminErrorPage,
51
+ meta: { public: true },
52
+ },
53
+ {
54
+ path: '/admin',
55
+ component: options.adminLayout,
56
+ children: [
57
+ { path: '', redirect: options.dashboardPath ?? '/admin/dashboard' },
58
+ ...options.children,
59
+ // Catch-all for manifest ProjectPages — Vue Router 4 matches
60
+ // more specific children first; the host only steps in when
61
+ // no static page matches. MUST come last.
62
+ createProjectPageHostRoute(),
63
+ ],
64
+ },
65
+ { path: '/', redirect: '/admin' },
66
+ { path: '/:pathMatch(.*)*', redirect: '/admin' },
67
+ ];
68
+ }