Merge pull request #29 from rede5/Front-back-integracao-task9

Resolvido problemas críticos na experiência do usuário (Event Owner) ao criar eventos, garantindo consistência de dados, eliminando criações duplicadas e corrigindo o funcionamento dos filtros na dashboard.

Principais Alterações:

Correção de Duplicidade na Criação (Critical Bug):
Removida a chamada direta à API 
createAgenda
 dentro do componente 
EventForm
. A criação agora é centralizada via callback 
onSubmit
, evitando que o evento fosse submetido duas vezes (uma pelo formulário e outra pelo Dashboard/Context).
Consistência de Dados e Formatação:
Implementado reload automático (window.location.href = '/painel') após o sucesso da criação. Isso garante que a lista de eventos carregue os dados completos do backend (incluindo joins de Curso, Instituição e FOT), resolvendo o bug onde o evento aparecia incompleto na lista.
Corrigido o formato da data enviada ao backend (ISOString com sufixo Z), resolvendo o erro de parse RFC3339 no servidor Go.
Normalizada a chave de recuperação do token no localStorage (de @Photum:token para token).
Correção de Filtros (Dashboard):
Ajustado o filtro avançado de FOT para buscar pelo campo visual fot (Número do FOT) em vez do fotId (UUID interno).
Adicionado suporte a busca case-insensitive (ignora maiúsculas/minúsculas).
Arquivos Impactados:

frontend/components/EventForm.tsx
frontend/contexts/DataContext.tsx
frontend/pages/Dashboard.tsx
This commit is contained in:
Andre F. Rodrigues 2025-12-16 20:43:56 -03:00 committed by GitHub
commit ccb0871388
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 30 additions and 18 deletions

View file

@ -334,23 +334,13 @@ export const EventForm: React.FC<EventFormProps> = ({
pre_venda: true
};
const authToken = userToken || localStorage.getItem("token") || "";
const response = await createAgenda(authToken, payload);
if (response.error) {
alert("Erro ao criar evento: " + response.error);
setShowToast(false);
return;
}
// Submit to parent handler
setTimeout(() => {
if (onSubmit) {
onSubmit(formData);
}
// Redirect or close is handled by parent, but we show success via toast usually
alert("Solicitação enviada com sucesso!");
}, 1000);
} catch (e: any) {
console.error(e);
alert("Erro inesperado: " + e.message);

View file

@ -107,7 +107,7 @@ export const Navbar: React.FC<NavbarProps> = ({ onNavigate, currentPage }) => {
{/* Logo */}
<div
className="flex-shrink-0 flex items-center cursor-pointer"
onClick={() => onNavigate("home")}
onClick={() => onNavigate("painel")}
>
<img
src="/logo.png"

View file

@ -638,13 +638,35 @@ export const DataProvider: React.FC<{ children: ReactNode }> = ({
const result = await getAgendas(visibleToken);
console.log("Raw Agenda Data:", result.data); // Debug logging
if (result.data) {
console.log("Sample event from backend:", result.data[0]); // DEBUG: Ver estrutura e status
// Map backend status to frontend EventStatus
const mapStatus = (backendStatus: string): EventStatus => {
const statusMap: Record<string, EventStatus> = {
"Pendente": EventStatus.PENDING_APPROVAL,
"Aguardando Aprovação": EventStatus.PENDING_APPROVAL,
"PENDING_APPROVAL": EventStatus.PENDING_APPROVAL,
"Confirmado": EventStatus.CONFIRMED,
"CONFIRMED": EventStatus.CONFIRMED,
"Em Planejamento": EventStatus.PLANNING,
"PLANNING": EventStatus.PLANNING,
"Em Execução": EventStatus.IN_PROGRESS,
"IN_PROGRESS": EventStatus.IN_PROGRESS,
"Entregue": EventStatus.DELIVERED,
"DELIVERED": EventStatus.DELIVERED,
"Arquivado": EventStatus.ARCHIVED,
"ARCHIVED": EventStatus.ARCHIVED,
};
return statusMap[backendStatus] || EventStatus.PENDING_APPROVAL;
};
const mappedEvents: EventData[] = result.data.map((e: any) => ({
id: e.id,
name: e.observacoes_evento || e.tipo_evento_nome || "Evento sem nome", // Fallback mapping
date: e.data_evento ? e.data_evento.split('T')[0] : "",
time: e.horario || "00:00",
type: (e.tipo_evento_nome || "Outro") as EventType, // Map string to enum if possible, or keep string
status: EventStatus.PENDING_APPROVAL,
status: mapStatus(e.status), // Map from backend status with fallback
address: {
street: e.endereco ? e.endereco.split(',')[0] : "",
number: e.endereco ? e.endereco.split(',')[1]?.split('-')[0]?.trim() || "" : "",
@ -764,7 +786,7 @@ export const DataProvider: React.FC<{ children: ReactNode }> = ({
}, [token]);
const addEvent = async (event: EventData) => {
const token = localStorage.getItem("@Photum:token");
const token = localStorage.getItem("token");
if (!token) {
console.error("No token found");
// Fallback for offline/mock
@ -776,7 +798,7 @@ export const DataProvider: React.FC<{ children: ReactNode }> = ({
// Map frontend fields (camelCase) to backend fields (snake_case)
const payload = {
fot_id: event.fotId,
data_evento: event.date, // "YYYY-MM-DD" is acceptable
data_evento: event.date + "T" + (event.time || "00:00") + ":00Z", // Backend expects full datetime with timezone
tipo_evento_id: event.typeId,
observacoes_evento: event.name, // "Observações do Evento" maps to name in EventForm
// local_evento: event.address.street + ", " + event.address.number, // Or map separate fields if needed
@ -807,8 +829,8 @@ export const DataProvider: React.FC<{ children: ReactNode }> = ({
if (result.data) {
// Success
console.log("Agenda criada:", result.data);
const newEvent = { ...event, id: result.data.id, status: EventStatus.PENDING_APPROVAL };
setEvents((prev) => [newEvent, ...prev]);
// Force reload to ensure complete data consistency (FOT, joins, etc.)
window.location.href = '/painel';
} else {
console.error("Erro ao criar agenda API:", result.error);
// Fallback or Toast?

View file

@ -102,7 +102,7 @@ export const Dashboard: React.FC<DashboardProps> = ({
!advancedFilters.date || e.date === advancedFilters.date;
const matchesFot =
!advancedFilters.fotId ||
String((e as any).fotId || "").includes(advancedFilters.fotId);
String(e.fot || "").toLowerCase().includes(advancedFilters.fotId.toLowerCase());
const matchesType =
!advancedFilters.type || e.type === advancedFilters.type;