diff --git a/docker-compose.yml b/docker-compose.yml index ed83493..969aa52 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -35,6 +35,7 @@ services: - "./backend/.env" environment: - BAILEYS_ENGINE=infinite + - TZ=America/Sao_Paulo - PORT=8018 - NODE_ENV=production # Senha do banco vem do ambiente (.env raiz em DEV; provisionado fora do git em PROD). diff --git a/frontend/components/HorariosConfig.tsx b/frontend/components/HorariosConfig.tsx index ec59eca..198b2cc 100644 --- a/frontend/components/HorariosConfig.tsx +++ b/frontend/components/HorariosConfig.tsx @@ -62,8 +62,9 @@ const GradeSemanal: React.FC<{ faixas: Faixa[]; onChange: (f: Faixa[]) => void; ); }; -export const HorariosConfig: React.FC<{ isOpen: boolean; onClose: () => void; clinicaId?: string }> = ({ isOpen, onClose, clinicaId }) => { - const [aba, setAba] = useState<'clinica' | 'dentistas'>('clinica'); +export const HorariosConfig: React.FC<{ isOpen: boolean; onClose: () => void; clinicaId?: string; initialTab?: 'clinica' | 'dentistas'; soDentista?: boolean }> = ({ isOpen, onClose, clinicaId, initialTab, soDentista }) => { + const [aba, setAba] = useState<'clinica' | 'dentistas'>(initialTab || 'clinica'); + useEffect(() => { if (isOpen && initialTab) setAba(initialTab); }, [isOpen, initialTab]); const [erro, setErro] = useState(null); const [ok, setOk] = useState(null); const [saving, setSaving] = useState(false); @@ -96,11 +97,13 @@ export const HorariosConfig: React.FC<{ isOpen: boolean; onClose: () => void; cl if (!clinicaId) return; try { const d = await req(`/clinica/${clinicaId}/dentistas`); - setDentistas(d.dentistas || []); - const first = (d.dentistas || []).find((x: Dentista) => x.eh_voce) || (d.dentistas || [])[0]; + let list: Dentista[] = d.dentistas || []; + if (soDentista) { const meus = list.filter((x) => x.eh_voce); if (meus.length) list = meus; } // dentista só vê o próprio + setDentistas(list); + const first = list.find((x: Dentista) => x.eh_voce) || list[0]; if (first) setDentSel(first.id); } catch (e: any) { flash(setErro, e.message); } - }, [clinicaId]); + }, [clinicaId, soDentista]); useEffect(() => { if (isOpen) { carregarClinica(); carregarDentistas(); } }, [isOpen, carregarClinica, carregarDentistas]); const carregarFolgas = useCallback((id: string) => { @@ -162,7 +165,7 @@ export const HorariosConfig: React.FC<{ isOpen: boolean; onClose: () => void; cl {/* Tabs */}
- {(['clinica', 'dentistas'] as const).map((t) => ( + {(soDentista ? (['dentistas'] as const) : (['clinica', 'dentistas'] as const)).map((t) => ( + {/* Título + recolher menu (desktop, ao lado). No mobile o AGENDAR e as + ações ficam empilhados abaixo (dentro da gaveta). */} +
{onToggleSidebar && ( )}

AGENDA CLÍNICA

- {(currentRole !== 'paciente' && !souDentista) && ( - - )}
- {/* AGENDAR (desktop, full-width no topo da coluna) */} + {/* AGENDAR (full-width no topo da coluna/gaveta — mobile e desktop) */} {(currentRole !== 'paciente' && !souDentista) && ( - )} - {/* ícones de ação — mesmo tamanho, distribuídos horizontalmente */} -
+ {/* Ações — mobile: empilhadas, ícone + nome, largura cheia; desktop: fileira de ícones */} +
{(currentRole !== 'paciente') && ( - )} {(currentRole === 'admin' || currentRole === 'donoclinica' || currentRole === 'donoconsultorio') && ( )} - {(currentRole === 'admin' || currentRole === 'donoclinica') && ( - )} {souDentista && ( - + )} + {souDentista && ( + )} {(currentRole !== 'paciente' && !souDentista) && ( - )} @@ -747,7 +770,10 @@ export const AgendaView: React.FC<{ onNavigate?: (view: string) => void; sidebar onEditar={() => { setShowDetails(false); setIsModalOpen(true); }} onAtender={handleAtender} onVerWhats={(info) => setWhatsTarget(info)} - podeAtender={!!onNavigate && currentRole !== 'paciente'} + // "Atender" (abre Lançar GTO) é ação CLÍNICA — atende quem trata: dentista, + // biomédico, dono da clínica/consultório, dentista locatário, admin. A recepção + // (funcionario) NÃO atende; ela só remarca/desmarca/agenda. + podeAtender={!!onNavigate && currentRole !== 'paciente' && currentRole !== 'funcionario'} dentistaRestrito={souDentista} /> @@ -861,6 +887,7 @@ export const AgendaView: React.FC<{ onNavigate?: (view: string) => void; sidebar initialPatient={reagendarPatient} /> setIsSettingsOpen(false)} dentists={dentists} /> + setShowMeusHorarios(false)} clinicaId={(HybridBackend.getActiveWorkspace() as any)?.id} initialTab="dentistas" soDentista /> {showInteresses && (
setShowInteresses(false)}>