@campxdev/campx-web-utils 2.0.13 → 2.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/cjs/index.js +1 -1
  2. package/dist/cjs/types/src/components/Exotel/CallButton.d.ts +10 -0
  3. package/dist/cjs/types/src/components/Exotel/CallDispositionForm.d.ts +29 -0
  4. package/dist/cjs/types/src/components/Exotel/ExotelPhone.d.ts +10 -0
  5. package/dist/cjs/types/src/components/Exotel/ExotelWrapper.d.ts +14 -0
  6. package/dist/cjs/types/src/components/Exotel/MicrophonePermission.d.ts +6 -0
  7. package/dist/cjs/types/src/components/Exotel/index.d.ts +6 -0
  8. package/dist/cjs/types/src/config/index.d.ts +1 -0
  9. package/dist/cjs/types/src/config/voip.config.d.ts +18 -0
  10. package/dist/cjs/types/src/constants/exotel.constants.d.ts +7 -0
  11. package/dist/cjs/types/src/providers/ExotelProvider.d.ts +79 -0
  12. package/dist/cjs/types/src/providers/VoIPProvider.d.ts +33 -0
  13. package/dist/cjs/types/src/providers/index.d.ts +2 -0
  14. package/dist/cjs/types/src/services/crypto/CryptoService.d.ts +23 -0
  15. package/dist/cjs/types/src/services/exotel/ExotelService.d.ts +47 -0
  16. package/dist/cjs/types/src/services/exotel/api.d.ts +158 -0
  17. package/dist/cjs/types/src/services/exotel/index.d.ts +2 -0
  18. package/dist/cjs/types/src/utils/exotel/formatters.d.ts +8 -0
  19. package/dist/cjs/types/src/utils/exotel/index.d.ts +1 -0
  20. package/dist/esm/index.js +2 -2
  21. package/dist/esm/types/src/components/Exotel/CallButton.d.ts +10 -0
  22. package/dist/esm/types/src/components/Exotel/CallDispositionForm.d.ts +29 -0
  23. package/dist/esm/types/src/components/Exotel/ExotelPhone.d.ts +10 -0
  24. package/dist/esm/types/src/components/Exotel/ExotelWrapper.d.ts +14 -0
  25. package/dist/esm/types/src/components/Exotel/MicrophonePermission.d.ts +6 -0
  26. package/dist/esm/types/src/components/Exotel/index.d.ts +6 -0
  27. package/dist/esm/types/src/config/index.d.ts +1 -0
  28. package/dist/esm/types/src/config/voip.config.d.ts +18 -0
  29. package/dist/esm/types/src/constants/exotel.constants.d.ts +7 -0
  30. package/dist/esm/types/src/providers/ExotelProvider.d.ts +79 -0
  31. package/dist/esm/types/src/providers/VoIPProvider.d.ts +33 -0
  32. package/dist/esm/types/src/providers/index.d.ts +2 -0
  33. package/dist/esm/types/src/services/crypto/CryptoService.d.ts +23 -0
  34. package/dist/esm/types/src/services/exotel/ExotelService.d.ts +47 -0
  35. package/dist/esm/types/src/services/exotel/api.d.ts +158 -0
  36. package/dist/esm/types/src/services/exotel/index.d.ts +2 -0
  37. package/dist/esm/types/src/utils/exotel/formatters.d.ts +8 -0
  38. package/dist/esm/types/src/utils/exotel/index.d.ts +1 -0
  39. package/dist/index.d.ts +357 -3
  40. package/dist/styles.css +337 -47
  41. package/dist/types/exotel-crm-websdk.d.ts +46 -0
  42. package/export.ts +6 -0
  43. package/package.json +4 -1
  44. package/src/components/Exotel/CallButton.tsx +164 -0
  45. package/src/components/Exotel/CallDispositionForm.tsx +213 -0
  46. package/src/components/Exotel/ExotelPhone.tsx +482 -0
  47. package/src/components/Exotel/ExotelWrapper.tsx +80 -0
  48. package/src/components/Exotel/MicrophonePermission.tsx +97 -0
  49. package/src/components/Exotel/index.ts +10 -0
  50. package/src/config/index.ts +1 -0
  51. package/src/config/voip.config.ts +26 -0
  52. package/src/constants/exotel.constants.ts +7 -0
  53. package/src/providers/ExotelProvider.tsx +526 -0
  54. package/src/providers/VoIPProvider.tsx +143 -0
  55. package/src/providers/index.ts +2 -0
  56. package/src/selectors/ResearchStageSelector.tsx +1 -0
  57. package/src/services/crypto/CryptoService.ts +112 -0
  58. package/src/services/exotel/ExotelService.ts +238 -0
  59. package/src/services/exotel/api.ts +319 -0
  60. package/src/services/exotel/index.ts +2 -0
  61. package/src/utils/exotel/formatters.ts +17 -0
  62. package/src/utils/exotel/index.ts +1 -0
  63. package/types/exotel-crm-websdk.d.ts +46 -0
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import * as _axios from 'axios';
2
2
  import { Severity, ConfirmDialogType, MultiSelectProps, SingleSelectProps } from '@campxdev/react-blueprint';
