fix:undefined checks, parsing simplification, and Tailwind standardization

This commit is contained in:
M-Gabrielly 2025-11-04 11:45:43 -03:00
parent 2dc7b00afc
commit 21636401b3
16 changed files with 115 additions and 106 deletions

View File

@ -193,7 +193,7 @@ export default function AgendamentoPage() {
<div className="flex flex-row">
<Button
variant={"outline"}
className="bg-muted hover:!bg-primary hover:!text-white transition-colors rounded-l-[100px] rounded-r-[0px]"
className="bg-muted hover:bg-primary! hover:text-white! transition-colors rounded-l-[100px] rounded-r-[0px]"
onClick={() => setActiveTab("calendar")}
>
Calendário
@ -201,7 +201,7 @@ export default function AgendamentoPage() {
<Button
variant={"outline"}
className="bg-muted hover:!bg-primary hover:!text-white transition-colors rounded-none"
className="bg-muted hover:bg-primary! hover:text-white! transition-colors rounded-none"
onClick={() => setActiveTab("3d")}
>
3D
@ -209,7 +209,7 @@ export default function AgendamentoPage() {
<Button
variant={"outline"}
className="bg-muted hover:!bg-primary hover:!text-white transition-colors rounded-r-[100px] rounded-l-[0px]"
className="bg-muted hover:bg-primary! hover:text-white! transition-colors rounded-r-[100px] rounded-l-[0px]"
onClick={() => setActiveTab("espera")}
>
Lista de espera

View File

@ -619,7 +619,7 @@ export default function ConsultasPage() {
size="sm"
onClick={() => setCurrentPage(1)}
disabled={currentPage === 1}
className="hover:!bg-primary hover:!text-white transition-colors"
className="hover:bg-primary! hover:text-white! transition-colors"
>
Primeira
</Button>
@ -628,7 +628,7 @@ export default function ConsultasPage() {
size="sm"
onClick={() => setCurrentPage((prev) => Math.max(1, prev - 1))}
disabled={currentPage === 1}
className="hover:!bg-primary hover:!text-white transition-colors"
className="hover:bg-primary! hover:text-white! transition-colors"
>
Anterior
</Button>
@ -640,7 +640,7 @@ export default function ConsultasPage() {
size="sm"
onClick={() => setCurrentPage((prev) => Math.min(totalPages, prev + 1))}
disabled={currentPage === totalPages || totalPages === 0}
className="hover:!bg-primary hover:!text-white transition-colors"
className="hover:bg-primary! hover:text-white! transition-colors"
>
Próxima
</Button>
@ -649,7 +649,7 @@ export default function ConsultasPage() {
size="sm"
onClick={() => setCurrentPage(totalPages)}
disabled={currentPage === totalPages || totalPages === 0}
className="hover:!bg-primary hover:!text-white transition-colors"
className="hover:bg-primary! hover:text-white! transition-colors"
>
Última
</Button>

View File

@ -283,15 +283,15 @@ export default function DashboardPage() {
<Plus className="h-4 w-4" />
Novo Paciente
</Button>
<Button onClick={() => router.push('/agenda')} variant="outline" className="gap-2 hover:!bg-primary hover:!text-white transition-colors">
<Button onClick={() => router.push('/agenda')} variant="outline" className="gap-2 hover:bg-primary! hover:text-white! transition-colors">
<Calendar className="h-4 w-4" />
Novo Agendamento
</Button>
<Button onClick={() => setShowDoctorForm(true)} variant="outline" className="gap-2 hover:!bg-primary hover:!text-white transition-colors">
<Button onClick={() => setShowDoctorForm(true)} variant="outline" className="gap-2 hover:bg-primary! hover:text-white! transition-colors">
<Stethoscope className="h-4 w-4" />
Novo Médico
</Button>
<Button onClick={() => router.push('/dashboard/relatorios')} variant="outline" className="gap-2 hover:!bg-primary hover:!text-white transition-colors">
<Button onClick={() => router.push('/dashboard/relatorios')} variant="outline" className="gap-2 hover:bg-primary! hover:text-white! transition-colors">
<FileText className="h-4 w-4" />
Ver Relatórios
</Button>
@ -340,7 +340,7 @@ export default function DashboardPage() {
<p className="text-xs text-muted-foreground">{report.exam || 'Sem descrição'}</p>
</div>
))}
<Button onClick={() => router.push('/dashboard/relatorios')} variant="ghost" className="w-full mt-2 hover:!bg-primary hover:!text-white transition-colors" size="sm">
<Button onClick={() => router.push('/dashboard/relatorios')} variant="ghost" className="w-full mt-2 hover:bg-primary! hover:text-white! transition-colors" size="sm">
Ver Todos
</Button>
</div>

View File

@ -350,7 +350,7 @@ export default function RelatoriosPage() {
<div className="bg-card border border-border rounded-lg shadow p-6">
<div className="flex items-center justify-between mb-2">
<h2 className="font-semibold text-lg text-foreground flex items-center gap-2"><BarChart2 className="w-5 h-5" /> Consultas por Período</h2>
<Button size="sm" variant="outline" className="hover:!bg-primary hover:!text-white transition-colors" onClick={() => exportPDF("Consultas por Período", "Resumo das consultas realizadas por período.")}> <FileDown className="w-4 h-4 mr-1" /> Exportar PDF</Button>
<Button size="sm" variant="outline" className="hover:bg-primary! hover:text-white! transition-colors" onClick={() => exportPDF("Consultas por Período", "Resumo das consultas realizadas por período.")}> <FileDown className="w-4 h-4 mr-1" /> Exportar PDF</Button>
</div>
{loading ? (
<div className="h-[220px] flex items-center justify-center text-muted-foreground">Carregando dados...</div>
@ -371,7 +371,7 @@ export default function RelatoriosPage() {
<div className="bg-card border border-border rounded-lg shadow p-6">
<div className="flex items-center justify-between mb-2">
<h2 className="font-semibold text-lg text-foreground flex items-center gap-2"><DollarSign className="w-5 h-5" /> Faturamento Mensal</h2>
<Button size="sm" variant="outline" className="hover:!bg-primary hover:!text-white transition-colors" onClick={() => exportPDF("Faturamento Mensal", "Resumo do faturamento mensal.")}> <FileDown className="w-4 h-4 mr-1" /> Exportar PDF</Button>
<Button size="sm" variant="outline" className="hover:bg-primary! hover:text-white! transition-colors" onClick={() => exportPDF("Faturamento Mensal", "Resumo do faturamento mensal.")}> <FileDown className="w-4 h-4 mr-1" /> Exportar PDF</Button>
</div>
{loading ? (
<div className="h-[220px] flex items-center justify-center text-muted-foreground">Carregando dados...</div>
@ -394,7 +394,7 @@ export default function RelatoriosPage() {
<div className="bg-card border border-border rounded-lg shadow p-6">
<div className="flex items-center justify-between mb-2">
<h2 className="font-semibold text-lg text-foreground flex items-center gap-2"><UserCheck className="w-5 h-5" /> Taxa de No-show</h2>
<Button size="sm" variant="outline" className="hover:!bg-primary hover:!text-white transition-colors" onClick={() => exportPDF("Taxa de No-show", "Resumo da taxa de no-show.")}> <FileDown className="w-4 h-4 mr-1" /> Exportar PDF</Button>
<Button size="sm" variant="outline" className="hover:bg-primary! hover:text-white! transition-colors" onClick={() => exportPDF("Taxa de No-show", "Resumo da taxa de no-show.")}> <FileDown className="w-4 h-4 mr-1" /> Exportar PDF</Button>
</div>
{loading ? (
<div className="h-[220px] flex items-center justify-center text-muted-foreground">Carregando dados...</div>
@ -415,7 +415,7 @@ export default function RelatoriosPage() {
<div className="bg-card border border-border rounded-lg shadow p-6">
<div className="flex items-center justify-between mb-2">
<h2 className="font-semibold text-lg text-foreground flex items-center gap-2"><ThumbsUp className="w-5 h-5" /> Satisfação dos Pacientes</h2>
<Button size="sm" variant="outline" className="hover:!bg-primary hover:!text-white transition-colors" onClick={() => exportPDF("Satisfação dos Pacientes", "Resumo dos indicadores de satisfação.")}> <FileDown className="w-4 h-4 mr-1" /> Exportar PDF</Button>
<Button size="sm" variant="outline" className="hover:bg-primary! hover:text-white! transition-colors" onClick={() => exportPDF("Satisfação dos Pacientes", "Resumo dos indicadores de satisfação.")}> <FileDown className="w-4 h-4 mr-1" /> Exportar PDF</Button>
</div>
<div className="flex flex-col items-center justify-center h-[220px]">
<span className="text-2xl font-bold text-foreground">Dados não foram disponibilizados</span>
@ -429,7 +429,7 @@ export default function RelatoriosPage() {
<div className="bg-card border border-border rounded-lg shadow p-6">
<div className="flex items-center justify-between mb-2">
<h2 className="font-semibold text-lg text-foreground flex items-center gap-2"><Users className="w-5 h-5" /> Pacientes Mais Atendidos</h2>
<Button size="sm" variant="outline" className="hover:!bg-primary hover:!text-white transition-colors" onClick={() => exportPDF("Pacientes Mais Atendidos", "Lista dos pacientes mais atendidos.")}> <FileDown className="w-4 h-4 mr-1" /> Exportar PDF</Button>
<Button size="sm" variant="outline" className="hover:bg-primary! hover:text-white! transition-colors" onClick={() => exportPDF("Pacientes Mais Atendidos", "Lista dos pacientes mais atendidos.")}> <FileDown className="w-4 h-4 mr-1" /> Exportar PDF</Button>
</div>
<table className="w-full text-sm mt-4">
<thead>
@ -463,7 +463,7 @@ export default function RelatoriosPage() {
<div className="bg-card border border-border rounded-lg shadow p-6">
<div className="flex items-center justify-between mb-2">
<h2 className="font-semibold text-lg text-foreground flex items-center gap-2"><Briefcase className="w-5 h-5" /> Médicos Mais Produtivos</h2>
<Button size="sm" variant="outline" className="hover:!bg-primary hover:!text-white transition-colors" onClick={() => exportPDF("Médicos Mais Produtivos", "Lista dos médicos mais produtivos.")}> <FileDown className="w-4 h-4 mr-1" /> Exportar PDF</Button>
<Button size="sm" variant="outline" className="hover:bg-primary! hover:text-white! transition-colors" onClick={() => exportPDF("Médicos Mais Produtivos", "Lista dos médicos mais produtivos.")}> <FileDown className="w-4 h-4 mr-1" /> Exportar PDF</Button>
</div>
<table className="w-full text-sm mt-4">
<thead>
@ -499,7 +499,7 @@ export default function RelatoriosPage() {
<div className="bg-card border border-border rounded-lg shadow p-6">
<div className="flex items-center justify-between mb-2">
<h2 className="font-semibold text-lg text-foreground flex items-center gap-2"><DollarSign className="w-5 h-5" /> Análise de Convênios</h2>
<Button size="sm" variant="outline" className="hover:!bg-primary hover:!text-white transition-colors" onClick={() => exportPDF("Análise de Convênios", "Resumo da análise de convênios.")}> <FileDown className="w-4 h-4 mr-1" /> Exportar PDF</Button>
<Button size="sm" variant="outline" className="hover:bg-primary! hover:text-white! transition-colors" onClick={() => exportPDF("Análise de Convênios", "Resumo da análise de convênios.")}> <FileDown className="w-4 h-4 mr-1" /> Exportar PDF</Button>
</div>
{loading ? (
<div className="h-[220px] flex items-center justify-center text-muted-foreground">Carregando dados...</div>
@ -522,7 +522,7 @@ export default function RelatoriosPage() {
<div className="bg-card border border-border rounded-lg shadow p-6">
<div className="flex items-center justify-between mb-2">
<h2 className="font-semibold text-lg text-foreground flex items-center gap-2"><TrendingUp className="w-5 h-5" /> Performance por Médico</h2>
<Button size="sm" variant="outline" className="hover:!bg-primary hover:!text-white transition-colors" onClick={() => exportPDF("Performance por Médico", "Resumo da performance por médico.")}> <FileDown className="w-4 h-4 mr-1" /> Exportar PDF</Button>
<Button size="sm" variant="outline" className="hover:bg-primary! hover:text-white! transition-colors" onClick={() => exportPDF("Performance por Médico", "Resumo da performance por médico.")}> <FileDown className="w-4 h-4 mr-1" /> Exportar PDF</Button>
</div>
<table className="w-full text-sm mt-4">
<thead>

View File

@ -623,7 +623,7 @@ export default function DoutoresPage() {
size="sm"
onClick={() => setCurrentPage(1)}
disabled={currentPage === 1}
className="hover:!bg-primary hover:!text-white transition-colors"
className="hover:bg-primary! hover:text-white! transition-colors"
>
Primeira
</Button>
@ -632,7 +632,7 @@ export default function DoutoresPage() {
size="sm"
onClick={() => setCurrentPage((prev) => Math.max(1, prev - 1))}
disabled={currentPage === 1}
className="hover:!bg-primary hover:!text-white transition-colors"
className="hover:bg-primary! hover:text-white! transition-colors"
>
Anterior
</Button>
@ -644,7 +644,7 @@ export default function DoutoresPage() {
size="sm"
onClick={() => setCurrentPage((prev) => Math.min(totalPages, prev + 1))}
disabled={currentPage === totalPages || totalPages === 0}
className="hover:!bg-primary hover:!text-white transition-colors"
className="hover:bg-primary! hover:text-white! transition-colors"
>
Próxima
</Button>
@ -653,7 +653,7 @@ export default function DoutoresPage() {
size="sm"
onClick={() => setCurrentPage(totalPages)}
disabled={currentPage === totalPages || totalPages === 0}
className="hover:!bg-primary hover:!text-white transition-colors"
className="hover:bg-primary! hover:text-white! transition-colors"
>
Última
</Button>

View File

@ -320,7 +320,7 @@ export default function PacientesPage() {
size="sm"
onClick={() => setCurrentPage(1)}
disabled={currentPage === 1}
className="hover:!bg-primary hover:!text-white transition-colors"
className="hover:bg-primary! hover:text-white! transition-colors"
>
Primeira
</Button>
@ -329,7 +329,7 @@ export default function PacientesPage() {
size="sm"
onClick={() => setCurrentPage((prev) => Math.max(1, prev - 1))}
disabled={currentPage === 1}
className="hover:!bg-primary hover:!text-white transition-colors"
className="hover:bg-primary! hover:text-white! transition-colors"
>
Anterior
</Button>
@ -341,7 +341,7 @@ export default function PacientesPage() {
size="sm"
onClick={() => setCurrentPage((prev) => Math.min(totalPages, prev + 1))}
disabled={currentPage === totalPages || totalPages === 0}
className="hover:!bg-primary hover:!text-white transition-colors"
className="hover:bg-primary! hover:text-white! transition-colors"
>
Próxima
</Button>
@ -350,7 +350,7 @@ export default function PacientesPage() {
size="sm"
onClick={() => setCurrentPage(totalPages)}
disabled={currentPage === totalPages || totalPages === 0}
className="hover:!bg-primary hover:!text-white transition-colors"
className="hover:bg-primary! hover:text-white! transition-colors"
>
Última
</Button>

View File

@ -154,7 +154,7 @@ export default function LoginAdminPage() {
</div>
<div className="mt-4 text-center">
<Button variant="outline" asChild className="w-full hover:!bg-primary hover:!text-white hover:!border-primary transition-all duration-200">
<Button variant="outline" asChild className="w-full hover:bg-primary! hover:text-white! hover:border-primary! transition-all duration-200">
<Link href="/">
Voltar ao Início
</Link>

View File

@ -240,7 +240,7 @@ export default function LoginPacientePage() {
</div>
<div className="mt-4 text-center">
<Button variant="outline" asChild className="w-full hover:!bg-primary hover:!text-white hover:!border-primary transition-all duration-200">
<Button variant="outline" asChild className="w-full hover:bg-primary! hover:text-white! hover:border-primary! transition-all duration-200">
<Link href="/">
Voltar ao Início
</Link>

View File

@ -164,7 +164,7 @@ export default function LoginPage() {
</div>
<div className="mt-4 text-center">
<Button variant="outline" asChild className="w-full hover:!bg-primary hover:!text-white hover:!border-primary transition-all duration-200">
<Button variant="outline" asChild className="w-full hover:bg-primary! hover:text-white! hover:border-primary! transition-all duration-200">
<Link href="/">
Voltar ao Início
</Link>

View File

@ -650,7 +650,7 @@ export default function PacientePage() {
<div className="space-y-6 rounded-2xl border border-primary/15 bg-gradient-to-r from-primary/5 to-primary/10 p-8 shadow-sm">
<div className="flex justify-center">
<Button asChild className="w-full md:w-auto px-10 py-3 bg-primary text-white hover:!bg-primary/90 hover:!text-white transition-all duration-200 font-semibold text-base rounded-lg shadow-md hover:shadow-lg active:scale-95">
<Button asChild className="w-full md:w-auto px-10 py-3 bg-primary text-white hover:bg-primary/90! hover:text-white! transition-all duration-200 font-semibold text-base rounded-lg shadow-md hover:shadow-lg active:scale-95">
<Link href={buildResultadosHref()} prefetch={false}>
Pesquisar Médicos
</Link>
@ -677,7 +677,7 @@ export default function PacientePage() {
size="icon"
onClick={(e: any) => { e.stopPropagation(); e.preventDefault(); navigateDate('prev') }}
aria-label="Dia anterior"
className={`group shadow-sm hover:!bg-primary hover:!text-white hover:!border-primary transition-all ${hoverPrimaryIconClass}`}
className={`group shadow-sm hover:bg-primary! hover:text-white! hover:border-primary! transition-all ${hoverPrimaryIconClass}`}
>
<ChevronLeft className="h-5 w-5 transition group-hover:text-white" />
</Button>
@ -688,7 +688,7 @@ export default function PacientePage() {
size="icon"
onClick={(e: any) => { e.stopPropagation(); e.preventDefault(); navigateDate('next') }}
aria-label="Próximo dia"
className={`group shadow-sm hover:!bg-primary hover:!text-white hover:!border-primary transition-all ${hoverPrimaryIconClass}`}
className={`group shadow-sm hover:bg-primary! hover:text-white! hover:border-primary! transition-all ${hoverPrimaryIconClass}`}
>
<ChevronRight className="h-5 w-5 transition group-hover:text-white" />
</Button>
@ -780,7 +780,7 @@ export default function PacientePage() {
<Button
type="button"
size="sm"
className="border border-primary/30 text-primary bg-primary/5 hover:!bg-primary hover:!text-white hover:!border-primary transition-all duration-200 focus-visible:ring-2 focus-visible:ring-primary/40 active:scale-95 text-xs font-semibold flex-1"
className="border border-primary/30 text-primary bg-primary/5 hover:bg-primary! hover:text-white! hover:border-primary! transition-all duration-200 focus-visible:ring-2 focus-visible:ring-primary/40 active:scale-95 text-xs font-semibold flex-1"
>
Detalhes
</Button>
@ -788,7 +788,7 @@ export default function PacientePage() {
<Button
type="button"
size="sm"
className="bg-primary/10 text-primary border border-primary/30 hover:!bg-primary hover:!text-white hover:!border-primary transition-all duration-200 focus-visible:ring-2 focus-visible:ring-primary/40 active:scale-95 text-xs font-semibold flex-1"
className="bg-primary/10 text-primary border border-primary/30 hover:bg-primary! hover:text-white! hover:border-primary! transition-all duration-200 focus-visible:ring-2 focus-visible:ring-primary/40 active:scale-95 text-xs font-semibold flex-1"
>
Reagendar
</Button>
@ -797,7 +797,7 @@ export default function PacientePage() {
<Button
type="button"
size="sm"
className="border border-destructive/30 text-destructive bg-destructive/5 hover:!bg-destructive hover:!text-white hover:!border-destructive transition-all duration-200 focus-visible:ring-2 focus-visible:ring-destructive/40 active:scale-95 text-xs font-semibold flex-1"
className="border border-destructive/30 text-destructive bg-destructive/5 hover:bg-destructive! hover:text-white! hover:border-destructive! transition-all duration-200 focus-visible:ring-2 focus-visible:ring-destructive/40 active:scale-95 text-xs font-semibold flex-1"
>
Cancelar
</Button>
@ -1312,8 +1312,8 @@ export default function PacientePage() {
<div className="text-base md:text-base text-muted-foreground mt-1">Data: {new Date(r.report_date || r.created_at || Date.now()).toLocaleDateString('pt-BR')}</div>
</div>
<div className="flex gap-2 mt-2 md:mt-0">
<Button variant="outline" className="hover:!bg-primary hover:!text-white transition-colors" onClick={async () => { setSelectedReport(r); }}>{strings.visualizarLaudo}</Button>
<Button variant="secondary" className="hover:!bg-primary hover:!text-white transition-colors" onClick={async () => { try { await navigator.clipboard.writeText(JSON.stringify(r)); setToast({ type: 'success', msg: 'Laudo copiado.' }) } catch { setToast({ type: 'error', msg: 'Falha ao copiar.' }) } }}>{strings.compartilhar}</Button>
<Button variant="outline" className="hover:bg-primary! hover:text-white! transition-colors" onClick={async () => { setSelectedReport(r); }}>{strings.visualizarLaudo}</Button>
<Button variant="secondary" className="hover:bg-primary! hover:text-white! transition-colors" onClick={async () => { try { await navigator.clipboard.writeText(JSON.stringify(r)); setToast({ type: 'success', msg: 'Laudo copiado.' }) } catch { setToast({ type: 'error', msg: 'Falha ao copiar.' }) } }}>{strings.compartilhar}</Button>
</div>
</div>
))}
@ -1543,7 +1543,7 @@ export default function PacientePage() {
</div>
<div className="flex items-center gap-3">
<SimpleThemeToggle />
<Button asChild variant="outline" className="hover:!bg-primary hover:!text-white hover:!border-primary transition-colors">
<Button asChild variant="outline" className="hover:bg-primary! hover:text-white! hover:border-primary! transition-colors">
<Link href="/">
<Home className="h-4 w-4 mr-1" /> Início
</Link>
@ -1553,7 +1553,7 @@ export default function PacientePage() {
variant="outline"
aria-label={strings.sair}
disabled={loading}
className="text-destructive border-destructive hover:!bg-destructive hover:!text-white hover:!border-destructive transition-colors"
className="text-destructive border-destructive hover:bg-destructive! hover:text-white! hover:border-destructive! transition-colors"
>
<LogOut className="h-4 w-4 mr-1" /> {strings.sair}
</Button>
@ -1569,7 +1569,7 @@ export default function PacientePage() {
variant={tab==='dashboard'?'default':'ghost'}
aria-current={tab==='dashboard'}
onClick={()=>setTab('dashboard')}
className={`w-full justify-start transition-colors hover:!bg-primary hover:!text-white cursor-pointer`}
className={`w-full justify-start transition-colors hover:bg-primary! hover:text-white! cursor-pointer`}
>
<Calendar className="mr-2 h-4 w-4" />{strings.dashboard}
</Button>
@ -1577,7 +1577,7 @@ export default function PacientePage() {
variant={tab==='consultas'?'default':'ghost'}
aria-current={tab==='consultas'}
onClick={()=>setTab('consultas')}
className={`w-full justify-start transition-colors hover:!bg-primary hover:!text-white cursor-pointer`}
className={`w-full justify-start transition-colors hover:bg-primary! hover:text-white! cursor-pointer`}
>
<Calendar className="mr-2 h-4 w-4" />{strings.consultas}
</Button>
@ -1585,7 +1585,7 @@ export default function PacientePage() {
variant={tab==='exames'?'default':'ghost'}
aria-current={tab==='exames'}
onClick={()=>setTab('exames')}
className={`w-full justify-start transition-colors hover:!bg-primary hover:!text-white cursor-pointer`}
className={`w-full justify-start transition-colors hover:bg-primary! hover:text-white! cursor-pointer`}
>
<FileText className="mr-2 h-4 w-4" />{strings.exames}
</Button>
@ -1594,7 +1594,7 @@ export default function PacientePage() {
variant={tab==='perfil'?'default':'ghost'}
aria-current={tab==='perfil'}
onClick={()=>setTab('perfil')}
className={`w-full justify-start transition-colors hover:!bg-primary hover:!text-white cursor-pointer`}
className={`w-full justify-start transition-colors hover:bg-primary! hover:text-white! cursor-pointer`}
>
<UserCog className="mr-2 h-4 w-4" />{strings.perfil}
</Button>

View File

@ -690,7 +690,7 @@ const ProfissionalPage = () => {
variant="outline"
size="sm"
onClick={() => navigateDate('prev')}
className="p-2 hover:!bg-primary hover:!text-white cursor-pointer transition-colors"
className="p-2 hover:bg-primary! hover:text-white! cursor-pointer transition-colors"
>
<ChevronLeft className="h-4 w-4" />
</Button>
@ -701,7 +701,7 @@ const ProfissionalPage = () => {
variant="outline"
size="sm"
onClick={() => navigateDate('next')}
className="p-2 hover:!bg-primary hover:!text-white cursor-pointer transition-colors"
className="p-2 hover:bg-primary! hover:text-white! cursor-pointer transition-colors"
>
<ChevronRight className="h-4 w-4" />
</Button>
@ -900,7 +900,7 @@ const ProfissionalPage = () => {
variant={selectedRange === 'todos' ? 'default' : 'outline'}
size="sm"
onClick={() => setSelectedRange('todos')}
className="hover:!bg-primary hover:!text-white transition-colors"
className="hover:bg-primary! hover:text-white! transition-colors"
>
Todos
</Button>
@ -908,7 +908,7 @@ const ProfissionalPage = () => {
variant={selectedRange === 'semana' ? 'default' : 'outline'}
size="sm"
onClick={() => setSelectedRange('semana')}
className="hover:!bg-primary hover:!text-white transition-colors"
className="hover:bg-primary! hover:text-white! transition-colors"
>
Semana
</Button>
@ -916,7 +916,7 @@ const ProfissionalPage = () => {
variant={selectedRange === 'mes' ? 'default' : 'outline'}
size="sm"
onClick={() => setSelectedRange('mes')}
className="hover:!bg-primary hover:!text-white transition-colors"
className="hover:bg-primary! hover:text-white! transition-colors"
>
Mês
</Button>
@ -1077,7 +1077,7 @@ const ProfissionalPage = () => {
<Button size="sm" onClick={doSearch} disabled={searching}>
Buscar
</Button>
<Button size="sm" variant="ghost" onClick={handleClear} className="hover:!bg-primary hover:!text-white transition-colors">
<Button size="sm" variant="ghost" onClick={handleClear} className="hover:bg-primary! hover:text-white! transition-colors">
Limpar
</Button>
</div>
@ -1383,7 +1383,7 @@ const ProfissionalPage = () => {
setIsViewing(true);
}
}}
className="flex items-center gap-1 hover:!bg-primary hover:!text-white transition-colors"
className="flex items-center gap-1 hover:bg-primary! hover:text-white! transition-colors"
>
<Eye className="w-4 h-4" />
Ver Laudo
@ -2457,7 +2457,7 @@ const ProfissionalPage = () => {
Este editor permite escrever relatórios de forma livre, com formatação de texto rica.
</div>
<div className="flex gap-2">
<Button variant="outline" onClick={onClose} className="hover:!bg-primary hover:!text-white transition-colors">
<Button variant="outline" onClick={onClose} className="hover:bg-primary! hover:text-white! transition-colors">
Cancelar
</Button>
{/* botão 'Salvar Rascunho' removido por não ser utilizado */}
@ -2656,7 +2656,7 @@ const ProfissionalPage = () => {
<Button onClick={handleSaveProfile} className="flex items-center gap-2">
Salvar
</Button>
<Button variant="outline" onClick={handleCancelEdit} className="hover:!bg-primary hover:!text-white transition-colors">
<Button variant="outline" onClick={handleCancelEdit} className="hover:bg-primary! hover:text-white! transition-colors">
Cancelar
</Button>
</div>
@ -2779,7 +2779,7 @@ const ProfissionalPage = () => {
</Avatar>
{isEditingProfile && (
<div className="space-y-2">
<Button variant="outline" size="sm" className="hover:!bg-primary hover:!text-white transition-colors">
<Button variant="outline" size="sm" className="hover:bg-primary! hover:text-white! transition-colors">
Alterar Foto
</Button>
<p className="text-xs text-muted-foreground">
@ -2875,7 +2875,7 @@ const ProfissionalPage = () => {
<nav className="bg-card shadow-md rounded-lg border border-border p-3 space-y-1">
<Button
variant={activeSection === 'calendario' ? 'default' : 'ghost'}
className="w-full justify-start transition-colors hover:!bg-primary hover:!text-white cursor-pointer"
className="w-full justify-start transition-colors hover:bg-primary! hover:text-white! cursor-pointer"
onClick={() => setActiveSection('calendario')}
>
<CalendarIcon className="mr-2 h-4 w-4" />
@ -2883,7 +2883,7 @@ const ProfissionalPage = () => {
</Button>
<Button
variant={activeSection === 'pacientes' ? 'default' : 'ghost'}
className="w-full justify-start transition-colors hover:!bg-primary hover:!text-white cursor-pointer"
className="w-full justify-start transition-colors hover:bg-primary! hover:text-white! cursor-pointer"
onClick={() => setActiveSection('pacientes')}
>
<Users className="mr-2 h-4 w-4" />
@ -2891,7 +2891,7 @@ const ProfissionalPage = () => {
</Button>
<Button
variant={activeSection === 'laudos' ? 'default' : 'ghost'}
className="w-full justify-start transition-colors hover:!bg-primary hover:!text-white cursor-pointer"
className="w-full justify-start transition-colors hover:bg-primary! hover:text-white! cursor-pointer"
onClick={() => setActiveSection('laudos')}
>
<FileText className="mr-2 h-4 w-4" />
@ -2899,7 +2899,7 @@ const ProfissionalPage = () => {
</Button>
<Button
variant={activeSection === 'comunicacao' ? 'default' : 'ghost'}
className="w-full justify-start transition-colors hover:!bg-primary hover:!text-white cursor-pointer"
className="w-full justify-start transition-colors hover:bg-primary! hover:text-white! cursor-pointer"
onClick={() => setActiveSection('comunicacao')}
>
<MessageSquare className="mr-2 h-4 w-4" />
@ -2907,7 +2907,7 @@ const ProfissionalPage = () => {
</Button>
<Button
variant={activeSection === 'perfil' ? 'default' : 'ghost'}
className="w-full justify-start transition-colors hover:!bg-primary hover:!text-white cursor-pointer"
className="w-full justify-start transition-colors hover:bg-primary! hover:text-white! cursor-pointer"
onClick={() => setActiveSection('perfil')}
>
<Settings className="mr-2 h-4 w-4" />
@ -2957,7 +2957,7 @@ const ProfissionalPage = () => {
<Button
onClick={() => setShowPopup(false)}
variant="outline"
className="flex-1 hover:!bg-primary hover:!text-white transition-colors"
className="flex-1 hover:bg-primary! hover:text-white! transition-colors"
>
Cancelar
</Button>
@ -3072,7 +3072,7 @@ const ProfissionalPage = () => {
<Button
onClick={() => setShowActionModal(false)}
variant="outline"
className="w-full mt-2 hover:!bg-primary hover:!text-white transition-colors"
className="w-full mt-2 hover:bg-primary! hover:text-white! transition-colors"
>
Cancelar
</Button>

View File

@ -655,7 +655,7 @@ export default function ResultadosClient() {
</div>
<Button
variant="outline"
className="rounded-full border-primary-foreground/30 bg-primary-foreground/10 text-primary-foreground hover:!bg-primary-foreground hover:!text-primary transition-colors"
className="rounded-full border-primary-foreground/30 bg-primary-foreground/10 text-primary-foreground hover:bg-primary-foreground! hover:text-primary! transition-colors"
>
Ajustar filtros
</Button>
@ -699,7 +699,7 @@ export default function ResultadosClient() {
</Toggle>
<Select value={convenio} onValueChange={setConvenio}>
<SelectTrigger className="h-10 min-w-[180px] rounded-full border border-primary/40 bg-primary/10 text-primary transition duration-200 hover:!border-primary focus:ring-2 focus:ring-primary cursor-pointer">
<SelectTrigger className="h-10 min-w-[180px] rounded-full border border-primary/40 bg-primary/10 text-primary transition duration-200 hover:border-primary! focus:ring-2 focus:ring-primary cursor-pointer">
<SelectValue placeholder="Convênio" />
</SelectTrigger>
<SelectContent>
@ -713,7 +713,7 @@ export default function ResultadosClient() {
</Select>
<Select value={bairro} onValueChange={setBairro}>
<SelectTrigger className="h-10 min-w-[160px] rounded-full border border-primary/40 bg-primary/10 text-primary transition duration-200 hover:!border-primary focus:ring-2 focus:ring-primary cursor-pointer">
<SelectTrigger className="h-10 min-w-[160px] rounded-full border border-primary/40 bg-primary/10 text-primary transition duration-200 hover:border-primary! focus:ring-2 focus:ring-primary cursor-pointer">
<SelectValue placeholder="Bairro" />
</SelectTrigger>
<SelectContent>
@ -758,7 +758,7 @@ export default function ResultadosClient() {
) : (
<Button
variant="outline"
className="rounded-full border border-primary/40 bg-primary/10 text-primary hover:!bg-primary hover:!text-white transition-colors"
className="rounded-full border border-primary/40 bg-primary/10 text-primary hover:bg-primary! hover:text-white! transition-colors"
>
<Filter className="mr-2 h-4 w-4" />
Mais filtros
@ -768,7 +768,7 @@ export default function ResultadosClient() {
<Button
variant="ghost"
className="ml-auto rounded-full text-primary hover:!bg-primary hover:!text-white transition-colors"
className="ml-auto rounded-full text-primary hover:bg-primary! hover:text-white! transition-colors"
onClick={() => router.back()}
>
Voltar
@ -827,7 +827,7 @@ export default function ResultadosClient() {
</div>
<Button
variant="ghost"
className="ml-auto h-fit rounded-full text-primary hover:!bg-primary hover:!text-white transition-colors"
className="ml-auto h-fit rounded-full text-primary hover:bg-primary! hover:text-white! transition-colors"
onClick={() => {
setMedicoSelecionado(medico)
setAbaDetalhe('experiencia')
@ -898,12 +898,12 @@ export default function ResultadosClient() {
>
Agendar consulta
</Button>
<Button variant="outline" className="h-11 rounded-full border-primary/40 bg-primary/10 text-primary hover:!bg-primary hover:!text-white transition-colors">
<Button variant="outline" className="h-11 rounded-full border-primary/40 bg-primary/10 text-primary hover:bg-primary! hover:text-white! transition-colors">
Enviar mensagem
</Button>
<Button
variant="ghost"
className="h-11 rounded-full text-primary hover:!bg-primary hover:!text-white transition-colors"
className="h-11 rounded-full text-primary hover:bg-primary! hover:text-white! transition-colors"
onClick={() => {
const willOpen = !agendasExpandida[id]
setAgendasExpandida(prev => ({ ...prev, [id]: !prev[id] }))
@ -947,11 +947,11 @@ export default function ResultadosClient() {
</div>
<div className="flex items-center gap-2">
<Button variant="outline" size="sm" onClick={() => setCurrentPage(1)} disabled={currentPage === 1} className="hover:!bg-primary hover:!text-white">Primeira</Button>
<Button variant="outline" size="sm" onClick={() => setCurrentPage(p => Math.max(1, p - 1))} disabled={currentPage === 1} className="hover:!bg-primary hover:!text-white">Anterior</Button>
<Button variant="outline" size="sm" onClick={() => setCurrentPage(1)} disabled={currentPage === 1} className="hover:bg-primary! hover:text-white!">Primeira</Button>
<Button variant="outline" size="sm" onClick={() => setCurrentPage(p => Math.max(1, p - 1))} disabled={currentPage === 1} className="hover:bg-primary! hover:text-white!">Anterior</Button>
<span className="text-sm text-muted-foreground">Página {currentPage} de {totalPages}</span>
<Button variant="outline" size="sm" onClick={() => setCurrentPage(p => Math.min(totalPages, p + 1))} disabled={currentPage === totalPages} className="hover:!bg-primary hover:!text-white">Próxima</Button>
<Button variant="outline" size="sm" onClick={() => setCurrentPage(totalPages)} disabled={currentPage === totalPages} className="hover:!bg-primary hover:!text-white">Última</Button>
<Button variant="outline" size="sm" onClick={() => setCurrentPage(p => Math.min(totalPages, p + 1))} disabled={currentPage === totalPages} className="hover:bg-primary! hover:text-white!">Próxima</Button>
<Button variant="outline" size="sm" onClick={() => setCurrentPage(totalPages)} disabled={currentPage === totalPages} className="hover:bg-primary! hover:text-white!">Última</Button>
</div>
</div>
)}

View File

@ -43,7 +43,7 @@ export function PagesHeader({ title = "", subtitle = "" }: { title?: string, sub
</div>
<div className="flex items-center space-x-4">
<Button variant="ghost" size="icon" className="hover:!bg-primary hover:!text-white transition-colors">
<Button variant="ghost" size="icon" className="hover:bg-primary! hover:text-white! transition-colors">
<Bell className="h-4 w-4" />
</Button>

View File

@ -17,7 +17,7 @@ export function SimpleThemeToggle() {
variant="outline"
size="icon"
onClick={toggleTheme}
className="hover:!bg-primary hover:!text-white hover:!border-primary cursor-pointer !shadow-sm !shadow-black/10 !border-2 !border-black dark:!shadow-none dark:!border-border transition-colors"
className="hover:bg-primary! hover:text-white! hover:border-primary! cursor-pointer shadow-sm! shadow-black/10! border-2! border-black! dark:shadow-none! dark:border-border! transition-colors"
>
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />

View File

@ -266,7 +266,7 @@ function SidebarTrigger({
data-slot="sidebar-trigger"
variant="ghost"
size="icon"
className={cn("size-7 hover:!bg-primary hover:!text-white transition-colors", className)}
className={cn("size-7 hover:bg-primary! hover:text-white! transition-colors", className)}
onClick={(event) => {
onClick?.(event)
toggleSidebar()

View File

@ -238,7 +238,7 @@ export async function criarDisponibilidade(input: DoctorAvailabilityCreate): Pro
// Normalize weekday to integer expected by the OpenAPI (0=Sunday .. 6=Saturday)
const mapWeekdayToInt = (w?: string | number): number | null => {
if (w === null || typeof w === 'undefined') return null;
if (w === null || w === undefined) return null;
if (typeof w === 'number') return Number(w);
const s = String(w).toLowerCase().trim();
const map: Record<string, number> = {
@ -270,7 +270,7 @@ export async function criarDisponibilidade(input: DoctorAvailabilityCreate): Pro
end_time: input.end_time,
slot_minutes: input.slot_minutes ?? 30,
appointment_type: input.appointment_type ?? 'presencial',
active: typeof input.active === 'undefined' ? true : input.active,
active: input.active === undefined ? true : input.active,
created_by: createdBy,
};
@ -307,7 +307,7 @@ export async function criarDisponibilidade(input: DoctorAvailabilityCreate): Pro
end_time: end,
slot_minutes: input.slot_minutes ?? 30,
appointment_type: input.appointment_type ?? 'presencial',
active: typeof input.active === 'undefined' ? true : input.active,
active: input.active === undefined ? true : input.active,
created_by: createdBy,
};
@ -349,7 +349,7 @@ export async function criarDisponibilidade(input: DoctorAvailabilityCreate): Pro
end_time: end,
slot_minutes: input.slot_minutes ?? 30,
appointment_type: input.appointment_type ?? 'presencial',
active: typeof input.active === 'undefined' ? true : input.active,
active: input.active === undefined ? true : input.active,
created_by: createdBy,
};
try {
@ -381,7 +381,7 @@ export async function criarDisponibilidade(input: DoctorAvailabilityCreate): Pro
export async function listarDisponibilidades(params?: { doctorId?: string; active?: boolean }): Promise<DoctorAvailability[]> {
const qs = new URLSearchParams();
if (params?.doctorId) qs.set('doctor_id', `eq.${encodeURIComponent(String(params.doctorId))}`);
if (typeof params?.active !== 'undefined') qs.set('active', `eq.${params.active ? 'true' : 'false'}`);
if (params?.active !== undefined) qs.set('active', `eq.${params.active ? 'true' : 'false'}`);
const url = `${REST}/doctor_availability${qs.toString() ? `?${qs.toString()}` : ''}`;
const res = await fetch(url, { method: 'GET', headers: baseHeaders() });
@ -616,9 +616,19 @@ function buildRedirectUrl(target?: 'paciente' | 'medico' | 'admin' | 'default',
const base = DEFAULT_REDIRECT_BASE.replace(/\/$/, '');
let path = '/';
if (target === 'paciente') path = '/paciente';
else if (target === 'medico') path = '/profissional';
else if (target === 'admin') path = '/dashboard';
switch (target) {
case 'paciente':
path = '/paciente';
break;
case 'medico':
path = '/profissional';
break;
case 'admin':
path = '/dashboard';
break;
default:
path = '/';
}
return `${base}${path}`;
}
@ -866,7 +876,7 @@ export async function buscarPacientes(termo: string): Promise<Paciente[]> {
try {
const [key, val] = String(query).split('=');
const params = new URLSearchParams();
if (key && typeof val !== 'undefined') params.set(key, val);
if (key && val !== undefined) params.set(key, val);
params.set('limit', '10');
const url = `${REST}/patients?${params.toString()}`;
const headers = baseHeaders();
@ -1115,23 +1125,21 @@ export async function criarAgendamento(input: AppointmentCreate): Promise<Appoin
}
// Otherwise check overlap with scheduled time
// Parse exception times and scheduled time to minutes
const parseToMinutes = (t?: string | null) => {
if (!t) return null;
const parts = String(t).split(':').map((p) => Number(p));
if (parts.length >= 2 && !Number.isNaN(parts[0]) && !Number.isNaN(parts[1])) return parts[0] * 60 + parts[1];
return null;
};
const exStart = parseToMinutes(ex.start_time ?? undefined);
const exEnd = parseToMinutes(ex.end_time ?? undefined);
const parseToMinutes = (t?: string | null) => {
if (!t) return null;
const parts = String(t).split(':').map(Number);
if (parts.length >= 2 && !Number.isNaN(parts[0]) && !Number.isNaN(parts[1])) return parts[0] * 60 + parts[1];
return null;
};
const exStart = parseToMinutes(ex.start_time ?? undefined);
const exEnd = parseToMinutes(ex.end_time ?? undefined);
const sched = new Date(input.scheduled_at);
const schedMinutes = sched.getHours() * 60 + sched.getMinutes();
const schedDuration = input.duration_minutes ?? 30;
const schedEndMinutes = schedMinutes + Number(schedDuration);
if (exStart != null && exEnd != null) {
if (schedMinutes < exEnd && exStart < schedEndMinutes) {
const reason = ex.reason ? ` Motivo: ${ex.reason}` : '';
throw new Error(`Não é possível agendar neste horário por uma exceção que bloqueia parte do dia.${reason}`);
}
if (exStart != null && exEnd != null && schedMinutes < exEnd && exStart < schedEndMinutes) {
const reason = ex.reason ? ` Motivo: ${ex.reason}` : '';
throw new Error(`Não é possível agendar neste horário por uma exceção que bloqueia parte do dia.${reason}`);
}
} catch (inner) {
// Propagate the exception as user-facing error
@ -1767,9 +1775,9 @@ export async function buscarMedicos(termo: string): Promise<Medico[]> {
try {
// Build the URL safely using URLSearchParams so special characters (like @) are encoded correctly
// query is like 'nome_social=ilike.*something*' -> split into key/value
const [key, val] = String(query).split('=');
const params = new URLSearchParams();
if (key && typeof val !== 'undefined') params.set(key, val);
const [key, val] = String(query).split('=');
const params = new URLSearchParams();
if (key && val !== undefined) params.set(key, val);
params.set('limit', '10');
const url = `${REST}/doctors?${params.toString()}`;
const headers = baseHeaders();
@ -1800,7 +1808,7 @@ export async function buscarMedicoPorId(id: string | number): Promise<Medico | n
const sId = String(id);
// Helper para escape de aspas
const escapeQuotes = (v: string) => v.replace(/"/g, '\\"');
const escapeQuotes = (v: string) => JSON.stringify(v).slice(1, -1);
try {
// 1) Se parece UUID, busca por id direto
@ -2085,9 +2093,9 @@ export async function criarMedico(input: MedicoInput): Promise<Medico> {
crm_uf: crmUf,
create_user: false,
};
if (input.specialty) fallbackPayload.specialty = input.specialty;
if (input.phone_mobile) fallbackPayload.phone_mobile = input.phone_mobile;
if (typeof input.phone2 !== 'undefined') fallbackPayload.phone2 = input.phone2;
if (input.specialty) fallbackPayload.specialty = input.specialty;
if (input.phone_mobile) fallbackPayload.phone_mobile = input.phone_mobile;
if (input.phone2 !== undefined) fallbackPayload.phone2 = input.phone2;
const url = `${API_BASE}/functions/v1/create-doctor`;
const headers = { ...baseHeaders(), 'Content-Type': 'application/json' } as Record<string, string>;
@ -2685,7 +2693,8 @@ export async function criarUsuarioPaciente(paciente: { email: string; full_name:
const parsed = await parse<any>(res as Response);
// Attach the generated password so callers (UI) can display it if necessary
return { ...(parsed || {}), password };
if (parsed && typeof parsed === 'object') return { ...(parsed as any), password };
return { password };
}