@saasicat/ui-vue 0.5.0 → 0.7.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 (186) hide show
  1. package/README.md +17 -0
  2. package/dist/{chunk-EH7TOD4H.js → chunk-A3W2N26K.js} +73 -77
  3. package/dist/{chunk-3YP2ZAOD.js → chunk-QZOSDCNP.js} +36 -1
  4. package/dist/chunk-X5SQ5HMB.js +3231 -0
  5. package/dist/client/index.cjs +3279 -76
  6. package/dist/client/index.d.cts +31 -5
  7. package/dist/client/index.d.ts +31 -5
  8. package/dist/client/index.js +23 -5
  9. package/dist/index.cjs +3709 -465
  10. package/dist/index.d.cts +37 -54
  11. package/dist/index.d.ts +37 -54
  12. package/dist/index.js +347 -311
  13. package/dist/messages-7b0P8W75.d.cts +1652 -0
  14. package/dist/messages-7b0P8W75.d.ts +1652 -0
  15. package/dist/quasar/index.cjs +3185 -4
  16. package/dist/quasar/index.d.cts +11 -2
  17. package/dist/quasar/index.d.ts +11 -2
  18. package/dist/quasar/index.js +8 -3
  19. package/dist/testing-e2e/admin-pages-suite.cjs +14 -11
  20. package/dist/testing-e2e/admin-pages-suite.js +14 -11
  21. package/dist/{ui-notify-COUzXEQ4.d.ts → use-super-admin-i18n-B3v3-SWZ.d.ts} +35 -3
  22. package/dist/{ui-notify-D_eAAwRh.d.cts → use-super-admin-i18n-DMktRVEt.d.cts} +35 -3
  23. package/package.json +2 -2
  24. package/src/client/action-registry.ts +4 -4
  25. package/src/client/batch-column-fetcher.ts +4 -4
  26. package/src/client/boot-loader.ts +3 -3
  27. package/src/client/i18n/currency.ts +42 -0
  28. package/src/client/i18n/define.ts +59 -0
  29. package/src/client/i18n/format.ts +12 -0
  30. package/src/client/i18n/index.ts +14 -0
  31. package/src/client/i18n/locale.ts +15 -0
  32. package/src/client/i18n/messages/audit.ts +42 -0
  33. package/src/client/i18n/messages/bundles.ts +459 -0
  34. package/src/client/i18n/messages/common.ts +147 -0
  35. package/src/client/i18n/messages/dashboard.ts +16 -0
  36. package/src/client/i18n/messages/discovery.ts +229 -0
  37. package/src/client/i18n/messages/email.ts +125 -0
  38. package/src/client/i18n/messages/marketing.ts +270 -0
  39. package/src/client/i18n/messages/nav.ts +72 -0
  40. package/src/client/i18n/messages/pilots.ts +192 -0
  41. package/src/client/i18n/messages/plan-detail.ts +266 -0
  42. package/src/client/i18n/messages/plan-editor.ts +177 -0
  43. package/src/client/i18n/messages/plan-versions.ts +251 -0
  44. package/src/client/i18n/messages/plans.ts +503 -0
  45. package/src/client/i18n/messages/promos.ts +202 -0
  46. package/src/client/i18n/messages/shell.ts +145 -0
  47. package/src/client/i18n/messages/tenants.ts +104 -0
  48. package/src/client/i18n/messages/users.ts +78 -0
  49. package/src/client/i18n/messages.ts +84 -0
  50. package/src/client/index.ts +2 -0
  51. package/src/client/manifest-loader.ts +4 -4
  52. package/src/client/nav-builder.ts +44 -51
  53. package/src/client/plan-versions-catalog.ts +42 -30
  54. package/src/components/BundleVersionPublishDialog.vue +35 -24
  55. package/src/components/MarketingPromotionsTab.vue +112 -59
  56. package/src/components/MfaPromptDialog.vue +11 -11
  57. package/src/components/TenantActionConfirmDialog.vue +19 -17
  58. package/src/components/VersionDiffPreview.vue +72 -43
  59. package/src/components/bundle-editor/BundleCreatePanel.vue +76 -63
  60. package/src/components/bundle-editor/BundleFeaturesEditor.vue +13 -6
  61. package/src/components/bundle-editor/BundlePlanCompatPicker.vue +19 -14
  62. package/src/components/bundle-editor/BundleQuotasEditor.vue +7 -4
  63. package/src/components/bundle-editor/BundleStatusBanner.vue +36 -19
  64. package/src/components/bundle-editor/BundleVersionInlineEditor.vue +51 -35
  65. package/src/components/bundle-editor/BundleVersionStrip.vue +24 -12
  66. package/src/components/bundle-editor/bundle-version-status.ts +29 -29
  67. package/src/components/dialogs/PilotCreateDialog.vue +58 -63
  68. package/src/components/dialogs/PilotEditDialog.vue +40 -34
  69. package/src/components/dialogs/PromoCodeCreateDialog.vue +89 -63
  70. package/src/components/dialogs/PromoCodeEditDialog.vue +98 -66
  71. package/src/components/dialogs/types.ts +3 -13
  72. package/src/components/plan/PlanCycleToggle.vue +20 -9
  73. package/src/components/plan-cockpit/PlanCockpit.vue +34 -15
  74. package/src/components/plan-cockpit/PlanCockpitAuditLog.vue +13 -6
  75. package/src/components/plan-cockpit/PlanCockpitDiffPanel.vue +18 -9
  76. package/src/components/plan-cockpit/PlanCockpitHeader.vue +9 -6
  77. package/src/components/plan-cockpit/PlanCockpitImpactPanel.vue +24 -11
  78. package/src/components/plan-cockpit/PlanCockpitKpis.vue +28 -17
  79. package/src/components/plan-cockpit/PlanCockpitVersions.vue +50 -25
  80. package/src/components/plan-create-dialog/PlanCreateDialog.vue +45 -35
  81. package/src/components/plan-detail/PlanAuditLog.vue +11 -6
  82. package/src/components/plan-detail/PlanDetail.vue +21 -23
  83. package/src/components/plan-detail/PlanDetailHeader.vue +20 -11
  84. package/src/components/plan-detail/PlanDetailKpis.vue +30 -17
  85. package/src/components/plan-detail/PlanTerminateDialog.vue +22 -9
  86. package/src/components/plan-detail/PlanVersionDiffPanel.vue +61 -27
  87. package/src/components/plan-detail/PlanVersionsPanel.vue +71 -36
  88. package/src/components/plan-list/PlanList.vue +99 -57
  89. package/src/components/plan-matrix/PlanMatrix.vue +85 -38
  90. package/src/components/plan-review/PlanReview.vue +105 -80
  91. package/src/components/plan-version-editor/PlanCatalogPreview.vue +43 -20
  92. package/src/components/plan-version-editor/PlanComponentPool.vue +15 -7
  93. package/src/components/plan-version-editor/PlanVersionBasket.vue +45 -24
  94. package/src/components/plan-version-editor/PlanVersionDiffDialog.vue +8 -7
  95. package/src/components/plan-version-editor/PlanVersionEditor.vue +74 -40
  96. package/src/components/plan-version-editor/PlanVersionEditorHeader.vue +24 -12
  97. package/src/index.ts +1 -1
  98. package/src/pages-standard/AdminLayout.vue +42 -17
  99. package/src/pages-standard/AdminManifestErrorPage.vue +10 -10
  100. package/src/pages-standard/AuditPage.vue +58 -19
  101. package/src/pages-standard/BundlesPage.vue +29 -18
  102. package/src/pages-standard/DashboardPage.vue +29 -15
  103. package/src/pages-standard/DiscoveryPage.vue +40 -28
  104. package/src/pages-standard/EmailHistoryPage.vue +92 -59
  105. package/src/pages-standard/MarketingCatalogPage.vue +35 -16
  106. package/src/pages-standard/PilotsPage.vue +57 -41
  107. package/src/pages-standard/PlanVersionsPage.vue +7 -3
  108. package/src/pages-standard/PlansPage.vue +89 -57
  109. package/src/pages-standard/PlatformEmailPage.vue +115 -50
  110. package/src/pages-standard/PromoCodeDetailPage.vue +66 -63
  111. package/src/pages-standard/PromoCodesPage.vue +46 -35
  112. package/src/pages-standard/SubscriptionsPage.vue +14 -9
  113. package/src/pages-standard/SuperAdminLoginPage.vue +16 -13
  114. package/src/pages-standard/SuperAdminSetupWizard.vue +51 -47
  115. package/src/pages-standard/TenantDetailPage.vue +50 -36
  116. package/src/pages-standard/TenantsPage.vue +54 -41
  117. package/src/pages-standard/UsersPage.vue +66 -42
  118. package/src/pages-standard/bundles-page/BundleAccordionList.vue +20 -8
  119. package/src/pages-standard/bundles-page/BundleDetailPanel.vue +28 -18
  120. package/src/pages-standard/bundles-page/BundlesFilterBar.vue +4 -1
  121. package/src/pages-standard/bundles-page/BundlesHeader.vue +9 -8
  122. package/src/pages-standard/bundles-page/BundlesKpis.vue +29 -11
  123. package/src/pages-standard/discovery-page/CatalogEntryTransPanel.vue +20 -8
  124. package/src/pages-standard/discovery-page/DiscoveryCapList.vue +5 -3
  125. package/src/pages-standard/discovery-page/DiscoveryFeatureCard.vue +43 -24
  126. package/src/pages-standard/discovery-page/DiscoveryHeader.vue +7 -4
  127. package/src/pages-standard/discovery-page/DiscoveryKpis.vue +28 -15
  128. package/src/pages-standard/discovery-page/DiscoveryQuotaCard.vue +20 -10
  129. package/src/pages-standard/discovery-page/DiscoveryStatusControl.vue +9 -6
  130. package/src/pages-standard/discovery-page/discovery-ui.ts +40 -52
  131. package/src/pages-standard/marketing-catalog/MarketingCatalogAdmin.vue +81 -49
  132. package/src/pages-standard/marketing-catalog/MarketingCatalogHeader.vue +13 -10
  133. package/src/pages-standard/marketing-catalog/MarketingCatalogPreview.vue +24 -20
  134. package/src/pages-standard/marketing-catalog/MarketingCatalogToolbar.vue +6 -3
  135. package/src/pages-standard/plan-versions/PlanDiffCard.vue +16 -6
  136. package/src/pages-standard/plan-versions/PlanVersionHeader.vue +41 -25
  137. package/src/pages-standard/plan-versions/PlanVersionsAudit.vue +45 -26
  138. package/src/pages-standard/plan-versions/PlanVersionsDiff.vue +7 -5
  139. package/src/pages-standard/plan-versions/PlanVersionsList.vue +39 -16
  140. package/src/pages-standard/plan-versions/PlanVersionsTimeline.vue +24 -12
  141. package/src/pages-standard/plan-versions/format.ts +33 -17
  142. package/src/pages-standard/plans-page/PlanArchiveDialog.vue +12 -8
  143. package/src/pages-standard/plans-page/PlanBundleOverview.vue +15 -6
  144. package/src/pages-standard/plans-page/PlanDiscardDraftDialog.vue +18 -7
  145. package/src/pages-standard/plans-page/PlanPublishDialog.vue +23 -12
  146. package/src/pages-standard/tenants/format.ts +3 -2
  147. package/src/pages-tenant/MySubscriptionBundlesPage.vue +72 -37
  148. package/src/pages-tenant/PlanChangeWizard.vue +8 -4
  149. package/src/pages-tenant/TenantPlanSection.vue +17 -13
  150. package/src/pages-tenant/default-i18n.ts +217 -1
  151. package/src/pages-tenant/tenant-plan-section/BundlePreviewDialog.vue +8 -6
  152. package/src/pages-tenant/tenant-plan-section/TenantBundleStore.vue +9 -10
  153. package/src/pages-tenant/tenant-plan-section/TenantFeatureMatrix.vue +4 -1
  154. package/src/quasar/create-super-admin-app.ts +19 -0
  155. package/src/testing-e2e/admin-pages-suite.ts +14 -11
  156. package/src/vue/project-page-host.ts +5 -3
  157. package/src/vue/use-audit-entries.ts +3 -3
  158. package/src/vue/use-bulk-publish.ts +6 -4
  159. package/src/vue/use-bundle-versions-map.ts +6 -4
  160. package/src/vue/use-bundles.ts +13 -13
  161. package/src/vue/use-catalog-entries.ts +13 -10
  162. package/src/vue/use-discovery.ts +8 -5
  163. package/src/vue/use-entitlement.ts +3 -3
  164. package/src/vue/use-live-plan-versions.ts +4 -4
  165. package/src/vue/use-marketing-projections.ts +9 -6
  166. package/src/vue/use-nav.ts +8 -2
  167. package/src/vue/use-plan-editor.ts +2 -2
  168. package/src/vue/use-plan-versions.ts +3 -3
  169. package/src/vue/use-plans.ts +12 -12
  170. package/src/vue/use-platform-tenant-actions.ts +9 -6
  171. package/src/vue/use-promotions.ts +9 -10
  172. package/src/vue/use-subscription-draft.ts +2 -3
  173. package/src/vue/use-super-admin-context.ts +3 -3
  174. package/src/vue/use-super-admin-i18n.ts +82 -0
  175. package/src/vue/use-tenant-action-flow.ts +11 -6
  176. package/src/vue/use-tenant-manifest.ts +1 -3
  177. package/src/vue/use-tenant-subscription-bundles.ts +4 -4
  178. package/src/vue/use-tenants.ts +3 -3
  179. package/dist/action-registry-CQ2wL3R-.d.cts +0 -85
  180. package/dist/action-registry-CQ2wL3R-.d.ts +0 -85
  181. package/dist/chunk-LVGUSD3T.js +0 -26
  182. package/src/components/BusinessTypeVersionEditorDialog.vue +0 -417
  183. package/src/components/BusinessTypeVersionPublishDialog.vue +0 -258
  184. package/src/pages-standard/BusinessTypesPage.vue +0 -662
  185. package/src/pages-standard/plan-versions/VersionDiffPreview.vue +0 -167
  186. package/src/vue/use-business-types.ts +0 -269
