@saasicat/ui-vue 0.21.0 → 0.22.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/dist/{catalog-BY_t9prv.d.cts → catalog-DJcfm5N2.d.cts} +20 -7
  2. package/dist/{catalog-BY_t9prv.d.ts → catalog-DJcfm5N2.d.ts} +20 -7
  3. package/dist/{chunk-JN6HZGLV.js → chunk-F7NRM6KI.js} +54 -28
  4. package/dist/{chunk-7IFKVGZV.js → chunk-LY52T4N4.js} +21 -2
  5. package/dist/{chunk-OTP3OSSW.js → chunk-XMMFN2WJ.js} +74 -3
  6. package/dist/client/index.cjs +132 -29
  7. package/dist/client/index.d.cts +53 -3
  8. package/dist/client/index.d.ts +53 -3
  9. package/dist/client/index.js +14 -2
  10. package/dist/index.cjs +319 -162
  11. package/dist/index.d.cts +30 -8
  12. package/dist/index.d.ts +30 -8
  13. package/dist/index.js +176 -133
  14. package/dist/quasar/index.cjs +76 -29
  15. package/dist/quasar/index.d.cts +2 -2
  16. package/dist/quasar/index.d.ts +2 -2
  17. package/dist/quasar/index.js +6 -2
  18. package/dist/testing-e2e/admin-pages-suite.d.cts +37 -0
  19. package/dist/testing-e2e/admin-pages-suite.d.ts +37 -0
  20. package/dist/{use-super-admin-i18n-c_Eqsu9u.d.ts → use-super-admin-i18n-CHNdsSlm.d.ts} +34 -7
  21. package/dist/{use-super-admin-i18n-DlJRGIVq.d.cts → use-super-admin-i18n-CgTuNi8h.d.cts} +34 -7
  22. package/package.json +18 -8
  23. package/src/client/i18n/messages/bundles.ts +0 -2
  24. package/src/client/i18n/messages/common.ts +22 -0
  25. package/src/client/i18n/messages/discovery.ts +2 -2
  26. package/src/client/i18n/messages/marketing.ts +2 -4
  27. package/src/client/i18n/messages/plan-detail.ts +0 -4
  28. package/src/client/i18n/messages/plans.ts +20 -8
  29. package/src/client/i18n/messages/tenants.ts +0 -2
  30. package/src/client/index.ts +1 -0
  31. package/src/client/manifest-loader.ts +1 -1
  32. package/src/client/resolve-plans.ts +144 -0
  33. package/src/components/BundleVersionPublishDialog.vue +6 -6
  34. package/src/components/KvBlock.vue +4 -4
  35. package/src/components/MarketingPromotionsTab.vue +34 -48
  36. package/src/components/MfaPromptDialog.vue +8 -2
  37. package/src/components/TenantActionConfirmDialog.vue +4 -4
  38. package/src/components/VersionDiffPreview.vue +7 -7
  39. package/src/components/admin-page/AdminFilters.vue +12 -0
  40. package/src/components/admin-page/AdminHero.vue +22 -5
  41. package/src/components/admin-page/AdminKpi.vue +84 -0
  42. package/src/components/admin-page/AdminPaginator.vue +195 -0
  43. package/src/components/admin-page/AdminRefreshBtn.vue +39 -0
  44. package/src/components/admin-page/AdminSection.vue +31 -16
  45. package/src/components/admin-page/AdminStatistics.vue +40 -0
  46. package/src/components/admin-page/AdminTable.vue +175 -0
  47. package/src/components/bundle-editor/BundleCreatePanel.vue +23 -23
  48. package/src/components/bundle-editor/BundleFeaturesEditor.vue +7 -7
  49. package/src/components/bundle-editor/BundlePlanCompatPicker.vue +9 -9
  50. package/src/components/bundle-editor/BundleQuotasEditor.vue +11 -11
  51. package/src/components/bundle-editor/BundleStatusBanner.vue +6 -6
  52. package/src/components/bundle-editor/BundleVersionInlineEditor.vue +18 -18
  53. package/src/components/bundle-editor/BundleVersionStrip.vue +12 -12
  54. package/src/components/dialogs/PilotCreateDialog.vue +12 -12
  55. package/src/components/dialogs/PilotEditDialog.vue +7 -7
  56. package/src/components/dialogs/PromoCodeCreateDialog.vue +8 -8
  57. package/src/components/dialogs/PromoCodeDialogFields.vue +33 -19
  58. package/src/components/dialogs/PromoCodeEditDialog.vue +10 -10
  59. package/src/components/plan/PlanGrid.vue +1 -1
  60. package/src/components/plan-create-dialog/PlanCreateDialog.vue +34 -46
  61. package/src/components/plan-detail/PlanDetail.vue +92 -302
  62. package/src/components/plan-detail/PlanDetailKpis.vue +22 -27
  63. package/src/components/plan-detail/PlanTitleEdit.vue +133 -0
  64. package/src/components/plan-list/PlanList.vue +72 -290
  65. package/src/components/plan-matrix/PlanMatrix.vue +66 -183
  66. package/src/components/plan-review/PlanReview.vue +191 -275
  67. package/src/components/plan-version-editor/PlanCatalogPreview.vue +7 -5
  68. package/src/components/plan-version-editor/PlanVersionEditor.vue +200 -295
  69. package/src/components/plan-version-editor/PlanVersionEditorHeader.vue +23 -55
  70. package/src/index.ts +1 -0
  71. package/src/pages-standard/AdminLayout.vue +34 -10
  72. package/src/pages-standard/AdminManifestErrorPage.vue +79 -9
  73. package/src/pages-standard/AuditPage.vue +53 -72
  74. package/src/pages-standard/BundlesPage.vue +128 -144
  75. package/src/pages-standard/DashboardPage.vue +43 -107
  76. package/src/pages-standard/DiscoveryPage.vue +158 -200
  77. package/src/pages-standard/EmailHistoryPage.vue +98 -88
  78. package/src/pages-standard/MarketingCatalogPage.vue +237 -267
  79. package/src/pages-standard/PilotsPage.vue +44 -60
  80. package/src/pages-standard/PlansPage.vue +230 -105
  81. package/src/pages-standard/PlatformEmailPage.vue +37 -40
  82. package/src/pages-standard/PromoCodeDetailPage.vue +16 -30
  83. package/src/pages-standard/PromoCodesPage.vue +86 -112
  84. package/src/pages-standard/SubscriptionsPage.vue +10 -17
  85. package/src/pages-standard/SuperAdminLoginPage.vue +12 -12
  86. package/src/pages-standard/SuperAdminSetupWizard.vue +20 -17
  87. package/src/pages-standard/TenantDetailPage.vue +45 -41
  88. package/src/pages-standard/TenantsPage.vue +184 -264
  89. package/src/pages-standard/UsersPage.vue +69 -104
  90. package/src/pages-standard/bundles-page/BundleAccordionList.vue +20 -17
  91. package/src/pages-standard/bundles-page/BundlesKpis.vue +13 -22
  92. package/src/pages-standard/bundles-page/BundlesToolbar.vue +6 -10
  93. package/src/pages-standard/discovery-page/CatalogEntryTransPanel.vue +10 -10
  94. package/src/pages-standard/discovery-page/DiscoveryCapList.vue +5 -5
  95. package/src/pages-standard/discovery-page/DiscoveryFeatureCard.vue +16 -16
  96. package/src/pages-standard/discovery-page/DiscoveryKpis.vue +31 -27
  97. package/src/pages-standard/discovery-page/DiscoveryQuotaCard.vue +7 -7
  98. package/src/pages-standard/marketing-catalog/MarketingCatalogAdmin.vue +1 -1
  99. package/src/pages-standard/marketing-catalog/MarketingCatalogHeader.vue +2 -13
  100. package/src/pages-standard/plan-versions/PlanDiffCard.vue +6 -6
  101. package/src/pages-standard/plan-versions/PlanVersionsDiff.vue +6 -6
  102. package/src/pages-standard/plan-versions/PlanVersionsTimeline.vue +16 -16
  103. package/src/pages-standard/plans-page/PlanBundleOverview.vue +14 -29
  104. package/src/pages-standard/plans-page/PlanPublishDialog.vue +1 -1
  105. package/src/pages-standard/plans-page/PlansPageToast.vue +1 -1
  106. package/src/pages-standard/sa-theme.css +481 -71
  107. package/src/pages-standard/tenant-detail/TenantUsers.vue +2 -8
  108. package/src/pages-standard/tenants/StatusPill.vue +2 -2
  109. package/src/pages-tenant/MySubscriptionBundlesPage.vue +25 -25
  110. package/src/pages-tenant/OnboardingConfigurator.vue +1 -5
  111. package/src/pages-tenant/PackageSnapshotPanel.vue +1 -1
  112. package/src/pages-tenant/TenantPlanSection.vue +12 -20
  113. package/src/quasar/create-super-admin-app.ts +4 -0
  114. package/src/vue/entitlement-provider.ts +0 -1
  115. package/src/vue/feature-router-guard.ts +0 -1
  116. package/src/vue/super-admin-context.ts +106 -1
  117. package/src/vue/use-api-list.ts +2 -1
  118. package/src/vue/use-pagination.ts +63 -0
  119. package/src/vue/use-plans.ts +1 -2
  120. package/src/vue/use-sign-out.ts +90 -0
  121. package/src/vue/use-tenant-billing.ts +1 -1
  122. package/src/vue/use-tenant-manifest.ts +0 -1
  123. package/src/components/KpiCard.vue +0 -53
  124. package/src/components/plan-cockpit/PlanCockpit.vue +0 -1027
  125. package/src/components/plan-cockpit/PlanCockpitAuditLog.vue +0 -72
  126. package/src/components/plan-cockpit/PlanCockpitDiffPanel.vue +0 -99
  127. package/src/components/plan-cockpit/PlanCockpitHeader.vue +0 -101
  128. package/src/components/plan-cockpit/PlanCockpitImpactPanel.vue +0 -112
  129. package/src/components/plan-cockpit/PlanCockpitKpis.vue +0 -68
  130. package/src/components/plan-cockpit/PlanCockpitVersions.vue +0 -249
  131. package/src/components/plan-cockpit/types.ts +0 -72
  132. package/src/components/plan-detail/PlanDetailHeader.vue +0 -194
