diff --git a/susconecta/app/financeiro/page.tsx b/susconecta/app/financeiro/page.tsx index a14d7e8..541e840 100644 --- a/susconecta/app/financeiro/page.tsx +++ b/susconecta/app/financeiro/page.tsx @@ -16,6 +16,8 @@ export default function FinanceiroPage() { const pathname = usePathname(); const router = useRouter(); const [bloqueio, setBloqueio] = useState(false); + const [formaTipo, setFormaTipo] = useState(""); + const [parcelas, setParcelas] = useState("1"); const isAg = pathname?.startsWith("/agendamento"); const isPr = pathname?.startsWith("/procedimento"); @@ -94,7 +96,7 @@ export default function FinanceiroPage() {
- setFormaTipo(e.target.value)} className="h-10 w-full rounded-md border border-gray-300 dark:border-input bg-background text-foreground pr-8 pl-3 text-[13px] appearance-none transition-colors hover:bg-muted/30 hover:border-gray-400"> diff --git a/susconecta/app/paciente/page.tsx b/susconecta/app/paciente/page.tsx index e8712ce..e13841b 100644 --- a/susconecta/app/paciente/page.tsx +++ b/susconecta/app/paciente/page.tsx @@ -1,40 +1,21 @@ "use client"; // import { useAuth } from '@/hooks/useAuth' // removido duplicado -import { useState } from "react"; -import { Button } from "@/components/ui/button"; -import { - Dialog, - DialogContent, - DialogHeader, - DialogTitle, - DialogDescription, - DialogFooter, -} from "@/components/ui/dialog"; -import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; -import { Textarea } from "@/components/ui/textarea"; -import { Avatar, AvatarFallback } from "@/components/ui/avatar"; -import { - User, - LogOut, - Calendar, - FileText, - MessageCircle, - UserCog, - Home, - Clock, - FolderOpen, - ChevronLeft, - ChevronRight, - MapPin, - Stethoscope, -} from "lucide-react"; -import { SimpleThemeToggle } from "@/components/simple-theme-toggle"; -import Link from "next/link"; -import ProtectedRoute from "@/components/ProtectedRoute"; -import { useAuth } from "@/hooks/useAuth"; +import { useState } from 'react' +import { useRouter } from 'next/navigation' +import { Button } from '@/components/ui/button' +import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from '@/components/ui/dialog' +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' +import { Input } from '@/components/ui/input' +import { Label } from '@/components/ui/label' +import { Textarea } from '@/components/ui/textarea' +import { Avatar, AvatarFallback } from '@/components/ui/avatar' +import { User, LogOut, Calendar, FileText, MessageCircle, UserCog, Home, Clock, FolderOpen, ChevronLeft, ChevronRight, MapPin, Stethoscope } from 'lucide-react' +import { SimpleThemeToggle } from '@/components/simple-theme-toggle' +import Link from 'next/link' +import ProtectedRoute from '@/components/ProtectedRoute' +import { useAuth } from '@/hooks/useAuth' +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' // Simulação de internacionalização básica const strings = { dashboard: "Dashboard", @@ -176,14 +157,8 @@ export default function PacientePage() { }, ]; - function formatDatePt(dateString: string) { - const date = new Date(dateString); - return date.toLocaleDateString("pt-BR", { - weekday: "long", - day: "numeric", - month: "long", - year: "numeric", - }); + function formatDatePt(date: Date) { + return date.toLocaleDateString('pt-BR', { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' }); } function navigateDate(direction: "prev" | "next") { @@ -201,121 +176,237 @@ export default function PacientePage() { ); function Consultas() { + const router = useRouter() + const [tipoConsulta, setTipoConsulta] = useState<'teleconsulta' | 'presencial'>('teleconsulta') + const [especialidade, setEspecialidade] = useState('cardiologia') + const [localizacao, setLocalizacao] = useState('') + const [mostrarAgendadas, setMostrarAgendadas] = useState(false) + const hoverPrimaryClass = "transition duration-200 hover:bg-[#2563eb] hover:text-white focus-visible:ring-2 focus-visible:ring-[#2563eb]/60 active:scale-[0.97]" + const activeToggleClass = "w-full transition duration-200 focus-visible:ring-2 focus-visible:ring-[#2563eb]/60 active:scale-[0.97] bg-[#2563eb] text-white hover:bg-[#2563eb] hover:text-white" + const inactiveToggleClass = "w-full transition duration-200 bg-slate-50 text-[#2563eb] border border-[#2563eb]/30 hover:bg-slate-100 hover:text-[#2563eb] dark:bg-white/5 dark:text-white dark:hover:bg-white/10 dark:border-white/20" + const hoverPrimaryIconClass = "rounded-xl bg-white text-[#1e293b] border border-black/10 shadow-[0_2px_8px_rgba(0,0,0,0.03)] transition duration-200 hover:bg-[#2563eb] hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#2563eb] dark:bg-slate-800 dark:text-slate-100 dark:border-white/10 dark:shadow-none dark:hover:bg-[#2563eb] dark:hover:text-white" + const today = new Date(); today.setHours(0, 0, 0, 0); + const selectedDate = new Date(currentDate); selectedDate.setHours(0, 0, 0, 0); + const isSelectedDateToday = selectedDate.getTime() === today.getTime() + + const handlePesquisar = () => { + const params = new URLSearchParams({ + tipo: tipoConsulta, + especialidade, + local: localizacao + }) + router.push(`/resultados?${params.toString()}`) + } + return (
-
-

Minhas Consultas

-
- {/* Navegação de Data */} -
-
- -

- {formatDatePt(todayString)} -

- - -
-
- {consultasDoDia.length} consulta - {consultasDoDia.length !== 1 ? "s" : ""} agendada - {consultasDoDia.length !== 1 ? "s" : ""} -
-
- {/* Lista de Consultas do Dia */} -
- {consultasDoDia.length === 0 ? ( -
- -

- Nenhuma consulta agendada para este dia -

-

Você pode agendar uma nova consulta

- +
+
+

Agende sua próxima consulta

+

Escolha o formato ideal, selecione a especialidade e encontre o profissional perfeito para você.

+
+ +
+
+ +
+ + +
- ) : ( - consultasDoDia.map((consulta) => ( -
-
-
-
-
-
- - {consulta.medico} -
-
- {consulta.especialidade} • {consulta.local} -
-
-
-
- - {consulta.hora} -
-
-
- {consulta.status} -
-
-
- - {consulta.status !== "Cancelada" && ( - - )} - {consulta.status !== "Cancelada" && ( - - )} -
+ +
+
+ + +
+ +
+ +
+ + setLocalizacao(event.target.value)} + placeholder="Cidade ou estado" + className="pl-9" + />
- )) - )} +
+ + +
+ +
+ +
+ + setMostrarAgendadas(open)}> + + + Consultas agendadas + Gerencie suas consultas confirmadas, pendentes ou canceladas. + + +
+
+ + {formatDatePt(currentDate)} + + {isSelectedDateToday && ( + + )} +
+
+ {consultasDoDia.length} consulta{consultasDoDia.length !== 1 ? 's' : ''} agendada{consultasDoDia.length !== 1 ? 's' : ''} +
+
+ +
+ {consultasDoDia.length === 0 ? ( +
+ +

Nenhuma consulta agendada para este dia

+

Use a busca para marcar uma nova consulta.

+
+ ) : ( + consultasDoDia.map(consulta => ( +
+
+
+ +
+
+ + {consulta.medico} +
+

+ {consulta.especialidade} • {consulta.local} +

+
+
+ +
+ + {consulta.hora} +
+ +
+ + {consulta.status} + +
+ +
+ + {consulta.status !== 'Cancelada' && ( + + )} + {consulta.status !== 'Cancelada' && ( + + )} +
+
+
+ )) + )} +
+ + + + +
+
); } diff --git a/susconecta/app/resultados/page.tsx b/susconecta/app/resultados/page.tsx new file mode 100644 index 0000000..2933e39 --- /dev/null +++ b/susconecta/app/resultados/page.tsx @@ -0,0 +1,977 @@ +'use client' + +import { useMemo, useState } from 'react' +import { useSearchParams, useRouter } from 'next/navigation' +import { Button } from '@/components/ui/button' +import { Card } from '@/components/ui/card' +import { Toggle } from '@/components/ui/toggle' +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' +import { Badge } from '@/components/ui/badge' +import { Avatar, AvatarFallback } from '@/components/ui/avatar' +import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog' +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' +import { + Building2, + Filter, + Globe, + HeartPulse, + Languages, + MapPin, + ShieldCheck, + Star, + Stethoscope, + ChevronRight, + UserRound +} from 'lucide-react' +import { cn } from '@/lib/utils' + +type TipoConsulta = 'teleconsulta' | 'local' + +type Medico = { + id: number + nome: string + especialidade: string + crm: string + categoriaHero: string + avaliacao: number + avaliacaoQtd: number + convenios: string[] + endereco?: string + bairro?: string + cidade?: string + precoLocal?: string + precoTeleconsulta?: string + atendeLocal: boolean + atendeTele: boolean + agenda: { + label: string + data: string + horarios: string[] + }[] + experiencia: string[] + planosSaude: string[] + consultorios: { nome: string; endereco: string; telefone: string }[] + servicos: { nome: string; preco: string }[] + opinioes: { id: number; paciente: string; data: string; nota: number; comentario: string }[] +} + +const especialidadesHero = ['Psicólogo', 'Médico clínico geral', 'Pediatra', 'Dentista', 'Ginecologista', 'Veja mais'] + +const medicosBase: Medico[] = [ + { + id: 1, + nome: 'Paula Pontes', + especialidade: 'Psicóloga clínica', + crm: 'CRP SE 19/4244', + categoriaHero: 'Psicólogo', + avaliacao: 4.9, + avaliacaoQtd: 23, + convenios: ['Amil', 'Unimed'], + endereco: 'Av. Doutor José Machado de Souza, 200 - Jardins', + bairro: 'Jardins', + cidade: 'Aracaju • SE', + precoLocal: 'R$ 180', + precoTeleconsulta: 'R$ 160', + atendeLocal: true, + atendeTele: true, + agenda: [ + { label: 'Hoje', data: '9 Out', horarios: [] }, + { label: 'Amanhã', data: '10 Out', horarios: ['09:00', '10:00', '11:00', '12:00', '13:00'] }, + { label: 'Sáb.', data: '11 Out', horarios: ['11:00', '12:00', '13:00', '14:00'] }, + { label: 'Dom.', data: '12 Out', horarios: [] } + ] + }, + { + id: 2, + nome: 'Marcos Vieira', + especialidade: 'Psicólogo comportamental', + crm: 'CRP SE 24/1198', + categoriaHero: 'Psicólogo', + avaliacao: 4.7, + avaliacaoQtd: 31, + convenios: ['SulAmérica', 'Bradesco Saúde'], + endereco: 'Rua Juarez Távora, 155 - São José', + bairro: 'São José', + cidade: 'Aracaju • SE', + precoLocal: 'R$ 190', + precoTeleconsulta: 'R$ 150', + atendeLocal: true, + atendeTele: true, + agenda: [ + { label: 'Hoje', data: '9 Out', horarios: ['14:00', '16:00'] }, + { label: 'Amanhã', data: '10 Out', horarios: ['10:00', '11:00', '12:00'] }, + { label: 'Sáb.', data: '11 Out', horarios: ['09:00', '10:30'] }, + { label: 'Dom.', data: '12 Out', horarios: [] } + ] + }, + { + id: 3, + nome: 'Julia Azevedo', + especialidade: 'Psicóloga infantil', + crm: 'CRP SE 23/4476', + categoriaHero: 'Psicólogo', + avaliacao: 4.95, + avaliacaoQtd: 45, + convenios: ['NotreDame Intermédica', 'Particular'], + precoTeleconsulta: 'R$ 140', + atendeLocal: false, + atendeTele: true, + agenda: [ + { label: 'Hoje', data: '9 Out', horarios: ['09:00'] }, + { label: 'Amanhã', data: '10 Out', horarios: ['09:30', '11:30'] }, + { label: 'Sáb.', data: '11 Out', horarios: ['08:30', '10:00', '11:00'] }, + { label: 'Dom.', data: '12 Out', horarios: [] } + ] + }, + { + id: 4, + nome: 'Rafael Sousa', + especialidade: 'Neuropsicólogo', + crm: 'CRP BA 03/8874', + categoriaHero: 'Psicólogo', + avaliacao: 4.82, + avaliacaoQtd: 52, + convenios: ['Amil', 'Particular'], + endereco: 'Rua Riachão, 77 - Centro', + bairro: 'Centro', + cidade: 'Aracaju • SE', + precoLocal: 'R$ 210', + atendeLocal: true, + atendeTele: false, + agenda: [ + { label: 'Hoje', data: '9 Out', horarios: [] }, + { label: 'Amanhã', data: '10 Out', horarios: ['09:00', '13:00'] }, + { label: 'Sáb.', data: '11 Out', horarios: ['10:00', '12:00'] }, + { label: 'Dom.', data: '12 Out', horarios: ['09:30'] } + ] + }, + { + id: 5, + nome: 'Lucas Amorim', + especialidade: 'Clínico geral', + crm: 'CRM SE 5122', + categoriaHero: 'Médico clínico geral', + avaliacao: 4.88, + avaliacaoQtd: 98, + convenios: ['Amil', 'Bradesco Saúde'], + endereco: 'Av. Beira Mar, 402 - Coroa do Meio', + bairro: 'Coroa do Meio', + cidade: 'Aracaju • SE', + precoLocal: 'R$ 220', + atendeLocal: true, + atendeTele: true, + agenda: [ + { label: 'Hoje', data: '9 Out', horarios: ['09:00', '11:00'] }, + { label: 'Amanhã', data: '10 Out', horarios: ['08:00', '09:30', '14:00'] }, + { label: 'Sáb.', data: '11 Out', horarios: ['10:30', '12:00'] }, + { label: 'Dom.', data: '12 Out', horarios: [] } + ] + }, + { + id: 6, + nome: 'Dr. João Silva', + especialidade: 'Ortopedista', + crm: 'CRM RJ 90876', + categoriaHero: 'Veja mais', + avaliacao: 4.7, + avaliacaoQtd: 96, + convenios: ['Unimed', 'Bradesco Saúde'], + endereco: 'Av. Beira Mar, 1450 - Farolândia', + bairro: 'Farolândia', + cidade: 'Aracaju • SE', + precoLocal: 'R$ 310', + atendeLocal: true, + atendeTele: false, + agenda: [ + { label: 'Hoje', data: '9 Out', horarios: [] }, + { label: 'Amanhã', data: '10 Out', horarios: ['08:00', '09:00'] }, + { label: 'Sáb.', data: '11 Out', horarios: ['10:00'] }, + { label: 'Dom.', data: '12 Out', horarios: [] } + ] + }, + { + id: 7, + nome: 'Dra. Beatriz Moura', + especialidade: 'Ginecologista', + crm: 'CRM BA 52110', + categoriaHero: 'Veja mais', + avaliacao: 4.95, + avaliacaoQtd: 186, + convenios: ['NotreDame Intermédica', 'Particular', 'Amil'], + endereco: 'Rua Tobias Barreto, 512 - Bairro São José', + bairro: 'São José', + cidade: 'Aracaju • SE', + precoLocal: 'R$ 280', + precoTeleconsulta: 'R$ 240', + atendeLocal: true, + atendeTele: true, + agenda: [ + { label: 'Hoje', data: '9 Out', horarios: ['14:00', '15:00'] }, + { label: 'Amanhã', data: '10 Out', horarios: ['09:00', '11:00', '16:00'] }, + { label: 'Sáb.', data: '11 Out', horarios: ['10:30', '12:30'] }, + { label: 'Dom.', data: '12 Out', horarios: ['11:30'] } + ] + }, + { + id: 8, + nome: 'Dr. André Lemos', + especialidade: 'Gastroenterologista', + crm: 'CRM SE 9033', + categoriaHero: 'Veja mais', + avaliacao: 4.75, + avaliacaoQtd: 105, + convenios: ['SulAmérica', 'Unimed'], + endereco: 'Rua Arauá, 22 - Centro', + bairro: 'Centro', + cidade: 'Aracaju • SE', + precoLocal: 'R$ 340', + atendeLocal: true, + atendeTele: true, + agenda: [ + { label: 'Hoje', data: '9 Out', horarios: ['13:00'] }, + { label: 'Amanhã', data: '10 Out', horarios: ['08:00', '09:00', '11:00', '15:00'] }, + { label: 'Sáb.', data: '11 Out', horarios: ['09:30', '10:15'] }, + { label: 'Dom.', data: '12 Out', horarios: [] } + ] + }, + { + id: 9, + nome: 'Dra. Fernanda Lima', + especialidade: 'Médico clínico geral', + crm: 'CRM SE 7890', + categoriaHero: 'Médico clínico geral', + avaliacao: 4.9, + avaliacaoQtd: 110, + convenios: ['Amil', 'Unimed', 'Bradesco Saúde'], + endereco: 'Av. Rio de Janeiro, 300 - São José', + bairro: 'São José', + cidade: 'Aracaju • SE', + precoLocal: 'R$ 250', + atendeLocal: true, + atendeTele: true, + agenda: [ + { label: 'Hoje', data: '9 Out', horarios: ['09:00', '11:00'] }, + { label: 'Amanhã', data: '10 Out', horarios: ['08:00', '09:30', '14:00'] }, + { label: 'Sáb.', data: '11 Out', horarios: ['10:30', '12:00'] }, + { label: 'Dom.', data: '12 Out', horarios: [] } + ] + }, + { + id: 10, + nome: 'Dra. Helena Castro', + especialidade: 'Pediatra geral', + crm: 'CRM SE 7812', + categoriaHero: 'Pediatra', + avaliacao: 4.92, + avaliacaoQtd: 134, + convenios: ['Amil', 'Unimed', 'SulAmérica'], + endereco: 'Rua José Hipólito, 98 - Suíssa', + bairro: 'Suíssa', + cidade: 'Aracaju • SE', + precoLocal: 'R$ 260', + precoTeleconsulta: 'R$ 220', + atendeLocal: true, + atendeTele: true, + agenda: [ + { label: 'Hoje', data: '9 Out', horarios: ['09:00', '11:30'] }, + { label: 'Amanhã', data: '10 Out', horarios: ['08:30', '10:00', '14:00'] }, + { label: 'Sáb.', data: '11 Out', horarios: ['09:30', '11:00'] }, + { label: 'Dom.', data: '12 Out', horarios: [] } + ] + }, + { + id: 11, + nome: 'Dr. Vinícius Prado', + especialidade: 'Pediatra neonatologista', + crm: 'CRM SE 6331', + categoriaHero: 'Pediatra', + avaliacao: 4.85, + avaliacaoQtd: 89, + convenios: ['Bradesco Saúde', 'NotreDame Intermédica'], + endereco: 'Av. Augusto Franco, 2220 - Siqueira Campos', + bairro: 'Siqueira Campos', + cidade: 'Aracaju • SE', + precoLocal: 'R$ 280', + atendeLocal: true, + atendeTele: false, + agenda: [ + { label: 'Hoje', data: '9 Out', horarios: [] }, + { label: 'Amanhã', data: '10 Out', horarios: ['08:00', '09:00', '11:30'] }, + { label: 'Sáb.', data: '11 Out', horarios: ['10:00'] }, + { label: 'Dom.', data: '12 Out', horarios: ['09:30'] } + ] + }, + { + id: 12, + nome: 'Dra. Marina Salles', + especialidade: 'Pediatra emergencista', + crm: 'CRM BA 85660', + categoriaHero: 'Pediatra', + avaliacao: 4.78, + avaliacaoQtd: 57, + convenios: ['Particular', 'Amil'], + precoTeleconsulta: 'R$ 210', + atendeLocal: false, + atendeTele: true, + agenda: [ + { label: 'Hoje', data: '9 Out', horarios: ['13:00', '15:00'] }, + { label: 'Amanhã', data: '10 Out', horarios: ['09:30', '12:30'] }, + { label: 'Sáb.', data: '11 Out', horarios: ['09:00'] }, + { label: 'Dom.', data: '12 Out', horarios: [] } + ] + }, + { + id: 13, + nome: 'Dr. Caio Moura', + especialidade: 'Pediatra pneumologista', + crm: 'CRM SE 7345', + categoriaHero: 'Pediatra', + avaliacao: 4.91, + avaliacaoQtd: 102, + convenios: ['SulAmérica', 'Unimed'], + endereco: 'Av. Hermes Fontes, 445 - Salgado Filho', + bairro: 'Salgado Filho', + cidade: 'Aracaju • SE', + precoLocal: 'R$ 270', + precoTeleconsulta: 'R$ 230', + atendeLocal: true, + atendeTele: true, + agenda: [ + { label: 'Hoje', data: '9 Out', horarios: ['10:00'] }, + { label: 'Amanhã', data: '10 Out', horarios: ['09:00', '11:00', '16:00'] }, + { label: 'Sáb.', data: '11 Out', horarios: ['09:30', '11:30'] }, + { label: 'Dom.', data: '12 Out', horarios: [] } + ] + }, + { + id: 14, + nome: 'Dra. Patrícia Freire', + especialidade: 'Cirurgiã-dentista', + crm: 'CRO SE 2133', + categoriaHero: 'Dentista', + avaliacao: 4.9, + avaliacaoQtd: 176, + convenios: ['OdontoPrev', 'Amil Dental'], + endereco: 'Rua Itabaiana, 410 - Centro', + bairro: 'Centro', + cidade: 'Aracaju • SE', + precoLocal: 'R$ 200', + precoTeleconsulta: 'R$ 160', + atendeLocal: true, + atendeTele: true, + agenda: [ + { label: 'Hoje', data: '9 Out', horarios: ['09:00', '13:30'] }, + { label: 'Amanhã', data: '10 Out', horarios: ['08:30', '10:00', '14:30'] }, + { label: 'Sáb.', data: '11 Out', horarios: ['09:30', '11:00'] }, + { label: 'Dom.', data: '12 Out', horarios: [] } + ] + }, + { + id: 15, + nome: 'Dr. Henrique Assis', + especialidade: 'Implantodontista', + crm: 'CRO SE 1450', + categoriaHero: 'Dentista', + avaliacao: 4.83, + avaliacaoQtd: 94, + convenios: ['SulAmérica Odonto', 'Particular'], + endereco: 'Av. Jorge Amado, 321 - Atalaia', + bairro: 'Atalaia', + cidade: 'Aracaju • SE', + precoLocal: 'R$ 350', + atendeLocal: true, + atendeTele: false, + agenda: [ + { label: 'Hoje', data: '9 Out', horarios: [] }, + { label: 'Amanhã', data: '10 Out', horarios: ['09:00', '11:00'] }, + { label: 'Sáb.', data: '11 Out', horarios: ['10:30'] }, + { label: 'Dom.', data: '12 Out', horarios: [] } + ] + }, + { + id: 16, + nome: 'Dra. Lívia Teles', + especialidade: 'Ortodontista', + crm: 'CRO BA 11567', + categoriaHero: 'Dentista', + avaliacao: 4.88, + avaliacaoQtd: 140, + convenios: ['Uniodonto', 'Amil Dental', 'Particular'], + precoTeleconsulta: 'R$ 120', + atendeLocal: false, + atendeTele: true, + agenda: [ + { label: 'Hoje', data: '9 Out', horarios: ['17:00'] }, + { label: 'Amanhã', data: '10 Out', horarios: ['09:00', '10:30', '15:00'] }, + { label: 'Sáb.', data: '11 Out', horarios: ['08:30', '09:30'] }, + { label: 'Dom.', data: '12 Out', horarios: [] } + ] + }, + { + id: 17, + nome: 'Dr. Pablo Menezes', + especialidade: 'Endodontista', + crm: 'CRO SE 2099', + categoriaHero: 'Dentista', + avaliacao: 4.76, + avaliacaoQtd: 83, + convenios: ['OdontoPrev', 'SulAmérica Odonto'], + endereco: 'Rua Cedro, 70 - Grageru', + bairro: 'Grageru', + cidade: 'Aracaju • SE', + precoLocal: 'R$ 230', + precoTeleconsulta: 'R$ 190', + atendeLocal: true, + atendeTele: true, + agenda: [ + { label: 'Hoje', data: '9 Out', horarios: ['09:00'] }, + { label: 'Amanhã', data: '10 Out', horarios: ['08:00', '09:00', '13:00'] }, + { label: 'Sáb.', data: '11 Out', horarios: ['09:30'] }, + { label: 'Dom.', data: '12 Out', horarios: [] } + ] + }, + { + id: 18, + nome: 'Dra. Beatriz Moura', + especialidade: 'Ginecologista obstetra', + crm: 'CRM BA 52110', + categoriaHero: 'Ginecologista', + avaliacao: 4.95, + avaliacaoQtd: 186, + convenios: ['NotreDame Intermédica', 'Particular', 'Amil'], + endereco: 'Rua Tobias Barreto, 512 - São José', + bairro: 'São José', + cidade: 'Aracaju • SE', + precoLocal: 'R$ 280', + precoTeleconsulta: 'R$ 240', + atendeLocal: true, + atendeTele: true, + agenda: [ + { label: 'Hoje', data: '9 Out', horarios: ['14:00', '15:00'] }, + { label: 'Amanhã', data: '10 Out', horarios: ['09:00', '11:00', '16:00'] }, + { label: 'Sáb.', data: '11 Out', horarios: ['10:30', '12:30'] }, + { label: 'Dom.', data: '12 Out', horarios: ['11:30'] } + ] + }, + { + id: 19, + nome: 'Dra. Camila Albuquerque', + especialidade: 'Ginecologista endocrinologista', + crm: 'CRM SE 6774', + categoriaHero: 'Ginecologista', + avaliacao: 4.89, + avaliacaoQtd: 122, + convenios: ['SulAmérica', 'Unimed'], + endereco: 'Av. Gonçalo Prado Rollemberg, 167 - São José', + bairro: 'São José', + cidade: 'Aracaju • SE', + precoLocal: 'R$ 300', + atendeLocal: true, + atendeTele: false, + agenda: [ + { label: 'Hoje', data: '9 Out', horarios: [] }, + { label: 'Amanhã', data: '10 Out', horarios: ['08:00', '09:30', '15:00'] }, + { label: 'Sáb.', data: '11 Out', horarios: ['09:00'] }, + { label: 'Dom.', data: '12 Out', horarios: [] } + ] + }, + { + id: 20, + nome: 'Dra. Renata Figueiredo', + especialidade: 'Ginecologista minimamente invasiva', + crm: 'CRM PE 112233', + categoriaHero: 'Ginecologista', + avaliacao: 4.94, + avaliacaoQtd: 208, + convenios: ['Amil', 'Bradesco Saúde', 'Particular'], + precoTeleconsulta: 'R$ 260', + atendeLocal: false, + atendeTele: true, + agenda: [ + { label: 'Hoje', data: '9 Out', horarios: ['09:00', '10:30'] }, + { label: 'Amanhã', data: '10 Out', horarios: ['08:30', '11:00', '14:30'] }, + { label: 'Sáb.', data: '11 Out', horarios: ['09:45'] }, + { label: 'Dom.', data: '12 Out', horarios: [] } + ] + }, + { + id: 21, + nome: 'Dr. Eduardo Fontes', + especialidade: 'Ginecologista mastologista', + crm: 'CRM SE 7012', + categoriaHero: 'Ginecologista', + avaliacao: 4.8, + avaliacaoQtd: 95, + convenios: ['NotreDame Intermédica', 'SulAmérica'], + endereco: 'Rua Teófilo Dantas, 55 - Centro', + bairro: 'Centro', + cidade: 'Aracaju • SE', + precoLocal: 'R$ 310', + atendeLocal: true, + atendeTele: true, + agenda: [ + { label: 'Hoje', data: '9 Out', horarios: ['08:30'] }, + { label: 'Amanhã', data: '10 Out', horarios: ['09:00', '11:00', '16:30'] }, + { label: 'Sáb.', data: '11 Out', horarios: ['10:00', '12:00'] }, + { label: 'Dom.', data: '12 Out', horarios: [] } + ] + } +] + +const medicosMock: Medico[] = medicosBase.map((medico, index) => ({ + ...medico, + experiencia: + medico.experiencia ?? + [ + 'Especialista com atuação reconhecida pelo respectivo conselho profissional.', + 'Formação continuada em instituições nacionais e internacionais.', + 'Atendimento humanizado com foco em resultados sustentáveis.' + ], + planosSaude: + medico.planosSaude ?? medico.convenios ?? ['Amil', 'Unimed', 'SulAmérica'], + consultorios: + medico.consultorios ?? + (medico.endereco + ? [ + { + nome: 'Clínica principal', + endereco: `${medico.endereco}${medico.cidade ? ` — ${medico.cidade}` : ''}`, + telefone: '(79) 4002-8922' + } + ] + : []), + servicos: + medico.servicos ?? + [ + { + nome: 'Consulta inicial', + preco: medico.precoLocal ?? medico.precoTeleconsulta ?? 'Sob consulta' + }, + { nome: 'Retorno em até 30 dias', preco: 'R$ 150' } + ], + opinioes: + medico.opinioes ?? + [ + { + id: index * 2 + 1, + paciente: 'Ana P.', + data: '01/09/2025', + nota: 5, + comentario: 'Profissional muito atencioso e detalhista.' + }, + { + id: index * 2 + 2, + paciente: 'Marcos L.', + data: '18/08/2025', + nota: 4, + comentario: 'Explicações claras e ambiente acolhedor.' + } + ] +})) + +export default function ResultadosPage() { + const params = useSearchParams() + const router = useRouter() + const [tipoConsulta, setTipoConsulta] = useState( + params.get('tipo') === 'presencial' ? 'local' : 'teleconsulta' + ) + const [especialidadeHero, setEspecialidadeHero] = useState(params.get('especialidade') || 'Psicólogo') + const [convenio, setConvenio] = useState('Todos') + const [bairro, setBairro] = useState('Todos') + const [modalFiltrosAberto, setModalFiltrosAberto] = useState(false) + const [agendasExpandida, setAgendasExpandida] = useState>({}) + const [medicoSelecionado, setMedicoSelecionado] = useState(null) + const [abaDetalhe, setAbaDetalhe] = useState('experiencia') + + const profissionais = useMemo(() => { + return medicosMock.filter(medico => { + if (tipoConsulta === 'local' && !medico.atendeLocal) return false + if (tipoConsulta === 'teleconsulta' && !medico.atendeTele) return false + if (convenio !== 'Todos' && !medico.convenios.includes(convenio)) return false + if (bairro !== 'Todos' && medico.bairro !== bairro) return false + if (especialidadeHero !== 'Veja mais' && medico.categoriaHero !== especialidadeHero) return false + if (especialidadeHero === 'Veja mais' && medico.categoriaHero !== 'Veja mais') return false + return true + }) + }, [bairro, convenio, especialidadeHero, tipoConsulta]) + + const toggleBase = + 'rounded-full px-4 py-[10px] text-sm font-medium transition hover:bg-primary hover:text-primary-foreground focus-visible:ring-2 focus-visible:ring-primary/60 active:scale-[0.97]' + + return ( +
+
+
+
+
+

