546 lines
24 KiB
TypeScript
546 lines
24 KiB
TypeScript
'use client'
|
|
|
|
import type React from "react"
|
|
import { useState, useEffect } from "react"
|
|
import { Button } from "@/components/ui/button"
|
|
import { Input } from "@/components/ui/input"
|
|
import { Label } from "@/components/ui/label"
|
|
import { Textarea } from "@/components/ui/textarea"
|
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"
|
|
import { Alert, AlertDescription } from "@/components/ui/alert"
|
|
import { salvarMedico, DoctorFormData } from "@/lib/api";
|
|
import { formatCPF, formatCelular, formatRG } from "@/lib/formatters";
|
|
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem } from "@/components/ui/command"
|
|
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
|
|
import { ScrollArea } from "@/components/ui/scroll-area"
|
|
import {
|
|
Upload,
|
|
ChevronDown,
|
|
ChevronUp,
|
|
X,
|
|
FileImage,
|
|
User,
|
|
Phone,
|
|
MapPin,
|
|
Save,
|
|
XCircle,
|
|
AlertCircle,
|
|
Loader2,
|
|
Stethoscope,
|
|
Check,
|
|
ChevronsUpDown
|
|
} from "lucide-react"
|
|
|
|
interface DoctorRegistrationFormProps {
|
|
doctorData?: DoctorFormData | null
|
|
onClose?: () => void
|
|
}
|
|
|
|
const especialidadesMedicas = [
|
|
"Acupuntura",
|
|
"Alergia e Imunologia",
|
|
"Anestesiologia",
|
|
"Angiologia",
|
|
"Cancerologia (Oncologia)",
|
|
"Cardiologia",
|
|
"Cirurgia Cardiovascular",
|
|
"Cirurgia da Mão",
|
|
"Cirurgia de Cabeça e Pescoço",
|
|
"Cirurgia do Aparelho Digestivo",
|
|
"Cirurgia Geral",
|
|
"Cirurgia Oncológica",
|
|
"Cirurgia Pediátrica",
|
|
"Cirurgia Plástica",
|
|
"Cirurgia Torácica",
|
|
"Cirurgia Vascular",
|
|
"Clínica Médica",
|
|
"Coloproctologia",
|
|
"Dermatologia",
|
|
"Endocrinologia e Metabologia",
|
|
"Endoscopia",
|
|
"Gastroenterologia",
|
|
"Genética Médica",
|
|
"Geriatria",
|
|
"Ginecologia e Obstetrícia",
|
|
"Hematologia e Hemoterapia",
|
|
"Homeopatia",
|
|
"Infectologia",
|
|
"Mastologia",
|
|
"Medicina de Emergência",
|
|
"Medicina de Família e Comunidade",
|
|
"Medicina do Trabalho",
|
|
"Medicina de Tráfego",
|
|
"Medicina Esportiva",
|
|
"Medicina Física e Reabilitação",
|
|
"Medicina Intensiva",
|
|
"Medicina Legal e Perícia Médica",
|
|
"Medicina Nuclear",
|
|
"Medicina Preventiva e Social",
|
|
"Nefrologia",
|
|
"Neurocirurgia",
|
|
"Neurologia",
|
|
"Nutrologia",
|
|
"Oftalmologia",
|
|
"Ortopedia e Traumatologia",
|
|
"Otorrinolaringologia",
|
|
"Patologia",
|
|
"Patologia Clínica/Medicina Laboratorial",
|
|
"Pediatria",
|
|
"Pneumologia",
|
|
"Psiquiatria",
|
|
"Radiologia e Diagnóstico por Imagem",
|
|
"Radioterapia",
|
|
"Reumatologia",
|
|
"Urologia",
|
|
];
|
|
|
|
export function DoctorRegistrationForm({
|
|
doctorData = null,
|
|
onClose,
|
|
}: DoctorRegistrationFormProps) {
|
|
|
|
const initialFormData: DoctorFormData = {
|
|
nome: "",
|
|
nomeSocial: "",
|
|
cpf: "",
|
|
rg: "",
|
|
crm: "",
|
|
crmUf: "",
|
|
especialidade: "",
|
|
email: "",
|
|
celular: "",
|
|
dataNascimento: "",
|
|
sexo: "",
|
|
cep: "",
|
|
logradouro: "",
|
|
numero: "",
|
|
complemento: "",
|
|
bairro: "",
|
|
cidade: "",
|
|
estado: "",
|
|
observacoes: "",
|
|
photo: null,
|
|
}
|
|
|
|
const [formData, setFormData] = useState<DoctorFormData>(initialFormData)
|
|
const [expandedSections, setExpandedSections] = useState({
|
|
dadosPessoais: true,
|
|
dadosProfissionais: true,
|
|
contato: true,
|
|
endereco: true,
|
|
observacoes: false,
|
|
})
|
|
|
|
const [photoPreview, setPhotoPreview] = useState<string | null>(null)
|
|
const [isLoadingCep, setIsLoadingCep] = useState(false)
|
|
const [errors, setErrors] = useState<Record<string, string>>({})
|
|
const [isSubmitting, setIsSubmitting] = useState(false)
|
|
const [openEspecialidade, setOpenEspecialidade] = useState(false)
|
|
|
|
useEffect(() => {
|
|
if (doctorData) {
|
|
setFormData(doctorData);
|
|
if (doctorData.photo && doctorData.photo instanceof File) {
|
|
const reader = new FileReader()
|
|
reader.onload = (e) => setPhotoPreview(e.target?.result as string)
|
|
reader.readAsDataURL(doctorData.photo)
|
|
}
|
|
} else {
|
|
setFormData(initialFormData);
|
|
setPhotoPreview(null);
|
|
}
|
|
}, [doctorData])
|
|
|
|
const toggleSection = (section: keyof typeof expandedSections) => {
|
|
setExpandedSections((prev) => ({
|
|
...prev,
|
|
[section]: !prev[section],
|
|
}))
|
|
}
|
|
|
|
const handleInputChange = (field: keyof DoctorFormData, value: string | boolean | File | File[] | null) => {
|
|
let formattedValue = value;
|
|
if (typeof value === 'string') {
|
|
if (field === "cpf") {
|
|
formattedValue = formatCPF(value);
|
|
} else if (field === "celular") {
|
|
formattedValue = formatCelular(value);
|
|
} else if (field === "rg") {
|
|
formattedValue = formatRG(value);
|
|
}
|
|
}
|
|
|
|
setFormData((prev) => ({
|
|
...prev,
|
|
[field]: formattedValue,
|
|
}))
|
|
|
|
if (errors[field]) {
|
|
setErrors((prev) => {
|
|
const newErrors = { ...prev }
|
|
delete newErrors[field]
|
|
return newErrors
|
|
})
|
|
}
|
|
}
|
|
|
|
const handlePhotoUpload = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
const file = event.target.files?.[0]
|
|
if (file) {
|
|
if (file.size > 5 * 1024 * 1024) { // 5MB limit
|
|
setErrors((prev) => ({ ...prev, photo: "Arquivo muito grande. Máximo 5MB." }))
|
|
return
|
|
}
|
|
handleInputChange("photo", file)
|
|
const reader = new FileReader()
|
|
reader.onload = (e) => setPhotoPreview(e.target?.result as string)
|
|
reader.readAsDataURL(file)
|
|
}
|
|
}
|
|
|
|
const searchCEP = async (cep: string) => {
|
|
const cleanCEP = cep.replace(/\D/g, "")
|
|
if (cleanCEP.length !== 8) return
|
|
|
|
setIsLoadingCep(true)
|
|
try {
|
|
const response = await fetch(`https://viacep.com.br/ws/${cleanCEP}/json/`)
|
|
const data = await response.json()
|
|
|
|
if (data.erro) {
|
|
setErrors((prev) => ({ ...prev, cep: "CEP não encontrado" }))
|
|
} else {
|
|
handleInputChange("logradouro", data.logradouro || "")
|
|
handleInputChange("bairro", data.bairro || "")
|
|
handleInputChange("cidade", data.localidade || "")
|
|
handleInputChange("estado", data.uf || "")
|
|
}
|
|
} catch (error) {
|
|
console.error("Erro ao buscar CEP:", error)
|
|
setErrors((prev) => ({ ...prev, cep: "Erro ao buscar CEP. Tente novamente." }))
|
|
} finally {
|
|
setIsLoadingCep(false)
|
|
}
|
|
}
|
|
|
|
const validateForm = () => {
|
|
const newErrors: Record<string, string> = {}
|
|
if (!formData.nome.trim()) newErrors.nome = "Nome é obrigatório"
|
|
if (!formData.cpf.trim()) newErrors.cpf = "CPF é obrigatório"
|
|
if (!formData.crm.trim()) newErrors.crm = "CRM é obrigatório"
|
|
if (!formData.crmUf.trim()) newErrors.crmUf = "UF do CRM é obrigatória"
|
|
if (!formData.especialidade.trim()) newErrors.especialidade = "Especialidade é obrigatória"
|
|
if (!formData.celular.trim()) newErrors.celular = "Celular é obrigatório"
|
|
if (!formData.email.trim()) newErrors.email = "E-mail é obrigatório"
|
|
if (!formData.cep.trim()) newErrors.cep = "CEP é obrigatório"
|
|
if (!formData.logradouro.trim()) newErrors.logradouro = "Logradouro é obrigatório"
|
|
if (!formData.numero.trim()) newErrors.numero = "Número é obrigatório"
|
|
if (!formData.bairro.trim()) newErrors.bairro = "Bairro é obrigatório"
|
|
if (!formData.cidade.trim()) newErrors.cidade = "Cidade é obrigatória"
|
|
if (!formData.estado.trim()) newErrors.estado = "Estado é obrigatório"
|
|
|
|
setErrors(newErrors)
|
|
return Object.keys(newErrors).length === 0
|
|
}
|
|
|
|
const handleSubmit = async (event: React.FormEvent) => {
|
|
event.preventDefault()
|
|
if (!validateForm()) return
|
|
|
|
setIsSubmitting(true)
|
|
try {
|
|
await salvarMedico(formData)
|
|
alert(doctorData?.id ? "Médico atualizado com sucesso!" : "Médico cadastrado com sucesso!")
|
|
if (onClose) onClose()
|
|
} catch (error) {
|
|
setErrors({ submit: "Erro ao salvar médico. Tente novamente." })
|
|
} finally {
|
|
setIsSubmitting(false)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit} className="space-y-6">
|
|
{errors.submit && (
|
|
<Alert variant="destructive">
|
|
<AlertCircle className="h-4 w-4" />
|
|
<AlertDescription>{errors.submit}</AlertDescription>
|
|
</Alert>
|
|
)}
|
|
|
|
{/* Dados Pessoais */}
|
|
<Collapsible open={expandedSections.dadosPessoais} onOpenChange={() => toggleSection("dadosPessoais")}>
|
|
<Card>
|
|
<CollapsibleTrigger asChild>
|
|
<CardHeader className="cursor-pointer">
|
|
<CardTitle className="flex items-center justify-between">
|
|
<span className="flex items-center gap-2"><User className="h-4 w-4" />Dados Pessoais</span>
|
|
{expandedSections.dadosPessoais ? <ChevronUp className="h-4 w-4" /> : <ChevronDown className="h-4 w-4" />}
|
|
</CardTitle>
|
|
</CardHeader>
|
|
</CollapsibleTrigger>
|
|
<CollapsibleContent>
|
|
<CardContent className="space-y-4 pt-4">
|
|
<div className="flex items-center gap-4">
|
|
<div className="w-24 h-24 border-2 border-dashed rounded-lg flex items-center justify-center overflow-hidden">
|
|
{photoPreview ? (
|
|
<img src={photoPreview} alt="Preview" className="w-full h-full object-cover" />
|
|
) : (
|
|
<FileImage className="h-8 w-8 text-muted-foreground" />
|
|
)}
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="photo" className="cursor-pointer">
|
|
<Button type="button" variant="outline" asChild>
|
|
<label htmlFor="photo" className="cursor-pointer"><Upload className="mr-2 h-4 w-4" />Carregar Foto</label>
|
|
</Button>
|
|
</Label>
|
|
<Input id="photo" type="file" accept="image/*" className="hidden" onChange={handlePhotoUpload} />
|
|
{errors.photo && <p className="text-sm text-destructive">{errors.photo}</p>}
|
|
<p className="text-xs text-muted-foreground">Máximo 5MB</p>
|
|
</div>
|
|
</div>
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<div className="space-y-2">
|
|
<Label htmlFor="nome">Nome *</Label>
|
|
<Input id="nome" value={formData.nome} onChange={(e) => handleInputChange("nome", e.target.value)} className={errors.nome ? "border-destructive" : ""} />
|
|
{errors.nome && <p className="text-sm text-destructive">{errors.nome}</p>}
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="nomeSocial">Nome Social</Label>
|
|
<Input id="nomeSocial" value={formData.nomeSocial || ''} onChange={(e) => handleInputChange("nomeSocial", e.target.value)} />
|
|
</div>
|
|
</div>
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<div className="space-y-2">
|
|
<Label htmlFor="cpf">CPF *</Label>
|
|
<Input id="cpf" value={formData.cpf} onChange={(e) => handleInputChange("cpf", e.target.value)} placeholder="000.000.000-00" className={errors.cpf ? "border-destructive" : ""} />
|
|
{errors.cpf && <p className="text-sm text-destructive">{errors.cpf}</p>}
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="rg">RG</Label>
|
|
<Input id="rg" value={formData.rg} onChange={(e) => handleInputChange("rg", e.target.value)} placeholder="00.000.000-0"/>
|
|
</div>
|
|
</div>
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<div className="space-y-2">
|
|
<Label>Sexo</Label>
|
|
<Select value={formData.sexo} onValueChange={(value) => handleInputChange("sexo", value)}>
|
|
<SelectTrigger><SelectValue placeholder="Selecione o sexo" /></SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="masculino">Masculino</SelectItem>
|
|
<SelectItem value="feminino">Feminino</SelectItem>
|
|
<SelectItem value="outro">Outro</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="dataNascimento">Data de Nascimento</Label>
|
|
<Input id="dataNascimento" type="date" value={formData.dataNascimento} onChange={(e) => handleInputChange("dataNascimento", e.target.value)} />
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</CollapsibleContent>
|
|
</Card>
|
|
</Collapsible>
|
|
|
|
{/* Dados Profissionais */}
|
|
<Collapsible open={expandedSections.dadosProfissionais} onOpenChange={() => toggleSection("dadosProfissionais")}>
|
|
<Card>
|
|
<CollapsibleTrigger asChild>
|
|
<CardHeader className="cursor-pointer">
|
|
<CardTitle className="flex items-center justify-between">
|
|
<span className="flex items-center gap-2"><Stethoscope className="h-4 w-4" />Dados Profissionais</span>
|
|
{expandedSections.dadosProfissionais ? <ChevronUp className="h-4 w-4" /> : <ChevronDown className="h-4 w-4" />}
|
|
</CardTitle>
|
|
</CardHeader>
|
|
</CollapsibleTrigger>
|
|
<CollapsibleContent>
|
|
<CardContent className="space-y-4 pt-4">
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<div className="space-y-2">
|
|
<Label htmlFor="crm">CRM *</Label>
|
|
<Input id="crm" value={formData.crm} onChange={(e) => handleInputChange("crm", e.target.value)} className={errors.crm ? "border-destructive" : ""} />
|
|
{errors.crm && <p className="text-sm text-destructive">{errors.crm}</p>}
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="crmUf">UF do CRM *</Label>
|
|
<Input id="crmUf" value={formData.crmUf} onChange={(e) => handleInputChange("crmUf", e.target.value)} className={errors.crmUf ? "border-destructive" : ""} />
|
|
{errors.crmUf && <p className="text-sm text-destructive">{errors.crmUf}</p>}
|
|
</div>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="especialidade">Especialidade *</Label>
|
|
<Popover open={openEspecialidade} onOpenChange={setOpenEspecialidade}>
|
|
<PopoverTrigger asChild>
|
|
<Button
|
|
variant="outline"
|
|
role="combobox"
|
|
aria-expanded={openEspecialidade}
|
|
className={`w-full justify-between ${errors.especialidade ? "border-destructive" : ""}`}>
|
|
{formData.especialidade || "Selecione a especialidade"}
|
|
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
|
</Button>
|
|
</PopoverTrigger>
|
|
<PopoverContent className="w-[--radix-popover-trigger-width] p-0">
|
|
<Command>
|
|
<CommandInput placeholder="Buscar especialidade..." />
|
|
<CommandEmpty>Nenhuma especialidade encontrada.</CommandEmpty>
|
|
<ScrollArea className="h-72">
|
|
<CommandGroup>
|
|
{especialidadesMedicas.map((especialidade) => (
|
|
<CommandItem
|
|
key={especialidade}
|
|
value={especialidade}
|
|
onSelect={(currentValue) => {
|
|
handleInputChange("especialidade", currentValue === formData.especialidade ? "" : currentValue)
|
|
setOpenEspecialidade(false)
|
|
}}>
|
|
<Check
|
|
className={`mr-2 h-4 w-4 ${formData.especialidade === especialidade ? "opacity-100" : "opacity-0"}`}
|
|
/>
|
|
{especialidade}
|
|
</CommandItem>
|
|
))}
|
|
</CommandGroup>
|
|
</ScrollArea>
|
|
</Command>
|
|
</PopoverContent>
|
|
</Popover>
|
|
{errors.especialidade && <p className="text-sm text-destructive">{errors.especialidade}</p>}
|
|
</div>
|
|
</CardContent>
|
|
</CollapsibleContent>
|
|
</Card>
|
|
</Collapsible>
|
|
|
|
{/* Contato */}
|
|
<Collapsible open={expandedSections.contato} onOpenChange={() => toggleSection("contato")}>
|
|
<Card>
|
|
<CollapsibleTrigger asChild>
|
|
<CardHeader className="cursor-pointer">
|
|
<CardTitle className="flex items-center justify-between">
|
|
<span className="flex items-center gap-2"><Phone className="h-4 w-4" />Contato</span>
|
|
{expandedSections.contato ? <ChevronUp className="h-4 w-4" /> : <ChevronDown className="h-4 w-4" />}
|
|
</CardTitle>
|
|
</CardHeader>
|
|
</CollapsibleTrigger>
|
|
<CollapsibleContent>
|
|
<CardContent className="space-y-4 pt-4">
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<div className="space-y-2">
|
|
<Label htmlFor="email">E-mail *</Label>
|
|
<Input id="email" type="email" value={formData.email} onChange={(e) => handleInputChange("email", e.target.value)} className={errors.email ? "border-destructive" : ""} />
|
|
{errors.email && <p className="text-sm text-destructive">{errors.email}</p>}
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="celular">Celular *</Label>
|
|
<Input id="celular" value={formData.celular} onChange={(e) => handleInputChange("celular", e.target.value)} placeholder="(XX) XXXXX-XXXX" className={errors.celular ? "border-destructive" : ""} />
|
|
{errors.celular && <p className="text-sm text-destructive">{errors.celular}</p>}
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</CollapsibleContent>
|
|
</Card>
|
|
</Collapsible>
|
|
|
|
{/* Endereço */}
|
|
<Collapsible open={expandedSections.endereco} onOpenChange={() => toggleSection("endereco")}>
|
|
<Card>
|
|
<CollapsibleTrigger asChild>
|
|
<CardHeader className="cursor-pointer">
|
|
<CardTitle className="flex items-center justify-between">
|
|
<span className="flex items-center gap-2"><MapPin className="h-4 w-4" />Endereço</span>
|
|
{expandedSections.endereco ? <ChevronUp className="h-4 w-4" /> : <ChevronDown className="h-4 w-4" />}
|
|
</CardTitle>
|
|
</CardHeader>
|
|
</CollapsibleTrigger>
|
|
<CollapsibleContent>
|
|
<CardContent className="space-y-4 pt-4">
|
|
<div className="grid grid-cols-3 gap-4 items-end">
|
|
<div className="space-y-2 col-span-1">
|
|
<Label htmlFor="cep">CEP *</Label>
|
|
<Input id="cep" value={formData.cep} onChange={(e) => handleInputChange("cep", e.target.value)} onBlur={(e) => searchCEP(e.target.value)} disabled={isLoadingCep} className={errors.cep ? "border-destructive" : ""} />
|
|
{errors.cep && <p className="text-sm text-destructive">{errors.cep}</p>}
|
|
</div>
|
|
{isLoadingCep && <Loader2 className="h-4 w-4 animate-spin" />}
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="logradouro">Logradouro *</Label>
|
|
<Input id="logradouro" value={formData.logradouro} onChange={(e) => handleInputChange("logradouro", e.target.value)} className={errors.logradouro ? "border-destructive" : ""} />
|
|
{errors.logradouro && <p className="text-sm text-destructive">{errors.logradouro}</p>}
|
|
</div>
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<div className="space-y-2">
|
|
<Label htmlFor="numero">Número *</Label>
|
|
<Input id="numero" value={formData.numero} onChange={(e) => handleInputChange("numero", e.target.value)} className={errors.numero ? "border-destructive" : ""} />
|
|
{errors.numero && <p className="text-sm text-destructive">{errors.numero}</p>}
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="complemento">Complemento</Label>
|
|
<Input id="complemento" value={formData.complemento || ''} onChange={(e) => handleInputChange("complemento", e.target.value)} />
|
|
</div>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="bairro">Bairro *</Label>
|
|
<Input id="bairro" value={formData.bairro} onChange={(e) => handleInputChange("bairro", e.target.value)} className={errors.bairro ? "border-destructive" : ""} />
|
|
{errors.bairro && <p className="text-sm text-destructive">{errors.bairro}</p>}
|
|
</div>
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<div className="space-y-2">
|
|
<Label htmlFor="cidade">Cidade *</Label>
|
|
<Input id="cidade" value={formData.cidade} onChange={(e) => handleInputChange("cidade", e.target.value)} className={errors.cidade ? "border-destructive" : ""} />
|
|
{errors.cidade && <p className="text-sm text-destructive">{errors.cidade}</p>}
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Label htmlFor="estado">Estado *</Label>
|
|
<Input id="estado" value={formData.estado} onChange={(e) => handleInputChange("estado", e.target.value)} className={errors.estado ? "border-destructive" : ""} />
|
|
{errors.estado && <p className="text-sm text-destructive">{errors.estado}</p>}
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</CollapsibleContent>
|
|
</Card>
|
|
</Collapsible>
|
|
|
|
{/* Observações */}
|
|
<Collapsible open={expandedSections.observacoes} onOpenChange={() => toggleSection("observacoes")}>
|
|
<Card>
|
|
<CollapsibleTrigger asChild>
|
|
<CardHeader className="cursor-pointer">
|
|
<CardTitle className="flex items-center justify-between">
|
|
<span className="flex items-center gap-2"><Stethoscope className="h-4 w-4" />Observações</span>
|
|
{expandedSections.observacoes ? <ChevronUp className="h-4 w-4" /> : <ChevronDown className="h-4 w-4" />}
|
|
</CardTitle>
|
|
</CardHeader>
|
|
</CollapsibleTrigger>
|
|
<CollapsibleContent>
|
|
<CardContent className="pt-4">
|
|
<Textarea
|
|
id="observacoes"
|
|
value={formData.observacoes || ''}
|
|
onChange={(e) => handleInputChange("observacoes", e.target.value)}
|
|
placeholder="Notas adicionais sobre o médico..."
|
|
rows={4}
|
|
/>
|
|
</CardContent>
|
|
</CollapsibleContent>
|
|
</Card>
|
|
</Collapsible>
|
|
|
|
<div className="flex justify-end gap-4 pt-6 border-t">
|
|
<Button type="button" variant="outline" onClick={onClose} disabled={isSubmitting}>
|
|
<XCircle className="mr-2 h-4 w-4" />
|
|
Cancelar
|
|
</Button>
|
|
<Button type="submit" className="bg-primary hover:bg-primary/90" disabled={isSubmitting}>
|
|
{isSubmitting ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : <Save className="mr-2 h-4 w-4" />}
|
|
{isSubmitting ? "Salvando..." : doctorData?.id ? "Atualizar Médico" : "Salvar Médico"}
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
)
|
|
}
|