@vc-shell/framework 1.1.82 → 1.1.83
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/CHANGELOG.md +27 -0
- package/core/api/virtocommerce.platform.ts +10457 -0
- package/core/plugins/extension-points/ExtensionSlot.vue +23 -0
- package/core/plugins/extension-points/README.md +406 -0
- package/core/plugins/extension-points/index.ts +8 -0
- package/core/plugins/extension-points/migration-examples.md +613 -0
- package/core/plugins/extension-points/simple-extensions.ts +148 -0
- package/core/plugins/index.ts +1 -0
- package/core/plugins/modularity/loader.ts +2 -2
- package/dist/core/api/virtocommerce.platform.d.ts +2442 -0
- package/dist/core/api/virtocommerce.platform.d.ts.map +1 -0
- package/dist/core/plugins/extension-points/ExtensionSlot.vue.d.ts +6 -0
- package/dist/core/plugins/extension-points/ExtensionSlot.vue.d.ts.map +1 -0
- package/dist/core/plugins/extension-points/index.d.ts +3 -0
- package/dist/core/plugins/extension-points/index.d.ts.map +1 -0
- package/dist/core/plugins/extension-points/simple-extensions.d.ts +29 -0
- package/dist/core/plugins/extension-points/simple-extensions.d.ts.map +1 -0
- package/dist/core/plugins/index.d.ts +1 -0
- package/dist/core/plugins/index.d.ts.map +1 -1
- package/dist/framework.js +5104 -5031
- package/dist/locales/de.json +1 -0
- package/dist/locales/en.json +1 -0
- package/dist/shared/components/notification-template/notification-template.vue.d.ts +8 -1
- package/dist/shared/components/notification-template/notification-template.vue.d.ts.map +1 -1
- package/dist/shared/composables/useModificationTracker/index.d.ts +5 -0
- package/dist/shared/composables/useModificationTracker/index.d.ts.map +1 -1
- package/dist/shared/pages/LoginPage/components/login/Login.vue.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/ui/components/molecules/vc-form/vc-form.vue.d.ts +5 -1
- package/dist/ui/components/molecules/vc-form/vc-form.vue.d.ts.map +1 -1
- package/dist/ui/components/molecules/vc-select/vc-select.vue.d.ts +10 -5
- package/dist/ui/components/molecules/vc-select/vc-select.vue.d.ts.map +1 -1
- package/package.json +4 -4
- package/shared/components/notification-template/notification-template.vue +5 -1
- package/shared/composables/useModificationTracker/index.ts +6 -0
- package/shared/pages/LoginPage/components/login/Login.vue +30 -34
- package/ui/components/molecules/vc-form/vc-form.vue +11 -3
- package/ui/components/molecules/vc-select/vc-select.vue +1 -2
|
@@ -0,0 +1,613 @@
|
|
|
1
|
+
# 🔄 Migration to New Extension System
|
|
2
|
+
|
|
3
|
+
Detailed examples for migrating existing extensions to the new system.
|
|
4
|
+
|
|
5
|
+
## 🎯 Migration Structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
Old system (extensions-helper.ts):
|
|
9
|
+
- Complex typing (inbound/outbound)
|
|
10
|
+
- Namespace-based system
|
|
11
|
+
- Injection through provide/inject
|
|
12
|
+
- A lot of boilerplate code
|
|
13
|
+
|
|
14
|
+
New system (extension-points):
|
|
15
|
+
- Simple composables
|
|
16
|
+
- Slots and data
|
|
17
|
+
- Vue 3 reactivity
|
|
18
|
+
- Minimal code
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## 📋 Complete Registration Module Migration
|
|
22
|
+
|
|
23
|
+
### Step 1: Update Login.vue
|
|
24
|
+
|
|
25
|
+
#### Before:
|
|
26
|
+
```vue
|
|
27
|
+
<!-- framework/shared/pages/LoginPage/components/login/Login.vue -->
|
|
28
|
+
<template>
|
|
29
|
+
<VcLoginForm>
|
|
30
|
+
<!-- ... existing content ... -->
|
|
31
|
+
|
|
32
|
+
<!-- Complex extension system -->
|
|
33
|
+
<template
|
|
34
|
+
v-for="extension in afterLoginFormExtensions"
|
|
35
|
+
:key="extension.id"
|
|
36
|
+
>
|
|
37
|
+
<div class="vc-login-page__extension">
|
|
38
|
+
<component :is="extension.component" />
|
|
39
|
+
</div>
|
|
40
|
+
</template>
|
|
41
|
+
</VcLoginForm>
|
|
42
|
+
</template>
|
|
43
|
+
|
|
44
|
+
<script setup lang="ts">
|
|
45
|
+
import { extensionsHelperSymbol } from "../extensions-helper";
|
|
46
|
+
|
|
47
|
+
const extensionsHelper = inject(extensionsHelperSymbol);
|
|
48
|
+
|
|
49
|
+
const afterLoginFormExtensions = computed(
|
|
50
|
+
(): ExtensionPoint[] =>
|
|
51
|
+
(extensionsHelper?.getOutboundExtensions("login-after-form") as ExtensionPoint[]) || []
|
|
52
|
+
);
|
|
53
|
+
</script>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
#### After:
|
|
57
|
+
```vue
|
|
58
|
+
<!-- framework/shared/pages/LoginPage/components/login/Login.vue -->
|
|
59
|
+
<template>
|
|
60
|
+
<VcLoginForm>
|
|
61
|
+
<!-- ... same existing content ... -->
|
|
62
|
+
|
|
63
|
+
<!-- Simple extension slot -->
|
|
64
|
+
<div class="vc-login-page__extensions">
|
|
65
|
+
<ExtensionSlot name="login-after-form" />
|
|
66
|
+
</div>
|
|
67
|
+
</VcLoginForm>
|
|
68
|
+
</template>
|
|
69
|
+
|
|
70
|
+
<script setup lang="ts">
|
|
71
|
+
// Remove old imports:
|
|
72
|
+
// import { extensionsHelperSymbol } from "../extensions-helper";
|
|
73
|
+
|
|
74
|
+
// Add new import:
|
|
75
|
+
import { ExtensionSlot } from '@vc-shell/framework/core/plugins/extension-points';
|
|
76
|
+
|
|
77
|
+
// Remove:
|
|
78
|
+
// const extensionsHelper = inject(extensionsHelperSymbol);
|
|
79
|
+
// const afterLoginFormExtensions = computed(...);
|
|
80
|
+
|
|
81
|
+
// Rest of the code remains unchanged
|
|
82
|
+
</script>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Step 2: Simplify Registration Module
|
|
86
|
+
|
|
87
|
+
#### Before:
|
|
88
|
+
```typescript
|
|
89
|
+
// vc-module-marketplace-registration-1/src/.../registration/index.ts
|
|
90
|
+
import * as locales from "./locales";
|
|
91
|
+
import { i18n } from "@vc-shell/framework";
|
|
92
|
+
import { Router } from "vue-router";
|
|
93
|
+
import { App } from "vue";
|
|
94
|
+
import { routes } from "./router";
|
|
95
|
+
import { useRegistrationForm } from "./composables/useRegistrationForm";
|
|
96
|
+
import { RegistrationButton } from "./components";
|
|
97
|
+
|
|
98
|
+
export default {
|
|
99
|
+
install(app: App, options?: { router: Router }) {
|
|
100
|
+
let routerInstance: Router;
|
|
101
|
+
|
|
102
|
+
if (options && options.router) {
|
|
103
|
+
const { router } = options;
|
|
104
|
+
routerInstance = router;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
routes.forEach((route) => {
|
|
108
|
+
routerInstance.addRoute(route);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
if (locales) {
|
|
112
|
+
Object.entries(locales).forEach(([key, message]) => {
|
|
113
|
+
i18n.global.mergeLocaleMessage(key, message);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
extensions: {
|
|
118
|
+
inbound: {
|
|
119
|
+
"registration-form": useRegistrationForm(),
|
|
120
|
+
},
|
|
121
|
+
outbound: {
|
|
122
|
+
"login-after-form": [{ id: "RegistrationButton", component: RegistrationButton }],
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
#### After:
|
|
129
|
+
```typescript
|
|
130
|
+
// vc-module-marketplace-registration-1/src/.../registration/index.ts
|
|
131
|
+
import * as locales from "./locales";
|
|
132
|
+
import { i18n } from "@vc-shell/framework";
|
|
133
|
+
import { Router } from "vue-router";
|
|
134
|
+
import { App } from "vue";
|
|
135
|
+
import { routes } from "./router";
|
|
136
|
+
import { useExtensionSlot, useExtensionData } from '@vc-shell/framework/core/plugins/extension-points';
|
|
137
|
+
import RegistrationButton from "./components/RegistrationButton.vue";
|
|
138
|
+
|
|
139
|
+
export default {
|
|
140
|
+
install(app: App, options?: { router: Router }) {
|
|
141
|
+
// Router setup (unchanged)
|
|
142
|
+
if (options?.router) {
|
|
143
|
+
routes.forEach((route) => {
|
|
144
|
+
options.router.addRoute(route);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Localization (unchanged)
|
|
149
|
+
if (locales) {
|
|
150
|
+
Object.entries(locales).forEach(([key, message]) => {
|
|
151
|
+
i18n.global.mergeLocaleMessage(key, message);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// 🎯 NEW: Simple component registration
|
|
156
|
+
const { addComponent } = useExtensionSlot('login-after-form');
|
|
157
|
+
|
|
158
|
+
addComponent({
|
|
159
|
+
id: 'registration-button',
|
|
160
|
+
component: RegistrationButton,
|
|
161
|
+
props: {
|
|
162
|
+
text: 'Register',
|
|
163
|
+
variant: 'outline',
|
|
164
|
+
},
|
|
165
|
+
priority: 10,
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// 🎯 NEW: Provide form data
|
|
169
|
+
const { updateData } = useExtensionData('registration-form');
|
|
170
|
+
|
|
171
|
+
updateData({
|
|
172
|
+
fields: [
|
|
173
|
+
{
|
|
174
|
+
name: 'firstName',
|
|
175
|
+
type: 'text',
|
|
176
|
+
component: 'VcInput',
|
|
177
|
+
label: 'VCMP_VENDOR_REGISTRATION.LABELS.FIRST_NAME',
|
|
178
|
+
placeholder: 'VCMP_VENDOR_REGISTRATION.PLACEHOLDERS.FIRST_NAME',
|
|
179
|
+
required: true,
|
|
180
|
+
rules: 'required',
|
|
181
|
+
priority: 10,
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
name: 'lastName',
|
|
185
|
+
type: 'text',
|
|
186
|
+
component: 'VcInput',
|
|
187
|
+
label: 'VCMP_VENDOR_REGISTRATION.LABELS.LAST_NAME',
|
|
188
|
+
placeholder: 'VCMP_VENDOR_REGISTRATION.PLACEHOLDERS.LAST_NAME',
|
|
189
|
+
required: true,
|
|
190
|
+
rules: 'required',
|
|
191
|
+
priority: 20,
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
name: 'organizationName',
|
|
195
|
+
type: 'text',
|
|
196
|
+
component: 'VcInput',
|
|
197
|
+
label: 'VCMP_VENDOR_REGISTRATION.LABELS.ORGANIZATION',
|
|
198
|
+
placeholder: 'VCMP_VENDOR_REGISTRATION.PLACEHOLDERS.ORGANIZATION',
|
|
199
|
+
required: true,
|
|
200
|
+
rules: 'required',
|
|
201
|
+
priority: 30,
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
name: 'contactEmail',
|
|
205
|
+
type: 'email',
|
|
206
|
+
component: 'VcInput',
|
|
207
|
+
label: 'VCMP_VENDOR_REGISTRATION.LABELS.EMAIL',
|
|
208
|
+
placeholder: 'VCMP_VENDOR_REGISTRATION.PLACEHOLDERS.EMAIL',
|
|
209
|
+
hint: 'VCMP_VENDOR_REGISTRATION.HINTS.EMAIL',
|
|
210
|
+
required: true,
|
|
211
|
+
rules: 'emailWithServerValidation',
|
|
212
|
+
priority: 40,
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
name: 'contactPhone',
|
|
216
|
+
type: 'tel',
|
|
217
|
+
component: 'VcInput',
|
|
218
|
+
label: 'VCMP_VENDOR_REGISTRATION.LABELS.PHONE',
|
|
219
|
+
placeholder: 'VCMP_VENDOR_REGISTRATION.PLACEHOLDERS.PHONE',
|
|
220
|
+
rules: 'phone',
|
|
221
|
+
priority: 50,
|
|
222
|
+
},
|
|
223
|
+
],
|
|
224
|
+
});
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Step 3: Simplify useRegistrationForm Composable
|
|
230
|
+
|
|
231
|
+
#### Before:
|
|
232
|
+
```typescript
|
|
233
|
+
// composables/useRegistrationForm/index.ts
|
|
234
|
+
import { ref, computed } from "vue";
|
|
235
|
+
|
|
236
|
+
export interface IFormField {
|
|
237
|
+
name: string;
|
|
238
|
+
type: string;
|
|
239
|
+
component: string;
|
|
240
|
+
label?: string;
|
|
241
|
+
placeholder?: string;
|
|
242
|
+
hint?: string;
|
|
243
|
+
required?: boolean;
|
|
244
|
+
rules?: string;
|
|
245
|
+
props?: Record<string, unknown>;
|
|
246
|
+
priority?: number;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export interface IRegistrationFormConfig {
|
|
250
|
+
fields: IFormField[];
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const defaultFields: IFormField[] = [
|
|
254
|
+
// ... lots of field code
|
|
255
|
+
];
|
|
256
|
+
|
|
257
|
+
const formConfig = ref<IRegistrationFormConfig>({
|
|
258
|
+
fields: [...defaultFields],
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
const formData = ref<Record<string, unknown>>({});
|
|
262
|
+
|
|
263
|
+
defaultFields.forEach((field) => {
|
|
264
|
+
formData.value[field.name] = "";
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
export function useRegistrationForm() {
|
|
268
|
+
const extendForm = (newFields: IFormField[]) => {
|
|
269
|
+
formConfig.value.fields = [...formConfig.value.fields, ...newFields].sort(
|
|
270
|
+
(a, b) => (a.priority || 0) - (b.priority || 0),
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
newFields.forEach((field) => {
|
|
274
|
+
if (!(field.name in formData.value)) {
|
|
275
|
+
formData.value[field.name] = "";
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
// ... lots of other logic
|
|
281
|
+
|
|
282
|
+
return {
|
|
283
|
+
formConfig: computed(() => formConfig.value),
|
|
284
|
+
formData: computed(() => formData.value),
|
|
285
|
+
extendForm,
|
|
286
|
+
removeField,
|
|
287
|
+
updateField,
|
|
288
|
+
updateFormData,
|
|
289
|
+
getFormData,
|
|
290
|
+
setFormData,
|
|
291
|
+
clearFormData,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
#### After:
|
|
297
|
+
```typescript
|
|
298
|
+
// composables/useRegistrationForm/index.ts
|
|
299
|
+
import { ref, computed } from "vue";
|
|
300
|
+
import { useExtensionData } from '@vc-shell/framework/core/plugins/extension-points';
|
|
301
|
+
|
|
302
|
+
export interface IFormField {
|
|
303
|
+
name: string;
|
|
304
|
+
type: string;
|
|
305
|
+
component: string;
|
|
306
|
+
label?: string;
|
|
307
|
+
placeholder?: string;
|
|
308
|
+
hint?: string;
|
|
309
|
+
required?: boolean;
|
|
310
|
+
rules?: string;
|
|
311
|
+
props?: Record<string, unknown>;
|
|
312
|
+
priority?: number;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
export function useRegistrationForm() {
|
|
316
|
+
// 🎯 NEW: Use extension system
|
|
317
|
+
const { data, updateData, getValue, setValue } = useExtensionData('registration-form');
|
|
318
|
+
|
|
319
|
+
// Local form data
|
|
320
|
+
const formData = ref<Record<string, unknown>>({});
|
|
321
|
+
|
|
322
|
+
// Fields from extension system
|
|
323
|
+
const formConfig = computed(() => ({
|
|
324
|
+
fields: (data.value.fields || []).sort((a: IFormField, b: IFormField) =>
|
|
325
|
+
(a.priority || 0) - (b.priority || 0)
|
|
326
|
+
),
|
|
327
|
+
}));
|
|
328
|
+
|
|
329
|
+
const extendForm = (newFields: IFormField[]) => {
|
|
330
|
+
const currentFields = data.value.fields || [];
|
|
331
|
+
updateData({
|
|
332
|
+
fields: [...currentFields, ...newFields],
|
|
333
|
+
});
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
const removeField = (fieldName: string) => {
|
|
337
|
+
const currentFields = data.value.fields || [];
|
|
338
|
+
updateData({
|
|
339
|
+
fields: currentFields.filter((field: IFormField) => field.name !== fieldName),
|
|
340
|
+
});
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
const updateField = (fieldName: string, updates: Partial<IFormField>) => {
|
|
344
|
+
const currentFields = data.value.fields || [];
|
|
345
|
+
const updatedFields = currentFields.map((field: IFormField) =>
|
|
346
|
+
field.name === fieldName ? { ...field, ...updates } : field
|
|
347
|
+
);
|
|
348
|
+
updateData({ fields: updatedFields });
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
const updateFormData = (fieldName: string, value: unknown) => {
|
|
352
|
+
formData.value[fieldName] = value;
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
const getFormData = () => {
|
|
356
|
+
return formData.value;
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
const setFormData = (newData: Record<string, unknown>) => {
|
|
360
|
+
formData.value = { ...formData.value, ...newData };
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
const clearFormData = () => {
|
|
364
|
+
formData.value = {};
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
return {
|
|
368
|
+
formConfig,
|
|
369
|
+
formData: computed(() => formData.value),
|
|
370
|
+
extendForm,
|
|
371
|
+
removeField,
|
|
372
|
+
updateField,
|
|
373
|
+
updateFormData,
|
|
374
|
+
getFormData,
|
|
375
|
+
setFormData,
|
|
376
|
+
clearFormData,
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### Step 4: Registration Button Component (unchanged)
|
|
382
|
+
|
|
383
|
+
```vue
|
|
384
|
+
<!-- components/RegistrationButton.vue -->
|
|
385
|
+
<template>
|
|
386
|
+
<VcButton @click="onRegisterClick">
|
|
387
|
+
{{ text || 'Register' }}
|
|
388
|
+
</VcButton>
|
|
389
|
+
</template>
|
|
390
|
+
|
|
391
|
+
<script setup lang="ts">
|
|
392
|
+
import { useRouter } from "vue-router";
|
|
393
|
+
|
|
394
|
+
interface Props {
|
|
395
|
+
text?: string;
|
|
396
|
+
variant?: string;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
const props = defineProps<Props>();
|
|
400
|
+
const router = useRouter();
|
|
401
|
+
|
|
402
|
+
const onRegisterClick = () => {
|
|
403
|
+
router.push("/registration");
|
|
404
|
+
};
|
|
405
|
+
</script>
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
## 📖 Complete Application Usage Example
|
|
409
|
+
|
|
410
|
+
### 1. Registration Customization from Main Application
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
// main.ts or any module file
|
|
414
|
+
import { useExtensionSlot, useExtensionData } from '@vc-shell/framework/core/plugins/extension-points';
|
|
415
|
+
import CustomRegistrationButton from './components/CustomRegistrationButton.vue';
|
|
416
|
+
|
|
417
|
+
// After app initialization:
|
|
418
|
+
|
|
419
|
+
// 1. Replace registration button with custom one
|
|
420
|
+
const { addComponent } = useExtensionSlot('login-after-form');
|
|
421
|
+
|
|
422
|
+
addComponent({
|
|
423
|
+
id: 'registration-button', // same ID - will replace existing
|
|
424
|
+
component: CustomRegistrationButton,
|
|
425
|
+
props: {
|
|
426
|
+
text: 'Create Seller Account',
|
|
427
|
+
variant: 'primary',
|
|
428
|
+
showIcon: true,
|
|
429
|
+
},
|
|
430
|
+
priority: 10,
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
// 2. Add custom fields to registration form
|
|
434
|
+
const { data: formData, updateData } = useExtensionData('registration-form');
|
|
435
|
+
|
|
436
|
+
// Get current fields
|
|
437
|
+
const currentFields = formData.value.fields || [];
|
|
438
|
+
|
|
439
|
+
// Add new field
|
|
440
|
+
updateData({
|
|
441
|
+
fields: [
|
|
442
|
+
...currentFields,
|
|
443
|
+
{
|
|
444
|
+
name: 'companyTaxId',
|
|
445
|
+
type: 'text',
|
|
446
|
+
component: 'VcInput',
|
|
447
|
+
label: 'Company Tax ID',
|
|
448
|
+
placeholder: 'Enter Tax ID',
|
|
449
|
+
required: true,
|
|
450
|
+
rules: 'required|taxId',
|
|
451
|
+
priority: 25, // between lastName (20) and organizationName (30)
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
name: 'businessType',
|
|
455
|
+
type: 'select',
|
|
456
|
+
component: 'VcSelect',
|
|
457
|
+
label: 'Business Type',
|
|
458
|
+
placeholder: 'Select type',
|
|
459
|
+
required: true,
|
|
460
|
+
props: {
|
|
461
|
+
options: [
|
|
462
|
+
{ value: 'individual', label: 'Individual Entrepreneur' },
|
|
463
|
+
{ value: 'llc', label: 'Limited Liability Company' },
|
|
464
|
+
{ value: 'corporation', label: 'Corporation' },
|
|
465
|
+
],
|
|
466
|
+
},
|
|
467
|
+
priority: 35,
|
|
468
|
+
},
|
|
469
|
+
],
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
// 3. Modify existing field
|
|
473
|
+
const updatedFields = formData.value.fields?.map((field: any) => {
|
|
474
|
+
if (field.name === 'organizationName') {
|
|
475
|
+
return {
|
|
476
|
+
...field,
|
|
477
|
+
label: 'Company Name',
|
|
478
|
+
placeholder: 'LLC "Company Name"',
|
|
479
|
+
required: false,
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
return field;
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
updateData({ fields: updatedFields });
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
### 2. Custom Registration Button Component
|
|
489
|
+
|
|
490
|
+
```vue
|
|
491
|
+
<!-- components/CustomRegistrationButton.vue -->
|
|
492
|
+
<template>
|
|
493
|
+
<div class="custom-registration">
|
|
494
|
+
<div class="registration-promo">
|
|
495
|
+
<VcIcon
|
|
496
|
+
v-if="showIcon"
|
|
497
|
+
icon="material-storefront"
|
|
498
|
+
class="tw-mb-2"
|
|
499
|
+
size="xl"
|
|
500
|
+
/>
|
|
501
|
+
<h3>Become a Partner!</h3>
|
|
502
|
+
<p class="tw-text-sm tw-text-gray-600">
|
|
503
|
+
Join our platform and start selling today
|
|
504
|
+
</p>
|
|
505
|
+
</div>
|
|
506
|
+
|
|
507
|
+
<VcButton
|
|
508
|
+
:variant="variant"
|
|
509
|
+
class="tw-w-full"
|
|
510
|
+
@click="openRegistration"
|
|
511
|
+
>
|
|
512
|
+
<VcIcon
|
|
513
|
+
v-if="showIcon"
|
|
514
|
+
icon="material-person_add"
|
|
515
|
+
class="tw-mr-2"
|
|
516
|
+
/>
|
|
517
|
+
{{ text }}
|
|
518
|
+
</VcButton>
|
|
519
|
+
|
|
520
|
+
<div class="tw-mt-2 tw-text-xs tw-text-center tw-text-gray-500">
|
|
521
|
+
Registration takes no more than 5 minutes
|
|
522
|
+
</div>
|
|
523
|
+
</div>
|
|
524
|
+
</template>
|
|
525
|
+
|
|
526
|
+
<script setup lang="ts">
|
|
527
|
+
import { useRouter } from 'vue-router';
|
|
528
|
+
|
|
529
|
+
interface Props {
|
|
530
|
+
text?: string;
|
|
531
|
+
variant?: string;
|
|
532
|
+
showIcon?: boolean;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
536
|
+
text: 'Register',
|
|
537
|
+
variant: 'primary',
|
|
538
|
+
showIcon: true,
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
const router = useRouter();
|
|
542
|
+
|
|
543
|
+
const openRegistration = () => {
|
|
544
|
+
// Can add analytics
|
|
545
|
+
console.log('User clicked registration button');
|
|
546
|
+
|
|
547
|
+
router.push('/registration');
|
|
548
|
+
};
|
|
549
|
+
</script>
|
|
550
|
+
|
|
551
|
+
<style scoped>
|
|
552
|
+
.custom-registration {
|
|
553
|
+
@apply tw-text-center tw-p-4 tw-bg-gray-50 tw-rounded-lg tw-mt-4;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
.registration-promo {
|
|
557
|
+
@apply tw-mb-4;
|
|
558
|
+
}
|
|
559
|
+
</style>
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
## 📋 Migration Checklist
|
|
563
|
+
|
|
564
|
+
### ✅ Preparation
|
|
565
|
+
- [ ] Study current extension system
|
|
566
|
+
- [ ] Identify all extension points
|
|
567
|
+
- [ ] Create migration plan
|
|
568
|
+
|
|
569
|
+
### ✅ Login.vue Update
|
|
570
|
+
- [ ] Replace complex extension logic with `<ExtensionSlot>`
|
|
571
|
+
- [ ] Remove old system imports
|
|
572
|
+
- [ ] Add `ExtensionSlot` import
|
|
573
|
+
- [ ] Test display
|
|
574
|
+
|
|
575
|
+
### ✅ Registration Module
|
|
576
|
+
- [ ] Simplify module `index.ts`
|
|
577
|
+
- [ ] Replace `extensions` object with composable calls
|
|
578
|
+
- [ ] Update `useRegistrationForm` composable
|
|
579
|
+
- [ ] Test component registration
|
|
580
|
+
|
|
581
|
+
### ✅ Testing
|
|
582
|
+
- [ ] Check registration button display
|
|
583
|
+
- [ ] Check registration form functionality
|
|
584
|
+
- [ ] Check app-level customization
|
|
585
|
+
- [ ] Check component replacement
|
|
586
|
+
|
|
587
|
+
### ✅ Documentation
|
|
588
|
+
- [ ] Update module documentation
|
|
589
|
+
- [ ] Add usage examples
|
|
590
|
+
- [ ] Document API changes
|
|
591
|
+
|
|
592
|
+
## 🚀 Migration Results
|
|
593
|
+
|
|
594
|
+
### Before (lines of code):
|
|
595
|
+
- `extensions-helper.ts`: ~210 lines
|
|
596
|
+
- Logic in `Login.vue`: ~15 lines
|
|
597
|
+
- `useRegistrationForm`: ~142 lines
|
|
598
|
+
- **Total**: ~367 lines of complex code
|
|
599
|
+
|
|
600
|
+
### After (lines of code):
|
|
601
|
+
- `simple-extensions.ts`: ~85 lines
|
|
602
|
+
- Logic in `Login.vue`: ~3 lines
|
|
603
|
+
- `useRegistrationForm`: ~60 lines
|
|
604
|
+
- **Total**: ~148 lines of simple code
|
|
605
|
+
|
|
606
|
+
### Benefits:
|
|
607
|
+
- ✅ **60% code reduction**
|
|
608
|
+
- ✅ **API simplification from 8 to 3 functions**
|
|
609
|
+
- ✅ **Full TypeScript support**
|
|
610
|
+
- ✅ **Better performance**
|
|
611
|
+
- ✅ **Easier to maintain and extend**
|
|
612
|
+
|
|
613
|
+
Migration complete! 🎉
|