@@ -2,21 +2,18 @@
2
2
  <div class="mc-admin">
3
3
  <div class="mc-admin-head">
4
4
  <div style="flex: 1">
5
- <div class="mc-admin-title">Marketing-Verwaltung</div>
6
- <div class="mc-admin-sub">
7
- Sichtbarkeit, Reihenfolge &amp; Highlight-Badges pro Plan · Edits gehen direkt
8
- live
9
- </div>
5
+ <div class="mc-admin-title">{{ msg.tabs.admin }}</div>
6
+ <div class="mc-admin-sub">{{ msg.admin.subtitle }}</div>
10
7
  </div>
11
8
  </div>
12
9
 
13
10
  <div class="mc-admin-grid">
14
11
  <div class="mc-admin-thead">
15
- <div>Plan</div>
16
- <div>Sichtbar</div>
17
- <div>Badge</div>
18
- <div>Priorität</div>
19
- <div>Highlight</div>
12
+ <div>{{ msg.admin.colPlan }}</div>
13
+ <div>{{ msg.admin.colVisible }}</div>
14
+ <div>{{ msg.admin.colBadge }}</div>
15
+ <div>{{ msg.admin.colPriority }}</div>
16
+ <div>{{ msg.admin.colHighlight }}</div>
20
17
  <div></div>
