@wisemen/wise-crm-web 0.2.0 → 0.2.2
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 +1037 -0
- package/dist/BusinessDetailSidebarProvider-BQMRbGHQ.js +2083 -0
- package/dist/{BusinessDetailView-DvhFfuGg.js → BusinessDetailView-BxGxWOme.js} +5 -5
- package/dist/{CrmDetailHeaderCard-e5332OkQ.js → CrmDetailHeaderCard-CCNJpMAK.js} +68 -67
- package/dist/{CrmDetailView-C-lsAhtD.js → CrmDetailView-ozCpuaX2.js} +14 -14
- package/dist/{DealCommunicationTabView-e7NkRy9r.js → DealCommunicationTabView-Df5EeolN.js} +2 -2
- package/dist/{DealDetailView-BDCbOBoo.js → DealDetailView-DdWHqaBr.js} +163 -163
- package/dist/{DealExternalAttachment-D1PznE3V.js → DealExternalAttachment-qHdh4yMI.js} +1 -1
- package/dist/{DealSendMailDialog-DVE2iYQC.js → DealSendMailDialog-BaYcWZP-.js} +65 -69
- package/dist/Error-BArv9rNb.js +12650 -0
- package/dist/IndividualDetailSidebarProvider-BXZH951l.js +608 -0
- package/dist/{IndividualDetailView-B7dX3hZ8.js → IndividualDetailView-DfYS31-e.js} +5 -5
- package/dist/LinkBrokenIcon-CTlqmapl.js +17 -0
- package/dist/api/mutations/deal/dealCreate.mutation.d.ts +1 -1
- package/dist/api/mutations/deal/dealUpdate.mutation.d.ts +3 -3
- package/dist/api/mutations/mail-template/mailTemplateUpdate.mutation.d.ts +1 -1
- package/dist/client/apiErrorCode.gen.d.ts +2 -2
- package/dist/client/sdk.gen.d.ts +20 -17
- package/dist/client/types.gen.d.ts +1057 -1376
- package/dist/client/zod.gen.d.ts +15453 -17750
- package/dist/{client-BP13IBbl.js → client-pCaNxE3C.js} +748 -1047
- package/dist/components/app/dialog/AppConfirmDialog.vue.d.ts +2 -2
- package/dist/components/crm-detail/CrmDetailHeaderCard.vue.d.ts +2 -0
- package/dist/components/crm-detail/CrmDetailSidebarAccordionContactPersonInfo.vue.d.ts +2 -2
- package/dist/components/crm-detail/CrmDetailSidebarAccordionGenericContactPersonInfo.vue.d.ts +2 -2
- package/dist/components/notes/NoteList.vue.d.ts +2 -2
- package/dist/deal/components/DealSendMailForm.vue.d.ts +2 -2
- package/dist/deal/components/DealSendMailFormFooter.vue.d.ts +1 -1
- package/dist/deal/components/DealSettingsDialogMailTemplateForm.vue.d.ts +2 -2
- package/dist/deal/components/DealSettingsDialogMailTemplateFormFields.vue.d.ts +2 -2
- package/dist/dialogs/contact-create/ContactCreateDialog.vue.d.ts +1 -1
- package/dist/dialogs/contact-create/components/ContactCreateDialogBusinessContactPersonSearch.vue.d.ts +2 -2
- package/dist/dialogs/contact-create/components/ContactCreateDialogBusinessGeneralInfo.vue.d.ts +2 -2
- package/dist/dialogs/contact-create/components/ContactCreateDialogFooter.vue.d.ts +2 -2
- package/dist/dialogs/contact-create/components/ContactCreateDialogFormSection.vue.d.ts +2 -2
- package/dist/dialogs/note/CrmDetailSidebarNotesView.vue.d.ts +2 -2
- package/dist/icons/LinkBrokenIcon.vue.d.ts +3 -0
- package/dist/icons/icon.d.ts +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +448 -453
- package/dist/models/brand-colors/brandColor.model.d.ts +14 -0
- package/dist/models/brand-colors/brandColor.transformer.d.ts +5 -0
- package/dist/models/conent-locale/contentLocaleEnum.model.d.ts +3 -3
- package/dist/models/deal/create/dealCreateForm.model.d.ts +2 -2
- package/dist/models/deal/detail/dealDetail.model.d.ts +2 -2
- package/dist/models/deal/index/dealIndex.model.d.ts +2 -2
- package/dist/models/deal/update/dealUpdateForm.model.d.ts +2 -2
- package/dist/models/mail-template/detail/mailTemplateDetail.model.d.ts +2 -2
- package/dist/models/mail-template/update/mailTemplateUpdateForm.model.d.ts +3 -3
- package/dist/models/phone-number/phoneNumberForm.model.d.ts +3 -0
- package/dist/models/tenant-config/tenantConfig.model.d.ts +3 -0
- package/dist/plugins/i18n.plugin.d.ts +4 -0
- package/dist/style.css +1 -1
- package/dist/testing/factories/business.factory.d.ts +2 -1
- package/dist/testing.js +23 -2
- package/package.json +2 -1
- package/dist/BusinessDetailSidebarProvider-D11bjWFa.js +0 -2081
- package/dist/BusinessDetailSidebarProvider-DYY-Uzvx.js +0 -2081
- package/dist/BusinessDetailSidebarProvider-ZYGQoNHh.js +0 -2081
- package/dist/BusinessDetailView-BOCy7G-w.js +0 -24
- package/dist/BusinessDetailView-WaATSNQS.js +0 -24
- package/dist/CrmDetailHeaderCard-C-JNdi7s.js +0 -2515
- package/dist/CrmDetailHeaderCard-qkNK-2wR.js +0 -2515
- package/dist/CrmDetailView-C6Xm1Lp6.js +0 -65
- package/dist/CrmDetailView-DQehs8Fb.js +0 -65
- package/dist/DealDetailView-BfkDNvK4.js +0 -1021
- package/dist/DealDetailView-Cs5TDhih.js +0 -1021
- package/dist/DealSendMailDialog-D5Voyhhc.js +0 -1556
- package/dist/DealSendMailDialog-OAn6xjLq.js +0 -1556
- package/dist/Error-5vt6UD4m.js +0 -3708
- package/dist/Error-B4TwHEhb.js +0 -3706
- package/dist/Error-BPxDpKcI.js +0 -3706
- package/dist/IndividualDetailSidebarProvider-CvZQdjzp.js +0 -606
- package/dist/IndividualDetailSidebarProvider-DBITt-9W.js +0 -606
- package/dist/IndividualDetailSidebarProvider-vIu7Hv8O.js +0 -606
- package/dist/IndividualDetailView-B1vbJXGc.js +0 -24
- package/dist/IndividualDetailView-BKEs0XS5.js +0 -24
- /package/dist/{LinkExternalIcon-B9Qg55Oa.js → LinkExternalIcon-LOVtSqBT.js} +0 -0
- /package/dist/{LinkIcon-DCW5zjbQ.js → LinkIcon-DqBbVrvs.js} +0 -0
- /package/dist/{LocationPinIcon-DBc-wt2e.js → LocationPinIcon-Cp-wRgk2.js} +0 -0
- /package/dist/{MailIcon-Do4a7S2W.js → MailIcon-CnTrB1k3.js} +0 -0
- /package/dist/{MobilePhoneIcon-DSXyKwjd.js → MobilePhoneIcon-B747hmpS.js} +0 -0
- /package/dist/{NumberedListIcon-DUaSJSYu.js → NumberedListIcon-amJxDaaD.js} +0 -0
- /package/dist/{PhoneIcon-C8Cv1IiW.js → PhoneIcon-94MYVL85.js} +0 -0
- /package/dist/{RefreshIcon-CKZgHIZU.js → RefreshIcon-DRe3coBc.js} +0 -0
- /package/dist/{SendIcon-B-sQkQ3W.js → SendIcon-MYItp1xI.js} +0 -0
- /package/dist/{SettingsIcon-DzP-IQS5.js → SettingsIcon-C0qTAv0w.js} +0 -0
- /package/dist/{StarOutlineIcon-c0VfXRdQ.js → StarOutlineIcon-CiFLgepk.js} +0 -0
- /package/dist/{StarYellowIcon-CH0CnlSU.js → StarYellowIcon-C0v_XGwI.js} +0 -0
- /package/dist/{ThreeDotsIcon-C6PCFq5J.js → ThreeDotsIcon-lujOTU3G.js} +0 -0
- /package/dist/{TimeLineMarkerIcon-6B6SbwTN.js → TimeLineMarkerIcon-C4LfErbc.js} +0 -0
- /package/dist/{TrashIcon-BTPSVviz.js → TrashIcon-v4L9SEK_.js} +0 -0
- /package/dist/{UploadCloudIcon-1aMW5OJq.js → UploadCloudIcon-j1-1Rvqb.js} +0 -0
- /package/dist/{UserCircleIcon-D-19dc-2.js → UserCircleIcon-BjUt_2C4.js} +0 -0
- /package/dist/{UserIcon-D1H8TGlg.js → UserIcon-Cb2jFKLr.js} +0 -0
- /package/dist/{VerticalDotsIcon-DmPza4Jd.js → VerticalDotsIcon-Y3m6tlQ2.js} +0 -0
- /package/dist/{WalletIcon-BlI3D3v-.js → WalletIcon-pPsKbzmh.js} +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,1037 @@
|
|
|
1
|
+
# @wisemen/wise-crm-web
|
|
2
|
+
|
|
3
|
+
A comprehensive CRM component library for Vue 3 applications, providing ready-to-use components, composables, and utilities for building CRM features.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Installation](#installation)
|
|
8
|
+
- [Quick Start](#quick-start)
|
|
9
|
+
- [Configuration](#configuration)
|
|
10
|
+
- [Components](#components)
|
|
11
|
+
- [Composables](#composables)
|
|
12
|
+
- [Routing](#routing)
|
|
13
|
+
- [Internationalization](#internationalization)
|
|
14
|
+
- [Icons](#icons)
|
|
15
|
+
- [Testing Utilities](#testing-utilities)
|
|
16
|
+
- [Type System](#type-system)
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# In a monorepo with pnpm workspaces
|
|
24
|
+
pnpm add @wisemen/wise-crm-web@workspace:*
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Or for external projects:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install @wisemen/wise-crm-web
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Quick Start
|
|
36
|
+
|
|
37
|
+
### 1. Initialize the CRM
|
|
38
|
+
|
|
39
|
+
Initialize the CRM configuration in your root layout or app entry point:
|
|
40
|
+
|
|
41
|
+
```vue
|
|
42
|
+
<script setup lang="ts">
|
|
43
|
+
import { useWiseCrmConfig } from '@wisemen/wise-crm-web'
|
|
44
|
+
import { BoardColumnTransitionTriggerType } from '@wisemen/wise-crm-web/client'
|
|
45
|
+
|
|
46
|
+
const wiseCrm = useWiseCrmConfig()
|
|
47
|
+
|
|
48
|
+
wiseCrm.init({
|
|
49
|
+
apiCrmBaseUrl: 'https://api.your-crm.com',
|
|
50
|
+
getAccessToken: () => oAuthClient.getAccessToken(),
|
|
51
|
+
googleMapsApiKey: 'YOUR_GOOGLE_MAPS_API_KEY',
|
|
52
|
+
locale: 'en-US',
|
|
53
|
+
options: {
|
|
54
|
+
deals: {
|
|
55
|
+
allowedTransitionTriggerTypes: [
|
|
56
|
+
BoardColumnTransitionTriggerType.EMAIL,
|
|
57
|
+
BoardColumnTransitionTriggerType.MANUAL,
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
widgets: {
|
|
61
|
+
entityStatistics: {
|
|
62
|
+
viewAllBusinessRouteName: 'crm-businesses',
|
|
63
|
+
viewAllIndividualRouteName: 'crm-individuals',
|
|
64
|
+
},
|
|
65
|
+
recentlyCreatedEntities: true,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
})
|
|
69
|
+
</script>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 2. Set Up Routes
|
|
73
|
+
|
|
74
|
+
Configure CRM routes in your router:
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import { useWiseCrmRoutes } from '@wisemen/wise-crm-web'
|
|
78
|
+
|
|
79
|
+
const routes = [
|
|
80
|
+
// ... your other routes
|
|
81
|
+
useWiseCrmRoutes({
|
|
82
|
+
businessTabRoutes: [
|
|
83
|
+
{
|
|
84
|
+
label: computed(() => 'Information'),
|
|
85
|
+
route: {
|
|
86
|
+
name: 'crm-business-information',
|
|
87
|
+
component: BusinessInformationTabView,
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
individualTabRoutes: [
|
|
92
|
+
{
|
|
93
|
+
label: computed(() => 'Information'),
|
|
94
|
+
route: {
|
|
95
|
+
name: 'crm-individual-information',
|
|
96
|
+
component: IndividualInformationTabView,
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
dealTabRoutes: [
|
|
101
|
+
{
|
|
102
|
+
label: computed(() => 'Information'),
|
|
103
|
+
route: {
|
|
104
|
+
name: 'crm-deal-information',
|
|
105
|
+
component: DealInformationTabView,
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
excludedReturnRoutes: [], // Optional: routes to exclude from return navigation
|
|
110
|
+
}),
|
|
111
|
+
]
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### 3. Integrate i18n and Icons
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
// i18n setup
|
|
118
|
+
import { wiseCrmLocales } from '@wisemen/wise-crm-web'
|
|
119
|
+
|
|
120
|
+
const messages = {
|
|
121
|
+
'en-US': {
|
|
122
|
+
...yourEnLocale,
|
|
123
|
+
...wiseCrmLocales['en-US'],
|
|
124
|
+
},
|
|
125
|
+
'nl-BE': {
|
|
126
|
+
...yourNlLocale,
|
|
127
|
+
...wiseCrmLocales['nl-BE'],
|
|
128
|
+
},
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Icons setup
|
|
132
|
+
import { wiseCrmIcons } from '@wisemen/wise-crm-web'
|
|
133
|
+
|
|
134
|
+
export const icons = {
|
|
135
|
+
...wiseCrmIcons,
|
|
136
|
+
...yourCustomIcons,
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Configuration
|
|
143
|
+
|
|
144
|
+
### `useWiseCrmConfig().init(options)`
|
|
145
|
+
|
|
146
|
+
Initialize the CRM with the following configuration options:
|
|
147
|
+
|
|
148
|
+
#### Required Parameters
|
|
149
|
+
|
|
150
|
+
| Parameter | Type | Description |
|
|
151
|
+
|-----------|------|-------------|
|
|
152
|
+
| `apiCrmBaseUrl` | `string` | Base URL for the CRM API |
|
|
153
|
+
| `getAccessToken` | `() => Promise<string>` | Function that returns the current authentication token |
|
|
154
|
+
| `googleMapsApiKey` | `string` | Google Maps API key for address autocomplete |
|
|
155
|
+
| `locale` | `Locale` | Initial locale ('en-US' or 'nl-BE') |
|
|
156
|
+
|
|
157
|
+
#### Options
|
|
158
|
+
|
|
159
|
+
##### `options.deals`
|
|
160
|
+
|
|
161
|
+
Configure deal/pipeline behavior:
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
{
|
|
165
|
+
deals: {
|
|
166
|
+
// Types of transitions allowed in the deal board
|
|
167
|
+
allowedTransitionTriggerTypes: BoardColumnTransitionTriggerType[]
|
|
168
|
+
} | null
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Available transition types:
|
|
173
|
+
- `BoardColumnTransitionTriggerType.MANUAL` - Manual drag & drop
|
|
174
|
+
- `BoardColumnTransitionTriggerType.EMAIL` - Email-triggered transitions
|
|
175
|
+
|
|
176
|
+
##### `options.widgets`
|
|
177
|
+
|
|
178
|
+
Configure widget behaviors:
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
{
|
|
182
|
+
widgets: {
|
|
183
|
+
entityStatistics?: {
|
|
184
|
+
// Route names for "View All" buttons in statistics widgets
|
|
185
|
+
viewAllBusinessRouteName: string
|
|
186
|
+
viewAllIndividualRouteName: string
|
|
187
|
+
}
|
|
188
|
+
// Enable recently created entities widget
|
|
189
|
+
recentlyCreatedEntities?: true
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Components
|
|
197
|
+
|
|
198
|
+
### Overview Components
|
|
199
|
+
|
|
200
|
+
#### `WiseCrmOverviewContent`
|
|
201
|
+
|
|
202
|
+
Main CRM dashboard with statistics widgets and recent activity.
|
|
203
|
+
|
|
204
|
+
```vue
|
|
205
|
+
<template>
|
|
206
|
+
<WiseCrmOverviewContent />
|
|
207
|
+
</template>
|
|
208
|
+
```
|
|
209
|
+
### Deal Components
|
|
210
|
+
|
|
211
|
+
#### `WiseCrmCrmDealOverview`
|
|
212
|
+
|
|
213
|
+
Kanban-style deal pipeline board with drag-and-drop.
|
|
214
|
+
|
|
215
|
+
```vue
|
|
216
|
+
<template>
|
|
217
|
+
<WiseCrmCrmDealOverview />
|
|
218
|
+
</template>
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Dialog Components
|
|
222
|
+
|
|
223
|
+
#### `WiseCrmContactCreateDialog`
|
|
224
|
+
|
|
225
|
+
Dialog for adding contact persons to a business.
|
|
226
|
+
|
|
227
|
+
```vue
|
|
228
|
+
<script setup lang="ts">
|
|
229
|
+
import { useWiseCrmContactCreateDialog, WiseCrmContactCreateDialog } from '@wisemen/wise-crm-web'
|
|
230
|
+
|
|
231
|
+
const contactDialog = useWiseCrmContactCreateDialog()
|
|
232
|
+
|
|
233
|
+
// Open from anywhere in your app
|
|
234
|
+
function addContact(): void {
|
|
235
|
+
contactDialog.open(businessUuid)
|
|
236
|
+
}
|
|
237
|
+
</script>
|
|
238
|
+
|
|
239
|
+
<template>
|
|
240
|
+
<WiseCrmContactCreateDialog />
|
|
241
|
+
</template>
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Card Components
|
|
245
|
+
|
|
246
|
+
#### `WiseCrmBusinessUpdateCard`
|
|
247
|
+
|
|
248
|
+
Form card for updating business information.
|
|
249
|
+
|
|
250
|
+
```vue
|
|
251
|
+
<script setup lang="ts">
|
|
252
|
+
import { useRouteParams } from '@vueuse/router'
|
|
253
|
+
import type { WiseCrmBusinessUuid } from '@wisemen/wise-crm-web'
|
|
254
|
+
import { WiseCrmBusinessUpdateCard } from '@wisemen/wise-crm-web'
|
|
255
|
+
|
|
256
|
+
const businessUuid = useRouteParams<WiseCrmBusinessUuid>('businessUuid', null)
|
|
257
|
+
</script>
|
|
258
|
+
|
|
259
|
+
<template>
|
|
260
|
+
<WiseCrmBusinessUpdateCard
|
|
261
|
+
v-if="businessUuid !== null"
|
|
262
|
+
:business-uuid="businessUuid"
|
|
263
|
+
/>
|
|
264
|
+
</template>
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**Props:**
|
|
268
|
+
- `businessUuid`: `WiseCrmBusinessUuid` - The business to update
|
|
269
|
+
|
|
270
|
+
#### `WiseCrmBusinessBillingInformationCard`
|
|
271
|
+
|
|
272
|
+
Form card for managing business billing information.
|
|
273
|
+
|
|
274
|
+
```vue
|
|
275
|
+
<template>
|
|
276
|
+
<WiseCrmBusinessBillingInformationCard :business-uuid="businessUuid" />
|
|
277
|
+
</template>
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
**Props:**
|
|
281
|
+
- `businessUuid`: `WiseCrmBusinessUuid` - The business UUID
|
|
282
|
+
|
|
283
|
+
#### `WiseCrmIndividualUpdateCard`
|
|
284
|
+
|
|
285
|
+
Form card for updating individual information.
|
|
286
|
+
|
|
287
|
+
```vue
|
|
288
|
+
<template>
|
|
289
|
+
<WiseCrmIndividualUpdateCard :individual-uuid="individualUuid" />
|
|
290
|
+
</template>
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
**Props:**
|
|
294
|
+
- `individualUuid`: `WiseCrmIndividualUuid` - The individual UUID
|
|
295
|
+
|
|
296
|
+
#### `WiseCrmIndividualBillingInformationCard`
|
|
297
|
+
|
|
298
|
+
Form card for managing individual billing information.
|
|
299
|
+
|
|
300
|
+
```vue
|
|
301
|
+
<template>
|
|
302
|
+
<WiseCrmIndividualBillingInformationCard :individual-uuid="individualUuid" />
|
|
303
|
+
</template>
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
**Props:**
|
|
307
|
+
- `individualUuid`: `WiseCrmIndividualUuid` - The individual UUID
|
|
308
|
+
|
|
309
|
+
### Widget Components
|
|
310
|
+
|
|
311
|
+
#### `WiseCrmBusinessWidget`
|
|
312
|
+
|
|
313
|
+
Statistics widget showing business metrics.
|
|
314
|
+
|
|
315
|
+
```vue
|
|
316
|
+
<template>
|
|
317
|
+
<WiseCrmBusinessWidget />
|
|
318
|
+
</template>
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
#### `WiseCrmIndividualWidget`
|
|
322
|
+
|
|
323
|
+
Statistics widget showing individual metrics.
|
|
324
|
+
|
|
325
|
+
```vue
|
|
326
|
+
<template>
|
|
327
|
+
<WiseCrmIndividualWidget />
|
|
328
|
+
</template>
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
#### `WiseCrmRecentlyCreatedWidget`
|
|
332
|
+
|
|
333
|
+
Widget displaying recently created entities.
|
|
334
|
+
|
|
335
|
+
```vue
|
|
336
|
+
<template>
|
|
337
|
+
<WiseCrmRecentlyCreatedWidget />
|
|
338
|
+
</template>
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
---
|
|
342
|
+
|
|
343
|
+
## Composables
|
|
344
|
+
|
|
345
|
+
### `useWiseCrm()`
|
|
346
|
+
|
|
347
|
+
Main composable for CRM operations and navigation.
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
import { useWiseCrm } from '@wisemen/wise-crm-web'
|
|
351
|
+
|
|
352
|
+
const crm = useWiseCrm()
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
#### Methods
|
|
356
|
+
|
|
357
|
+
##### `openBusinessDetail(businessUuid: WiseCrmBusinessUuid): void`
|
|
358
|
+
|
|
359
|
+
Navigate to business detail page.
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
crm.openBusinessDetail(businessUuid)
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
##### `openIndividualDetail(individualUuid: WiseCrmIndividualUuid): void`
|
|
366
|
+
|
|
367
|
+
Navigate to individual detail page.
|
|
368
|
+
|
|
369
|
+
```typescript
|
|
370
|
+
crm.openIndividualDetail(individualUuid)
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
##### `getEntityConfig(type: EntityType): EntityConfig | null`
|
|
374
|
+
|
|
375
|
+
Get configuration for a specific entity type.
|
|
376
|
+
|
|
377
|
+
```typescript
|
|
378
|
+
const businessConfig = crm.getEntityConfig(EntityType.BUSINESS)
|
|
379
|
+
console.log(businessConfig?.name) // Localized name like "Business" or "Bedrijf"
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
##### `goToReturnRoute(): void`
|
|
383
|
+
|
|
384
|
+
Navigate back to the stored return route (useful for "back" buttons).
|
|
385
|
+
|
|
386
|
+
```typescript
|
|
387
|
+
crm.goToReturnRoute()
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
##### `storeReturnRoute(route: RouteLocationNormalized, excludedRoutes?: (string | RegExp)[]): void`
|
|
391
|
+
|
|
392
|
+
Manually store a return route (usually handled automatically by `useWiseCrmRoutes`).
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
crm.storeReturnRoute(router.currentRoute.value, ['crm-detail'])
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### `useWiseCrmConfig()`
|
|
399
|
+
|
|
400
|
+
CRM initialization and configuration composable.
|
|
401
|
+
|
|
402
|
+
```typescript
|
|
403
|
+
import { useWiseCrmConfig } from '@wisemen/wise-crm-web'
|
|
404
|
+
|
|
405
|
+
const wiseCrm = useWiseCrmConfig()
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
#### Properties
|
|
409
|
+
|
|
410
|
+
##### `isInitialized: Ref<boolean>`
|
|
411
|
+
|
|
412
|
+
Reactive flag indicating if CRM has been initialized.
|
|
413
|
+
|
|
414
|
+
```typescript
|
|
415
|
+
watch(wiseCrm.isInitialized, (initialized) => {
|
|
416
|
+
if (initialized) {
|
|
417
|
+
console.log('CRM is ready!')
|
|
418
|
+
}
|
|
419
|
+
})
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
#### Methods
|
|
423
|
+
|
|
424
|
+
##### `init(props: InitProps): Promise<void>`
|
|
425
|
+
|
|
426
|
+
Initialize the CRM (see [Configuration](#configuration) section).
|
|
427
|
+
|
|
428
|
+
##### `getConfig(): TenantConfig`
|
|
429
|
+
|
|
430
|
+
Get the current tenant configuration.
|
|
431
|
+
|
|
432
|
+
```typescript
|
|
433
|
+
const config = wiseCrm.getConfig()
|
|
434
|
+
console.log(config.entities) // Entity configurations
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
##### `getOptions(): InitProps['options']`
|
|
438
|
+
|
|
439
|
+
Get the initialization options.
|
|
440
|
+
|
|
441
|
+
```typescript
|
|
442
|
+
const options = wiseCrm.getOptions()
|
|
443
|
+
console.log(options.deals?.allowedTransitionTriggerTypes)
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
##### `getCustomFieldDefinitionForEntity(entityType: EntityType): CustomFieldDefinitionIndex[]`
|
|
447
|
+
|
|
448
|
+
Get custom field definitions for an entity type.
|
|
449
|
+
|
|
450
|
+
```typescript
|
|
451
|
+
const customFields = wiseCrm.getCustomFieldDefinitionForEntity(EntityType.BUSINESS)
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
### `useWiseCrmContactCreateDialog()`
|
|
455
|
+
|
|
456
|
+
Composable for controlling the contact creation dialog.
|
|
457
|
+
|
|
458
|
+
```typescript
|
|
459
|
+
import { useWiseCrmContactCreateDialog } from '@wisemen/wise-crm-web'
|
|
460
|
+
|
|
461
|
+
const contactDialog = useWiseCrmContactCreateDialog()
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
#### Methods
|
|
465
|
+
|
|
466
|
+
##### `open(businessUuid: WiseCrmBusinessUuid): void`
|
|
467
|
+
|
|
468
|
+
Open the contact creation dialog for a specific business.
|
|
469
|
+
|
|
470
|
+
```typescript
|
|
471
|
+
contactDialog.open(businessUuid)
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
---
|
|
475
|
+
|
|
476
|
+
## Routing
|
|
477
|
+
|
|
478
|
+
### `useWiseCrmRoutes(options)`
|
|
479
|
+
|
|
480
|
+
Generate CRM routes with tab-based detail views.
|
|
481
|
+
|
|
482
|
+
```typescript
|
|
483
|
+
import type { ComputedRef } from 'vue'
|
|
484
|
+
import { useWiseCrmRoutes } from '@wisemen/wise-crm-web'
|
|
485
|
+
|
|
486
|
+
interface CrmRouteOptions {
|
|
487
|
+
label: ComputedRef<string>
|
|
488
|
+
route: RouteRecordRaw
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
const crmRoutes = useWiseCrmRoutes({
|
|
492
|
+
businessTabRoutes: CrmRouteOptions[],
|
|
493
|
+
individualTabRoutes: CrmRouteOptions[],
|
|
494
|
+
dealTabRoutes: CrmRouteOptions[],
|
|
495
|
+
excludedReturnRoutes?: (string | RegExp)[], // Optional
|
|
496
|
+
})
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
#### Parameters
|
|
500
|
+
|
|
501
|
+
- `businessTabRoutes`: Array of tab routes for business detail pages
|
|
502
|
+
- `individualTabRoutes`: Array of tab routes for individual detail pages
|
|
503
|
+
- `dealTabRoutes`: Array of tab routes for deal detail pages
|
|
504
|
+
- `excludedReturnRoutes`: Routes to exclude from return navigation tracking
|
|
505
|
+
|
|
506
|
+
#### Example
|
|
507
|
+
|
|
508
|
+
```typescript
|
|
509
|
+
const crmRoutes = useWiseCrmRoutes({
|
|
510
|
+
businessTabRoutes: [
|
|
511
|
+
{
|
|
512
|
+
label: computed(() => i18n.t('information')),
|
|
513
|
+
route: {
|
|
514
|
+
name: 'crm-business-information',
|
|
515
|
+
path: 'information',
|
|
516
|
+
component: BusinessInformationView,
|
|
517
|
+
},
|
|
518
|
+
},
|
|
519
|
+
{
|
|
520
|
+
label: computed(() => i18n.t('contacts')),
|
|
521
|
+
route: {
|
|
522
|
+
name: 'crm-business-contacts',
|
|
523
|
+
path: 'contacts',
|
|
524
|
+
component: BusinessContactsView,
|
|
525
|
+
},
|
|
526
|
+
},
|
|
527
|
+
],
|
|
528
|
+
individualTabRoutes: [
|
|
529
|
+
{
|
|
530
|
+
label: computed(() => i18n.t('information')),
|
|
531
|
+
route: {
|
|
532
|
+
name: 'crm-individual-information',
|
|
533
|
+
path: 'information',
|
|
534
|
+
component: IndividualInformationView,
|
|
535
|
+
},
|
|
536
|
+
},
|
|
537
|
+
],
|
|
538
|
+
dealTabRoutes: [],
|
|
539
|
+
excludedReturnRoutes: [
|
|
540
|
+
'crm-business-detail',
|
|
541
|
+
'crm-individual-detail',
|
|
542
|
+
/^crm-.*-edit$/,
|
|
543
|
+
],
|
|
544
|
+
})
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
### Generated Routes
|
|
548
|
+
|
|
549
|
+
The composable automatically generates these route patterns:
|
|
550
|
+
|
|
551
|
+
- `/individual/:individualUuid` - Individual detail page with tabs
|
|
552
|
+
- `/business/:businessUuid` - Business detail page with tabs
|
|
553
|
+
- `/deal/:dealUuid` - Deal detail page with tabs
|
|
554
|
+
|
|
555
|
+
---
|
|
556
|
+
|
|
557
|
+
## Internationalization
|
|
558
|
+
|
|
559
|
+
### Available Locales
|
|
560
|
+
|
|
561
|
+
- `en-US` - English (United States)
|
|
562
|
+
- `nl-BE` - Dutch (Belgium)
|
|
563
|
+
|
|
564
|
+
### Integration
|
|
565
|
+
|
|
566
|
+
```typescript
|
|
567
|
+
import { wiseCrmLocales } from '@wisemen/wise-crm-web'
|
|
568
|
+
|
|
569
|
+
const i18n = createI18n({
|
|
570
|
+
messages: {
|
|
571
|
+
'en-US': {
|
|
572
|
+
...yourMessages,
|
|
573
|
+
...wiseCrmLocales['en-US'],
|
|
574
|
+
},
|
|
575
|
+
'nl-BE': {
|
|
576
|
+
...yourMessages,
|
|
577
|
+
...wiseCrmLocales['nl-BE'],
|
|
578
|
+
},
|
|
579
|
+
},
|
|
580
|
+
})
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
### Updating Locale
|
|
584
|
+
|
|
585
|
+
The CRM automatically watches for locale changes if you're using vue-i18n. To manually update:
|
|
586
|
+
|
|
587
|
+
```typescript
|
|
588
|
+
import { useI18n } from 'vue-i18n'
|
|
589
|
+
|
|
590
|
+
const i18n = useI18n()
|
|
591
|
+
i18n.locale.value = 'nl-BE' // CRM will automatically update
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
---
|
|
595
|
+
|
|
596
|
+
## Icons
|
|
597
|
+
|
|
598
|
+
### Integration
|
|
599
|
+
|
|
600
|
+
```typescript
|
|
601
|
+
import { wiseCrmIcons } from '@wisemen/wise-crm-web'
|
|
602
|
+
|
|
603
|
+
export const icons = {
|
|
604
|
+
...wiseCrmIcons,
|
|
605
|
+
// Your custom icons
|
|
606
|
+
customIcon: () => import('./CustomIcon.vue'),
|
|
607
|
+
}
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
### Available Icons
|
|
611
|
+
|
|
612
|
+
The CRM includes icons for:
|
|
613
|
+
- Entity types (business, individual, deal)
|
|
614
|
+
- Actions (add, edit, delete, search)
|
|
615
|
+
- Navigation (back, forward, close)
|
|
616
|
+
- Status indicators
|
|
617
|
+
- And more...
|
|
618
|
+
|
|
619
|
+
---
|
|
620
|
+
|
|
621
|
+
## Testing Utilities
|
|
622
|
+
|
|
623
|
+
### Factory Classes
|
|
624
|
+
|
|
625
|
+
The library includes factory classes for generating mock data in tests.
|
|
626
|
+
|
|
627
|
+
#### Import Path
|
|
628
|
+
|
|
629
|
+
```typescript
|
|
630
|
+
import {
|
|
631
|
+
BusinessFactory,
|
|
632
|
+
IndividualFactory,
|
|
633
|
+
DealFactory,
|
|
634
|
+
NoteFactory,
|
|
635
|
+
} from '@wisemen/wise-crm-web/testing'
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
### `BusinessFactory`
|
|
639
|
+
|
|
640
|
+
#### Methods
|
|
641
|
+
|
|
642
|
+
##### `createDetail(overrides?): ViewBusinessDetailResponse`
|
|
643
|
+
|
|
644
|
+
Create a mock business detail object.
|
|
645
|
+
|
|
646
|
+
```typescript
|
|
647
|
+
const business = BusinessFactory.createDetail({
|
|
648
|
+
name: 'Custom Corp',
|
|
649
|
+
email: 'custom@example.com',
|
|
650
|
+
})
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
##### `createIndex(overrides?): ViewBusinessIndexResponseItem`
|
|
654
|
+
|
|
655
|
+
Create a mock business list item.
|
|
656
|
+
|
|
657
|
+
```typescript
|
|
658
|
+
const businessItem = BusinessFactory.createIndex({
|
|
659
|
+
name: 'List Item Corp',
|
|
660
|
+
})
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
##### `createIndexList(count, overrides?): ViewBusinessIndexResponseItem[]`
|
|
664
|
+
|
|
665
|
+
Create an array of mock business list items.
|
|
666
|
+
|
|
667
|
+
```typescript
|
|
668
|
+
const businesses = BusinessFactory.createIndexList(10)
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
##### `createBillingInformation(overrides?): ViewBusinessBillingInformationDetailResponse`
|
|
672
|
+
|
|
673
|
+
Create mock billing information.
|
|
674
|
+
|
|
675
|
+
```typescript
|
|
676
|
+
const billing = BusinessFactory.createBillingInformation({
|
|
677
|
+
invoiceEmail: 'billing@example.com',
|
|
678
|
+
})
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
##### `createContactPerson(overrides?): BusinessContactPersonResponse`
|
|
682
|
+
|
|
683
|
+
Create a mock contact person.
|
|
684
|
+
|
|
685
|
+
```typescript
|
|
686
|
+
const contact = BusinessFactory.createContactPerson({
|
|
687
|
+
firstName: 'John',
|
|
688
|
+
lastName: 'Doe',
|
|
689
|
+
})
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
##### `createStatistics(overrides?): ViewBusinessStatisticsResponse`
|
|
693
|
+
|
|
694
|
+
Create mock business statistics.
|
|
695
|
+
|
|
696
|
+
```typescript
|
|
697
|
+
const stats = BusinessFactory.createStatistics({
|
|
698
|
+
total: 100,
|
|
699
|
+
monthlyAdded: 10,
|
|
700
|
+
})
|
|
701
|
+
```
|
|
702
|
+
|
|
703
|
+
### `IndividualFactory`
|
|
704
|
+
|
|
705
|
+
Similar methods to `BusinessFactory` for individual entities:
|
|
706
|
+
|
|
707
|
+
- `createDetail(overrides?)`
|
|
708
|
+
- `createIndex(overrides?)`
|
|
709
|
+
- `createIndexList(count, overrides?)`
|
|
710
|
+
- `createBillingInformation(overrides?)`
|
|
711
|
+
- `createStatistics(overrides?)`
|
|
712
|
+
|
|
713
|
+
### `DealFactory`
|
|
714
|
+
|
|
715
|
+
- `createDetail(overrides?)`
|
|
716
|
+
- `createIndex(overrides?)`
|
|
717
|
+
- `createIndexList(count, overrides?)`
|
|
718
|
+
|
|
719
|
+
### `NoteFactory`
|
|
720
|
+
|
|
721
|
+
- `create(overrides?)`
|
|
722
|
+
- `createList(count, overrides?)`
|
|
723
|
+
|
|
724
|
+
### Testing Example
|
|
725
|
+
|
|
726
|
+
```typescript
|
|
727
|
+
import { expect, test } from '@playwright/test'
|
|
728
|
+
import { BusinessFactory } from '@wisemen/wise-crm-web/testing'
|
|
729
|
+
import { HttpResponse } from 'msw'
|
|
730
|
+
|
|
731
|
+
test('Create business', async ({ page, http, worker }) => {
|
|
732
|
+
const mockBusiness = BusinessFactory.createDetail({
|
|
733
|
+
name: 'Test Business',
|
|
734
|
+
})
|
|
735
|
+
|
|
736
|
+
await worker.use(
|
|
737
|
+
http.post('*/api/v1/businesses', () => {
|
|
738
|
+
return HttpResponse.json(
|
|
739
|
+
{ uuid: mockBusiness.uuid },
|
|
740
|
+
{ status: 201 }
|
|
741
|
+
)
|
|
742
|
+
}),
|
|
743
|
+
http.get(`*/api/v1/businesses/${mockBusiness.uuid}`, () => {
|
|
744
|
+
return HttpResponse.json(mockBusiness)
|
|
745
|
+
}),
|
|
746
|
+
)
|
|
747
|
+
|
|
748
|
+
await page.goto('/crm/businesses')
|
|
749
|
+
// ... rest of test
|
|
750
|
+
})
|
|
751
|
+
```
|
|
752
|
+
|
|
753
|
+
---
|
|
754
|
+
|
|
755
|
+
## Type System
|
|
756
|
+
|
|
757
|
+
### Entity UUID Types
|
|
758
|
+
|
|
759
|
+
The library exports branded UUID types for type safety:
|
|
760
|
+
|
|
761
|
+
```typescript
|
|
762
|
+
import type {
|
|
763
|
+
WiseCrmBusinessUuid,
|
|
764
|
+
WiseCrmIndividualUuid,
|
|
765
|
+
} from '@wisemen/wise-crm-web'
|
|
766
|
+
|
|
767
|
+
// These are branded types that prevent mixing UUIDs
|
|
768
|
+
function updateBusiness(uuid: WiseCrmBusinessUuid): void {
|
|
769
|
+
// TypeScript ensures you can't pass WiseCrmIndividualUuid here
|
|
770
|
+
}
|
|
771
|
+
```
|
|
772
|
+
|
|
773
|
+
### Validation Schemas
|
|
774
|
+
|
|
775
|
+
UUID schemas for runtime validation:
|
|
776
|
+
|
|
777
|
+
```typescript
|
|
778
|
+
import {
|
|
779
|
+
businessUuidSchema,
|
|
780
|
+
individualUuidSchema,
|
|
781
|
+
} from '@wisemen/wise-crm-web'
|
|
782
|
+
|
|
783
|
+
// Use with zod or similar validators
|
|
784
|
+
const result = businessUuidSchema.safeParse(value)
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
### Dialog Content Tabs
|
|
788
|
+
|
|
789
|
+
```typescript
|
|
790
|
+
import type { WiseCrmDialogContentTab } from '@wisemen/wise-crm-web'
|
|
791
|
+
|
|
792
|
+
// Type for custom dialog tab content
|
|
793
|
+
const tabs: WiseCrmDialogContentTab[] = [
|
|
794
|
+
{ label: 'General', component: GeneralTab },
|
|
795
|
+
{ label: 'Advanced', component: AdvancedTab },
|
|
796
|
+
]
|
|
797
|
+
```
|
|
798
|
+
|
|
799
|
+
---
|
|
800
|
+
|
|
801
|
+
## Environment Variables
|
|
802
|
+
|
|
803
|
+
### Required
|
|
804
|
+
|
|
805
|
+
```env
|
|
806
|
+
# CRM API Base URL
|
|
807
|
+
API_CRM_BASE_URL=https://api.your-crm.com
|
|
808
|
+
|
|
809
|
+
# Google Maps API Key (for address autocomplete)
|
|
810
|
+
GOOGLE_MAPS_API_KEY=your_google_maps_api_key
|
|
811
|
+
```
|
|
812
|
+
|
|
813
|
+
### Example `.env`
|
|
814
|
+
|
|
815
|
+
```env
|
|
816
|
+
API_CRM_BASE_URL=https://wise-crm.development.appwi.se
|
|
817
|
+
GOOGLE_MAPS_API_KEY=AIzaSyD0DOeAK9X_gXAtwPEyKPl4CaJc1dhKC9Q
|
|
818
|
+
```
|
|
819
|
+
|
|
820
|
+
---
|
|
821
|
+
|
|
822
|
+
## Advanced Usage
|
|
823
|
+
|
|
824
|
+
### Custom Field Definitions
|
|
825
|
+
|
|
826
|
+
Access custom field definitions for dynamic form generation:
|
|
827
|
+
|
|
828
|
+
```typescript
|
|
829
|
+
import { EntityType } from '@wisemen/wise-crm-web/client'
|
|
830
|
+
import { useWiseCrmConfig } from '@wisemen/wise-crm-web'
|
|
831
|
+
|
|
832
|
+
const crmConfig = useWiseCrmConfig()
|
|
833
|
+
|
|
834
|
+
const customFields = crmConfig.getCustomFieldDefinitionForEntity(
|
|
835
|
+
EntityType.BUSINESS
|
|
836
|
+
)
|
|
837
|
+
|
|
838
|
+
// Use customFields to render dynamic form fields
|
|
839
|
+
```
|
|
840
|
+
|
|
841
|
+
### Entity Configuration
|
|
842
|
+
|
|
843
|
+
Get localized entity names and colors:
|
|
844
|
+
|
|
845
|
+
```typescript
|
|
846
|
+
import { EntityType } from '@wisemen/wise-crm-web/client'
|
|
847
|
+
import { useWiseCrm } from '@wisemen/wise-crm-web'
|
|
848
|
+
|
|
849
|
+
const crm = useWiseCrm()
|
|
850
|
+
const businessConfig = crm.getEntityConfig(EntityType.BUSINESS)
|
|
851
|
+
|
|
852
|
+
console.log(businessConfig?.name) // "Business" or "Bedrijf"
|
|
853
|
+
console.log(businessConfig?.color) // "blue", "green", etc.
|
|
854
|
+
```
|
|
855
|
+
|
|
856
|
+
### CSS Custom Properties
|
|
857
|
+
|
|
858
|
+
The CRM automatically sets CSS custom properties for entity colors:
|
|
859
|
+
|
|
860
|
+
```css
|
|
861
|
+
/* Available CSS variables */
|
|
862
|
+
--wise-crm-business-50
|
|
863
|
+
--wise-crm-business-100
|
|
864
|
+
--wise-crm-business-200
|
|
865
|
+
/* ... etc for all color shades */
|
|
866
|
+
|
|
867
|
+
--wise-crm-individual-50
|
|
868
|
+
--wise-crm-individual-100
|
|
869
|
+
/* ... etc */
|
|
870
|
+
```
|
|
871
|
+
|
|
872
|
+
Use these in your custom components for consistent theming:
|
|
873
|
+
|
|
874
|
+
```vue
|
|
875
|
+
<style scoped>
|
|
876
|
+
.business-badge {
|
|
877
|
+
background-color: var(--wise-crm-business-100);
|
|
878
|
+
color: var(--wise-crm-business-700);
|
|
879
|
+
}
|
|
880
|
+
</style>
|
|
881
|
+
```
|
|
882
|
+
|
|
883
|
+
---
|
|
884
|
+
|
|
885
|
+
## Troubleshooting
|
|
886
|
+
|
|
887
|
+
### "CRM Tenant Config not initialized" Error
|
|
888
|
+
|
|
889
|
+
**Cause:** Attempting to use CRM components before initialization.
|
|
890
|
+
|
|
891
|
+
**Solution:** Ensure `useWiseCrmConfig().init()` is called before rendering any CRM components. Use `isInitialized` to conditionally render:
|
|
892
|
+
|
|
893
|
+
```vue
|
|
894
|
+
<script setup lang="ts">
|
|
895
|
+
import { useWiseCrmConfig } from '@wisemen/wise-crm-web'
|
|
896
|
+
|
|
897
|
+
const crmConfig = useWiseCrmConfig()
|
|
898
|
+
|
|
899
|
+
// Initialize in onMounted or similar
|
|
900
|
+
onMounted(async () => {
|
|
901
|
+
await crmConfig.init({ /* ... */ })
|
|
902
|
+
})
|
|
903
|
+
</script>
|
|
904
|
+
|
|
905
|
+
<template>
|
|
906
|
+
<div v-if="crmConfig.isInitialized.value">
|
|
907
|
+
<WiseCrmOverviewContent />
|
|
908
|
+
</div>
|
|
909
|
+
<div v-else>
|
|
910
|
+
Loading CRM...
|
|
911
|
+
</div>
|
|
912
|
+
</template>
|
|
913
|
+
```
|
|
914
|
+
|
|
915
|
+
### TypeScript Errors with Factory Methods
|
|
916
|
+
|
|
917
|
+
**Cause:** Stale TypeScript cache or build artifacts.
|
|
918
|
+
|
|
919
|
+
**Solution:**
|
|
920
|
+
1. Restart TypeScript server: `Cmd+Shift+P` → "TypeScript: Restart TS Server"
|
|
921
|
+
2. Rebuild packages: `pnpm build`
|
|
922
|
+
3. Clear build cache: `rm -rf dist node_modules/.cache`
|
|
923
|
+
|
|
924
|
+
### Address Autocomplete Not Working
|
|
925
|
+
|
|
926
|
+
**Cause:** Invalid or missing Google Maps API key.
|
|
927
|
+
|
|
928
|
+
**Solution:** Ensure your `GOOGLE_MAPS_API_KEY` environment variable is set and the key has the Places API enabled in Google Cloud Console.
|
|
929
|
+
|
|
930
|
+
---
|
|
931
|
+
|
|
932
|
+
## Examples
|
|
933
|
+
|
|
934
|
+
### Complete Integration Example
|
|
935
|
+
|
|
936
|
+
```vue
|
|
937
|
+
<!-- App.vue -->
|
|
938
|
+
<script setup lang="ts">
|
|
939
|
+
import { useWiseCrmConfig } from '@wisemen/wise-crm-web'
|
|
940
|
+
import { BoardColumnTransitionTriggerType } from '@wisemen/wise-crm-web/client'
|
|
941
|
+
import { onMounted } from 'vue'
|
|
942
|
+
|
|
943
|
+
const crmConfig = useWiseCrmConfig()
|
|
944
|
+
|
|
945
|
+
onMounted(async () => {
|
|
946
|
+
await crmConfig.init({
|
|
947
|
+
apiCrmBaseUrl: import.meta.env.API_CRM_BASE_URL,
|
|
948
|
+
getAccessToken: () => authClient.getToken(),
|
|
949
|
+
googleMapsApiKey: import.meta.env.GOOGLE_MAPS_API_KEY,
|
|
950
|
+
locale: 'en-US',
|
|
951
|
+
options: {
|
|
952
|
+
deals: {
|
|
953
|
+
allowedTransitionTriggerTypes: [
|
|
954
|
+
BoardColumnTransitionTriggerType.MANUAL,
|
|
955
|
+
],
|
|
956
|
+
},
|
|
957
|
+
widgets: {
|
|
958
|
+
entityStatistics: {
|
|
959
|
+
viewAllBusinessRouteName: 'businesses',
|
|
960
|
+
viewAllIndividualRouteName: 'individuals',
|
|
961
|
+
},
|
|
962
|
+
recentlyCreatedEntities: true,
|
|
963
|
+
},
|
|
964
|
+
},
|
|
965
|
+
})
|
|
966
|
+
})
|
|
967
|
+
</script>
|
|
968
|
+
|
|
969
|
+
<template>
|
|
970
|
+
<RouterView v-if="crmConfig.isInitialized.value" />
|
|
971
|
+
</template>
|
|
972
|
+
```
|
|
973
|
+
|
|
974
|
+
```typescript
|
|
975
|
+
// router.ts
|
|
976
|
+
import { createRouter } from 'vue-router'
|
|
977
|
+
import { useWiseCrmRoutes } from '@wisemen/wise-crm-web'
|
|
978
|
+
import { computed } from 'vue'
|
|
979
|
+
|
|
980
|
+
const router = createRouter({
|
|
981
|
+
routes: [
|
|
982
|
+
{
|
|
983
|
+
path: '/crm',
|
|
984
|
+
children: [
|
|
985
|
+
{
|
|
986
|
+
name: 'crm-overview',
|
|
987
|
+
path: '',
|
|
988
|
+
component: () => import('./views/CrmOverview.vue'),
|
|
989
|
+
},
|
|
990
|
+
{
|
|
991
|
+
name: 'crm-businesses',
|
|
992
|
+
path: 'businesses',
|
|
993
|
+
component: () => import('./views/BusinessList.vue'),
|
|
994
|
+
},
|
|
995
|
+
{
|
|
996
|
+
name: 'crm-individuals',
|
|
997
|
+
path: 'individuals',
|
|
998
|
+
component: () => import('./views/IndividualList.vue'),
|
|
999
|
+
},
|
|
1000
|
+
],
|
|
1001
|
+
},
|
|
1002
|
+
useWiseCrmRoutes({
|
|
1003
|
+
businessTabRoutes: [
|
|
1004
|
+
{
|
|
1005
|
+
label: computed(() => 'Information'),
|
|
1006
|
+
route: {
|
|
1007
|
+
name: 'business-info',
|
|
1008
|
+
path: 'information',
|
|
1009
|
+
component: () => import('./views/BusinessInfo.vue'),
|
|
1010
|
+
},
|
|
1011
|
+
},
|
|
1012
|
+
],
|
|
1013
|
+
individualTabRoutes: [
|
|
1014
|
+
{
|
|
1015
|
+
label: computed(() => 'Information'),
|
|
1016
|
+
route: {
|
|
1017
|
+
name: 'individual-info',
|
|
1018
|
+
path: 'information',
|
|
1019
|
+
component: () => import('./views/IndividualInfo.vue'),
|
|
1020
|
+
},
|
|
1021
|
+
},
|
|
1022
|
+
],
|
|
1023
|
+
dealTabRoutes: [],
|
|
1024
|
+
}),
|
|
1025
|
+
],
|
|
1026
|
+
})
|
|
1027
|
+
```
|
|
1028
|
+
|
|
1029
|
+
---
|
|
1030
|
+
|
|
1031
|
+
## License
|
|
1032
|
+
|
|
1033
|
+
MIT
|
|
1034
|
+
|
|
1035
|
+
## Support
|
|
1036
|
+
|
|
1037
|
+
For issues and questions, please contact the WiseMen Digital team.
|