@saasicat/ui-vue 0.4.0 → 0.6.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 (214) hide show
  1. package/README.md +64 -4
  2. package/dist/chunk-A3W2N26K.js +714 -0
  3. package/dist/chunk-QZOSDCNP.js +98 -0
  4. package/dist/chunk-X5SQ5HMB.js +3231 -0
  5. package/dist/client/index.cjs +3988 -0
  6. package/dist/client/index.d.cts +321 -0
  7. package/dist/client/index.d.ts +321 -0
  8. package/dist/client/index.js +70 -0
  9. package/dist/index.cjs +4446 -1249
  10. package/dist/index.d.cts +297 -888
  11. package/dist/index.d.ts +297 -888
  12. package/dist/index.js +609 -1348
  13. package/dist/messages-7b0P8W75.d.cts +1652 -0
  14. package/dist/messages-7b0P8W75.d.ts +1652 -0
  15. package/dist/quasar/index.cjs +3340 -0
  16. package/dist/quasar/index.d.cts +95 -0
  17. package/dist/quasar/index.d.ts +95 -0
  18. package/dist/quasar/index.js +96 -0
  19. package/dist/testing-e2e/admin-pages-suite.cjs +14 -11
  20. package/dist/testing-e2e/admin-pages-suite.js +14 -11
  21. package/dist/use-super-admin-i18n-B3v3-SWZ.d.ts +210 -0
  22. package/dist/use-super-admin-i18n-DMktRVEt.d.cts +210 -0
  23. package/package.json +23 -3
  24. package/src/{action-registry.ts → client/action-registry.ts} +4 -4
  25. package/src/{batch-column-fetcher.ts → client/batch-column-fetcher.ts} +4 -4
  26. package/src/{boot-loader.ts → client/boot-loader.ts} +3 -3
  27. package/src/client/i18n/currency.ts +42 -0
  28. package/src/client/i18n/define.ts +59 -0
  29. package/src/client/i18n/format.ts +12 -0
  30. package/src/client/i18n/index.ts +14 -0
  31. package/src/client/i18n/locale.ts +15 -0
  32. package/src/client/i18n/messages/audit.ts +42 -0
  33. package/src/client/i18n/messages/bundles.ts +459 -0
  34. package/src/client/i18n/messages/common.ts +147 -0
  35. package/src/client/i18n/messages/dashboard.ts +16 -0
  36. package/src/client/i18n/messages/discovery.ts +229 -0
  37. package/src/client/i18n/messages/email.ts +125 -0
  38. package/src/client/i18n/messages/marketing.ts +270 -0
  39. package/src/client/i18n/messages/nav.ts +72 -0
  40. package/src/client/i18n/messages/pilots.ts +192 -0
  41. package/src/client/i18n/messages/plan-detail.ts +266 -0
  42. package/src/client/i18n/messages/plan-editor.ts +177 -0
  43. package/src/client/i18n/messages/plan-versions.ts +251 -0
  44. package/src/client/i18n/messages/plans.ts +503 -0
  45. package/src/client/i18n/messages/promos.ts +202 -0
  46. package/src/client/i18n/messages/shell.ts +145 -0
  47. package/src/client/i18n/messages/tenants.ts +104 -0
  48. package/src/client/i18n/messages/users.ts +78 -0
  49. package/src/client/i18n/messages.ts +84 -0
  50. package/src/client/index.ts +27 -0
  51. package/src/{manifest-loader.ts → client/manifest-loader.ts} +4 -4
  52. package/src/{nav-builder.ts → client/nav-builder.ts} +44 -51
  53. package/src/{plan-versions-catalog.ts → client/plan-versions-catalog.ts} +42 -30
  54. package/src/components/BundleVersionPublishDialog.vue +35 -24
  55. package/src/components/FeatureGate.vue +1 -1
  56. package/src/components/MarketingPromotionsTab.vue +112 -59
  57. package/src/components/MfaPromptDialog.vue +11 -11
  58. package/src/components/TenantActionConfirmDialog.vue +19 -17
  59. package/src/components/VersionDiffPreview.vue +72 -43
  60. package/src/components/bundle-editor/BundleCreatePanel.vue +76 -63
  61. package/src/components/bundle-editor/BundleFeaturesEditor.vue +13 -6
  62. package/src/components/bundle-editor/BundlePlanCompatPicker.vue +19 -14
  63. package/src/components/bundle-editor/BundleQuotasEditor.vue +7 -4
  64. package/src/components/bundle-editor/BundleStatusBanner.vue +36 -19
  65. package/src/components/bundle-editor/BundleVersionInlineEditor.vue +51 -35
  66. package/src/components/bundle-editor/BundleVersionStrip.vue +24 -12
  67. package/src/components/bundle-editor/bundle-version-status.ts +29 -29
  68. package/src/components/dialogs/PilotCreateDialog.vue +58 -63
  69. package/src/components/dialogs/PilotEditDialog.vue +40 -34
  70. package/src/components/dialogs/PromoCodeCreateDialog.vue +89 -63
  71. package/src/components/dialogs/PromoCodeEditDialog.vue +98 -66
  72. package/src/components/dialogs/types.ts +3 -13
  73. package/src/components/plan/PlanCycleToggle.vue +21 -10
  74. package/src/components/plan/PlanGrid.vue +2 -2
  75. package/src/components/plan/PriceSummary.vue +1 -1
  76. package/src/components/plan/PromoCodeInput.vue +1 -1
  77. package/src/components/plan/PublicBundleGrid.vue +1 -1
  78. package/src/components/plan-cockpit/PlanCockpit.vue +34 -15
  79. package/src/components/plan-cockpit/PlanCockpitAuditLog.vue +13 -6
  80. package/src/components/plan-cockpit/PlanCockpitDiffPanel.vue +18 -9
  81. package/src/components/plan-cockpit/PlanCockpitHeader.vue +9 -6
  82. package/src/components/plan-cockpit/PlanCockpitImpactPanel.vue +24 -11
  83. package/src/components/plan-cockpit/PlanCockpitKpis.vue +28 -17
  84. package/src/components/plan-cockpit/PlanCockpitVersions.vue +50 -25
  85. package/src/components/plan-create-dialog/PlanCreateDialog.vue +45 -35
  86. package/src/components/plan-detail/PlanAuditLog.vue +11 -6
  87. package/src/components/plan-detail/PlanDetail.vue +21 -23
  88. package/src/components/plan-detail/PlanDetailHeader.vue +20 -11
  89. package/src/components/plan-detail/PlanDetailKpis.vue +30 -17
  90. package/src/components/plan-detail/PlanTerminateDialog.vue +22 -9
  91. package/src/components/plan-detail/PlanVersionDiffPanel.vue +61 -27
  92. package/src/components/plan-detail/PlanVersionsPanel.vue +71 -36
  93. package/src/components/plan-list/PlanList.vue +99 -57
  94. package/src/components/plan-matrix/PlanMatrix.vue +85 -38
  95. package/src/components/plan-review/PlanReview.vue +105 -80
  96. package/src/components/plan-version-editor/PlanCatalogPreview.vue +43 -20
  97. package/src/components/plan-version-editor/PlanComponentPool.vue +15 -7
  98. package/src/components/plan-version-editor/PlanVersionBasket.vue +45 -24
  99. package/src/components/plan-version-editor/PlanVersionDiffDialog.vue +8 -7
  100. package/src/components/plan-version-editor/PlanVersionEditor.vue +74 -40
  101. package/src/components/plan-version-editor/PlanVersionEditorHeader.vue +24 -12
  102. package/src/index.ts +82 -79
  103. package/src/pages-standard/AdminLayout.vue +43 -18
  104. package/src/pages-standard/AdminManifestErrorPage.vue +10 -10
  105. package/src/pages-standard/AuditPage.vue +58 -19
  106. package/src/pages-standard/BundlesPage.vue +29 -18
  107. package/src/pages-standard/DashboardPage.vue +31 -17
  108. package/src/pages-standard/DiscoveryPage.vue +40 -28
  109. package/src/pages-standard/EmailHistoryPage.vue +98 -69
  110. package/src/pages-standard/MarketingCatalogPage.vue +40 -21
  111. package/src/pages-standard/PilotsPage.vue +64 -52
  112. package/src/pages-standard/PlanVersionsPage.vue +9 -5
  113. package/src/pages-standard/PlansPage.vue +91 -59
  114. package/src/pages-standard/PlatformEmailPage.vue +120 -53
  115. package/src/pages-standard/PromoCodeDetailPage.vue +66 -63
  116. package/src/pages-standard/PromoCodesPage.vue +51 -54
  117. package/src/pages-standard/SubscriptionsPage.vue +14 -9
  118. package/src/pages-standard/SuperAdminLoginPage.vue +19 -16
  119. package/src/pages-standard/SuperAdminSetupWizard.vue +53 -49
  120. package/src/pages-standard/TenantDetailPage.vue +54 -40
  121. package/src/pages-standard/TenantsPage.vue +57 -44
  122. package/src/pages-standard/UsersPage.vue +70 -52
  123. package/src/pages-standard/bundles-page/BundleAccordionList.vue +20 -8
  124. package/src/pages-standard/bundles-page/BundleDetailPanel.vue +28 -18
  125. package/src/pages-standard/bundles-page/BundlesFilterBar.vue +4 -1
  126. package/src/pages-standard/bundles-page/BundlesHeader.vue +9 -8
  127. package/src/pages-standard/bundles-page/BundlesKpis.vue +29 -11
  128. package/src/pages-standard/discovery-page/CatalogEntryTransPanel.vue +20 -8
  129. package/src/pages-standard/discovery-page/DiscoveryCapList.vue +5 -3
  130. package/src/pages-standard/discovery-page/DiscoveryFeatureCard.vue +43 -24
  131. package/src/pages-standard/discovery-page/DiscoveryHeader.vue +7 -4
  132. package/src/pages-standard/discovery-page/DiscoveryKpis.vue +28 -15
  133. package/src/pages-standard/discovery-page/DiscoveryQuotaCard.vue +20 -10
  134. package/src/pages-standard/discovery-page/DiscoveryStatusControl.vue +9 -6
  135. package/src/pages-standard/discovery-page/discovery-ui.ts +40 -52
  136. package/src/pages-standard/marketing-catalog/MarketingCatalogAdmin.vue +81 -49
  137. package/src/pages-standard/marketing-catalog/MarketingCatalogHeader.vue +13 -10
  138. package/src/pages-standard/marketing-catalog/MarketingCatalogPreview.vue +24 -20
  139. package/src/pages-standard/marketing-catalog/MarketingCatalogToolbar.vue +6 -3
  140. package/src/pages-standard/plan-versions/PlanDiffCard.vue +16 -6
  141. package/src/pages-standard/plan-versions/PlanVersionHeader.vue +42 -26
  142. package/src/pages-standard/plan-versions/PlanVersionsAudit.vue +46 -27
  143. package/src/pages-standard/plan-versions/PlanVersionsDiff.vue +8 -6
  144. package/src/pages-standard/plan-versions/PlanVersionsList.vue +40 -17
  145. package/src/pages-standard/plan-versions/PlanVersionsMatrix.vue +1 -1
  146. package/src/pages-standard/plan-versions/PlanVersionsTimeline.vue +25 -13
  147. package/src/pages-standard/plan-versions/format.ts +33 -17
  148. package/src/pages-standard/plans-page/PlanArchiveDialog.vue +12 -8
  149. package/src/pages-standard/plans-page/PlanBundleOverview.vue +15 -6
  150. package/src/pages-standard/plans-page/PlanDiscardDraftDialog.vue +18 -7
  151. package/src/pages-standard/plans-page/PlanPublishDialog.vue +23 -12
  152. package/src/pages-standard/tenants/format.ts +3 -2
  153. package/src/pages-tenant/MySubscriptionBundlesPage.vue +73 -38
  154. package/src/pages-tenant/OnboardingConfigurator.vue +3 -3
  155. package/src/pages-tenant/PackageSnapshotPanel.vue +1 -1
  156. package/src/pages-tenant/PlanChangeWizard.vue +10 -6
  157. package/src/pages-tenant/TenantPlanSection.vue +20 -16
  158. package/src/pages-tenant/default-i18n.ts +217 -1
  159. package/src/pages-tenant/tenant-plan-section/BundlePreviewDialog.vue +9 -7
  160. package/src/pages-tenant/tenant-plan-section/TenantBundleStore.vue +11 -12
  161. package/src/pages-tenant/tenant-plan-section/TenantFeatureMatrix.vue +4 -1
  162. package/src/pages-tenant/tenant-plan-section/TenantPlanCardHeader.vue +1 -1
  163. package/src/pages-tenant/tenant-plan-section/TenantUsageGrid.vue +1 -1
  164. package/src/quasar/create-super-admin-app.ts +192 -0
  165. package/src/quasar/index.ts +11 -0
  166. package/src/quasar/notify.ts +30 -0
  167. package/src/testing-e2e/admin-pages-suite.ts +14 -11
  168. package/src/{manifest-store-factory.ts → vue/manifest-store-factory.ts} +1 -1
  169. package/src/{platform-loaders.ts → vue/platform-loaders.ts} +4 -4
  170. package/src/{project-page-host.ts → vue/project-page-host.ts} +6 -4
  171. package/src/{create-super-admin-app.ts → vue/super-admin-context.ts} +20 -139
  172. package/src/vue/ui-notify.ts +30 -0
  173. package/src/{use-actions.ts → vue/use-actions.ts} +1 -1
  174. package/src/{use-api-list.ts → vue/use-api-list.ts} +1 -1
  175. package/src/{use-audit-entries.ts → vue/use-audit-entries.ts} +3 -3
  176. package/src/{use-batch-columns.ts → vue/use-batch-columns.ts} +1 -1
  177. package/src/{use-bulk-publish.ts → vue/use-bulk-publish.ts} +7 -5
  178. package/src/{use-bundle-versions-map.ts → vue/use-bundle-versions-map.ts} +7 -5
  179. package/src/{use-bundles.ts → vue/use-bundles.ts} +14 -14
  180. package/src/{use-catalog-entries.ts → vue/use-catalog-entries.ts} +14 -11
  181. package/src/{use-discovery.ts → vue/use-discovery.ts} +9 -6
  182. package/src/{use-entitlement.ts → vue/use-entitlement.ts} +4 -4
  183. package/src/{use-live-plan-versions.ts → vue/use-live-plan-versions.ts} +5 -5
  184. package/src/{use-manifest.ts → vue/use-manifest.ts} +1 -1
  185. package/src/{use-marketing-projections.ts → vue/use-marketing-projections.ts} +10 -7
  186. package/src/{use-nav.ts → vue/use-nav.ts} +9 -3
  187. package/src/{use-plan-editor.ts → vue/use-plan-editor.ts} +2 -2
  188. package/src/{use-plan-versions.ts → vue/use-plan-versions.ts} +3 -3
  189. package/src/{use-plans.ts → vue/use-plans.ts} +13 -13
  190. package/src/{use-platform-tenant-actions.ts → vue/use-platform-tenant-actions.ts} +9 -6
  191. package/src/{use-promotions.ts → vue/use-promotions.ts} +10 -11
  192. package/src/{use-public-boot.ts → vue/use-public-boot.ts} +1 -1
  193. package/src/{use-subscription-draft.ts → vue/use-subscription-draft.ts} +2 -3
  194. package/src/{use-super-admin-context.ts → vue/use-super-admin-context.ts} +5 -5
  195. package/src/vue/use-super-admin-i18n.ts +82 -0
  196. package/src/{use-tenant-action-flow.ts → vue/use-tenant-action-flow.ts} +12 -7
  197. package/src/{use-tenant-billing-catalog.ts → vue/use-tenant-billing-catalog.ts} +2 -2
  198. package/src/{use-tenant-billing.ts → vue/use-tenant-billing.ts} +2 -2
  199. package/src/{use-tenant-manifest.ts → vue/use-tenant-manifest.ts} +2 -4
  200. package/src/{use-tenant-subscription-bundles.ts → vue/use-tenant-subscription-bundles.ts} +5 -5
  201. package/src/{use-tenants.ts → vue/use-tenants.ts} +3 -3
  202. package/dist/testing-e2e/admin-pages-suite.d.cts +0 -37
  203. package/dist/testing-e2e/admin-pages-suite.d.ts +0 -37
  204. package/src/components/BusinessTypeVersionEditorDialog.vue +0 -417
  205. package/src/components/BusinessTypeVersionPublishDialog.vue +0 -258
  206. package/src/pages-standard/BusinessTypesPage.vue +0 -662
  207. package/src/pages-standard/plan-versions/VersionDiffPreview.vue +0 -167
  208. package/src/use-business-types.ts +0 -269
  209. /package/src/{http-json.ts → client/http-json.ts} +0 -0
  210. /package/src/{types.ts → client/types.ts} +0 -0
  211. /package/src/{version.ts → client/version.ts} +0 -0
  212. /package/src/{create-admin-routes.ts → vue/create-admin-routes.ts} +0 -0
  213. /package/src/{entitlement-provider.ts → vue/entitlement-provider.ts} +0 -0
  214. /package/src/{feature-router-guard.ts → vue/feature-router-guard.ts} +0 -0