21
18
  </div>
22
19
 
@@ -45,7 +42,9 @@
45
42
  v-if="row.publishedVersions.length > 1"
46
43
  class="mc-version-tabs"
47
44
  role="tablist"
48
- :aria-label="`Plan-Versionen für ${row.plan.label}`"
45
+ :aria-label="
46
+ formatMessage(msg.admin.versionTabsLabel, { plan: row.plan.label })
47
+ "
49
48
  >
50
49
  <button
51
50
  v-for="v in row.publishedVersions"
@@ -107,23 +106,23 @@
107
106
  </div>
108
107
  <div class="mc-admin-row-end">
109
108
  <span v-if="!row.liveVersion" class="mc-chip mc-chip--muted">
110
- keine Live-Version
109
+ {{ msg.admin.noLiveVersion }}
111
110
  </span>
112
111
  <span v-else-if="!row.m.visible" class="mc-chip mc-chip--muted">
113
- versteckt
112
+ {{ msg.admin.hidden }}
114
113
  </span>
115
114
  <span v-else-if="row.m.highlight" class="mc-chip mc-chip--featured">
116
- Featured
115
+ {{ msg.admin.featured }}
117
116
  </span>
118
- <span v-else class="mc-chip mc-chip--live">live</span>
117
+ <span v-else class="mc-chip mc-chip--live">{{ msg.admin.live }}</span>
119
118
  <button
