Merge branch 'dev' into hml

This commit is contained in:
NANDO9322 2026-02-20 10:28:42 -03:00
commit 1bdb446709
5 changed files with 71 additions and 9 deletions

View file

@ -24,7 +24,52 @@ O **Photum** é uma aplicação web full-stack desenvolvida com React + TypeScri
- ✅ **Backend Go**: API RESTful completa com PostgreSQL - ✅ **Backend Go**: API RESTful completa com PostgreSQL
--- ---
1. 📊 Status Report
Módulo / Perfil,Status,Detalhes Críticos (Blockers)
Superadmin,🔴 CRÍTICO,Cadastro FOT travado (sem Empresa/Curso/Ano). Dashboard quebra ao redimensionar. Modal de Novo Usuário trava a tela (scroll lock).
Empresa,🟠 PARCIAL,Equipe: Faltam funções e regiões. Filtros: Vazios.
Fotógrafo,🔴 CRÍTICO,Meus Pagamentos: Tela Branca (Crash). Região: Não editável.
Cliente,🟠 PARCIAL,"Solicitar Evento: Trava no ""Tipo de Evento"" (vazio). Upload e Mapas OK."
Geral (Backend),❌ OFF,A maioria dos formulários depende de GET /api/... que não está retornando dados.
```mermaid
graph TD
%% Atores
SA((Superadmin))
EMP((Empresa))
FOTO((Fotógrafo))
CLI((Cliente))
%% Bloqueios do Superadmin
SA -->|Tenta Cadastrar| FOT[Cadastro FOT]
FOT -->|Erro| DropEmp[Select Empresa VAZIO]
FOT -->|Erro| DropCur[Select Curso VAZIO]
FOT -.->|Bloqueio| FimFOT(Não Salva)
SA -->|Visualiza| Dash[Dashboard]
Dash -->|Redimensiona| BugUI[Layout Quebra/Some]
SA -->|Gerenciar| Users[Aprovação Usuários]
Users -->|Novo Usuário| ModalLock[Modal Trava Scroll]
ModalLock -->|Refresh| Logout(Força Logout)
%% Bloqueios da Empresa/Equipe
EMP -->|Adicionar| Member[Novo Profissional]
Member -->|Erro| DropFunc[Funções VAZIAS]
Member -->|Erro| DropReg[Regiões INCOMPLETAS]
%% Bloqueios do Fotógrafo
FOTO -->|Acessa| Fin[Meus Pagamentos]
Fin -->|Erro| WS[TELA BRANCA / Crash]
%% Bloqueios do Cliente
CLI -->|Solicita| NewEvent[Novo Evento]
NewEvent -->|Erro| DropTipo[Tipo Evento VAZIO]
NewEvent -->|Sucesso| Maps[Localização/Mapbox OK]
NewEvent -->|Sucesso| Upload[Upload Inspirações OK]
```
---
## 🚀 Como Executar o Projeto ## 🚀 Como Executar o Projeto
### Pré-requisitos ### Pré-requisitos

View file

