- Adiciona role 'agenda_viewer' para profissionais visualizarem apenas suas agendas - Implementa middleware de autorização baseado em roles - Adiciona validação de permissões nos endpoints de agenda - Melhora exibição de dados financeiros e logísticos - Atualiza componentes frontend para melhor UX - Adiciona documentação sobre o papel de visualização de agenda
5.7 KiB
5.7 KiB
Melhorias em Filtros Financeiros e Cadastro - Changelog
Data de Implementação: 19 de janeiro de 2026
Branch: dev
📋 Visão Geral
Implementação de filtros avançados de data na página de Extrato Financeiro e validação obrigatória de foto de perfil no cadastro de profissionais, visando melhorar o controle financeiro e a qualidade dos dados cadastrais.
🚀 Funcionalidades Implementadas
1. Sistema de Filtros Avançados de Data - Extrato Financeiro
Objetivo: Fornecer controle granular sobre visualização de transações financeiras
Implementações:
- ✅ Filtro de data de início para definir período inicial
- ✅ Filtro de data final para definir período final
- ✅ Opção para incluir/excluir finais de semana
- ✅ Painel expansível/recolhível para organização da interface
- ✅ Botão de limpeza rápida de filtros
- ✅ Integração com filtros existentes (FOT, Evento, Serviço, etc.)
Funcionalidades:
- ✅ Painel de filtros com indicador visual (▶/▼)
- ✅ Layout responsivo com grid para desktop
- ✅ Cálculo automático de intervalos de datas
- ✅ Exclusão automática de sábados e domingos quando desabilitado
- ✅ Mensagem visual quando filtros estão ativos
- ✅ Preservação de filtros de coluna existentes
Arquivos Modificados:
frontend/pages/Finance.tsx
2. Validação Obrigatória de Foto de Perfil
Objetivo: Garantir que todos os profissionais tenham foto de perfil cadastrada
Implementações:
No Formulário (ProfessionalForm):
- ✅ Validação no
handleSubmitantes do envio - ✅ Label atualizado com asterisco (*) indicando obrigatoriedade
- ✅ Mensagem de erro clara: "A foto de perfil é obrigatória!"
- ✅ Bloqueio do envio se foto não estiver presente
No Registro (ProfessionalRegister):
- ✅ Validação adicional antes do upload
- ✅ Tratamento de erro específico para foto ausente
- ✅ Upload obrigatório (não mais opcional)
- ✅ Mensagem de erro: "A foto de perfil é obrigatória."
Arquivos Modificados:
frontend/components/ProfessionalForm.tsxfrontend/pages/ProfessionalRegister.tsx
🔧 Detalhes Técnicos
1. Filtros Avançados de Data
Novos Estados Implementados:
const [dateFilters, setDateFilters] = useState({
startDate: "",
endDate: "",
includeWeekends: true,
});
const [showDateFilters, setShowDateFilters] = useState(false);
Algoritmo de Filtragem:
// Advanced date filters
if (dateFilters.startDate || dateFilters.endDate || !dateFilters.includeWeekends) {
result = result.filter(t => {
// Parse date from dataRaw (YYYY-MM-DD) or data (DD/MM/YYYY)
let dateToCheck: Date;
if (t.dataRaw) {
dateToCheck = new Date(t.dataRaw);
} else {
const parts = t.data.split('/');
if (parts.length === 3) {
dateToCheck = new Date(
parseInt(parts[2]),
parseInt(parts[1]) - 1,
parseInt(parts[0])
);
} else {
return true; // Keep if can't parse
}
}
// Check date range
if (dateFilters.startDate) {
const startDate = new Date(dateFilters.startDate);
if (dateToCheck < startDate) return false;
}
if (dateFilters.endDate) {
const endDate = new Date(dateFilters.endDate);
endDate.setHours(23, 59, 59, 999);
if (dateToCheck > endDate) return false;
}
// Check weekends
if (!dateFilters.includeWeekends) {
const dayOfWeek = dateToCheck.getDay();
if (dayOfWeek === 0 || dayOfWeek === 6) return false;
}
return true;
});
}
Lógica de Exclusão de Finais de Semana:
dayOfWeek === 0→ DomingodayOfWeek === 6→ Sábado- Exclusão automática quando checkbox desmarcado
Interface de Usuário:
<div className="bg-white rounded shadow p-4 grid grid-cols-1 md:grid-cols-3 gap-4 mb-4">
<div>
<label>Data Início</label>
<input type="date" />
</div>
<div>
<label>Data Final</label>
<input type="date" />
</div>
<div>
<label>
<input type="checkbox" />
Incluir finais de semana
</label>
</div>
</div>
2. Validação de Foto Obrigatória
Fluxo de Validação:
- Formulário (ProfessionalForm.tsx):
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
// Validação de foto de perfil
if (!formData.avatar) {
alert("A foto de perfil é obrigatória!");
return;
}
// ... restante das validações
};
- Upload (ProfessionalRegister.tsx):
// Upload de Avatar (obrigatório)
if (!professionalData.avatar) {
throw new Error("A foto de perfil é obrigatória.");
}
try {
console.log("Iniciando upload do avatar...");
const uploadRes = await getUploadURL(
professionalData.avatar.name,
professionalData.avatar.type
);
if (uploadRes.error || !uploadRes.data) {
throw new Error(uploadRes.error || "Erro ao obter URL de upload");
}
await uploadFileToSignedUrl(
uploadRes.data.upload_url,
professionalData.avatar
);
avatarUrl = uploadRes.data.public_url;
console.log("Upload concluído. URL:", avatarUrl);
} catch (err) {
console.error("Erro no upload do avatar:", err);
throw new Error(
"Falha ao enviar foto de perfil: " +
(err instanceof Error ? err.message : "Erro desconhecido")
);
}
Indicadores Visuais:
- Label com asterisco vermelho: "Foto de Perfil *"
- Preview circular da foto com borda destacada (#B9CF33)
- Botão de remoção (X) quando foto está carregada
- Placeholder visual quando não há foto