package/src/index.ts CHANGED
@@ -1,75 +1,88 @@
1
- // @saasicat/ui-vue — Vue 3 components + composables for the
2
- // SuperAdmin UI shell.
1
+ // @saasicat/ui-vue — Vue 3 composables + loaders for the SuperAdmin UI shell.
3
2
  //
4
- // P4.1 (Phase 30): public boot loader + manifest loader (ETag cache).
5
- // P4.2 (Phase 31): nav builder + extension host + action registry.
6
- // P4.3 (Phase 32): batch column fetcher.
7
- // P4.4 (Phase 33): composables for standard pages (Tenants, Audit, Entitlement).
8
- // P4.5 (Phase 34): plan-versions list composables + bulk-publish orchestration.
3
+ // The package is layered; each layer has its own entry:
9
4
  //
10
- // Contents:
11
- // - types: HttpClient, KvStore, defaultHttpClient, defaultKvStore
12
- // - boot-loader: BootLoader (framework-agnostic) + BootLoadError
13
- // - manifest-loader: ManifestLoader with ETag cache + ManifestLoadError
14
- // - nav-builder: buildRoutes, buildSidebar, resolveExtension
15
- // - action-registry: ActionRegistry, MissingHandlerError, ActionDefNotInManifestError
16
- // - batch-column-fetcher: BatchColumnFetcher + BatchColumnDriftError
17
- // - use-api-list: useApiList<T> generic list composable
18
- // - use-tenants: useTenants typed wrapper
19
- // - use-audit-entries: useAuditEntries typed wrapper
20
- // - use-entitlement: useEntitlement composable
21
- // - use-plan-versions: usePlanVersionsCatalog
22
- // - use-bulk-publish: useBulkPublish (parallel publishes with status tracking)
23
- // - use-plan-editor: usePlanEditor composable (feature discovery, plannedOnly filter)
24
- // - use-public-boot: usePublicBoot composable
25
- // - use-manifest: useManifest composable
26
- // - use-nav: useNav composable
27
- // - use-actions: useActions composable
28
- // - use-batch-columns: useBatchColumns composable
5
+ // - `@saasicat/ui-vue/client` (`src/client/`) — framework-free core:
6
+ // loaders, nav builder, action registry, HTTP contract. No Vue, no
7
+ // Pinia, no Quasar.
8
+ // - `@saasicat/ui-vue` (this entry, `src/vue/`) Vue bindings: composables,
9
+ // router guards, injection keys, optional Pinia store factory. Re-exports
10
+ // the client layer. No Quasar.
11
+ // - `@saasicat/ui-vue/quasar` (`src/quasar/`) — Quasar bootstrap:
12
+ // `createSuperAdminApp()` and the Quasar notify port implementation.
13
+ // - Quasar standard pages/components — raw SFCs via the
14
+ // `./pages-standard/*`, `./pages-tenant/*` and `./components/*` subpath
15
+ // exports (tsup ignores `.vue`).
16
+ //
17
+ // Layer rule (enforced via ESLint `no-restricted-imports`): client imports
18
+ // nothing framework-specific; vue never imports quasar; this entry never
19
+ // reaches the quasar layer or the SFC directories (except the whitelisted
20
+ // framework-free type/i18n modules below).
21
+
22
+ // ---------------------------------------------------------------------------
23
+ // Client layer (framework-free core).
24
+ // ---------------------------------------------------------------------------
25
+ export * from './client/index.js';
26
+
27
+ // ---------------------------------------------------------------------------
28
+ // Vue layer: shell contract (injection keys, option types, navigation guard)
29
+ // and the UI notify port. `createSuperAdminApp()` itself lives in
30
+ // `@saasicat/ui-vue/quasar`.
31
+ // ---------------------------------------------------------------------------
32
+ export * from './vue/super-admin-context.js';
33
+ export * from './vue/ui-notify.js';
34
+ export * from './vue/use-super-admin-context.js';
35
+ export * from './vue/use-super-admin-i18n.js';
29
36
 
