From 821ae591d4dcc7a0161acaa042fa51bb079be1d8 Mon Sep 17 00:00:00 2001 From: VPS 4 Builder Date: Thu, 2 Jul 2026 00:42:34 +0200 Subject: [PATCH] =?UTF-8?q?style(newwhats):=20tema=20branco/profissional?= =?UTF-8?q?=20na=20Secret=C3=A1ria=20(/wa-secretaria)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Converte a SecretariaView do dark para o tema claro do scoreodonto (bg-gray-50/white, text-gray-*, border-gray-*), preservando botões brand, backdrops de modal e acentos. Co-Authored-By: Claude Opus 4.8 --- frontend/views/newwhats/SecretariaView.tsx | 350 ++++++++++----------- 1 file changed, 175 insertions(+), 175 deletions(-) diff --git a/frontend/views/newwhats/SecretariaView.tsx b/frontend/views/newwhats/SecretariaView.tsx index 36842d9..2b54bfc 100644 --- a/frontend/views/newwhats/SecretariaView.tsx +++ b/frontend/views/newwhats/SecretariaView.tsx @@ -27,12 +27,12 @@ const NAV_ITEMS: { id: NavTab; icon: React.ElementType; label: string }[] = [ function ThinNav({ active, onChange, onHelp, onBack }: { active: NavTab; onChange: (t: NavTab) => void; onHelp: () => void; onBack?: () => void }) { return ( -
+
{onBack && ( @@ -44,8 +44,8 @@ function ThinNav({ active, onChange, onHelp, onBack }: { active: NavTab; onChang onClick={() => onChange(id)} className={`w-10 h-10 rounded-xl flex items-center justify-center transition-all ${ active === id - ? 'bg-brand-500/20 text-brand-400' - : 'text-slate-600 hover:text-slate-400 hover:bg-white/5' + ? 'bg-brand-500/20 text-brand-600' + : 'text-gray-500 hover:text-gray-600 hover:bg-gray-50' }`} > @@ -58,7 +58,7 @@ function ThinNav({ active, onChange, onHelp, onBack }: { active: NavTab; onChang @@ -84,15 +84,15 @@ function AgentDropdown({
@@ -102,17 +102,17 @@ function AgentDropdown({ animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -6 }} transition={{ duration: 0.12 }} - className="absolute left-2 right-2 top-full mt-1 bg-[#12151e] border border-white/10 rounded-xl shadow-2xl z-50 overflow-hidden" + className="absolute left-2 right-2 top-full mt-1 bg-gray-50 border border-gray-200 rounded-xl shadow-2xl z-50 overflow-hidden" > {agents.map((a) => ( ))} @@ -126,7 +126,7 @@ function AgentDropdown({ const STATUS_META = { active: { label: 'Ativa', color: 'text-green-400', dot: 'bg-green-400' }, - closed: { label: 'Encerrada', color: 'text-slate-500', dot: 'bg-slate-600' }, + closed: { label: 'Encerrada', color: 'text-gray-500', dot: 'bg-gray-400' }, escalated: { label: 'Escalada', color: 'text-yellow-400', dot: 'bg-yellow-400' }, } @@ -144,14 +144,14 @@ function ConversationList({ return (
- + Sessões de Teste @@ -159,10 +159,10 @@ function ConversationList({ {loadingConversations ? (
- +
) : conversations.length === 0 ? ( -

+

{selectedAgent ? 'Nenhuma sessão. Clique em + para iniciar.' : 'Selecione um agente.'}

) : ( @@ -173,28 +173,28 @@ function ConversationList({ return (
onSelect(c)} > -
- +
+
-

+

{c.contact_name}

{m.label} - + {format(parseISO(c.updated_at), "dd/MM HH:mm", { locale: ptBR })}
@@ -292,7 +292,7 @@ function BrainPanel({ return (
- + Nós do Cérebro
@@ -300,7 +300,7 @@ function BrainPanel({ onClick={() => setShowAddMenu((o) => !o)} disabled={!selectedAgent} title="Adicionar nó" - className="w-6 h-6 rounded-lg bg-white/5 hover:bg-brand-500/20 text-slate-500 hover:text-brand-400 flex items-center justify-center transition-all disabled:opacity-30" + className="w-6 h-6 rounded-lg bg-gray-50 hover:bg-brand-500/20 text-gray-500 hover:text-brand-600 flex items-center justify-center transition-all disabled:opacity-30" > @@ -310,14 +310,14 @@ function BrainPanel({ initial={{ opacity: 0, y: -4 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -4 }} - className="absolute right-0 top-full mt-1 bg-[#12151e] border border-white/10 rounded-xl shadow-2xl z-50 overflow-hidden w-40" + className="absolute right-0 top-full mt-1 bg-gray-50 border border-gray-200 rounded-xl shadow-2xl z-50 overflow-hidden w-40" > {(Object.keys(NODE_META) as BrainNodeType[]).map((type) => { const m = NODE_META[type] const Icon = m.icon return (
@@ -381,17 +381,17 @@ function BrainPanel({ onClick={() => onOpen(node)} title="Abrir editor" className={`w-5 h-5 flex items-center justify-center transition-colors ${ - isOpen ? 'text-brand-400' : 'text-slate-600 hover:text-brand-400' + isOpen ? 'text-brand-600' : 'text-gray-500 hover:text-brand-600' }`} > {/* Toggle active */} {isEditing ? ( @@ -399,16 +399,16 @@ function BrainPanel({ - ) : ( <> - - @@ -424,7 +424,7 @@ function BrainPanel({ className={`flex items-center gap-1.5 px-2 py-1 rounded-lg text-[10px] font-semibold transition-all ${ hasModel ? 'bg-brand-500/15 text-brand-300 border border-brand-500/20' - : 'bg-white/5 text-slate-600 border border-white/5 hover:text-slate-400' + : 'bg-gray-50 text-gray-500 border border-gray-100 hover:text-gray-600' }`} > @@ -438,21 +438,21 @@ function BrainPanel({ initial={{ opacity: 0, y: -4 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -4 }} - className="absolute left-3 top-full mt-1 bg-[#12151e] border border-white/10 rounded-xl shadow-2xl z-50 overflow-hidden w-56" + className="absolute left-3 top-full mt-1 bg-gray-50 border border-gray-200 rounded-xl shadow-2xl z-50 overflow-hidden w-56" > {/* Opção: usar padrão do agente */} -
+
{providerModels.map((mdl) => ( @@ -481,10 +481,10 @@ function BrainPanel({ value={editContent} onChange={(e) => setEditContent(e.target.value)} rows={5} - className="w-full text-xs text-slate-400 bg-black/20 border-t border-white/5 px-3 py-2 focus:outline-none focus:bg-black/30 resize-none font-mono leading-relaxed" + className="w-full text-xs text-gray-600 bg-gray-50 border-t border-gray-100 px-3 py-2 focus:outline-none focus:bg-gray-50 resize-none font-mono leading-relaxed" /> ) : ( -

+

{node.content}

)} @@ -502,7 +502,7 @@ function BrainPanel({ const SLOT_STATUS: Record = { available: { label: 'Disponível', color: 'text-green-400', dot: 'bg-green-400' }, booked: { label: 'Agendado', color: 'text-blue-400', dot: 'bg-blue-400' }, - cancelled: { label: 'Cancelado', color: 'text-slate-500', dot: 'bg-slate-600' }, + cancelled: { label: 'Cancelado', color: 'text-gray-500', dot: 'bg-gray-400' }, } function CalendarPanel({ @@ -524,9 +524,9 @@ function CalendarPanel({ return (
- Agenda + Agenda @@ -534,13 +534,13 @@ function CalendarPanel({ {loading ? (
- +
) : (
{Object.entries(grouped).map(([date, daySlots]) => (
-

+

{format(parseISO(date), "EEE, dd/MM", { locale: ptBR })}

@@ -548,14 +548,14 @@ function CalendarPanel({ const m = SLOT_STATUS[slot.status] return (
-

{slot.title}

+

{slot.title}

- - + + {slot.time_start.slice(0, 5)}–{slot.time_end.slice(0, 5)} {slot.attendee_name && ( @@ -567,7 +567,7 @@ function CalendarPanel({ {slot.status === 'available' && ( @@ -575,13 +575,13 @@ function CalendarPanel({ {slot.status === 'booked' && ( )} @@ -619,43 +619,43 @@ function AgentsPanel({ return (
- Agentes + Agentes
{loadingAgents ? ( -
+
) : (
{agents.map((a) => { const isEditing = editingId === a.id const isSelected = selected?.id === a.id return ( -
+
- +
onSelect(a)}> -

{a.name}

-

{a.provider} / {a.model}

+

{a.name}

+

{a.provider} / {a.model}

- -
{isEditing && ( -
+
{[ { key: 'name', label: 'Nome', type: 'text' }, { key: 'description', label: 'Descrição', type: 'text' }, @@ -665,23 +665,23 @@ function AgentsPanel({ { key: 'context_window', label: 'Context Window', type: 'number' }, ].map(({ key, label, type }) => (
-

{label}

+

{label}

setForm((f) => ({ ...f, [key]: type === 'number' ? parseFloat(e.target.value) : e.target.value }))} - className="w-full text-xs bg-black/30 text-white border border-white/10 rounded-lg px-2 py-1.5 focus:outline-none focus:border-brand-500/40" + className="w-full text-xs bg-gray-50 text-gray-800 border border-gray-200 rounded-lg px-2 py-1.5 focus:outline-none focus:border-brand-500/40" />
))}
@@ -700,7 +700,7 @@ function AgentsPanel({ // ─── Numbers Panel ──────────────────────────────────────────────────────────── const ROLE_META: Record = { - secretary_virtual: { label: 'Secretária Virtual', icon: Sparkles, color: 'text-brand-400', bg: 'bg-brand-500/15' }, + secretary_virtual: { label: 'Secretária Virtual', icon: Sparkles, color: 'text-brand-600', bg: 'bg-brand-500/15' }, clinic: { label: 'Clínica / Empresa', icon: Building2, color: 'text-blue-400', bg: 'bg-blue-500/10' }, doctor: { label: 'Médico / Dr.', icon: Stethoscope, color: 'text-green-400', bg: 'bg-green-500/10' }, specialist: { label: 'Especialista', icon: Star, color: 'text-purple-400', bg: 'bg-purple-500/10' }, @@ -761,31 +761,31 @@ function NumbersPanel({ const statusDot = (status: string) => { if (status === 'CONNECTED') return 'bg-green-400' if (status === 'CONNECTING') return 'bg-yellow-400 animate-pulse' - return 'bg-slate-600' + return 'bg-gray-400' } return (
- Instâncias / Papéis + Instâncias / Papéis
-

+

Atribua um papel a cada instância WhatsApp. A secretária usa isso para saber para qual número enviar consultas internas.

{(loading || loadingInst) ? (
- +
) : instances.length === 0 ? ( -

+

Nenhuma instância WhatsApp encontrada. Crie instâncias na tela principal.

) : ( @@ -801,29 +801,29 @@ function NumbersPanel({
{/* Status dot + ícone */}
-
- +
+
- +
{/* Info */}
-

{inst.name}

+

{inst.name}

{m ? ( {m.label} ) : ( - sem papel atribuído + sem papel atribuído )} - {num?.area && · {num.area}} + {num?.area && · {num.area}}
@@ -833,7 +833,7 @@ function NumbersPanel({ -
+
)} {ROLE_OPTIONS.map((o) => { @@ -867,7 +867,7 @@ function NumbersPanel({ )} {/* Editar detalhes (área, prioridade) */} {num && !isEditing && ( @@ -905,7 +905,7 @@ function NumbersPanel({ @@ -916,23 +916,23 @@ function NumbersPanel({ {/* Inline edit: área + prioridade */} {isEditing && ( -
+
-

Área / Especialidade

+

Área / Especialidade

setEditForm((f) => ({ ...f, area: e.target.value }))} placeholder="Ex: Cardiologia" - className="w-full text-xs bg-black/30 text-white border border-white/10 rounded-lg px-2 py-1.5 focus:outline-none focus:border-brand-500/40" + className="w-full text-xs bg-gray-50 text-gray-800 border border-gray-200 rounded-lg px-2 py-1.5 focus:outline-none focus:border-brand-500/40" />
-

Prioridade fallback

+

Prioridade fallback

setEditForm((f) => ({ ...f, priority: parseInt(e.target.value) || 1 }))} - className="w-full text-xs bg-black/30 text-white border border-white/10 rounded-lg px-2 py-1.5 focus:outline-none focus:border-brand-500/40" + className="w-full text-xs bg-gray-50 text-gray-800 border border-gray-200 rounded-lg px-2 py-1.5 focus:outline-none focus:border-brand-500/40" />
@@ -1010,7 +1010,7 @@ function NodeEditorPanel({ return (
{/* Header */} -
+
@@ -1018,7 +1018,7 @@ function NodeEditorPanel({ { setTitle(e.target.value); setDirty(true) }} - className="flex-1 text-sm font-bold bg-transparent text-white focus:outline-none border-b border-transparent focus:border-white/20 transition-colors truncate" + className="flex-1 text-sm font-bold bg-transparent text-gray-800 focus:outline-none border-b border-transparent focus:border-gray-300 transition-colors truncate" /> {m.label} @@ -1031,8 +1031,8 @@ function NodeEditorPanel({ title={node.active ? 'Desativar nó' : 'Ativar nó'} className="flex items-center gap-1 px-2 py-1 rounded-lg text-[10px] font-semibold border transition-all" style={node.active - ? { borderColor: 'rgba(99,179,237,0.2)', color: '#63b3ed', background: 'rgba(99,179,237,0.08)' } - : { borderColor: 'rgba(255,255,255,0.05)', color: '#4a5568', background: 'transparent' } + ? { borderColor: 'rgba(37,99,235,0.25)', color: '#2563eb', background: 'rgba(37,99,235,0.06)' } + : { borderColor: 'rgba(0,0,0,0.08)', color: '#6b7280', background: 'transparent' } } > {node.active ? : } @@ -1046,7 +1046,7 @@ function NodeEditorPanel({ className={`flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-bold transition-all ${ dirty ? 'bg-brand-500 hover:bg-brand-600 text-white' - : 'bg-white/5 text-slate-600 cursor-not-allowed' + : 'bg-gray-50 text-gray-500 cursor-not-allowed' }`} > @@ -1056,7 +1056,7 @@ function NodeEditorPanel({ @@ -1064,7 +1064,7 @@ function NodeEditorPanel({ @@ -1073,16 +1073,16 @@ function NodeEditorPanel({ {/* Model picker — apenas para nó persona */} {node.type === 'persona' && ( -
- - Modelo deste nó: +
+ + Modelo deste nó:
-
+
{providerModels.map((mdl) => ( @@ -1130,22 +1130,22 @@ function NodeEditorPanel({ )} {/* Editor */} -
+