120
119
  v-if="row.liveVersion"
121
120
  type="button"
122
121
  class="mc-expand-btn"
123
122
  :title="
124
123
  expandedKey === row.plan.planKey
125
- ? 'Schließen'
126
- : 'Teaser, Trial & Top-Features bearbeiten'
124
+ ? common.close
125
+ : msg.admin.expandTitle
127
126
  "
128
127
  @click="$emit('toggle-expand', row)"
129
128
  >
@@ -151,19 +150,27 @@
151
150
  <div class="mc-expand-col">
152
151
  <div class="mc-expand-sec">
153
152
  <div class="mc-field-head">
154
- <label class="mc-expand-label">Plan-Name</label>
153
+ <label class="mc-expand-label">
154
+ {{ msg.admin.planNameLabel }}
155
+ </label>
155
156
  <span
156
157
  v-if="activeLocale !== defaultLocale"
157
158
  class="mc-source-hint"
158
159
  >
159
160
  {{ defaultLocale.toUpperCase() }}:
160
- <em>„{{ row.plan.label }}"</em>
161
+ <em>
162
+ {{
163
+ formatMessage(msg.admin.planNameSourceValue, {
164
+ label: row.plan.label,
165
+ })
166
+ }}
167
+ </em>
161
168
  </span>
162
169
  </div>
163
170
  <div v-if="activeLocale === defaultLocale" class="mc-locked-value">
164
171
  <span>{{ row.plan.label }}</span>
165
172
  <span class="mc-locked-hint">
166
- wird in den Plan-Stammdaten gepflegt
173
+ {{ msg.admin.planNameLocked }}
167
174
  </span>
168
175
  </div>
169
176
  <input
@@ -178,29 +185,31 @@
178
185
  v-if="activeLocale !== defaultLocale && !row.m.displayLabel"
179
186
  class="mc-expand-hint"
180
187
  >
181
- leer · Fallback auf „{{ row.plan.label }}" wird verwendet
188
+ {{
189
+ formatMessage(msg.admin.planNameFallbackHint, {
190
+ label: row.plan.label,
191
+ })
192
+ }}
182
193
  </div>
183
194
  </div>
184
195
 
185
196
  <div class="mc-expand-sec">
186
- <label class="mc-expand-label">Teaser-Text</label>
197
+ <label class="mc-expand-label">{{ msg.admin.teaserLabel }}</label>
187
198
  <textarea
188
199
  class="mc-field mc-field--area"
189
200
  rows="2"
190
- placeholder="Kurzbeschreibung für die Pricing-Page …"
201
+ :placeholder="msg.admin.teaserPlaceholder"
191
202
  :value="row.m.description"
192
203
  :disabled="busy"
193
204
  @change="
194
205
  $emit('patch', row, { description: textValue($event) })
195
206
  "
196
207
  />
197
- <div class="mc-expand-hint">
198
- erscheint unter dem Plannamen in der Vorschau
199
- </div>
208
+ <div class="mc-expand-hint">{{ msg.admin.teaserHint }}</div>
200
209
  </div>
