Merge branch 'dev' into hml
This commit is contained in:
commit
1bdb446709
5 changed files with 71 additions and 9 deletions
45
README.md
45
README.md
|
|
@ -24,7 +24,52 @@ O **Photum** é uma aplicação web full-stack desenvolvida com React + TypeScri
|
|||
- ✅ **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
|
||||
|
||||
### Pré-requisitos
|
||||
|
|
|
|||
|
|
@ -106,7 +106,12 @@ export const Navbar: React.FC<NavbarProps> = ({ onNavigate, currentPage }) => {
|
|||
if (!user) return "";
|
||||
if (user.role === UserRole.BUSINESS_OWNER) return "Empresa";
|
||||
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.AGENDA_VIEWER) return "Visualizador";
|
||||
if (user.role === UserRole.RESEARCHER) return "Pesquisa";
|
||||
|
|
@ -440,7 +445,7 @@ export const Navbar: React.FC<NavbarProps> = ({ onNavigate, currentPage }) => {
|
|||
user.role === UserRole.EVENT_OWNER) && (
|
||||
<button
|
||||
onClick={() => {
|
||||
setIsEditProfileModalOpen(true);
|
||||
onNavigate("profile");
|
||||
setIsAccountDropdownOpen(false);
|
||||
}}
|
||||
className="w-full flex items-center gap-3 px-4 py-3 rounded-xl hover:bg-white transition-colors text-left group"
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) =>
|
|||
cidade: backendUser.cidade,
|
||||
estado: backendUser.estado,
|
||||
professionalId: data.profissional?.id, // Map professional ID
|
||||
functions: data.profissional?.functions || [],
|
||||
};
|
||||
console.log("AuthContext: restoreSession mapped user:", mappedUser);
|
||||
if (!backendUser.ativo) {
|
||||
|
|
@ -221,6 +222,7 @@ const login = async (email: string, password?: string) => {
|
|||
cidade: backendUser.cidade,
|
||||
estado: backendUser.estado,
|
||||
professionalId: data.profissional?.id, // Map professional ID
|
||||
functions: data.profissional?.functions || [],
|
||||
};
|
||||
|
||||
setUser(mappedUser);
|
||||
|
|
@ -338,6 +340,7 @@ const login = async (email: string, password?: string) => {
|
|||
bairro: backendUser.bairro,
|
||||
cidade: backendUser.cidade,
|
||||
estado: backendUser.estado,
|
||||
functions: backendUser.functions || [],
|
||||
};
|
||||
if (autoLogin) {
|
||||
setUser(mappedUser);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import {
|
|||
rejectUser as apiRejectUser,
|
||||
updateUserRole,
|
||||
getCompanies,
|
||||
getFunctions,
|
||||
} from "../services/apiService";
|
||||
import { UserApprovalStatus, UserRole } from "../types";
|
||||
import {
|
||||
|
|
@ -62,7 +63,7 @@ const UserDetailsModal: React.FC<UserDetailsModalProps> = ({
|
|||
|
||||
return (
|
||||
<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">
|
||||
<h3 className="text-xl font-bold text-gray-900 font-serif">
|
||||
Detalhes do Cadastro
|
||||
|
|
@ -196,20 +197,27 @@ const CreateUserModal: React.FC<CreateUserModalProps> = ({
|
|||
formData,
|
||||
setFormData
|
||||
}) => {
|
||||
// Fetch companies
|
||||
// Fetch companies and functions
|
||||
const [companies, setCompanies] = useState<any[]>([]);
|
||||
const [functions, setFunctions] = useState<any[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
if (formData.role === "EVENT_OWNER") {
|
||||
getCompanies().then(res => {
|
||||
if(res.data) setCompanies(res.data);
|
||||
});
|
||||
}
|
||||
if (formData.role === "PHOTOGRAPHER") {
|
||||
getFunctions().then(res => {
|
||||
if(res.data) setFunctions(res.data);
|
||||
});
|
||||
}
|
||||
}, [formData.role]);
|
||||
|
||||
if (!isOpen) return null;
|
||||
return (
|
||||
<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">
|
||||
<h3 className="text-xl font-bold text-gray-900 font-serif">
|
||||
Novo Usuário
|
||||
|
|
@ -259,7 +267,7 @@ const CreateUserModal: React.FC<CreateUserModalProps> = ({
|
|||
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"
|
||||
>
|
||||
<option value="PHOTOGRAPHER">Fotógrafo</option>
|
||||
<option value="PHOTOGRAPHER">Profissional</option>
|
||||
<option value="EVENT_OWNER">Cliente (Empresa)</option>
|
||||
<option value="BUSINESS_OWNER">Dono de Negócio</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"
|
||||
>
|
||||
<option value="">Selecione...</option>
|
||||
<option value="Fotógrafo">Fotógrafo</option>
|
||||
<option value="Cinegrafista">Cinegrafista</option>
|
||||
<option value="Editor">Editor</option>
|
||||
{functions.map(f => (
|
||||
<option key={f.id} value={f.nome}>{f.nome}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ export interface User {
|
|||
companyName?: string; // Nome da empresa vinculada
|
||||
allowedRegions?: string[]; // Regiões permitidas para o usuário
|
||||
professionalId?: string; // ID do profissional vinculado (se houver)
|
||||
functions?: { id: string; nome: string }[]; // Funções assumidas pelo profissional
|
||||
|
||||
// Client / Event Owner specific fields
|
||||
cpf_cnpj?: string;
|
||||
|
|
|
|||
Loading…
Reference in a new issue