@ -106,7 +106,12 @@ export const Navbar: React.FC<NavbarProps> = ({ onNavigate, currentPage }) => {
if (!user) return ""; if (!user) return "";
if (user.role === UserRole.BUSINESS_OWNER) return "Empresa"; if (user.role === UserRole.BUSINESS_OWNER) return "Empresa";
if (user.role === UserRole.EVENT_OWNER) return "Cliente"; if (user.role === UserRole.EVENT_OWNER) return "Cliente";
if (user.role === UserRole.PHOTOGRAPHER) return "Fotógrafo"; if (user.role === UserRole.PHOTOGRAPHER) {
if (user.functions && user.functions.length > 0) {
return user.functions[0].nome;
}
return "Profissional";
}
if (user.role === UserRole.SUPERADMIN) return "Super Admin"; if (user.role === UserRole.SUPERADMIN) return "Super Admin";
if (user.role === UserRole.AGENDA_VIEWER) return "Visualizador"; if (user.role === UserRole.AGENDA_VIEWER) return "Visualizador";
if (user.role === UserRole.RESEARCHER) return "Pesquisa"; if (user.role === UserRole.RESEARCHER) return "Pesquisa";
@ -440,7 +445,7 @@ export const Navbar: React.FC<NavbarProps> = ({ onNavigate, currentPage }) => {
user.role === UserRole.EVENT_OWNER) && ( user.role === UserRole.EVENT_OWNER) && (
<button <button
onClick={() => { onClick={() => {
setIsEditProfileModalOpen(true); onNavigate("profile");
setIsAccountDropdownOpen(false); setIsAccountDropdownOpen(false);
}} }}
className="w-full flex items-center gap-3 px-4 py-3 rounded-xl hover:bg-white transition-colors text-left group" className="w-full flex items-center gap-3 px-4 py-3 rounded-xl hover:bg-white transition-colors text-left group"

View file

@ -120,6 +120,7 @@ export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) =>
cidade: backendUser.cidade, cidade: backendUser.cidade,
estado: backendUser.estado, estado: backendUser.estado,
professionalId: data.profissional?.id, // Map professional ID professionalId: data.profissional?.id, // Map professional ID
functions: data.profissional?.functions || [],
}; };
console.log("AuthContext: restoreSession mapped user:", mappedUser); console.log("AuthContext: restoreSession mapped user:", mappedUser);
if (!backendUser.ativo) { if (!backendUser.ativo) {
@ -221,6 +222,7 @@ const login = async (email: string, password?: string) => {
cidade: backendUser.cidade, cidade: backendUser.cidade,
estado: backendUser.estado, estado: backendUser.estado,
professionalId: data.profissional?.id, // Map professional ID professionalId: data.profissional?.id, // Map professional ID
functions: data.profissional?.functions || [],
}; };
setUser(mappedUser); setUser(mappedUser);
@ -338,6 +340,7 @@ const login = async (email: string, password?: string) => {
bairro: backendUser.bairro, bairro: backendUser.bairro,
cidade: backendUser.cidade, cidade: backendUser.cidade,
estado: backendUser.estado, estado: backendUser.estado,
functions: backendUser.functions || [],
}; };
if (autoLogin) { if (autoLogin) {
setUser(mappedUser); setUser(mappedUser);

View file

@ -8,6 +8,7 @@ import {
rejectUser as apiRejectUser, rejectUser as apiRejectUser,
updateUserRole, updateUserRole,
getCompanies, getCompanies,
getFunctions,
} from "../services/apiService"; } from "../services/apiService";
import { UserApprovalStatus, UserRole } from "../types"; import { UserApprovalStatus, UserRole } from "../types";
import { import {
@ -62,7 +63,7 @@ const UserDetailsModal: React.FC<UserDetailsModalProps> = ({
return ( return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50 p-4 fade-in"> <div className="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50 p-4 fade-in">
<div className="bg-white rounded-lg shadow-xl w-full max-w-lg overflow-hidden animate-slide-up"> <div className="bg-white rounded-lg shadow-xl w-full max-w-lg max-h-[95vh] overflow-y-auto animate-slide-up">
<div className="flex justify-between items-center p-6 border-b border-gray-100"> <div className="flex justify-between items-center p-6 border-b border-gray-100">
<h3 className="text-xl font-bold text-gray-900 font-serif"> <h3 className="text-xl font-bold text-gray-900 font-serif">
Detalhes do Cadastro Detalhes do Cadastro
@ -196,20 +197,27 @@ const CreateUserModal: React.FC<CreateUserModalProps> = ({
formData, formData,
setFormData setFormData
}) => { }) => {
// Fetch companies // Fetch companies and functions
const [companies, setCompanies] = useState<any[]>([]); const [companies, setCompanies] = useState<any[]>([]);
const [functions, setFunctions] = useState<any[]>([]);
useEffect(() => { useEffect(() => {
if (formData.role === "EVENT_OWNER") { if (formData.role === "EVENT_OWNER") {
getCompanies().then(res => { getCompanies().then(res => {
if(res.data) setCompanies(res.data); if(res.data) setCompanies(res.data);
}); });
} }
if (formData.role === "PHOTOGRAPHER") {
getFunctions().then(res => {
if(res.data) setFunctions(res.data);
});
}
}, [formData.role]); }, [formData.role]);
if (!isOpen) return null; if (!isOpen) return null;
return ( return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50 p-4 fade-in"> <div className="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50 p-4 fade-in">
<div className="bg-white rounded-lg shadow-xl w-full max-w-md overflow-hidden animate-slide-up"> <div className="bg-white rounded-lg shadow-xl w-full max-w-md max-h-[95vh] overflow-y-auto animate-slide-up">
<div className="flex justify-between items-center p-6 border-b border-gray-100"> <div className="flex justify-between items-center p-6 border-b border-gray-100">
<h3 className="text-xl font-bold text-gray-900 font-serif"> <h3 className="text-xl font-bold text-gray-900 font-serif">
Novo Usuário Novo Usuário
@ -259,7 +267,7 @@ const CreateUserModal: React.FC<CreateUserModalProps> = ({
onChange={(e) => setFormData({...formData, role: e.target.value})} onChange={(e) => setFormData({...formData, role: e.target.value})}
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-photum-green focus:border-transparent outline-none transition-all" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-photum-green focus:border-transparent outline-none transition-all"
> >
<option value="PHOTOGRAPHER">Fotógrafo</option> <option value="PHOTOGRAPHER">Profissional</option>
<option value="EVENT_OWNER">Cliente (Empresa)</option> <option value="EVENT_OWNER">Cliente (Empresa)</option>
<option value="BUSINESS_OWNER">Dono de Negócio</option> <option value="BUSINESS_OWNER">Dono de Negócio</option>
<option value="ADMIN">Administrador</option> <option value="ADMIN">Administrador</option>
@ -451,9 +459,9 @@ const CreateUserModal: React.FC<CreateUserModalProps> = ({
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-photum-green focus:border-transparent outline-none transition-all" className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-photum-green focus:border-transparent outline-none transition-all"
> >
<option value="">Selecione...</option> <option value="">Selecione...</option>
<option value="Fotógrafo">Fotógrafo</option> {functions.map(f => (
<option value="Cinegrafista">Cinegrafista</option> <option key={f.id} value={f.nome}>{f.nome}</option>
<option value="Editor">Editor</option> ))}
</select> </select>
</div> </div>
</div> </div>

View file

@ -50,6 +50,7 @@ export interface User {
companyName?: string; // Nome da empresa vinculada companyName?: string; // Nome da empresa vinculada
allowedRegions?: string[]; // Regiões permitidas para o usuário allowedRegions?: string[]; // Regiões permitidas para o usuário
professionalId?: string; // ID do profissional vinculado (se houver) professionalId?: string; // ID do profissional vinculado (se houver)
functions?: { id: string; nome: string }[]; // Funções assumidas pelo profissional
// Client / Event Owner specific fields // Client / Event Owner specific fields
cpf_cnpj?: string; cpf_cnpj?: string;