feat: cron automático de thumbnails + lista de pacientes em tabela + CRUD
continuous-integration/webhook Deploy concluído (VPS4)
continuous-integration/webhook Deploy concluído (VPS4)
Backend: - server.js: cron thumb-backfill a cada 10min com rastreio de estado (lastRun, nextRun, running, lastResult). GET /api/cron/status e POST /api/cron/run/:key para consulta e disparo manual via painel. - routes/images.js: PUT /api/images/patients/:name — edita patient_name, doctor e remark em todas as imagens do paciente de uma vez. Frontend: - PatientsPage.jsx (/patients): tabela com colunas Nome (+ miniatura), Dentista, Imagens, Última atualização, Observações, Ações. Suporta busca, paginação infinita, editar e excluir por linha. - SettingsPage.jsx (/settings): seção de Cron Jobs com status, resultado e botão "Executar agora"; seção de informações do servidor. - EditPatientModal.jsx: edita nome, dentista e observações do paciente. - Sidebar.jsx: add "Pacientes" (todos usuários) e "Configurações" (admin). - App.jsx: rotas /patients (protegida) e /settings (admin). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -207,6 +207,49 @@ router.get('/by-patient', async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// ================================================================
|
||||
// PUT /api/images/patients/:name - Editar dados de um paciente
|
||||
// Atualiza patient_name, doctor e remark em todas as imagens do paciente.
|
||||
// ================================================================
|
||||
router.put('/patients/:name', async (req, res) => {
|
||||
try {
|
||||
const oldName = decodeURIComponent(req.params.name);
|
||||
const { newName, doctor, remark } = req.body;
|
||||
|
||||
if (!oldName) return res.status(400).json({ error: 'Nome do paciente obrigatório.' });
|
||||
|
||||
const updates = [];
|
||||
const params = [];
|
||||
let i = 1;
|
||||
|
||||
if (newName !== undefined && newName.trim() !== '') {
|
||||
updates.push(`patient_name = $${i++}`);
|
||||
params.push(newName.trim());
|
||||
}
|
||||
if (doctor !== undefined) {
|
||||
updates.push(`doctor = $${i++}`);
|
||||
params.push(doctor);
|
||||
}
|
||||
if (remark !== undefined) {
|
||||
updates.push(`remark = $${i++}`);
|
||||
params.push(remark);
|
||||
}
|
||||
|
||||
if (updates.length === 0) return res.status(400).json({ error: 'Nenhum campo para atualizar.' });
|
||||
|
||||
params.push(oldName);
|
||||
const result = await db.run(
|
||||
`UPDATE images SET ${updates.join(', ')} WHERE patient_name = $${i}`,
|
||||
params
|
||||
);
|
||||
|
||||
res.json({ success: true, updated: result.changes });
|
||||
} catch (error) {
|
||||
console.error('Erro ao editar paciente:', error);
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// ================================================================
|
||||
// DELETE /api/images/by-patient - Excluir todas imagens de um paciente
|
||||
// ================================================================
|
||||
|
||||
Reference in New Issue
Block a user