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 ...). 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([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(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([])). 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([]). [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); } }