@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.
- package/README.md +17 -0
- package/dist/{chunk-EH7TOD4H.js → chunk-A3W2N26K.js} +73 -77
- package/dist/{chunk-3YP2ZAOD.js → chunk-QZOSDCNP.js} +36 -1
- package/dist/chunk-X5SQ5HMB.js +3231 -0
- package/dist/client/index.cjs +3279 -76
- package/dist/client/index.d.cts +31 -5
- package/dist/client/index.d.ts +31 -5
- package/dist/client/index.js +23 -5
- package/dist/index.cjs +3709 -465
- package/dist/index.d.cts +37 -54
- package/dist/index.d.ts +37 -54
- package/dist/index.js +347 -311
- package/dist/messages-7b0P8W75.d.cts +1652 -0
- package/dist/messages-7b0P8W75.d.ts +1652 -0
- package/dist/quasar/index.cjs +3185 -4
- package/dist/quasar/index.d.cts +11 -2
- package/dist/quasar/index.d.ts +11 -2
- package/dist/quasar/index.js +8 -3
- package/dist/testing-e2e/admin-pages-suite.cjs +14 -11
- package/dist/testing-e2e/admin-pages-suite.js +14 -11
- package/dist/{ui-notify-COUzXEQ4.d.ts → use-super-admin-i18n-B3v3-SWZ.d.ts} +35 -3
- package/dist/{ui-notify-D_eAAwRh.d.cts → use-super-admin-i18n-DMktRVEt.d.cts} +35 -3
- package/package.json +2 -2
- package/src/client/action-registry.ts +4 -4
- package/src/client/batch-column-fetcher.ts +4 -4
- package/src/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 +2 -0
- package/src/client/manifest-loader.ts +4 -4
- package/src/client/nav-builder.ts +44 -51
- package/src/client/plan-versions-catalog.ts +42 -30
- package/src/components/BundleVersionPublishDialog.vue +35 -24
- 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 +20 -9
- 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 +1 -1
- package/src/pages-standard/AdminLayout.vue +42 -17
- 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 +29 -15
- package/src/pages-standard/DiscoveryPage.vue +40 -28
- package/src/pages-standard/EmailHistoryPage.vue +92 -59
- package/src/pages-standard/MarketingCatalogPage.vue +35 -16
- package/src/pages-standard/PilotsPage.vue +57 -41
- package/src/pages-standard/PlanVersionsPage.vue +7 -3
- package/src/pages-standard/PlansPage.vue +89 -57
- package/src/pages-standard/PlatformEmailPage.vue +115 -50
- package/src/pages-standard/PromoCodeDetailPage.vue +66 -63
- package/src/pages-standard/PromoCodesPage.vue +46 -35
- package/src/pages-standard/SubscriptionsPage.vue +14 -9
- package/src/pages-standard/SuperAdminLoginPage.vue +16 -13
- package/src/pages-standard/SuperAdminSetupWizard.vue +51 -47
- package/src/pages-standard/TenantDetailPage.vue +50 -36
- package/src/pages-standard/TenantsPage.vue +54 -41
- package/src/pages-standard/UsersPage.vue +66 -42
- 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 +41 -25
- package/src/pages-standard/plan-versions/PlanVersionsAudit.vue +45 -26
- package/src/pages-standard/plan-versions/PlanVersionsDiff.vue +7 -5
- package/src/pages-standard/plan-versions/PlanVersionsList.vue +39 -16
- package/src/pages-standard/plan-versions/PlanVersionsTimeline.vue +24 -12
- 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 +72 -37
- package/src/pages-tenant/PlanChangeWizard.vue +8 -4
- package/src/pages-tenant/TenantPlanSection.vue +17 -13
- package/src/pages-tenant/default-i18n.ts +217 -1
- package/src/pages-tenant/tenant-plan-section/BundlePreviewDialog.vue +8 -6
- package/src/pages-tenant/tenant-plan-section/TenantBundleStore.vue +9 -10
- package/src/pages-tenant/tenant-plan-section/TenantFeatureMatrix.vue +4 -1
- package/src/quasar/create-super-admin-app.ts +19 -0
- package/src/testing-e2e/admin-pages-suite.ts +14 -11
- package/src/vue/project-page-host.ts +5 -3
- package/src/vue/use-audit-entries.ts +3 -3
- package/src/vue/use-bulk-publish.ts +6 -4
- package/src/vue/use-bundle-versions-map.ts +6 -4
- package/src/vue/use-bundles.ts +13 -13
- package/src/vue/use-catalog-entries.ts +13 -10
- package/src/vue/use-discovery.ts +8 -5
- package/src/vue/use-entitlement.ts +3 -3
- package/src/vue/use-live-plan-versions.ts +4 -4
- package/src/vue/use-marketing-projections.ts +9 -6
- package/src/vue/use-nav.ts +8 -2
- package/src/vue/use-plan-editor.ts +2 -2
- package/src/vue/use-plan-versions.ts +3 -3
- package/src/vue/use-plans.ts +12 -12
- package/src/vue/use-platform-tenant-actions.ts +9 -6
- package/src/vue/use-promotions.ts +9 -10
- package/src/vue/use-subscription-draft.ts +2 -3
- package/src/vue/use-super-admin-context.ts +3 -3
- package/src/vue/use-super-admin-i18n.ts +82 -0
- package/src/vue/use-tenant-action-flow.ts +11 -6
- package/src/vue/use-tenant-manifest.ts +1 -3
- package/src/vue/use-tenant-subscription-bundles.ts +4 -4
- package/src/vue/use-tenants.ts +3 -3
- package/dist/action-registry-CQ2wL3R-.d.cts +0 -85
- package/dist/action-registry-CQ2wL3R-.d.ts +0 -85
- package/dist/chunk-LVGUSD3T.js +0 -26
- 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/vue/use-business-types.ts +0 -269
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div v-if="!changes || changes.length === 0" class="sa-pv-diff-preview__empty">
|
|
3
|
-
Keine Änderungen gegenüber der Vorgängerversion.
|
|
4
|
-
</div>
|
|
5
|
-
<div v-else class="sa-pv-diff-preview__list">
|
|
6
|
-
<div
|
|
7
|
-
v-for="(c, idx) in changes"
|
|
8
|
-
:key="idx"
|
|
9
|
-
class="sa-pv-diff-preview__row"
|
|
10
|
-
:class="rowClass(c.direction)"
|
|
11
|
-
>
|
|
12
|
-
<div class="sa-pv-diff-preview__direction">
|
|
13
|
-
<q-icon :name="iconFor(c.direction)" size="16px" />
|
|
14
|
-
<span>{{ labelFor(c.direction) }}</span>
|
|
15
|
-
</div>
|
|
16
|
-
<div class="sa-pv-diff-preview__field">{{ humanFieldLabel(c.field) }}</div>
|
|
17
|
-
<div class="sa-pv-diff-preview__values">
|
|
18
|
-
<span v-if="c.field !== 'features.added'" class="old">{{
|
|
19
|
-
formatValue(c.oldValue)
|
|
20
|
-
}}</span>
|
|
21
|
-
<q-icon
|
|
22
|
-
v-if="c.field !== 'features.added' && c.field !== 'features.removed'"
|
|
23
|
-
name="arrow_forward"
|
|
24
|
-
size="14px"
|
|
25
|
-
/>
|
|
26
|
-
<span v-if="c.field !== 'features.removed'" class="new">{{
|
|
27
|
-
formatValue(c.newValue)
|
|
28
|
-
}}</span>
|
|
29
|
-
</div>
|
|
30
|
-
</div>
|
|
31
|
-
</div>
|
|
32
|
-
</template>
|
|
33
|
-
|
|
34
|
-
<script setup lang="ts">
|
|
35
|
-
import { computed } from 'vue';
|
|
36
|
-
import type { VersionChange } from '@saasicat/types';
|
|
37
|
-
|
|
38
|
-
const props = defineProps<{
|
|
39
|
-
changes?: VersionChange[] | null;
|
|
40
|
-
/**
|
|
41
|
-
* Optional: field labels (e.g. `{ maxUsers: 'Max. Benutzer' }`).
|
|
42
|
-
* Apps map their own Quota fields here; the default covers the generic
|
|
43
|
-
* platform fields.
|
|
44
|
-
*/
|
|
45
|
-
fieldLabels?: Record<string, string>;
|
|
46
|
-
}>();
|
|
47
|
-
|
|
48
|
-
const DEFAULT_FIELD_LABELS: Record<string, string> = {
|
|
49
|
-
'features.added': 'Hinzugefügte Features',
|
|
50
|
-
'features.removed': 'Entfernte Features',
|
|
51
|
-
maxUsers: 'Max. Benutzer',
|
|
52
|
-
maxStorageGb: 'Speicher (GB)',
|
|
53
|
-
monthlyNet: 'Preis monatlich (netto)',
|
|
54
|
-
yearlyNet: 'Preis jährlich (netto)',
|
|
55
|
-
unitSize: 'Einheitsgröße',
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const mergedFieldLabels = computed(() => ({
|
|
59
|
-
...DEFAULT_FIELD_LABELS,
|
|
60
|
-
...(props.fieldLabels ?? {}),
|
|
61
|
-
}));
|
|
62
|
-
|
|
63
|
-
function iconFor(direction: VersionChange['direction']): string {
|
|
64
|
-
if (direction === 'IMPROVEMENT') return 'trending_up';
|
|
65
|
-
if (direction === 'REGRESSION') return 'trending_down';
|
|
66
|
-
return 'remove';
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function labelFor(direction: VersionChange['direction']): string {
|
|
70
|
-
if (direction === 'IMPROVEMENT') return 'Verbesserung';
|
|
71
|
-
if (direction === 'REGRESSION') return 'Verschlechterung';
|
|
72
|
-
return 'Neutral';
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function rowClass(direction: VersionChange['direction']): string {
|
|
76
|
-
if (direction === 'IMPROVEMENT') return 'sa-pv-diff-preview__row--improvement';
|
|
77
|
-
if (direction === 'REGRESSION') return 'sa-pv-diff-preview__row--regression';
|
|
78
|
-
return 'sa-pv-diff-preview__row--neutral';
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function humanFieldLabel(field: string): string {
|
|
82
|
-
return mergedFieldLabels.value[field] ?? field;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function formatValue(value: unknown): string {
|
|
86
|
-
if (value === null || value === undefined) return '–';
|
|
87
|
-
if (Array.isArray(value)) {
|
|
88
|
-
if (value.length === 0) return '–';
|
|
89
|
-
return value.join(', ');
|
|
90
|
-
}
|
|
91
|
-
if (typeof value === 'string' && /^\d+\.\d{2}$/.test(value)) {
|
|
92
|
-
return `${value} €`;
|
|
93
|
-
}
|
|
94
|
-
return String(value);
|
|
95
|
-
}
|
|
96
|
-
</script>
|
|
97
|
-
|
|
98
|
-
<style scoped>
|
|
99
|
-
.sa-pv-diff-preview__empty {
|
|
100
|
-
color: #64748b;
|
|
101
|
-
font-style: italic;
|
|
102
|
-
padding: 12px;
|
|
103
|
-
background: #f8fafc;
|
|
104
|
-
border-radius: 8px;
|
|
105
|
-
border: 1px dashed #cbd5e1;
|
|
106
|
-
}
|
|
107
|
-
.sa-pv-diff-preview__list {
|
|
108
|
-
display: flex;
|
|
109
|
-
flex-direction: column;
|
|
110
|
-
gap: 6px;
|
|
111
|
-
}
|
|
112
|
-
.sa-pv-diff-preview__row {
|
|
113
|
-
display: grid;
|
|
114
|
-
grid-template-columns: 160px 200px 1fr;
|
|
115
|
-
gap: 12px;
|
|
116
|
-
padding: 8px 12px;
|
|
117
|
-
border-radius: 8px;
|
|
118
|
-
border: 1px solid;
|
|
119
|
-
font-size: 13px;
|
|
120
|
-
align-items: center;
|
|
121
|
-
}
|
|
122
|
-
.sa-pv-diff-preview__row--improvement {
|
|
123
|
-
background: #f0fdf4;
|
|
124
|
-
border-color: #bbf7d0;
|
|
125
|
-
color: #166534;
|
|
126
|
-
}
|
|
127
|
-
.sa-pv-diff-preview__row--regression {
|
|
128
|
-
background: #fef2f2;
|
|
129
|
-
border-color: #fecaca;
|
|
130
|
-
color: #991b1b;
|
|
131
|
-
}
|
|
132
|
-
.sa-pv-diff-preview__row--neutral {
|
|
133
|
-
background: #f8fafc;
|
|
134
|
-
border-color: #e2e8f0;
|
|
135
|
-
color: #475569;
|
|
136
|
-
}
|
|
137
|
-
.sa-pv-diff-preview__direction {
|
|
138
|
-
display: flex;
|
|
139
|
-
align-items: center;
|
|
140
|
-
gap: 6px;
|
|
141
|
-
font-weight: 600;
|
|
142
|
-
font-size: 12px;
|
|
143
|
-
text-transform: uppercase;
|
|
144
|
-
letter-spacing: 0.04em;
|
|
145
|
-
}
|
|
146
|
-
.sa-pv-diff-preview__field {
|
|
147
|
-
color: #0f172a;
|
|
148
|
-
font-weight: 500;
|
|
149
|
-
}
|
|
150
|
-
.sa-pv-diff-preview__values {
|
|
151
|
-
display: flex;
|
|
152
|
-
align-items: center;
|
|
153
|
-
gap: 8px;
|
|
154
|
-
}
|
|
155
|
-
.sa-pv-diff-preview__values .old {
|
|
156
|
-
color: #94a3b8;
|
|
157
|
-
text-decoration: line-through;
|
|
158
|
-
font-family: ui-monospace, 'SF Mono', Menlo, monospace;
|
|
159
|
-
font-size: 12px;
|
|
160
|
-
}
|
|
161
|
-
.sa-pv-diff-preview__values .new {
|
|
162
|
-
color: inherit;
|
|
163
|
-
font-weight: 600;
|
|
164
|
-
font-family: ui-monospace, 'SF Mono', Menlo, monospace;
|
|
165
|
-
font-size: 12px;
|
|
166
|
-
}
|
|
167
|
-
</style>
|
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
// useBusinessTypes + useBusinessTypeVersions — Vue 3 composables for
|
|
2
|
-
// SuperAdmin business-type management (backend: BusinessTypesController under
|
|
3
|
-
// /admin/catalog/business-types + /admin/catalog/business-type-versions).
|
|
4
|
-
//
|
|
5
|
-
// Pattern analogous to use-bundles.ts.
|
|
6
|
-
|
|
7
|
-
import { ref, type Ref } from 'vue';
|
|
8
|
-
import type {
|
|
9
|
-
BusinessTypeRow,
|
|
10
|
-
BusinessTypeVersionMutationResult,
|
|
11
|
-
BusinessTypeVersionRow,
|
|
12
|
-
CreateBusinessTypeData,
|
|
13
|
-
CreateBusinessTypeVersionDraftData,
|
|
14
|
-
UpdateBusinessTypeData,
|
|
15
|
-
UpdateBusinessTypeVersionDraftData,
|
|
16
|
-
} from '@saasicat/types';
|
|
17
|
-
import { defaultHttpClient, type HttpClient } from '../client/types.js';
|
|
18
|
-
|
|
19
|
-
export interface UseBusinessTypesOptions {
|
|
20
|
-
adminEndpoint: string;
|
|
21
|
-
http?: HttpClient;
|
|
22
|
-
getAuthToken?: () => string | null;
|
|
23
|
-
projectKey: string;
|
|
24
|
-
autoLoad?: boolean;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export class BusinessTypesApiError extends Error {
|
|
28
|
-
constructor(
|
|
29
|
-
public readonly status: number,
|
|
30
|
-
public readonly body: unknown,
|
|
31
|
-
message: string,
|
|
32
|
-
) {
|
|
33
|
-
super(message);
|
|
34
|
-
this.name = 'BusinessTypesApiError';
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export interface UseBusinessTypesResult {
|
|
39
|
-
businessTypes: Ref<BusinessTypeRow[]>;
|
|
40
|
-
loading: Ref<boolean>;
|
|
41
|
-
error: Ref<Error | null>;
|
|
42
|
-
|
|
43
|
-
load: () => Promise<void>;
|
|
44
|
-
create: (data: CreateBusinessTypeData) => Promise<BusinessTypeRow>;
|
|
45
|
-
update: (businessTypeId: string, data: UpdateBusinessTypeData) => Promise<BusinessTypeRow>;
|
|
46
|
-
softDelete: (businessTypeId: string) => Promise<void>;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function useBusinessTypes(options: UseBusinessTypesOptions): UseBusinessTypesResult {
|
|
50
|
-
if (!options?.adminEndpoint) {
|
|
51
|
-
throw new Error('useBusinessTypes: `adminEndpoint` ist Pflicht.');
|
|
52
|
-
}
|
|
53
|
-
if (!options?.projectKey) {
|
|
54
|
-
throw new Error('useBusinessTypes: `projectKey` ist Pflicht.');
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const http = options.http ?? defaultHttpClient();
|
|
58
|
-
const businessTypes = ref<BusinessTypeRow[]>([]);
|
|
59
|
-
const loading = ref(false);
|
|
60
|
-
const error = ref<Error | null>(null);
|
|
61
|
-
|
|
62
|
-
const baseUrl = `${options.adminEndpoint}/catalog/business-types`;
|
|
63
|
-
|
|
64
|
-
function authHeaders(): Record<string, string> {
|
|
65
|
-
const token = options.getAuthToken?.();
|
|
66
|
-
return token ? { Authorization: `Bearer ${token}` } : {};
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async function fetchJson<T>(url: string, init?: Parameters<HttpClient>[1]): Promise<T | null> {
|
|
70
|
-
const res = await http(url, {
|
|
71
|
-
method: init?.method ?? 'GET',
|
|
72
|
-
headers: { 'content-type': 'application/json', ...authHeaders(), ...init?.headers },
|
|
73
|
-
body: init?.body,
|
|
74
|
-
});
|
|
75
|
-
if (res.status === 204) return null;
|
|
76
|
-
const body = await res.json().catch(() => null);
|
|
77
|
-
if (res.status >= 400) {
|
|
78
|
-
throw new BusinessTypesApiError(
|
|
79
|
-
res.status,
|
|
80
|
-
body,
|
|
81
|
-
`BusinessTypes-API antwortete mit HTTP ${res.status}`,
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
return body as T;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
async function load(): Promise<void> {
|
|
88
|
-
loading.value = true;
|
|
89
|
-
error.value = null;
|
|
90
|
-
try {
|
|
91
|
-
const data = await fetchJson<BusinessTypeRow[]>(
|
|
92
|
-
`${baseUrl}?projectKey=${encodeURIComponent(options.projectKey)}`,
|
|
93
|
-
);
|
|
94
|
-
businessTypes.value = data ?? [];
|
|
95
|
-
} catch (err) {
|
|
96
|
-
error.value = err instanceof Error ? err : new Error(String(err));
|
|
97
|
-
} finally {
|
|
98
|
-
loading.value = false;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
async function create(data: CreateBusinessTypeData): Promise<BusinessTypeRow> {
|
|
103
|
-
const created = await fetchJson<BusinessTypeRow>(baseUrl, {
|
|
104
|
-
method: 'POST',
|
|
105
|
-
body: JSON.stringify(data),
|
|
106
|
-
});
|
|
107
|
-
if (!created) throw new BusinessTypesApiError(0, null, 'Create gab keinen Body zurück');
|
|
108
|
-
businessTypes.value = [...businessTypes.value, created];
|
|
109
|
-
return created;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
async function update(
|
|
113
|
-
businessTypeId: string,
|
|
114
|
-
data: UpdateBusinessTypeData,
|
|
115
|
-
): Promise<BusinessTypeRow> {
|
|
116
|
-
const updated = await fetchJson<BusinessTypeRow>(`${baseUrl}/${businessTypeId}`, {
|
|
117
|
-
method: 'PATCH',
|
|
118
|
-
body: JSON.stringify(data),
|
|
119
|
-
});
|
|
120
|
-
if (!updated) throw new BusinessTypesApiError(0, null, 'Update gab keinen Body zurück');
|
|
121
|
-
businessTypes.value = businessTypes.value.map((b) =>
|
|
122
|
-
b.id === businessTypeId ? updated : b,
|
|
123
|
-
);
|
|
124
|
-
return updated;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
async function softDelete(businessTypeId: string): Promise<void> {
|
|
128
|
-
await fetchJson<null>(`${baseUrl}/${businessTypeId}`, { method: 'DELETE' });
|
|
129
|
-
businessTypes.value = businessTypes.value.filter((b) => b.id !== businessTypeId);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (options.autoLoad) {
|
|
133
|
-
void load();
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
return { businessTypes, loading, error, load, create, update, softDelete };
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// =============================================================================
|
|
140
|
-
// useBusinessTypeVersions
|
|
141
|
-
// =============================================================================
|
|
142
|
-
|
|
143
|
-
export interface UseBusinessTypeVersionsOptions {
|
|
144
|
-
adminEndpoint: string;
|
|
145
|
-
businessTypeId: string;
|
|
146
|
-
http?: HttpClient;
|
|
147
|
-
getAuthToken?: () => string | null;
|
|
148
|
-
autoLoad?: boolean;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
export interface UseBusinessTypeVersionsResult {
|
|
152
|
-
versions: Ref<BusinessTypeVersionRow[]>;
|
|
153
|
-
loading: Ref<boolean>;
|
|
154
|
-
error: Ref<Error | null>;
|
|
155
|
-
|
|
156
|
-
load: () => Promise<void>;
|
|
157
|
-
createDraft: (
|
|
158
|
-
data: Omit<CreateBusinessTypeVersionDraftData, 'businessTypeId'>,
|
|
159
|
-
) => Promise<BusinessTypeVersionMutationResult>;
|
|
160
|
-
updateDraft: (
|
|
161
|
-
versionId: string,
|
|
162
|
-
data: UpdateBusinessTypeVersionDraftData,
|
|
163
|
-
) => Promise<BusinessTypeVersionMutationResult>;
|
|
164
|
-
publish: (
|
|
165
|
-
versionId: string,
|
|
166
|
-
opts?: { forceRegressive?: boolean },
|
|
167
|
-
) => Promise<BusinessTypeVersionMutationResult>;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
export function useBusinessTypeVersions(
|
|
171
|
-
options: UseBusinessTypeVersionsOptions,
|
|
172
|
-
): UseBusinessTypeVersionsResult {
|
|
173
|
-
if (!options?.adminEndpoint) {
|
|
174
|
-
throw new Error('useBusinessTypeVersions: `adminEndpoint` ist Pflicht.');
|
|
175
|
-
}
|
|
176
|
-
if (!options?.businessTypeId) {
|
|
177
|
-
throw new Error('useBusinessTypeVersions: `businessTypeId` ist Pflicht.');
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
const http = options.http ?? defaultHttpClient();
|
|
181
|
-
const versions = ref<BusinessTypeVersionRow[]>([]);
|
|
182
|
-
const loading = ref(false);
|
|
183
|
-
const error = ref<Error | null>(null);
|
|
184
|
-
|
|
185
|
-
const versionsUrl = `${options.adminEndpoint}/catalog/business-types/${options.businessTypeId}/versions`;
|
|
186
|
-
const versionUrlBase = `${options.adminEndpoint}/catalog/business-type-versions`;
|
|
187
|
-
|
|
188
|
-
function authHeaders(): Record<string, string> {
|
|
189
|
-
const token = options.getAuthToken?.();
|
|
190
|
-
return token ? { Authorization: `Bearer ${token}` } : {};
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
async function fetchJson<T>(url: string, init?: Parameters<HttpClient>[1]): Promise<T | null> {
|
|
194
|
-
const res = await http(url, {
|
|
195
|
-
method: init?.method ?? 'GET',
|
|
196
|
-
headers: { 'content-type': 'application/json', ...authHeaders(), ...init?.headers },
|
|
197
|
-
body: init?.body,
|
|
198
|
-
});
|
|
199
|
-
if (res.status === 204) return null;
|
|
200
|
-
const body = await res.json().catch(() => null);
|
|
201
|
-
if (res.status >= 400) {
|
|
202
|
-
throw new BusinessTypesApiError(
|
|
203
|
-
res.status,
|
|
204
|
-
body,
|
|
205
|
-
`BusinessTypeVersions-API antwortete mit HTTP ${res.status}`,
|
|
206
|
-
);
|
|
207
|
-
}
|
|
208
|
-
return body as T;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
async function load(): Promise<void> {
|
|
212
|
-
loading.value = true;
|
|
213
|
-
error.value = null;
|
|
214
|
-
try {
|
|
215
|
-
const data = await fetchJson<BusinessTypeVersionRow[]>(versionsUrl);
|
|
216
|
-
versions.value = data ?? [];
|
|
217
|
-
} catch (err) {
|
|
218
|
-
error.value = err instanceof Error ? err : new Error(String(err));
|
|
219
|
-
} finally {
|
|
220
|
-
loading.value = false;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
async function createDraft(
|
|
225
|
-
data: Omit<CreateBusinessTypeVersionDraftData, 'businessTypeId'>,
|
|
226
|
-
): Promise<BusinessTypeVersionMutationResult> {
|
|
227
|
-
const result = await fetchJson<BusinessTypeVersionMutationResult>(versionsUrl, {
|
|
228
|
-
method: 'POST',
|
|
229
|
-
body: JSON.stringify(data),
|
|
230
|
-
});
|
|
231
|
-
if (!result) throw new BusinessTypesApiError(0, null, 'CreateDraft gab keinen Body zurück');
|
|
232
|
-
versions.value = [...versions.value, result.businessTypeVersion];
|
|
233
|
-
return result;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
async function updateDraft(
|
|
237
|
-
versionId: string,
|
|
238
|
-
data: UpdateBusinessTypeVersionDraftData,
|
|
239
|
-
): Promise<BusinessTypeVersionMutationResult> {
|
|
240
|
-
const result = await fetchJson<BusinessTypeVersionMutationResult>(
|
|
241
|
-
`${versionUrlBase}/${versionId}`,
|
|
242
|
-
{ method: 'PATCH', body: JSON.stringify(data) },
|
|
243
|
-
);
|
|
244
|
-
if (!result) throw new BusinessTypesApiError(0, null, 'UpdateDraft gab keinen Body zurück');
|
|
245
|
-
versions.value = versions.value.map((v) =>
|
|
246
|
-
v.id === versionId ? result.businessTypeVersion : v,
|
|
247
|
-
);
|
|
248
|
-
return result;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
async function publish(
|
|
252
|
-
versionId: string,
|
|
253
|
-
opts: { forceRegressive?: boolean } = {},
|
|
254
|
-
): Promise<BusinessTypeVersionMutationResult> {
|
|
255
|
-
const result = await fetchJson<BusinessTypeVersionMutationResult>(
|
|
256
|
-
`${versionUrlBase}/${versionId}/publish`,
|
|
257
|
-
{ method: 'POST', body: JSON.stringify(opts) },
|
|
258
|
-
);
|
|
259
|
-
if (!result) throw new BusinessTypesApiError(0, null, 'Publish gab keinen Body zurück');
|
|
260
|
-
await load();
|
|
261
|
-
return result;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
if (options.autoLoad) {
|
|
265
|
-
void load();
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
return { versions, loading, error, load, createDraft, updateDraft, publish };
|
|
269
|
-
}
|