-
Informações Médicas
-
-
-
-
-
-
-
-
-
- handleInputChange("peso", e.target.value)}
- placeholder="0.0"
- />
-
-
-
-
- handleInputChange("altura", e.target.value)}
- placeholder="0.00"
- />
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ Observações (Apenas internas)
+
+
- {/* Insurance Information Section */}
-
-
Informações de convênio
-
-
-
-
-
-
-
-
- handleInputChange("plano", e.target.value)} />
-
-
-
-
- handleInputChange("numeroMatricula", e.target.value)}
- />
-
-
-
-
- handleInputChange("validadeCarteira", e.target.value)}
- disabled={validadeIndeterminada}
- />
-
-
-
-
-
- setValidadeIndeterminada(checked === true)}
- />
-
-
-
-
-
-
+
-
-
- )
-}
+
+ );
+}
\ No newline at end of file
diff --git a/app/manager/home/novo/page.tsx b/app/manager/home/novo/page.tsx
index c79396f..1912432 100644
--- a/app/manager/home/novo/page.tsx
+++ b/app/manager/home/novo/page.tsx
@@ -1,479 +1,534 @@
"use client"
import { useState } from "react"
+import { useRouter } from "next/navigation"
import Link from "next/link"
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 { Upload, Plus, X, ChevronDown } from "lucide-react"
+import { Checkbox } from "@/components/ui/checkbox"
+import { Upload, X, ChevronDown, Save, Loader2 } from "lucide-react"
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"
import ManagerLayout from "@/components/manager-layout"
+import { doctorsService } from "services/doctorsApi.mjs";
+
+
+const UF_LIST = ["AC", "AL", "AP", "AM", "BA", "CE", "DF", "ES", "GO", "MA", "MT", "MS", "MG", "PA", "PB", "PR", "PE", "PI", "RJ", "RN", "RS", "RO", "RR", "SC", "SP", "SE", "TO"];
+
+
+
+interface DoctorFormData {
+
+ nomeCompleto: string;
+ crm: string;
+ crmEstado: string;
+ cpf: string;
+ email: string;
+ especialidade: string;
+ telefoneCelular: string;
+ telefone2: string;
+ cep: string;
+ endereco: string;
+ numero: string;
+ complemento: string;
+ bairro: string;
+ cidade: string;
+ estado: string;
+ dataNascimento: string;
+ rg: string;
+ ativo: boolean;
+ observacoes: string;
+ anexos: { id: number, name: string }[];
+}
+
+
+const apiMap: { [K in keyof DoctorFormData]: string | null } = {
+ nomeCompleto: 'full_name',
+ crm: 'crm',
+ crmEstado: 'crm_uf',
+ cpf: 'cpf',
+ email: 'email',
+
+ especialidade: 'specialty',
+ telefoneCelular: 'phone_mobile',
+ telefone2: 'phone2',
+ cep: 'cep',
+ endereco: 'street',
+ numero: 'number',
+ complemento: 'complement',
+ bairro: 'neighborhood',
+ cidade: 'city',
+ estado: 'state',
+ dataNascimento: 'birth_date',
+ rg: 'rg',
+ ativo: 'active',
+
+ observacoes: null,
+ anexos: null,
+};
+
+
+const defaultFormData: DoctorFormData = {
+ nomeCompleto: '', crm: '', crmEstado: '', cpf: '', email: '',
+ especialidade: '', telefoneCelular: '', telefone2: '', cep: '',
+ endereco: '', numero: '', complemento: '', bairro: '', cidade: '', estado: '',
+ dataNascimento: '', rg: '', ativo: true,
+ observacoes: '', anexos: [],
+};
+
+
+
+
+const cleanNumber = (value: string): string => value.replace(/\D/g, '');
+
+const formatCPF = (value: string): string => {
+ const cleaned = cleanNumber(value).substring(0, 11);
+ return cleaned.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, '$1.$2.$3-$4');
+};
+
+const formatCEP = (value: string): string => {
+ const cleaned = cleanNumber(value).substring(0, 8);
+ return cleaned.replace(/(\d{5})(\d{3})/, '$1-$2');
+};
+
+const formatPhoneMobile = (value: string): string => {
+ const cleaned = cleanNumber(value).substring(0, 11);
+ if (cleaned.length > 10) {
+ return cleaned.replace(/(\d{2})(\d{5})(\d{4})/, '($1) $2-$3');
+ }
+ return cleaned.replace(/(\d{2})(\d{4})(\d{4})/, '($1) $2-$3');
+};
+
+
+
export default function NovoMedicoPage() {
- const [anexosOpen, setAnexosOpen] = useState(false)
- const [anexos, setAnexos] = useState
([])
+ const router = useRouter();
+ const [formData, setFormData] = useState(defaultFormData);
+ const [isSaving, setIsSaving] = useState(false);
+ const [error, setError] = useState(null);
+ const [anexosOpen, setAnexosOpen] = useState(false);
+
+ const handleInputChange = (key: keyof DoctorFormData, value: string | boolean | { id: number, name: string }[]) => {
+
+
+ if (typeof value === 'string') {
+ let maskedValue = value;
+ if (key === 'cpf') maskedValue = formatCPF(value);
+ if (key === 'cep') maskedValue = formatCEP(value);
+ if (key === 'telefoneCelular' || key === 'telefone2') maskedValue = formatPhoneMobile(value);
+
+ setFormData((prev) => ({ ...prev, [key]: maskedValue }));
+ } else {
+ setFormData((prev) => ({ ...prev, [key]: value }));
+ }
+ };
+
+
const adicionarAnexo = () => {
- setAnexos([...anexos, `Documento ${anexos.length + 1}`])
+ const newId = Date.now();
+ handleInputChange('anexos', [...formData.anexos, { id: newId, name: `Documento ${formData.anexos.length + 1}` }]);
}
- const removerAnexo = (index: number) => {
- setAnexos(anexos.filter((_, i) => i !== index))
+ const removerAnexo = (id: number) => {
+ handleInputChange('anexos', formData.anexos.filter((anexo) => anexo.id !== id));
}
+
+
+ const requiredFields = [
+ { key: 'nomeCompleto', name: 'Nome Completo' },
+ { key: 'crm', name: 'CRM' },
+ { key: 'crmEstado', name: 'UF do CRM' },
+ { key: 'cpf', name: 'CPF' },
+ { key: 'email', name: 'E-mail' },
+ ] as const;
+
+
+
+ const handleSubmit = async (e: React.FormEvent) => {
+ e.preventDefault();
+ setError(null);
+ setIsSaving(true);
+
+
+ for (const field of requiredFields) {
+ let valueToCheck = formData[field.key];
+
+
+ if (!valueToCheck || String(valueToCheck).trim() === '') {
+ setError(`O campo obrigatório "${field.name}" deve ser preenchido.`);
+ setIsSaving(false);
+ return;
+ }
+ }
+
+ const finalPayload: { [key: string]: any } = {};
+ const formKeys = Object.keys(formData) as Array;
+
+
+ formKeys.forEach((key) => {
+ const apiFieldName = apiMap[key];
+
+ if (!apiFieldName) return;
+
+ let value = formData[key];
+
+ if (typeof value === 'string') {
+ let trimmedValue = value.trim();
+
+
+ const isOptional = !requiredFields.some(f => f.key === key);
+
+ if (isOptional && trimmedValue === '') {
+ finalPayload[apiFieldName] = null;
+ return;
+ }
+
+
+ if (key === 'crmEstado' || key === 'estado') {
+ trimmedValue = trimmedValue.toUpperCase();
+ }
+
+ value = trimmedValue;
+ }
+
+ finalPayload[apiFieldName] = value;
+ });
+
+
+ try {
+
+ const response = await doctorsService.create(finalPayload);
+ router.push("/manager/home");
+ } catch (e: any) {
+ console.error("Erro ao salvar o médico:", e);
+
+ let detailedError = `Erro na requisição. Verifique se o **CRM** ou **CPF** já existem ou se as **Máscaras/Datas** estão incorretas.`;
+
+
+ if (e.message && e.message.includes("duplicate key value violates unique constraint")) {
+
+ detailedError = "O CPF ou CRM informado já está cadastrado no sistema. Por favor, verifique os dados de identificação.";
+ } else if (e.message && e.message.includes("Detalhes:")) {
+
+ detailedError = e.message.split("Detalhes:")[1].trim();
+ } else if (e.message) {
+ detailedError = e.message;
+ }
+
+ setError(`Erro ao cadastrar. Detalhes: ${detailedError}`);
+ } finally {
+ setIsSaving(false);
+ }
+ };
return (
-
+
Novo Médico
-
Cadastre um novo médico no sistema
+
+ Preencha os dados do novo médico para cadastro.
+
+
+
Cancelar
+
-