forked from RiseUP/riseup_squad_03
modified: .env.example
new file: .env.local modified: .gitignore new file: docs/mock-audit.md modified: eslint.config.js modified: package-lock.json modified: package.json deleted: src/App.css modified: src/App.jsx deleted: src/assets/react.svg deleted: src/assets/vite.svg new file: src/components/RichTextEditor.jsx modified: src/components/calendar/AgendaMonthlyView.jsx modified: src/components/calendar/AgendaWeeklyView.jsx modified: src/components/ui.jsx modified: src/config/api.js modified: src/data/mockData.js new file: src/data/reportTemplates.js modified: src/hooks/useAgenda.js modified: src/mappers/appointmentMapper.js modified: src/pages/AgendaPage.jsx modified: src/pages/MedicalRecordsPage.jsx modified: src/pages/MessagesPage.jsx modified: src/pages/PatientsPage.jsx modified: src/pages/ProfilePage.jsx modified: src/pages/ReportsPage.jsx modified: src/pages/UsersPage.jsx modified: src/pages/VisitsPage.jsx modified: src/repositories/patientRepository.js modified: src/repositories/profileRepository.js modified: src/repositories/userRepository.js deleted: test.mjs deleted: test2.mjs deleted: test3.mjs deleted: test4.mjs deleted: test5.mjs new file: tests/mappers.test.mjs new file: tests/patientRepository.test.mjs new file: tests/permissions.test.mjs new file: tests/repositoryUtils.test.mjs
This commit is contained in:
@@ -10,11 +10,10 @@ export const patientRepository = {
|
||||
},
|
||||
|
||||
async getById(patientId) {
|
||||
const [patients, appointments] = await Promise.all([
|
||||
this.getAll(),
|
||||
const [patient, appointments] = await Promise.all([
|
||||
getPatientById(patientId),
|
||||
getAppointments().catch(() => []),
|
||||
])
|
||||
const patient = patients.find((p) => String(p.id) === String(patientId)) || null
|
||||
return patient ? mapPatientToDetail(patient, appointments) : null
|
||||
},
|
||||
|
||||
@@ -126,6 +125,35 @@ export const patientRepository = {
|
||||
return response.json()
|
||||
},
|
||||
|
||||
async uploadAvatar(patientId, file) {
|
||||
if (!patientId) {
|
||||
throw new Error('Não foi possível identificar o paciente para enviar o avatar.')
|
||||
}
|
||||
|
||||
const extension = file.name?.split('.').pop() || 'jpg'
|
||||
const objectPath = `patients/${patientId}/avatar.${extension}`
|
||||
const avatarUrl = `${apiConfig.storageUrl}/object/avatars/${objectPath}`
|
||||
const response = await fetch(avatarUrl, {
|
||||
method: 'POST',
|
||||
headers: getAuthenticatedHeaders({
|
||||
'Content-Type': file.type || 'application/octet-stream',
|
||||
'x-upsert': 'true',
|
||||
}),
|
||||
body: file,
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(await getResponseError(response, 'Falha ao enviar avatar do paciente.'))
|
||||
}
|
||||
|
||||
await updatePatientAvatarUrl(patientId, avatarUrl).catch(() => null)
|
||||
|
||||
return {
|
||||
avatarUrl,
|
||||
path: objectPath,
|
||||
}
|
||||
},
|
||||
|
||||
// 5. Deletar paciente
|
||||
async remove(patientId) {
|
||||
const response = await fetch(`${apiConfig.restUrl}/patients?id=eq.${patientId}`, {
|
||||
@@ -138,6 +166,20 @@ export const patientRepository = {
|
||||
},
|
||||
}
|
||||
|
||||
async function getPatientById(patientId) {
|
||||
const query = new URLSearchParams({
|
||||
select: '*',
|
||||
id: `eq.${patientId}`,
|
||||
limit: '1',
|
||||
})
|
||||
|
||||
const response = await fetch(`${apiConfig.restUrl}/patients?${query.toString()}`, { headers: getAuthenticatedHeaders() })
|
||||
if (!response.ok) throw new Error(await getResponseError(response, 'Erro ao buscar paciente.'))
|
||||
|
||||
const data = await response.json()
|
||||
return Array.isArray(data) ? data[0] || null : data
|
||||
}
|
||||
|
||||
function mapPatientToDirectory(patient, appointments = []) {
|
||||
const appointmentSummary = summarizeAppointments(patient.id, appointments)
|
||||
const city = getFirstValue(patient, ['city', 'cidade', 'address_city', 'municipio'], patient.address?.city)
|
||||
@@ -148,6 +190,7 @@ function mapPatientToDirectory(patient, appointments = []) {
|
||||
...patient,
|
||||
name: patient.name || patient.full_name || patient.nome || 'Paciente',
|
||||
phone: patient.phone || patient.phone_mobile || patient.telefone || '',
|
||||
avatarUrl: normalizeAvatarUrl(patient.avatarUrl || patient.avatar_url || patient.avatar_path),
|
||||
detailId: patient.id,
|
||||
insurance: normalizeInsurance(insurance),
|
||||
city,
|
||||
@@ -183,6 +226,7 @@ function mapPatientToDetail(patient, appointments = []) {
|
||||
status: patient.status || 'Acompanhamento',
|
||||
risk: patient.risk || patient.risco || 'Baixo',
|
||||
email: patient.email || '',
|
||||
avatarUrl: directory.avatarUrl,
|
||||
address: formatAddress(directory) || patient.address || patient.endereco || 'Endereço não informado',
|
||||
team: patient.team || patient.equipe || [],
|
||||
notes: normalizeNotes(patient.notes || patient.observacoes || directory.notesText),
|
||||
@@ -332,6 +376,25 @@ function normalizeInsurance(value) {
|
||||
return normalized
|
||||
}
|
||||
|
||||
function normalizeAvatarUrl(value) {
|
||||
const avatar = String(value || '').trim()
|
||||
if (!avatar) return ''
|
||||
if (/^https?:\/\//i.test(avatar)) return avatar
|
||||
return `${apiConfig.storageUrl}/object/avatars/${avatar.replace(/^\/+/, '')}`
|
||||
}
|
||||
|
||||
async function updatePatientAvatarUrl(patientId, avatarUrl) {
|
||||
const response = await fetch(`${apiConfig.restUrl}/patients?id=eq.${patientId}`, {
|
||||
method: 'PATCH',
|
||||
headers: getAuthenticatedHeaders({ Prefer: 'return=minimal' }),
|
||||
body: JSON.stringify({ avatar_url: avatarUrl }),
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(await getResponseError(response, 'Falha ao salvar avatar do paciente.'))
|
||||
}
|
||||
}
|
||||
|
||||
function calculateAge(birthDate) {
|
||||
if (!birthDate) return 0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user