30
- export * from './version.js';
31
- export * from './types.js';
32
- export * from './http-json.js';
33
- export * from './create-admin-routes.js';
34
- export * from './boot-loader.js';
35
- export * from './manifest-loader.js';
36
- export * from './nav-builder.js';
37
- export * from './action-registry.js';
38
- export * from './batch-column-fetcher.js';
39
- export * from './use-api-list.js';
40
- export * from './use-tenants.js';
41
- export * from './use-audit-entries.js';
42
- export * from './use-entitlement.js';
43
- export * from './use-tenant-manifest.js';
44
- export * from './entitlement-provider.js';
45
- export * from './feature-router-guard.js';
37
+ // ---------------------------------------------------------------------------
38
+ // Vue layer: composables, guards, hosts, store factory.
39
+ // ---------------------------------------------------------------------------
40
+ export * from './vue/create-admin-routes.js';
41
+ export * from './vue/use-api-list.js';
42
+ export * from './vue/use-tenants.js';
43
+ export * from './vue/use-audit-entries.js';
44
+ export * from './vue/use-entitlement.js';
45
+ export * from './vue/use-tenant-manifest.js';
46
+ export * from './vue/entitlement-provider.js';
47
+ export * from './vue/feature-router-guard.js';
46
48
  // FeatureGate.vue is not bundled — consumers import it directly:
47
49
  // import FeatureGate from '@saasicat/ui-vue/components/FeatureGate.vue';
48
- export * from './use-tenant-billing-catalog.js';
49
- export * from './use-tenant-billing.js';
50
- export * from './use-subscription-draft.js';
51
- export * from './pages-tenant/default-i18n.js';
52
- export * from './use-plan-versions.js';
53
- export * from './use-bulk-publish.js';
54
- export * from './use-plan-editor.js';
55
- export * from './use-public-boot.js';
56
- export * from './use-discovery.js';
57
- export * from './use-catalog-entries.js';
58
- export * from './use-bundles.js';
59
- export * from './use-bundle-versions-map.js';
60
- export * from './use-tenant-subscription-bundles.js';
61
- export * from './use-business-types.js';
62
- export * from './use-marketing-projections.js';
63
- export * from './use-promotions.js';
64
- export * from './use-plans.js';
65
- export * from './use-live-plan-versions.js';
66
- export * from './use-manifest.js';
67
- export * from './use-nav.js';
68
- export * from './use-actions.js';
69
- export * from './use-tenant-action-flow.js';
70
- export * from './use-platform-tenant-actions.js';
71
- export * from './use-batch-columns.js';
72
- export * from './plan-versions-catalog.js';
50
+ export * from './vue/use-tenant-billing-catalog.js';
51
+ export * from './vue/use-tenant-billing.js';
52
+ export * from './vue/use-subscription-draft.js';
53
+ export * from './vue/use-plan-versions.js';
54
+ export * from './vue/use-bulk-publish.js';
55
+ export * from './vue/use-plan-editor.js';
56
+ export * from './vue/use-public-boot.js';
57
+ export * from './vue/use-discovery.js';
58
+ export * from './vue/use-catalog-entries.js';
59
+ export * from './vue/use-bundles.js';
60
+ export * from './vue/use-bundle-versions-map.js';
61
+ export * from './vue/use-tenant-subscription-bundles.js';
62
+ export * from './vue/use-marketing-projections.js';
63
+ export * from './vue/use-promotions.js';
64
+ export * from './vue/use-plans.js';
65
+ export * from './vue/use-live-plan-versions.js';
66
+ export * from './vue/use-manifest.js';
67
+ export * from './vue/use-nav.js';
68
+ export * from './vue/use-actions.js';
69
+ export * from './vue/use-tenant-action-flow.js';
70
+ export * from './vue/use-platform-tenant-actions.js';
71
+ export * from './vue/use-batch-columns.js';
72
+ // Loader factory that builds BootLoader + ManifestLoader from the same
73
+ // endpoint configuration as createSuperAdminApp() — so that endpoints live
74
+ // in a single place per app.
75
+ export * from './vue/platform-loaders.js';
76
+ // ProjectPageHost: resolves manifest projectPages dynamically against the
77
+ // extensions: map — replaces static route duplication in the apps.
78
+ export * from './vue/project-page-host.js';
79
+ // Manifest Pinia store factory — standardizes ensureLoaded/reload/clearCache.
80
+ export * from './vue/manifest-store-factory.js';
81
+
82
+ // ---------------------------------------------------------------------------
83
+ // Framework-free type/i18n modules that deliberately stay co-located with
84
+ // their SFCs (whitelisted in the ESLint layer rules).
85
+ // ---------------------------------------------------------------------------
73
86
  // Platform dialog types for app wrappers that type submit handlers.