201
210
 
202
211
  <div class="mc-expand-sec">
203
- <label class="mc-expand-label">Kostenlose Testphase</label>
212
+ <label class="mc-expand-label">{{ msg.admin.trialLabel }}</label>
204
213
  <div class="mc-trial-row">
205
214
  <label class="mc-toggle">
206
215
  <input
@@ -216,7 +225,11 @@
216
225
  <span />
217
226
  </label>
218
227
  <span class="mc-trial-label">
219
- {{ row.m.trialEnabled ? 'Trial aktiv' : 'Kein Trial' }}
228
+ {{
229
+ row.m.trialEnabled
230
+ ? msg.admin.trialOn
231
+ : msg.admin.trialOff
232
+ }}
220
233
  </span>
221
234
  <span class="mc-trial-days">
222
235
  <input
@@ -233,19 +246,18 @@
233
246
  })
234
247
  "
235
248
  />
236
- <span class="mc-trial-unit">Tage</span>
249
+ <span class="mc-trial-unit">
250
+ {{ msg.admin.trialDaysUnit }}
251
+ </span>
237
252
  </span>
238
253
  </div>
239
- <div class="mc-expand-hint">
240
- CTA-Text generiert sich automatisch („Jetzt
241
- {{ row.m.trialDays }} Tage testen“).
242
- </div>
254
+ <div class="mc-expand-hint">{{ trialCtaHint(row) }}</div>
243
255
  </div>
244
256
 
245
257
  <div class="mc-expand-sec">
246
- <label class="mc-expand-label"
247
- >CTA-Text überschreiben (optional)</label
248
- >
258
+ <label class="mc-expand-label">
259
+ {{ msg.admin.ctaOverrideLabel }}
260
+ </label>
249
261
  <input
250
262
  class="mc-field"
251
263
  :placeholder="autoCtaText(row)"
@@ -257,7 +269,7 @@
257
269
  })
258
270
  "
259
271
  />
260
- <div class="mc-expand-hint">leer lassen für Auto-Text</div>
272
+ <div class="mc-expand-hint">{{ msg.admin.ctaOverrideHint }}</div>
261
273
  </div>
262
274
  </div>
263
275
 
@@ -265,10 +277,14 @@
265
277
  <div class="mc-expand-sec">
266
278
  <div class="mc-tf-head">
267
279
  <label class="mc-expand-label" style="margin: 0">
268
- Top-Features
280
+ {{ msg.topFeatures }}
269
281
  </label>
270
282
  <span class="mc-expand-hint" style="margin-left: auto">
271
- {{ editFeatures.length }} Einträge
283
+ {{
284
+ formatMessage(msg.admin.topFeatureCount, {
285
+ count: editFeatures.length,
286
+ })
287
+ }}
272
288
  </span>
273
289
  </div>
274
290
 
@@ -280,7 +296,7 @@
280
296
  :placeholder="
281
297
  f.key
282
298
  ? resolveComponentLabel(f.key)
283
- : 'z. B. Beitragsverwaltung'
299
+ : msg.admin.featureLabelPlaceholder
284
300
  "
285
301
  :value="f.label"
286
302
  :disabled="busy"
@@ -291,7 +307,7 @@
291
307
  />
292
308
  <input
293
309
  class="mc-field mc-tf-strong"
294
- placeholder="Highlight, z. B. bis 100"
310
+ :placeholder="msg.admin.featureStrongPlaceholder"
295
311
  :value="f.strong"
296
312
  :disabled="busy"
297
313
  @input="
@@ -303,7 +319,7 @@
303
319
  <button
304
320
  type="button"
305
321
  class="mc-iconbtn"
306
- title="Nach oben"
322
+ :title="msg.admin.moveUp"
307
323
  :disabled="i === 0 || busy"
308
324
  @click="$emit('move-feature', row, i, -1)"
309
325
  >
@@ -312,7 +328,7 @@
312
328
  <button
313
329
  type="button"
314
330
  class="mc-iconbtn"
315
- title="Nach unten"
331
+ :title="msg.admin.moveDown"
316
332
  :disabled="i === editFeatures.length - 1 || busy"
317
333
  @click="$emit('move-feature', row, i, 1)"
318
334
  >
@@ -321,7 +337,7 @@
321
337
  <button
322
338
  type="button"
323
339
  class="mc-iconbtn mc-iconbtn--danger"
324
- title="Entfernen"
340
+ :title="common.remove"
325
341
  :disabled="busy"
326
342
  @click="$emit('remove-feature', row, i)"
327
343
  >
@@ -339,8 +355,7 @@
339
355
  </div>
340
356
  </div>
341
357
  <div v-if="editFeatures.length === 0" class="mc-tf-empty">
342
- Noch keine Top-Features — füge Plan-Komponenten oder freien
343
- Text hinzu.
358
+ {{ msg.admin.topFeaturesEmpty }}
344
359
  </div>
345
360
  </div>
346
361
 
@@ -361,20 +376,26 @@
361
376
  >
