From 27b828f808ae7c4a922b1576c00336f2b4e0ed8d Mon Sep 17 00:00:00 2001 From: Matthew Olker Date: Mon, 27 Apr 2026 10:35:11 -0400 Subject: [PATCH 1/3] Countdown implementation --- .../CampaignCountdown/campaign-countdown.tsx | 61 +++++++ .../campaign-countdown.types.ts | 27 +++ .../campaign-countdown.utils.ts | 85 +++++++++ .../src/components/task/constants.ts | 1 + .../contact-center/cc-components/src/index.ts | 3 + .../campaign-countdown.snapshot.tsx.snap | 40 ++++ .../campaign-countdown.snapshot.tsx | 27 +++ .../CampaignCountdown/campaign-countdown.tsx | 172 ++++++++++++++++++ .../campaign-countdown.utils.tsx | 104 +++++++++++ widgets-samples/cc/samples-cc-wc-app/app.js | 2 + 10 files changed, 522 insertions(+) create mode 100644 packages/contact-center/cc-components/src/components/task/CampaignCountdown/campaign-countdown.tsx create mode 100644 packages/contact-center/cc-components/src/components/task/CampaignCountdown/campaign-countdown.types.ts create mode 100644 packages/contact-center/cc-components/src/components/task/CampaignCountdown/campaign-countdown.utils.ts create mode 100644 packages/contact-center/cc-components/tests/components/task/CampaignCountdown/__snapshots__/campaign-countdown.snapshot.tsx.snap create mode 100644 packages/contact-center/cc-components/tests/components/task/CampaignCountdown/campaign-countdown.snapshot.tsx create mode 100644 packages/contact-center/cc-components/tests/components/task/CampaignCountdown/campaign-countdown.tsx create mode 100644 packages/contact-center/cc-components/tests/components/task/CampaignCountdown/campaign-countdown.utils.tsx diff --git a/packages/contact-center/cc-components/src/components/task/CampaignCountdown/campaign-countdown.tsx b/packages/contact-center/cc-components/src/components/task/CampaignCountdown/campaign-countdown.tsx new file mode 100644 index 000000000..6d3462fa5 --- /dev/null +++ b/packages/contact-center/cc-components/src/components/task/CampaignCountdown/campaign-countdown.tsx @@ -0,0 +1,61 @@ +import React, {useEffect, useRef, useState, useCallback} from 'react'; +import {Text} from '@momentum-ui/react-collaboration'; +import {CampaignCountdownProps} from './campaign-countdown.types'; +import {formatCountdown, calculateRemainingSeconds} from './campaign-countdown.utils'; +import {withMetrics} from '@webex/cc-ui-logging'; +import {TIME_LEFT} from '../constants'; + +const CampaignCountdown: React.FC = ({ + timeoutInSeconds, + timeoutTimestamp, + onTimeout, + logger, +}) => { + const calculateRemaining = useCallback((): number => { + return calculateRemainingSeconds(timeoutTimestamp, timeoutInSeconds, logger); + }, [timeoutTimestamp, timeoutInSeconds, logger]); + + const [remainingSeconds, setRemainingSeconds] = useState(calculateRemaining()); + const [hasTimedOut, setHasTimedOut] = useState(false); + const timerRef = useRef | undefined>(); + + useEffect(() => { + setRemainingSeconds(calculateRemaining()); + setHasTimedOut(false); + }, [timeoutTimestamp, timeoutInSeconds, calculateRemaining]); + + useEffect(() => { + if (timerRef.current !== undefined) { + clearTimeout(timerRef.current); + timerRef.current = undefined; + } + + if (remainingSeconds > 0) { + timerRef.current = setTimeout(() => { + setRemainingSeconds((prev) => prev - 1); + timerRef.current = undefined; + }, 1000); + } else if (remainingSeconds === 0 && !hasTimedOut) { + setHasTimedOut(true); + onTimeout?.(); + } + + return () => { + if (timerRef.current !== undefined) { + clearTimeout(timerRef.current); + timerRef.current = undefined; + } + }; + }, [remainingSeconds, hasTimedOut, onTimeout]); + + const formattedTime = formatCountdown(remainingSeconds, logger); + + return ( + + {TIME_LEFT} {formattedTime} + + ); +}; + +const CampaignCountdownWithMetrics = withMetrics(CampaignCountdown, 'CampaignCountdown'); +export default CampaignCountdownWithMetrics; diff --git a/packages/contact-center/cc-components/src/components/task/CampaignCountdown/campaign-countdown.types.ts b/packages/contact-center/cc-components/src/components/task/CampaignCountdown/campaign-countdown.types.ts new file mode 100644 index 000000000..653b28623 --- /dev/null +++ b/packages/contact-center/cc-components/src/components/task/CampaignCountdown/campaign-countdown.types.ts @@ -0,0 +1,27 @@ +import {ILogger} from '@webex/cc-store'; + +export interface CampaignCountdownProps { + /** + * Timeout duration in seconds. + * Use this OR timeoutTimestamp, not both. + */ + timeoutInSeconds?: number; + + /** + * Epoch timestamp (in milliseconds) when the countdown should expire. + * This is where `campaignPreviewOfferTimeout` from callProcessingDetails should be passed. + * Can be provided as a string or number - will be parsed automatically. + * Takes precedence over timeoutInSeconds if both are provided. + */ + timeoutTimestamp?: string | number; + + /** + * Callback fired when the countdown reaches zero + */ + onTimeout?: () => void; + + /** + * Logger instance for logging purposes + */ + logger?: ILogger; +} diff --git a/packages/contact-center/cc-components/src/components/task/CampaignCountdown/campaign-countdown.utils.ts b/packages/contact-center/cc-components/src/components/task/CampaignCountdown/campaign-countdown.utils.ts new file mode 100644 index 000000000..b9c3aec65 --- /dev/null +++ b/packages/contact-center/cc-components/src/components/task/CampaignCountdown/campaign-countdown.utils.ts @@ -0,0 +1,85 @@ +import {ILogger} from '@webex/cc-store'; + +/** + * Parses the timeoutTimestamp value (string or number) to a number. + * The backend sends campaignPreviewOfferTimeout as a string epoch timestamp in milliseconds. + */ +export const parseTimeoutTimestamp = (value: string | number | undefined, logger?: ILogger): number => { + try { + if (value === undefined) { + return 0; + } + if (typeof value === 'number') { + return value; + } + if (typeof value === 'string') { + const parsed = parseInt(value, 10); + if (!isNaN(parsed)) { + return parsed; + } + } + return 0; + } catch (error) { + logger?.error('CC-Widgets: CampaignCountdown: Error in parseTimeoutTimestamp', { + module: 'cc-components#campaign-countdown.utils.ts', + method: 'parseTimeoutTimestamp', + error: error.message, + }); + return 0; + } +}; + +/** + * Calculates remaining seconds based on either a timestamp or a direct seconds value. + * If timeoutTimestamp is provided, it calculates the difference from now. + * Otherwise, it uses timeoutInSeconds directly. + */ +export const calculateRemainingSeconds = ( + timeoutTimestamp?: string | number, + timeoutInSeconds?: number, + logger?: ILogger +): number => { + try { + // timeoutTimestamp takes precedence + if (timeoutTimestamp !== undefined) { + const parsedTimestamp = parseTimeoutTimestamp(timeoutTimestamp, logger); + if (parsedTimestamp > 0) { + const now = Date.now(); + const diffMs = parsedTimestamp - now; + return diffMs > 0 ? Math.ceil(diffMs / 1000) : 0; + } + } + // Fall back to timeoutInSeconds + if (typeof timeoutInSeconds === 'number') { + return Math.max(0, timeoutInSeconds); + } + return 0; + } catch (error) { + logger?.error('CC-Widgets: CampaignCountdown: Error in calculateRemainingSeconds', { + module: 'cc-components#campaign-countdown.utils.ts', + method: 'calculateRemainingSeconds', + error: error.message, + }); + return 0; + } +}; + +/** + * Formats seconds into MM:SS format for countdown display + */ +export const formatCountdown = (seconds: number, logger?: ILogger): string => { + try { + const safeSeconds = Math.max(0, seconds); + const minutes = Math.floor(safeSeconds / 60); + const remainingSeconds = safeSeconds % 60; + + return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`; + } catch (error) { + logger?.error('CC-Widgets: CampaignCountdown: Error in formatCountdown', { + module: 'cc-components#campaign-countdown.utils.ts', + method: 'formatCountdown', + error: error.message, + }); + return '00:00'; + } +}; diff --git a/packages/contact-center/cc-components/src/components/task/constants.ts b/packages/contact-center/cc-components/src/components/task/constants.ts index 8308c8b9b..519543c1e 100644 --- a/packages/contact-center/cc-components/src/components/task/constants.ts +++ b/packages/contact-center/cc-components/src/components/task/constants.ts @@ -37,3 +37,4 @@ export const QUEUE = 'Queue:'; export const PHONE_NUMBER = 'Phone Number:'; export const CUSTOMER_NAME = 'Customer Name'; export const RONA = 'RONA:'; +export const TIME_LEFT = 'Time left:'; diff --git a/packages/contact-center/cc-components/src/index.ts b/packages/contact-center/cc-components/src/index.ts index 97a152d57..d8b046b6e 100644 --- a/packages/contact-center/cc-components/src/index.ts +++ b/packages/contact-center/cc-components/src/index.ts @@ -6,6 +6,7 @@ import IncomingTaskComponent from './components/task/IncomingTask/incoming-task' import TaskListComponent from './components/task/TaskList/task-list'; import OutdialCallComponent from './components/task/OutdialCall/outdial-call'; import CampaignErrorDialogComponent from './components/task/CampaignErrorDialog/campaign-error-dialog'; +import CampaignCountdownComponent from './components/task/CampaignCountdown/campaign-countdown'; import RealTimeTranscriptComponent from './components/task/RealTimeTranscript/real-time-transcript'; export { @@ -17,6 +18,7 @@ export { TaskListComponent, OutdialCallComponent, CampaignErrorDialogComponent, + CampaignCountdownComponent, RealTimeTranscriptComponent, }; export * from './components/StationLogin/constants'; @@ -24,3 +26,4 @@ export * from './components/StationLogin/station-login.types'; export * from './components/UserState/user-state.types'; export * from './components/task/task.types'; export * from './components/task/CampaignErrorDialog/campaign-error-dialog.types'; +export * from './components/task/CampaignCountdown/campaign-countdown.types'; diff --git a/packages/contact-center/cc-components/tests/components/task/CampaignCountdown/__snapshots__/campaign-countdown.snapshot.tsx.snap b/packages/contact-center/cc-components/tests/components/task/CampaignCountdown/__snapshots__/campaign-countdown.snapshot.tsx.snap new file mode 100644 index 000000000..b32019383 --- /dev/null +++ b/packages/contact-center/cc-components/tests/components/task/CampaignCountdown/__snapshots__/campaign-countdown.snapshot.tsx.snap @@ -0,0 +1,40 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CampaignCountdown Snapshots Rendering should match snapshot with 0 seconds timeout 1`] = ` +
+ + Time left: + + 00:00 + +
+`; + +exports[`CampaignCountdown Snapshots Rendering should match snapshot with 30 seconds timeout 1`] = ` +
+ + Time left: + + 00:30 + +
+`; + +exports[`CampaignCountdown Snapshots Rendering should match snapshot with 125 seconds timeout 1`] = ` +
+ + Time left: + + 02:05 + +
+`; diff --git a/packages/contact-center/cc-components/tests/components/task/CampaignCountdown/campaign-countdown.snapshot.tsx b/packages/contact-center/cc-components/tests/components/task/CampaignCountdown/campaign-countdown.snapshot.tsx new file mode 100644 index 000000000..f20570433 --- /dev/null +++ b/packages/contact-center/cc-components/tests/components/task/CampaignCountdown/campaign-countdown.snapshot.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import {render} from '@testing-library/react'; +import '@testing-library/jest-dom'; +import CampaignCountdownComponent from '../../../../src/components/task/CampaignCountdown/campaign-countdown'; + +describe('CampaignCountdown Snapshots', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('Rendering', () => { + it('should match snapshot with 30 seconds timeout', () => { + const {container} = render(); + expect(container).toMatchSnapshot(); + }); + + it('should match snapshot with 0 seconds timeout', () => { + const {container} = render(); + expect(container).toMatchSnapshot(); + }); + + it('should match snapshot with 125 seconds timeout', () => { + const {container} = render(); + expect(container).toMatchSnapshot(); + }); + }); +}); diff --git a/packages/contact-center/cc-components/tests/components/task/CampaignCountdown/campaign-countdown.tsx b/packages/contact-center/cc-components/tests/components/task/CampaignCountdown/campaign-countdown.tsx new file mode 100644 index 000000000..d8705afc1 --- /dev/null +++ b/packages/contact-center/cc-components/tests/components/task/CampaignCountdown/campaign-countdown.tsx @@ -0,0 +1,172 @@ +import React from 'react'; +import {render, screen, act} from '@testing-library/react'; +import '@testing-library/jest-dom'; +import CampaignCountdownComponent from '../../../../src/components/task/CampaignCountdown/campaign-countdown'; +import {CampaignCountdownProps} from '../../../../src/components/task/CampaignCountdown/campaign-countdown.types'; + +describe('CampaignCountdownComponent', () => { + const defaultProps: CampaignCountdownProps = { + timeoutInSeconds: 30, + }; + + beforeEach(() => { + jest.clearAllMocks(); + jest.useFakeTimers(); + }); + + afterEach(() => { + jest.useRealTimers(); + }); + + describe('Rendering', () => { + it('should render the countdown element', () => { + render(); + + const countdown = screen.getByTestId('campaign-countdown'); + expect(countdown).toBeInTheDocument(); + }); + + it('should display "Time left:" label with formatted time', () => { + render(); + + const countdown = screen.getByTestId('campaign-countdown'); + expect(countdown).toHaveTextContent('Time left:'); + expect(countdown).toHaveTextContent('00:30'); + }); + + it('should format time correctly for various values', () => { + const {rerender} = render(); + expect(screen.getByTestId('campaign-countdown')).toHaveTextContent('00:00'); + + rerender(); + expect(screen.getByTestId('campaign-countdown')).toHaveTextContent('00:59'); + + rerender(); + expect(screen.getByTestId('campaign-countdown')).toHaveTextContent('01:00'); + + rerender(); + expect(screen.getByTestId('campaign-countdown')).toHaveTextContent('02:05'); + }); + + it('should handle negative values gracefully', () => { + render(); + + const countdown = screen.getByTestId('campaign-countdown'); + expect(countdown).toHaveTextContent('00:00'); + }); + }); + + describe('Countdown Logic', () => { + it('should decrement the countdown every second', () => { + render(); + + expect(screen.getByTestId('campaign-countdown')).toHaveTextContent('00:05'); + + act(() => { + jest.advanceTimersByTime(1000); + }); + expect(screen.getByTestId('campaign-countdown')).toHaveTextContent('00:04'); + + act(() => { + jest.advanceTimersByTime(1000); + }); + expect(screen.getByTestId('campaign-countdown')).toHaveTextContent('00:03'); + }); + + it('should call onTimeout when countdown reaches zero', () => { + const onTimeout = jest.fn(); + render(); + + expect(onTimeout).not.toHaveBeenCalled(); + + act(() => { + jest.advanceTimersByTime(1000); + }); + act(() => { + jest.advanceTimersByTime(1000); + }); + + expect(onTimeout).toHaveBeenCalledTimes(1); + }); + + it('should stop at zero and not go negative', () => { + render(); + + act(() => { + jest.advanceTimersByTime(3000); + }); + + expect(screen.getByTestId('campaign-countdown')).toHaveTextContent('00:00'); + }); + + it('should reset countdown when timeoutInSeconds prop changes', () => { + const {rerender} = render(); + + act(() => { + jest.advanceTimersByTime(1000); + }); + act(() => { + jest.advanceTimersByTime(1000); + }); + act(() => { + jest.advanceTimersByTime(1000); + }); + expect(screen.getByTestId('campaign-countdown')).toHaveTextContent('00:07'); + + rerender(); + expect(screen.getByTestId('campaign-countdown')).toHaveTextContent('00:20'); + }); + }); + + describe('Timestamp-based countdown (campaignPreviewOfferTimeout)', () => { + it('should handle string timestamp from backend', () => { + const futureTimestamp = String(Date.now() + 30000); + render(); + + const countdown = screen.getByTestId('campaign-countdown'); + expect(countdown).toHaveTextContent('00:30'); + }); + + it('should handle number timestamp', () => { + const futureTimestamp = Date.now() + 30000; + render(); + + const countdown = screen.getByTestId('campaign-countdown'); + expect(countdown).toHaveTextContent('00:30'); + }); + + it('should show 00:00 for past timestamp', () => { + const pastTimestamp = String(Date.now() - 5000); + render(); + + const countdown = screen.getByTestId('campaign-countdown'); + expect(countdown).toHaveTextContent('00:00'); + }); + + it('should prioritize timeoutTimestamp over timeoutInSeconds', () => { + const futureTimestamp = Date.now() + 10000; // 10 seconds + render(); + + const countdown = screen.getByTestId('campaign-countdown'); + expect(countdown).toHaveTextContent('00:10'); + }); + }); + + describe('Styling', () => { + it('should have the correct CSS class', () => { + render(); + + const countdown = screen.getByTestId('campaign-countdown'); + expect(countdown).toHaveClass('task-text'); + }); + }); + + describe('Accessibility', () => { + it('should render as a text element', () => { + render(); + + const countdown = screen.getByTestId('campaign-countdown'); + expect(countdown.tagName).toBe('MDC-TEXT'); + }); + }); +}); diff --git a/packages/contact-center/cc-components/tests/components/task/CampaignCountdown/campaign-countdown.utils.tsx b/packages/contact-center/cc-components/tests/components/task/CampaignCountdown/campaign-countdown.utils.tsx new file mode 100644 index 000000000..06826aee8 --- /dev/null +++ b/packages/contact-center/cc-components/tests/components/task/CampaignCountdown/campaign-countdown.utils.tsx @@ -0,0 +1,104 @@ +import { + formatCountdown, + calculateRemainingSeconds, + parseTimeoutTimestamp, +} from '../../../../src/components/task/CampaignCountdown/campaign-countdown.utils'; + +describe('CampaignCountdown.utils', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('formatCountdown', () => { + it('should format zero seconds correctly', () => { + expect(formatCountdown(0)).toBe('00:00'); + }); + + it('should format seconds only correctly', () => { + expect(formatCountdown(5)).toBe('00:05'); + expect(formatCountdown(30)).toBe('00:30'); + expect(formatCountdown(59)).toBe('00:59'); + }); + + it('should format minutes and seconds correctly', () => { + expect(formatCountdown(60)).toBe('01:00'); + expect(formatCountdown(90)).toBe('01:30'); + expect(formatCountdown(125)).toBe('02:05'); + }); + + it('should handle large values correctly', () => { + expect(formatCountdown(3600)).toBe('60:00'); + expect(formatCountdown(3661)).toBe('61:01'); + }); + + it('should handle negative values by returning 00:00', () => { + expect(formatCountdown(-5)).toBe('00:00'); + expect(formatCountdown(-100)).toBe('00:00'); + }); + + it('should pad single digit values with leading zeros', () => { + expect(formatCountdown(1)).toBe('00:01'); + expect(formatCountdown(9)).toBe('00:09'); + expect(formatCountdown(61)).toBe('01:01'); + }); + }); + + describe('parseTimeoutTimestamp', () => { + it('should parse string timestamp correctly', () => { + expect(parseTimeoutTimestamp('1777297081043')).toBe(1777297081043); + }); + + it('should return number timestamp as-is', () => { + expect(parseTimeoutTimestamp(1777297081043)).toBe(1777297081043); + }); + + it('should return 0 for undefined', () => { + expect(parseTimeoutTimestamp(undefined)).toBe(0); + }); + + it('should return 0 for invalid string', () => { + expect(parseTimeoutTimestamp('invalid')).toBe(0); + }); + }); + + describe('calculateRemainingSeconds', () => { + it('should return timeoutInSeconds when provided', () => { + expect(calculateRemainingSeconds(undefined, 30)).toBe(30); + expect(calculateRemainingSeconds(undefined, 60)).toBe(60); + }); + + it('should return 0 for negative timeoutInSeconds', () => { + expect(calculateRemainingSeconds(undefined, -5)).toBe(0); + }); + + it('should calculate remaining seconds from future timestamp (number)', () => { + const futureTimestamp = Date.now() + 30000; + const result = calculateRemainingSeconds(futureTimestamp, undefined); + expect(result).toBeGreaterThanOrEqual(29); + expect(result).toBeLessThanOrEqual(31); + }); + + it('should calculate remaining seconds from future timestamp (string)', () => { + const futureTimestamp = String(Date.now() + 30000); + const result = calculateRemainingSeconds(futureTimestamp, undefined); + expect(result).toBeGreaterThanOrEqual(29); + expect(result).toBeLessThanOrEqual(31); + }); + + it('should return 0 for past timestamp', () => { + const pastTimestamp = Date.now() - 5000; + expect(calculateRemainingSeconds(pastTimestamp, undefined)).toBe(0); + }); + + it('should prioritize timestamp over timeoutInSeconds', () => { + const futureTimestamp = Date.now() + 10000; + const result = calculateRemainingSeconds(futureTimestamp, 60); + expect(result).toBeGreaterThanOrEqual(9); + expect(result).toBeLessThanOrEqual(11); + }); + + it('should return 0 when neither value is provided', () => { + expect(calculateRemainingSeconds(undefined, undefined)).toBe(0); + }); + }); +}); diff --git a/widgets-samples/cc/samples-cc-wc-app/app.js b/widgets-samples/cc/samples-cc-wc-app/app.js index df2aea984..b93ec401a 100644 --- a/widgets-samples/cc/samples-cc-wc-app/app.js +++ b/widgets-samples/cc/samples-cc-wc-app/app.js @@ -1,3 +1,5 @@ +const store = window.store; + const accessTokenElem = document.getElementById('access_token_elem'); const oAuthLoginBtn = document.getElementById('oauth_login_btn'); const loginTypeElem = document.getElementById('loginType'); From cc371dc741b0cc3404d2f949f8d46644133e8fcd Mon Sep 17 00:00:00 2001 From: Matthew Olker Date: Mon, 27 Apr 2026 15:29:30 -0400 Subject: [PATCH 2/3] PR Comment --- .../task/CampaignCountdown/campaign-countdown.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/contact-center/cc-components/src/components/task/CampaignCountdown/campaign-countdown.tsx b/packages/contact-center/cc-components/src/components/task/CampaignCountdown/campaign-countdown.tsx index 6d3462fa5..84c2c13ed 100644 --- a/packages/contact-center/cc-components/src/components/task/CampaignCountdown/campaign-countdown.tsx +++ b/packages/contact-center/cc-components/src/components/task/CampaignCountdown/campaign-countdown.tsx @@ -32,7 +32,10 @@ const CampaignCountdown: React.FC = ({ if (remainingSeconds > 0) { timerRef.current = setTimeout(() => { - setRemainingSeconds((prev) => prev - 1); + // Recalculate from wall clock when using timeoutTimestamp to handle + // browser throttling (background tabs, blocked main thread) + const newRemaining = timeoutTimestamp !== undefined ? calculateRemaining() : remainingSeconds - 1; + setRemainingSeconds(newRemaining); timerRef.current = undefined; }, 1000); } else if (remainingSeconds === 0 && !hasTimedOut) { @@ -46,7 +49,7 @@ const CampaignCountdown: React.FC = ({ timerRef.current = undefined; } }; - }, [remainingSeconds, hasTimedOut, onTimeout]); + }, [remainingSeconds, hasTimedOut, onTimeout, timeoutTimestamp, calculateRemaining]); const formattedTime = formatCountdown(remainingSeconds, logger); From ce82ee2b8899e447a0e2e34a90c191add388d650 Mon Sep 17 00:00:00 2001 From: Matthew Olker Date: Tue, 28 Apr 2026 10:06:59 -0400 Subject: [PATCH 3/3] Change Text import --- .../task/CampaignCountdown/campaign-countdown.tsx | 4 ++-- .../__snapshots__/campaign-countdown.snapshot.tsx.snap | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/contact-center/cc-components/src/components/task/CampaignCountdown/campaign-countdown.tsx b/packages/contact-center/cc-components/src/components/task/CampaignCountdown/campaign-countdown.tsx index 84c2c13ed..7d1e23b25 100644 --- a/packages/contact-center/cc-components/src/components/task/CampaignCountdown/campaign-countdown.tsx +++ b/packages/contact-center/cc-components/src/components/task/CampaignCountdown/campaign-countdown.tsx @@ -1,5 +1,5 @@ import React, {useEffect, useRef, useState, useCallback} from 'react'; -import {Text} from '@momentum-ui/react-collaboration'; +import {Text} from '@momentum-design/components/dist/react'; import {CampaignCountdownProps} from './campaign-countdown.types'; import {formatCountdown, calculateRemainingSeconds} from './campaign-countdown.utils'; import {withMetrics} from '@webex/cc-ui-logging'; @@ -54,7 +54,7 @@ const CampaignCountdown: React.FC = ({ const formattedTime = formatCountdown(remainingSeconds, logger); return ( - + {TIME_LEFT} {formattedTime} ); diff --git a/packages/contact-center/cc-components/tests/components/task/CampaignCountdown/__snapshots__/campaign-countdown.snapshot.tsx.snap b/packages/contact-center/cc-components/tests/components/task/CampaignCountdown/__snapshots__/campaign-countdown.snapshot.tsx.snap index b32019383..a372c9e54 100644 --- a/packages/contact-center/cc-components/tests/components/task/CampaignCountdown/__snapshots__/campaign-countdown.snapshot.tsx.snap +++ b/packages/contact-center/cc-components/tests/components/task/CampaignCountdown/__snapshots__/campaign-countdown.snapshot.tsx.snap @@ -3,7 +3,7 @@ exports[`CampaignCountdown Snapshots Rendering should match snapshot with 0 seconds timeout 1`] = `
Time left: @@ -16,7 +16,7 @@ exports[`CampaignCountdown Snapshots Rendering should match snapshot with 0 seco exports[`CampaignCountdown Snapshots Rendering should match snapshot with 30 seconds timeout 1`] = `
Time left: @@ -29,7 +29,7 @@ exports[`CampaignCountdown Snapshots Rendering should match snapshot with 30 sec exports[`CampaignCountdown Snapshots Rendering should match snapshot with 125 seconds timeout 1`] = `
Time left: