@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.
- package/README.md +64 -4
- package/dist/chunk-A3W2N26K.js +714 -0
- package/dist/chunk-QZOSDCNP.js +98 -0
- package/dist/chunk-X5SQ5HMB.js +3231 -0
- package/dist/client/index.cjs +3988 -0
- package/dist/client/index.d.cts +321 -0
- package/dist/client/index.d.ts +321 -0
- package/dist/client/index.js +70 -0
- package/dist/index.cjs +4446 -1249
- package/dist/index.d.cts +297 -888
- package/dist/index.d.ts +297 -888
- package/dist/index.js +609 -1348
- package/dist/messages-7b0P8W75.d.cts +1652 -0
- package/dist/messages-7b0P8W75.d.ts +1652 -0
- package/dist/quasar/index.cjs +3340 -0
- package/dist/quasar/index.d.cts +95 -0
- package/dist/quasar/index.d.ts +95 -0
- package/dist/quasar/index.js +96 -0
- package/dist/testing-e2e/admin-pages-suite.cjs +14 -11
- package/dist/testing-e2e/admin-pages-suite.js +14 -11
- package/dist/use-super-admin-i18n-B3v3-SWZ.d.ts +210 -0
- package/dist/use-super-admin-i18n-DMktRVEt.d.cts +210 -0
- package/package.json +23 -3
- package/src/{action-registry.ts → client/action-registry.ts} +4 -4
- package/src/{batch-column-fetcher.ts → client/batch-column-fetcher.ts} +4 -4
- package/src/{boot-loader.ts → client/boot-loader.ts} +3 -3
- package/src/client/i18n/currency.ts +42 -0
- package/src/client/i18n/define.ts +59 -0
- package/src/client/i18n/format.ts +12 -0
- package/src/client/i18n/index.ts +14 -0
- package/src/client/i18n/locale.ts +15 -0
- package/src/client/i18n/messages/audit.ts +42 -0
- package/src/client/i18n/messages/bundles.ts +459 -0
- package/src/client/i18n/messages/common.ts +147 -0
- package/src/client/i18n/messages/dashboard.ts +16 -0
- package/src/client/i18n/messages/discovery.ts +229 -0
- package/src/client/i18n/messages/email.ts +125 -0
- package/src/client/i18n/messages/marketing.ts +270 -0
- package/src/client/i18n/messages/nav.ts +72 -0
- package/src/client/i18n/messages/pilots.ts +192 -0
- package/src/client/i18n/messages/plan-detail.ts +266 -0
- package/src/client/i18n/messages/plan-editor.ts +177 -0
- package/src/client/i18n/messages/plan-versions.ts +251 -0
- package/src/client/i18n/messages/plans.ts +503 -0
- package/src/client/i18n/messages/promos.ts +202 -0
- package/src/client/i18n/messages/shell.ts +145 -0
- package/src/client/i18n/messages/tenants.ts +104 -0
- package/src/client/i18n/messages/users.ts +78 -0
- package/src/client/i18n/messages.ts +84 -0
- package/src/client/index.ts +27 -0
- package/src/{manifest-loader.ts → client/manifest-loader.ts} +4 -4
- package/src/{nav-builder.ts → client/nav-builder.ts} +44 -51
- package/src/{plan-versions-catalog.ts → client/plan-versions-catalog.ts} +42 -30
- package/src/components/BundleVersionPublishDialog.vue +35 -24
- package/src/components/FeatureGate.vue +1 -1
- package/src/components/MarketingPromotionsTab.vue +112 -59
- package/src/components/MfaPromptDialog.vue +11 -11
- package/src/components/TenantActionConfirmDialog.vue +19 -17
- package/src/components/VersionDiffPreview.vue +72 -43
- package/src/components/bundle-editor/BundleCreatePanel.vue +76 -63
- package/src/components/bundle-editor/BundleFeaturesEditor.vue +13 -6
- package/src/components/bundle-editor/BundlePlanCompatPicker.vue +19 -14
- package/src/components/bundle-editor/BundleQuotasEditor.vue +7 -4
- package/src/components/bundle-editor/BundleStatusBanner.vue +36 -19
- package/src/components/bundle-editor/BundleVersionInlineEditor.vue +51 -35
- package/src/components/bundle-editor/BundleVersionStrip.vue +24 -12
- package/src/components/bundle-editor/bundle-version-status.ts +29 -29
- package/src/components/dialogs/PilotCreateDialog.vue +58 -63
- package/src/components/dialogs/PilotEditDialog.vue +40 -34
- package/src/components/dialogs/PromoCodeCreateDialog.vue +89 -63
- package/src/components/dialogs/PromoCodeEditDialog.vue +98 -66
- package/src/components/dialogs/types.ts +3 -13
- package/src/components/plan/PlanCycleToggle.vue +21 -10
- package/src/components/plan/PlanGrid.vue +2 -2
- package/src/components/plan/PriceSummary.vue +1 -1
- package/src/components/plan/PromoCodeInput.vue +1 -1
- package/src/components/plan/PublicBundleGrid.vue +1 -1
- package/src/components/plan-cockpit/PlanCockpit.vue +34 -15
- package/src/components/plan-cockpit/PlanCockpitAuditLog.vue +13 -6
- package/src/components/plan-cockpit/PlanCockpitDiffPanel.vue +18 -9
- package/src/components/plan-cockpit/PlanCockpitHeader.vue +9 -6
- package/src/components/plan-cockpit/PlanCockpitImpactPanel.vue +24 -11
- package/src/components/plan-cockpit/PlanCockpitKpis.vue +28 -17
- package/src/components/plan-cockpit/PlanCockpitVersions.vue +50 -25
- package/src/components/plan-create-dialog/PlanCreateDialog.vue +45 -35
- package/src/components/plan-detail/PlanAuditLog.vue +11 -6
- package/src/components/plan-detail/PlanDetail.vue +21 -23
- package/src/components/plan-detail/PlanDetailHeader.vue +20 -11
- package/src/components/plan-detail/PlanDetailKpis.vue +30 -17
- package/src/components/plan-detail/PlanTerminateDialog.vue +22 -9
- package/src/components/plan-detail/PlanVersionDiffPanel.vue +61 -27
- package/src/components/plan-detail/PlanVersionsPanel.vue +71 -36
- package/src/components/plan-list/PlanList.vue +99 -57
- package/src/components/plan-matrix/PlanMatrix.vue +85 -38
- package/src/components/plan-review/PlanReview.vue +105 -80
- package/src/components/plan-version-editor/PlanCatalogPreview.vue +43 -20
- package/src/components/plan-version-editor/PlanComponentPool.vue +15 -7
- package/src/components/plan-version-editor/PlanVersionBasket.vue +45 -24
- package/src/components/plan-version-editor/PlanVersionDiffDialog.vue +8 -7
- package/src/components/plan-version-editor/PlanVersionEditor.vue +74 -40
- package/src/components/plan-version-editor/PlanVersionEditorHeader.vue +24 -12
- package/src/index.ts +82 -79
- package/src/pages-standard/AdminLayout.vue +43 -18
- package/src/pages-standard/AdminManifestErrorPage.vue +10 -10
- package/src/pages-standard/AuditPage.vue +58 -19
- package/src/pages-standard/BundlesPage.vue +29 -18
- package/src/pages-standard/DashboardPage.vue +31 -17
- package/src/pages-standard/DiscoveryPage.vue +40 -28
- package/src/pages-standard/EmailHistoryPage.vue +98 -69
- package/src/pages-standard/MarketingCatalogPage.vue +40 -21
- package/src/pages-standard/PilotsPage.vue +64 -52
- package/src/pages-standard/PlanVersionsPage.vue +9 -5
- package/src/pages-standard/PlansPage.vue +91 -59
- package/src/pages-standard/PlatformEmailPage.vue +120 -53
- package/src/pages-standard/PromoCodeDetailPage.vue +66 -63
- package/src/pages-standard/PromoCodesPage.vue +51 -54
- package/src/pages-standard/SubscriptionsPage.vue +14 -9
- package/src/pages-standard/SuperAdminLoginPage.vue +19 -16
- package/src/pages-standard/SuperAdminSetupWizard.vue +53 -49
- package/src/pages-standard/TenantDetailPage.vue +54 -40
- package/src/pages-standard/TenantsPage.vue +57 -44
- package/src/pages-standard/UsersPage.vue +70 -52
- package/src/pages-standard/bundles-page/BundleAccordionList.vue +20 -8
- package/src/pages-standard/bundles-page/BundleDetailPanel.vue +28 -18
- package/src/pages-standard/bundles-page/BundlesFilterBar.vue +4 -1
- package/src/pages-standard/bundles-page/BundlesHeader.vue +9 -8
- package/src/pages-standard/bundles-page/BundlesKpis.vue +29 -11
- package/src/pages-standard/discovery-page/CatalogEntryTransPanel.vue +20 -8
- package/src/pages-standard/discovery-page/DiscoveryCapList.vue +5 -3
- package/src/pages-standard/discovery-page/DiscoveryFeatureCard.vue +43 -24
- package/src/pages-standard/discovery-page/DiscoveryHeader.vue +7 -4
- package/src/pages-standard/discovery-page/DiscoveryKpis.vue +28 -15
- package/src/pages-standard/discovery-page/DiscoveryQuotaCard.vue +20 -10
- package/src/pages-standard/discovery-page/DiscoveryStatusControl.vue +9 -6
- package/src/pages-standard/discovery-page/discovery-ui.ts +40 -52
- package/src/pages-standard/marketing-catalog/MarketingCatalogAdmin.vue +81 -49
- package/src/pages-standard/marketing-catalog/MarketingCatalogHeader.vue +13 -10
- package/src/pages-standard/marketing-catalog/MarketingCatalogPreview.vue +24 -20
- package/src/pages-standard/marketing-catalog/MarketingCatalogToolbar.vue +6 -3
- package/src/pages-standard/plan-versions/PlanDiffCard.vue +16 -6
- package/src/pages-standard/plan-versions/PlanVersionHeader.vue +42 -26
- package/src/pages-standard/plan-versions/PlanVersionsAudit.vue +46 -27
- package/src/pages-standard/plan-versions/PlanVersionsDiff.vue +8 -6
- package/src/pages-standard/plan-versions/PlanVersionsList.vue +40 -17
- package/src/pages-standard/plan-versions/PlanVersionsMatrix.vue +1 -1
- package/src/pages-standard/plan-versions/PlanVersionsTimeline.vue +25 -13
- package/src/pages-standard/plan-versions/format.ts +33 -17
- package/src/pages-standard/plans-page/PlanArchiveDialog.vue +12 -8
- package/src/pages-standard/plans-page/PlanBundleOverview.vue +15 -6
- package/src/pages-standard/plans-page/PlanDiscardDraftDialog.vue +18 -7
- package/src/pages-standard/plans-page/PlanPublishDialog.vue +23 -12
- package/src/pages-standard/tenants/format.ts +3 -2
- package/src/pages-tenant/MySubscriptionBundlesPage.vue +73 -38
- package/src/pages-tenant/OnboardingConfigurator.vue +3 -3
- package/src/pages-tenant/PackageSnapshotPanel.vue +1 -1
- package/src/pages-tenant/PlanChangeWizard.vue +10 -6
- package/src/pages-tenant/TenantPlanSection.vue +20 -16
- package/src/pages-tenant/default-i18n.ts +217 -1
- package/src/pages-tenant/tenant-plan-section/BundlePreviewDialog.vue +9 -7
- package/src/pages-tenant/tenant-plan-section/TenantBundleStore.vue +11 -12
- package/src/pages-tenant/tenant-plan-section/TenantFeatureMatrix.vue +4 -1
- package/src/pages-tenant/tenant-plan-section/TenantPlanCardHeader.vue +1 -1
- package/src/pages-tenant/tenant-plan-section/TenantUsageGrid.vue +1 -1
- package/src/quasar/create-super-admin-app.ts +192 -0
- package/src/quasar/index.ts +11 -0
- package/src/quasar/notify.ts +30 -0
- package/src/testing-e2e/admin-pages-suite.ts +14 -11
- package/src/{manifest-store-factory.ts → vue/manifest-store-factory.ts} +1 -1
- package/src/{platform-loaders.ts → vue/platform-loaders.ts} +4 -4
- package/src/{project-page-host.ts → vue/project-page-host.ts} +6 -4
- package/src/{create-super-admin-app.ts → vue/super-admin-context.ts} +20 -139
- package/src/vue/ui-notify.ts +30 -0
- package/src/{use-actions.ts → vue/use-actions.ts} +1 -1
- package/src/{use-api-list.ts → vue/use-api-list.ts} +1 -1
- package/src/{use-audit-entries.ts → vue/use-audit-entries.ts} +3 -3
- package/src/{use-batch-columns.ts → vue/use-batch-columns.ts} +1 -1
- package/src/{use-bulk-publish.ts → vue/use-bulk-publish.ts} +7 -5
- package/src/{use-bundle-versions-map.ts → vue/use-bundle-versions-map.ts} +7 -5
- package/src/{use-bundles.ts → vue/use-bundles.ts} +14 -14
- package/src/{use-catalog-entries.ts → vue/use-catalog-entries.ts} +14 -11
- package/src/{use-discovery.ts → vue/use-discovery.ts} +9 -6
- package/src/{use-entitlement.ts → vue/use-entitlement.ts} +4 -4
- package/src/{use-live-plan-versions.ts → vue/use-live-plan-versions.ts} +5 -5
- package/src/{use-manifest.ts → vue/use-manifest.ts} +1 -1
- package/src/{use-marketing-projections.ts → vue/use-marketing-projections.ts} +10 -7
- package/src/{use-nav.ts → vue/use-nav.ts} +9 -3
- package/src/{use-plan-editor.ts → vue/use-plan-editor.ts} +2 -2
- package/src/{use-plan-versions.ts → vue/use-plan-versions.ts} +3 -3
- package/src/{use-plans.ts → vue/use-plans.ts} +13 -13
- package/src/{use-platform-tenant-actions.ts → vue/use-platform-tenant-actions.ts} +9 -6
- package/src/{use-promotions.ts → vue/use-promotions.ts} +10 -11
- package/src/{use-public-boot.ts → vue/use-public-boot.ts} +1 -1
- package/src/{use-subscription-draft.ts → vue/use-subscription-draft.ts} +2 -3
- package/src/{use-super-admin-context.ts → vue/use-super-admin-context.ts} +5 -5
- package/src/vue/use-super-admin-i18n.ts +82 -0
- package/src/{use-tenant-action-flow.ts → vue/use-tenant-action-flow.ts} +12 -7
- package/src/{use-tenant-billing-catalog.ts → vue/use-tenant-billing-catalog.ts} +2 -2
- package/src/{use-tenant-billing.ts → vue/use-tenant-billing.ts} +2 -2
- package/src/{use-tenant-manifest.ts → vue/use-tenant-manifest.ts} +2 -4
- package/src/{use-tenant-subscription-bundles.ts → vue/use-tenant-subscription-bundles.ts} +5 -5
- package/src/{use-tenants.ts → vue/use-tenants.ts} +3 -3
- package/dist/testing-e2e/admin-pages-suite.d.cts +0 -37
- package/dist/testing-e2e/admin-pages-suite.d.ts +0 -37
- package/src/components/BusinessTypeVersionEditorDialog.vue +0 -417
- package/src/components/BusinessTypeVersionPublishDialog.vue +0 -258
- package/src/pages-standard/BusinessTypesPage.vue +0 -662
- package/src/pages-standard/plan-versions/VersionDiffPreview.vue +0 -167
- package/src/use-business-types.ts +0 -269
- /package/src/{http-json.ts → client/http-json.ts} +0 -0
- /package/src/{types.ts → client/types.ts} +0 -0
- /package/src/{version.ts → client/version.ts} +0 -0
- /package/src/{create-admin-routes.ts → vue/create-admin-routes.ts} +0 -0
- /package/src/{entitlement-provider.ts → vue/entitlement-provider.ts} +0 -0
- /package/src/{feature-router-guard.ts → vue/feature-router-guard.ts} +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div class="sa-promo-codes">
|
|
3
3
|
<header class="sa-page-head">
|
|
4
4
|
<div>
|
|
5
|
-
<h1 class="sa-page-head__title">
|
|
5
|
+
<h1 class="sa-page-head__title">{{ msg.title }}</h1>
|
|
6
6
|
<p v-if="subtitle" class="sa-page-head__sub">{{ subtitle }}</p>
|
|
7
7
|
</div>
|
|
8
8
|
<div class="sa-page-head__actions">
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
unelevated
|
|
13
13
|
color="primary"
|
|
14
14
|
icon="add"
|
|
15
|
-
:label="
|
|
15
|
+
:label="resolvedCreateLabel"
|
|
16
16
|
@click="showCreate = true"
|
|
17
17
|
/>
|
|
18
18
|
</slot>
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
v-model="filter.search"
|
|
42
42
|
outlined
|
|
43
43
|
dense
|
|
44
|
-
label="
|
|
44
|
+
:label="msg.list.searchLabel"
|
|
45
45
|
clearable
|
|
46
46
|
@update:model-value="reload"
|
|
47
47
|
/>
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
emit-value
|
|
53
53
|
map-options
|
|
54
54
|
clearable
|
|
55
|
-
label="
|
|
55
|
+
:label="common.status"
|
|
56
56
|
:options="statusOptions"
|
|
57
57
|
@update:model-value="reload"
|
|
58
58
|
/>
|
|
@@ -138,6 +138,9 @@ export function computePlanColors(
|
|
|
138
138
|
<script setup lang="ts">
|
|
139
139
|
import { computed, onMounted, reactive, ref } from 'vue';
|
|
140
140
|
import { useQuasar } from 'quasar';
|
|
141
|
+
import { formatMessage } from '../client/i18n/format.js';
|
|
142
|
+
import { useSaMessages, useSuperAdminI18n } from '../vue/use-super-admin-i18n.js';
|
|
143
|
+
import { useSuperAdminNotify } from '../quasar/notify.js';
|
|
141
144
|
import PromoCodeCreateDialog from '../components/dialogs/PromoCodeCreateDialog.vue';
|
|
142
145
|
import PromoCodeEditDialog, {
|
|
143
146
|
type PromoCodeEditRow,
|
|
@@ -209,12 +212,17 @@ const props = withDefaults(
|
|
|
209
212
|
}>(),
|
|
210
213
|
{
|
|
211
214
|
statusOptions: () => ['ACTIVE', 'PAUSED', 'EXHAUSTED', 'EXPIRED'],
|
|
212
|
-
createLabel: 'Promo-Code anlegen',
|
|
213
215
|
planOptions: () => [],
|
|
214
216
|
},
|
|
215
217
|
);
|
|
216
218
|
|
|
219
|
+
const msg = useSaMessages('promos');
|
|
220
|
+
const common = useSaMessages('common');
|
|
221
|
+
const { intlLocale } = useSuperAdminI18n();
|
|
222
|
+
const resolvedCreateLabel = computed(() => props.createLabel ?? msg.value.createAction);
|
|
223
|
+
|
|
217
224
|
const q = useQuasar();
|
|
225
|
+
const notify = useSuperAdminNotify();
|
|
218
226
|
const rows = ref<PromoRow[]>([]);
|
|
219
227
|
const loading = ref(false);
|
|
220
228
|
const filter = reactive({ search: '', status: null as string | null });
|
|
@@ -265,23 +273,23 @@ const statTiles = computed<
|
|
|
265
273
|
if (c) counts[c]++;
|
|
266
274
|
}
|
|
267
275
|
return [
|
|
268
|
-
{ id: 'all', label:
|
|
276
|
+
{ id: 'all', label: common.value.all, count: rows.value.length },
|
|
269
277
|
{
|
|
270
278
|
id: 'active',
|
|
271
|
-
label:
|
|
279
|
+
label: common.value.active,
|
|
272
280
|
count: counts.active,
|
|
273
281
|
tone: 'positive',
|
|
274
|
-
hint:
|
|
282
|
+
hint: msg.value.list.hintRedeemable,
|
|
275
283
|
},
|
|
276
284
|
{
|
|
277
285
|
id: 'scheduled',
|
|
278
|
-
label:
|
|
286
|
+
label: msg.value.list.tileScheduled,
|
|
279
287
|
count: counts.scheduled,
|
|
280
288
|
tone: 'info',
|
|
281
|
-
hint:
|
|
289
|
+
hint: msg.value.list.hintStartsLater,
|
|
282
290
|
},
|
|
283
|
-
{ id: 'paused', label:
|
|
284
|
-
{ id: 'expired', label:
|
|
291
|
+
{ id: 'paused', label: msg.value.list.tilePaused, count: counts.paused, tone: 'warn' },
|
|
292
|
+
{ id: 'expired', label: common.value.expired, count: counts.expired, tone: 'muted' },
|
|
285
293
|
];
|
|
286
294
|
});
|
|
287
295
|
|
|
@@ -303,36 +311,41 @@ function onStatusTileClick(id: StatusFilter): void {
|
|
|
303
311
|
}
|
|
304
312
|
}
|
|
305
313
|
|
|
306
|
-
const baseColumns = [
|
|
314
|
+
const baseColumns = computed(() => [
|
|
307
315
|
{
|
|
308
316
|
name: 'code',
|
|
309
|
-
label:
|
|
317
|
+
label: msg.value.list.columnCode,
|
|
310
318
|
field: 'code',
|
|
311
319
|
align: 'left' as const,
|
|
312
320
|
sortable: true,
|
|
313
321
|
},
|
|
314
|
-
{
|
|
315
|
-
|
|
316
|
-
|
|
322
|
+
{
|
|
323
|
+
name: 'valueType',
|
|
324
|
+
label: common.value.type,
|
|
325
|
+
field: 'valueType',
|
|
326
|
+
align: 'left' as const,
|
|
327
|
+
},
|
|
328
|
+
{ name: 'value', label: msg.value.list.columnValue, field: 'value', align: 'right' as const },
|
|
329
|
+
{ name: 'status', label: common.value.status, field: 'status', align: 'left' as const },
|
|
317
330
|
{
|
|
318
331
|
name: 'redemptions',
|
|
319
|
-
label:
|
|
332
|
+
label: msg.value.list.columnRedemptions,
|
|
320
333
|
field: (r: PromoRow) => `${r.redemptionsCount} / ${r.maxRedemptions ?? '∞'}`,
|
|
321
334
|
align: 'right' as const,
|
|
322
335
|
},
|
|
323
336
|
{
|
|
324
337
|
name: 'campaign',
|
|
325
|
-
label:
|
|
338
|
+
label: msg.value.list.columnCampaign,
|
|
326
339
|
field: (r: PromoRow) => r.campaignTag ?? '—',
|
|
327
340
|
align: 'left' as const,
|
|
328
341
|
},
|
|
329
342
|
{
|
|
330
343
|
name: 'validUntil',
|
|
331
|
-
label:
|
|
344
|
+
label: msg.value.list.columnValidUntil,
|
|
332
345
|
field: (r: PromoRow) => formatDate(r.validUntil) ?? '—',
|
|
333
346
|
align: 'left' as const,
|
|
334
347
|
},
|
|
335
|
-
];
|
|
348
|
+
]);
|
|
336
349
|
|
|
337
350
|
// Built-in default actions — APPENDED to the consumer actions, not replacing them.
|
|
338
351
|
const bakedActions = computed<PromoRowAction[]>(() => {
|
|
@@ -340,7 +353,7 @@ const bakedActions = computed<PromoRowAction[]>(() => {
|
|
|
340
353
|
if (props.enableEdit && props.submitEdit) {
|
|
341
354
|
out.push({
|
|
342
355
|
id: 'edit',
|
|
343
|
-
label:
|
|
356
|
+
label: common.value.edit,
|
|
344
357
|
icon: 'edit',
|
|
345
358
|
color: 'primary',
|
|
346
359
|
handler: (row) => openEdit(row),
|
|
@@ -349,7 +362,7 @@ const bakedActions = computed<PromoRowAction[]>(() => {
|
|
|
349
362
|
if (props.enableStatusToggle && props.submitEdit) {
|
|
350
363
|
out.push({
|
|
351
364
|
id: 'pause',
|
|
352
|
-
label:
|
|
365
|
+
label: msg.value.list.actionPause,
|
|
353
366
|
icon: 'pause',
|
|
354
367
|
color: 'warning',
|
|
355
368
|
condition: (row) => row.status === 'ACTIVE',
|
|
@@ -357,7 +370,7 @@ const bakedActions = computed<PromoRowAction[]>(() => {
|
|
|
357
370
|
});
|
|
358
371
|
out.push({
|
|
359
372
|
id: 'activate',
|
|
360
|
-
label:
|
|
373
|
+
label: msg.value.list.actionActivate,
|
|
361
374
|
icon: 'play_arrow',
|
|
362
375
|
color: 'primary',
|
|
363
376
|
condition: (row) => row.status === 'PAUSED',
|
|
@@ -367,7 +380,7 @@ const bakedActions = computed<PromoRowAction[]>(() => {
|
|
|
367
380
|
if (props.enableDelete && props.submitDelete) {
|
|
368
381
|
out.push({
|
|
369
382
|
id: 'delete',
|
|
370
|
-
label:
|
|
383
|
+
label: common.value.delete,
|
|
371
384
|
icon: 'delete',
|
|
372
385
|
color: 'negative',
|
|
373
386
|
handler: (row) => onDeleteClick(row),
|
|
@@ -382,7 +395,7 @@ const mergedActions = computed<readonly PromoRowAction[]>(() => [
|
|
|
382
395
|
]);
|
|
383
396
|
|
|
384
397
|
const effectiveColumns = computed(() => {
|
|
385
|
-
const cols = [...baseColumns];
|
|
398
|
+
const cols = [...baseColumns.value];
|
|
386
399
|
if (mergedActions.value.length > 0) {
|
|
387
400
|
cols.push({
|
|
388
401
|
name: 'actions',
|
|
@@ -490,14 +503,10 @@ async function onPatch(row: PromoRow, data: PromoCodeUpdatePayload): Promise<voi
|
|
|
490
503
|
if (!props.submitEdit) return;
|
|
491
504
|
try {
|
|
492
505
|
await props.submitEdit(row.id, data);
|
|
493
|
-
|
|
494
|
-
type: 'positive',
|
|
495
|
-
message: `${row.code} → ${data.status}`,
|
|
496
|
-
position: 'top',
|
|
497
|
-
});
|
|
506
|
+
notify('positive', `${row.code} → ${data.status}`);
|
|
498
507
|
await reload();
|
|
499
508
|
} catch (err) {
|
|
500
|
-
|
|
509
|
+
notify('negative', errMsg(err));
|
|
501
510
|
}
|
|
502
511
|
}
|
|
503
512
|
|
|
@@ -505,40 +514,28 @@ function onDeleteClick(row: PromoRow): void {
|
|
|
505
514
|
if (!props.submitDelete) return;
|
|
506
515
|
const submit = props.submitDelete;
|
|
507
516
|
q.dialog({
|
|
508
|
-
title:
|
|
509
|
-
message:
|
|
510
|
-
cancel:
|
|
511
|
-
ok: { label:
|
|
517
|
+
title: formatMessage(msg.value.list.deleteTitle, { code: row.code }),
|
|
518
|
+
message: msg.value.list.deleteMessage,
|
|
519
|
+
cancel: common.value.cancel,
|
|
520
|
+
ok: { label: common.value.delete, color: 'negative' },
|
|
512
521
|
}).onOk(async () => {
|
|
513
522
|
try {
|
|
514
523
|
await submit(row.id);
|
|
515
|
-
|
|
516
|
-
type: 'positive',
|
|
517
|
-
message: `${row.code} gelöscht.`,
|
|
518
|
-
position: 'top',
|
|
519
|
-
});
|
|
524
|
+
notify('positive', formatMessage(msg.value.list.deletedNotice, { code: row.code }));
|
|
520
525
|
await reload();
|
|
521
526
|
} catch (err) {
|
|
522
|
-
|
|
527
|
+
notify('negative', errMsg(err));
|
|
523
528
|
}
|
|
524
529
|
});
|
|
525
530
|
}
|
|
526
531
|
|
|
527
532
|
function onCreated(): void {
|
|
528
|
-
|
|
529
|
-
type: 'positive',
|
|
530
|
-
message: 'Promo-Code angelegt.',
|
|
531
|
-
position: 'top',
|
|
532
|
-
});
|
|
533
|
+
notify('positive', msg.value.list.createdNotice);
|
|
533
534
|
void reload();
|
|
534
535
|
}
|
|
535
536
|
|
|
536
537
|
function onUpdated(): void {
|
|
537
|
-
|
|
538
|
-
type: 'positive',
|
|
539
|
-
message: 'Promo-Code aktualisiert.',
|
|
540
|
-
position: 'top',
|
|
541
|
-
});
|
|
538
|
+
notify('positive', msg.value.list.updatedNotice);
|
|
542
539
|
void reload();
|
|
543
540
|
}
|
|
544
541
|
|
|
@@ -546,14 +543,14 @@ function errMsg(err: unknown): string {
|
|
|
546
543
|
return (
|
|
547
544
|
(err as { response?: { data?: { message?: string } } })?.response?.data?.message ??
|
|
548
545
|
(err as Error)?.message ??
|
|
549
|
-
|
|
546
|
+
msg.value.list.actionFailed
|
|
550
547
|
);
|
|
551
548
|
}
|
|
552
549
|
|
|
553
550
|
function formatDate(iso: string | Date | null | undefined): string | null {
|
|
554
551
|
if (!iso) return null;
|
|
555
552
|
try {
|
|
556
|
-
return new Date(iso).toLocaleDateString(
|
|
553
|
+
return new Date(iso).toLocaleDateString(intlLocale.value, {
|
|
557
554
|
day: '2-digit',
|
|
558
555
|
month: 'short',
|
|
559
556
|
year: 'numeric',
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div class="sa-subscriptions">
|
|
3
3
|
<header class="sa-subscriptions__head">
|
|
4
4
|
<div>
|
|
5
|
-
<h1 class="sa-subscriptions__title">
|
|
5
|
+
<h1 class="sa-subscriptions__title">{{ msg.subscriptions.title }}</h1>
|
|
6
6
|
<p v-if="subtitle" class="sa-subscriptions__sub">{{ subtitle }}</p>
|
|
7
7
|
</div>
|
|
8
8
|
<slot name="head-actions" />
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
|
|
27
27
|
<script setup lang="ts">
|
|
28
28
|
import { computed, onMounted, ref } from 'vue';
|
|
29
|
+
import { useSaMessages, useSuperAdminI18n } from '../vue/use-super-admin-i18n.js';
|
|
29
30
|
|
|
30
31
|
// Platform standard page: subscriptions (minimal). Apps pass
|
|
31
32
|
// `loadSubscriptions` + optional `columns` through — default columns show
|
|
@@ -60,39 +61,43 @@ const props = withDefaults(
|
|
|
60
61
|
{},
|
|
61
62
|
);
|
|
62
63
|
|
|
64
|
+
const msg = useSaMessages('tenants');
|
|
65
|
+
const common = useSaMessages('common');
|
|
66
|
+
const { intlLocale } = useSuperAdminI18n();
|
|
67
|
+
|
|
63
68
|
const rows = ref<SubscriptionRow[]>([]);
|
|
64
69
|
const loading = ref(false);
|
|
65
70
|
|
|
66
|
-
const defaultColumns
|
|
71
|
+
const defaultColumns = computed<Column[]>(() => [
|
|
67
72
|
{
|
|
68
73
|
name: 'tenant',
|
|
69
|
-
label:
|
|
74
|
+
label: msg.value.tenant,
|
|
70
75
|
field: (r) => r.tenant?.name ?? r.tenant?.slug ?? r.tenantSlug ?? '—',
|
|
71
76
|
align: 'left',
|
|
72
77
|
sortable: true,
|
|
73
78
|
},
|
|
74
79
|
{
|
|
75
80
|
name: 'plan',
|
|
76
|
-
label:
|
|
81
|
+
label: msg.value.plan,
|
|
77
82
|
field: (r) => r.plan ?? r.planId ?? '—',
|
|
78
83
|
align: 'left',
|
|
79
84
|
},
|
|
80
85
|
{
|
|
81
86
|
name: 'status',
|
|
82
|
-
label:
|
|
87
|
+
label: common.value.status,
|
|
83
88
|
field: (r) => r.status ?? '—',
|
|
84
89
|
align: 'left',
|
|
85
90
|
},
|
|
86
91
|
{
|
|
87
92
|
name: 'periodEndsAt',
|
|
88
|
-
label:
|
|
93
|
+
label: msg.value.subscriptions.columnEndsAt,
|
|
89
94
|
field: (r) => formatDate(r.periodEndsAt) ?? '∞',
|
|
90
95
|
align: 'left',
|
|
91
96
|
},
|
|
92
|
-
];
|
|
97
|
+
]);
|
|
93
98
|
|
|
94
99
|
const effectiveColumns = computed<Column[]>(() =>
|
|
95
|
-
props.columns ? [...props.columns] : defaultColumns,
|
|
100
|
+
props.columns ? [...props.columns] : defaultColumns.value,
|
|
96
101
|
);
|
|
97
102
|
|
|
98
103
|
async function reload() {
|
|
@@ -112,7 +117,7 @@ onMounted(reload);
|
|
|
112
117
|
function formatDate(iso: string | null | undefined): string | null {
|
|
113
118
|
if (!iso) return null;
|
|
114
119
|
try {
|
|
115
|
-
return new Date(iso).toLocaleDateString(
|
|
120
|
+
return new Date(iso).toLocaleDateString(intlLocale.value, {
|
|
116
121
|
day: '2-digit',
|
|
117
122
|
month: 'short',
|
|
118
123
|
year: 'numeric',
|
|
@@ -20,30 +20,32 @@
|
|
|
20
20
|
</div>
|
|
21
21
|
</div>
|
|
22
22
|
|
|
23
|
-
<h1 class="sa-login-title">
|
|
23
|
+
<h1 class="sa-login-title">{{ msg.login.signIn }}</h1>
|
|
24
24
|
<p v-if="subtitle" class="sa-login-subtitle">{{ subtitle }}</p>
|
|
25
25
|
|
|
26
26
|
<q-form @submit.prevent="handleSubmit" class="sa-login-form">
|
|
27
27
|
<q-input
|
|
28
28
|
v-model="form.email"
|
|
29
|
-
label="
|
|
29
|
+
:label="msg.emailLabel"
|
|
30
30
|
type="email"
|
|
31
|
+
autocomplete="username"
|
|
31
32
|
outlined
|
|
32
33
|
dense
|
|
33
34
|
autofocus
|
|
34
35
|
:disable="loading"
|
|
35
36
|
class="q-mb-sm"
|
|
36
|
-
:rules="[(v: string) => /\S+@\S+\.\S+/.test(v) ||
|
|
37
|
+
:rules="[(v: string) => /\S+@\S+\.\S+/.test(v) || msg.invalidEmail]"
|
|
37
38
|
/>
|
|
38
39
|
<q-input
|
|
39
40
|
v-model="form.password"
|
|
40
|
-
label="
|
|
41
|
+
:label="msg.passwordLabel"
|
|
41
42
|
:type="showPw ? 'text' : 'password'"
|
|
43
|
+
autocomplete="current-password"
|
|
42
44
|
outlined
|
|
43
45
|
dense
|
|
44
46
|
:disable="loading"
|
|
45
47
|
class="q-mb-sm"
|
|
46
|
-
:rules="[(v: string) => v.length > 0 ||
|
|
48
|
+
:rules="[(v: string) => v.length > 0 || msg.login.passwordRequired]"
|
|
47
49
|
>
|
|
48
50
|
<template #append>
|
|
49
51
|
<q-icon
|
|
@@ -62,7 +64,7 @@
|
|
|
62
64
|
unelevated
|
|
63
65
|
color="primary"
|
|
64
66
|
icon="login"
|
|
65
|
-
label="
|
|
67
|
+
:label="msg.login.signIn"
|
|
66
68
|
:loading="loading"
|
|
67
69
|
:disable="!canSubmit"
|
|
68
70
|
class="full-width q-mt-sm"
|
|
@@ -71,7 +73,8 @@
|
|
|
71
73
|
</q-form>
|
|
72
74
|
|
|
73
75
|
<div v-if="devHint" class="sa-login-hint">
|
|
74
|
-
|
|
76
|
+
{{ msg.login.devHintLabel }} <code>{{ devHint.email }}</code> /
|
|
77
|
+
<code>{{ devHint.password }}</code>
|
|
75
78
|
</div>
|
|
76
79
|
</div>
|
|
77
80
|
|
|
@@ -86,14 +89,15 @@ import { computed, onMounted, reactive, ref } from 'vue';
|
|
|
86
89
|
import { useRouter } from 'vue-router';
|
|
87
90
|
import type { SetupStatusResponse } from '@saasicat/types';
|
|
88
91
|
|
|
89
|
-
import { usePublicBoot } from '../use-public-boot.js';
|
|
92
|
+
import { usePublicBoot } from '../vue/use-public-boot.js';
|
|
90
93
|
import {
|
|
91
94
|
useSuperAdminBrand,
|
|
92
95
|
useSuperAdminEndpoints,
|
|
93
96
|
useSuperAdminHttp,
|
|
94
97
|
useSuperAdminLoginAdapter,
|
|
95
|
-
} from '../use-super-admin-context.js';
|
|
96
|
-
import { getJson } from '../http-json.js';
|
|
98
|
+
} from '../vue/use-super-admin-context.js';
|
|
99
|
+
import { getJson } from '../client/http-json.js';
|
|
100
|
+
import { useSaMessages } from '../vue/use-super-admin-i18n.js';
|
|
97
101
|
import SuperAdminSetupWizard from './SuperAdminSetupWizard.vue';
|
|
98
102
|
|
|
99
103
|
interface Props {
|
|
@@ -107,6 +111,7 @@ interface Props {
|
|
|
107
111
|
const props = defineProps<Props>();
|
|
108
112
|
|
|
109
113
|
const router = useRouter();
|
|
114
|
+
const msg = useSaMessages('shell');
|
|
110
115
|
const brand = useSuperAdminBrand();
|
|
111
116
|
const endpoints = useSuperAdminEndpoints();
|
|
112
117
|
const adapter = useSuperAdminLoginAdapter();
|
|
@@ -161,11 +166,9 @@ function describeError(
|
|
|
161
166
|
result: Extract<Awaited<ReturnType<typeof adapter.login>>, { ok: false }>,
|
|
162
167
|
): string {
|
|
163
168
|
if (result.message) return result.message;
|
|
164
|
-
if (result.code === 'BAD_CREDENTIALS') return
|
|
165
|
-
if (result.code === 'NOT_SUPER_ADMIN')
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
return 'Anmeldung fehlgeschlagen.';
|
|
169
|
+
if (result.code === 'BAD_CREDENTIALS') return msg.value.login.errorBadCredentials;
|
|
170
|
+
if (result.code === 'NOT_SUPER_ADMIN') return msg.value.login.errorNotSuperAdmin;
|
|
171
|
+
return msg.value.login.errorFailed;
|
|
169
172
|
}
|
|
170
173
|
|
|
171
174
|
async function handleSubmit(): Promise<void> {
|
|
@@ -182,7 +185,7 @@ async function handleSubmit(): Promise<void> {
|
|
|
182
185
|
} catch (err) {
|
|
183
186
|
const e = err as { response?: { data?: { message?: string; code?: string } } };
|
|
184
187
|
errorMessage.value =
|
|
185
|
-
e.response?.data?.message ?? e.response?.data?.code ??
|
|
188
|
+
e.response?.data?.message ?? e.response?.data?.code ?? msg.value.login.errorFailed;
|
|
186
189
|
} finally {
|
|
187
190
|
loading.value = false;
|
|
188
191
|
}
|