212 lines
5.7 KiB
React
212 lines
5.7 KiB
React
|
|
import { useEffect, useRef } from 'react';
|
||
|
|
|
||
|
|
export function ChatWindow({
|
||
|
|
contact,
|
||
|
|
messages,
|
||
|
|
selectedArea,
|
||
|
|
setSelectedArea,
|
||
|
|
draft,
|
||
|
|
setDraft,
|
||
|
|
onSend,
|
||
|
|
onToggleTransfer,
|
||
|
|
isReplying,
|
||
|
|
isMobile = false,
|
||
|
|
}) {
|
||
|
|
const messagesRef = useRef(null);
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
const container = messagesRef.current;
|
||
|
|
if (!container) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
container.scrollTo({
|
||
|
|
top: container.scrollHeight,
|
||
|
|
behavior: 'smooth',
|
||
|
|
});
|
||
|
|
}, [messages, isReplying]);
|
||
|
|
|
||
|
|
return (
|
||
|
|
<section
|
||
|
|
style={{
|
||
|
|
background: '#fff',
|
||
|
|
border: '1px solid var(--color-border)',
|
||
|
|
borderRadius: '28px',
|
||
|
|
overflow: 'hidden',
|
||
|
|
display: 'grid',
|
||
|
|
gridTemplateRows: 'auto 1fr auto',
|
||
|
|
minHeight: 680,
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
<header
|
||
|
|
style={{
|
||
|
|
padding: '1.25rem 1.5rem',
|
||
|
|
borderBottom: '1px solid var(--color-border)',
|
||
|
|
display: 'grid',
|
||
|
|
gridTemplateColumns: isMobile ? '1fr' : 'minmax(0, 1fr) auto',
|
||
|
|
gap: '1rem',
|
||
|
|
alignItems: 'center',
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
<div>
|
||
|
|
<strong style={{ display: 'block', fontSize: '1.15rem' }}>{contact.name}</strong>
|
||
|
|
<span style={{ color: 'var(--color-text-soft)' }}>
|
||
|
|
{contact.status === 'online' ? 'Online' : 'Offline'} • {contact.lastSeen}
|
||
|
|
</span>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div
|
||
|
|
style={{
|
||
|
|
display: 'flex',
|
||
|
|
gap: '0.7rem',
|
||
|
|
flexWrap: 'wrap',
|
||
|
|
justifyContent: isMobile ? 'stretch' : 'flex-end',
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
<select
|
||
|
|
value={selectedArea}
|
||
|
|
onChange={(event) => setSelectedArea(event.target.value)}
|
||
|
|
style={{
|
||
|
|
border: '1px solid var(--color-border)',
|
||
|
|
borderRadius: '14px',
|
||
|
|
padding: '0.8rem 0.95rem',
|
||
|
|
background: '#fff',
|
||
|
|
fontWeight: 600,
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
<option>Suporte</option>
|
||
|
|
<option>Financeiro</option>
|
||
|
|
<option>Comercial</option>
|
||
|
|
</select>
|
||
|
|
<button
|
||
|
|
type="button"
|
||
|
|
onClick={onToggleTransfer}
|
||
|
|
style={{
|
||
|
|
border: 'none',
|
||
|
|
borderRadius: '14px',
|
||
|
|
padding: '0.8rem 1rem',
|
||
|
|
background: 'rgba(0, 49, 80, 0.08)',
|
||
|
|
color: 'var(--color-primary)',
|
||
|
|
fontWeight: 700,
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
Transferir
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
</header>
|
||
|
|
|
||
|
|
<div
|
||
|
|
ref={messagesRef}
|
||
|
|
style={{
|
||
|
|
padding: '1.5rem',
|
||
|
|
display: 'grid',
|
||
|
|
gap: '0.9rem',
|
||
|
|
alignContent: 'start',
|
||
|
|
overflowY: 'auto',
|
||
|
|
background:
|
||
|
|
'radial-gradient(circle at top left, rgba(0, 164, 183, 0.06), transparent 22%), linear-gradient(180deg, rgba(245, 248, 251, 0.8), rgba(255, 255, 255, 0.95))',
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
{messages.map((message) => {
|
||
|
|
const isAgent = message.sender === 'agent';
|
||
|
|
const isSystem = message.sender === 'system';
|
||
|
|
|
||
|
|
if (isSystem) {
|
||
|
|
return (
|
||
|
|
<div
|
||
|
|
key={message.id}
|
||
|
|
style={{
|
||
|
|
justifySelf: 'center',
|
||
|
|
padding: '0.7rem 1rem',
|
||
|
|
borderRadius: '999px',
|
||
|
|
background: 'rgba(0, 49, 80, 0.08)',
|
||
|
|
color: 'var(--color-primary)',
|
||
|
|
fontSize: '0.88rem',
|
||
|
|
fontWeight: 600,
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
{message.text}
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div
|
||
|
|
key={message.id}
|
||
|
|
style={{
|
||
|
|
justifySelf: isAgent ? 'end' : 'start',
|
||
|
|
maxWidth: isMobile ? '88%' : '72%',
|
||
|
|
padding: '0.95rem 1rem',
|
||
|
|
borderRadius: isAgent ? '18px 18px 6px 18px' : '18px 18px 18px 6px',
|
||
|
|
background: isAgent ? 'var(--color-primary)' : '#edf1f5',
|
||
|
|
color: isAgent ? '#fff' : 'var(--color-text)',
|
||
|
|
boxShadow: 'var(--shadow-md)',
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
{message.text}
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
})}
|
||
|
|
|
||
|
|
{isReplying ? (
|
||
|
|
<div
|
||
|
|
style={{
|
||
|
|
justifySelf: 'start',
|
||
|
|
padding: '0.8rem 0.95rem',
|
||
|
|
borderRadius: '18px 18px 18px 6px',
|
||
|
|
background: '#edf1f5',
|
||
|
|
color: 'var(--color-text-soft)',
|
||
|
|
fontWeight: 600,
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
Digitando...
|
||
|
|
</div>
|
||
|
|
) : null}
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<footer
|
||
|
|
style={{
|
||
|
|
padding: '1rem 1.25rem 1.25rem',
|
||
|
|
borderTop: '1px solid var(--color-border)',
|
||
|
|
display: 'grid',
|
||
|
|
gridTemplateColumns: isMobile ? '1fr' : '1fr auto',
|
||
|
|
gap: '0.75rem',
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
<input
|
||
|
|
type="text"
|
||
|
|
value={draft}
|
||
|
|
onChange={(event) => setDraft(event.target.value)}
|
||
|
|
onKeyDown={(event) => {
|
||
|
|
if (event.key === 'Enter') {
|
||
|
|
onSend();
|
||
|
|
}
|
||
|
|
}}
|
||
|
|
placeholder="Escreva sua mensagem..."
|
||
|
|
style={{
|
||
|
|
border: '1px solid var(--color-border)',
|
||
|
|
borderRadius: '18px',
|
||
|
|
padding: '0.95rem 1rem',
|
||
|
|
background: '#fff',
|
||
|
|
outline: 'none',
|
||
|
|
}}
|
||
|
|
/>
|
||
|
|
<button
|
||
|
|
type="button"
|
||
|
|
onClick={onSend}
|
||
|
|
style={{
|
||
|
|
border: 'none',
|
||
|
|
borderRadius: '18px',
|
||
|
|
padding: '0.95rem 1.2rem',
|
||
|
|
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
||
|
|
color: '#fff',
|
||
|
|
fontWeight: 700,
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
Enviar
|
||
|
|
</button>
|
||
|
|
</footer>
|
||
|
|
</section>
|
||
|
|
);
|
||
|
|
}
|