@@ -110,7 +110,7 @@ function statusMetaOf(v: BundleVersionRow): BundleStatusMeta {
110
110
  gap: 8px;
111
111
  padding: 14px 16px;
112
112
  background: #fbfbfd;
113
- border: 1px solid var(--bv-border, #e5e7eb);
113
+ border: 1px solid var(--bv-border, var(--sa-border));
114
114
  border-radius: 10px;
115
115
  }
116
116
  .bv-vstrip-label {
@@ -118,7 +118,7 @@ function statusMetaOf(v: BundleVersionRow): BundleStatusMeta {
118
118
  font-weight: 700;
119
119
  text-transform: uppercase;
120
120
  letter-spacing: 0.1em;
121
- color: #64748b;
121
+ color: var(--sa-muted);
122
122
  }
123
123
  .bv-vstrip-tabs {
124
124
  display: flex;
@@ -135,11 +135,11 @@ function statusMetaOf(v: BundleVersionRow): BundleStatusMeta {
135
135
  align-items: center;
136
136
  padding: 8px 12px;
137
137
  background: #fff;
138
- border: 1px solid #e2e8f0;
138
+ border: 1px solid var(--sa-border);
139
139
  border-radius: 8px;
140
140
  cursor: pointer;
141
141
  font-family: inherit;
142
- color: #0f172a;
142
+ color: var(--sa-heading);
143
143
  text-align: left;
144
144
  transition:
145
145
  border-color 0.12s,
@@ -147,10 +147,10 @@ function statusMetaOf(v: BundleVersionRow): BundleStatusMeta {
147
147
  background 0.12s;
148
148
  }
149
149
  .bv-vtab:hover {
150
- background: #f8fafc;
150
+ background: var(--sa-bg-surface-2);
151
151
  }
152
152
  .bv-vtab-current {
153
- border-color: #2563eb;
153
+ border-color: var(--sa-primary);
154
154
  box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.12);
155
155
  }
156
156
  .bv-vtab-name {
@@ -178,8 +178,8 @@ function statusMetaOf(v: BundleVersionRow): BundleStatusMeta {
178
178
  color: #92400e;
179
179
  }
180
180
  .bv-vtab-status.superseded {
181
- background: #e2e8f0;
182
- color: #475569;
181
+ background: var(--sa-border);
182
+ color: var(--sa-muted-dark);
183
183
  }
184
184
  .bv-vtab-status.draft {
185
185
  background: #dbeafe;
@@ -188,12 +188,12 @@ function statusMetaOf(v: BundleVersionRow): BundleStatusMeta {
188
188
  .bv-vtab-dates {
189
189
  grid-column: 1 / -1;
190
190
  font-size: 11px;
191
- color: #64748b;
191
+ color: var(--sa-muted);
192
192
  }
193
193
  .bv-vtab-price {
194
194
  grid-column: 1 / -1;
195
195
  font-size: 11.5px;
196
- color: #475569;
196
+ color: var(--sa-muted-dark);
197
197
  font-weight: 600;
198
198
  }
199
199
 
@@ -204,12 +204,12 @@ function statusMetaOf(v: BundleVersionRow): BundleStatusMeta {
204
204
  padding: 8px 12px;
205
205
  background: #fff;
206
206
  border: 1px dashed #cbd5e1;
207
- color: #2563eb;
207
+ color: var(--sa-primary);
208
208
  font-size: 12.5px;
209
209
  font-weight: 600;
210
210
  }
211
211
  .bv-vtab-new:hover:not(:disabled) {
212
- background: #eff6ff;
212
+ background: var(--sa-primary-50);
213
213
  border-color: #93c5fd;
214
214
  }
215
215
  .bv-vtab-new:disabled {
@@ -1,8 +1,8 @@
1
1
  <template>
2
2
  <q-dialog
3
3
  :model-value="modelValue"
4
- @update:model-value="emit('update:modelValue', $event)"
5
4
  persistent
5
+ @update:model-value="emit('update:modelValue', $event)"
6
6
  >
7
7
  <q-card class="pl-dlg">
8
8
  <q-card-section class="pl-dlg__head">
@@ -11,12 +11,12 @@
11
11
  <div class="pl-dlg__sub">{{ subtitle ?? msg.createDialog.subtitle }}</div>
12
12
  </div>
13
13
  <q-btn
14
+ v-close-popup
14
15
  class="pl-dlg__close"
15
16
  flat
16
17
  dense
17
18
  round
18
19
  icon="close"
19
- v-close-popup
20
20
  :disable="loading"
21
21
  />
22
22
  </q-card-section>
@@ -237,7 +237,7 @@
237
237
  <q-icon name="send" size="14px" />
238
238
  {{ msg.createDialog.invitationHint }} <strong>{{ form.admin.email }}</strong>
239
239
  </span>
240
- <q-btn flat :label="common.cancel" v-close-popup :disable="loading" />
240
+ <q-btn v-close-popup flat :label="common.cancel" :disable="loading" />
241
241
  <q-btn
242
242
  unelevated
243
243
  color="primary"
@@ -491,7 +491,7 @@ async function doSubmit(code: string): Promise<void> {
491
491
 
492
492
  .pl-dlg__sub {
493
493
  font-size: 12.5px;
494
- color: var(--sa-muted, #64748b);
494
+ color: var(--sa-muted, var(--sa-muted));
495
495
  margin-top: 3px;
496
496
  line-height: 1.4;
497
497
  }
@@ -508,8 +508,8 @@ async function doSubmit(code: string): Promise<void> {
508
508
  align-items: center;
509
509
  gap: 6px;
510
510
  font-size: 12px;
511
- color: var(--sa-muted-dark, #475569);
512
- background: #eff6ff;
511
+ color: var(--sa-muted-dark, var(--sa-muted-dark));
512
+ background: var(--sa-primary-50);
513
513
  border: 1px solid #bfdbfe;
514
514
  border-radius: 999px;
515
515
  padding: 4px 12px;
@@ -539,7 +539,7 @@ async function doSubmit(code: string): Promise<void> {
539
539
  font: 600 11px var(--sa-font-body, system-ui, sans-serif);
540
540
  letter-spacing: 0.04em;
541
541
  text-transform: uppercase;
542
- color: var(--sa-muted, #64748b);
542
+ color: var(--sa-muted, var(--sa-muted));
543
543
  display: flex;
544
544
  align-items: baseline;
545
545
  gap: 6px;
@@ -549,7 +549,7 @@ async function doSubmit(code: string): Promise<void> {
549
549
  font-weight: 500;
550
550
  text-transform: none;
551
551
  letter-spacing: 0;
552
- color: #94a3b8;
552
+ color: var(--sa-muted-light);
553
553
  font-size: 11px;
554
554
  }
555
555
 
@@ -576,17 +576,17 @@ async function doSubmit(code: string): Promise<void> {
576
576
  display: flex;
577
577
  align-items: stretch;
578
578
  background: #fff;
579
- border: 1px solid var(--sa-border, #e2e8f0);
579
+ border: 1px solid var(--sa-border, var(--sa-border));
580
580
  border-radius: 8px;
581
581
  overflow: hidden;
582
582
  }
583
583
 
584
584
  .pl-slug-input__prefix {
585
585
  padding: 9px 12px;
586
- background: #f8fafc;
587
- color: #94a3b8;
586
+ background: var(--sa-bg-surface-2);
587
+ color: var(--sa-muted-light);
588
588
  font: 500 12px var(--sa-font-mono, ui-monospace, monospace);
589
- border-right: 1px solid var(--sa-border, #e2e8f0);
589
+ border-right: 1px solid var(--sa-border, var(--sa-border));
590
590
  white-space: nowrap;
591
591
  }
592
592
 
@@ -1,26 +1,26 @@
1
1
  <template>
2
2
  <q-dialog
3
3
  :model-value="modelValue"
4
- @update:model-value="emit('update:modelValue', $event)"
5
4
  persistent
5
+ @update:model-value="emit('update:modelValue', $event)"
6
6
  >
7
7
  <q-card class="pl-dlg">
8
8
  <q-card-section class="pl-dlg__head">
9
9
  <div>
10
10
  <div class="pl-dlg__title">{{ msg.editDialog.title }}</div>
11
- <div class="pl-dlg__sub" v-if="row">
11
+ <div v-if="row" class="pl-dlg__sub">
12
12
  <strong>{{ row.tenant.name }}</strong>
13
13
  <span class="pl-dlg__sep">·</span>
14
14
  <code>{{ row.tenant.slug }}</code>
15
15
  </div>
16
16
  </div>
17
17
  <q-btn
18
+ v-close-popup
18
19
  class="pl-dlg__close"
19
20
  flat
20
21
  dense
21
22
  round
22
23
  icon="close"
23
- v-close-popup
24
24
  :disable="loading"
25
25
  />
26
26
  </q-card-section>
@@ -122,7 +122,7 @@
122
122
  </q-card-section>
123
123
 
124
124
  <q-card-actions align="right" class="pl-dlg__foot">
125
- <q-btn flat :label="common.cancel" v-close-popup :disable="loading" />
125
+ <q-btn v-close-popup flat :label="common.cancel" :disable="loading" />
126
126
  <q-btn
127
127
  unelevated
128
128
  color="primary"
@@ -339,7 +339,7 @@ async function doSubmit(code: string): Promise<void> {
339
339
 
340
340
  .pl-dlg__sub {
341
341
  font-size: 12.5px;
342
- color: var(--sa-muted, #64748b);
342
+ color: var(--sa-muted, var(--sa-muted));
343
343
  margin-top: 3px;
344
344
  }
345
345
 
@@ -350,8 +350,8 @@ async function doSubmit(code: string): Promise<void> {
350
350
 
351
351
  .pl-dlg__sub code {
352
352
  font-family: var(--sa-font-mono, ui-monospace, monospace);
353
- background: #f1f5f9;
354
- color: var(--sa-muted-dark, #475569);
353
+ background: var(--sa-border-soft);
354
+ color: var(--sa-muted-dark, var(--sa-muted-dark));
355
355
  padding: 1px 6px;
356
356
  border-radius: 4px;
357
357
  font-size: 11.5px;
@@ -1,8 +1,8 @@
1
1
  <template>
2
2
  <q-dialog
3
3
  :model-value="modelValue"
4
- @update:model-value="emit('update:modelValue', $event)"
5
4
  persistent
5
+ @update:model-value="emit('update:modelValue', $event)"
6
6
  >
7
7
  <q-card class="pc-dlg">
8
8
  <q-card-section class="pc-dlg__head">
@@ -11,22 +11,22 @@
11
11
  <div class="pc-dlg__sub">{{ subtitle ?? msg.createDialog.subtitle }}</div>
12
12
  </div>
13
13
  <q-btn
14
+ v-close-popup
14
15
  class="pc-dlg__close"
15
16
  flat
16
17
  dense
17
18
  round
18
19
  icon="close"
19
- v-close-popup
20
20
  :disable="loading"
21
21
  />
22
22
  </q-card-section>
23
23
 
24
24
  <q-card-section class="pc-dlg__body">
25
25
  <PromoCodeDialogFields
26
- mode="create"
27
- :form="form"
28
26
  v-model:code="form.code"
29
27
  v-model:advanced-open="advancedOpen"
28
+ mode="create"
29
+ :form="form"
30
30
  :show-campaign-tag="showCampaignTag"
31
31
  :plans="plans"
32
32
  />
@@ -35,7 +35,7 @@
35
35
  </q-card-section>
36
36
 
37
37
  <q-card-actions align="right" class="pc-dlg__foot">
38
- <q-btn flat :label="common.cancel" v-close-popup :disable="loading" />
38
+ <q-btn v-close-popup flat :label="common.cancel" :disable="loading" />
39
39
  <q-btn
40
40
  unelevated
41
41
  color="primary"
@@ -190,12 +190,12 @@ async function onSubmit() {
190
190
  font-family: var(--sa-font-head, system-ui, sans-serif);
191
191
  font-weight: 700;
192
192
  font-size: 18px;
193
- color: var(--sa-heading, #0f172a);
193
+ color: var(--sa-heading, var(--sa-heading));
194
194
  }
195
195
 
196
196
  .pc-dlg__sub {
197
197
  font-size: 12.5px;
198
- color: var(--sa-muted, #64748b);
198
+ color: var(--sa-muted, var(--sa-muted));
199
199
  margin-top: 2px;
200
200
  }
201
201
 
@@ -207,7 +207,7 @@ async function onSubmit() {
207
207
  }
208
208
 
209
209
  .pc-dlg__foot {
210
- border-top: 1px solid var(--sa-border, #e2e8f0);
210
+ border-top: 1px solid var(--sa-border, var(--sa-border));
211
211
  }
212
212
 
213
213
  .pc-error {
@@ -1,4 +1,15 @@
1
1
  <template>
2
+ <!-- This block writes into the `form` prop, which both dialogs create as a
3
+ `reactive()` object and hand down; the type is named
4
+ `PromoCodeSharedForm` for exactly that reason. A deliberate shared-state
5
+ contract, not an oversight.
6
+
7
+ It is still the wrong shape: the field block cannot be reused with a
8
+ one-way owner, and the two dialogs around it are 115 lines of clone.
9
+ Both are replaced by `AdminFormDialog` + `AdminFieldGrid`, which own the
10
+ submit lifecycle instead of sharing a mutable object. Until then the
11
+ rule stays sharp everywhere else rather than being weakened repo-wide. -->
12
+ <!-- eslint-disable vue/no-mutating-props -->
2
13
  <!-- Section: Code & Discount -->
3
14
  <div class="pc-section">
4
15
  <div class="pc-section__title">{{ msg.form.sectionCodeDiscount }}</div>
@@ -353,11 +364,14 @@ function isPlanSelected(key: string): boolean {
353
364
  }
354
365
 
355
366
  function togglePlan(key: string): void {
367
+ // Same shared-`form` contract as the template above (see the comment there).
368
+ /* eslint-disable vue/no-mutating-props */
356
369
  if (props.form.appliesToPlans.includes(key)) {
357
370
  props.form.appliesToPlans = props.form.appliesToPlans.filter((k) => k !== key);
358
371
  } else {
359
372
  props.form.appliesToPlans = [...props.form.appliesToPlans, key];
360
373
  }
374
+ /* eslint-enable vue/no-mutating-props */
361
375
  }
362
376
 
363
377
  function planChipStyle(p: PromoCodePlanOption): Record<string, string> {
@@ -394,7 +408,7 @@ const advancedOpen = defineModel<boolean>('advancedOpen', { default: false });
394
408
 
395
409
  <style scoped>
396
410
  .pc-section {
397
- border: 1px solid var(--sa-border, #e2e8f0);
411
+ border: 1px solid var(--sa-border, var(--sa-border));
398
412
  border-radius: 10px;
399
413
  padding: 14px 16px;
400
414
  background: #fafbfc;
@@ -404,7 +418,7 @@ const advancedOpen = defineModel<boolean>('advancedOpen', { default: false });
404
418
  font-family: var(--sa-font-head, system-ui, sans-serif);
405
419
  font-weight: 700;
406
420
  font-size: 13px;
407
- color: var(--sa-heading, #0f172a);
421
+ color: var(--sa-heading, var(--sa-heading));
408
422
  margin-bottom: 12px;
409
423
  letter-spacing: -0.005em;
410
424
  }
@@ -414,7 +428,7 @@ const advancedOpen = defineModel<boolean>('advancedOpen', { default: false });
414
428
  background: transparent;
415
429
  cursor: pointer;
416
430
  font: 600 12.5px var(--sa-font-body, system-ui, sans-serif);
417
- color: var(--sa-muted-dark, #475569);
431
+ color: var(--sa-muted-dark, var(--sa-muted-dark));
418
432
  display: inline-flex;
419
433
  align-items: center;
420
434
  gap: 4px;
@@ -457,19 +471,19 @@ const advancedOpen = defineModel<boolean>('advancedOpen', { default: false });
457
471
  .pc-field__label {
458
472
  font-size: 11.5px;
459
473
  font-weight: 600;
460
- color: var(--sa-muted, #64748b);
474
+ color: var(--sa-muted, var(--sa-muted));
461
475
  text-transform: uppercase;
462
476
  letter-spacing: 0.04em;
463
477
  }
464
478
 
465
479
  .pc-field__hint {
466
480
  font-size: 11.5px;
467
- color: #94a3b8;
481
+ color: var(--sa-muted-light);
468
482
  }
469
483
 
470
484
  .pc-input {
471
485
  width: 100%;
472
- border: 1px solid var(--sa-border, #e2e8f0);
486
+ border: 1px solid var(--sa-border, var(--sa-border));
473
487
  background: #fff;
474
488
  border-radius: 7px;
475
489
  padding: 8px 10px;
@@ -501,17 +515,17 @@ textarea.pc-input {
501
515
  }
502
516
 
503
517
  .pc-btn-mini {
504
- border: 1px solid var(--sa-border, #e2e8f0);
518
+ border: 1px solid var(--sa-border, var(--sa-border));
505
519
  background: #fff;
506
520
  border-radius: 7px;
507
521
  padding: 6px 10px;
508
522
  font: 500 12px var(--sa-font-body, system-ui, sans-serif);
509
523
  cursor: pointer;
510
- color: var(--sa-muted-dark, #475569);
524
+ color: var(--sa-muted-dark, var(--sa-muted-dark));
511
525
  }
512
526
 
513
527
  .pc-btn-mini:hover {
514
- background: #f1f5f9;
528
+ background: var(--sa-border-soft);
515
529
  }
516
530
 
517
531
  .pc-type-grid {
@@ -521,7 +535,7 @@ textarea.pc-input {
521
535
  }
522
536
 
523
537
  .pc-type-opt {
524
- border: 1px solid var(--sa-border, #e2e8f0);
538
+ border: 1px solid var(--sa-border, var(--sa-border));
525
539
  background: #fff;
526
540
  border-radius: 8px;
527
541
  padding: 8px 10px;
@@ -543,12 +557,12 @@ textarea.pc-input {
543
557
 
544
558
  .pc-type-opt__label {
545
559
  font: 600 12.5px var(--sa-font-body, system-ui, sans-serif);
546
- color: var(--sa-heading, #0f172a);
560
+ color: var(--sa-heading, var(--sa-heading));
547
561
  }
548
562
 
549
563
  .pc-type-opt__sub {
550
564
  font: 11.5px var(--sa-font-mono, ui-monospace, monospace);
551
- color: var(--sa-muted, #64748b);
565
+ color: var(--sa-muted, var(--sa-muted));
552
566
  margin-top: 1px;
553
567
  }
554
568
 
@@ -563,12 +577,12 @@ textarea.pc-input {
563
577
  align-items: center;
564
578
  gap: 8px;
565
579
  background: #fff;
566
- border: 1px solid var(--sa-border, #e2e8f0);
580
+ border: 1px solid var(--sa-border, var(--sa-border));
567
581
  border-radius: 999px;
568
582
  padding: 5px 12px 5px 8px;
569
583
  font: 600 12px var(--sa-font-body, system-ui, sans-serif);
570
584
  cursor: pointer;
571
- color: var(--sa-muted-dark, #475569);
585
+ color: var(--sa-muted-dark, var(--sa-muted-dark));
572
586
  transition:
573
587
  border-color 0.1s,
574
588
  background 0.1s;
@@ -597,13 +611,13 @@ textarea.pc-input {
597
611
 
598
612
  .pc-dur-opt {
599
613
  flex: 1;
600
- border: 1px solid var(--sa-border, #e2e8f0);
614
+ border: 1px solid var(--sa-border, var(--sa-border));
601
615
  background: #fff;
602
616
  border-radius: 7px;
603
617
  padding: 6px 10px;
604
618
  font: 500 12px var(--sa-font-body, system-ui, sans-serif);
605
619
  cursor: pointer;
606
- color: var(--sa-muted-dark, #475569);
620
+ color: var(--sa-muted-dark, var(--sa-muted-dark));
607
621
  }
608
622
 
609
623
  .pc-dur-opt--active {
@@ -646,12 +660,12 @@ textarea.pc-input {
646
660
 
647
661
  .pc-preview__code {
648
662
  background: #fff;
649
- border: 1px solid var(--sa-border, #e2e8f0);
663
+ border: 1px solid var(--sa-border, var(--sa-border));
650
664
  border-radius: 6px;
651
665
  padding: 3px 8px;
652
666
  font: 600 13px var(--sa-font-mono, ui-monospace, monospace);
653
667
  letter-spacing: 0.04em;
654
- color: var(--sa-heading, #0f172a);
668
+ color: var(--sa-heading, var(--sa-heading));
655
669
  }
656
670
 
657
671
  .pc-preview__disc {
@@ -661,6 +675,6 @@ textarea.pc-input {
661
675
 
662
676
  .pc-preview__meta {
663
677
  font-size: 12px;
664
- color: var(--sa-muted, #64748b);
678
+ color: var(--sa-muted, var(--sa-muted));
665
679
  }
666
680
  </style>
@@ -1,14 +1,14 @@
1
1
  <template>
2
2
  <q-dialog
3
3
  :model-value="modelValue"
4
- @update:model-value="emit('update:modelValue', $event)"
5
4
  persistent
5
+ @update:model-value="emit('update:modelValue', $event)"
6
6
  >
7
7
  <q-card class="pc-dlg">
8
8
  <q-card-section class="pc-dlg__head">
9
9
  <div>
10
10
  <div class="pc-dlg__title">{{ msg.editDialog.title }}</div>
11
- <div class="pc-dlg__sub" v-if="row">
11
+ <div v-if="row" class="pc-dlg__sub">
12
12
  {{ msg.form.codeLabel }} <strong>{{ row.code }}</strong> ·
13
13
  {{
14
14
  formatMessage(msg.editDialog.redemptionsSoFar, {
@@ -18,22 +18,22 @@
18
18
  </div>
19
19
  </div>
20
20
  <q-btn
21
+ v-close-popup
21
22
  class="pc-dlg__close"
22
23
  flat
23
24
  dense
24
25
  round
25
26
  icon="close"
26
- v-close-popup
27
27
  :disable="loading"
28
28
  />
29
29
  </q-card-section>
30
30
 
31
31
  <q-card-section class="pc-dlg__body">
32
32
  <PromoCodeDialogFields
33
+ v-model:advanced-open="advancedOpen"
33
34
  mode="edit"
34
35
  :form="form"
35
36
  :code="row?.code ?? ''"
36
- v-model:advanced-open="advancedOpen"
37
37
  :show-campaign-tag="showCampaignTag"
38
38
  :plans="plans"
39
39
  />
@@ -42,7 +42,7 @@
42
42
  </q-card-section>
43
43
 
44
44
  <q-card-actions align="right" class="pc-dlg__foot">
45
- <q-btn flat :label="common.cancel" v-close-popup :disable="loading" />
45
+ <q-btn v-close-popup flat :label="common.cancel" :disable="loading" />
46
46
  <q-btn
47
47
  unelevated
48
48
  color="primary"
@@ -304,12 +304,12 @@ async function onSubmit() {
304
304
  font-family: var(--sa-font-head, system-ui, sans-serif);
305
305
  font-weight: 700;
306
306
  font-size: 18px;
307
- color: var(--sa-heading, #0f172a);
307
+ color: var(--sa-heading, var(--sa-heading));
308
308
  }
309
309
 
310
310
  .pc-dlg__sub {
311
311
  font-size: 12.5px;
312
- color: var(--sa-muted, #64748b);
312
+ color: var(--sa-muted, var(--sa-muted));
313
313
  margin-top: 2px;
314
314
  }
315
315
 
@@ -321,7 +321,7 @@ async function onSubmit() {
321
321
  }
322
322
 
323
323
  .pc-dlg__foot {
324
- border-top: 1px solid var(--sa-border, #e2e8f0);
324
+ border-top: 1px solid var(--sa-border, var(--sa-border));
325
325
  }
326
326
 
327
327
  .pc-error {
@@ -336,8 +336,8 @@ async function onSubmit() {
336
336
 
337
337
  /* The code cannot be changed after creation. */
338
338
  .pc-input:disabled {
339
- background: #f8fafc;
340
- color: #64748b;
339
+ background: var(--sa-bg-surface-2);
340
+ color: var(--sa-muted);
341
341
  cursor: not-allowed;
342
342
  }
343
343
  </style>
@@ -113,7 +113,7 @@ function planPrice(plan: CatalogPlan): number | null {
113
113
  --sp-text-strong: rgba(255, 255, 255, 0.92);
114
114
  --sp-text-muted: rgba(255, 255, 255, 0.65);
115
115
  --sp-flag-current-bg: rgba(255, 255, 255, 0.85);
116
- --sp-flag-current-fg: #0f172a;
116
+ --sp-flag-current-fg: var(--sa-heading);
117
117
  }
118
118
  .sp-model {
119
119
  position: relative;