omnichannel-frontend/src/modules/home/components/AttendantOpsPanel.jsx

136 lines
4.1 KiB
React
Raw Normal View History

import { useEffect, useState } from 'react';
export function AttendantOpsPanel({
activeChatsCount,
isPaused = false,
pauseDurationLabel = '00:00',
isPresenceLoading = false,
onTogglePause,
}) {
const [secondsOnline, setSecondsOnline] = useState(0);
useEffect(() => {
if (isPaused) return undefined;
const intervalId = window.setInterval(() => {
setSecondsOnline((current) => current + 1);
}, 1000);
return () => window.clearInterval(intervalId);
}, [isPaused]);
const formatTime = (totalSeconds) => {
const hours = Math.floor(totalSeconds / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const seconds = totalSeconds % 60;
return [hours, minutes, seconds]
.map((value) => value.toString().padStart(2, '0'))
.filter((value, index) => value !== '00' || index > 0)
.join(':');
};
const presenceLabel = isPaused ? 'Tempo em pausa' : 'Tempo online';
const presenceTime = isPaused ? pauseDurationLabel : formatTime(secondsOnline);
const statusColor = isPaused ? '#ef4444' : '#10b981';
return (
<div
style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))',
gap: '1rem',
}}
>
<article
style={{
padding: '1.25rem',
borderRadius: '24px',
border: '1px solid var(--color-border)',
background: 'linear-gradient(145deg, #ffffff, #f8fafc)',
boxShadow: 'var(--shadow-sm)',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
}}
>
<div>
<span style={{ color: 'var(--color-text-soft)', fontSize: '0.9rem', fontWeight: 600 }}>
{presenceLabel}
</span>
<strong style={{ display: 'block', fontSize: '1.6rem', marginTop: '0.2rem', color: 'var(--color-text)' }}>
{presenceTime}
</strong>
</div>
<div
title={isPaused ? 'Agente pausado' : 'Agente disponivel'}
style={{
width: 12,
height: 12,
borderRadius: '50%',
background: statusColor,
boxShadow: `0 0 10px ${statusColor}`,
}}
/>
</article>
<article
style={{
padding: '1.25rem',
borderRadius: '24px',
border: '1px solid var(--color-border)',
background: 'linear-gradient(145deg, #ffffff, #f8fafc)',
boxShadow: 'var(--shadow-sm)',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
}}
>
<div>
<span style={{ color: 'var(--color-text-soft)', fontSize: '0.9rem', fontWeight: 600 }}>
Atendimentos abertos
</span>
<strong style={{ display: 'block', fontSize: '1.6rem', marginTop: '0.2rem', color: 'var(--color-text)' }}>
{isPaused ? 0 : activeChatsCount}
</strong>
</div>
</article>
<article
style={{
padding: '1.25rem',
borderRadius: '24px',
border: '1px solid var(--color-border)',
background: 'linear-gradient(145deg, #ffffff, #f8fafc)',
boxShadow: 'var(--shadow-sm)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<button
type="button"
onClick={onTogglePause}
disabled={isPresenceLoading}
style={{
width: '100%',
height: '100%',
padding: '1rem',
borderRadius: '16px',
border: 'none',
background: isPaused ? 'rgba(16, 185, 129, 0.1)' : 'rgba(239, 68, 68, 0.1)',
color: isPaused ? '#10b981' : '#ef4444',
fontSize: '1rem',
fontWeight: 800,
cursor: isPresenceLoading ? 'wait' : 'pointer',
transition: 'all 0.2s ease',
opacity: isPresenceLoading ? 0.7 : 1,
}}
>
{isPaused ? 'Retomar Atendimento' : 'Pausar'}
</button>
</article>
</div>
);
}