362
377
  <path d="M12 5v14M5 12h14" />
363
378
  </svg>
364
- <span>Eigener Eintrag</span>
379
+ <span>{{ msg.admin.addCustomFeature }}</span>
365
380
  </button>
366
381
  <div
367
382
  v-if="suggestionsFor(row).length > 0"
368
383
  class="mc-tf-suggestions"
369
384
  >
370
- <span class="mc-expand-hint">aus Plan-Komponenten:</span>
385
+ <span class="mc-expand-hint">
386
+ {{ msg.admin.suggestionsLabel }}
387
+ </span>
371
388
  <button
372
389
  v-for="(s, i) in suggestionsFor(row)"
373
390
  :key="i"
374
391
  type="button"
375
392
  class="mc-tf-chip"
376
393
  :disabled="busy"
377
- :title="`„${s.label}“ als Top-Feature übernehmen`"
394
+ :title="
395
+ formatMessage(msg.admin.addSuggestionTitle, {
396
+ label: s.label,
397
+ })
398
+ "
378
399
  @click="$emit('add-suggestion', row, s)"
379
400
  >
380
401
  <svg
@@ -403,6 +424,8 @@
403
424
 
404
425
  <script setup lang="ts">
405
426
  import type { MarketingTopFeature, PlanRow, PlanVersionRow } from '@saasicat/types';
427
+ import { formatMessage } from '../../client/i18n/format.js';
428
+ import { useSaMessages } from '../../vue/use-super-admin-i18n.js';
406
429
  import type { FeatureSuggestion, MarketingRow, ResolvedMarketing } from './types.js';
407
430
 