74
87
  export * from './components/dialogs/types.js';
75
88
  // Pure resolvers for translated feature/quota labels in the bundle editors.
@@ -78,18 +91,8 @@ export * from './components/bundle-editor/catalog-i18n.js';
78
91
  export * from './pages-standard/platform-email.types.js';
79
92
  // Types of the shared EmailHistoryPage (platform email history).
80
93
  export * from './pages-standard/email-history.types.js';
81
- // Universal bootstrap helper for SuperAdmin apps + associated composables.
82
- export * from './create-super-admin-app.js';
83
- export * from './use-super-admin-context.js';
84
- // Loader factory that builds BootLoader + ManifestLoader from the same
85
- // endpoint configuration as createSuperAdminApp() — so that endpoints live
86
- // in a single place per app.
87
- export * from './platform-loaders.js';
88
- // ProjectPageHost: resolves manifest projectPages dynamically against the
89
- // extensions: map — replaces static route duplication in the apps.
90
- export * from './project-page-host.js';
91
- // Manifest Pinia store factory — standardizes ensureLoaded/reload/clearCache.
92
- export * from './manifest-store-factory.js';
94
+ // Default German labels for the tenant-facing pages.
95
+ export * from './pages-tenant/default-i18n.js';
93
96
 
94
97
  // The shared SuperAdmin LoginPage lives at
95
98
  // `@saasicat/ui-vue/pages-standard/SuperAdminLoginPage.vue` —
@@ -2,7 +2,7 @@
2
2
  <q-layout view="lHh Lpr lFf">
3
3
  <div v-if="isProduction" class="sa-admin-banner sa-admin-banner--prod">
4
4
  <q-icon name="warning" size="14px" />
5
- <strong>PRODUCTION</strong> — Aktionen wirken sich sofort auf alle Mandanten aus.
5
+ <strong>PRODUCTION</strong> — {{ msg.header.productionWarning }}
6
6
  </div>
7
7
 
8
8
  <q-header elevated class="sa-admin-header">
