FEAT: Atualizado abertura de atendimento com agenda e etiqueta

This commit is contained in:
Rafael Alves Lopes 2026-05-26 11:35:13 -03:00
parent 7a7179bb5d
commit dcad70b708

View File

@ -6,7 +6,6 @@ import { API_BASE_URL } from '../../../shared/services/apiConfig';
import { getCurrentUser } from '../../auth/services/sessionService';
import { listContactProfiles, saveContactProfile } from '../../chat/services/contactProfileService';
import { getAccessOptions } from '../../management/services/adminAccessService';
import { RecentContactsList } from '../components/RecentContactsList';
import { attendanceChannels } from '../services/attendanceMocks';
const countryOptions = [
@ -253,7 +252,7 @@ export function NewAttendancePage({ embedded = false }) {
}
return contacts.filter((contact) => {
const haystack = `${contact.name} ${contact.phone} ${contact.rawPhone}`.toLowerCase();
const haystack = `${contact.name} ${contact.phone} ${contact.rawPhone} ${contact.company} ${contact.note}`.toLowerCase();
return haystack.includes(search);
});
}, [contacts, search]);
@ -269,9 +268,9 @@ export function NewAttendancePage({ embedded = false }) {
const gridTemplateColumns = isMobile
? '1fr'
: isWideDesktop
? 'minmax(300px, 360px) minmax(0, 1fr)'
? 'minmax(0, 1fr) minmax(340px, 0.8fr)'
: isDesktop || isTablet
? 'minmax(280px, 340px) minmax(0, 1fr)'
? 'minmax(0, 1fr) minmax(320px, 0.85fr)'
: '1fr';
function selectContact(contactId) {
@ -406,12 +405,6 @@ export function NewAttendancePage({ embedded = false }) {
alignItems: 'start',
}}
>
<RecentContactsList
contacts={filteredContacts}
activeContactId={selectedContactId}
onSelectContact={selectContact}
/>
<section
style={{
background: '#fff',
@ -430,20 +423,6 @@ export function NewAttendancePage({ embedded = false }) {
</p>
</div>
<input
type="search"
value={searchValue}
onChange={(event) => setSearchValue(event.target.value)}
placeholder="Buscar contato salvo por nome ou número"
style={{
border: '1px solid var(--color-border)',
borderRadius: '18px',
padding: '0.95rem 1rem',
background: '#fff',
outline: 'none',
}}
/>
<div
style={{
display: 'grid',
@ -565,12 +544,12 @@ export function NewAttendancePage({ embedded = false }) {
}}
>
<label style={{ display: 'grid', gap: '0.45rem' }}>
<span style={{ fontWeight: 600 }}>Tag</span>
<span style={{ fontWeight: 600 }}>Etiqueta de identificação</span>
<input
type="text"
value={form.company}
onChange={(event) => setForm((current) => ({ ...current, company: event.target.value }))}
placeholder="Tag ou conta vinculada"
placeholder="Ex: Departamento, vaga ou conta vinculada"
style={{
border: '1px solid var(--color-border)',
borderRadius: '18px',
@ -768,7 +747,7 @@ export function NewAttendancePage({ embedded = false }) {
Número: {buildInternationalPhone(form.phone, selectedCountryId) ? `+${buildInternationalPhone(form.phone, selectedCountryId)}` : 'Não informado'}
</span>
<span style={{ color: 'rgba(255, 255, 255, 0.74)' }}>
Tag: {form.company || 'Não informada'}
Etiqueta de identificação: {form.company || 'Não informada'}
</span>
<span style={{ color: 'rgba(255, 255, 255, 0.74)' }}>
Origem: {selectedContactId ? 'Agenda' : 'Novo contato'}
@ -826,6 +805,127 @@ export function NewAttendancePage({ embedded = false }) {
</article>
</section>
</section>
<aside style={{ display: 'grid', gap: '0.85rem', alignContent: 'start' }}>
<article
style={{
border: '1px solid var(--color-border)',
borderRadius: 24,
padding: '1rem',
background: '#fff',
display: 'grid',
gap: '0.75rem',
}}
>
<div>
<strong style={{ display: 'block' }}>Agenda de contatos</strong>
<span style={{ color: 'var(--color-text-soft)', fontSize: '0.9rem' }}>
Selecione um contato salvo para preencher o atendimento.
</span>
</div>
<input
type="search"
value={searchValue}
onChange={(event) => setSearchValue(event.target.value)}
placeholder="Buscar por nome, telefone ou etiqueta"
style={{
border: '1px solid var(--color-border)',
borderRadius: '16px',
padding: '0.85rem 0.9rem',
background: '#fff',
outline: 'none',
fontWeight: 600,
}}
/>
<div style={{ display: 'grid', gap: '0.45rem', maxHeight: 460, overflowY: 'auto', paddingRight: '0.2rem' }}>
{filteredContacts.map((contact) => {
const isSelected = selectedContactId === contact.id;
return (
<button
key={contact.id}
type="button"
onClick={() => selectContact(contact.id)}
style={{
border: '1px solid',
borderColor: isSelected ? 'rgba(0, 164, 183, 0.36)' : 'var(--color-border)',
borderRadius: 16,
padding: '0.78rem',
background: isSelected ? 'rgba(0, 164, 183, 0.08)' : '#fff',
textAlign: 'left',
display: 'grid',
gap: '0.25rem',
cursor: 'pointer',
}}
>
<strong style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
{contact.name}
</strong>
<span style={{ color: 'var(--color-text-soft)', fontSize: '0.88rem' }}>
+{contact.rawPhone || normalizePhone(contact.phone)}
</span>
{contact.company ? (
<span
style={{
width: 'fit-content',
borderRadius: 999,
padding: '0.16rem 0.48rem',
background: 'rgba(0,49,80,0.06)',
color: 'var(--color-text-soft)',
fontSize: '0.76rem',
fontWeight: 800,
}}
>
{contact.company}
</span>
) : null}
</button>
);
})}
{!filteredContacts.length ? (
<span style={{ color: 'var(--color-text-soft)', fontWeight: 700 }}>
Nenhum contato encontrado na agenda.
</span>
) : null}
</div>
{selectedContactId ? (
<button
type="button"
onClick={clearSelection}
style={{
border: '1px solid var(--color-border)',
borderRadius: 14,
padding: '0.75rem',
background: '#fff',
color: 'var(--color-primary)',
fontWeight: 800,
}}
>
Limpar contato selecionado
</button>
) : null}
</article>
<article
style={{
border: '1px solid rgba(0, 164, 183, 0.24)',
borderRadius: 24,
padding: '1rem',
background: 'rgba(0, 164, 183, 0.06)',
color: 'var(--color-text-soft)',
lineHeight: 1.45,
fontWeight: 700,
}}
>
{selectedContactId
? 'Contato carregado da agenda. Você ainda pode ajustar nome, etiqueta e observação antes de iniciar.'
: 'Você também pode digitar um novo número manualmente no formulário.'}
</article>
</aside>
</section>
</section>
);