feat: add call duration
This commit is contained in:
@@ -77,4 +77,15 @@ describe('VoiceCall.vue', () => {
|
||||
|
||||
expect(wrapper.text()).toContain('You answered');
|
||||
});
|
||||
|
||||
it('shows the formatted duration when a call has ended', () => {
|
||||
messageContext.contentAttributes.value.data.status =
|
||||
VOICE_CALL_STATUS.COMPLETED;
|
||||
messageContext.contentAttributes.value.data.meta.duration = 133;
|
||||
|
||||
const wrapper = mountComponent();
|
||||
|
||||
expect(wrapper.text()).toContain('Call ended');
|
||||
expect(wrapper.text()).toContain('02:13');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@ import { computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useMessageContext } from '../provider.js';
|
||||
import { MESSAGE_TYPES, VOICE_CALL_STATUS } from '../constants';
|
||||
import { formatDuration } from 'shared/helpers/timeHelper';
|
||||
|
||||
import Icon from 'dashboard/components-next/icon/Icon.vue';
|
||||
import BaseBubble from 'next/message/bubbles/Base.vue';
|
||||
@@ -29,6 +30,9 @@ const status = computed(() => data.value?.status?.toString());
|
||||
const joinedBy = computed(() => {
|
||||
return data.value?.meta?.joinedBy || data.value?.meta?.joined_by;
|
||||
});
|
||||
const callDuration = computed(() => {
|
||||
return data.value?.meta?.duration;
|
||||
});
|
||||
|
||||
const isOutbound = computed(() => messageType.value === MESSAGE_TYPES.OUTGOING);
|
||||
const isFailed = computed(() =>
|
||||
@@ -64,7 +68,10 @@ const subtext = computed(() => {
|
||||
}
|
||||
|
||||
if (status.value === VOICE_CALL_STATUS.COMPLETED) {
|
||||
return t('CONVERSATION.VOICE_CALL.CALL_ENDED');
|
||||
return (
|
||||
formatDuration(callDuration.value) ||
|
||||
t('CONVERSATION.VOICE_CALL.CALL_ENDED')
|
||||
);
|
||||
}
|
||||
|
||||
if (status.value === VOICE_CALL_STATUS.IN_PROGRESS) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import TwilioVoiceClient from 'dashboard/api/channel/voice/twilioVoiceClient';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
import { useCallsStore } from 'dashboard/stores/calls';
|
||||
import Timer from 'dashboard/helper/Timer';
|
||||
import { formatDuration } from 'shared/helpers/timeHelper';
|
||||
|
||||
export function useCallSession() {
|
||||
const callsStore = useCallsStore();
|
||||
@@ -98,9 +99,7 @@ export function useCallSession() {
|
||||
};
|
||||
|
||||
const formattedCallDuration = computed(() => {
|
||||
const minutes = Math.floor(callDuration.value / 60);
|
||||
const seconds = callDuration.value % 60;
|
||||
return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
||||
return formatDuration(callDuration.value);
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
dynamicTime,
|
||||
dateFormat,
|
||||
shortTimestamp,
|
||||
formatDuration,
|
||||
getDayDifferenceFromNow,
|
||||
hasOneDayPassed,
|
||||
} from 'shared/helpers/timeHelper';
|
||||
@@ -93,6 +94,24 @@ describe('#shortTimestamp', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('#formatDuration', () => {
|
||||
it('returns empty string for invalid values', () => {
|
||||
expect(formatDuration(null)).toEqual('');
|
||||
expect(formatDuration(undefined)).toEqual('');
|
||||
expect(formatDuration(-1)).toEqual('');
|
||||
expect(formatDuration('abc')).toEqual('');
|
||||
});
|
||||
|
||||
it('formats short durations as mm:ss', () => {
|
||||
expect(formatDuration(0)).toEqual('00:00');
|
||||
expect(formatDuration(133)).toEqual('02:13');
|
||||
});
|
||||
|
||||
it('formats long durations as hh:mm:ss', () => {
|
||||
expect(formatDuration(3733)).toEqual('01:02:13');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getDayDifferenceFromNow', () => {
|
||||
it('returns 0 for timestamps from today', () => {
|
||||
// Mock current date: May 5, 2023
|
||||
|
||||
@@ -93,6 +93,32 @@ export const shortTimestamp = (time, withAgo = false) => {
|
||||
return convertToShortTime;
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats a duration in seconds into mm:ss or hh:mm:ss.
|
||||
* @param {number|string} durationInSeconds - Duration in seconds.
|
||||
* @returns {string} Formatted duration string.
|
||||
*/
|
||||
export const formatDuration = durationInSeconds => {
|
||||
if (durationInSeconds === null || durationInSeconds === undefined) return '';
|
||||
|
||||
const totalSeconds = Number(durationInSeconds);
|
||||
if (Number.isNaN(totalSeconds) || totalSeconds < 0) return '';
|
||||
|
||||
const hours = Math.floor(totalSeconds / 3600);
|
||||
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
||||
const seconds = totalSeconds % 60;
|
||||
|
||||
if (hours > 0) {
|
||||
return `${hours.toString().padStart(2, '0')}:${minutes
|
||||
.toString()
|
||||
.padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
return `${minutes.toString().padStart(2, '0')}:${seconds
|
||||
.toString()
|
||||
.padStart(2, '0')}`;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the difference in days between now and a given timestamp.
|
||||
* @param {Date} now - Current date/time.
|
||||
|
||||
Reference in New Issue
Block a user