@@ -10,11 +10,11 @@
10
10
  <q-btn flat dense round icon="menu" @click="leftDrawerOpen = !leftDrawerOpen" />
11
11
  <q-toolbar-title class="text-weight-bold">
12
12
  {{ currentPageTitle }}
13
- <div class="sa-admin-header__sub">SuperAdmin · Plattform-Verwaltung</div>
13
+ <div class="sa-admin-header__sub">{{ msg.header.subtitle }}</div>
14
14
  </q-toolbar-title>
15
15
  <q-space />
16
16
  <slot name="header-actions" />
17
- <q-badge class="sa-admin-badge q-mr-sm">SUPER ADMIN</q-badge>
17
+ <q-badge class="sa-admin-badge q-mr-sm">{{ msg.header.roleBadge }}</q-badge>
18
18
  <div class="sa-admin-user">
19
19
  <q-avatar size="32px" class="sa-admin-user__avatar">
20
20
  {{ initials }}
@@ -24,7 +24,7 @@
24
24
  <div class="text-caption sa-admin-user__email">{{ userEmail }}</div>
25
25
  </div>
26
26
  <q-btn flat round dense icon="logout" size="sm" @click="emit('logout')">
27
- <q-tooltip>Abmelden</q-tooltip>
27
+ <q-tooltip>{{ msg.header.logout }}</q-tooltip>
28
28
  </q-btn>
29
29
  </div>
30
30
  </q-toolbar>
@@ -39,10 +39,12 @@
39
39
  >
40
40
  <div class="sa-admin-drawer__stack">
41
41
  <div class="sa-admin-drawer__brand">
42
- <div class="sa-admin-drawer__logo">{{ brandLogoText }}</div>
42
+ <div class="sa-admin-drawer__logo">{{ brand.logoText }}</div>
43
43
  <div>
44
- <div class="sa-admin-drawer__brand-name">{{ brandName }}</div>
45
- <div class="sa-admin-drawer__brand-tag">{{ brandTag }} v{{ adminUiVersion }}</div>
44
+ <div class="sa-admin-drawer__brand-name">{{ brand.name }}</div>
45
+ <div class="sa-admin-drawer__brand-tag">
46
+ {{ brand.tag }} v{{ adminUiVersion }}
47
+ </div>
46
48
  </div>
47
49
  </div>
48
50
 
@@ -75,7 +77,7 @@
75
77
  target="_blank"
76
78
  rel="noopener"
77
79
  >
78
- <q-icon name="menu_book" size="14px" /> Doku öffnen
80
+ <q-icon name="menu_book" size="14px" /> {{ msg.drawer.docs }}
79
81
  </a>
80
82
  </slot>
81
83
  </div>
@@ -91,11 +93,13 @@
91
93
  </template>
92
94
 
93
95
  <script setup lang="ts">
94
- import { computed, ref } from 'vue';
96
+ import { computed, inject, ref } from 'vue';
95
97
  import { useRoute } from 'vue-router';
96
98
  import type { AdminManifest, StandardPageKey } from '@saasicat/types';
97
- import { buildRoutes, buildSidebar, DEFAULT_SECTION_ORDER } from '../nav-builder.js';
98
- import { ADMIN_UI_VERSION } from '../version.js';
99
+ import { buildRoutes, buildSidebar, defaultSectionOrder } from '../client/nav-builder.js';
100
+ import { SUPER_ADMIN_BRAND_KEY, SUPER_ADMIN_MANIFEST_KEY } from '../vue/super-admin-context.js';
101
+ import { useSaMessages, useSuperAdminI18n } from '../vue/use-super-admin-i18n.js';
102
+ import { ADMIN_UI_VERSION } from '../client/version.js';
99
103
 
100
104
  // SuperAdmin layout — universal platform shell for all consumer apps.
101
105
  // CSS classes `sa-admin-*` with BEM convention; apps can override any class
