2026-03-19 18:22:18 -03:00
|
|
|
import { Link } from 'react-router-dom';
|
|
|
|
|
import { BrandMark } from '../../../shared/components/BrandMark';
|
|
|
|
|
import { useViewport } from '../../../shared/hooks/useViewport';
|
|
|
|
|
import { ChatConversationList } from '../components/ChatConversationList';
|
|
|
|
|
import { ChatTransferPanel } from '../components/ChatTransferPanel';
|
|
|
|
|
import { ChatWindow } from '../components/ChatWindow';
|
|
|
|
|
import { useChat } from '../hooks/useChat';
|
|
|
|
|
import { quickReplies } from '../services/chatMocks';
|
|
|
|
|
|
|
|
|
|
export function ChatPage() {
|
|
|
|
|
const { isWideDesktop, isDesktop, isTablet, isMobile } = useViewport();
|
|
|
|
|
const {
|
|
|
|
|
contacts,
|
|
|
|
|
activeContact,
|
|
|
|
|
activeContactId,
|
|
|
|
|
setActiveContactId,
|
|
|
|
|
messages,
|
|
|
|
|
draft,
|
|
|
|
|
setDraft,
|
2026-05-18 17:34:23 -03:00
|
|
|
attachedFile,
|
|
|
|
|
attachFile,
|
|
|
|
|
removeAttachedFile,
|
2026-03-19 18:22:18 -03:00
|
|
|
sendMessage,
|
2026-05-18 17:34:23 -03:00
|
|
|
hydrateMessageMedia,
|
2026-03-19 18:22:18 -03:00
|
|
|
isReplying,
|
|
|
|
|
selectedArea,
|
|
|
|
|
setSelectedArea,
|
|
|
|
|
isTransferOpen,
|
|
|
|
|
setIsTransferOpen,
|
|
|
|
|
transferArea,
|
|
|
|
|
setTransferArea,
|
|
|
|
|
transferAreas,
|
|
|
|
|
attendants,
|
|
|
|
|
transferAttendant,
|
|
|
|
|
setTransferAttendant,
|
|
|
|
|
transferNote,
|
|
|
|
|
setTransferNote,
|
|
|
|
|
submitTransfer,
|
|
|
|
|
} = useChat();
|
|
|
|
|
|
|
|
|
|
const gridTemplateColumns = isMobile
|
|
|
|
|
? '1fr'
|
|
|
|
|
: isWideDesktop
|
|
|
|
|
? 'minmax(260px, 320px) minmax(0, 1.6fr) minmax(280px, 320px)'
|
|
|
|
|
: isDesktop || isTablet
|
|
|
|
|
? 'minmax(260px, 320px) minmax(0, 1fr)'
|
|
|
|
|
: '1fr';
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<main style={{ minHeight: '100vh', padding: '1.5rem' }}>
|
|
|
|
|
<section
|
|
|
|
|
style={{
|
|
|
|
|
width: 'min(1680px, calc(100vw - 3rem))',
|
|
|
|
|
margin: '0 auto',
|
|
|
|
|
background: 'var(--color-surface-strong)',
|
|
|
|
|
borderRadius: '32px',
|
|
|
|
|
boxShadow: 'var(--shadow-lg)',
|
|
|
|
|
padding: '1.5rem',
|
|
|
|
|
display: 'grid',
|
|
|
|
|
gap: '1.25rem',
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<header
|
|
|
|
|
style={{
|
|
|
|
|
display: 'grid',
|
|
|
|
|
gridTemplateColumns: isMobile ? '1fr' : 'auto 1fr auto',
|
|
|
|
|
gap: '1rem',
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<BrandMark />
|
|
|
|
|
<div
|
|
|
|
|
style={{
|
|
|
|
|
justifySelf: isMobile ? 'stretch' : 'center',
|
|
|
|
|
padding: '0.85rem 1rem',
|
|
|
|
|
borderRadius: '18px',
|
|
|
|
|
background: 'rgba(0, 49, 80, 0.06)',
|
|
|
|
|
color: 'var(--color-primary)',
|
|
|
|
|
fontWeight: 700,
|
|
|
|
|
textAlign: 'center',
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
Atendimento em tempo real
|
|
|
|
|
</div>
|
|
|
|
|
<Link
|
|
|
|
|
to="/home"
|
|
|
|
|
style={{
|
|
|
|
|
justifySelf: isMobile ? 'stretch' : 'end',
|
|
|
|
|
borderRadius: '16px',
|
|
|
|
|
padding: '0.85rem 1rem',
|
|
|
|
|
background: 'var(--color-primary)',
|
|
|
|
|
color: '#fff',
|
|
|
|
|
fontWeight: 700,
|
|
|
|
|
textAlign: 'center',
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
Voltar para home
|
|
|
|
|
</Link>
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
<section
|
|
|
|
|
style={{
|
|
|
|
|
display: 'grid',
|
|
|
|
|
gridTemplateColumns,
|
|
|
|
|
gap: '1rem',
|
|
|
|
|
alignItems: 'start',
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<ChatConversationList
|
|
|
|
|
contacts={contacts}
|
|
|
|
|
activeContactId={activeContactId}
|
|
|
|
|
onSelectContact={setActiveContactId}
|
|
|
|
|
isMobile={isMobile}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<div style={{ display: 'grid', gap: '1rem', minWidth: 0 }}>
|
|
|
|
|
<ChatWindow
|
|
|
|
|
contact={activeContact}
|
|
|
|
|
messages={messages}
|
|
|
|
|
selectedArea={selectedArea}
|
|
|
|
|
setSelectedArea={setSelectedArea}
|
|
|
|
|
draft={draft}
|
|
|
|
|
setDraft={setDraft}
|
2026-05-18 17:34:23 -03:00
|
|
|
attachedFile={attachedFile}
|
|
|
|
|
onAttachFile={attachFile}
|
|
|
|
|
onRemoveAttachedFile={removeAttachedFile}
|
|
|
|
|
onLoadMedia={hydrateMessageMedia}
|
2026-03-19 18:22:18 -03:00
|
|
|
onSend={sendMessage}
|
|
|
|
|
onToggleTransfer={() => setIsTransferOpen((current) => !current)}
|
|
|
|
|
isReplying={isReplying}
|
|
|
|
|
isMobile={isMobile}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
style={{
|
|
|
|
|
display: 'grid',
|
|
|
|
|
gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))',
|
|
|
|
|
gap: '0.75rem',
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{quickReplies.map((reply) => (
|
|
|
|
|
<button
|
|
|
|
|
key={reply}
|
|
|
|
|
type="button"
|
|
|
|
|
onClick={() => setDraft(reply)}
|
|
|
|
|
style={{
|
|
|
|
|
border: '1px solid var(--color-border)',
|
|
|
|
|
borderRadius: '18px',
|
|
|
|
|
padding: '0.85rem 1rem',
|
|
|
|
|
background: '#fff',
|
|
|
|
|
color: 'var(--color-primary)',
|
|
|
|
|
fontWeight: 600,
|
|
|
|
|
textAlign: 'left',
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{reply}
|
|
|
|
|
</button>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{isWideDesktop ? (
|
|
|
|
|
<ChatTransferPanel
|
|
|
|
|
isOpen={isTransferOpen}
|
|
|
|
|
transferArea={transferArea}
|
|
|
|
|
setTransferArea={setTransferArea}
|
|
|
|
|
transferAreas={transferAreas}
|
|
|
|
|
attendants={attendants}
|
|
|
|
|
transferAttendant={transferAttendant}
|
|
|
|
|
setTransferAttendant={setTransferAttendant}
|
|
|
|
|
transferNote={transferNote}
|
|
|
|
|
setTransferNote={setTransferNote}
|
|
|
|
|
onSubmit={submitTransfer}
|
|
|
|
|
onClose={() => setIsTransferOpen(false)}
|
|
|
|
|
/>
|
|
|
|
|
) : null}
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
{!isWideDesktop ? (
|
|
|
|
|
<ChatTransferPanel
|
|
|
|
|
isOpen={isTransferOpen}
|
|
|
|
|
transferArea={transferArea}
|
|
|
|
|
setTransferArea={setTransferArea}
|
|
|
|
|
transferAreas={transferAreas}
|
|
|
|
|
attendants={attendants}
|
|
|
|
|
transferAttendant={transferAttendant}
|
|
|
|
|
setTransferAttendant={setTransferAttendant}
|
|
|
|
|
transferNote={transferNote}
|
|
|
|
|
setTransferNote={setTransferNote}
|
|
|
|
|
onSubmit={submitTransfer}
|
|
|
|
|
onClose={() => setIsTransferOpen(false)}
|
|
|
|
|
/>
|
|
|
|
|
) : null}
|
|
|
|
|
</section>
|
|
|
|
|
</main>
|
|
|
|
|
);
|
|
|
|
|
}
|