@campxdev/campx-web-utils 2.0.14 → 2.0.16

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.
@@ -1,20 +1,19 @@
1
- import { axios } from '../../config/axios'
2
- import { workspace } from '../../utils/constants'
1
+ import { axios } from '../../config/axios';
3
2
 
4
3
  /**
5
4
  * Voice config from notification-configs API
6
5
  */
7
6
  export interface VoiceConfig {
8
- id: string
9
- isEnabled: boolean
10
- name: string
11
- channelType: string
7
+ id: string;
8
+ isEnabled: boolean;
9
+ name: string;
10
+ channelType: string;
12
11
  EXOTEL?: {
13
- appId: string
14
- appSecret: string
15
- token?: string
16
- tokenExpiresAt?: string
17
- }
12
+ appId: string;
13
+ appSecret: string;
14
+ token?: string;
15
+ tokenExpiresAt?: string;
16
+ };
18
17
  }
19
18
 
20
19
  /**
@@ -22,17 +21,17 @@ export interface VoiceConfig {
22
21
  */
23
22
  export interface NotificationConfigResponse {
24
23
  config: {
25
- id: string
26
- tenantId: string
27
- institutionUniqueId: number
28
- enableVoice?: boolean
29
- voiceConfigs?: VoiceConfig[]
24
+ id: string;
25
+ tenantId: string;
26
+ institutionUniqueId: number;
27
+ enableVoice?: boolean;
28
+ voiceConfigs?: VoiceConfig[];
30
29
  // ... other fields not relevant to VoIP
31
- }
30
+ };
32
31
  options: {
33
- voiceChannels?: string[]
32
+ voiceChannels?: string[];
34
33
  // ... other fields
35
- }
34
+ };
36
35
  }
37
36
 
38
37
  /**
@@ -42,28 +41,28 @@ export interface NotificationConfigResponse {
42
41
  * - voiceConfigs has at least one enabled config
43
42
  */
44
43
  export const checkVoIPEnabled = async (): Promise<{
45
- enabled: boolean
46
- hasValidToken: boolean
44
+ enabled: boolean;
45
+ hasValidToken: boolean;
47
46
  }> => {
48
47
  try {
49
48
  const { data } = await axios.get<NotificationConfigResponse>(
50
49
  '/notifications/notification-configs',
51
- )
50
+ );
52
51
 
53
- const config = data?.config
52
+ const config = data?.config;
54
53
 
55
54
  // Check if voice is enabled at tenant level
56
55
  if (!config?.enableVoice) {
57
- return { enabled: false, hasValidToken: false }
56
+ return { enabled: false, hasValidToken: false };
58
57
  }
59
58
 
60
59
  // Check if there's at least one enabled voice config
61
60
  const enabledVoiceConfig = config.voiceConfigs?.find(
62
61
  (vc) => vc.isEnabled === true,
63
- )
62
+ );
64
63
 
65
64
  if (!enabledVoiceConfig) {
66
- return { enabled: false, hasValidToken: false }
65
+ return { enabled: false, hasValidToken: false };
67
66
  }
68
67
 
69
68
  // Check if token exists and is not expired
@@ -71,116 +70,117 @@ export const checkVoIPEnabled = async (): Promise<{
71
70
  enabledVoiceConfig.EXOTEL?.token &&
72
71
  enabledVoiceConfig.EXOTEL?.tokenExpiresAt &&
73
72
  new Date(enabledVoiceConfig.EXOTEL.tokenExpiresAt) > new Date()
74
- )
73
+ );
75
74
 
76
- return { enabled: true, hasValidToken }
75
+ return { enabled: true, hasValidToken };
77
76
  } catch (error) {
78
- console.error('Failed to check VoIP config:', error)
79
- return { enabled: false, hasValidToken: false }
77
+ console.error('Failed to check VoIP config:', error);
78
+ return { enabled: false, hasValidToken: false };
80
79
  }
81
- }
80
+ };
82
81
 
83
82
  /**
84
83
  * Get the active Exotel voice token from the backend.
85
84
  * The backend manages credentials securely and auto-refreshes tokens.
86
85
  */
