@saasicat/ui-vue 0.21.0 → 0.22.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 (132) hide show
  1. package/dist/{catalog-BY_t9prv.d.cts → catalog-DJcfm5N2.d.cts} +20 -7
  2. package/dist/{catalog-BY_t9prv.d.ts → catalog-DJcfm5N2.d.ts} +20 -7
  3. package/dist/{chunk-JN6HZGLV.js → chunk-F7NRM6KI.js} +54 -28
  4. package/dist/{chunk-7IFKVGZV.js → chunk-LY52T4N4.js} +21 -2
  5. package/dist/{chunk-OTP3OSSW.js → chunk-XMMFN2WJ.js} +74 -3
  6. package/dist/client/index.cjs +132 -29
  7. package/dist/client/index.d.cts +53 -3
  8. package/dist/client/index.d.ts +53 -3
  9. package/dist/client/index.js +14 -2
  10. package/dist/index.cjs +319 -162
  11. package/dist/index.d.cts +30 -8
  12. package/dist/index.d.ts +30 -8
  13. package/dist/index.js +176 -133
  14. package/dist/quasar/index.cjs +76 -29
  15. package/dist/quasar/index.d.cts +2 -2
  16. package/dist/quasar/index.d.ts +2 -2
  17. package/dist/quasar/index.js +6 -2
  18. package/dist/testing-e2e/admin-pages-suite.d.cts +37 -0
  19. package/dist/testing-e2e/admin-pages-suite.d.ts +37 -0
  20. package/dist/{use-super-admin-i18n-c_Eqsu9u.d.ts → use-super-admin-i18n-CHNdsSlm.d.ts} +34 -7
  21. package/dist/{use-super-admin-i18n-DlJRGIVq.d.cts → use-super-admin-i18n-CgTuNi8h.d.cts} +34 -7
  22. package/package.json +18 -8
  23. package/src/client/i18n/messages/bundles.ts +0 -2
  24. package/src/client/i18n/messages/common.ts +22 -0
  25. package/src/client/i18n/messages/discovery.ts +2 -2
  26. package/src/client/i18n/messages/marketing.ts +2 -4
  27. package/src/client/i18n/messages/plan-detail.ts +0 -4
  28. package/src/client/i18n/messages/plans.ts +20 -8
  29. package/src/client/i18n/messages/tenants.ts +0 -2
  30. package/src/client/index.ts +1 -0
  31. package/src/client/manifest-loader.ts +1 -1
  32. package/src/client/resolve-plans.ts +144 -0
  33. package/src/components/BundleVersionPublishDialog.vue +6 -6
  34. package/src/components/KvBlock.vue +4 -4
  35. package/src/components/MarketingPromotionsTab.vue +34 -48
  36. package/src/components/MfaPromptDialog.vue +8 -2
  37. package/src/components/TenantActionConfirmDialog.vue +4 -4
  38. package/src/components/VersionDiffPreview.vue +7 -7
  39. package/src/components/admin-page/AdminFilters.vue +12 -0
  40. package/src/components/admin-page/AdminHero.vue +22 -5
  41. package/src/components/admin-page/AdminKpi.vue +84 -0
  42. package/src/components/admin-page/AdminPaginator.vue +195 -0
  43. package/src/components/admin-page/AdminRefreshBtn.vue +39 -0
  44. package/src/components/admin-page/AdminSection.vue +31 -16
  45. package/src/components/admin-page/AdminStatistics.vue +40 -0
  46. package/src/components/admin-page/AdminTable.vue +175 -0
  47. package/src/components/bundle-editor/BundleCreatePanel.vue +23 -23
  48. package/src/components/bundle-editor/BundleFeaturesEditor.vue +7 -7
  49. package/src/components/bundle-editor/BundlePlanCompatPicker.vue +9 -9
  50. package/src/components/bundle-editor/BundleQuotasEditor.vue +11 -11
  51. package/src/components/bundle-editor/BundleStatusBanner.vue +6 -6
  52. package/src/components/bundle-editor/BundleVersionInlineEditor.vue +18 -18
  53. package/src/components/bundle-editor/BundleVersionStrip.vue +12 -12
  54. package/src/components/dialogs/PilotCreateDialog.vue +12 -12
  55. package/src/components/dialogs/PilotEditDialog.vue +7 -7
  56. package/src/components/dialogs/PromoCodeCreateDialog.vue +8 -8
  57. package/src/components/dialogs/PromoCodeDialogFields.vue +33 -19
  58. package/src/components/dialogs/PromoCodeEditDialog.vue +10 -10
  59. package/src/components/plan/PlanGrid.vue +1 -1
  60. package/src/components/plan-create-dialog/PlanCreateDialog.vue +34 -46
  61. package/src/components/plan-detail/PlanDetail.vue +92 -302
  62. package/src/components/plan-detail/PlanDetailKpis.vue +22 -27
  63. package/src/components/plan-detail/PlanTitleEdit.vue +133 -0
  64. package/src/components/plan-list/PlanList.vue +72 -290
  65. package/src/components/plan-matrix/PlanMatrix.vue +66 -183
  66. package/src/components/plan-review/PlanReview.vue +191 -275
  67. package/src/components/plan-version-editor/PlanCatalogPreview.vue +7 -5
  68. package/src/components/plan-version-editor/PlanVersionEditor.vue +200 -295
  69. package/src/components/plan-version-editor/PlanVersionEditorHeader.vue +23 -55
  70. package/src/index.ts +1 -0
  71. package/src/pages-standard/AdminLayout.vue +34 -10
  72. package/src/pages-standard/AdminManifestErrorPage.vue +79 -9
  73. package/src/pages-standard/AuditPage.vue +53 -72
  74. package/src/pages-standard/BundlesPage.vue +128 -144
  75. package/src/pages-standard/DashboardPage.vue +43 -107
  76. package/src/pages-standard/DiscoveryPage.vue +158 -200
  77. package/src/pages-standard/EmailHistoryPage.vue +98 -88
  78. package/src/pages-standard/MarketingCatalogPage.vue +237 -267
  79. package/src/pages-standard/PilotsPage.vue +44 -60
  80. package/src/pages-standard/PlansPage.vue +230 -105
  81. package/src/pages-standard/PlatformEmailPage.vue +37 -40
  82. package/src/pages-standard/PromoCodeDetailPage.vue +16 -30
  83. package/src/pages-standard/PromoCodesPage.vue +86 -112
  84. package/src/pages-standard/SubscriptionsPage.vue +10 -17
  85. package/src/pages-standard/SuperAdminLoginPage.vue +12 -12
  86. package/src/pages-standard/SuperAdminSetupWizard.vue +20 -17
  87. package/src/pages-standard/TenantDetailPage.vue +45 -41
  88. package/src/pages-standard/TenantsPage.vue +184 -264
  89. package/src/pages-standard/UsersPage.vue +69 -104
  90. package/src/pages-standard/bundles-page/BundleAccordionList.vue +20 -17
  91. package/src/pages-standard/bundles-page/BundlesKpis.vue +13 -22
  92. package/src/pages-standard/bundles-page/BundlesToolbar.vue +6 -10
  93. package/src/pages-standard/discovery-page/CatalogEntryTransPanel.vue +10 -10
  94. package/src/pages-standard/discovery-page/DiscoveryCapList.vue +5 -5
  95. package/src/pages-standard/discovery-page/DiscoveryFeatureCard.vue +16 -16
  96. package/src/pages-standard/discovery-page/DiscoveryKpis.vue +31 -27
  97. package/src/pages-standard/discovery-page/DiscoveryQuotaCard.vue +7 -7
  98. package/src/pages-standard/marketing-catalog/MarketingCatalogAdmin.vue +1 -1
  99. package/src/pages-standard/marketing-catalog/MarketingCatalogHeader.vue +2 -13
  100. package/src/pages-standard/plan-versions/PlanDiffCard.vue +6 -6
  101. package/src/pages-standard/plan-versions/PlanVersionsDiff.vue +6 -6
  102. package/src/pages-standard/plan-versions/PlanVersionsTimeline.vue +16 -16
  103. package/src/pages-standard/plans-page/PlanBundleOverview.vue +14 -29
  104. package/src/pages-standard/plans-page/PlanPublishDialog.vue +1 -1
  105. package/src/pages-standard/plans-page/PlansPageToast.vue +1 -1
  106. package/src/pages-standard/sa-theme.css +481 -71
  107. package/src/pages-standard/tenant-detail/TenantUsers.vue +2 -8
  108. package/src/pages-standard/tenants/StatusPill.vue +2 -2
  109. package/src/pages-tenant/MySubscriptionBundlesPage.vue +25 -25
  110. package/src/pages-tenant/OnboardingConfigurator.vue +1 -5
  111. package/src/pages-tenant/PackageSnapshotPanel.vue +1 -1
  112. package/src/pages-tenant/TenantPlanSection.vue +12 -20
  113. package/src/quasar/create-super-admin-app.ts +4 -0
  114. package/src/vue/entitlement-provider.ts +0 -1
  115. package/src/vue/feature-router-guard.ts +0 -1
  116. package/src/vue/super-admin-context.ts +106 -1
  117. package/src/vue/use-api-list.ts +2 -1
  118. package/src/vue/use-pagination.ts +63 -0
  119. package/src/vue/use-plans.ts +1 -2
  120. package/src/vue/use-sign-out.ts +90 -0
  121. package/src/vue/use-tenant-billing.ts +1 -1
  122. package/src/vue/use-tenant-manifest.ts +0 -1
  123. package/src/components/KpiCard.vue +0 -53
  124. package/src/components/plan-cockpit/PlanCockpit.vue +0 -1027
  125. package/src/components/plan-cockpit/PlanCockpitAuditLog.vue +0 -72
  126. package/src/components/plan-cockpit/PlanCockpitDiffPanel.vue +0 -99
  127. package/src/components/plan-cockpit/PlanCockpitHeader.vue +0 -101
  128. package/src/components/plan-cockpit/PlanCockpitImpactPanel.vue +0 -112
  129. package/src/components/plan-cockpit/PlanCockpitKpis.vue +0 -68
  130. package/src/components/plan-cockpit/PlanCockpitVersions.vue +0 -249
  131. package/src/components/plan-cockpit/types.ts +0 -72
  132. package/src/components/plan-detail/PlanDetailHeader.vue +0 -194