@@ -131,8 +135,13 @@ export interface SidebarItem {
131
135
 
132
136
  const props = withDefaults(
133
137
  defineProps<{
134
- brandLogoText: string;
135
- brandName: string;
138
+ /**
139
+ * Branding. Optional — when the layout is mounted as a route component
140
+ * inside `createSuperAdminApp({ brand })`, these default to the
141
+ * provided brand and only need passing to override it.
142
+ */
143
+ brandLogoText?: string;
144
+ brandName?: string;
136
145
  brandTag?: string;
137
146
  manifest?: AdminManifest | null;
138
147
  staticNavFallback?: readonly SidebarItem[];
@@ -164,13 +173,11 @@ const props = withDefaults(
164
173
  adminPathPrefix?: string;
165
174
  }>(),
166
175
  {
167
- brandTag: 'SuperAdmin',
168
176
  staticNavFallback: () => [],
169
177
  localItems: () => [],
170
178
  localItemsSection: null,
171
179
  adminPathPrefix: '/admin',
172
180
  isProduction: false,
173
- sectionOrder: () => DEFAULT_SECTION_ORDER,
174
181
  },
175
182
  );
176
183
 
@@ -179,6 +186,23 @@ const emit = defineEmits<{
179
186
  }>();
180
187
 
181
188
  const route = useRoute();
189
+ const msg = useSaMessages('shell');
190
+ const { locale } = useSuperAdminI18n();
191
+ // Provided by createSuperAdminApp(); null when the layout is mounted
192
+ // stand-alone. Grouped into one object so the names cannot shadow the
193
+ // same-named props inside the template.
194
+ const injectedBrand = inject(SUPER_ADMIN_BRAND_KEY, null);
195
+ // Same idea for the manifest: createSuperAdminApp({ manifestGuard: {
196
+ // getManifest } }) provides an accessor, so pages mounted straight as route
197
+ // components do not have to be wrapped just to thread the prop through.
198
+ const injectedManifest = inject(SUPER_ADMIN_MANIFEST_KEY, null);
199
+ const activeManifest = computed(() => props.manifest ?? injectedManifest?.() ?? null);
200
+ const brand = computed(() => ({
201
+ logoText: props.brandLogoText ?? injectedBrand?.logoText ?? '',
202
+ name: props.brandName ?? injectedBrand?.name ?? '',
203
+ tag: props.brandTag ?? injectedBrand?.tag ?? 'SuperAdmin',
204
+ }));
205
+
182
206
  const leftDrawerOpen = ref(false);
183
207
 
184
208
  const adminUiVersion = ADMIN_UI_VERSION;
@@ -195,18 +219,19 @@ interface NavSection {
195
219
  }
196
220
 
197
221
  const navSections = computed<NavSection[]>(() => {
198
- const m = props.manifest;
222
+ const m = activeManifest.value;
199
223
  if (!m) {
200
224
  // Pre-manifest: static fallback + local items as one unnamed
201
225
  // section, so that the UI has no flicker before manifest load.
202
226
  return [{ title: null, items: [...props.staticNavFallback, ...props.localItems] }];
203
227
  }
204
228
  const routes = buildRoutes(m, {
229
+ locale: locale.value,
205
230
  standardPageRoutes: props.standardPageRoutes,
206
231
  standardPageNavSection: props.standardPageNavSection,
207
232
  availableExtensions: props.availableExtensions,
208
233
  });
209
- const sections = buildSidebar(routes, props.sectionOrder);
234
+ const sections = buildSidebar(routes, props.sectionOrder ?? defaultSectionOrder(locale.value));
210
235
  const result: NavSection[] = sections.map((s) => ({
211
236
  title: s.section,
212
237
  items: s.items.map((item) => ({
@@ -241,7 +266,7 @@ const currentPageTitle = computed(() => {
241
266
  }
242
267
  // Default: sidebar item label that matches the active route.
243
268
  const item = resolvedNav.value.find((i) => i.to === route.path);
244
- return item?.label ?? `${props.brandName} SuperAdmin`;
269
+ return item?.label ?? `${brand.value.name} SuperAdmin`;
245
270
  });
246
271
  </script>
247
272
 
@@ -3,21 +3,16 @@
3
3
  <q-card class="sa-manifest-error__card">
4
4
  <q-card-section class="sa-manifest-error__head">
5
5
  <q-icon name="cloud_off" size="32px" color="negative" />
6
- <h1 class="sa-manifest-error__title">Admin-Manifest nicht erreichbar</h1>
6
+ <h1 class="sa-manifest-error__title">{{ msg.manifestError.title }}</h1>
7
7
  </q-card-section>
8
8
  <q-card-section>
9
- <p class="sa-manifest-error__lead">
10
- Das Plattform-Manifest konnte nicht geladen werden. Ohne Manifest sind Sidebar,
11
- Capabilities und Action-Buttons nicht zuverlässig — die UI würde sonst falsche
12
- oder unerreichbare Buttons rendern. Der Router hat dich deshalb hierher
13
- geschickt (fail-closed).
14
- </p>
9
+ <p class="sa-manifest-error__lead">{{ msg.manifestError.lead }}</p>
15
10
  <p v-if="errorMessage" class="sa-manifest-error__detail">
16
- <strong>Detail:</strong> {{ errorMessage }}
11
+ <strong>{{ msg.manifestError.detailLabel }}</strong> {{ errorMessage }}
17
12
  </p>
18
13
  <div class="sa-manifest-error__actions">
19
- <q-btn unelevated color="primary" label="Erneut laden" @click="onRetry" />
20
- <q-btn flat label="Logout" @click="onLogout" />
14
+ <q-btn unelevated color="primary" :label="common.reload" @click="onRetry" />
15
+ <q-btn flat :label="msg.header.logout" @click="onLogout" />
21
16
  </div>
22
17
  </q-card-section>
23
18
  </q-card>
@@ -25,11 +20,16 @@
25
20
  </template>
26
21
 
27
22
  <script setup lang="ts">
23
+ import { useSaMessages } from '../vue/use-super-admin-i18n.js';
24
+
28
25
  // Platform standard error page for `manifestGuard.errorRoute`.
29
26
  // Consumers pass `onRetry`/`onLogout` in as callbacks and decide
30
27
  // themselves what happens (e.g. manifestStore.clearCache() + ensureLoaded,
31
28
  // authStore.logout, router.replace).
32
29
 
30
+ const msg = useSaMessages('shell');
31
+ const common = useSaMessages('common');
32
+
33
33
  defineProps<{
34
34
  errorMessage?: string | null;
35
35
  onRetry: () => Promise<void> | void;
@@ -2,18 +2,51 @@
2
2
  <div class="sa-audit">
3
3
  <header class="sa-audit__head">
4
4
  <div>
5
- <h1 class="sa-audit__title">Audit-Trail</h1>
6
- <p class="sa-audit__sub">{{ rows.length }} Einträge · plattformweit.</p>
5
+ <h1 class="sa-audit__title">{{ msg.title }}</h1>
6
+ <p class="sa-audit__sub">
7
+ {{ formatMessage(msg.subtitle, { count: rows.length }) }}
8
+ </p>
7
9
  </div>
8
- <q-btn unelevated color="primary" icon="refresh" label="Filtern" @click="reload" />
10
+ <q-btn
11
+ unelevated
12
+ color="primary"
13
+ icon="refresh"
14
+ :label="msg.filterButton"
15
+ @click="reload"
16
+ />
9
17
  </header>
10
18
 
11
19
  <div class="sa-audit__body">
12
20
  <div class="sa-audit__filter">
13
- <q-input v-model="filter.actor" outlined dense label="Actor (E-Mail)" clearable />
14
- <q-input v-model="filter.action" outlined dense label="Action" clearable />
15
- <q-input v-model="filter.entity" outlined dense label="Entity" clearable />
16
- <q-input v-model="filter.since" outlined dense type="date" label="Seit" clearable />
21
+ <q-input
22
+ v-model="filter.actor"
23
+ outlined
24
+ dense
25
+ :label="msg.filters.actor"
26
+ clearable
27
+ />
28
+ <q-input
29
+ v-model="filter.action"
30
+ outlined
31
+ dense
32
+ :label="msg.filters.action"
33
+ clearable
34
+ />
35
+ <q-input
36
+ v-model="filter.entity"
37
+ outlined
38
+ dense
39
+ :label="msg.filters.entity"
40
+ clearable
41
+ />
42
+ <q-input
43
+ v-model="filter.since"
44
+ outlined
45
+ dense
46
+ type="date"
47
+ :label="msg.filters.since"
48
+ clearable
49
+ />
17
50
  </div>
18
51
 
19
52
  <div class="sa-audit__card">
@@ -29,7 +62,7 @@
29
62
  <template #body-cell-changes="{ row }">
30
63
  <q-td>
31
64
  <q-btn flat dense icon="code" color="primary" @click="openDetail(row)">
32
- <q-tooltip>Details</q-tooltip>
65
+ <q-tooltip>{{ common.details }}</q-tooltip>
33
66
  </q-btn>
34
67
  </q-td>
35
68
  </template>
@@ -42,7 +75,7 @@
42
75
  <q-card-section>
43
76
  <div class="text-h6">{{ detail?.action }} · {{ detail?.entity }}</div>
44
77
  <div class="text-caption text-grey-7">
45
- {{ detail ? formatTs(detail.createdAt) : '' }} · Actor:
78
+ {{ detail ? formatTs(detail.createdAt) : '' }} · {{ msg.detailActorPrefix }}
46
79
  {{ detail ? actorEmail(detail) : '—' }}
47
80
  </div>
48
81
  </q-card-section>
@@ -52,7 +85,7 @@
52
85
  }}</pre>
53
86
  </q-card-section>
54
87
  <q-card-actions align="right">
55
- <q-btn v-close-popup flat label="Schließen" />
88
+ <q-btn v-close-popup flat :label="common.close" />
56
89
  </q-card-actions>
57
90
  </q-card>
58
91
  </q-dialog>
@@ -60,7 +93,9 @@
60
93
  </template>
61
94
 
62
95
  <script setup lang="ts">
63
- import { onMounted, reactive, ref } from 'vue';
96
+ import { computed, onMounted, reactive, ref } from 'vue';
97
+ import { formatMessage } from '../client/i18n/format.js';
98
+ import { useSaMessages, useSuperAdminI18n } from '../vue/use-super-admin-i18n.js';
64
99
 
65
100
  // Platform standard page: audit trail. Data-agnostic — the app passes
66
101
  // `loadAudit({ actor, action, entity, since, limit })` through.
@@ -89,36 +124,40 @@ const props = defineProps<{
89
124
  pageSize?: number;
90
125
  }>();
91
126
 
127
+ const msg = useSaMessages('audit');
128
+ const common = useSaMessages('common');
129
+ const { intlLocale } = useSuperAdminI18n();
130
+
92
131
  const rows = ref<AuditRow[]>([]);
93
132
  const loading = ref(false);
94
133
  const filter = reactive({ actor: '', action: '', entity: '', since: '' });
95
134
  const detailOpen = ref(false);
96
135
  const detail = ref<AuditRow | null>(null);
97
136
 
98
- const columns = [
137
+ const columns = computed(() => [
99
138
  {
100
139
  name: 'createdAt',
101
- label: 'Zeit',
140
+ label: msg.value.columns.time,
102
141
  field: (r: AuditRow) => formatTs(r.createdAt),
103
142
  align: 'left' as const,
104
143
  sortable: true,
105
144
  },
106
145
  {
107
146
  name: 'actor',
108
- label: 'Actor',
147
+ label: msg.value.columns.actor,
109
148
  field: actorEmail,
110
149
  align: 'left' as const,
111
150
  },
112
- { name: 'action', label: 'Action', field: 'action', align: 'left' as const },
113
- { name: 'entity', label: 'Entity', field: 'entity', align: 'left' as const },
151
+ { name: 'action', label: msg.value.columns.action, field: 'action', align: 'left' as const },
152
+ { name: 'entity', label: msg.value.columns.entity, field: 'entity', align: 'left' as const },
114
153
  {
115
154
  name: 'entityId',
116
- label: 'ID',
155
+ label: msg.value.columns.id,
117
156
  field: (r: AuditRow) => r.entityId.slice(0, 8),
118
157
  align: 'left' as const,
119
158
  },
120
159
  { name: 'changes', label: '', field: 'id', align: 'right' as const },
121
- ];
160
+ ]);
122
161
 
123
162
  async function reload() {
124
163
  loading.value = true;
@@ -153,7 +192,7 @@ function actorEmail(r: AuditRow): string {
153
192
  function formatTs(iso: string | null | undefined): string {
154
193
  if (!iso) return '—';
155
194
  try {
156
- return new Date(iso).toLocaleString('de-DE', {
195
+ return new Date(iso).toLocaleString(intlLocale.value, {
157
196
  day: '2-digit',
158
197
  month: 'short',
159
198
  year: 'numeric',