call-control-sdk 5.2.6 → 5.3.3

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 CHANGED
@@ -1,218 +1,1179 @@
1
- ### Call Control SDK [![npm version](https://img.shields.io/npm/v/call-control-sdk.svg?color=blue)](https://www.npmjs.com/package/call-control-sdk) [![npm downloads](https://img.shields.io/npm/dm/call-control-sdk.svg?color=green)](https://www.npmjs.com/package/call-control-sdk)
1
+ # Call Control SDK - Comprehensive Documentation
2
2
 
3
- A lightweight SDK that provides a **draggable call control panel** and utility hooks for managing calls in real-time. Built with **TypeScript**, **Material-UI**, and designed for **agent productivity**.
3
+ ## Table of Contents
4
+ 1. [Overview](#overview)
5
+ 2. [Architecture](#architecture)
6
+ 3. [Installation & Setup](#installation--setup)
7
+ 4. [Core Components](#core-components)
8
+ 5. [Hooks & Utilities](#hooks--utilities)
9
+ 6. [Services & APIs](#services--apis)
10
+ 7. [TypeScript Types](#typescript-types)
11
+ 8. [Usage Examples](#usage-examples)
12
+ 9. [Best Practices](#best-practices)
13
+ 10. [API Reference](#api-reference)
14
+ 11. [Troubleshooting](#troubleshooting)
15
+ 12. [Productivity Features](#productivity-features)
4
16
 
5
- #### ✨ Features
17
+ ---
18
+
19
+ ## Overview
20
+
21
+ The **Call Control SDK** is a comprehensive TypeScript-based library designed for WebRTC call management in contact center environments. It provides a draggable call control panel with real-time call management capabilities, agent productivity tools, and seamless integration with existing applications.
6
22
 
23
+ ### Key Features
7
24
  - 🎯 **Complete Call Control** – Hold, Mute, Status management, and End Call
8
25
  - 🖱️ **Draggable Interface** – Movable panel with persisted position
9
- - 💾 **State Persistence** – Saves control states in `localStorage`
26
+ - 💾 **State Persistence** – Saves control states in localStorage
10
27
  - ⏱️ **Live Call Timer** – Real-time call duration tracking
11
28
  - 🎨 **Material-UI Design** – Responsive and accessible UI
12
29
  - 📱 **Touch Support** – Works seamlessly on desktop and mobile
13
30
  - 🔧 **TypeScript Support** – Full type safety and IntelliSense
14
31
  - 🎪 **Singleton State** – Consistent shared state across components
32
+ - 📊 **Event Tracking** – Comprehensive analytics and monitoring
33
+ - 🔄 **WebSocket Integration** – Real-time communication
34
+ - 📞 **Conference Calling** – Multi-line conference management
35
+ - 🔀 **Call Transfer** – Transfer to agents, processes, or queues
36
+
37
+ ---
38
+
39
+ ## Architecture
40
+
41
+ ### Core Architecture Components
42
+
43
+ ```
44
+ ┌─────────────────────────────────────────────────────────────┐
45
+ │ Call Control SDK │
46
+ ├─────────────────────────────────────────────────────────────┤
47
+ │ Components Layer │
48
+ │ ├── CallControlPanel (Main UI Component) │
49
+ │ ├── CallControls (Control Buttons & Logic) │
50
+ │ ├── Dialog Components (Transfer, Conference, etc.) │
51
+ │ └── SDKProvider (Context Provider) │
52
+ ├─────────────────────────────────────────────────────────────┤
53
+ │ Hooks Layer │
54
+ │ ├── useSDKState (State Management) │
55
+ │ ├── useClickToCall (Call Initiation) │
56
+ │ ├── useEndCall (Call Termination) │
57
+ │ ├── useLogout (Agent Logout) │
58
+ │ ├── useDraggable (Drag & Drop) │
59
+ │ └── eventsTracker (Analytics) │
60
+ ├─────────────────────────────────────────────────────────────┤
61
+ │ Services Layer │
62
+ │ ├── axios.ts (HTTP Client) │
63
+ │ ├── request.ts (API Hooks) │
64
+ │ ├── endPoint.ts (API Endpoints) │
65
+ │ └── websocketClient.ts (Real-time Communication) │
66
+ ├─────────────────────────────────────────────────────────────┤
67
+ │ State Management │
68
+ │ ├── sdk-state.ts (Singleton State Manager) │
69
+ │ └── types.ts (TypeScript Definitions) │
70
+ └─────────────────────────────────────────────────────────────┘
71
+ ```
15
72
 
16
- [![bundle size](https://img.shields.io/bundlephobia/minzip/call-control-sdk?color=orange&fontSize=12px)](https://bundlephobia.com/package/call-control-sdk)
73
+ ### State Management Flow
17
74
 
18
- ##### 📦 Installation
75
+ ```mermaid
76
+ graph TD
77
+ A[SDK Initialization] --> B[State Manager]
78
+ B --> C[localStorage Persistence]
79
+ B --> D[Component Updates]
80
+ D --> E[UI Rendering]
81
+ E --> F[User Interactions]
82
+ F --> G[API Calls]
83
+ G --> H[State Updates]
84
+ H --> B
85
+
86
+ I[WebSocket Events] --> J[Real-time Updates]
87
+ J --> B
88
+
89
+ K[Event Tracking] --> L[Analytics]
90
+ L --> M[Performance Monitoring]
91
+ ```
92
+
93
+ ---
94
+
95
+ ## Installation & Setup
96
+
97
+ ### Prerequisites
98
+ - Node.js 16+
99
+ - React 16+
100
+ - TypeScript 5+
101
+
102
+ ### Installation
19
103
 
20
104
  ```bash
21
105
  npm install call-control-sdk
22
106
  ```
23
107
 
24
- ###### 🔑 Peer Dependencies
108
+ ### Peer Dependencies
25
109
 
26
110
  ```bash
27
111
  npm install react react-dom axios @mui/material @mui/icons-material @emotion/react @emotion/styled
28
112
  ```
29
113
 
30
- ##### 📚 Table of Contents
114
+ ### Basic Setup
115
+
116
+ ```tsx
117
+ import React, { useEffect } from 'react';
118
+ import { initSDK, CallControlPanel } from 'call-control-sdk';
119
+
120
+ function App() {
121
+ useEffect(() => {
122
+ // Initialize the SDK
123
+ initSDK({
124
+ apiKey: "your-api-key",
125
+ tenantId: "your-tenant-id",
126
+ agentId: "your-agent-id"
127
+ });
128
+ }, []);
129
+
130
+ return (
131
+ <div className="app">
132
+ <h1>Agent Dashboard</h1>
133
+ <CallControlPanel
134
+ onDataChange={(data) => {
135
+ console.log('Call data updated:', data);
136
+ }}
137
+ />
138
+ </div>
139
+ );
140
+ }
141
+
142
+ export default App;
143
+ ```
144
+
145
+ ---
146
+
147
+ ## Core Components
148
+
149
+ ### 1. CallControlPanel
150
+
151
+ The main UI component that renders the draggable call control interface.
152
+
153
+ ```tsx
154
+ interface CallControlPanelProps {
155
+ onDataChange?: (data: CallData) => void;
156
+ }
157
+
158
+ // Usage
159
+ <CallControlPanel
160
+ onDataChange={(callData) => {
161
+ // Handle call data changes
162
+ updateDashboard(callData);
163
+ }}
164
+ />
165
+ ```
166
+
167
+ **Features:**
168
+ - Draggable positioning with persistence
169
+ - Real-time call status display
170
+ - Agent status management
171
+ - Call duration timer
172
+ - Control buttons (Hold, Mute, Transfer, Conference, End Call)
173
+
174
+ ### 2. CallControls
175
+
176
+ The core control component containing all call management buttons and logic.
177
+
178
+ **Key Controls:**
179
+ - **Agent Ready**: Set agent status to ready
180
+ - **Hold/Resume**: Toggle call hold state
181
+ - **Mute/Unmute**: Toggle microphone state
182
+ - **Transfer**: Transfer call to another agent/queue/process
183
+ - **Conference**: Add participants to conference call
184
+ - **End Call**: Terminate call with disposition
185
+
186
+ ### 3. Dialog Components
187
+
188
+ #### ConferenceDialog
189
+ Manages multi-line conference calls with up to 5 lines.
190
+
191
+ ```tsx
192
+ // Conference line management
193
+ interface ConferenceLineTypes {
194
+ line: number;
195
+ status: string;
196
+ type: "external" | "internal" | "";
197
+ phone: string;
198
+ isMute: boolean;
199
+ isHold: boolean;
200
+ isCallStart: boolean;
201
+ isMergeCall: boolean;
202
+ }
203
+ ```
204
+
205
+ #### CallTransferDialog
206
+ Handles call transfers to:
207
+ - **Agents**: Transfer to specific agents
208
+ - **Processes**: Transfer to business processes
209
+ - **Queues**: Transfer to call queues
210
+
211
+ #### EndCallDispositionDialog
212
+ Captures call disposition and follow-up information:
213
+ - Disposition codes (Resolved, Not Interested)
214
+ - Follow-up requirements
215
+ - Callback scheduling
216
+
217
+ ---
218
+
219
+ ## Hooks & Utilities
220
+
221
+ ### 1. useSDKState
222
+
223
+ Provides reactive access to the SDK's global state.
224
+
225
+ ```tsx
226
+ import { useSDKState } from 'call-control-sdk';
227
+
228
+ function MyComponent() {
229
+ const state = useSDKState();
230
+
231
+ return (
232
+ <div>
233
+ <p>Agent Status: {state.status}</p>
234
+ <p>Call Duration: {state.callStartTime}</p>
235
+ <p>Is Muted: {state.isMuted ? 'Yes' : 'No'}</p>
236
+ </div>
237
+ );
238
+ }
239
+ ```
240
+
241
+ ### 2. useClickToCall
242
+
243
+ Initiates outbound calls to phone numbers.
244
+
245
+ ```tsx
246
+ import { useClickToCall } from 'call-control-sdk';
247
+
248
+ function DialerComponent() {
249
+ const { handleStartCall, isLoading, isSuccess, error } = useClickToCall();
250
+
251
+ const makeCall = () => {
252
+ handleStartCall({ mobileNumber: "1234567890" });
253
+ };
254
+
255
+ return (
256
+ <button onClick={makeCall} disabled={isLoading}>
257
+ {isLoading ? 'Calling...' : 'Call'}
258
+ </button>
259
+ );
260
+ }
261
+ ```
262
+
263
+ ### 3. useEndCall
264
+
265
+ Terminates active calls with disposition tracking.
266
+
267
+ ```tsx
268
+ import { useEndCall } from 'call-control-sdk';
269
+
270
+ function EndCallComponent() {
271
+ const { handleEndCall, isLoading } = useEndCall();
272
+
273
+ const endCall = () => {
274
+ handleEndCall({
275
+ disposition: "RES",
276
+ followUp: "N",
277
+ callbackDate: "",
278
+ callbackHrs: "",
279
+ callbackMins: ""
280
+ });
281
+ };
282
+
283
+ return (
284
+ <button onClick={endCall} disabled={isLoading}>
285
+ End Call
286
+ </button>
287
+ );
288
+ }
289
+ ```
290
+
291
+ ### 4. useLogout
292
+
293
+ Handles agent logout functionality.
294
+
295
+ ```tsx
296
+ import { useLogout } from 'call-control-sdk';
297
+
298
+ function LogoutComponent() {
299
+ const { logout, isLoading } = useLogout();
300
+
301
+ return (
302
+ <button onClick={logout} disabled={isLoading}>
303
+ {isLoading ? 'Logging out...' : 'Logout'}
304
+ </button>
305
+ );
306
+ }
307
+ ```
308
+
309
+ ### 5. useDraggable
310
+
311
+ Provides drag-and-drop functionality for UI elements.
312
+
313
+ ```tsx
314
+ import { useDraggable } from 'call-control-sdk';
315
+
316
+ function DraggablePanel() {
317
+ const { position, isDragging, dragRef, handleMouseDown, handleTouchStart } =
318
+ useDraggable({ x: 100, y: 100 }, (newPosition) => {
319
+ console.log('Moved to:', newPosition);
320
+ });
321
+
322
+ return (
323
+ <div
324
+ ref={dragRef}
325
+ onMouseDown={handleMouseDown}
326
+ onTouchStart={handleTouchStart}
327
+ style={{
328
+ position: 'fixed',
329
+ left: position.x,
330
+ top: position.y,
331
+ cursor: isDragging ? 'grabbing' : 'grab'
332
+ }}
333
+ >
334
+ Drag me
335
+ </div>
336
+ );
337
+ }
338
+ ```
339
+
340
+ ---
341
+
342
+ ## Services & APIs
343
+
344
+ ### 1. HTTP Client (axios.ts)
345
+
346
+ Configured Axios instance with:
347
+ - Base URL configuration
348
+ - Authorization headers
349
+ - Request/response interceptors
350
+ - Error handling
351
+ - Retry logic for 401 errors
352
+
353
+ ```tsx
354
+ // Automatic token injection
355
+ axiosInstance.interceptors.request.use((config) => {
356
+ const token = getAuthToken();
357
+ if (token && config.headers) {
358
+ config.headers.Authorization = `Bearer ${token}`;
359
+ }
360
+ return config;
361
+ });
362
+ ```
363
+
364
+ ### 2. API Request Hooks (request.ts)
365
+
366
+ Custom hooks for different HTTP methods:
367
+
368
+ #### useGetRequest
369
+ ```tsx
370
+ const [getData, { isLoading, isSuccess, error, data }] = useGetRequest<User>({
371
+ onSuccess: (response) => console.log('Success:', response),
372
+ onError: (error) => console.error('Error:', error)
373
+ });
374
+
375
+ // Usage
376
+ getData('/api/users');
377
+ ```
378
+
379
+ #### usePostRequest
380
+ ```tsx
381
+ const [createUser, { isLoading, isSuccess, error }] = usePostRequest<User>({
382
+ onSuccess: (response) => console.log('User created:', response)
383
+ });
384
+
385
+ // Usage
386
+ createUser('/api/users', userData);
387
+ ```
388
+
389
+ ### 3. API Endpoints (endPoint.ts)
390
+
391
+ Centralized endpoint configuration:
392
+
393
+ ```tsx
394
+ export const END_POINT = {
395
+ LOGIN: `${BASE_URL}/api/v1/cti/login?provider=convox`,
396
+ READY_AGENT: `${BASE_URL}/api/v1/cti/ready-agent?provider=convox`,
397
+ CLICK_TO_CALL: `${BASE_URL}/api/v1/cti/calls?provider=convox`,
398
+ HOLD_CALL: `${BASE_URL}/api/v1/cti/calls/hold?provider=convox`,
399
+ MUTE_CALL: `${BASE_URL}/api/v1/cti/calls/mute?provider=convox`,
400
+ END_CALL: `${BASE_URL}/api/v1/cti/calls/end?provider=convox`,
401
+ CONFERENCE_CALL: `${BASE_URL}/api/v1/cti/calls/conference?provider=convox`,
402
+ TRANSFER_CALL: `${BASE_URL}/api/v1/cti/calls/transfer?provider=convox`,
403
+ // ... more endpoints
404
+ };
405
+ ```
406
+
407
+ ### 4. WebSocket Integration
408
+
409
+ Real-time communication for call events:
410
+
411
+ ```tsx
412
+ // WebSocket connection setup
413
+ useEffect(() => {
414
+ if (state.agentId) {
415
+ const ws = new WebSocket(`${WS_END_POINT.WS}?agent_id=${state.agentId}`);
416
+
417
+ ws.onmessage = (event) => {
418
+ const data = JSON.parse(event.data);
419
+ sdkStateManager.updateCallData(data);
420
+
421
+ if (data.status === "ONCALL") {
422
+ sdkStateManager.startCall();
423
+ }
424
+ if (data.status === "WRAPUP") {
425
+ sdkStateManager.endCall();
426
+ }
427
+ };
428
+
429
+ return () => ws.close();
430
+ }
431
+ }, [state.agentId]);
432
+ ```
433
+
434
+ ---
435
+
436
+ ## TypeScript Types
437
+
438
+ ### Core Types
439
+
440
+ ```tsx
441
+ // Call data structure
442
+ interface CallData {
443
+ mobileNumber?: string;
444
+ callReferenceId?: string;
445
+ convoxId?: string;
446
+ type?: string;
447
+ status?: string;
448
+ agent_id?: string;
449
+ phone_number?: string;
450
+ event_time?: string;
451
+ convox_id?: string;
452
+ process_id?: string;
453
+ process_name?: string;
454
+ }
455
+
456
+ // Agent status types
457
+ type CallStatus =
458
+ | "idle"
459
+ | "ready"
460
+ | "break"
461
+ | "on call"
462
+ | "wrap up"
463
+ | "dial"
464
+ | "hold"
465
+ | "mute";
466
+
467
+ // Conference line configuration
468
+ type ConferenceLineTypes = {
469
+ line: number;
470
+ status: string;
471
+ type: "external" | "internal" | "";
472
+ phone: string;
473
+ isMute: boolean;
474
+ isHold: boolean;
475
+ isCallStart: boolean;
476
+ isMergeCall: boolean;
477
+ };
478
+
479
+ // SDK state interface
480
+ interface SDKState {
481
+ apiKey: string | null;
482
+ process?: { process_id: number; process_name: string } | null;
483
+ agentId: string;
484
+ isInitialized: boolean;
485
+ isHolding: boolean;
486
+ isMuted: boolean;
487
+ status: CallStatus;
488
+ convox_id?: string;
489
+ process_id?: number;
490
+ callStartTime: number | null;
491
+ position?: { x: number; y: number };
492
+ controlPanelPosition: { x: number; y: number };
493
+ iframePosition: { x: number; y: number };
494
+ callData: CallData;
495
+ conferenceLine: ConferenceLineTypes[];
496
+ }
497
+ ```
498
+
499
+ ### API Request Types
500
+
501
+ ```tsx
502
+ // Request result interface
503
+ interface RequestResult<T> {
504
+ isLoading: boolean;
505
+ isSuccess: boolean;
506
+ isError: boolean;
507
+ error: AxiosError | null;
508
+ data: AxiosResponse<T> | null;
509
+ }
510
+
511
+ // Request options
512
+ interface RequestOptions {
513
+ onSuccess?: (response: AxiosResponse, request: any) => void;
514
+ onError?: (error: any, request: any) => void;
515
+ }
516
+
517
+ // Hook signatures
518
+ type UseGetRequest<T = UseApiRequest> = [
519
+ (url: string, config?: AxiosRequestConfig) => void,
520
+ RequestResult<T>
521
+ ];
522
+
523
+ type UsePostRequest<T = UseApiRequest> = [
524
+ (url: string, payload: T, config?: AxiosRequestConfig) => void,
525
+ RequestResult<T>
526
+ ];
527
+ ```
528
+
529
+ ---
530
+
531
+ ## Usage Examples
532
+
533
+ ### 1. Complete Agent Dashboard
534
+
535
+ ```tsx
536
+ import React, { useEffect, useState } from 'react';
537
+ import {
538
+ initSDK,
539
+ CallControlPanel,
540
+ useClickToCall,
541
+ useEndCall,
542
+ useLogout
543
+ } from 'call-control-sdk';
544
+
545
+ function AgentDashboard() {
546
+ const [callData, setCallData] = useState(null);
547
+
548
+ // Initialize SDK
549
+ useEffect(() => {
550
+ initSDK({
551
+ apiKey: process.env.REACT_APP_API_KEY,
552
+ tenantId: process.env.REACT_APP_TENANT_ID,
553
+ agentId: process.env.REACT_APP_AGENT_ID
554
+ });
555
+ }, []);
31
556
 
32
- 1. [Getting Started](#-getting-started)
33
- 2. [Core API](#-core-api)
34
- - [initSDK](#initsdk)
35
- - [CallControlPanel](#callcontrolpanel)
36
- - [updateCallData](#updatecalldata)
37
- 3. [Hooks](#-hooks)
38
- - [useLogout](#uselogout)
39
- - [useEndCall](#useendcall)
40
- 4. [Payloads](#-payloads)
41
- 5. [Control Features](#-control-features)
42
- 6. [Browser Support](#-browser-support)
43
- 7. [License](#-license)
557
+ // Call management hooks
558
+ const { handleStartCall, isLoading: calling } = useClickToCall();
559
+ const { handleEndCall, isLoading: ending } = useEndCall();
560
+ const { logout, isLoading: loggingOut } = useLogout();
561
+
562
+ const handleCallDataChange = (data) => {
563
+ setCallData(data);
564
+ // Update dashboard metrics
565
+ updateDashboardMetrics(data);
566
+ };
44
567
 
45
- ##### 🚀 Getting Started
568
+ return (
569
+ <div className="agent-dashboard">
570
+ <header className="dashboard-header">
571
+ <h1>Agent Dashboard</h1>
572
+ <button onClick={logout} disabled={loggingOut}>
573
+ {loggingOut ? 'Logging out...' : 'Logout'}
574
+ </button>
575
+ </header>
576
+
577
+ <main className="dashboard-content">
578
+ <div className="call-controls">
579
+ <CallControlPanel onDataChange={handleCallDataChange} />
580
+ </div>
581
+
582
+ <div className="dashboard-widgets">
583
+ <CallMetricsWidget data={callData} />
584
+ <CustomerInfoWidget data={callData} />
585
+ <CallHistoryWidget />
586
+ </div>
587
+ </main>
588
+ </div>
589
+ );
590
+ }
591
+ ```
46
592
 
47
- ### 1. Initialize the SDK
593
+ ### 2. Custom Call Controls
48
594
 
49
595
  ```tsx
50
- import { useEffect } from "react";
51
- import { initSDK } from "call-control-sdk";
596
+ import React from 'react';
597
+ import { useSDKState, useClickToCall, useEndCall } from 'call-control-sdk';
598
+
599
+ function CustomCallControls() {
600
+ const state = useSDKState();
601
+ const { handleStartCall } = useClickToCall();
602
+ const { handleEndCall } = useEndCall();
603
+
604
+ const isOnCall = state.callData?.status === "ONCALL";
605
+ const callDuration = state.callStartTime
606
+ ? Math.floor((Date.now() - state.callStartTime) / 1000)
607
+ : 0;
608
+
609
+ const formatDuration = (seconds) => {
610
+ const mins = Math.floor(seconds / 60);
611
+ const secs = seconds % 60;
612
+ return `${mins.toString().padStart(2, "0")}:${secs.toString().padStart(2, "0")}`;
613
+ };
614
+
615
+ return (
616
+ <div className="custom-controls">
617
+ <div className="call-status">
618
+ <span className="status">{state.status}</span>
619
+ {isOnCall && (
620
+ <span className="duration">{formatDuration(callDuration)}</span>
621
+ )}
622
+ </div>
623
+
624
+ <div className="control-buttons">
625
+ {!isOnCall && (
626
+ <button onClick={() => handleStartCall({ mobileNumber: "1234567890" })}>
627
+ Start Call
628
+ </button>
629
+ )}
630
+
631
+ {isOnCall && (
632
+ <>
633
+ <button
634
+ onClick={() => handleEndCall({ disposition: "RES" })}
635
+ className="end-call"
636
+ >
637
+ End Call
638
+ </button>
639
+ </>
640
+ )}
641
+ </div>
642
+ </div>
643
+ );
644
+ }
645
+ ```
646
+
647
+ ### 3. Conference Call Management
648
+
649
+ ```tsx
650
+ import React, { useState } from 'react';
651
+ import { useSDKState } from 'call-control-sdk';
652
+
653
+ function ConferenceManager() {
654
+ const state = useSDKState();
655
+ const [showConference, setShowConference] = useState(false);
656
+
657
+ const addParticipant = (phoneNumber) => {
658
+ // Find available conference line
659
+ const availableLine = state.conferenceLine.find(
660
+ line => line.line !== 1 && line.status === "IDLE"
661
+ );
662
+
663
+ if (availableLine) {
664
+ // Initiate conference call
665
+ handleConferenceCall(availableLine.line, phoneNumber);
666
+ }
667
+ };
668
+
669
+ return (
670
+ <div className="conference-manager">
671
+ <button onClick={() => setShowConference(true)}>
672
+ Manage Conference
673
+ </button>
674
+
675
+ {showConference && (
676
+ <div className="conference-dialog">
677
+ <h3>Conference Lines</h3>
678
+ {state.conferenceLine.map(line => (
679
+ <div key={line.line} className="conference-line">
680
+ <span>Line {line.line}: {line.status}</span>
681
+ {line.line !== 1 && (
682
+ <input
683
+ placeholder="Phone number"
684
+ onBlur={(e) => addParticipant(e.target.value)}
685
+ />
686
+ )}
687
+ </div>
688
+ ))}
689
+ </div>
690
+ )}
691
+ </div>
692
+ );
693
+ }
694
+ ```
52
695
 
53
- // Initialize at the top level of your app
696
+ ---
697
+
698
+ ## Best Practices
699
+
700
+ ### 1. Initialization
701
+
702
+ ```tsx
703
+ // ✅ Good: Initialize SDK early in app lifecycle
54
704
  function App() {
55
705
  useEffect(() => {
56
- // Initialize the SDK.
57
706
  try {
58
707
  initSDK({
59
- apiKey: "your-api-key",
60
- tenantId: "your-tenant-id",
61
- agentId: "your-agent-id",
708
+ apiKey: process.env.REACT_APP_API_KEY,
709
+ tenantId: process.env.REACT_APP_TENANT_ID,
710
+ agentId: process.env.REACT_APP_AGENT_ID
62
711
  });
63
- console.log("SDK initialized successfully");
64
712
  } catch (error) {
65
- console.error("SDK initialization failed:", error);
713
+ console.error('SDK initialization failed:', error);
714
+ // Handle initialization error
66
715
  }
67
716
  }, []);
68
717
 
69
- return <h1>My App</h1>;
718
+ return <YourApp />;
719
+ }
720
+
721
+ // ❌ Bad: Initializing in component that might unmount
722
+ function SomeComponent() {
723
+ useEffect(() => {
724
+ initSDK(config); // This might be called multiple times
725
+ }, []);
70
726
  }
71
727
  ```
72
728
 
73
- ### 2. Add the Call Control Panel
729
+ ### 2. State Management
74
730
 
75
731
  ```tsx
76
- import { CallControlPanel } from "call-control-sdk";
77
-
78
- export default function App() {
79
- const handleDataChange = (data) => {
80
- console.log("Call data updated:", data);
81
- };
82
-
732
+ // Good: Use the provided state hook
733
+ function MyComponent() {
734
+ const state = useSDKState();
735
+
83
736
  return (
84
737
  <div>
85
- <h1>Agent Dashboard</h1>
86
- <CallControlPanel onDataChange={handleDataChange} />
738
+ <p>Status: {state.status}</p>
739
+ <p>Call Duration: {state.callStartTime}</p>
87
740
  </div>
88
741
  );
89
742
  }
743
+
744
+ // ❌ Bad: Direct state access
745
+ function MyComponent() {
746
+ const state = sdkStateManager.getState(); // Won't trigger re-renders
747
+ return <div>{state.status}</div>;
748
+ }
90
749
  ```
91
750
 
92
- ### 3. Logout Agent
751
+ ### 3. Error Handling
93
752
 
94
753
  ```tsx
95
- import { useLogout } from "call-control-sdk";
754
+ // Good: Comprehensive error handling
755
+ function CallComponent() {
756
+ const { handleStartCall, isLoading, isError, error } = useClickToCall();
757
+
758
+ const makeCall = async () => {
759
+ try {
760
+ await handleStartCall({ mobileNumber: "1234567890" });
761
+ } catch (error) {
762
+ console.error('Call failed:', error);
763
+ // Show user-friendly error message
764
+ showNotification('Call failed. Please try again.');
765
+ }
766
+ };
96
767
 
97
- export default function LogoutButton() {
98
- const { logout, isLoading, isSuccess, isError, error } = useLogout();
99
- return <button onClick={logout}>Logout</button>;
768
+ return (
769
+ <div>
770
+ <button onClick={makeCall} disabled={isLoading}>
771
+ {isLoading ? 'Calling...' : 'Call'}
772
+ </button>
773
+ {isError && <p className="error">Error: {error?.message}</p>}
774
+ </div>
775
+ );
100
776
  }
101
777
  ```
102
778
 
103
- ### 4. End Call
779
+ ### 4. Performance Optimization
104
780
 
105
781
  ```tsx
106
- import { useEndCall } from "call-control-sdk";
782
+ // Good: Memoize expensive operations
783
+ function CallMetrics({ callData }) {
784
+ const formattedDuration = useMemo(() => {
785
+ if (!callData?.startTime) return '00:00';
786
+ const duration = Date.now() - callData.startTime;
787
+ return formatDuration(duration);
788
+ }, [callData?.startTime]);
107
789
 
108
- export default function EndCallButton() {
109
- const { handleEndCall, isLoading, isSuccess, isError, error } = useEndCall();
790
+ return <div>Duration: {formattedDuration}</div>;
791
+ }
110
792
 
111
- const onEndCall = () => {
112
- handleEndCall({
113
- disposition: "RES", // Call disposition
114
- });
115
- };
793
+ // Good: Debounce user input
794
+ function PhoneInput() {
795
+ const [phoneNumber, setPhoneNumber] = useState('');
796
+ const debouncedPhone = useDebounce(phoneNumber, 500);
797
+
798
+ useEffect(() => {
799
+ if (debouncedPhone.length === 10) {
800
+ validatePhoneNumber(debouncedPhone);
801
+ }
802
+ }, [debouncedPhone]);
803
+ }
804
+ ```
116
805
 
806
+ ### 5. Accessibility
807
+
808
+ ```tsx
809
+ // ✅ Good: Accessible controls
810
+ function AccessibleCallControls() {
811
+ const state = useSDKState();
812
+
117
813
  return (
118
- <div>
119
- <button onClick={onEndCall} disabled={isLoading}>
120
- {isLoading ? "Ending Call..." : "End Call"}
814
+ <div role="toolbar" aria-label="Call controls">
815
+ <button
816
+ onClick={handleMute}
817
+ aria-pressed={state.isMuted}
818
+ aria-label={state.isMuted ? 'Unmute microphone' : 'Mute microphone'}
819
+ >
820
+ {state.isMuted ? <MicOffIcon /> : <MicIcon />}
821
+ </button>
822
+
823
+ <button
824
+ onClick={handleHold}
825
+ aria-pressed={state.isHolding}
826
+ aria-label={state.isHolding ? 'Resume call' : 'Hold call'}
827
+ >
828
+ {state.isHolding ? <PlayIcon /> : <PauseIcon />}
121
829
  </button>
122
- {isSuccess && <p>✅ Call ended successfully</p>}
123
- {isError && <p>❌ Error: {error?.message}</p>}
124
830
  </div>
125
831
  );
126
832
  }
127
833
  ```
128
834
 
129
- ##### 🛠 Core API
835
+ ---
836
+
837
+ ## API Reference
838
+
839
+ ### Core Functions
840
+
841
+ #### `initSDK(config: InitSDKParams): void`
842
+
843
+ Initializes the Call Control SDK.
844
+
845
+ **Parameters:**
846
+ - `config.apiKey` (string, required): API key for authentication
847
+ - `config.tenantId` (string, required): Tenant ID for events/authentication
848
+ - `config.agentId` (string, required): Agent ID for call controls
849
+
850
+ **Example:**
851
+ ```tsx
852
+ initSDK({
853
+ apiKey: "your-api-key",
854
+ tenantId: "tenant-123",
855
+ agentId: "agent-456"
856
+ });
857
+ ```
858
+
859
+ #### `CallControlPanel`
860
+
861
+ React component that renders the draggable call control interface.
862
+
863
+ **Props:**
864
+ - `onDataChange?: (data: CallData) => void`: Callback fired when call data changes
865
+
866
+ **Example:**
867
+ ```tsx
868
+ <CallControlPanel
869
+ onDataChange={(data) => {
870
+ console.log('Call updated:', data);
871
+ }}
872
+ />
873
+ ```
874
+
875
+ ### Hooks
130
876
 
131
- ### `initSDK(config)`
877
+ #### `useSDKState(): SDKState`
132
878
 
133
- Initializes the SDK. Must be called **before using any components or hooks**.
879
+ Returns the current SDK state with reactive updates.
134
880
 
135
- **Parameters**:
881
+ **Returns:** `SDKState` object containing:
882
+ - `isInitialized`: boolean
883
+ - `status`: CallStatus
884
+ - `isHolding`: boolean
885
+ - `isMuted`: boolean
886
+ - `callData`: CallData
887
+ - `conferenceLine`: ConferenceLineTypes[]
888
+ - And more...
136
889
 
137
- | Name | Type | Required | Description |
138
- | ---------- | ------ | -------- | ----------------------------------- |
139
- | `apiKey` | string | ✅ | API key for authentication |
140
- | `tenantId` | string | ✅ | Tenant ID for events/authentication |
141
- | `agentId` | string | ✅ | Agent ID for call controls |
890
+ #### `useClickToCall()`
142
891
 
143
- ### `CallControlPanel`
892
+ Hook for initiating outbound calls.
144
893
 
145
- Draggable control panel for call management.
894
+ **Returns:**
895
+ - `handleStartCall`: (payload: StartCallPayload) => Promise<void>
896
+ - `isLoading`: boolean
897
+ - `isSuccess`: boolean
898
+ - `isError`: boolean
899
+ - `error`: any
900
+ - `data`: any
146
901
 
147
- **Props**:
902
+ #### `useEndCall()`
148
903
 
149
- | Prop | Type | Required | Description |
150
- | --------------- | -------- | -------- | -------------------------------------------------------------------------------------------------- |
151
- | `onDataChange?` | function | ❌ | Callback fired when call data changes. Receives `{ mobileNumber, callReferenceId, agentLoginId }`. |
904
+ Hook for ending active calls.
152
905
 
153
- ### `updateCallData(data: Partial<CallData>)`
906
+ **Returns:**
907
+ - `handleEndCall`: (data: EndCallData) => Promise<void>
908
+ - `isLoading`: boolean
909
+ - `isSuccess`: boolean
910
+ - `isError`: boolean
911
+ - `error`: any
912
+ - `data`: any
154
913
 
155
- Update call data programmatically.
914
+ #### `useLogout()`
156
915
 
157
- **Parameters**:
916
+ Hook for agent logout functionality.
158
917
 
159
- | Field | Type | Description |
160
- | ------------------ | ------ | ---------------------- |
161
- | `mobileNumber?` | string | Mobile phone number |
162
- | `callReferenceId?` | string | Unique call reference |
163
- | `agentLoginId?` | string | Agent login identifier |
918
+ **Returns:**
919
+ - `logout`: () => Promise<void>
920
+ - `isLoading`: boolean
921
+ - `isSuccess`: boolean
922
+ - `isError`: boolean
923
+ - `error`: any
924
+ - `data`: any
925
+
926
+ ---
164
927
 
165
- ##### 🪝 Hooks
928
+ ## Troubleshooting
166
929
 
167
- ### `useLogout()`
930
+ ### Common Issues
168
931
 
169
- Logs out the current agent.
932
+ #### 1. SDK Not Initializing
170
933
 
934
+ **Problem:** SDK fails to initialize
935
+ **Solution:**
171
936
  ```tsx
172
- const { logOut } = useLogout();
173
- <button onClick={logOut}>Logout</button>;
937
+ // Check if all required parameters are provided
938
+ try {
939
+ initSDK({
940
+ apiKey: "valid-api-key", // Ensure this is not empty
941
+ tenantId: "valid-tenant-id", // Ensure this is not empty
942
+ agentId: "valid-agent-id" // Ensure this is not empty
943
+ });
944
+ } catch (error) {
945
+ console.error('SDK initialization failed:', error);
946
+ }
174
947
  ```
175
948
 
176
- ### `useEndCall()`
949
+ #### 2. State Not Updating
177
950
 
178
- Hook for ending an active call.
951
+ **Problem:** Components not re-rendering when state changes
952
+ **Solution:**
953
+ ```tsx
954
+ // ✅ Use the hook, not direct state access
955
+ function MyComponent() {
956
+ const state = useSDKState(); // This will trigger re-renders
957
+
958
+ // ❌ Don't do this
959
+ // const state = sdkStateManager.getState();
960
+ }
961
+ ```
179
962
 
180
- **Returns**:
963
+ #### 3. WebSocket Connection Issues
181
964
 
182
- | Key | Type | Description |
183
- | --------------- | -------- | --------------------------------------------------------------- |
184
- | `handleEndCall` | function | `(payload: EndCallPayload) => void` – triggers end-call request |
185
- | `isLoading` | boolean | True while request is pending |
186
- | `isSuccess` | boolean | True if request succeeded |
187
- | `isError` | boolean | True if request failed |
188
- | `error` | any | Error object if failed |
189
- | `data` | any | API response on success |
965
+ **Problem:** Real-time updates not working
966
+ **Solution:**
967
+ ```tsx
968
+ // Check WebSocket connection
969
+ useEffect(() => {
970
+ if (state.agentId) {
971
+ const ws = new WebSocket(`${WS_END_POINT.WS}?agent_id=${state.agentId}`);
972
+
973
+ ws.onopen = () => console.log('WebSocket connected');
974
+ ws.onerror = (error) => console.error('WebSocket error:', error);
975
+ ws.onclose = () => console.log('WebSocket disconnected');
976
+
977
+ return () => ws.close();
978
+ }
979
+ }, [state.agentId]);
980
+ ```
190
981
 
191
- ##### 📦 Payloads
982
+ #### 4. Call Controls Not Working
192
983
 
193
- ### `EndCallPayload`
984
+ **Problem:** Buttons not responding or API calls failing
985
+ **Solution:**
986
+ ```tsx
987
+ // Check agent status and call state
988
+ function CallControls() {
989
+ const state = useSDKState();
990
+
991
+ // Ensure agent is ready before allowing calls
992
+ const canMakeCall = state.status === "idle" || state.status === "ready";
993
+
994
+ return (
995
+ <button
996
+ onClick={handleCall}
997
+ disabled={!canMakeCall || isLoading}
998
+ >
999
+ Call
1000
+ </button>
1001
+ );
1002
+ }
1003
+ ```
1004
+
1005
+ ### Debug Mode
1006
+
1007
+ Enable debug logging:
194
1008
 
195
- ```ts
196
- interface EndCallPayload {
197
- disposition?: string; // Call disposition (default: "RES")
1009
+ ```tsx
1010
+ // Add to your app initialization
1011
+ if (process.env.NODE_ENV === 'development') {
1012
+ // Enable SDK debug mode
1013
+ sdkStateManager.debugStorage();
1014
+
1015
+ // Log all state changes
1016
+ sdkStateManager.subscribe(() => {
1017
+ console.log('SDK State changed:', sdkStateManager.getState());
1018
+ });
198
1019
  }
199
1020
  ```
200
1021
 
201
- ## 🎛 Control Features
1022
+ ---
202
1023
 
203
- - **Status Management**: Idle / Break
204
- - **Call Controls**: Hold / Resume, Mute / Unmute, End Call, Agent Status
205
- - **Persistent State**: Hold, mute, agent status, panel position, call timer
1024
+ ## Productivity Features
206
1025
 
207
- ##### 🌍 Browser Support
1026
+ ### 1. Agent Productivity Metrics
208
1027
 
209
- - Chrome 60+
210
- - ✅ Firefox 60+
211
- - ✅ Safari 12+
212
- - Edge 79+
1028
+ The SDK automatically tracks various productivity metrics:
1029
+
1030
+ ```tsx
1031
+ // Event tracking for productivity analysis
1032
+ eventTracker.logEvent('callStarted', {
1033
+ agentId: state.agentId,
1034
+ phoneNumber: state.callData.phone_number,
1035
+ timestamp: new Date().toISOString(),
1036
+ processId: state.process?.process_id
1037
+ });
1038
+
1039
+ eventTracker.logEvent('callEnded', {
1040
+ agentId: state.agentId,
1041
+ duration: callDuration,
1042
+ disposition: disposition,
1043
+ timestamp: new Date().toISOString()
1044
+ });
1045
+ ```
1046
+
1047
+ ### 2. Real-time Status Updates
1048
+
1049
+ ```tsx
1050
+ // Automatic status synchronization
1051
+ useEffect(() => {
1052
+ const ws = new WebSocket(`${WS_END_POINT.WS}?agent_id=${state.agentId}`);
1053
+
1054
+ ws.onmessage = (event) => {
1055
+ const data = JSON.parse(event.data);
1056
+
1057
+ // Update call data
1058
+ sdkStateManager.updateCallData(data);
1059
+
1060
+ // Track status changes
1061
+ eventTracker.logEvent('statusChanged', {
1062
+ from: state.status,
1063
+ to: data.status,
1064
+ timestamp: new Date().toISOString()
1065
+ });
1066
+ };
1067
+ }, [state.agentId]);
1068
+ ```
1069
+
1070
+ ### 3. Call Quality Monitoring
1071
+
1072
+ ```tsx
1073
+ // Monitor call quality metrics
1074
+ function CallQualityMonitor() {
1075
+ const state = useSDKState();
1076
+
1077
+ useEffect(() => {
1078
+ if (state.callData?.status === "ONCALL") {
1079
+ const startTime = Date.now();
1080
+
1081
+ const interval = setInterval(() => {
1082
+ const duration = Date.now() - startTime;
1083
+
1084
+ // Log call quality metrics every 30 seconds
1085
+ if (duration % 30000 === 0) {
1086
+ eventTracker.logEvent('callQualityMetrics', {
1087
+ duration: duration,
1088
+ isHolding: state.isHolding,
1089
+ isMuted: state.isMuted,
1090
+ timestamp: new Date().toISOString()
1091
+ });
1092
+ }
1093
+ }, 1000);
1094
+
1095
+ return () => clearInterval(interval);
1096
+ }
1097
+ }, [state.callData?.status, state.isHolding, state.isMuted]);
1098
+ }
1099
+ ```
1100
+
1101
+ ### 4. Performance Analytics
1102
+
1103
+ ```tsx
1104
+ // Track UI performance
1105
+ function PerformanceTracker() {
1106
+ useEffect(() => {
1107
+ // Track component render times
1108
+ const startTime = performance.now();
1109
+
1110
+ return () => {
1111
+ const renderTime = performance.now() - startTime;
1112
+ eventTracker.logEvent('componentRender', {
1113
+ component: 'CallControlPanel',
1114
+ renderTime: renderTime,
1115
+ timestamp: new Date().toISOString()
1116
+ });
1117
+ };
1118
+ }, []);
1119
+ }
1120
+ ```
1121
+
1122
+ ### 5. User Experience Optimization
1123
+
1124
+ ```tsx
1125
+ // Optimize user interactions
1126
+ function OptimizedCallControls() {
1127
+ const state = useSDKState();
1128
+
1129
+ // Debounce rapid button clicks
1130
+ const debouncedHold = useDebounce(() => {
1131
+ handleHoldToggle();
1132
+ }, 300);
1133
+
1134
+ // Track user interaction patterns
1135
+ const trackInteraction = (action) => {
1136
+ eventTracker.logEvent('userInteraction', {
1137
+ action: action,
1138
+ agentId: state.agentId,
1139
+ timestamp: new Date().toISOString()
1140
+ });
1141
+ };
1142
+
1143
+ return (
1144
+ <div>
1145
+ <button
1146
+ onClick={() => {
1147
+ trackInteraction('holdToggle');
1148
+ debouncedHold();
1149
+ }}
1150
+ >
1151
+ Hold
1152
+ </button>
1153
+ </div>
1154
+ );
1155
+ }
1156
+ ```
213
1157
 
214
1158
  ---
215
1159
 
216
- ##### 📄 License
1160
+ ## Conclusion
1161
+
1162
+ The Call Control SDK provides a comprehensive solution for WebRTC call management in contact center environments. With its draggable interface, real-time state management, extensive TypeScript support, and productivity features, it enables developers to build robust call center applications quickly and efficiently.
1163
+
1164
+ Key benefits:
1165
+ - **Rapid Development**: Pre-built components and hooks accelerate development
1166
+ - **Type Safety**: Full TypeScript support prevents runtime errors
1167
+ - **Real-time Updates**: WebSocket integration ensures live data synchronization
1168
+ - **Productivity Focus**: Built-in analytics and monitoring capabilities
1169
+ - **Accessibility**: Material-UI components with proper ARIA support
1170
+ - **Mobile Ready**: Touch support and responsive design
1171
+ - **Extensible**: Modular architecture allows for easy customization
1172
+
1173
+ For additional support or feature requests, please refer to the official documentation or contact the development team.
1174
+
1175
+ ---
217
1176
 
218
- MIT © 2025 [![license](https://img.shields.io/npm/l/call-control-sdk.svg)](#-license)
1177
+ *Documentation Version: 1.0*
1178
+ *Last Updated: 2025*
1179
+ *SDK Version: 5.3.0*