docs: atualizar READMEs com sistema de avatares e remover arquivos de teste

This commit is contained in:
guisilvagomes 2025-10-28 11:48:06 -03:00
parent 7c68682e97
commit 31aacb7a3d
5 changed files with 47 additions and 118 deletions

View File

@ -1,6 +1,6 @@
# MediConnect - Sistema de Agendamento Médico
Aplicação SPA (React + Vite + TypeScript) consumindo **Supabase** (Auth, PostgREST) diretamente do frontend, hospedada no **Cloudflare Pages**.
Aplicação SPA (React + Vite + TypeScript) consumindo **Supabase** (Auth, PostgREST, Storage) diretamente do frontend, hospedada no **Cloudflare Pages**.
---
@ -15,11 +15,12 @@ Aplicação SPA (React + Vite + TypeScript) consumindo **Supabase** (Auth, Postg
```
Frontend (Vite/React) → Supabase API
Cloudflare Pages
↓ ├── Auth (JWT)
Cloudflare Pages ├── PostgREST (PostgreSQL)
└── Storage (Avatares)
```
**Mudança importante:** O sistema **não usa mais Netlify Functions**. Toda comunicação é direta entre frontend e Supabase via services (`authService`, `userService`, `patientService`, etc.).
**Mudança importante:** O sistema **não usa mais Netlify Functions**. Toda comunicação é direta entre frontend e Supabase via services (`authService`, `userService`, `patientService`, `avatarService`, etc.).
---
@ -242,6 +243,44 @@ await appointmentService.updateStatus(id, "confirmed");
await appointmentService.cancel(id, "Motivo do cancelamento");
```
#### 📸 Avatares (avatarService)
```typescript
// Upload de avatar (usa FormData com x-upsert: true)
const file = event.target.files[0]; // File do input
const result = await avatarService.upload({
userId: user.id,
file: file,
});
// Retorna: { Key: "url-publica-do-avatar" }
// Obter URL pública do avatar
const url = avatarService.getPublicUrl({
userId: user.id,
ext: "png", // ou 'jpg', 'webp'
});
// Retorna: https://yuanqfswhberkoevtmfr.supabase.co/storage/v1/object/avatars/{userId}/avatar.png
// Auto-load de avatar (testa múltiplas extensões)
const extensions = ["png", "jpg", "webp"];
for (const ext of extensions) {
const url = avatarService.getPublicUrl({ userId: user.id, ext });
const response = await fetch(url, { method: "HEAD" });
if (response.ok) {
setAvatarUrl(url);
break;
}
}
```
**Detalhes importantes:**
- Upload usa **multipart/form-data** via FormData
- Header `x-upsert: true` permite sobrescrever avatares existentes
- Suporta formatos: PNG, JPG, WEBP (máx 2MB)
- URLs públicas não requerem autenticação
- Avatar é carregado automaticamente nos painéis
---
## 🔧 Configuração da API

Binary file not shown.

Before

Width:  |  Height:  |  Size: 472 KiB

View File

@ -1,58 +0,0 @@
const axios = require("axios");
const ANON_KEY =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inl1YW5xZnN3aGJlcmtvZXZ0bWZyIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTQ5NTQzNjksImV4cCI6MjA3MDUzMDM2OX0.g8Fm4XAvtX46zifBZnYVH4tVuQkqUH6Ia9CXQj4DztQ";
const BASE_URL = "https://yuanqfswhberkoevtmfr.supabase.co";
(async () => {
try {
console.log("🔐 Fazendo login como admin...");
const loginRes = await axios.post(
`${BASE_URL}/auth/v1/token?grant_type=password`,
{
email: "riseup@popcode.com.br",
password: "riseup",
},
{
headers: {
"Content-Type": "application/json",
apikey: ANON_KEY,
},
}
);
console.log("✅ Login admin bem-sucedido!");
const token = loginRes.data.access_token;
console.log("\n🔍 Buscando usuário fernando...");
const usersRes = await axios.get(`${BASE_URL}/rest/v1/profiles?select=*`, {
headers: {
apikey: ANON_KEY,
Authorization: `Bearer ${token}`,
},
});
console.log(`\n📊 Total de usuários: ${usersRes.data.length}`);
const fernando = usersRes.data.find(
(u) =>
u.email &&
(u.email.toLowerCase().includes("fernando") ||
u.full_name?.toLowerCase().includes("fernando"))
);
if (fernando) {
console.log("\n✅ Usuário Fernando encontrado:");
console.log(JSON.stringify(fernando, null, 2));
} else {
console.log("\n❌ Usuário Fernando NÃO encontrado na tabela profiles");
console.log("\n📧 Alguns emails cadastrados:");
usersRes.data.slice(0, 15).forEach((u) => {
if (u.email)
console.log(` - ${u.email} (${u.full_name || "sem nome"})`);
});
}
} catch (err) {
console.error("❌ Erro:", err.response?.data || err.message);
}
})();

View File

@ -1,55 +0,0 @@
import axios from "axios";
const SUPABASE_URL = "https://yuanqfswhberkoevtmfr.supabase.co";
const SUPABASE_ANON_KEY =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inl1YW5xZnN3aGJlcmtvZXZ0bWZyIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTQ5NTQzNjksImV4cCI6MjA3MDUzMDM2OX0.g8Fm4XAvtX46zifBZnYVH4tVuQkqUH6Ia9CXQj4DztQ";
async function testPasswordRecovery() {
console.log("\n=== TESTE DE RECUPERAÇÃO DE SENHA ===\n");
const testEmail = "fernando.pirichowski@souunit.com.br";
try {
console.log("📧 Enviando email de recuperação para:", testEmail);
const response = await axios.post(
`${SUPABASE_URL}/auth/v1/recover`,
{
email: testEmail,
options: {
redirectTo: "https://mediconnectbrasil.app/reset-password",
},
},
{
headers: {
"Content-Type": "application/json",
apikey: SUPABASE_ANON_KEY,
},
}
);
console.log("✅ Email de recuperação enviado com sucesso!");
console.log("Status:", response.status);
console.log("Response:", JSON.stringify(response.data, null, 2));
console.log("\n📬 Verifique o email:", testEmail);
console.log(
"🔗 O link redirecionará para: https://mediconnectbrasil.app/reset-password"
);
console.log("\n💡 O link virá no formato:");
console.log(
" https://yuanqfswhberkoevtmfr.supabase.co/auth/v1/verify?token=...&type=recovery&redirect_to=https://mediconnectbrasil.app/reset-password"
);
console.log("\n💡 Depois do clique, será redirecionado para:");
console.log(
" https://mediconnectbrasil.app/reset-password#access_token=...&refresh_token=..."
);
} catch (error) {
console.log("❌ Erro ao enviar email de recuperação:");
console.log("Status:", error.response?.status);
console.log("Error:", error.response?.data || error.message);
}
console.log("\n=== TESTE CONCLUÍDO ===\n");
}
testPasswordRecovery();

View File

@ -28,6 +28,7 @@ O MediConnect é uma plataforma web que conecta **pacientes**, **médicos** e **
- ✅ Agendamento de consultas online
- ✅ Gestão de disponibilidade dos médicos
- ✅ Acompanhamento de consultas e prontuários
- ✅ Sistema de avatares com upload de imagens
- ✅ Recuperação de senha
- ✅ Sistema de roles e permissões
- ✅ Interface responsiva e acessível
@ -75,7 +76,8 @@ O MediConnect é uma plataforma web que conecta **pacientes**, **médicos** e **
3. **Persistência (Supabase)**
- PostgreSQL com Row Level Security (RLS)
- Supabase Auth para autenticação
- Supabase Auth para autenticação JWT
- Supabase Storage para upload de avatares
- Supabase Functions para lógica serverless
---
@ -98,6 +100,7 @@ O MediConnect é uma plataforma web que conecta **pacientes**, **médicos** e **
- **Supabase** - Backend as a Service
- **PostgreSQL** - Banco de dados relacional
- **Supabase Auth** - Autenticação JWT
- **Supabase Storage** - Armazenamento de avatares
### Deploy