diff --git a/app/manager/home/novo/page.tsx b/app/manager/home/novo/page.tsx deleted file mode 100644 index 1912432..0000000 --- a/app/manager/home/novo/page.tsx +++ /dev/null @@ -1,534 +0,0 @@ -"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 { 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 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 = () => { - const newId = Date.now(); - handleInputChange('anexos', [...formData.anexos, { id: newId, name: `Documento ${formData.anexos.length + 1}` }]); - } - - 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

-

- Preencha os dados do novo médico para cadastro. -

-
- - - -
- -
- - {error && ( -
-

Erro no Cadastro:

-

{error}

-
- )} - - -
-

- Dados Principais e Pessoais -

- - -
-
- - handleInputChange("nomeCompleto", e.target.value)} - placeholder="Nome do Médico" - required - /> -
-
- - handleInputChange("crm", e.target.value)} - placeholder="Ex: 123456" - required - /> -
-
- - -
-
- - -
-
- - handleInputChange("especialidade", e.target.value)} - placeholder="Ex: Cardiologia" - /> -
-
- - handleInputChange("cpf", e.target.value)} - placeholder="000.000.000-00" - maxLength={14} - required - /> -
-
- - handleInputChange("rg", e.target.value)} - placeholder="00.000.000-0" - /> -
-
- - -
-
- - handleInputChange("email", e.target.value)} - placeholder="exemplo@dominio.com" - required - /> -
-
- - handleInputChange("dataNascimento", e.target.value)} - /> -
-
-
- - -
-

- Contato e Endereço -

- - -
-
- - handleInputChange("telefoneCelular", e.target.value)} - placeholder="(00) 00000-0000" - maxLength={15} - /> -
-
- - handleInputChange("telefone2", e.target.value)} - placeholder="(00) 00000-0000" - maxLength={15} - /> -
-
-
- handleInputChange("ativo", checked === true)} - /> - -
-
-
- - -
-
- - handleInputChange("cep", e.target.value)} - placeholder="00000-000" - maxLength={9} - /> -
-
- - handleInputChange("endereco", e.target.value)} - placeholder="Rua, Avenida, etc." - /> -
-
-
-
- - handleInputChange("numero", e.target.value)} - placeholder="123" - /> -
-
- - handleInputChange("complemento", e.target.value)} - placeholder="Apto, Bloco, etc." - /> -
-
-
-
- - handleInputChange("bairro", e.target.value)} - placeholder="Bairro" - /> -
-
- - handleInputChange("estado", e.target.value)} - placeholder="SP" - /> -
-
- - handleInputChange("cidade", e.target.value)} - placeholder="São Paulo" - /> -
-
-
- - -
-

- Outras Informações (Internas) -

- -
-
- -