3
3
  import { Store } from 'pullstate';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
5
- import { ReactNode } from 'react';
5
+ import React, { ReactNode } from 'react';
6
6
  import { ReducersMapObject } from '@reduxjs/toolkit';
7
7
  export { BrowserRouter } from 'react-router-dom';
8
8
 
@@ -30,6 +30,25 @@ declare function createRsbuildSharedConfig(dependencies: Dependencies, alwaysEag
30
30
 
31
31
  declare const nonWorkspaceAxios: _axios.AxiosInstance;
32
32
 
33
+ /**
34
+ * VoIP Configuration Module
35
+ *
36
+ * This module manages VoIP/Exotel configuration for workspaces.
37
+ * Only workspaces listed in VOIP_ENABLED_WORKSPACES will have VoIP functionality.
38
+ */
39
+ /**
40
+ * List of workspaces that have VoIP/Exotel calling enabled.
41
+ * Add workspace names here to enable VoIP for that workspace.
42
+ */
43
+ declare const VOIP_ENABLED_WORKSPACES: string[];
44
+ /**
45
+ * Check if VoIP is enabled for a given workspace
46
+ *
47
+ * @param workspaceName - The name of the workspace to check
48
+ * @returns boolean indicating if VoIP is enabled for the workspace
49
+ */
50
+ declare function isVoIPEnabledForWorkspace(workspaceName: string): boolean;
51
+
33
52
  type Classroom = {
34
53
  id: number;
35
54
  batchName?: string;
@@ -198,5 +217,340 @@ declare const workspaceApiMapping: Record<string, string>;
198
217
 
199
218
  declare const openInNewTab: (pathAfterBase: string, excludeInstitution?: boolean, excludeWorkspace?: boolean) => void;
200
219
 
201
- export { ApplicationStore, BatchSelector, ConfirmDialogProvider, CourseSelector, DepartmentMongoMultiSelector, DepartmentSelector, DepartmentSqlMultiSelector, EmployeesSelector, ErrorBoundary, ExamTypeSelector, ExamsRegulationSelector, FeeTypeSelector, HostelBlockSelector, HostelFloorSelector, HostelRoomSelector, MonthYearSelector, PrintFormatSelector, ProgramSelector, Providers, RegulationSelector, ResearchExpertDesignationSelector, ResearchExpertSelector, ResearchStageSelector, SemesterSelector, SnackbarProvider, StudentSelector, StudentServicesSelector, YearRangeSelector, axios, createRsbuildSharedConfig, initialApplicationState, institutionCode, isDevelopment, nonWorkspaceAxios, openInNewTab, tenantCode, useConfirm, workspace, workspaceApiMapping };
202
- export type { ApplicationStoreType, ErrorBoundaryProps, InstitutionInfo };
220
+ type PermissionStatus = 'granted' | 'denied' | 'prompt' | 'unknown';
221
+
222
+ /**
223
+ * Voice config from notification-configs API
224
+ */
225
+ interface VoiceConfig {
226
+ id: string;
227
+ isEnabled: boolean;
228
+ name: string;
229
+ channelType: string;
230
+ EXOTEL?: {
231
+ appId: string;
232
+ appSecret: string;
233
+ token?: string;
234
+ tokenExpiresAt?: string;
235
+ };
236
+ }
237
+ /**
238
+ * Notification config response structure
239
+ */
240
+ interface NotificationConfigResponse {
241
+ config: {
242
+ id: string;
243
+ tenantId: string;
244
+ institutionUniqueId: number;
245
+ enableVoice?: boolean;
246
+ voiceConfigs?: VoiceConfig[];
247
+ };
248
+ options: {
249
+ voiceChannels?: string[];
250
+ };
251
+ }
252
+ /**
253
+ * Check if VoIP is enabled for the current tenant by fetching notification config.
254
+ * Returns true only if:
255
+ * - enableVoice is true
256
+ * - voiceConfigs has at least one enabled config
257
+ */
258
+ declare const checkVoIPEnabled: () => Promise<{
259
+ enabled: boolean;
260
+ hasValidToken: boolean;
261
+ }>;
262
+ /**
263
+ * Get the active Exotel voice token from the backend.
264
+ * The backend manages credentials securely and auto-refreshes tokens.
265
+ */
266
+ declare const getActiveVoiceToken: () => Promise<{
267
+ token: string;
268
+ expiresAt: string;
269
+ } | null>;
270
+ /**
271
+ * @deprecated Use getActiveVoiceToken instead.
272
+ * This function is kept for backwards compatibility but will be removed.
273
+ */
274
+ declare const createExotelAppToken: () => Promise<{
275
+ Data: string;
276
+ }>;
277
+ interface CallActivity {
278
+ id: string;
279
+ callSid: string;
280
+ prospectId: string;
281
+ direction: 'inbound' | 'outbound';
282
+ status: string;
283
+ durationSeconds?: number;
284
+ createdAt: string;
285
+ startTime?: string;
286
+ endTime?: string;
287
+ fromNumber?: string;
288
+ toNumber?: string;
289
+ userId?: number;
290
+ dispositionCategory?: string;
291
+ dispositionReason?: string;
292
+ dispositionNotes?: string;
293
+ callStatusDisposition?: 'connected' | 'not_connected';
294
+ recordingUrl?: string;
295
+ }
296
+ interface InitiateCallInput {
297
+ prospectId: string;
298
+ toNumber: string;
299
+ fromNumber?: string;
300
+ userId?: number;
301
+ callSid?: string;
302
+ }
303
+ interface SaveDispositionInput {
304
+ callId: string;
305
+ prospectId?: string;
306
+ callStatusDisposition?: 'connected' | 'not_connected';
307
+ dispositionCategory: string;
308
+ dispositionReason?: string;
309
+ dispositionNotes?: string;
310
+ callbackScheduledAt?: string;
311
+ }
312
+ interface CancelCallInput {
313
+ callSid: string;
314
+ reason?: string;
315
+ }
316
+ interface CallActivityResponse {
317
+ success: boolean;
318
+ message: string;
319
+ data: CallActivity;
320
+ }
321
+ interface RegisterIncomingCallInput {
322
+ callSid: string;
323
+ fromNumber: string;
324
+ toNumber?: string;
325
+ prospectId?: string;
326
+ userId?: number;
327
+ }
328
+ interface RegisterIncomingCallResponse {
329
+ success: boolean;
330
+ message: string;
331
+ data: CallActivity;
332
+ prospect?: {
333
+ id: string;
334
+ uniqueId?: number;
335
+ prospectId?: string;
336
+ name: string;
337
+ mobile: string;
338
+ };
339
+ }
340
+ /**
341
+ * Initiate an outbound call - creates call activity record
342
+ */
343
+ declare const initiateCallActivity: (input: InitiateCallInput) => Promise<{
344
+ success: boolean;
345
+ message: string;
346
+ data: CallActivity;
347
+ }>;
348
+ /**
349
+ * Register an incoming call - creates call activity record
350
+ */
351
+ declare const registerIncomingCall: (input: RegisterIncomingCallInput) => Promise<RegisterIncomingCallResponse>;
352
+ /**
353
+ * Fetch call history for a prospect
354
+ */
355
+ declare const fetchCallHistory: (prospectId: string) => Promise<CallActivity[]>;
356
+ /**
357
+ * Get call activity by ID
358
+ */
359
+ declare const getCallActivityById: (id: string) => Promise<CallActivity>;
360
+ /**
361
+ * Get call activity by CallSid
362
+ */
363
+ declare const getCallActivityByCallSid: (callSid: string) => Promise<CallActivity>;
364
+ /**
365
+ * Get call count for a prospect
366
+ */
367
+ declare const getCallCountByProspect: (prospectId: string) => Promise<number>;
368
+ /**
369
+ * Save call disposition
370
+ */
371
+ declare const saveCallDisposition: (input: SaveDispositionInput) => Promise<CallActivity>;
372
+ /**
373
+ * Cancel/decline a call before it was connected
374
+ * Updates the call activity status to CANCELED
375
+ */
376
+ declare const cancelCall: (input: CancelCallInput) => Promise<{
377
+ success: boolean;
378
+ message: string;
379
+ }>;
380
+
381
+ interface CallEventData {
382
+ callId: string;
383
+ remoteId: string;
384
+ remoteDisplayName: string;
385
+ callDirection: string;
386
+ callState: string;
387
+ callDuration: string;
388
+ callStartedTime: string;
389
+ callEstablishedTime: string;
390
+ callEndedTime: string;
391
+ callAnswerTime: string;
392
+ callEndReason: string;
393
+ sessionId: string;
394
+ callFromNumber?: string;
395
+ status?: string;
396
+ }
397
+ type CallPhase = 'idle' | 'ready_to_call' | 'calling' | 'incoming' | 'connected' | 'ended';
398
+ interface CallState {
399
+ phase: CallPhase;
400
+ callData: CallEventData | null;
401
+ isOnHold: boolean;
402
+ isMuted: boolean;
403
+ isSpeakerOff: boolean;
404
+ callDirection: 'outbound' | 'inbound' | null;
405
+ callStartTime: number | null;
406
+ callDuration: number;
407
+ callerName: string | null;
408
+ callerNumber: string | null;
409
+ callActivityId: string | null;
410
+ exotelCallSid: string | null;
411
+ prospectUniqueId: number | null;
412
+ wasAccepted: boolean;
413
+ }
414
+ interface CallDispositionData {
415
+ callId: string;
416
+ exotelCallId: string;
417
+ callDirection: 'outbound' | 'inbound';
418
+ callDuration: number;
419
+ callerName: string | null;
420
+ callerNumber: string | null;
421
+ }
422
+ interface ExotelContextType {
423
+ isInitialized: boolean;
424
+ isConnected: boolean;
425
+ callState: CallState;
426
+ permissionStatus: PermissionStatus;
427
+ dispositionData: CallDispositionData | null;
428
+ makeCall: (phoneNumber: string, callerName?: string, callActivityId?: string, maskedNumber?: string) => Promise<any>;
429
+ acceptCall: () => Promise<void>;
430
+ hangupCall: () => void;
431
+ rejectCall: () => void;
432
+ toggleHold: () => void;
433
+ toggleMute: () => void;
434
+ toggleSpeaker: () => void;
435
+ sendDTMF: (digit: string) => void;
436
+ registerDevice: () => Promise<void>;
437
+ unregisterDevice: () => void;
438
+ requestMicrophoneAccess: () => Promise<boolean>;
439
+ clearDisposition: () => void;
440
+ setCallActivityId: (callActivityId: string) => void;
441
+ setExotelCallSid: (callSid: string) => void;
442
+ }
443
+ interface ExotelProviderProps {
444
+ children: ReactNode;
445
+ accessToken: string;
446
+ agentUserId: string;
447
+ autoConnectVOIP?: boolean;
448
+ callerName?: string;
449
+ callerNumber?: string;
450
+ }
451
+ declare const ExotelProvider: React.FC<ExotelProviderProps>;
452
+ declare const useExotel: () => ExotelContextType;
453
+ /**
454
+ * Safe version of useExotel that returns null when outside the provider
455
+ * Use this in components that may render outside of ExotelProvider
456
+ */
457
+ declare const useExotelSafe: () => ExotelContextType | null;
458
+
459
+ type CallStatusType = 'connected' | 'not_connected';
460
+ interface DispositionFormData {
461
+ prospectId?: string;
462
+ callId: string;
463
+ channel: string;
464
+ direction: string;
465
+ duration: number;
466
+ callStatusDisposition: CallStatusType;
467
+ dispositionReason?: string;
468
+ dispositionCategory: string;
469
+ remarks: string;
470
+ callerName: string;
471
+ callerNumber: string;
472
+ }
473
+ interface ExistingDispositionData {
474
+ callStatusDisposition?: CallStatusType;
475
+ dispositionCategory?: string;
476
+ dispositionNotes?: string;
477
+ }
478
+ interface CallDispositionFormProps {
479
+ dispositionData: CallDispositionData;
480
+ prospectId?: string;
481
+ onClose: () => void;
482
+ onSave: (data: DispositionFormData) => Promise<any>;
483
+ existingData?: ExistingDispositionData;
484
+ }
485
+ declare const CallDispositionForm: ({ dispositionData, prospectId, onClose, onSave, existingData, }: CallDispositionFormProps) => react_jsx_runtime.JSX.Element;
486
+
487
+ interface ExotelPhoneProps {
488
+ className?: string;
489
+ prospectId?: string;
490
+ prospectName?: string;
491
+ prospectNumber?: string;
492
+ onSaveDisposition?: (data: DispositionFormData) => Promise<any>;
493
+ }
494
+ declare const ExotelPhone: ({ className, prospectId, prospectName, prospectNumber, onSaveDisposition }: ExotelPhoneProps) => react_jsx_runtime.JSX.Element | null;
495
+
496
+ interface CallButtonProps {
497
+ phoneNumber?: string;
498
+ encryptedPhoneNumber?: string;
499
+ callerName?: string;
500
+ prospectId?: string;
501
+ className?: string;
502
+ disabled?: boolean;
503
+ }
504
+ declare const CallButton: ({ phoneNumber, encryptedPhoneNumber, callerName, prospectId, className, disabled, }: CallButtonProps) => react_jsx_runtime.JSX.Element | null;
505
+
506
+ interface MicrophonePermissionProps {
507
+ onPermissionGranted?: () => void;
508
+ onPermissionDenied?: () => void;
509
+ }
510
+ declare const MicrophonePermission: ({ onPermissionGranted, onPermissionDenied, }: MicrophonePermissionProps) => react_jsx_runtime.JSX.Element;
511
+
512
+ interface ExotelWrapperProps {
513
+ children: ReactNode;
514
+ enabled?: boolean;
515
+ prospectId?: string;
516
+ prospectName?: string;
517
+ prospectNumber?: string;
518
+ }
519
+ /**
520
+ * Wrapper component that initializes Exotel VoIP functionality
521
+ * Fetches the access token from backend and provides the Exotel context to children
522
+ */
523
+ declare const ExotelWrapper: ({ children, enabled, prospectId, prospectName, prospectNumber, }: ExotelWrapperProps) => react_jsx_runtime.JSX.Element;
524
+
525
+ interface VoIPProviderProps {
526
+ children: ReactNode;
527
+ workspace: string;
528
+ agentUserId?: string;
529
+ prospectId?: string;
530
+ prospectName?: string;
531
+ prospectNumber?: string;
532
+ onSaveDisposition?: (data: DispositionFormData) => Promise<any>;
533
+ }
534
+ /**
535
+ * VoIPProvider - Workspace-level VoIP/Exotel integration
536
+ *
537
+ * This provider checks if VoIP is enabled for the current workspace AND tenant
538
+ * and initializes the Exotel SDK if enabled.
539
+ *
540
+ * VoIP is enabled only when ALL conditions are met:
541
+ * 1. Workspace is in VOIP_ENABLED_WORKSPACES (common-workspace, tele-caller-workspace)
542
+ * 2. Tenant has enableVoice: true in notification config
543
+ * 3. Tenant has at least one enabled voice config (voiceConfigs[].isEnabled: true)
544
+ * 4. Active token is available
545
+ *
546
+ * Features:
547
+ * - Workspace-level VoIP enablement
548
+ * - Tenant-level VoIP configuration check
549
+ * - Automatic token fetching from backend
550
+ * - Microphone permission handling
551
+ * - Floating phone UI for active calls
552
+ */
553
+ declare const VoIPProvider: React.FC<VoIPProviderProps>;
554
+
555
+ export { ApplicationStore, BatchSelector, CallButton, CallDispositionForm, ConfirmDialogProvider, CourseSelector, DepartmentMongoMultiSelector, DepartmentSelector, DepartmentSqlMultiSelector, EmployeesSelector, ErrorBoundary, ExamTypeSelector, ExamsRegulationSelector, ExotelPhone, ExotelProvider, ExotelWrapper, FeeTypeSelector, HostelBlockSelector, HostelFloorSelector, HostelRoomSelector, MicrophonePermission, MonthYearSelector, PrintFormatSelector, ProgramSelector, Providers, RegulationSelector, ResearchExpertDesignationSelector, ResearchExpertSelector, ResearchStageSelector, SemesterSelector, SnackbarProvider, StudentSelector, StudentServicesSelector, VOIP_ENABLED_WORKSPACES, VoIPProvider, YearRangeSelector, axios, cancelCall, checkVoIPEnabled, createExotelAppToken, createRsbuildSharedConfig, fetchCallHistory, getActiveVoiceToken, getCallActivityByCallSid, getCallActivityById, getCallCountByProspect, initialApplicationState, initiateCallActivity, institutionCode, isDevelopment, isVoIPEnabledForWorkspace, nonWorkspaceAxios, openInNewTab, registerIncomingCall, saveCallDisposition, tenantCode, useConfirm, useExotel, useExotelSafe, workspace, workspaceApiMapping };
556
+ export type { ApplicationStoreType, CallActivity, CallActivityResponse, CallDispositionData, CallEventData, CallPhase, CallState, CancelCallInput, DispositionFormData, ErrorBoundaryProps, ExistingDispositionData, ExotelContextType, ExotelProviderProps, InitiateCallInput, InstitutionInfo, NotificationConfigResponse, PermissionStatus, RegisterIncomingCallInput, RegisterIncomingCallResponse, SaveDispositionInput, VoiceConfig };