87
86
  export const getActiveVoiceToken = async (): Promise<{
88
- token: string
89
- expiresAt: string
87
+ token: string;
88
+ expiresAt: string;
90
89
  } | null> => {
91
90
  try {
92
91
  const { data } = await axios.get(
93
92
  '/notifications/notification-configs/voice-config/active-token',
94
- )
95
- return data
93
+ );
94
+ return data;
96
95
  } catch (error) {
97
- console.error('Failed to fetch Exotel token:', error)
98
- return null
96
+ console.error('Failed to fetch Exotel token:', error);
97
+ return null;
99
98
  }
100
- }
99
+ };
101
100
 
102
101
  /**
103
102
  * @deprecated Use getActiveVoiceToken instead.
104
103
  * This function is kept for backwards compatibility but will be removed.
105
104
  */
106
105
  export const createExotelAppToken = async () => {
107
- const tokenData = await getActiveVoiceToken()
106
+ const tokenData = await getActiveVoiceToken();
108
107
  if (!tokenData) {
109
- throw new Error('No active voice configuration found')
108
+ throw new Error('No active voice configuration found');
110
109
  }
111
- return { Data: tokenData.token }
112
- }
110
+ return { Data: tokenData.token };
111
+ };
113
112
 
114
113
  // ============ Call Activity APIs ============
115
114
 
116
115
  export interface CallActivity {
117
- id: string
118
- callSid: string
119
- prospectId: string
120
- direction: 'inbound' | 'outbound'
121
- status: string
122
- durationSeconds?: number
123
- createdAt: string
124
- startTime?: string
125
- endTime?: string
126
- fromNumber?: string
127
- toNumber?: string
128
- userId?: number
129
- dispositionCategory?: string
130
- dispositionReason?: string
131
- dispositionNotes?: string
132
- callStatusDisposition?: 'connected' | 'not_connected'
133
- recordingUrl?: string
116
+ id: string;
117
+ callSid: string;
118
+ prospectId: string;
119
+ direction: 'inbound' | 'outbound';
120
+ status: string;
121
+ durationSeconds?: number;
122
+ createdAt: string;
123
+ startTime?: string;
124
+ endTime?: string;
125
+ fromNumber?: string;
126
+ toNumber?: string;
127
+ userId?: number;
128
+ dispositionCategory?: string;
129
+ dispositionReason?: string;
130
+ dispositionNotes?: string;
131
+ callStatusDisposition?: 'connected' | 'not_connected';
132
+ recordingUrl?: string;
134
133
  }
135
134
 
136
135
  export interface InitiateCallInput {
137
- prospectId: string
138
- toNumber: string
139
- fromNumber?: string
140
- userId?: number
141
- callSid?: string // Exotel CallSid from SDK response
136
+ prospectId: string;
137
+ toNumber: string;
138
+ fromNumber?: string;
139
+ userId?: number;
140
+ callSid?: string; // Exotel CallSid from SDK response
142
141
  }
143
142
 
144
143
  export interface SaveDispositionInput {
145
- callId: string
146
- prospectId?: string
147
- callStatusDisposition?: 'connected' | 'not_connected'
148
- dispositionCategory: string
149
- dispositionReason?: string
150
- dispositionNotes?: string
151
- callbackScheduledAt?: string
144
+ callId: string;
145
+ prospectId?: string;
146
+ callStatusDisposition?: 'connected' | 'not_connected'; // Step 1: Call Status
147
+ dispositionCategory: string; // Step 2: Call Disposition
148
+ prospectStatus?: string; // Step 3: Prospect Status (optional)
149
+ dispositionReason?: string; // Deprecated
150
+ dispositionNotes?: string; // Step 4: Notes/Remarks
151
+ callbackScheduledAt?: string;
152
152
  }
153
153
 
154
154
  export interface CancelCallInput {
155
- callSid: string
156
- reason?: string // 'declined' | 'cancelled' | 'missed' | 'timeout'
155
+ callSid: string;
156
+ reason?: string; // 'declined' | 'cancelled' | 'missed' | 'timeout'
157
157
  }
