@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
|
@@ -7,10 +7,14 @@
|
|
|
7
7
|
<q-card class="pc-dlg">
|
|
8
8
|
<q-card-section class="pc-dlg__head">
|
|
9
9
|
<div>
|
|
10
|
-
<div class="pc-dlg__title">
|
|
10
|
+
<div class="pc-dlg__title">{{ msg.editDialog.title }}</div>
|
|
11
11
|
<div class="pc-dlg__sub" v-if="row">
|
|
12
|
-
|
|
13
|
-
{{
|
|
12
|
+
{{ msg.form.codeLabel }} <strong>{{ row.code }}</strong> ·
|
|
13
|
+
{{
|
|
14
|
+
formatMessage(msg.editDialog.redemptionsSoFar, {
|
|
15
|
+
count: row.redemptionsCount,
|
|
16
|
+
})
|
|
17
|
+
}}
|
|
14
18
|
</div>
|
|
15
19
|
</div>
|
|
16
20
|
<q-btn
|
|
@@ -27,23 +31,23 @@
|
|
|
27
31
|
<q-card-section class="pc-dlg__body">
|
|
28
32
|
<!-- Section: Code & discount -->
|
|
29
33
|
<div class="pc-section">
|
|
30
|
-
<div class="pc-section__title">
|
|
34
|
+
<div class="pc-section__title">{{ msg.form.sectionCodeDiscount }}</div>
|
|
31
35
|
<div class="pc-grid pc-grid--2">
|
|
32
36
|
<div class="pc-field">
|
|
33
|
-
<div class="pc-field__label">
|
|
37
|
+
<div class="pc-field__label">{{ msg.form.codeLabel }}</div>
|
|
34
38
|
<input
|
|
35
39
|
:value="row?.code ?? ''"
|
|
36
40
|
class="pc-input pc-input--code"
|
|
37
41
|
disabled
|
|
38
42
|
/>
|
|
39
|
-
<div class="pc-field__hint">
|
|
43
|
+
<div class="pc-field__hint">{{ msg.form.codeStableHint }}</div>
|
|
40
44
|
</div>
|
|
41
45
|
|
|
42
46
|
<div class="pc-field">
|
|
43
|
-
<div class="pc-field__label">
|
|
47
|
+
<div class="pc-field__label">{{ msg.form.valueTypeLabel }}</div>
|
|
44
48
|
<div class="pc-type-grid">
|
|
45
49
|
<button
|
|
46
|
-
v-for="o in
|
|
50
|
+
v-for="o in typeOptions"
|
|
47
51
|
:key="o.k"
|
|
48
52
|
type="button"
|
|
49
53
|
class="pc-type-opt"
|
|
@@ -59,7 +63,11 @@
|
|
|
59
63
|
|
|
60
64
|
<div class="pc-field" style="max-width: 280px">
|
|
61
65
|
<div class="pc-field__label">
|
|
62
|
-
{{
|
|
66
|
+
{{
|
|
67
|
+
form.valueType === 'PERCENT'
|
|
68
|
+
? msg.form.valuePercentLabel
|
|
69
|
+
: msg.form.valueAbsoluteLabel
|
|
70
|
+
}}
|
|
63
71
|
</div>
|
|
64
72
|
<input
|
|
65
73
|
v-model.number="form.value"
|
|
@@ -73,10 +81,10 @@
|
|
|
73
81
|
|
|
74
82
|
<!-- Section: Validity & duration -->
|
|
75
83
|
<div class="pc-section">
|
|
76
|
-
<div class="pc-section__title">
|
|
84
|
+
<div class="pc-section__title">{{ msg.form.sectionValidity }}</div>
|
|
77
85
|
|
|
78
86
|
<div v-if="plans.length > 0" class="pc-field">
|
|
79
|
-
<div class="pc-field__label">
|
|
87
|
+
<div class="pc-field__label">{{ msg.form.plansLabel }}</div>
|
|
80
88
|
<div class="pc-plan-pick">
|
|
81
89
|
<button
|
|
82
90
|
v-for="p in plans"
|
|
@@ -95,16 +103,20 @@
|
|
|
95
103
|
</button>
|
|
96
104
|
</div>
|
|
97
105
|
<div class="pc-field__hint">
|
|
98
|
-
|
|
106
|
+
{{
|
|
107
|
+
formatMessage(msg.form.plansHint, {
|
|
108
|
+
count: form.appliesToPlans.length,
|
|
109
|
+
})
|
|
110
|
+
}}
|
|
99
111
|
</div>
|
|
100
112
|
</div>
|
|
101
113
|
|
|
102
114
|
<div class="pc-grid pc-grid--2">
|
|
103
115
|
<div class="pc-field">
|
|
104
|
-
<div class="pc-field__label">
|
|
116
|
+
<div class="pc-field__label">{{ msg.form.durationLabel }}</div>
|
|
105
117
|
<div class="pc-dur">
|
|
106
118
|
<button
|
|
107
|
-
v-for="o in
|
|
119
|
+
v-for="o in durationOptions"
|
|
108
120
|
:key="o.k"
|
|
109
121
|
type="button"
|
|
110
122
|
class="pc-dur-opt"
|
|
@@ -122,43 +134,45 @@
|
|
|
122
134
|
min="1"
|
|
123
135
|
style="margin-top: 8px; max-width: 120px"
|
|
124
136
|
:placeholder="
|
|
125
|
-
form.durationType === 'MONTHS'
|
|
137
|
+
form.durationType === 'MONTHS'
|
|
138
|
+
? msg.form.durationMonthsPlaceholder
|
|
139
|
+
: msg.form.durationCyclesPlaceholder
|
|
126
140
|
"
|
|
127
141
|
/>
|
|
128
142
|
</div>
|
|
129
143
|
|
|
130
144
|
<div class="pc-field">
|
|
131
|
-
<div class="pc-field__label">
|
|
145
|
+
<div class="pc-field__label">{{ msg.form.maxRedemptionsLabel }}</div>
|
|
132
146
|
<input
|
|
133
147
|
v-model.number="form.maxRedemptions"
|
|
134
148
|
class="pc-input"
|
|
135
149
|
type="number"
|
|
136
150
|
min="1"
|
|
137
|
-
placeholder="
|
|
151
|
+
:placeholder="msg.form.maxRedemptionsPlaceholder"
|
|
138
152
|
/>
|
|
139
153
|
<div class="pc-field__hint">
|
|
140
|
-
|
|
154
|
+
{{ msg.form.maxRedemptionsHintEdit }}
|
|
141
155
|
</div>
|
|
142
156
|
</div>
|
|
143
157
|
</div>
|
|
144
158
|
|
|
145
159
|
<div class="pc-grid pc-grid--2">
|
|
146
160
|
<div class="pc-field">
|
|
147
|
-
<div class="pc-field__label">
|
|
161
|
+
<div class="pc-field__label">{{ msg.form.validFromLabel }}</div>
|
|
148
162
|
<input v-model="form.validFrom" class="pc-input" type="date" />
|
|
149
163
|
</div>
|
|
150
164
|
<div class="pc-field">
|
|
151
|
-
<div class="pc-field__label">
|
|
165
|
+
<div class="pc-field__label">{{ msg.form.validUntilLabel }}</div>
|
|
152
166
|
<input v-model="form.validUntil" class="pc-input" type="date" />
|
|
153
167
|
</div>
|
|
154
168
|
</div>
|
|
155
169
|
|
|
156
170
|
<div class="pc-grid pc-grid--2">
|
|
157
171
|
<div class="pc-field">
|
|
158
|
-
<div class="pc-field__label">
|
|
172
|
+
<div class="pc-field__label">{{ common.status }}</div>
|
|
159
173
|
<div class="pc-status">
|
|
160
174
|
<button
|
|
161
|
-
v-for="o in
|
|
175
|
+
v-for="o in statusOptions"
|
|
162
176
|
:key="o.k"
|
|
163
177
|
type="button"
|
|
164
178
|
class="pc-status-opt"
|
|
@@ -171,32 +185,30 @@
|
|
|
171
185
|
{{ o.label }}
|
|
172
186
|
</button>
|
|
173
187
|
</div>
|
|
174
|
-
<div class="pc-field__hint">
|
|
175
|
-
Bestehende Redemptions bleiben unverändert.
|
|
176
|
-
</div>
|
|
188
|
+
<div class="pc-field__hint">{{ msg.form.statusHint }}</div>
|
|
177
189
|
</div>
|
|
178
190
|
</div>
|
|
179
191
|
</div>
|
|
180
192
|
|
|
181
193
|
<!-- Section: Campaign & note -->
|
|
182
194
|
<div class="pc-section">
|
|
183
|
-
<div class="pc-section__title">
|
|
195
|
+
<div class="pc-section__title">{{ msg.form.sectionCampaign }}</div>
|
|
184
196
|
<div v-if="showCampaignTag" class="pc-field">
|
|
185
|
-
<div class="pc-field__label">
|
|
197
|
+
<div class="pc-field__label">{{ msg.form.campaignLabel }}</div>
|
|
186
198
|
<input
|
|
187
199
|
v-model="form.campaignTag"
|
|
188
200
|
class="pc-input"
|
|
189
|
-
placeholder="
|
|
201
|
+
:placeholder="msg.form.campaignPlaceholder"
|
|
190
202
|
/>
|
|
191
|
-
<div class="pc-field__hint">
|
|
203
|
+
<div class="pc-field__hint">{{ msg.form.campaignHint }}</div>
|
|
192
204
|
</div>
|
|
193
205
|
<div class="pc-field">
|
|
194
|
-
<div class="pc-field__label">
|
|
206
|
+
<div class="pc-field__label">{{ msg.form.noteLabel }}</div>
|
|
195
207
|
<textarea
|
|
196
208
|
v-model="form.description"
|
|
197
209
|
class="pc-input"
|
|
198
210
|
rows="2"
|
|
199
|
-
placeholder="
|
|
211
|
+
:placeholder="msg.form.notePlaceholder"
|
|
200
212
|
/>
|
|
201
213
|
</div>
|
|
202
214
|
</div>
|
|
@@ -212,45 +224,45 @@
|
|
|
212
224
|
:name="advancedOpen ? 'expand_more' : 'chevron_right'"
|
|
213
225
|
size="16px"
|
|
214
226
|
/>
|
|
215
|
-
|
|
227
|
+
{{ msg.form.advancedToggle }}
|
|
216
228
|
</button>
|
|
217
229
|
<div v-if="advancedOpen" class="pc-advanced">
|
|
218
230
|
<div class="pc-grid pc-grid--2">
|
|
219
231
|
<div class="pc-field">
|
|
220
|
-
<div class="pc-field__label">
|
|
232
|
+
<div class="pc-field__label">{{ msg.form.billingCycleLabel }}</div>
|
|
221
233
|
<select v-model="form.appliesToBilling" class="pc-input">
|
|
222
|
-
<option :value="null">
|
|
223
|
-
<option value="MONTHLY">
|
|
224
|
-
<option value="YEARLY">
|
|
234
|
+
<option :value="null">{{ common.both }}</option>
|
|
235
|
+
<option value="MONTHLY">{{ common.monthly }}</option>
|
|
236
|
+
<option value="YEARLY">{{ common.yearly }}</option>
|
|
225
237
|
</select>
|
|
226
238
|
</div>
|
|
227
239
|
<div class="pc-field">
|
|
228
|
-
<div class="pc-field__label">
|
|
240
|
+
<div class="pc-field__label">{{ msg.form.minAmountLabel }}</div>
|
|
229
241
|
<input
|
|
230
242
|
v-model.number="form.minimumPlanAmountGross"
|
|
231
243
|
class="pc-input"
|
|
232
244
|
type="number"
|
|
233
245
|
min="0"
|
|
234
|
-
placeholder="
|
|
246
|
+
:placeholder="msg.form.minAmountPlaceholder"
|
|
235
247
|
/>
|
|
236
248
|
</div>
|
|
237
249
|
</div>
|
|
238
250
|
<div class="pc-grid pc-grid--2">
|
|
239
251
|
<label class="pc-check">
|
|
240
252
|
<input v-model="form.firstTimeCustomersOnly" type="checkbox" />
|
|
241
|
-
<span>
|
|
253
|
+
<span>{{ msg.form.firstTimeOnly }}</span>
|
|
242
254
|
</label>
|
|
243
255
|
<label class="pc-check">
|
|
244
256
|
<input v-model="form.allowZeroInvoice" type="checkbox" />
|
|
245
|
-
<span>
|
|
257
|
+
<span>{{ msg.form.allowZeroInvoice }}</span>
|
|
246
258
|
</label>
|
|
247
259
|
</div>
|
|
248
260
|
<div class="pc-field">
|
|
249
|
-
<div class="pc-field__label">
|
|
261
|
+
<div class="pc-field__label">{{ msg.form.revenueAccountLabel }}</div>
|
|
250
262
|
<input
|
|
251
263
|
v-model="form.revenueDeductionAccount"
|
|
252
264
|
class="pc-input"
|
|
253
|
-
placeholder="
|
|
265
|
+
:placeholder="msg.form.revenueAccountPlaceholder"
|
|
254
266
|
/>
|
|
255
267
|
</div>
|
|
256
268
|
</div>
|
|
@@ -258,7 +270,7 @@
|
|
|
258
270
|
|
|
259
271
|
<!-- Live preview -->
|
|
260
272
|
<div class="pc-preview">
|
|
261
|
-
<div class="pc-preview__eyebrow">
|
|
273
|
+
<div class="pc-preview__eyebrow">{{ msg.form.previewEyebrow }}</div>
|
|
262
274
|
<div class="pc-preview__body">
|
|
263
275
|
<code class="pc-preview__code">{{ row?.code || 'CODE' }}</code>
|
|
264
276
|
<span class="pc-preview__disc">{{ previewValue }}</span>
|
|
@@ -270,11 +282,11 @@
|
|
|
270
282
|
</q-card-section>
|
|
271
283
|
|
|
272
284
|
<q-card-actions align="right" class="pc-dlg__foot">
|
|
273
|
-
<q-btn flat label="
|
|
285
|
+
<q-btn flat :label="common.cancel" v-close-popup :disable="loading" />
|
|
274
286
|
<q-btn
|
|
275
287
|
unelevated
|
|
276
288
|
color="primary"
|
|
277
|
-
label="
|
|
289
|
+
:label="common.save"
|
|
278
290
|
:loading="loading"
|
|
279
291
|
:disable="!isValid || !hasChanges"
|
|
280
292
|
@click="onSubmit"
|
|
@@ -286,6 +298,8 @@
|
|
|
286
298
|
|
|
287
299
|
<script setup lang="ts">
|
|
288
300
|
import { computed, reactive, ref, watch } from 'vue';
|
|
301
|
+
import { formatMessage } from '../../client/i18n/format.js';
|
|
302
|
+
import { useSaMessages } from '../../vue/use-super-admin-i18n.js';
|
|
289
303
|
import type {
|
|
290
304
|
PromoCodeDurationType,
|
|
291
305
|
PromoCodePlanOption,
|
|
@@ -341,21 +355,36 @@ const emit = defineEmits<{
|
|
|
341
355
|
(e: 'updated'): void;
|
|
342
356
|
}>();
|
|
343
357
|
|
|
344
|
-
const
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
{ k: '
|
|
351
|
-
{ k: '
|
|
352
|
-
];
|
|
358
|
+
const msg = useSaMessages('promos');
|
|
359
|
+
const common = useSaMessages('common');
|
|
360
|
+
|
|
361
|
+
const statusOptions = computed<
|
|
362
|
+
ReadonlyArray<{ k: 'ACTIVE' | 'PAUSED'; label: string; icon: string }>
|
|
363
|
+
>(() => [
|
|
364
|
+
{ k: 'ACTIVE', label: common.value.active, icon: 'play_arrow' },
|
|
365
|
+
{ k: 'PAUSED', label: msg.value.form.statusPaused, icon: 'pause' },
|
|
366
|
+
]);
|
|
367
|
+
|
|
368
|
+
const typeOptions = computed<ReadonlyArray<{ k: PromoCodeValueType; label: string; sub: string }>>(
|
|
369
|
+
() => [
|
|
370
|
+
{
|
|
371
|
+
k: 'PERCENT',
|
|
372
|
+
label: msg.value.form.valueTypePercent,
|
|
373
|
+
sub: msg.value.form.valueTypePercentSub,
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
k: 'ABSOLUTE',
|
|
377
|
+
label: msg.value.form.valueTypeAbsolute,
|
|
378
|
+
sub: msg.value.form.valueTypeAbsoluteSub,
|
|
379
|
+
},
|
|
380
|
+
],
|
|
381
|
+
);
|
|
353
382
|
|
|
354
|
-
const
|
|
355
|
-
{ k: 'ONCE', label:
|
|
356
|
-
{ k: 'MONTHS', label:
|
|
357
|
-
{ k: 'BILLING_CYCLES', label:
|
|
358
|
-
];
|
|
383
|
+
const durationOptions = computed<ReadonlyArray<{ k: PromoCodeDurationType; label: string }>>(() => [
|
|
384
|
+
{ k: 'ONCE', label: msg.value.form.durationOnce },
|
|
385
|
+
{ k: 'MONTHS', label: msg.value.form.durationMonths },
|
|
386
|
+
{ k: 'BILLING_CYCLES', label: msg.value.form.durationBillingCycles },
|
|
387
|
+
]);
|
|
359
388
|
|
|
360
389
|
interface EditForm {
|
|
361
390
|
status: 'ACTIVE' | 'PAUSED';
|
|
@@ -450,17 +479,20 @@ const previewValue = computed(() => {
|
|
|
450
479
|
|
|
451
480
|
const previewMeta = computed(() => {
|
|
452
481
|
const parts: string[] = [];
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
else
|
|
482
|
+
const count = form.durationValue || 0;
|
|
483
|
+
if (form.durationType === 'ONCE') parts.push(msg.value.form.previewOnce);
|
|
484
|
+
else if (form.durationType === 'MONTHS')
|
|
485
|
+
parts.push(formatMessage(msg.value.form.previewMonths, { count }));
|
|
486
|
+
else parts.push(formatMessage(msg.value.form.previewCycles, { count }));
|
|
456
487
|
parts.push(
|
|
457
488
|
form.appliesToPlans.length > 0
|
|
458
489
|
? form.appliesToPlans.join(', ')
|
|
459
490
|
: props.plans.length > 0
|
|
460
|
-
?
|
|
461
|
-
:
|
|
491
|
+
? msg.value.form.previewAllPlans
|
|
492
|
+
: msg.value.form.previewNoPlanFilter,
|
|
462
493
|
);
|
|
463
|
-
if (form.maxRedemptions)
|
|
494
|
+
if (form.maxRedemptions)
|
|
495
|
+
parts.push(formatMessage(msg.value.form.previewMax, { count: form.maxRedemptions }));
|
|
464
496
|
return parts.join(' · ');
|
|
465
497
|
});
|
|
466
498
|
|
|
@@ -554,7 +586,7 @@ async function onSubmit() {
|
|
|
554
586
|
error.value =
|
|
555
587
|
(err as { response?: { data?: { message?: string } } }).response?.data?.message ??
|
|
556
588
|
(err as Error).message ??
|
|
557
|
-
|
|
589
|
+
common.value.errorSaveFailed;
|
|
558
590
|
} finally {
|
|
559
591
|
loading.value = false;
|
|
560
592
|
}
|
|
@@ -34,9 +34,9 @@ export interface PilotEditResult {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
|
-
* Tenant-specific vocabulary for the pilot dialogs. The platform
|
|
38
|
-
*
|
|
39
|
-
* their domain language (e.g. "Verein" or "Händler").
|
|
37
|
+
* Tenant-specific vocabulary for the pilot dialogs. The platform provides
|
|
38
|
+
* neutral defaults via the `pilots.copyDefaults` message namespace; consumers
|
|
39
|
+
* override with their domain language (e.g. "Verein" or "Händler").
|
|
40
40
|
*/
|
|
41
41
|
export interface PilotCopy {
|
|
42
42
|
/** Subtitle of the tenant section in the create dialog. */
|
|
@@ -53,16 +53,6 @@ export interface PilotCopy {
|
|
|
53
53
|
notePlaceholder?: string;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
/** Neutral, tenant-agnostic defaults for {@link PilotCopy}. */
|
|
57
|
-
export const DEFAULT_PILOT_COPY: Required<PilotCopy> = {
|
|
58
|
-
tenantSubtitle: 'Stammdaten des Mandanten',
|
|
59
|
-
tenantNameLabel: 'Name des Mandanten',
|
|
60
|
-
tenantNamePlaceholder: 'z. B. Muster GmbH',
|
|
61
|
-
slugPlaceholder: 'muster-mandant',
|
|
62
|
-
adminEmailPlaceholder: 'admin@example.com',
|
|
63
|
-
notePlaceholder: 'z. B. Sales-Pilot · Demo-Zugang',
|
|
64
|
-
};
|
|
65
|
-
|
|
66
56
|
export type PromoCodeValueType = 'PERCENT' | 'ABSOLUTE';
|
|
67
57
|
export type PromoCodeDurationType = 'ONCE' | 'MONTHS' | 'BILLING_CYCLES';
|
|
68
58
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="sp-cycle" role="radiogroup" :aria-label="
|
|
2
|
+
<div class="sp-cycle" role="radiogroup" :aria-label="labels.ariaLabel">
|
|
3
3
|
<button
|
|
4
4
|
type="button"
|
|
5
5
|
class="sp-cycle__btn"
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
:aria-checked="modelValue === 'MONTHLY'"
|
|
9
9
|
@click="emit('update:modelValue', 'MONTHLY')"
|
|
10
10
|
>
|
|
11
|
-
{{
|
|
11
|
+
{{ labels.monthly }}
|
|
12
12
|
</button>
|
|
13
13
|
<button
|
|
14
14
|
type="button"
|
|
@@ -18,33 +18,44 @@
|
|
|
18
18
|
:aria-checked="modelValue === 'YEARLY'"
|
|
19
19
|
@click="emit('update:modelValue', 'YEARLY')"
|
|
20
20
|
>
|
|
21
|
-
{{
|
|
22
|
-
<span v-if="
|
|
21
|
+
{{ labels.yearly }}
|
|
22
|
+
<span v-if="labels.savePill" class="sp-cycle__pill">{{ labels.savePill }}</span>
|
|
23
23
|
</button>
|
|
24
24
|
</div>
|
|
25
25
|
</template>
|
|
26
26
|
|
|
27
27
|
<script setup lang="ts">
|
|
28
|
-
import
|
|
28
|
+
import { computed } from 'vue';
|
|
29
|
+
import { useSaMessages } from '../../vue/use-super-admin-i18n.js';
|
|
30
|
+
import type { BillingCycleStr } from '../../vue/use-tenant-billing.js';
|
|
29
31
|
|
|
30
32
|
interface I18n {
|
|
31
|
-
ariaLabel
|
|
32
|
-
monthly
|
|
33
|
-
yearly
|
|
33
|
+
ariaLabel?: string;
|
|
34
|
+
monthly?: string;
|
|
35
|
+
yearly?: string;
|
|
34
36
|
/** Optional: Spar-Pill neben "Jährlich" (z. B. "−2 Mt"). */
|
|
35
37
|
savePill?: string;
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
const props = defineProps<{
|
|
39
41
|
modelValue: BillingCycleStr;
|
|
40
|
-
|
|
42
|
+
/** Per-string overrides; unset entries fall back to the platform catalog. */
|
|
43
|
+
i18n?: I18n;
|
|
41
44
|
}>();
|
|
42
45
|
|
|
43
46
|
const emit = defineEmits<{
|
|
44
47
|
'update:modelValue': [BillingCycleStr];
|
|
45
48
|
}>();
|
|
46
49
|
|
|
47
|
-
|
|
50
|
+
const msg = useSaMessages('plans');
|
|
51
|
+
const common = useSaMessages('common');
|
|
52
|
+
|
|
53
|
+
const labels = computed(() => ({
|
|
54
|
+
ariaLabel: props.i18n?.ariaLabel ?? msg.value.cycle.ariaLabel,
|
|
55
|
+
monthly: props.i18n?.monthly ?? common.value.monthly,
|
|
56
|
+
yearly: props.i18n?.yearly ?? common.value.yearly,
|
|
57
|
+
savePill: props.i18n?.savePill,
|
|
58
|
+
}));
|
|
48
59
|
</script>
|
|
49
60
|
|
|
50
61
|
<style scoped>
|
|
@@ -48,8 +48,8 @@
|
|
|
48
48
|
</template>
|
|
49
49
|
|
|
50
50
|
<script setup lang="ts">
|
|
51
|
-
import type { CatalogPlan } from '../../use-tenant-billing-catalog.js';
|
|
52
|
-
import type { BillingCycleStr } from '../../use-tenant-billing.js';
|
|
51
|
+
import type { CatalogPlan } from '../../vue/use-tenant-billing-catalog.js';
|
|
52
|
+
import type { BillingCycleStr } from '../../vue/use-tenant-billing.js';
|
|
53
53
|
|
|
54
54
|
interface I18n {
|
|
55
55
|
popular: string;
|
|
@@ -76,7 +76,7 @@ import {
|
|
|
76
76
|
type BundleAvailabilityState,
|
|
77
77
|
type PublicMarketingBundle,
|
|
78
78
|
} from '@saasicat/types';
|
|
79
|
-
import type { BillingCycleStr } from '../../use-tenant-billing.js';
|
|
79
|
+
import type { BillingCycleStr } from '../../vue/use-tenant-billing.js';
|
|
80
80
|
|
|
81
81
|
interface I18n {
|
|
82
82
|
perMonth: string;
|
|
@@ -55,6 +55,9 @@
|
|
|
55
55
|
<script setup lang="ts">
|
|
56
56
|
import { computed } from 'vue';
|
|
57
57
|
import type { PlanRow, PlanVersionRow } from '@saasicat/types';
|
|
58
|
+
import { formatMessage } from '../../client/i18n/format.js';
|
|
59
|
+
import { formatCurrency } from '../../client/i18n/currency.js';
|
|
60
|
+
import { useSaMessages, useSuperAdminI18n } from '../../vue/use-super-admin-i18n.js';
|
|
58
61
|
import PlanCockpitAuditLog from './PlanCockpitAuditLog.vue';
|
|
59
62
|
import PlanCockpitDiffPanel from './PlanCockpitDiffPanel.vue';
|
|
60
63
|
import PlanCockpitHeader from './PlanCockpitHeader.vue';
|
|
@@ -114,6 +117,9 @@ const emit = defineEmits<{
|
|
|
114
117
|
(e: 'viewDiff', from: PlanVersionRow, to: PlanVersionRow): void;
|
|
115
118
|
}>();
|
|
116
119
|
|
|
120
|
+
const msg = useSaMessages('planDetail');
|
|
121
|
+
const { locale } = useSuperAdminI18n();
|
|
122
|
+
|
|
117
123
|
function forwardViewDiff(from: PlanVersionRow, to: PlanVersionRow): void {
|
|
118
124
|
emit('viewDiff', from, to);
|
|
119
125
|
}
|
|
@@ -176,7 +182,7 @@ const timelineAxis = computed(() => {
|
|
|
176
182
|
for (const v of [...props.versions].sort((a, b) => a.version - b.version)) {
|
|
177
183
|
if (v.validFrom) labels.push(v.validFrom.slice(0, 7));
|
|
178
184
|
}
|
|
179
|
-
labels.push(
|
|
185
|
+
labels.push(msg.value.versions.timelineNow);
|
|
180
186
|
return labels;
|
|
181
187
|
});
|
|
182
188
|
|
|
@@ -184,8 +190,7 @@ const timelineAxis = computed(() => {
|
|
|
184
190
|
function formatMoney(raw: string | number): string {
|
|
185
191
|
const num = typeof raw === 'string' ? Number(raw) : raw;
|
|
186
192
|
if (!Number.isFinite(num)) return String(raw);
|
|
187
|
-
|
|
188
|
-
return `${num.toFixed(2).replace('.', ',')} €`;
|
|
193
|
+
return formatCurrency(num, locale.value);
|
|
189
194
|
}
|
|
190
195
|
|
|
191
196
|
// ── Diff ────────────────────────────────────────────────────────────
|
|
@@ -255,34 +260,44 @@ const diff = computed<DiffSummary>(() => {
|
|
|
255
260
|
removedQuotas,
|
|
256
261
|
changedQuotas,
|
|
257
262
|
priceChanged,
|
|
258
|
-
priceFrom:
|
|
259
|
-
priceTo:
|
|
263
|
+
priceFrom: formatPricePair(from),
|
|
264
|
+
priceTo: formatPricePair(to),
|
|
260
265
|
};
|
|
261
266
|
});
|
|
262
267
|
|
|
268
|
+
function formatPricePair(version: PlanVersionRow): string {
|
|
269
|
+
return formatMessage(msg.value.diff.pricePair, {
|
|
270
|
+
monthly: formatMoney(version.monthlyNet),
|
|
271
|
+
yearly: formatMoney(version.yearlyNet),
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
|
|
263
275
|
const STYLES = {
|
|
264
|
-
added: { bg: '#ecfdf5', border: '#a7f3d0', color: '#047857', sign: '+'
|
|
265
|
-
removed: { bg: '#fef2f2', border: '#fecaca', color: '#b91c1c', sign: '−'
|
|
266
|
-
changed: { bg: '#fffbeb', border: '#fde68a', color: '#b45309', sign: '~'
|
|
276
|
+
added: { bg: '#ecfdf5', border: '#a7f3d0', color: '#047857', sign: '+' },
|
|
277
|
+
removed: { bg: '#fef2f2', border: '#fecaca', color: '#b91c1c', sign: '−' },
|
|
278
|
+
changed: { bg: '#fffbeb', border: '#fde68a', color: '#b45309', sign: '~' },
|
|
267
279
|
} as const;
|
|
268
280
|
|
|
269
281
|
const diffRows = computed<DiffRow[]>(() => {
|
|
282
|
+
const texts = msg.value.diff;
|
|
270
283
|
const out: DiffRow[] = [];
|
|
271
284
|
for (const f of diff.value.addedFeatures) {
|
|
272
285
|
out.push({
|
|
273
286
|
id: `add-f-${f}`,
|
|
274
|
-
section:
|
|
287
|
+
section: texts.sectionLabelFeatures,
|
|
275
288
|
label: featureLabel(f),
|
|
276
289
|
sub: f,
|
|
290
|
+
tag: texts.tagNew,
|
|
277
291
|
...STYLES.added,
|
|
278
292
|
});
|
|
279
293
|
}
|
|
280
294
|
for (const f of diff.value.removedFeatures) {
|
|
281
295
|
out.push({
|
|
282
296
|
id: `rem-f-${f}`,
|
|
283
|
-
section:
|
|
297
|
+
section: texts.sectionLabelFeatures,
|
|
284
298
|
label: featureLabel(f),
|
|
285
299
|
sub: f,
|
|
300
|
+
tag: texts.tagRemoved,
|
|
286
301
|
...STYLES.removed,
|
|
287
302
|
});
|
|
288
303
|
}
|
|
@@ -290,11 +305,12 @@ const diffRows = computed<DiffRow[]>(() => {
|
|
|
290
305
|
const unit = quotaUnit(q.key);
|
|
291
306
|
out.push({
|
|
292
307
|
id: `chg-q-${q.key}`,
|
|
293
|
-
section:
|
|
308
|
+
section: texts.sectionLabelQuotas,
|
|
294
309
|
label: quotaLabel(q.key),
|
|
295
310
|
sub: q.key,
|
|
296
311
|
from: `${q.from}${unit ? ' ' + unit : ''}`,
|
|
297
312
|
to: `${q.to}${unit ? ' ' + unit : ''}`,
|
|
313
|
+
tag: texts.tagChanged,
|
|
298
314
|
...STYLES.changed,
|
|
299
315
|
});
|
|
300
316
|
}
|
|
@@ -302,10 +318,11 @@ const diffRows = computed<DiffRow[]>(() => {
|
|
|
302
318
|
const unit = quotaUnit(q.key);
|
|
303
319
|
out.push({
|
|
304
320
|
id: `add-q-${q.key}`,
|
|
305
|
-
section:
|
|
321
|
+
section: texts.sectionLabelQuotas,
|
|
306
322
|
label: quotaLabel(q.key),
|
|
307
323
|
sub: q.key,
|
|
308
324
|
to: `${q.value}${unit ? ' ' + unit : ''}`,
|
|
325
|
+
tag: texts.tagNew,
|
|
309
326
|
...STYLES.added,
|
|
310
327
|
});
|
|
311
328
|
}
|
|
@@ -313,20 +330,22 @@ const diffRows = computed<DiffRow[]>(() => {
|
|
|
313
330
|
const unit = quotaUnit(q.key);
|
|
314
331
|
out.push({
|
|
315
332
|
id: `rem-q-${q.key}`,
|
|
316
|
-
section:
|
|
333
|
+
section: texts.sectionLabelQuotas,
|
|
317
334
|
label: quotaLabel(q.key),
|
|
318
335
|
sub: q.key,
|
|
319
336
|
from: `${q.value}${unit ? ' ' + unit : ''}`,
|
|
337
|
+
tag: texts.tagRemoved,
|
|
320
338
|
...STYLES.removed,
|
|
321
339
|
});
|
|
322
340
|
}
|
|
323
341
|
if (diff.value.priceChanged) {
|
|
324
342
|
out.push({
|
|
325
343
|
id: 'chg-price',
|
|
326
|
-
section:
|
|
327
|
-
label:
|
|
344
|
+
section: texts.sectionLabelPrice,
|
|
345
|
+
label: texts.priceYearMonthLabel,
|
|
328
346
|
from: diff.value.priceFrom,
|
|
329
347
|
to: diff.value.priceTo,
|
|
348
|
+
tag: texts.tagChanged,
|
|
330
349
|
...STYLES.changed,
|
|
331
350
|
});
|
|
332
351
|
}
|