@@ -39,6 +39,7 @@ __export(client_exports, {
39
39
  SA_MESSAGES: () => SA_MESSAGES,
40
40
  buildRoutes: () => buildRoutes,
41
41
  buildSidebar: () => buildSidebar,
42
+ countPlans: () => countPlans,
42
43
  createAdminResourceClient: () => createAdminResourceClient,
43
44
  createSaCatalog: () => createSaCatalog,
44
45
  defaultHttpClient: () => defaultHttpClient,
@@ -48,6 +49,9 @@ __export(client_exports, {
48
49
  formatCurrency: () => formatCurrency,
49
50
  formatMessage: () => formatMessage,
50
51
  getJson: () => getJson,
52
+ isCurrentlyValid: () => isCurrentlyValid,
53
+ isExpired: () => isExpired,
54
+ isFutureScheduled: () => isFutureScheduled,
51
55
  isProductionBoot: () => isProductionBoot,
52
56
  isSaBuiltinLocale: () => isSaBuiltinLocale,
53
57
  mergeMessages: () => mergeMessages,
@@ -55,6 +59,8 @@ __export(client_exports, {
55
59
  resolveExtension: () => resolveExtension,
56
60
  resolveLoginBranding: () => resolveLoginBranding,
57
61
  resolveMessages: () => resolveMessages,
62
+ resolvePlans: () => resolvePlans,
63
+ todayIsoDate: () => todayIsoDate,
58
64
  trimTrailingSlashes: () => trimTrailingSlashes
59
65
  });
60
66
  module.exports = __toCommonJS(client_exports);
@@ -233,7 +239,7 @@ var ManifestLoader = class {
233
239
  if (res.status !== 200) {
234
240
  throw new ManifestLoadError(
235
241
  res.status,
236
- `Manifest-Endpunkt antwortete HTTP ${res.status}`
242
+ `Manifest endpoint responded with HTTP ${res.status}`
237
243
  );
238
244
  }
239
245
  const body = await res.json();
@@ -839,8 +845,7 @@ var bundlesMessages = defineMessages(
839
845
  title: "Bundles",
840
846
  subtitle: "Produktgruppen aus Features & Quotas \u2014 verwendet in Pl\xE4nen. Bundles werden im SuperAdmin kuratiert.",
841
847
  displayLocale: "Anzeige-Sprache",
842
- newBundle: "Neues Bundle",
843
- reload: "Liste neu laden"
848
+ newBundle: "Neues Bundle"
844
849
  },
845
850
  filter: {
846
851
  all: "Alle Status",
@@ -1054,8 +1059,7 @@ var bundlesMessages = defineMessages(
1054
1059
  title: "Bundles",
1055
1060
  subtitle: "Product groups made of features & quotas \u2014 used in plans. Bundles are curated in the SuperAdmin.",
1056
1061
  displayLocale: "Display language",
1057
- newBundle: "New bundle",
1058
- reload: "Reload list"
1062
+ newBundle: "New bundle"
1059
1063
  },
1060
1064
  filter: {
1061
1065
  all: "All statuses",
@@ -1255,6 +1259,8 @@ var commonMessages = defineMessages(
1255
1259
  saving: "Speichere \u2026",
1256
1260
  loadingData: "Daten werden geladen\u2026",
1257
1261
  noData: "Keine Daten vorhanden",
1262
+ filters: "Filter",
1263
+ results: "Ergebnisse",
1258
1264
  error: "Fehler",
1259
1265
  errorLoadFailed: "Laden fehlgeschlagen",
1260
1266
  errorSaveFailed: "Speichern fehlgeschlagen",
@@ -1300,7 +1306,16 @@ var commonMessages = defineMessages(
1300
1306
  unlimited: "unbegrenzt",
1301
1307
  both: "Beide",
1302
1308
  createFailed: "Anlegen fehlgeschlagen",
1303
- noChanges: "Keine \xC4nderungen"
1309
+ noChanges: "Keine \xC4nderungen",
1310
+ paginator: {
1311
+ label: "Seitennavigation",
1312
+ rowsPerPage: "Zeilen pro Seite",
1313
+ all: "Alle",
1314
+ page: "Seite {page}/{pages}",
1315
+ pageInput: "Seite, 1 bis {pages}",
1316
+ previous: "Vorherige Seite",
1317
+ next: "N\xE4chste Seite"
1318
+ }
1304
1319
  },
1305
1320
  {
1306
1321
  save: "Save",
@@ -1326,6 +1341,8 @@ var commonMessages = defineMessages(
1326
1341
  saving: "Saving \u2026",
1327
1342
  loadingData: "Loading data\u2026",
1328
1343
  noData: "No data available",
1344
+ filters: "Filters",
1345
+ results: "Results",
1329
1346
  error: "Error",
1330
1347
  errorLoadFailed: "Failed to load",
1331
1348
  errorSaveFailed: "Failed to save",
@@ -1371,7 +1388,16 @@ var commonMessages = defineMessages(
1371
1388
  unlimited: "unlimited",
1372
1389
  both: "Both",
1373
1390
  createFailed: "Creation failed",
1374
- noChanges: "No changes"
1391
+ noChanges: "No changes",
1392
+ paginator: {
1393
+ label: "Pagination",
1394
+ rowsPerPage: "Rows per page",
1395
+ all: "All",
1396
+ page: "Page {page}/{pages}",
1397
+ pageInput: "Page, 1 to {pages}",
1398
+ previous: "Previous page",
1399
+ next: "Next page"
1400
+ }
1375
1401
  }
1376
1402
  );
1377
1403
 
@@ -1476,7 +1502,7 @@ var discoveryMessages = defineMessages(
1476
1502
  quota: {
1477
1503
  usageProvider: "UsageProvider",
1478
1504
  usageProviderMissing: "fehlt",
1479
- noUsageProviderWarning: "Eine harte Quota ohne UsageProvider ist nicht deploy-f\xE4hig (Preflight, SPEC_V2 \xA76.3).",
1505
+ noUsageProviderWarning: "Eine harte Quota ohne UsageProvider ist nicht deploy-f\xE4hig (Preflight).",
1480
1506
  outdatedBanner: "Die code-abgeleiteten Quota-Fakten (Einheit/Enforcement/Provider) haben sich seit der letzten Freigabe ge\xE4ndert \u2014 bitte pr\xFCfen und"
1481
1507
  },
1482
1508
  caps: {
@@ -1580,7 +1606,7 @@ var discoveryMessages = defineMessages(
1580
1606
  quota: {
1581
1607
  usageProvider: "UsageProvider",
1582
1608
  usageProviderMissing: "missing",
1583
- noUsageProviderWarning: "A hard quota without a UsageProvider is not deployable (preflight, SPEC_V2 \xA76.3).",
1609
+ noUsageProviderWarning: "A hard quota without a UsageProvider is not deployable (preflight).",
1584
1610
  outdatedBanner: "The code-derived quota facts (unit/enforcement/provider) have changed since the last approval \u2014 please review and"
1585
1611
  },
1586
1612
  caps: {
@@ -1740,8 +1766,7 @@ var marketingMessages = defineMessages(
1740
1766
  localesLabel: "Sprachen:",
1741
1767
  defaultLocale: "Default-Sprache",
1742
1768
  deactivateLocale: "Sprache deaktivieren",
1743
- addLocale: "+ Sprache",
1744
- refresh: "Aktualisieren"
1769
+ addLocale: "+ Sprache"
1745
1770
  },
1746
1771
  page: {
1747
1772
  loading: "Lade Marketing-Catalog \u2026",
@@ -1809,7 +1834,7 @@ var marketingMessages = defineMessages(
1809
1834
  },
1810
1835
  promotionsTab: {
1811
1836
  title: "Aktionen & Rabatte",
1812
- subtitle: "Zeitlich begrenzte Preis-Aktionen \u2014 \xFCberschreiben den regul\xE4ren Preis auf der Pricing-Page (SPEC_V2 \xA79a).",
1837
+ subtitle: "Zeitlich begrenzte Preis-Aktionen \u2014 \xFCberschreiben den regul\xE4ren Preis auf der Pricing-Page.",
1813
1838
  add: "+ Aktion anlegen",
1814
1839
  timelineHead: "Aktions-Timeline \xB7 gestrichelt = heute",
1815
1840
  today: "heute",
@@ -1868,8 +1893,7 @@ var marketingMessages = defineMessages(
1868
1893
  localesLabel: "Languages:",
1869
1894
  defaultLocale: "Default language",
1870
1895
  deactivateLocale: "Deactivate language",
1871
- addLocale: "+ Language",
1872
- refresh: "Refresh"
1896
+ addLocale: "+ Language"
1873
1897
  },
1874
1898
  page: {
1875
1899
  loading: "Loading marketing catalog \u2026",
@@ -1937,7 +1961,7 @@ var marketingMessages = defineMessages(
1937
1961
  },
1938
1962
  promotionsTab: {
1939
1963
  title: "Promotions & discounts",
1940
- subtitle: "Time-limited price promotions \u2014 they override the regular price on the pricing page (SPEC_V2 \xA79a).",
1964
+ subtitle: "Time-limited price promotions \u2014 they override the regular price on the pricing page.",
1941
1965
  add: "+ Create promotion",
1942
1966
  timelineHead: "Promotion timeline \xB7 dashed = today",
1943
1967
  today: "today",
@@ -2202,10 +2226,8 @@ var planDetailMessages = defineMessages(
2202
2226
  versionsSummary: "{published} live/superseded",
2203
2227
  versionsSummaryWithDrafts: "{published} live/superseded \xB7 {drafts} Draft",
2204
2228
  openDraft: "Offener Draft",
2205
- noDraft: "Kein Draft",
2206
2229
  readyToEdit: "Bereit zum Bearbeiten",
2207
- noOpenDraft: "Keine Draft-Version offen",
2208
- createNewDraft: "Neue Draft anlegen"
2230
+ noOpenDraft: "Keine Draft-Version offen"
2209
2231
  },
2210
2232
  versions: {
2211
2233
  title: "Versionen",
@@ -2329,10 +2351,8 @@ var planDetailMessages = defineMessages(
2329
2351
  versionsSummary: "{published} live/superseded",
2330
2352
  versionsSummaryWithDrafts: "{published} live/superseded \xB7 {drafts} draft",
2331
2353
  openDraft: "Open draft",
2332
- noDraft: "No draft",
2333
2354
  readyToEdit: "Ready to edit",
2334
- noOpenDraft: "No draft version open",
2335
- createNewDraft: "Create a new draft"
2355
+ noOpenDraft: "No draft version open"
2336
2356
  },
2337
2357
  versions: {
2338
2358
  title: "Versions",
@@ -2719,6 +2739,7 @@ var plansMessages = defineMessages(
2719
2739
  // PlansPage — shell of the plan area: loading state, toasts and the
2720
2740
  // error texts of the draft/publish/archive/discard actions.
2721
2741
  page: {
2742
+ subtitle: "Pl\xE4ne b\xFCndeln Features & Quotas zu einem Angebot. Jede \xC4nderung wird als neue Version ver\xF6ffentlicht \u2014 Live-Versionen bleiben unangetastet.",
2722
2743
  loading: "Pl\xE4ne werden geladen\u2026",
2723
2744
  toastPlanCreated: "Plan {planKey} angelegt \u2014 jetzt die erste Version zusammenstellen.",
2724
2745
  toastDraftSaved: "Draft v{version} von {planKey} gespeichert.",
@@ -2765,7 +2786,10 @@ var plansMessages = defineMessages(
2765
2786
  // PlanList — default plan overview with one row per plan.
2766
2787
  list: {
2767
2788
  title: "Alle Pl\xE4ne",
2768
- summary: "{plans} Pl\xE4ne \xB7 {live} live \xB7 {drafts} offene Drafts \xB7 {tenants} Mandanten zugeordnet",
2789
+ statPlans: "Pl\xE4ne",
2790
+ statLive: "Live",
2791
+ statDrafts: "Offene Drafts",
2792
+ statTenants: "Mandanten",
2769
2793
  matrixView: "Matrix-Ansicht",
2770
2794
  newPlan: "Neuer Plan",
2771
2795
  searchPlaceholder: "Plan suchen\u2026",
@@ -2803,7 +2827,10 @@ var plansMessages = defineMessages(
2803
2827
  // PlanMatrix — all plans side by side, components as rows.
2804
2828
  matrix: {
2805
2829
  title: "Pl\xE4ne \xB7 Matrix-Vergleich",
2806
- summary: "Alle Pl\xE4ne nebeneinander \xB7 {plans} Pl\xE4ne \xB7 {features} Features \xB7 {quotas} Quotas \xB7 {bundles} Bundles",
2830
+ statPlans: "Pl\xE4ne",
2831
+ statFeatures: "Features",
2832
+ statQuotas: "Quotas",
2833
+ statBundles: "Bundles",
2807
2834
  catalogPreview: "Catalog-Vorschau",
2808
2835
  createPlan: "Plan anlegen",
2809
2836
  createPlanSub: "oder Klon erstellen",
@@ -2944,6 +2971,7 @@ var plansMessages = defineMessages(
2944
2971
  },
2945
2972
  {
2946
2973
  page: {
2974
+ subtitle: "Plans bundle features & quotas into an offering. Every change ships as a new version \u2014 live versions stay untouched.",
2947
2975
  loading: "Loading plans\u2026",
2948
2976
  toastPlanCreated: "Plan {planKey} created \u2014 now assemble the first version.",
2949
2977
  toastDraftSaved: "Draft v{version} of {planKey} saved.",
@@ -2988,7 +3016,10 @@ var plansMessages = defineMessages(
2988
3016
  },
2989
3017
  list: {
2990
3018
  title: "All plans",
2991
- summary: "{plans} plans \xB7 {live} live \xB7 {drafts} open drafts \xB7 {tenants} tenants assigned",
3019
+ statPlans: "Plans",
3020
+ statLive: "Live",
3021
+ statDrafts: "Open drafts",
3022
+ statTenants: "Tenants",
2992
3023
  matrixView: "Matrix view",
2993
3024
  newPlan: "New plan",
2994
3025
  searchPlaceholder: "Search plan\u2026",
@@ -3025,7 +3056,10 @@ var plansMessages = defineMessages(
3025
3056
  },
3026
3057
  matrix: {
3027
3058
  title: "Plans \xB7 matrix comparison",
3028
- summary: "All plans side by side \xB7 {plans} plans \xB7 {features} features \xB7 {quotas} quotas \xB7 {bundles} bundles",
3059
+ statPlans: "Plans",
3060
+ statFeatures: "Features",
3061
+ statQuotas: "Quotas",
3062
+ statBundles: "Bundles",
3029
3063
  catalogPreview: "Catalog preview",
3030
3064
  createPlan: "Create plan",
3031
3065
  createPlanSub: "or create a clone",
@@ -3514,8 +3548,7 @@ var tenantsMessages = defineMessages(
3514
3548
  columnUsage: "Verbrauch",
3515
3549
  columnCreatedAt: "Angelegt",
3516
3550
  suspended: "Suspendiert",
3517
- empty: "Keine Mandanten mit diesen Filtern.",
3518
- pagination: "{total} Mandanten \xB7 Seite {page} / {pages}"
3551
+ empty: "Keine Mandanten mit diesen Filtern."
3519
3552
  },
3520
3553
  detail: {
3521
3554
  backToList: "Mandanten-Liste",
@@ -3563,8 +3596,7 @@ var tenantsMessages = defineMessages(
3563
3596
  columnUsage: "Usage",
3564
3597
  columnCreatedAt: "Created",
3565
3598
  suspended: "Suspended",
3566
- empty: "No tenants match these filters.",
3567
- pagination: "{total} tenants \xB7 Page {page} / {pages}"
3599
+ empty: "No tenants match these filters."
3568
3600
  },
3569
3601
  detail: {
3570
3602
  backToList: "Tenant list",
@@ -3759,6 +3791,71 @@ function resolveLoginBranding(boot, fallback = {}) {
3759
3791
  function isProductionBoot(boot) {
3760
3792
  return boot?.project?.environment === "production";
3761
3793
  }
3794
+
3795
+ // src/client/resolve-plans.ts
3796
+ function todayIsoDate() {
3797
+ return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
3798
+ }
3799
+ function isCurrentlyValid(v, today) {
3800
+ if (!v.publishedAt) return false;
3801
+ if (v.validFrom && v.validFrom.slice(0, 10) > today) return false;
3802
+ if (v.validUntil && v.validUntil.slice(0, 10) < today) return false;
3803
+ return true;
3804
+ }
3805
+ function isFutureScheduled(v, today) {
3806
+ if (!v.publishedAt) return false;
3807
+ if (!v.validFrom) return false;
3808
+ return v.validFrom.slice(0, 10) > today;
3809
+ }
3810
+ function isExpired(v, today) {
3811
+ if (!v.publishedAt) return false;
3812
+ if (!v.validUntil) return false;
3813
+ return v.validUntil.slice(0, 10) < today;
3814
+ }
3815
+ function resolvePlans({
3816
+ plans,
3817
+ versionsByPlanId,
3818
+ tenantCountsByPlanKey,
3819
+ today = todayIsoDate()
3820
+ }) {
3821
+ return [...plans].sort((a, b) => a.sortOrder - b.sortOrder || a.planKey.localeCompare(b.planKey)).map((plan) => {
3822
+ const versions = versionsByPlanId[plan.id] ?? [];
3823
+ const drafts = versions.filter((v) => !v.publishedAt);
3824
+ const published = versions.filter((v) => Boolean(v.publishedAt));
3825
+ const currentLive = published.find((v) => isCurrentlyValid(v, today)) ?? null;
3826
+ const futureScheduled = published.filter((v) => isFutureScheduled(v, today)).sort((a, b) => (a.validFrom ?? "").localeCompare(b.validFrom ?? ""));
3827
+ const primary = currentLive ?? futureScheduled[0] ?? null;
3828
+ const seen = /* @__PURE__ */ new Set();
3829
+ if (primary) seen.add(primary.id);
3830
+ const subRows = [];
3831
+ for (const v of [...futureScheduled, ...drafts]) {
3832
+ if (seen.has(v.id)) continue;
3833
+ subRows.push(v);
3834
+ seen.add(v.id);
3835
+ }
3836
+ return {
3837
+ plan,
3838
+ planKey: plan.planKey,
3839
+ label: plan.label,
3840
+ description: plan.description ?? null,
3841
+ currentLive,
3842
+ primary,
3843
+ subRows,
3844
+ hasAnyVersion: versions.length > 0,
3845
+ allExpired: versions.length > 0 && drafts.length === 0 && futureScheduled.length === 0 && published.every((v) => isExpired(v, today)),
3846
+ draft: drafts[0] ?? null,
3847
+ tenantCount: tenantCountsByPlanKey[plan.planKey] ?? 0
3848
+ };
3849
+ });
3850
+ }
3851
+ function countPlans(resolved) {
3852
+ return {
3853
+ plans: resolved.length,
3854
+ live: resolved.filter((p) => p.currentLive !== null).length,
3855
+ drafts: resolved.filter((p) => p.draft !== null).length,
3856
+ tenants: resolved.reduce((sum, p) => sum + p.tenantCount, 0)
3857
+ };
3858
+ }
3762
3859
  // Annotate the CommonJS export names for ESM import in node:
3763
3860
  0 && (module.exports = {
3764
3861
  ADMIN_UI_VERSION,
@@ -3780,6 +3877,7 @@ function isProductionBoot(boot) {
3780
3877
  SA_MESSAGES,
3781
3878
  buildRoutes,
3782
3879
  buildSidebar,
3880
+ countPlans,
3783
3881
  createAdminResourceClient,
3784
3882
  createSaCatalog,
3785
3883
  defaultHttpClient,
@@ -3789,6 +3887,9 @@ function isProductionBoot(boot) {
3789
3887
  formatCurrency,
3790
3888
  formatMessage,
3791
3889
  getJson,
3890
+ isCurrentlyValid,
3891
+ isExpired,
3892
+ isFutureScheduled,
3792
3893
  isProductionBoot,
3793
3894
  isSaBuiltinLocale,
3794
3895
  mergeMessages,
@@ -3796,5 +3897,7 @@ function isProductionBoot(boot) {
3796
3897
  resolveExtension,
3797
3898
  resolveLoginBranding,
3798
3899
  resolveMessages,
3900
+ resolvePlans,
3901
+ todayIsoDate,
3799
3902
  trimTrailingSlashes
3800
3903
  });
@@ -1,5 +1,5 @@
1
- import { H as HttpClient, K as KvStore, S as SaLocale, w as SaNavMessages } from '../catalog-BY_t9prv.cjs';
2
- export { f as ActionDefNotInManifestError, A as ActionHandler, e as ActionRegistry, D as DEFAULT_SA_LOCALE, g as HttpResponse, M as MessageTree, h as MissingHandlerError, P as PartialMessages, R as ResolvedAction, i as SA_INTL_LOCALES, j as SA_LOCALES, k as SA_LOCALE_LABELS, l as SA_MESSAGES, m as SaBuiltinLocale, n as SaCatalog, o as SaCatalogOptions, c as SaLocaleDefinition, b as SaLocaleOption, a as SaMessages, d as SaMessagesOverrides, T as TranslationOf, p as createSaCatalog, q as defaultHttpClient, r as defaultKvStore, s as defineMessages, t as isSaBuiltinLocale, u as mergeMessages, v as resolveMessages } from '../catalog-BY_t9prv.cjs';
1
+ import { H as HttpClient, K as KvStore, S as SaLocale, w as SaNavMessages } from '../catalog-DJcfm5N2.cjs';
2
+ export { f as ActionDefNotInManifestError, A as ActionHandler, e as ActionRegistry, D as DEFAULT_SA_LOCALE, g as HttpResponse, M as MessageTree, h as MissingHandlerError, P as PartialMessages, R as ResolvedAction, i as SA_INTL_LOCALES, j as SA_LOCALES, k as SA_LOCALE_LABELS, l as SA_MESSAGES, m as SaBuiltinLocale, n as SaCatalog, o as SaCatalogOptions, c as SaLocaleDefinition, b as SaLocaleOption, a as SaMessages, d as SaMessagesOverrides, T as TranslationOf, p as createSaCatalog, q as defaultHttpClient, r as defaultKvStore, s as defineMessages, t as isSaBuiltinLocale, u as mergeMessages, v as resolveMessages } from '../catalog-DJcfm5N2.cjs';
3
3
  import { PublicBootResponse, AdminManifest, StandardPageKey, TenantColumnDef, PromoCodeRecord, AdminTenantDetail, AdminUserListFilter, AdminUserListRow, AdminAuditListFilter, AuditEntry, AdminSubscriptionListRow } from '@saasicat/types';
4
4
 
5
5
  declare const ADMIN_UI_VERSION = "1.2.0";
@@ -339,4 +339,54 @@ declare function isProductionBoot(boot: {
339
339
  project?: LoginBootProject | null;
340
340
  } | null | undefined): boolean;
341
341
 
342
- export { ADMIN_UI_VERSION, type AdminPromoListFilter, type AdminPromoListRow, type AdminResourceClientOptions, type BatchColumnData, BatchColumnDriftError, BatchColumnFetcher, type BatchColumnFetcherOptions, type BatchColumnRow, type BatchColumnValue, BootLoadError, BootLoader, type BootLoaderOptions, type BuildRouteEntry, type CachedManifestEntry, DEFAULT_STANDARD_PAGE_ROUTES, HttpClient, HttpJsonError, KvStore, type LoginBootProject, type LoginBrandFallback, type LoginBranding, ManifestLoadError, ManifestLoader, type ManifestLoaderOptions, type MessageParams, type NavBuilderOptions, type ParamStyle, SaLocale, type SidebarItem, type SidebarSection, buildRoutes, buildSidebar, createAdminResourceClient, defaultSectionOrder, formatCurrency, formatMessage, getJson, isProductionBoot, postJson, resolveExtension, resolveLoginBranding, trimTrailingSlashes };
342
+ interface PlanRowLike {
343
+ id: string;
344
+ planKey: string;
345
+ label: string;
346
+ description?: string | null;
347
+ sortOrder: number;
348
+ }
349
+ interface PlanVersionLike {
350
+ id: string;
351
+ publishedAt?: string | null;
352
+ validFrom?: string | null;
353
+ validUntil?: string | null;
354
+ }
355
+ interface ResolvedPlan<P extends PlanRowLike, V extends PlanVersionLike> {
356
+ plan: P;
357
+ planKey: string;
358
+ label: string;
359
+ description: string | null;
360
+ /** Version currently active for new bookings. */
361
+ currentLive: V | null;
362
+ /** Version shown on the parent row — the live one where there is one. */
363
+ primary: V | null;
364
+ /** Future-published versions first, then drafts. */
365
+ subRows: V[];
366
+ hasAnyVersion: boolean;
367
+ /** Every version has run out: hidden from the admin listing. */
368
+ allExpired: boolean;
369
+ draft: V | null;
370
+ tenantCount: number;
371
+ }
372
+ declare function todayIsoDate(): string;
373
+ declare function isCurrentlyValid(v: PlanVersionLike, today: string): boolean;
374
+ declare function isFutureScheduled(v: PlanVersionLike, today: string): boolean;
375
+ declare function isExpired(v: PlanVersionLike, today: string): boolean;
376
+ interface ResolvePlansInput<P extends PlanRowLike, V extends PlanVersionLike> {
377
+ plans: readonly P[];
378
+ versionsByPlanId: Record<string, V[]>;
379
+ tenantCountsByPlanKey: Record<string, number>;
380
+ /** Injectable for tests; defaults to today. */
381
+ today?: string;
382
+ }
383
+ declare function resolvePlans<P extends PlanRowLike, V extends PlanVersionLike>({ plans, versionsByPlanId, tenantCountsByPlanKey, today, }: ResolvePlansInput<P, V>): ResolvedPlan<P, V>[];
384
+ interface PlanCounts {
385
+ plans: number;
386
+ live: number;
387
+ drafts: number;
388
+ tenants: number;
389
+ }
390
+ declare function countPlans<P extends PlanRowLike, V extends PlanVersionLike>(resolved: readonly ResolvedPlan<P, V>[]): PlanCounts;
391
+
392
+ export { ADMIN_UI_VERSION, type AdminPromoListFilter, type AdminPromoListRow, type AdminResourceClientOptions, type BatchColumnData, BatchColumnDriftError, BatchColumnFetcher, type BatchColumnFetcherOptions, type BatchColumnRow, type BatchColumnValue, BootLoadError, BootLoader, type BootLoaderOptions, type BuildRouteEntry, type CachedManifestEntry, DEFAULT_STANDARD_PAGE_ROUTES, HttpClient, HttpJsonError, KvStore, type LoginBootProject, type LoginBrandFallback, type LoginBranding, ManifestLoadError, ManifestLoader, type ManifestLoaderOptions, type MessageParams, type NavBuilderOptions, type ParamStyle, type PlanCounts, type PlanRowLike, type PlanVersionLike, type ResolvePlansInput, type ResolvedPlan, SaLocale, type SidebarItem, type SidebarSection, buildRoutes, buildSidebar, countPlans, createAdminResourceClient, defaultSectionOrder, formatCurrency, formatMessage, getJson, isCurrentlyValid, isExpired, isFutureScheduled, isProductionBoot, postJson, resolveExtension, resolveLoginBranding, resolvePlans, todayIsoDate, trimTrailingSlashes };
@@ -1,5 +1,5 @@
1
- import { H as HttpClient, K as KvStore, S as SaLocale, w as SaNavMessages } from '../catalog-BY_t9prv.js';
2
- export { f as ActionDefNotInManifestError, A as ActionHandler, e as ActionRegistry, D as DEFAULT_SA_LOCALE, g as HttpResponse, M as MessageTree, h as MissingHandlerError, P as PartialMessages, R as ResolvedAction, i as SA_INTL_LOCALES, j as SA_LOCALES, k as SA_LOCALE_LABELS, l as SA_MESSAGES, m as SaBuiltinLocale, n as SaCatalog, o as SaCatalogOptions, c as SaLocaleDefinition, b as SaLocaleOption, a as SaMessages, d as SaMessagesOverrides, T as TranslationOf, p as createSaCatalog, q as defaultHttpClient, r as defaultKvStore, s as defineMessages, t as isSaBuiltinLocale, u as mergeMessages, v as resolveMessages } from '../catalog-BY_t9prv.js';
1
+ import { H as HttpClient, K as KvStore, S as SaLocale, w as SaNavMessages } from '../catalog-DJcfm5N2.js';
2
+ export { f as ActionDefNotInManifestError, A as ActionHandler, e as ActionRegistry, D as DEFAULT_SA_LOCALE, g as HttpResponse, M as MessageTree, h as MissingHandlerError, P as PartialMessages, R as ResolvedAction, i as SA_INTL_LOCALES, j as SA_LOCALES, k as SA_LOCALE_LABELS, l as SA_MESSAGES, m as SaBuiltinLocale, n as SaCatalog, o as SaCatalogOptions, c as SaLocaleDefinition, b as SaLocaleOption, a as SaMessages, d as SaMessagesOverrides, T as TranslationOf, p as createSaCatalog, q as defaultHttpClient, r as defaultKvStore, s as defineMessages, t as isSaBuiltinLocale, u as mergeMessages, v as resolveMessages } from '../catalog-DJcfm5N2.js';
3
3
  import { PublicBootResponse, AdminManifest, StandardPageKey, TenantColumnDef, PromoCodeRecord, AdminTenantDetail, AdminUserListFilter, AdminUserListRow, AdminAuditListFilter, AuditEntry, AdminSubscriptionListRow } from '@saasicat/types';
4
4
 
5
5
  declare const ADMIN_UI_VERSION = "1.2.0";
@@ -339,4 +339,54 @@ declare function isProductionBoot(boot: {
339
339
  project?: LoginBootProject | null;
340
340
  } | null | undefined): boolean;
341
341
 
342
- export { ADMIN_UI_VERSION, type AdminPromoListFilter, type AdminPromoListRow, type AdminResourceClientOptions, type BatchColumnData, BatchColumnDriftError, BatchColumnFetcher, type BatchColumnFetcherOptions, type BatchColumnRow, type BatchColumnValue, BootLoadError, BootLoader, type BootLoaderOptions, type BuildRouteEntry, type CachedManifestEntry, DEFAULT_STANDARD_PAGE_ROUTES, HttpClient, HttpJsonError, KvStore, type LoginBootProject, type LoginBrandFallback, type LoginBranding, ManifestLoadError, ManifestLoader, type ManifestLoaderOptions, type MessageParams, type NavBuilderOptions, type ParamStyle, SaLocale, type SidebarItem, type SidebarSection, buildRoutes, buildSidebar, createAdminResourceClient, defaultSectionOrder, formatCurrency, formatMessage, getJson, isProductionBoot, postJson, resolveExtension, resolveLoginBranding, trimTrailingSlashes };
342
+ interface PlanRowLike {
343
+ id: string;
344
+ planKey: string;
345
+ label: string;
346
+ description?: string | null;
347
+ sortOrder: number;
348
+ }
349
+ interface PlanVersionLike {
350
+ id: string;
351
+ publishedAt?: string | null;
352
+ validFrom?: string | null;
353
+ validUntil?: string | null;
354
+ }
355
+ interface ResolvedPlan<P extends PlanRowLike, V extends PlanVersionLike> {
356
+ plan: P;
357
+ planKey: string;
358
+ label: string;
359
+ description: string | null;
360
+ /** Version currently active for new bookings. */
361
+ currentLive: V | null;
362
+ /** Version shown on the parent row — the live one where there is one. */
363
+ primary: V | null;
364
+ /** Future-published versions first, then drafts. */
365
+ subRows: V[];
366
+ hasAnyVersion: boolean;
367
+ /** Every version has run out: hidden from the admin listing. */
368
+ allExpired: boolean;
369
+ draft: V | null;
370
+ tenantCount: number;
371
+ }
372
+ declare function todayIsoDate(): string;
373
+ declare function isCurrentlyValid(v: PlanVersionLike, today: string): boolean;
374
+ declare function isFutureScheduled(v: PlanVersionLike, today: string): boolean;
375
+ declare function isExpired(v: PlanVersionLike, today: string): boolean;
376
+ interface ResolvePlansInput<P extends PlanRowLike, V extends PlanVersionLike> {
377
+ plans: readonly P[];
378
+ versionsByPlanId: Record<string, V[]>;
379
+ tenantCountsByPlanKey: Record<string, number>;
380
+ /** Injectable for tests; defaults to today. */
381
+ today?: string;
382
+ }
383
+ declare function resolvePlans<P extends PlanRowLike, V extends PlanVersionLike>({ plans, versionsByPlanId, tenantCountsByPlanKey, today, }: ResolvePlansInput<P, V>): ResolvedPlan<P, V>[];
384
+ interface PlanCounts {
385
+ plans: number;
386
+ live: number;
387
+ drafts: number;
388
+ tenants: number;
389
+ }
390
+ declare function countPlans<P extends PlanRowLike, V extends PlanVersionLike>(resolved: readonly ResolvedPlan<P, V>[]): PlanCounts;
391
+
392
+ export { ADMIN_UI_VERSION, type AdminPromoListFilter, type AdminPromoListRow, type AdminResourceClientOptions, type BatchColumnData, BatchColumnDriftError, BatchColumnFetcher, type BatchColumnFetcherOptions, type BatchColumnRow, type BatchColumnValue, BootLoadError, BootLoader, type BootLoaderOptions, type BuildRouteEntry, type CachedManifestEntry, DEFAULT_STANDARD_PAGE_ROUTES, HttpClient, HttpJsonError, KvStore, type LoginBootProject, type LoginBrandFallback, type LoginBranding, ManifestLoadError, ManifestLoader, type ManifestLoaderOptions, type MessageParams, type NavBuilderOptions, type ParamStyle, type PlanCounts, type PlanRowLike, type PlanVersionLike, type ResolvePlansInput, type ResolvedPlan, SaLocale, type SidebarItem, type SidebarSection, buildRoutes, buildSidebar, countPlans, createAdminResourceClient, defaultSectionOrder, formatCurrency, formatMessage, getJson, isCurrentlyValid, isExpired, isFutureScheduled, isProductionBoot, postJson, resolveExtension, resolveLoginBranding, resolvePlans, todayIsoDate, trimTrailingSlashes };
@@ -13,15 +13,21 @@ import {
13
13
  MissingHandlerError,
14
14
  buildRoutes,
15
15
  buildSidebar,
16
+ countPlans,
16
17
  createAdminResourceClient,
17
18
  defaultSectionOrder,
18
19
  getJson,
20
+ isCurrentlyValid,
21
+ isExpired,
22
+ isFutureScheduled,
19
23
  isProductionBoot,
20
24
  postJson,
21
25
  resolveExtension,
22
26
  resolveLoginBranding,
27
+ resolvePlans,
28
+ todayIsoDate,
23
29
  trimTrailingSlashes
24
- } from "../chunk-OTP3OSSW.js";
30
+ } from "../chunk-XMMFN2WJ.js";
25
31
  import {
26
32
  DEFAULT_SA_LOCALE,
27
33
  SA_INTL_LOCALES,
@@ -37,7 +43,7 @@ import {
37
43
  isSaBuiltinLocale,
38
44
  mergeMessages,
39
45
  resolveMessages
40
- } from "../chunk-JN6HZGLV.js";
46
+ } from "../chunk-F7NRM6KI.js";
41
47
  export {
42
48
  ADMIN_UI_VERSION,
43
49
  ActionDefNotInManifestError,
@@ -58,6 +64,7 @@ export {
58
64
  SA_MESSAGES,
59
65
  buildRoutes,
60
66
  buildSidebar,
67
+ countPlans,
61
68
  createAdminResourceClient,
62
69
  createSaCatalog,
63
70
  defaultHttpClient,
@@ -67,6 +74,9 @@ export {
67
74
  formatCurrency,
68
75
  formatMessage,
69
76
  getJson,
77
+ isCurrentlyValid,
78
+ isExpired,
79
+ isFutureScheduled,
70
80
  isProductionBoot,
71
81
  isSaBuiltinLocale,
72
82
  mergeMessages,
@@ -74,5 +84,7 @@ export {
74
84
  resolveExtension,
75
85
  resolveLoginBranding,
76
86
  resolveMessages,
87
+ resolvePlans,
88
+ todayIsoDate,
77
89
  trimTrailingSlashes
78
90
  };