Resultados da procura

+

Qual especialização você deseja?

+
+ +
+
+ {especialidadesHero.map(item => ( + + ))} +
+
+ +
+ setTipoConsulta('teleconsulta')} + className={cn(toggleBase, tipoConsulta === 'teleconsulta' ? 'bg-primary text-primary-foreground' : 'border border-primary/40 text-primary')} + > + + Teleconsulta + + setTipoConsulta('local')} + className={cn(toggleBase, tipoConsulta === 'local' ? 'bg-primary text-primary-foreground' : 'border border-primary/40 text-primary')} + > + + Consulta no local + + + + + + + + + +
+ +
+ {profissionais.map(medico => ( + +
+ + + + + +
+
+

{medico.nome}

+ {medico.especialidade} +
+
+ + + {medico.avaliacao.toFixed(1)} • {medico.avaliacaoQtd} avaliações + + {medico.crm} + {medico.convenios.join(', ')} +
+
+ +
+ + {tipoConsulta === 'local' && medico.atendeLocal && ( +
+ + + {medico.endereco} + +
+ {medico.cidade} + {medico.precoLocal} +
+
+ )} + + {tipoConsulta === 'teleconsulta' && medico.atendeTele && ( +
+ + + Teleconsulta + + {medico.precoTeleconsulta} +
+ )} + +
+ + + Idiomas: Português, Inglês + + + + Acolhimento em cada consulta + + + + Pagamento seguro + + + + Especialista recomendado + +
+ +
+ + + +
+ +
+
+ {medico.agenda.map(coluna => { + const horarios = agendasExpandida[medico.id] ? coluna.horarios : coluna.horarios.slice(0, 3) + return ( +
+

{coluna.label}

+

{coluna.data}

+
+ {horarios.length ? ( + horarios.map(horario => ( + + )) + ) : ( + + Sem horários + + )} + {!agendasExpandida[medico.id] && coluna.horarios.length > 3 && ( + +{coluna.horarios.length - 3} horários + )} +
+
+ ) + })} +
+
+
+ ))} + + {!profissionais.length && ( + + Nenhum profissional encontrado. Ajuste os filtros para ver outras opções. + + )} +
+ + !open && setMedicoSelecionado(null)}> + + {medicoSelecionado && ( + <> + + + {medicoSelecionado.nome} + +

+ {medicoSelecionado.especialidade} • {medicoSelecionado.crm} +

+
+ +
+
+ + + {medicoSelecionado.avaliacao.toFixed(1)} ({medicoSelecionado.avaliacaoQtd} avaliações) + + {medicoSelecionado.planosSaude.join(' • ')} +
+ + + + + Experiência + + + Planos de saúde + + + Consultórios + + + Serviços + + + Opiniões ({medicoSelecionado.opinioes.length}) + + + Agenda + + + + + {medicoSelecionado.experiencia.map((linha, index) => ( +

{linha}

+ ))} +
+ + + {medicoSelecionado.planosSaude.map(plano => ( + + {plano} + + ))} + + + + {medicoSelecionado.consultorios.length ? ( + medicoSelecionado.consultorios.map((consultorio, index) => ( +
+

{consultorio.nome}

+

{consultorio.endereco}

+

Telefone: {consultorio.telefone}

+
+ )) + ) : ( +

Atendimento exclusivamente por teleconsulta.

+ )} +
+ + + {medicoSelecionado.servicos.map(servico => ( +
+ {servico.nome} + {servico.preco} +
+ ))} +
+ + + {medicoSelecionado.opinioes.map(opiniao => ( +
+
+ {opiniao.paciente} + {opiniao.data} +
+
+ {Array.from({ length: opiniao.nota }).map((_, index) => ( + + ))} +
+

{opiniao.comentario}

+
+ ))} +
+ + +

+ Escolha o melhor horário disponível para sua consulta. +

+
+
+ {medicoSelecionado.agenda.map(coluna => ( +
+

{coluna.label}

+

{coluna.data}

+
+ {coluna.horarios.length ? ( + coluna.horarios.map(horario => ( + + )) + ) : ( + + Sem horários + + )} +
+
+ ))} +
+
+
+
+
+ + )} +
+
+
+
+ ) +} diff --git a/susconecta/components/forms/doctor-registration-form.tsx b/susconecta/components/forms/doctor-registration-form.tsx index 58fb11a..775f37e 100644 --- a/susconecta/components/forms/doctor-registration-form.tsx +++ b/susconecta/components/forms/doctor-registration-form.tsx @@ -401,29 +401,40 @@ export function DoctorRegistrationForm({ setSubmitting(true); setErrors((e) => ({ ...e, submit: "" })); - const payload: MedicoInput = { - user_id: null, - crm: form.crm || "", - crm_uf: form.estado_crm || "", - specialty: form.especialidade || "", - full_name: form.full_name || "", - cpf: form.cpf || "", - email: form.email || "", - phone_mobile: form.celular || "", - phone2: form.telefone || null, - cep: form.cep || "", - street: form.logradouro || "", - number: form.numero || "", - complement: form.complemento || undefined, - neighborhood: form.bairro || undefined, - city: form.cidade || "", - state: form.estado || "", - birth_date: form.data_nascimento || null, - rg: form.rg || null, - active: true, - created_by: null, - updated_by: null, - }; +const payload: MedicoInput = { + user_id: null, + crm: form.crm || "", + crm_uf: form.estado_crm || "", + specialty: form.especialidade || "", + full_name: form.full_name || "", + cpf: form.cpf || "", + email: form.email || "", + phone_mobile: form.celular || "", + phone2: form.telefone || null, + cep: form.cep || "", + street: form.logradouro || "", + number: form.numero || "", + complement: form.complemento || undefined, + neighborhood: form.bairro || undefined, + city: form.cidade || "", + state: form.estado || "", + // converte dd/MM/yyyy para ISO + birth_date: (() => { + try { + const parts = String(form.data_nascimento).split(/\D+/).filter(Boolean); + if (parts.length === 3) { + const [d, m, y] = parts; + const date = new Date(Number(y), Number(m) - 1, Number(d)); + if (!isNaN(date.getTime())) return date.toISOString().slice(0, 10); + } + } catch {} + return null; + })(), + rg: form.rg || null, + active: true, + created_by: null, + updated_by: null, +}; // Validação dos campos obrigatórios const requiredFields = [ @@ -790,11 +801,20 @@ export function DoctorRegistrationForm({
- setField("data_nascimento", e.target.value) - } + onChange={(e) => { + const v = e.target.value.replace(/[^0-9\/]/g, "").slice(0, 10); + setField("data_nascimento", v); + }} + onBlur={() => { + const raw = form.data_nascimento; + const parts = raw.split(/\D+/).filter(Boolean); + if (parts.length === 3) { + const d = `${parts[0].padStart(2,'0')}/${parts[1].padStart(2,'0')}/${parts[2].padStart(4,'0')}`; + setField("data_nascimento", d); + } + }} />
diff --git a/susconecta/components/forms/patient-registration-form.tsx b/susconecta/components/forms/patient-registration-form.tsx index 0cfffb5..bef7db7 100644 --- a/susconecta/components/forms/patient-registration-form.tsx +++ b/susconecta/components/forms/patient-registration-form.tsx @@ -1,6 +1,7 @@ "use client"; import { useEffect, useMemo, useState } from "react"; +import { format, parse, isValid, parseISO } from "date-fns"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; @@ -154,24 +155,26 @@ export function PatientRegistrationForm({ const p = await buscarPacientePorId(String(patientId)); console.log("[PatientForm] Dados recebidos:", p); setForm((s) => ({ - ...s, - nome: p.full_name || "", // 👈 trocar nome → full_name - nome_social: p.social_name || "", - cpf: p.cpf || "", - rg: p.rg || "", - sexo: p.sex || "", - birth_date: p.birth_date || "", // 👈 trocar data_nascimento → birth_date - telefone: p.phone_mobile || "", - email: p.email || "", - cep: p.cep || "", - logradouro: p.street || "", - numero: p.number || "", - complemento: p.complement || "", - bairro: p.neighborhood || "", - cidade: p.city || "", - estado: p.state || "", - observacoes: p.notes || "", - })); + ...s, + nome: p.full_name || "", // 👈 trocar nome → full_name + nome_social: p.social_name || "", + cpf: p.cpf || "", + rg: p.rg || "", + sexo: p.sex || "", + birth_date: p.birth_date ? (() => { + try { return format(parseISO(String(p.birth_date)), 'dd/MM/yyyy'); } catch { return String(p.birth_date); } + })() : "", + telefone: p.phone_mobile || "", + email: p.email || "", + cep: p.cep || "", + logradouro: p.street || "", + numero: p.number || "", + complemento: p.complement || "", + bairro: p.neighborhood || "", + cidade: p.city || "", + estado: p.state || "", + observacoes: p.notes || "", +})); const ax = await listarAnexos(String(patientId)).catch(() => []); setServerAnexos(Array.isArray(ax) ? ax : []); @@ -235,25 +238,38 @@ export function PatientRegistrationForm({ } function toPayload(): PacienteInput { - return { - full_name: form.nome, // 👈 troca 'nome' por 'full_name' - social_name: form.nome_social || null, - cpf: form.cpf, - rg: form.rg || null, - sex: form.sexo || null, - birth_date: form.birth_date || null, // 👈 troca data_nascimento → birth_date - phone_mobile: form.telefone || null, - email: form.email || null, - cep: form.cep || null, - street: form.logradouro || null, - number: form.numero || null, - complement: form.complemento || null, - neighborhood: form.bairro || null, - city: form.cidade || null, - state: form.estado || null, - notes: form.observacoes || null, - }; - } + // converte dd/MM/yyyy para ISO (yyyy-MM-dd) se possível + let isoDate: string | null = null; + try { + const parts = String(form.birth_date).split(/\D+/).filter(Boolean); + if (parts.length === 3) { + const [d, m, y] = parts; + const date = new Date(Number(y), Number(m) - 1, Number(d)); + if (!isNaN(date.getTime())) { + isoDate = date.toISOString().slice(0, 10); + } + } + } catch {} + + return { + full_name: form.nome, // 👈 troca 'nome' por 'full_name' + social_name: form.nome_social || null, + cpf: form.cpf, + rg: form.rg || null, + sex: form.sexo || null, + birth_date: isoDate, // enviar ISO ou null + phone_mobile: form.telefone || null, + email: form.email || null, + cep: form.cep || null, + street: form.logradouro || null, + number: form.numero || null, + complement: form.complemento || null, + neighborhood: form.bairro || null, + city: form.cidade || null, + state: form.estado || null, + notes: form.observacoes || null, + }; +} async function handleSubmit(event_: React.FormEvent) { event_.preventDefault(); @@ -603,9 +619,22 @@ export function PatientRegistrationForm({
setField("birth_date", e.target.value)} + onChange={(e) => { + // permita apenas números e '/' + const v = e.target.value.replace(/[^0-9\/]/g, "").slice(0, 10); + setField("birth_date", v); + }} + onBlur={() => { + // tenta formatar automaticamente se for uma data válida + const raw = form.birth_date; + const parts = raw.split(/\D+/).filter(Boolean); + if (parts.length === 3) { + const d = `${parts[0].padStart(2,'0')}/${parts[1].padStart(2,'0')}/${parts[2].padStart(4,'0')}`; + setField("birth_date", d); + } + }} />
diff --git a/susconecta/next-env.d.ts b/susconecta/next-env.d.ts index 830fb59..40c3d68 100644 --- a/susconecta/next-env.d.ts +++ b/susconecta/next-env.d.ts @@ -1,6 +1,5 @@ /// /// -/// // NOTE: This file should not be edited -// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. +// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.