Some checks are pending
Deploy Dev / deploy (push) Waiting to run
- Ajustado border Radius de todos componentes de 28 para 20px - Criado modal para quando for criado um novo template
198 lines
5.6 KiB
JavaScript
198 lines
5.6 KiB
JavaScript
import { useEffect, useState } from 'react';
|
|
import { getCurrentUser } from '../../auth/services/sessionService';
|
|
import { getContactProfile, saveContactProfile } from '../services/contactProfileService';
|
|
|
|
function getUserId(user) {
|
|
const value = user?.databaseId || user?.id;
|
|
const numeric = Number(value);
|
|
return Number.isFinite(numeric) ? numeric : null;
|
|
}
|
|
|
|
function formatPhone(phone) {
|
|
const digits = String(phone || '').replace(/\D/g, '');
|
|
if (!digits) return 'Telefone não disponível';
|
|
|
|
if (digits.startsWith('55') && digits.length === 13) {
|
|
return `+55 (${digits.slice(2, 4)}) ${digits.slice(4, 9)}-${digits.slice(9)}`;
|
|
}
|
|
|
|
if (digits.startsWith('55') && digits.length === 12) {
|
|
return `+55 (${digits.slice(2, 4)}) ${digits.slice(4, 8)}-${digits.slice(8)}`;
|
|
}
|
|
|
|
if (digits.length === 11) {
|
|
return `(${digits.slice(0, 2)}) ${digits.slice(2, 7)}-${digits.slice(7)}`;
|
|
}
|
|
|
|
if (digits.length === 10) {
|
|
return `(${digits.slice(0, 2)}) ${digits.slice(2, 6)}-${digits.slice(6)}`;
|
|
}
|
|
|
|
return phone;
|
|
}
|
|
|
|
export function ContactProfilePanel({ isOpen, contact, onClose, onSaved }) {
|
|
const [profile, setProfile] = useState(null);
|
|
const [form, setForm] = useState({ name: '', company: '', note: '' });
|
|
const [isSaving, setIsSaving] = useState(false);
|
|
const [error, setError] = useState('');
|
|
|
|
useEffect(() => {
|
|
let isMounted = true;
|
|
|
|
async function loadProfile() {
|
|
if (!isOpen || !contact?.id) return;
|
|
try {
|
|
const data = await getContactProfile(contact.id);
|
|
if (!isMounted) return;
|
|
setProfile(data);
|
|
setForm({
|
|
name: data.name || contact.name || '',
|
|
company: data.company || '',
|
|
note: data.note || '',
|
|
});
|
|
setError('');
|
|
} catch (err) {
|
|
if (isMounted) setError(err.message);
|
|
}
|
|
}
|
|
|
|
loadProfile();
|
|
return () => {
|
|
isMounted = false;
|
|
};
|
|
}, [isOpen, contact?.id]);
|
|
|
|
if (!isOpen) {
|
|
return null;
|
|
}
|
|
|
|
const fieldStyle = {
|
|
width: '100%',
|
|
border: '1px solid var(--color-border)',
|
|
borderRadius: '12px',
|
|
padding: '0.9rem 1rem',
|
|
background: '#fff',
|
|
outline: 'none',
|
|
};
|
|
|
|
async function submit() {
|
|
if (!contact?.id) return;
|
|
setIsSaving(true);
|
|
try {
|
|
const userId = getUserId(getCurrentUser());
|
|
const saved = await saveContactProfile(contact.id, {
|
|
phone: profile?.phone || contact?.contactProfile?.phone || '',
|
|
name: form.name,
|
|
company: form.company,
|
|
note: form.note,
|
|
userId,
|
|
});
|
|
setProfile(saved);
|
|
onSaved?.(contact.id, saved);
|
|
setError('');
|
|
} catch (err) {
|
|
setError(err.message);
|
|
} finally {
|
|
setIsSaving(false);
|
|
}
|
|
}
|
|
|
|
return (
|
|
<aside
|
|
style={{
|
|
background: '#fff',
|
|
border: '1px solid var(--color-border)',
|
|
borderRadius: '20px',
|
|
padding: '1.25rem',
|
|
display: 'grid',
|
|
gap: '1rem',
|
|
}}
|
|
>
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', gap: '1rem' }}>
|
|
<div>
|
|
<strong style={{ display: 'block', fontSize: '1.06rem' }}>Contato do cliente</strong>
|
|
<span style={{ color: 'var(--color-text-soft)' }}>
|
|
Atualize os dados de agenda deste atendimento.
|
|
</span>
|
|
</div>
|
|
<button
|
|
type="button"
|
|
onClick={onClose}
|
|
style={{
|
|
border: 'none',
|
|
background: 'transparent',
|
|
color: 'var(--color-text-soft)',
|
|
fontWeight: 700,
|
|
}}
|
|
>
|
|
Fechar
|
|
</button>
|
|
</div>
|
|
|
|
<label style={{ display: 'grid', gap: '0.45rem' }}>
|
|
<span style={{ fontWeight: 600 }}>Nome</span>
|
|
<input
|
|
value={form.name}
|
|
onChange={(event) => setForm((current) => ({ ...current, name: event.target.value }))}
|
|
style={fieldStyle}
|
|
/>
|
|
</label>
|
|
|
|
<label style={{ display: 'grid', gap: '0.45rem' }}>
|
|
<span style={{ fontWeight: 600 }}>Etiqueta de identificação</span>
|
|
<input
|
|
value={form.company}
|
|
onChange={(event) => setForm((current) => ({ ...current, company: event.target.value }))}
|
|
placeholder="Ex: Departamento, vaga ou conta vinculada"
|
|
style={fieldStyle}
|
|
/>
|
|
</label>
|
|
|
|
<label style={{ display: 'grid', gap: '0.45rem' }}>
|
|
<span style={{ fontWeight: 600 }}>Telefone</span>
|
|
<input
|
|
value={formatPhone(profile?.phone || contact?.contactProfile?.phone)}
|
|
disabled
|
|
style={{
|
|
...fieldStyle,
|
|
background: 'rgba(0, 49, 80, 0.04)',
|
|
color: 'var(--color-text-soft)',
|
|
fontWeight: 700,
|
|
}}
|
|
/>
|
|
</label>
|
|
|
|
<label style={{ display: 'grid', gap: '0.45rem' }}>
|
|
<span style={{ fontWeight: 600 }}>Observação</span>
|
|
<textarea
|
|
rows={5}
|
|
value={form.note}
|
|
onChange={(event) => setForm((current) => ({ ...current, note: event.target.value }))}
|
|
placeholder="Informações relevantes do cliente."
|
|
style={{ ...fieldStyle, resize: 'vertical' }}
|
|
/>
|
|
</label>
|
|
|
|
{error ? <span style={{ color: '#b42318', fontWeight: 700 }}>{error}</span> : null}
|
|
|
|
<button
|
|
type="button"
|
|
onClick={submit}
|
|
disabled={isSaving}
|
|
style={{
|
|
border: 'none',
|
|
borderRadius: '12px',
|
|
padding: '0.95rem 1rem',
|
|
background: 'linear-gradient(135deg, var(--color-primary), #0b5a86)',
|
|
color: '#fff',
|
|
fontWeight: 700,
|
|
opacity: isSaving ? 0.65 : 1,
|
|
}}
|
|
>
|
|
{isSaving ? 'Salvando...' : 'Salvar contato'}
|
|
</button>
|
|
</aside>
|
|
);
|
|
}
|