158
158
 
159
159
  export interface CallActivityResponse {
160
- success: boolean
161
- message: string
162
- data: CallActivity
160
+ success: boolean;
161
+ message: string;
162
+ data: CallActivity;
163
163
  }
164
164
 
165
165
  export interface RegisterIncomingCallInput {
166
- callSid: string
167
- fromNumber: string
168
- toNumber?: string
169
- prospectId?: string
170
- userId?: number
166
+ callSid: string;
167
+ fromNumber: string;
168
+ toNumber?: string;
169
+ prospectId?: string;
170
+ userId?: number;
171
171
  }
172
172
 
173
173
  export interface RegisterIncomingCallResponse {
174
- success: boolean
175
- message: string
176
- data: CallActivity
174
+ success: boolean;
175
+ message: string;
176
+ data: CallActivity;
177
177
  prospect?: {
178
- id: string
179
- uniqueId?: number
180
- prospectId?: string // Formatted ID like PRSP-000001
181
- name: string
182
- mobile: string
183
- }
178
+ id: string;
179
+ uniqueId?: number;
180
+ prospectId?: string; // Formatted ID like PRSP-000001
181
+ name: string;
182
+ mobile: string;
183
+ };
184
184
  }
185
185
 
186
186
  /**
@@ -189,14 +189,12 @@ export interface RegisterIncomingCallResponse {
189
189
  export const initiateCallActivity = async (
190
190
  input: InitiateCallInput,
191
191
  ): Promise<{ success: boolean; message: string; data: CallActivity }> => {
192
- const endpoint =
193
- workspace === 'common-workspace'
194
- ? `/paymentx/call-activities`
195
- : `/call-activities`
196
-
197
- const { data } = await axios.post(`${endpoint}/initiate`, input)
198
- return data
199
- }
192
+ const { data } = await axios.post(
193
+ `/communication-activities/initiate`,
194
+ input,
195
+ );
196
+ return data;
197
+ };
200
198
 
201
199
  /**
202
200
  * Register an incoming call - creates call activity record
@@ -204,14 +202,12 @@ export const initiateCallActivity = async (
204
202
  export const registerIncomingCall = async (
205
203
  input: RegisterIncomingCallInput,
206
204
  ): Promise<RegisterIncomingCallResponse> => {
207
- const endpoint =
208
- workspace === 'common-workspace'
209
- ? `/paymentx/call-activities`
210
- : `/call-activities`
211
-
212
- const { data } = await axios.post(`${endpoint}/register-incoming`, input)
213
- return data
214
- }
205
+ const { data } = await axios.post(
206
+ `/communication-activities/register-incoming`,
207
+ input,
208
+ );
209
+ return data;
210
+ };
215
211
 
216
212
  /**
217
213
  * Fetch call history for a prospect
@@ -219,16 +215,11 @@ export const registerIncomingCall = async (
219
215
  export const fetchCallHistory = async (
220
216
  prospectId: string,
221
217
  ): Promise<CallActivity[]> => {
222
- const endpoint =
223
- workspace === 'common-workspace'
224
- ? `/paymentx/call-activities`
225
- : `/call-activities`
226
-
227
- const { data } = await axios.get(`${endpoint}/by-prospect`, {
218
+ const { data } = await axios.get(`/communication-activities/by-prospect`, {
228
219
  params: { prospectId },
229
- })
230
- return data
231
- }
220
+ });
221
+ return data;
222
+ };
232
223
 
233
224
  /**
234
225
  * Get call activity by ID
@@ -236,14 +227,9 @@ export const fetchCallHistory = async (
236
227
  export const getCallActivityById = async (
237
228
  id: string,
238
229
  ): Promise<CallActivity> => {
239
- const endpoint =
240
- workspace === 'common-workspace'
241
- ? `/paymentx/call-activities`
242
- : `/call-activities`
243
-
244
- const { data } = await axios.get(`${endpoint}/${id}`)
245
- return data
246
- }
230
+ const { data } = await axios.get(`/communication-activities/${id}`);
231
+ return data;
232
+ };
247
233
 
248
234
  /**
249
235
  * Get call activity by CallSid
@@ -251,16 +237,11 @@ export const getCallActivityById = async (
251
237
  export const getCallActivityByCallSid = async (
252
238
  callSid: string,
253
239
  ): Promise<CallActivity> => {
254
- const endpoint =
255
- workspace === 'common-workspace'
256
- ? `/paymentx/call-activities`
257
- : `/call-activities`
258
-
259
- const { data } = await axios.get(`${endpoint}/by-call-sid`, {
240
+ const { data } = await axios.get(`/communication-activities/by-call-sid`, {
260
241
  params: { callSid },
261
- })
262
- return data
263
- }
242
+ });
243
+ return data;
244
+ };
264
245
 
265
246
  /**
266
247
  * Get call count for a prospect
@@ -268,16 +249,14 @@ export const getCallActivityByCallSid = async (
268
249
  export const getCallCountByProspect = async (
269
250
  prospectId: string,
270
251
  ): Promise<number> => {
271
- const endpoint =
272
- workspace === 'common-workspace'
273
- ? `/paymentx/call-activities`
274
- : `/call-activities`
275
-
276
- const { data } = await axios.get(`${endpoint}/count-by-prospect`, {
277
- params: { prospectId },
278
- })
279
- return data?.count || 0
280
- }
252
+ const { data } = await axios.get(
253
+ `/communication-activities/count-by-prospect`,
254
+ {
255
+ params: { prospectId },
256
+ },
257
+ );
258
+ return data?.count || 0;
259
+ };
281
260
 
282
261
  /**
283
262
  * Save call disposition
@@ -285,21 +264,20 @@ export const getCallCountByProspect = async (
285
264
  export const saveCallDisposition = async (
286
265
  input: SaveDispositionInput,
287
266
  ): Promise<CallActivity> => {
288
- const endpoint =
289
- workspace === 'common-workspace'
290
- ? `/paymentx/call-activities`
291
- : `/call-activities`
292
-
293
267
  const requestBody = {
294
268
  callStatusDisposition: input.callStatusDisposition,
295
269
  dispositionCategory: input.dispositionCategory,
270
+ prospectStatus: input.prospectStatus,
296
271
  dispositionNotes: input.dispositionNotes,
297
272
  callbackScheduledAt: input.callbackScheduledAt,
298
273
  };
299
274
 
300
- const { data } = await axios.post(`${endpoint}/${input.callId}/disposition`, requestBody)
301
- return data
302
- }
275
+ const { data } = await axios.post(
276
+ `/communication-activities/${input.callId}/disposition`,
277
+ requestBody,
278
+ );
279
+ return data;
280
+ };
303
281
 
304
282
  /**
305
283
  * Cancel/decline a call before it was connected
@@ -308,12 +286,6 @@ export const saveCallDisposition = async (
308
286
  export const cancelCall = async (
309
287
  input: CancelCallInput,
310
288
  ): Promise<{ success: boolean; message: string }> => {
311
- const endpoint =
312
- workspace === 'common-workspace'
313
- ? `/paymentx/call-activities`
314
- : `/call-activities`
315
-
316
- const { data } = await axios.post(`${endpoint}/cancel`, input)
317
- return data
318
- }
319
-
289
+ const { data } = await axios.post(`/communication-activities/cancel`, input);
290
+ return data;
291
+ };
@@ -26,6 +26,7 @@ export const workspaceApiMapping: Record<string, string> = {
26
26
  'finance-officer-workspace': 'finance-officer-api',
27
27
  'outreach-agent-workspace': 'outreach-agent-api',
28
28
  'prospect-workspace': 'prospect-api',
29
+ 'external-expert-workspace': 'external-expert-api',
29
30
  'research-coordinator-workspace': 'research-coordinator-api',
30
31
  'tele-counsellor-workspace': 'tele-counsellor-api',
31
32
  'team-owner-workspace': '/team-owner-api',