408
431
  defineProps<{
@@ -434,6 +457,15 @@ defineEmits<{
434
457
  (e: 'add-suggestion', row: MarketingRow, suggestion: FeatureSuggestion): void;
435
458
  }>();
436
459
 
460
+ const msg = useSaMessages('marketing');
461
+ const common = useSaMessages('common');
462
+
463
+ /** Hint below the trial toggle — shows the auto CTA text for the set trial days. */
464
+ function trialCtaHint(row: MarketingRow): string {
465
+ const cta = formatMessage(msg.value.cta.trial, { days: row.m.trialDays });
466
+ return formatMessage(msg.value.admin.ctaAutoHint, { cta });
467
+ }
468
+
437
469
  function textValue(event: Event): string {
438
470
  return (event.target as HTMLInputElement | HTMLTextAreaElement | null)?.value ?? '';
439
471
  }
@@ -1,15 +1,12 @@
1
1
  <template>
2
2
  <div class="mc-page-head">
3
3
  <div>
4
- <h2 class="mc-h-title">Marketing-Catalog</h2>
5
- <p class="mc-h-sub">
6
- Öffentliche Marketing-Projektion · gefilterte Sicht für Website, Pricing-Page und
7
- Checkout
8
- </p>
4
+ <h2 class="mc-h-title">{{ msg.header.title }}</h2>
5
+ <p class="mc-h-sub">{{ msg.header.subtitle }}</p>
9
6
  </div>
10
7
  <div class="mc-head-actions">
11
8
  <div class="mc-locale-mgr">
12
- <span class="mc-locale-mgr-label">Sprachen:</span>
9
+ <span class="mc-locale-mgr-label">{{ msg.header.localesLabel }}</span>
13
10
  <span
14
11
  v-for="loc in activeLocaleSet"
15
12
  :key="loc"
@@ -22,13 +19,15 @@
22
19
  @click="$emit('localeChange', loc)"
23
20
  >
24
21
  {{ loc.toUpperCase() }}
25
- <span v-if="loc === defaultLocale" title="Default-Sprache">★</span>
22
+ <span v-if="loc === defaultLocale" :title="msg.header.defaultLocale"
23
+ >★</span
24
+ >
26
25
  </button>
27
26
  <button
28
27
  v-if="loc !== defaultLocale"
29
28
  type="button"
30
29
  class="mc-locale-x"
31
- title="Sprache deaktivieren"
30
+ :title="msg.header.deactivateLocale"
32
31
  @click="$emit('removeLocale', loc)"
33
32
  >
34
33
  ×
@@ -41,7 +40,7 @@
41
40
  :disabled="addableLocales.length === 0"
42
41
  @click="$emit('update:localePickerOpen', !localePickerOpen)"
43
42
  >
44
- + Sprache
43
+ {{ msg.header.addLocale }}
45
44
  </button>
46
45
  <div v-if="localePickerOpen" class="mc-locale-picker">
47
46
  <button
@@ -67,13 +66,15 @@
67
66
  >
68
67
  <path d="M21 12a9 9 0 1 1-3-6.7M21 3v6h-6" />
69
68
  </svg>
70
- <span>Aktualisieren</span>
69
+ <span>{{ msg.header.refresh }}</span>
71
70
  </button>
72
71
  </div>
73
72
  </div>
74
73
  </template>
75
74
 
76
75
  <script setup lang="ts">
76
+ import { useSaMessages } from '../../vue/use-super-admin-i18n.js';
77
+
77
78
  defineProps<{
78
79
  activeLocaleSet: string[];
79
80
  activeLocale: string;
@@ -90,4 +91,6 @@ defineEmits<{
90
91
  (e: 'update:localePickerOpen', value: boolean): void;
91
92
  (e: 'reload'): void;
92
93
  }>();
94
+
95
+ const msg = useSaMessages('marketing');
93
96
  </script>
@@ -7,15 +7,13 @@
7
7
  <div class="mc-chrome-url">{{ previewUrl }}</div>
8
8
  </div>
9
9
  <div class="mc-canvas">
10
- <div class="mc-eyebrow">Preise &amp; Pakete</div>
11
- <h1 class="mc-hero">Der passende Plan</h1>
12
- <p class="mc-sub">
13
- Flexibel skalieren, jederzeit upgraden. Kein Setup-Fee, monatlich kündbar.
14
- </p>
10
+ <div class="mc-eyebrow">{{ msg.preview.eyebrow }}</div>
11
+ <h1 class="mc-hero">{{ msg.preview.hero }}</h1>
12
+ <p class="mc-sub">{{ msg.preview.sub }}</p>
15
13
 
16
14
  <div v-if="visibleRows.length === 0" class="mc-banner mc-banner--info">
17
- Kein Plan ist aktuell für den Public-Catalog sichtbar. Aktiviere die Sichtbarkeit im
18
- Tab <strong>Marketing-Verwaltung</strong>.
15
+ {{ msg.preview.emptyBefore }} <strong>{{ msg.tabs.admin }}</strong
16
+ >{{ msg.preview.emptyAfter }}
19
17
  </div>
20
18
 
21
19
  <div v-else class="mc-grid">
@@ -49,42 +47,46 @@
49
47
  </template>
50
48
  <template v-else-if="!row.liveVersion">
51
49
  <span class="mc-card-price-big" style="font-size: 22px">
52
- Auf Anfrage
50
+ {{ msg.preview.priceOnRequest }}
53
51
  </span>
54
52
  </template>
55
53
  <template v-else-if="promoResultOf(row)">
56
54
  <span class="mc-card-price-big">
57
55
  {{ formatEuro(promoResultOf(row)?.discounted ?? 0) }}
58
56
  </span>
59
- <span class="mc-card-price-unit">/ Monat</span>
57
+ <span class="mc-card-price-unit">{{ msg.preview.perMonth }}</span>
60
58
  </template>
61
59
  <template v-else>
62
60
  <span class="mc-card-price-big">
63
61
  {{ formatEuro(monthlyOf(row)) }}
64
62
  </span>
65
- <span class="mc-card-price-unit">/ Monat</span>
63
+ <span class="mc-card-price-unit">{{ msg.preview.perMonth }}</span>
66
64
  </template>
67
65
  </div>
68
66
  <div v-if="promoResultOf(row)" class="mc-card-price-strike">
69
67
  <s>{{ formatEuro(promoResultOf(row)?.original ?? 0) }}</s>
70
- <span class="mc-price-regular">regulär</span>
68
+ <span class="mc-price-regular">{{ msg.preview.regularPrice }}</span>
71
69
  </div>
72
70
  <div
73
71
  v-else-if="row.liveVersion && yearlyOf(row) > 0 && !row.m.priceTag"
74
72
  class="mc-card-price-y"
75
73
  >
76
- oder {{ formatEuro(yearlyOf(row)) }} jährlich
74
+ {{
75
+ formatMessage(msg.preview.orYearly, {
76
+ price: formatEuro(yearlyOf(row)),
77
+ })
78
+ }}
77
79
  </div>
78
80
 
79
81
  <button type="button" class="mc-card-cta">{{ ctaText(row) }}</button>
80
82
  <div v-if="showTrialNote(row) && !promoOf(row)" class="mc-card-trialnote">
81
- {{ row.m.trialDays }} Tage kostenlos · keine Kreditkarte nötig
83
+ {{ formatMessage(msg.preview.trialNote, { days: row.m.trialDays }) }}
82
84
  </div>
83
85
  <div v-if="promoFineprintOf(row)" class="mc-card-fineprint">
84
86
  {{ promoFineprintOf(row) }}
85
87
  </div>
86
88
 
87
- <div class="mc-card-includes">Top-Features</div>
89
+ <div class="mc-card-includes">{{ msg.topFeatures }}</div>
88
90
  <ul v-if="row.m.topFeatures.length > 0" class="mc-card-features">
89
91
  <li v-for="(f, i) in row.m.topFeatures" :key="i">
90
92
  <span class="mc-tick">
@@ -105,7 +107,9 @@
105
107
  </span>
106
108
  </li>
107
109
  </ul>
108
- <div v-else class="mc-card-features-empty">Keine Top-Features gepflegt.</div>
110
+ <div v-else class="mc-card-features-empty">
111
+ {{ msg.preview.noTopFeatures }}
112
+ </div>
109
113
  </div>
110
114
  </div>
111
115
  </div>
@@ -113,11 +117,9 @@
113
117
  </template>
114
118
 
115
119
  <script setup lang="ts">
116
- import type {
117
- MarketingTopFeature,
118
- PromotionResult,
119
- PromotionRow,
120
- } from '@saasicat/types';
120
+ import type { MarketingTopFeature, PromotionResult, PromotionRow } from '@saasicat/types';
121
+ import { formatMessage } from '../../client/i18n/format.js';
122
+ import { useSaMessages } from '../../vue/use-super-admin-i18n.js';
121
123
  import type { MarketingRow } from './types.js';
122
124
 
123
125
  defineProps<{
@@ -135,4 +137,6 @@ defineProps<{
135
137
  showTrialNote: (row: MarketingRow) => boolean;
136
138
  topFeatureLabel: (feature: MarketingTopFeature) => string;
137
139
  }>();
140
+
141
+ const msg = useSaMessages('marketing');
138
142
  </script>
@@ -7,7 +7,7 @@
7
7
  :class="{ active: tab === 'preview' }"
8
8
  @click="$emit('update:tab', 'preview')"
9
9
  >
10
- Public-Catalog Vorschau
10
+ {{ msg.tabs.preview }}
11
11
  </button>
12
12
  <button
13
13
  type="button"
@@ -15,7 +15,7 @@
15
15
  :class="{ active: tab === 'admin' }"
16
16
  @click="$emit('update:tab', 'admin')"
17
17
  >
18
- Marketing-Verwaltung
18
+ {{ msg.tabs.admin }}
19
19
  </button>
20
20
  <button
21
21
  type="button"
@@ -23,7 +23,7 @@
23
23
  :class="{ active: tab === 'promos' }"
24
24
  @click="$emit('update:tab', 'promos')"
25
25
  >
26
- Aktionen
26
+ {{ msg.tabs.promos }}
27
27
  <span v-if="activePromoCount > 0" class="mc-tab-count">
28
28
  {{ activePromoCount }}
29
29
  </span>
@@ -43,6 +43,7 @@
43
43
  </template>
44
44
 
45
45
  <script setup lang="ts">
46
+ import { useSaMessages } from '../../vue/use-super-admin-i18n.js';
46
47
  import type { MarketingCatalogTab } from './types.js';
47
48
 
48
49
  defineProps<{
@@ -55,4 +56,6 @@ defineProps<{
55
56
  defineEmits<{
56
57
  (e: 'update:tab', tab: MarketingCatalogTab): void;
57
58
  }>();
59
+
60
+ const msg = useSaMessages('marketing');
58
61
  </script>
@@ -6,7 +6,7 @@
6
6
  {{ title }}
7
7
  <span v-if="versionNew" class="sa-pv-diff-card__ver">v{{ versionNew }}</span>
8
8
  </div>
9
- <div class="sa-pv-diff-card__sub">Keine Änderungen</div>
9
+ <div class="sa-pv-diff-card__sub">{{ common.noChanges }}</div>
10
10
  </div>
11
11
  </div>
12
12
  <div v-else class="sa-pv-diff-card">
@@ -27,9 +27,7 @@
27
27
  <span v-else-if="versionOld != null" class="sa-pv-diff-card__ver"
28
28
  >− v{{ versionOld }}</span
29
29
  >
30
- <span class="sa-pv-diff-card__count">
31
- {{ changes.length }} Änderung{{ changes.length !== 1 ? 'en' : '' }}
32
- </span>
30
+ <span class="sa-pv-diff-card__count">{{ changeCountLabel }}</span>
33
31
  </header>
34
32
  <div class="sa-pv-diff-card__body">
35
33
  <VersionDiffPreview :changes="changes" :field-labels="fieldLabels" />
@@ -38,10 +36,13 @@
38
36
  </template>
39
37
 
40
38
  <script setup lang="ts">
39
+ import { computed } from 'vue';
41
40
  import type { VersionChange } from '@saasicat/types';
42
- import VersionDiffPreview from './VersionDiffPreview.vue';
41
+ import { formatMessage } from '../../client/i18n/format.js';
42
+ import { useSaMessages } from '../../vue/use-super-admin-i18n.js';
43
+ import VersionDiffPreview from '../../components/VersionDiffPreview.vue';
43
44
 
44
- defineProps<{
45
+ const props = defineProps<{
45
46
  title: string;
46
47
  versionOld: number | null;
47
48
  versionNew: number | null;
@@ -49,6 +50,15 @@ defineProps<{
49
50
  changes: VersionChange[];
50
51
  fieldLabels?: Record<string, string>;
51
52
  }>();
53
+
54
+ const msg = useSaMessages('planVersions');
55
+ const common = useSaMessages('common');
56
+
57
+ const changeCountLabel = computed(() => {
58
+ const count = props.changes.length;
59
+ const template = count === 1 ? msg.value.diff.changeCountOne : msg.value.diff.changeCountMany;
60
+ return formatMessage(template, { count });
61
+ });
52
62
  </script>
53
63
 
54
64
  <style scoped>