FEAT: Ajustado espaço delimitador da tela de chat e conversas ativas
This commit is contained in:
parent
bff4e18094
commit
7dc07c2a80
@ -23,6 +23,29 @@ function ChannelBadge({ channel }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function PresenceDot({ status }) {
|
||||||
|
const color =
|
||||||
|
status === 'online'
|
||||||
|
? '#16a34a'
|
||||||
|
: status === 'away'
|
||||||
|
? '#e5a22a'
|
||||||
|
: '#dc2626';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
style={{
|
||||||
|
width: 10,
|
||||||
|
height: 10,
|
||||||
|
borderRadius: 999,
|
||||||
|
background: color,
|
||||||
|
boxShadow: `0 0 0 3px ${color}22`,
|
||||||
|
flex: '0 0 auto',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function ChatConversationList({
|
export function ChatConversationList({
|
||||||
contacts,
|
contacts,
|
||||||
activeContactId,
|
activeContactId,
|
||||||
@ -37,7 +60,10 @@ export function ChatConversationList({
|
|||||||
borderRadius: '28px',
|
borderRadius: '28px',
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
|
gridTemplateRows: 'auto minmax(0, 1fr)',
|
||||||
gap: '0.85rem',
|
gap: '0.85rem',
|
||||||
|
height: isMobile ? 'auto' : 'min(760px, calc(100vh - 190px))',
|
||||||
|
minHeight: 0,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
@ -52,6 +78,9 @@ export function ChatConversationList({
|
|||||||
display: 'grid',
|
display: 'grid',
|
||||||
gap: '0.75rem',
|
gap: '0.75rem',
|
||||||
gridTemplateColumns: isMobile ? '1fr' : '1fr',
|
gridTemplateColumns: isMobile ? '1fr' : '1fr',
|
||||||
|
overflowY: 'auto',
|
||||||
|
minHeight: 0,
|
||||||
|
paddingRight: '0.15rem',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{contacts.map((contact) => {
|
{contacts.map((contact) => {
|
||||||
@ -74,7 +103,12 @@ export function ChatConversationList({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', gap: '1rem' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', gap: '1rem' }}>
|
||||||
<strong>{contact.name}</strong>
|
<span style={{ display: 'inline-flex', alignItems: 'center', gap: '0.5rem', minWidth: 0 }}>
|
||||||
|
<PresenceDot status={contact.status} />
|
||||||
|
<strong style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
|
||||||
|
{contact.name}
|
||||||
|
</strong>
|
||||||
|
</span>
|
||||||
<span style={{ fontSize: '0.82rem', color: 'var(--color-text-soft)' }}>
|
<span style={{ fontSize: '0.82rem', color: 'var(--color-text-soft)' }}>
|
||||||
{contact.time}
|
{contact.time}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@ -179,6 +179,40 @@ function AttachmentPreview({ file, onRemove }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ContactPresence({ contact }) {
|
||||||
|
const status = contact.status || 'offline';
|
||||||
|
const color =
|
||||||
|
status === 'online'
|
||||||
|
? '#16a34a'
|
||||||
|
: status === 'away'
|
||||||
|
? '#e5a22a'
|
||||||
|
: '#dc2626';
|
||||||
|
const label = status === 'online' ? 'Online agora' : contact.lastSeen || 'Offline';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
display: 'inline-flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: '0.5rem',
|
||||||
|
color: 'var(--color-text-soft)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
style={{
|
||||||
|
width: 10,
|
||||||
|
height: 10,
|
||||||
|
borderRadius: 999,
|
||||||
|
background: color,
|
||||||
|
boxShadow: `0 0 0 3px ${color}22`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{label}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function ChatWindow({
|
export function ChatWindow({
|
||||||
contact,
|
contact,
|
||||||
messages,
|
messages,
|
||||||
@ -217,8 +251,10 @@ export function ChatWindow({
|
|||||||
borderRadius: '28px',
|
borderRadius: '28px',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
gridTemplateRows: 'auto 1fr auto',
|
gridTemplateRows: 'auto minmax(0, 1fr) auto',
|
||||||
minHeight: 680,
|
height: isMobile ? 'auto' : 'min(760px, calc(100vh - 190px))',
|
||||||
|
minHeight: isMobile ? 640 : 0,
|
||||||
|
minWidth: 0,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<header
|
<header
|
||||||
@ -233,9 +269,7 @@ export function ChatWindow({
|
|||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<strong style={{ display: 'block', fontSize: '1.15rem' }}>{contact.name}</strong>
|
<strong style={{ display: 'block', fontSize: '1.15rem' }}>{contact.name}</strong>
|
||||||
<span style={{ color: 'var(--color-text-soft)' }}>
|
<ContactPresence contact={contact} />
|
||||||
{contact.status === 'online' ? 'Online' : 'Offline'} • {contact.lastSeen}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@ -286,6 +320,7 @@ export function ChatWindow({
|
|||||||
gap: '0.9rem',
|
gap: '0.9rem',
|
||||||
alignContent: 'start',
|
alignContent: 'start',
|
||||||
overflowY: 'auto',
|
overflowY: 'auto',
|
||||||
|
minHeight: 0,
|
||||||
background:
|
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))',
|
'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))',
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -40,13 +40,20 @@ function getPreviewFromMessage(message) {
|
|||||||
|
|
||||||
function normalizeChat(chat) {
|
function normalizeChat(chat) {
|
||||||
const id = getSerializedId(chat.id);
|
const id = getSerializedId(chat.id);
|
||||||
|
const lastActivitySeconds = chat.timestamp ? Math.floor(Date.now() / 1000) - chat.timestamp : null;
|
||||||
|
const isRecentlyActive = lastActivitySeconds !== null && lastActivitySeconds < 300;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
name: getContactName(chat),
|
name: getContactName(chat),
|
||||||
channel: 'WhatsApp',
|
channel: 'WhatsApp',
|
||||||
status: 'online',
|
status: isRecentlyActive ? 'online' : 'away',
|
||||||
area: chat.assignment?.area_id ? String(chat.assignment.area_id) : 'Suporte',
|
area: chat.assignment?.area_id ? String(chat.assignment.area_id) : 'Suporte',
|
||||||
lastSeen: chat.timestamp ? `Visto as ${formatTime(chat.timestamp)}` : 'Online agora',
|
lastSeen: isRecentlyActive
|
||||||
|
? 'Online agora'
|
||||||
|
: chat.timestamp
|
||||||
|
? `Visto as ${formatTime(chat.timestamp)}`
|
||||||
|
: 'Sem atividade recente',
|
||||||
preview: chat.preview || chat.lastMessage?.body || '',
|
preview: chat.preview || chat.lastMessage?.body || '',
|
||||||
time: formatTime(chat.timestamp) || 'Agora',
|
time: formatTime(chat.timestamp) || 'Agora',
|
||||||
unread: chat.unreadCount || 0,
|
unread: chat.unreadCount || 0,
|
||||||
|
|||||||
@ -103,7 +103,7 @@ export function ChatPage() {
|
|||||||
display: 'grid',
|
display: 'grid',
|
||||||
gridTemplateColumns,
|
gridTemplateColumns,
|
||||||
gap: '1rem',
|
gap: '1rem',
|
||||||
alignItems: 'start',
|
alignItems: 'stretch',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ChatConversationList
|
<ChatConversationList
|
||||||
@ -113,7 +113,7 @@ export function ChatPage() {
|
|||||||
isMobile={isMobile}
|
isMobile={isMobile}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div style={{ display: 'grid', gap: '1rem', minWidth: 0 }}>
|
<div style={{ display: 'grid', gap: '1rem', minWidth: 0, alignContent: 'start' }}>
|
||||||
<ChatWindow
|
<ChatWindow
|
||||||
contact={activeContact}
|
contact={activeContact}
|
||||||
messages={messages}
|
messages={messages}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user