chore: floating button for incoming call

This commit is contained in:
Sojan
2025-04-29 03:45:08 -07:00
parent 4c579bc71e
commit 3f0c01e166
11 changed files with 896 additions and 314 deletions
+56 -45
View File
@@ -3,76 +3,87 @@ import ApiClient from '../ApiClient';
class VoiceAPI extends ApiClient {
constructor() {
// Use empty string for resource to avoid duplicate 'accounts' in URL
super('', { accountScoped: true });
// Use 'voice' as the resource with accountScoped: true
super('voice', { accountScoped: true });
}
// Initiate a call to a contact
initiateCall(contactId) {
// Get the account ID from the current URL
const accountId = this.accountIdFromRoute;
// Make sure we have the right endpoint path
return axios.post(
`/api/v1/accounts/${accountId}/contacts/${contactId}/call`
);
if (!contactId) {
throw new Error('Contact ID is required to initiate a call');
}
// Based on the route definition, the correct URL path is /api/v1/accounts/{accountId}/contacts/{contactId}/call
// The endpoint is defined in the contacts namespace, not voice namespace
return axios.post(`${this.baseUrl().replace('/voice', '')}/contacts/${contactId}/call`);
}
// End an active call
endCall(callSid, conversationId) {
if (!conversationId) {
console.error('VoiceAPI: Cannot end call - conversation ID is required');
return Promise.reject(
new Error('Conversation ID is required to end a call')
);
throw new Error('Conversation ID is required to end a call');
}
if (!callSid) {
console.error('VoiceAPI: Cannot end call - call SID is required');
return Promise.reject(new Error('Call SID is required to end a call'));
throw new Error('Call SID is required to end a call');
}
// Validate call SID format - Twilio call SID starts with 'CA' followed by alphanumeric characters
// Validate call SID format - Twilio call SID starts with 'CA' or 'TJ'
if (!callSid.startsWith('CA') && !callSid.startsWith('TJ')) {
console.error('VoiceAPI: Invalid call SID format:', callSid);
return Promise.reject(
new Error(
'Invalid call SID format. Expected Twilio call SID starting with CA or TJ.'
)
throw new Error(
'Invalid call SID format. Expected Twilio call SID starting with CA or TJ.'
);
}
// Get the account ID from the current URL
const accountId = this.accountIdFromRoute;
console.log(
`VoiceAPI: Ending call with SID ${callSid} for conversation ${conversationId} in account ${accountId}`
);
// Make the actual API call with conversation ID as a parameter
// Using the route structure that matches the Rails routes.rb definition
return axios
.post(`/api/v1/accounts/${accountId}/voice/end_call`, {
call_sid: callSid,
conversation_id: conversationId,
id: conversationId, // Also include as 'id' as the controller may check for it
})
.then(response => {
console.log('VoiceAPI: End call API succeeded:', response);
return response;
})
.catch(error => {
console.error('VoiceAPI: End call API failed:', error);
throw error;
});
return axios.post(`${this.url}/end_call`, {
call_sid: callSid,
conversation_id: conversationId,
id: conversationId,
});
}
// Get call status
getCallStatus(callSid) {
// Get the account ID from the current URL
const accountId = this.accountIdFromRoute;
return axios.get(`/api/v1/accounts/${accountId}/voice/call_status`, {
if (!callSid) {
throw new Error('Call SID is required to get call status');
}
return axios.get(`${this.url}/call_status`, {
params: { call_sid: callSid },
});
}
// Join an incoming call as an agent (join the conference)
joinCall(callSid, conversationId) {
if (!conversationId) {
throw new Error('Conversation ID is required to join a call');
}
if (!callSid) {
throw new Error('Call SID is required to join a call');
}
return axios.post(`${this.url}/join_call`, {
call_sid: callSid,
conversation_id: conversationId,
});
}
// Reject an incoming call as an agent (don't join the conference)
rejectCall(callSid, conversationId) {
if (!conversationId) {
throw new Error('Conversation ID is required to reject a call');
}
if (!callSid) {
throw new Error('Call SID is required to reject a call');
}
return axios.post(`${this.url}/reject_call`, {
call_sid: callSid,
conversation_id: conversationId,
});
}
}
export default new VoiceAPI();