2025-10-20 21:49:35 -03:00

270 lines
10 KiB
Plaintext

Olá! Vamos iniciar uma sessão de refatoração de componentes React/Next.js.
Seu Papel: A partir de agora, você atuará como um Desenvolvedor Sênior realizando uma revisão de código e refatoração. Seu objetivo não é apenas corrigir os erros óbvios, mas garantir que cada componente seja robusto, legível e siga as melhores práticas.
Contexto do Projeto:
A aplicação foi recentemente refatorada para usar uma camada de serviço (services/) para todas as chamadas de API e uma estrutura de layout automática do Next.js App Router. As páginas (page.tsx) estão desatualizadas e precisam ser corrigidas.
As 6 Regras de Ouro da Refatoração (Checklist Obrigatório):
Para CADA arquivo de página que eu fornecer, você deve aplicar TODAS as seguintes regras, sem exceção:
[UI] Limpeza do Layout Antigo:
REMOVER qualquer import de componentes de layout antigos (ex: import ManagerLayout from '...').
REMOVER o componente wrapper do JSX (ex: as tags <ManagerLayout>...</ManagerLayout>). A página deve retornar apenas seu próprio conteúdo.
[API] Substituição da Chamada de API:
LOCALIZAR a lógica de busca de dados (geralmente em useEffect).
SUBSTITUIR a chamada fetch antiga pela função correspondente da nossa camada de serviço (ex: fetch('/rest/v1/doctors') se torna medicosApi.list()). Use a documentação da API abaixo como referência.
[ESTADO] Gerenciamento de Estado Robusto:
IMPLEMENTAR estados explícitos para isLoading e error.
O estado principal de dados deve ser inicializado como um array ou objeto vazio.
Exemplo:
code
TypeScript
const [doctors, setDoctors] = useState<Doctor[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
[TIPAGEM] Garantir a Segurança de Tipos (Type Safety):
IMPORTAR as interfaces de tipo (Doctor, Patient, etc.) do arquivo de serviço correspondente.
APLICAR essa interface ao estado do useState (ex: useState<Doctor[]>([])). Chega de any!
[UI] Feedback Visual para o Usuário:
ADICIONAR renderização condicional no JSX para os estados de carregamento e erro.
Se isLoading for true, exiba um componente de "Carregando..." (pode ser um simples texto ou um spinner).
Se error existir, exiba uma mensagem de erro para o usuário.
Se os dados estiverem vazios após o carregamento, exiba uma mensagem como "Nenhum médico encontrado".
[LIMPEZA] Limpeza Final do Código:
REMOVER quaisquer variáveis, estados ou imports que se tornaram inúteis após a refatoração.
Formato da Resposta (Obrigatório):
Para cada arquivo que eu enviar, sua resposta deve SEMPRE seguir este formato:
[CÓDIGO REATORADO]
Um único bloco de código contendo o arquivo page.tsx completo e corrigido, aplicando TODAS as 6 regras.
[RESUMO DAS ALTERAÇÕES]
Uma lista (bullet points) explicando as principais mudanças que você fez, justificando-as com base nas "Regras de Ouro". Ex:
[API & Estado]: Substituí o fetch por medicosApi.list() e adicionei os estados isLoading e error.
[Tipagem]: Importei a interface Doctor e a apliquei ao estado com useState<Doctor[]>([]).
[UI]: Adicionei renderização condicional para exibir mensagens de carregamento e erro.
[Limpeza]: Removi o import ManagerLayout e o wrapper do JSX.
Referência Essencial: Documentação da Camada de Serviço
(Use esta documentação para saber qual função de serviço chamar)
code
Code
// services/medicosApi.ts -> Funções: list, getById, create, update, delete. Tipos: Doctor.
// services/pacientesApi.ts -> Funções: list, getById, create, update, delete. Tipos: Patient.
// services/agendamentosApi.ts -> Funções: list, getById, create, update, delete, searchAvailableSlots. Tipos: Appointment.
// services/usuariosApi.ts -> Funções: listRoles, createUser, getCurrentUser, getFullData. Tipos: User, UserRole.
// ... (e assim por diante para todos os outros arquivos de serviço)
Estou pronto. Por favor, me envie o código do primeiro arquivo page.tsx para ser refatorado.
======================================================================
DOCUMENTAÇÃO DA CAMADA DE SERVIÇO (SERVICES)
Este documento descreve a arquitetura e o funcionamento da camada de serviço,
responsável por toda a comunicação com o backend (Supabase API).
ARQUITETURA GERAL
A camada de serviço é composta por 12 arquivos, organizados por módulos
de funcionalidade da API. A arquitetura é centralizada em um arquivo
principal api.ts que configura o Axios, enquanto os outros arquivos
consomem essa configuração para realizar as chamadas específicas.
ARQUIVO PRINCIPAL: api.ts
Propósito: Este é o coração da camada de serviço. Ele cria e exporta
uma instância centralizada do Axios pré-configurada para interagir com
a API do Supabase.
Configurações Principais:
baseURL: Aponta para https://yuanqfswhberkoevtmfr.supabase.co.
apikey: A chave pública (anon key) do Supabase é adicionada como
um cabeçalho padrão em TODAS as requisições.
Interceptor de Requisição (Request Interceptor):
Antes de qualquer requisição ser enviada, o interceptor busca por um
cookie chamado supabase-token.
Se o token for encontrado, ele é adicionado ao cabeçalho Authorization
como um Bearer Token.
Isso automatiza o processo de autenticação para todas as rotas protegidas,
evitando a necessidade de adicionar o token manualmente em cada chamada.
Importante: Este arquivo NÃO contém nenhuma função de endpoint (como
login ou listagem de médicos). Sua única responsabilidade é a configuração
do cliente HTTP.
MÓDULOS DE SERVIÇO
Cada arquivo a seguir representa um módulo da API e exporta um objeto
com funções assíncronas para interagir com os endpoints.
2.1. autenticacaoApi.ts
Propósito: Gerencia todas as operações de autenticação.
Observação: Este módulo utiliza fetch diretamente em vez da instância
api do Axios. Isso é necessário porque as funções de login são as que
OBTÊM o token, que o interceptor do Axios precisa para funcionar. Ele também
gerencia a gravação e remoção do supabase-token nos cookies do navegador.
Funções Exportadas:
loginWithEmailAndPassword(email, password): Envia credenciais para POST /auth/v1/token?grant_type=password, recebe o token de acesso e o armazena nos cookies.
logout(): Envia uma requisição para POST /auth/v1/logout para invalidar a sessão no Supabase e remove o token dos cookies.
sendMagicLink(email, redirectTo): Envia um email para POST /auth/v1/otp para login sem senha.
renewToken(refreshToken): Usa um refresh token para obter um novo token de acesso via POST /auth/v1/token?grant_type=refresh_token.
2.2. atribuicoesApi.ts
Propósito: Gerencia as atribuições de pacientes a profissionais.
Tabela Alvo: patient_assignments
Funções Exportadas:
list(): Busca a lista de todas as atribuições (GET /rest/v1/patient_assignments).
create(data): Cria uma nova atribuição (POST /rest/v1/patient_assignments).
2.3. avatarsApi.ts
Propósito: Gerencia o upload e a remoção de avatares no Supabase Storage.
Observação: As URLs e o método de envio (multipart/form-data) são
específicos para o serviço de Storage do Supabase.
Funções Exportadas:
upload(userId, file): Envia um arquivo de imagem para POST /storage/v1/object/avatars/{userId}/avatar.
remove(userId): Deleta o avatar de um usuário (DELETE /storage/v1/object/avatars/{userId}/avatar).
getPublicUrl(userId, ext): Monta e retorna a URL pública para acessar a imagem do avatar, não faz uma chamada de API.
2.4. medicosApi.ts
Propósito: Gerencia o CRUD (Create, Read, Update, Delete) completo para o recurso de médicos.
Tabela Alvo: doctors
Funções Exportadas:
list(): GET /rest/v1/doctors
getById(id): GET /rest/v1/doctors?id=eq.{id}
create(data): POST /rest/v1/doctors
update(id, data): PATCH /rest/v1/doctors?id=eq.{id}
delete(id): DELETE /rest/v1/doctors?id=eq.{id}
2.5. pacientesApi.ts
Propósito: Gerencia o CRUD completo para o recurso de pacientes.
Tabela Alvo: patients
Funções Exportadas: CRUD padrão (list, getById, create, update, delete).
2.6. perfisApi.ts
Propósito: Gerencia a listagem e atualização de perfis de usuários.
Tabela Alvo: profiles
Funções Exportadas:
list(): GET /rest/v1/profiles
update(userId, data): PATCH /rest/v1/profiles?id=eq.{userId}
2.7. relatoriosApi.ts
Propósito: Gerencia o CRUD completo para o recurso de relatórios.
Tabela Alvo: reports
Funções Exportadas: CRUD padrão (list, getById, create, update, delete).
2.8. usuariosApi.ts
Propósito: Agrupa endpoints relacionados a usuários que não são CRUD direto da tabela profiles.
Funções Exportadas:
listRoles(): Busca as funções (roles) dos usuários (GET /rest/v1/user_roles).
createUser(data): Chama uma Supabase Function para criar um novo usuário (POST /functions/v1/create-user).
getCurrentUser(): Obtém os dados do usuário atualmente autenticado (GET /auth/v1/user).
getFullData(userId): Chama uma Supabase Function para obter dados consolidados de um usuário (GET /functions/v1/user-info).
2.9. smsApi.ts
Propósito: Responsável pelo envio de mensagens SMS.
Funções Exportadas:
send(data): Chama a Supabase Function para enviar um SMS (POST /functions/v1/send-sms).
2.10. agendamentosApi.ts
Propósito: Gerencia o CRUD de agendamentos e a busca por horários.
Tabela Alvo: appointments
Funções Exportadas:
CRUD padrão (list, getById, create, update, delete).
searchAvailableSlots(data): Chama a Supabase Function para buscar horários disponíveis (POST /functions/v1/get-available-slots).
2.11. disponibilidadeApi.ts
Propósito: Gerencia o CRUD completo para a disponibilidade dos médicos.
Tabela Alvo: doctor_availability
Funções Exportadas: CRUD padrão (list, getById, create, update, delete).
2.12. excecoesApi.ts
Propósito: Gerencia as exceções (bloqueios/liberações) na agenda dos médicos.
Tabela Alvo: doctor_exceptions
Funções Exportadas:
list(): GET /rest/v1/doctor_exceptions
create(data): POST /rest/v1/doctor_exceptions
delete(id): DELETE /rest/v1/doctor_exceptions?id=eq.{id}
COMO UTILIZAR
Para usar qualquer uma dessas funções em um componente ou página do Next.js,
basta importar o módulo desejado e chamar a função. O tratamento de erros
(com try/catch) e o gerenciamento de estado (loading, data, error) devem
ser feitos no local onde a função é chamada.
Exemplo:
code
TypeScript
download
content_copy
expand_less
import { medicosApi } from './services/medicosApi';
async function fetchDoctors() {
try {
const doctors = await medicosApi.list();
console.log(doctors);
} catch (error) {
console.error("Erro ao buscar médicos:", error);
}
}