Backend: - Adiciona campo `contacts` (JSONB) na tabela `agendas` e atualiza lógica de criação. Frontend: - Adiciona campos dinâmicos de contato no formulário de Novo Evento. - Otimiza busca do Mapbox priorizando a região selecionada (SP/MG). - Implementa "Deep Linking" no Dashboard (abrir detalhes do evento direto via URL). - Corrige "flicker" (piscada da lista) ao carregar detalhes via link permitindo carregamento suave. - Adiciona botão "Aprovar" e fluxo de aprovação na visualização de detalhes. - Corrige fluxo de edição (salvar retorna para detalhes sem recarregar a página). - Corrige navegação dos botões "Voltar" em Detalhes e Logística para retornarem corretamente à lista/painel. - Melhora layout do cabeçalho de detalhes (remove ID vazio e unifica títulos duplicados). - Ajusta clique no Logo para forçar reset da navegação para o Painel.
708 lines
32 KiB
TypeScript
708 lines
32 KiB
TypeScript
import React, { useState, useEffect } from "react";
|
|
import { UserRole } from "../types";
|
|
import { useAuth } from "../contexts/AuthContext";
|
|
import {
|
|
BrowserRouter,
|
|
Routes,
|
|
Route,
|
|
Navigate,
|
|
useNavigate,
|
|
useLocation,
|
|
} from "react-router-dom";
|
|
import {
|
|
Menu,
|
|
X,
|
|
LogOut,
|
|
User,
|
|
Settings,
|
|
Camera,
|
|
Mail,
|
|
Phone,
|
|
GraduationCap,
|
|
} from "lucide-react";
|
|
import { Button } from "./Button";
|
|
import { RegionSwitcher } from "./RegionSwitcher";
|
|
|
|
interface NavbarProps {
|
|
onNavigate: (page: string) => void;
|
|
currentPage: string;
|
|
}
|
|
|
|
export const Navbar: React.FC<NavbarProps> = ({ onNavigate, currentPage }) => {
|
|
const navigate = useNavigate();
|
|
const { user, logout } = useAuth();
|
|
const [isScrolled, setIsScrolled] = useState(false);
|
|
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
|
const [isAccountDropdownOpen, setIsAccountDropdownOpen] = useState(false);
|
|
const [isEditProfileModalOpen, setIsEditProfileModalOpen] = useState(false);
|
|
const [profileData, setProfileData] = useState({
|
|
name: user?.name || "",
|
|
email: user?.email || "",
|
|
phone: "",
|
|
avatar: user?.avatar || "",
|
|
});
|
|
const [avatarFile, setAvatarFile] = useState<File | null>(null);
|
|
const [avatarPreview, setAvatarPreview] = useState<string | null>(null);
|
|
|
|
useEffect(() => {
|
|
const handleScroll = () => {
|
|
setIsScrolled(window.scrollY > 20);
|
|
};
|
|
window.addEventListener("scroll", handleScroll);
|
|
return () => window.removeEventListener("scroll", handleScroll);
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
const handleClickOutside = (event: MouseEvent) => {
|
|
if (isAccountDropdownOpen) {
|
|
const target = event.target as HTMLElement;
|
|
if (!target.closest(".relative")) {
|
|
setIsAccountDropdownOpen(false);
|
|
}
|
|
}
|
|
};
|
|
document.addEventListener("mousedown", handleClickOutside);
|
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
}, [isAccountDropdownOpen]);
|
|
|
|
const getLinks = () => {
|
|
if (!user) return [];
|
|
|
|
switch (user.role) {
|
|
case UserRole.SUPERADMIN:
|
|
case UserRole.BUSINESS_OWNER:
|
|
return [
|
|
{ name: "Agenda", path: "painel" },
|
|
{ name: "Equipe", path: "equipe" },
|
|
{ name: "Cadastro de FOT", path: "cursos" },
|
|
{ name: "Aprovação de Cadastros", path: "aprovacao-cadastros" },
|
|
{ name: "Códigos de Acesso", path: "codigos-acesso" },
|
|
{ name: "Financeiro", path: "financeiro" },
|
|
];
|
|
case UserRole.AGENDA_VIEWER:
|
|
return [
|
|
{ name: "Agenda", path: "painel" },
|
|
];
|
|
case UserRole.RESEARCHER:
|
|
return [
|
|
{ name: "Painel", path: "painel" },
|
|
];
|
|
case UserRole.EVENT_OWNER:
|
|
return [
|
|
{ name: "Meus Eventos", path: "painel" },
|
|
{ name: "Solicitar Evento", path: "solicitar-evento" },
|
|
];
|
|
case UserRole.PHOTOGRAPHER:
|
|
return [
|
|
{ name: "Eventos Designados", path: "painel" },
|
|
{ name: "Meus Pagamentos", path: "meus-pagamentos" },
|
|
];
|
|
default:
|
|
return [];
|
|
}
|
|
};
|
|
|
|
const getRoleLabel = () => {
|
|
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.SUPERADMIN) return "Super Admin";
|
|
if (user.role === UserRole.AGENDA_VIEWER) return "Visualizador";
|
|
if (user.role === UserRole.RESEARCHER) return "Pesquisa";
|
|
return "";
|
|
};
|
|
|
|
const getAvatarSrc = (targetUser: { name: string; avatar?: string }) => {
|
|
if (targetUser?.avatar && targetUser.avatar.trim() !== "") {
|
|
return targetUser.avatar;
|
|
}
|
|
return `https://ui-avatars.com/api/?name=${encodeURIComponent(
|
|
targetUser.name || "User"
|
|
)}&background=random&color=fff&size=128`;
|
|
};
|
|
|
|
const handleAvatarChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
const file = e.target.files?.[0];
|
|
if (file) {
|
|
// Validate file size (max 5MB)
|
|
if (file.size > 5 * 1024 * 1024) {
|
|
alert("A imagem deve ter no máximo 5MB");
|
|
return;
|
|
}
|
|
|
|
// Validate file type
|
|
if (!file.type.startsWith('image/')) {
|
|
alert("Por favor, selecione uma imagem válida");
|
|
return;
|
|
}
|
|
|
|
setAvatarFile(file);
|
|
|
|
// Create preview URL
|
|
const reader = new FileReader();
|
|
reader.onloadend = () => {
|
|
setAvatarPreview(reader.result as string);
|
|
};
|
|
reader.readAsDataURL(file);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<nav className="fixed top-0 left-0 w-full z-50 bg-white shadow-sm py-2 sm:py-3">
|
|
<div className="max-w-7xl mx-auto px-3 sm:px-4 lg:px-6">
|
|
<div className="flex justify-between items-center h-12 sm:h-14 md:h-16">
|
|
|
|
{/* Logo */}
|
|
<div
|
|
className="flex-shrink-0 flex items-center cursor-pointer"
|
|
onClick={() => window.location.href = "/painel"}
|
|
>
|
|
<img
|
|
src="/logo.png"
|
|
alt="Photum Formaturas"
|
|
className="h-18 sm:h-30 w-auto max-w-[200px] object-contain mb-4 ml-3"
|
|
/>
|
|
</div>
|
|
|
|
{/* Desktop Navigation */}
|
|
{user && (
|
|
<div className="hidden lg:flex items-center space-x-3 xl:space-x-6">
|
|
{getLinks().map((link) => (
|
|
<button
|
|
key={link.path}
|
|
onClick={() => onNavigate(link.path)}
|
|
className={`text-xs xl:text-sm font-medium tracking-wide uppercase hover:text-brand-gold transition-colors pb-1 ${currentPage === link.path
|
|
? "text-brand-gold border-b-2 border-brand-gold"
|
|
: "text-gray-600 border-b-2 border-transparent"
|
|
}`}
|
|
>
|
|
{link.name}
|
|
</button>
|
|
))}
|
|
<div className="ml-4 border-l pl-4 border-gray-200">
|
|
<RegionSwitcher />
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Right Side Actions */}
|
|
<div className="hidden lg:flex items-center space-x-2 xl:space-x-4">
|
|
{user ? (
|
|
<div className="flex items-center gap-2 xl:gap-3">
|
|
<div className="flex flex-col items-end mr-1 xl:mr-2">
|
|
<span className="text-xs xl:text-sm font-bold text-brand-black leading-tight">
|
|
{user.name}
|
|
</span>
|
|
<span className="text-[9px] xl:text-[10px] uppercase tracking-wider text-brand-gold leading-tight">
|
|
{getRoleLabel()}
|
|
</span>
|
|
</div>
|
|
|
|
{/* Avatar com dropdown */}
|
|
<div className="relative">
|
|
<button
|
|
onClick={() =>
|
|
setIsAccountDropdownOpen(!isAccountDropdownOpen)
|
|
}
|
|
className="h-8 w-8 xl:h-9 xl:w-9 rounded-full bg-gray-100 overflow-hidden border border-gray-200 ring-2 ring-transparent hover:ring-brand-gold transition-all cursor-pointer"
|
|
>
|
|
<img
|
|
src={getAvatarSrc(user)}
|
|
alt="Avatar"
|
|
className="w-full h-full object-cover"
|
|
onError={(e) => {
|
|
e.currentTarget.src = `https://ui-avatars.com/api/?name=${encodeURIComponent(user.name || "User")}&background=random&color=fff&size=128`;
|
|
}}
|
|
/>
|
|
</button>
|
|
|
|
{/* Profile Preview Dropdown */}
|
|
{isAccountDropdownOpen && (
|
|
<div className="absolute right-0 top-full mt-3 w-80 bg-white rounded-2xl shadow-2xl border border-gray-100 overflow-hidden z-50 fade-in">
|
|
{/* Header com foto e info */}
|
|
<div className="bg-gradient-to-r from-[#492E61] to-[#5a3a7a] p-6 text-center relative">
|
|
<div className="w-20 h-20 mx-auto mb-3 rounded-full bg-white/20 backdrop-blur-sm flex items-center justify-center border-4 border-white/30 overflow-hidden">
|
|
<img
|
|
src={getAvatarSrc(user)}
|
|
alt={user.name}
|
|
className="w-full h-full object-cover"
|
|
onError={(e) => {
|
|
e.currentTarget.src = `https://ui-avatars.com/api/?name=${encodeURIComponent(user.name || "User")}&background=random&color=fff&size=128`;
|
|
}}
|
|
/>
|
|
</div>
|
|
<h3 className="text-white font-bold text-lg mb-1">
|
|
{user.name}
|
|
</h3>
|
|
<p className="text-white/90 text-sm mb-1">
|
|
{user.email}
|
|
</p>
|
|
<span className="inline-block px-3 py-1 bg-white/20 backdrop-blur-sm rounded-full text-xs font-medium text-white border border-white/30">
|
|
{getRoleLabel()}
|
|
</span>
|
|
</div>
|
|
|
|
{/* Menu Items */}
|
|
<div className="p-4 space-y-2 bg-gray-50">
|
|
{/* Editar Perfil - Apenas para Fotógrafos e Clientes */}
|
|
{(user.role === UserRole.PHOTOGRAPHER ||
|
|
user.role === UserRole.EVENT_OWNER) && (
|
|
<button
|
|
onClick={() => {
|
|
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"
|
|
>
|
|
<div className="w-10 h-10 rounded-lg bg-[#492E61]/10 flex items-center justify-center group-hover:bg-[#492E61]/20 transition-colors">
|
|
<User size={20} className="text-[#492E61]" />
|
|
</div>
|
|
<div className="flex-1">
|
|
<p className="text-sm font-semibold text-gray-900">
|
|
Editar Perfil
|
|
</p>
|
|
<p className="text-xs text-gray-500">
|
|
Atualize suas informações
|
|
</p>
|
|
</div>
|
|
</button>
|
|
)}
|
|
|
|
{/* Configurações - Apenas para CEO e Business Owner */}
|
|
{(user.role === UserRole.BUSINESS_OWNER ||
|
|
user.role === UserRole.SUPERADMIN) && (
|
|
<button
|
|
onClick={() => {
|
|
onNavigate("configuracoes");
|
|
setIsAccountDropdownOpen(false);
|
|
}}
|
|
className="w-full flex items-center gap-3 px-4 py-3 rounded-xl hover:bg-white transition-colors text-left group"
|
|
>
|
|
<div className="w-10 h-10 rounded-lg bg-gray-200 flex items-center justify-center group-hover:bg-gray-300 transition-colors">
|
|
<Settings size={20} className="text-gray-600" />
|
|
</div>
|
|
<div className="flex-1">
|
|
<p className="text-sm font-semibold text-gray-900">
|
|
Configurações
|
|
</p>
|
|
<p className="text-xs text-gray-500">
|
|
Preferências da conta
|
|
</p>
|
|
</div>
|
|
</button>
|
|
)}
|
|
|
|
{/* Sair */}
|
|
<button
|
|
onClick={() => {
|
|
logout();
|
|
setIsAccountDropdownOpen(false);
|
|
}}
|
|
className="w-full flex items-center gap-3 px-4 py-3 rounded-xl hover:bg-red-50 transition-colors text-left group border-t border-gray-200 mt-2 pt-4"
|
|
>
|
|
<div className="w-10 h-10 rounded-lg bg-red-100 flex items-center justify-center group-hover:bg-red-200 transition-colors">
|
|
<LogOut size={20} className="text-red-600" />
|
|
</div>
|
|
<div className="flex-1">
|
|
<p className="text-sm font-semibold text-red-600">
|
|
Sair da Conta
|
|
</p>
|
|
<p className="text-xs text-red-400">
|
|
Desconectar do sistema
|
|
</p>
|
|
</div>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
) : (
|
|
!['entrar', 'cadastro', 'cadastro-profissional'].includes(currentPage) && (
|
|
<div className="relative">
|
|
<button
|
|
onClick={() =>
|
|
setIsAccountDropdownOpen(!isAccountDropdownOpen)
|
|
}
|
|
className="flex items-center gap-2 px-4 py-2 rounded-full hover:bg-gray-100 transition-colors shadow-md"
|
|
>
|
|
<div className="w-10 h-10 rounded-full border-2 border-brand-gold flex items-center justify-center text-brand-gold hover:bg-brand-gold hover:text-white transition-colors">
|
|
<User size={24} />
|
|
</div>
|
|
<div className="text-left hidden lg:block">
|
|
<p className="text-xs text-gray-500">Olá, bem-vindo(a)</p>
|
|
<p className="text-xs font-semibold text-gray-700">
|
|
Entrar/Cadastrar
|
|
</p>
|
|
</div>
|
|
</button>
|
|
|
|
{/* Dropdown Popup - Responsivo */}
|
|
{isAccountDropdownOpen && (
|
|
<div className="absolute right-0 lg:left-1/2 lg:-translate-x-1/2 top-full mt-3 w-72 bg-white rounded-2xl shadow-2xl border border-gray-100 overflow-hidden z-50 fade-in">
|
|
{/* Header com ícone */}
|
|
<div className="bg-gradient-to-r from-[#492E61] to-[#5a3a7a] p-6 text-center">
|
|
<div className="w-16 h-16 mx-auto mb-3 rounded-full bg-white/20 backdrop-blur-sm flex items-center justify-center border-2 border-white/30">
|
|
<User size={32} className="text-white" />
|
|
</div>
|
|
<p className="text-white/70 text-xs mb-1">
|
|
Olá, bem-vindo(a)
|
|
</p>
|
|
<p className="text-white font-semibold text-base">
|
|
Entrar/Cadastrar
|
|
</p>
|
|
</div>
|
|
|
|
{/* Botões */}
|
|
<div className="p-5 space-y-3 bg-gray-50">
|
|
<Button
|
|
onClick={() => {
|
|
onNavigate("entrar");
|
|
setIsAccountDropdownOpen(false);
|
|
}}
|
|
variant="secondary"
|
|
className="w-full rounded-xl shadow-sm hover:shadow-md transition-shadow"
|
|
>
|
|
ENTRAR
|
|
</Button>
|
|
|
|
<Button
|
|
onClick={() => {
|
|
onNavigate("cadastro");
|
|
setIsAccountDropdownOpen(false);
|
|
}}
|
|
variant="primary"
|
|
className="w-full rounded-xl shadow-sm hover:shadow-md transition-shadow"
|
|
>
|
|
Cadastre-se agora
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
)}
|
|
</div>
|
|
|
|
{/* Mobile Buttons */}
|
|
<div className="lg:hidden flex items-center gap-2">
|
|
{user ? (
|
|
<>
|
|
<div className="relative">
|
|
<button
|
|
onClick={() =>
|
|
setIsAccountDropdownOpen(!isAccountDropdownOpen)
|
|
}
|
|
className="h-9 w-9 sm:h-10 sm:w-10 rounded-full bg-gray-100 overflow-hidden border border-gray-200 ring-2 ring-transparent active:ring-brand-gold transition-all shadow-md"
|
|
>
|
|
<img
|
|
src={getAvatarSrc(user)}
|
|
alt="Avatar"
|
|
className="w-full h-full object-cover"
|
|
onError={(e) => {
|
|
e.currentTarget.src = `https://ui-avatars.com/api/?name=${encodeURIComponent(user.name || "User")}&background=random&color=fff&size=128`;
|
|
}}
|
|
/>
|
|
</button>
|
|
|
|
{/* Profile Preview Dropdown Mobile */}
|
|
{isAccountDropdownOpen && (
|
|
<div className="absolute right-0 top-full mt-3 w-80 bg-white rounded-2xl shadow-2xl border border-gray-100 overflow-hidden z-50 fade-in">
|
|
{/* Header com foto e info */}
|
|
<div className="bg-gradient-to-r from-[#492E61] to-[#5a3a7a] p-6 text-center relative">
|
|
<div className="w-20 h-20 mx-auto mb-3 rounded-full bg-white/20 backdrop-blur-sm flex items-center justify-center border-4 border-white/30 overflow-hidden">
|
|
<img
|
|
src={getAvatarSrc(user)}
|
|
alt={user.name}
|
|
className="w-full h-full object-cover"
|
|
onError={(e) => {
|
|
e.currentTarget.src = `https://ui-avatars.com/api/?name=${encodeURIComponent(user.name || "User")}&background=random&color=fff&size=128`;
|
|
}}
|
|
/>
|
|
</div>
|
|
<h3 className="text-white font-bold text-lg mb-1">
|
|
{user.name}
|
|
</h3>
|
|
<p className="text-white/90 text-sm mb-1">
|
|
{user.email}
|
|
</p>
|
|
<span className="inline-block px-3 py-1 bg-white/20 backdrop-blur-sm rounded-full text-xs font-medium text-white border border-white/30">
|
|
{getRoleLabel()}
|
|
</span>
|
|
</div>
|
|
|
|
{/* Menu Items */}
|
|
<div className="p-4 space-y-2 bg-gray-50">
|
|
{/* Editar Perfil - Apenas para Fotógrafos e Clientes */}
|
|
{(user.role === UserRole.PHOTOGRAPHER ||
|
|
user.role === UserRole.EVENT_OWNER) && (
|
|
<button
|
|
onClick={() => {
|
|
setIsEditProfileModalOpen(true);
|
|
setIsAccountDropdownOpen(false);
|
|
}}
|
|
className="w-full flex items-center gap-3 px-4 py-3 rounded-xl hover:bg-white transition-colors text-left group"
|
|
>
|
|
<div className="w-10 h-10 rounded-lg bg-[#492E61]/10 flex items-center justify-center group-hover:bg-[#492E61]/20 transition-colors">
|
|
<User size={20} className="text-[#492E61]" />
|
|
</div>
|
|
<div className="flex-1">
|
|
<p className="text-sm font-semibold text-gray-900">
|
|
Editar Perfil
|
|
</p>
|
|
<p className="text-xs text-gray-500">
|
|
Atualize suas informações
|
|
</p>
|
|
</div>
|
|
</button>
|
|
)}
|
|
|
|
{/* Configurações - Apenas para CEO e Business Owner */}
|
|
{(user.role === UserRole.BUSINESS_OWNER ||
|
|
user.role === UserRole.SUPERADMIN) && (
|
|
<button
|
|
onClick={() => {
|
|
onNavigate("configuracoes");
|
|
setIsAccountDropdownOpen(false);
|
|
}}
|
|
className="w-full flex items-center gap-3 px-4 py-3 rounded-xl hover:bg-white transition-colors text-left group"
|
|
>
|
|
<div className="w-10 h-10 rounded-lg bg-gray-200 flex items-center justify-center group-hover:bg-gray-300 transition-colors">
|
|
<Settings size={20} className="text-gray-600" />
|
|
</div>
|
|
<div className="flex-1">
|
|
<p className="text-sm font-semibold text-gray-900">
|
|
Configurações
|
|
</p>
|
|
<p className="text-xs text-gray-500">
|
|
Preferências da conta
|
|
</p>
|
|
</div>
|
|
</button>
|
|
)}
|
|
|
|
{/* Sair */}
|
|
<button
|
|
onClick={() => {
|
|
logout();
|
|
setIsAccountDropdownOpen(false);
|
|
}}
|
|
className="w-full flex items-center gap-3 px-4 py-3 rounded-xl hover:bg-red-50 transition-colors text-left group border-t border-gray-200 mt-2 pt-4"
|
|
>
|
|
<div className="w-10 h-10 rounded-lg bg-red-100 flex items-center justify-center group-hover:bg-red-200 transition-colors">
|
|
<LogOut size={20} className="text-red-600" />
|
|
</div>
|
|
<div className="flex-1">
|
|
<p className="text-sm font-semibold text-red-600">
|
|
Sair da Conta
|
|
</p>
|
|
<p className="text-xs text-red-400">
|
|
Desconectar do sistema
|
|
</p>
|
|
</div>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Menu Hamburguer - Apenas para usuários logados */}
|
|
<button
|
|
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
|
|
className="text-brand-black hover:text-brand-gold p-1.5 sm:p-2"
|
|
>
|
|
{isMobileMenuOpen ? (
|
|
<X size={22} className="sm:w-6 sm:h-6" />
|
|
) : (
|
|
<Menu size={22} className="sm:w-6 sm:h-6" />
|
|
)}
|
|
</button>
|
|
</>
|
|
) : (
|
|
!['entrar', 'cadastro', 'cadastro-profissional'].includes(currentPage) && (
|
|
<div className="relative">
|
|
<button
|
|
onClick={() =>
|
|
setIsAccountDropdownOpen(!isAccountDropdownOpen)
|
|
}
|
|
className="w-10 h-10 rounded-full border-2 border-brand-gold flex items-center justify-center text-brand-gold shadow-md"
|
|
>
|
|
<User size={20} />
|
|
</button>
|
|
|
|
{/* Dropdown Popup Mobile */}
|
|
{isAccountDropdownOpen && (
|
|
<div className="absolute right-0 top-full mt-3 w-72 bg-white rounded-2xl shadow-2xl border border-gray-100 overflow-hidden z-50 fade-in">
|
|
{/* Header com ícone */}
|
|
<div className="bg-gradient-to-r from-[#492E61] to-[#5a3a7a] p-6 text-center">
|
|
<div className="w-16 h-16 mx-auto mb-3 rounded-full bg-white/20 backdrop-blur-sm flex items-center justify-center border-2 border-white/30">
|
|
<User size={32} className="text-white" />
|
|
</div>
|
|
<p className="text-white/70 text-xs mb-1">
|
|
Olá, bem-vindo(a)
|
|
</p>
|
|
<p className="text-white font-semibold text-base">
|
|
Entrar/Cadastrar
|
|
</p>
|
|
</div>
|
|
|
|
{/* Botões */}
|
|
<div className="p-5 space-y-3 bg-gray-50">
|
|
<Button
|
|
onClick={() => {
|
|
onNavigate("entrar");
|
|
setIsAccountDropdownOpen(false);
|
|
}}
|
|
variant="secondary"
|
|
className="w-full rounded-xl shadow-sm hover:shadow-md transition-shadow"
|
|
>
|
|
ENTRAR
|
|
</Button>
|
|
|
|
<Button
|
|
onClick={() => {
|
|
onNavigate("cadastro");
|
|
setIsAccountDropdownOpen(false);
|
|
}}
|
|
variant="primary"
|
|
className="w-full rounded-xl shadow-sm hover:shadow-md transition-shadow"
|
|
>
|
|
Cadastre-se agora
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Mobile Menu */}
|
|
{isMobileMenuOpen && (
|
|
<div className="lg:hidden absolute top-full left-0 w-full bg-white border-b border-gray-100 shadow-lg fade-in">
|
|
<div className="px-3 sm:px-4 py-3 sm:py-4 space-y-2 sm:space-y-3">
|
|
{user &&
|
|
getLinks().map((link) => (
|
|
<button
|
|
key={link.path}
|
|
onClick={() => {
|
|
onNavigate(link.path);
|
|
setIsMobileMenuOpen(false);
|
|
}}
|
|
className="block w-full text-left text-sm sm:text-base font-medium text-gray-700 hover:text-brand-gold py-2 border-b border-gray-50"
|
|
>
|
|
{link.name}
|
|
</button>
|
|
))}
|
|
<div className="pt-4">
|
|
{user ? (
|
|
<div className="space-y-3">
|
|
<div className="py-2 flex justify-center border-b border-gray-100">
|
|
<RegionSwitcher />
|
|
</div>
|
|
{/* Info do usuário */}
|
|
<div className="flex items-center justify-between pb-3 border-b border-gray-100">
|
|
<div className="flex items-center">
|
|
<img
|
|
src={getAvatarSrc(user)}
|
|
className="w-10 h-10 rounded-full mr-3 border-2 border-gray-200"
|
|
alt={user.name}
|
|
onError={(e) => {
|
|
e.currentTarget.src = `https://ui-avatars.com/api/?name=${encodeURIComponent(user.name || "User")}&background=random&color=fff&size=128`;
|
|
}}
|
|
/>
|
|
<div>
|
|
<span className="font-bold text-sm block text-gray-900">
|
|
{user.name}
|
|
</span>
|
|
<span className="text-xs text-brand-gold font-medium">
|
|
{getRoleLabel()}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Botão Editar Perfil - Apenas para Fotógrafos e Clientes */}
|
|
{(user.role === UserRole.PHOTOGRAPHER ||
|
|
user.role === UserRole.EVENT_OWNER) && (
|
|
<button
|
|
onClick={() => {
|
|
onNavigate("profile");
|
|
setIsMobileMenuOpen(false);
|
|
}}
|
|
className="w-full flex items-center gap-3 px-4 py-3 bg-[#492E61]/5 hover:bg-[#492E61]/10 rounded-xl transition-colors"
|
|
>
|
|
<div className="w-10 h-10 rounded-lg bg-[#492E61]/10 flex items-center justify-center">
|
|
<User size={20} className="text-[#492E61]" />
|
|
</div>
|
|
<div className="flex-1 text-left">
|
|
<p className="text-sm font-semibold text-gray-900">
|
|
Editar Perfil
|
|
</p>
|
|
<p className="text-xs text-gray-500">
|
|
Atualize suas informações
|
|
</p>
|
|
</div>
|
|
</button>
|
|
)}
|
|
|
|
{/* Botão Sair */}
|
|
<button
|
|
onClick={() => {
|
|
logout();
|
|
setIsMobileMenuOpen(false);
|
|
}}
|
|
className="w-full flex items-center gap-3 px-4 py-3 bg-red-50 hover:bg-red-100 rounded-xl transition-colors"
|
|
>
|
|
<div className="w-10 h-10 rounded-lg bg-red-100 flex items-center justify-center">
|
|
<LogOut size={20} className="text-red-600" />
|
|
</div>
|
|
<div className="flex-1 text-left">
|
|
<p className="text-sm font-semibold text-red-600">
|
|
Sair da Conta
|
|
</p>
|
|
<p className="text-xs text-red-400">
|
|
Desconectar do sistema
|
|
</p>
|
|
</div>
|
|
</button>
|
|
</div>
|
|
) : (
|
|
<div className="flex flex-col gap-2">
|
|
<Button
|
|
className="w-full rounded-lg"
|
|
size="lg"
|
|
variant="secondary"
|
|
onClick={() => {
|
|
onNavigate("entrar");
|
|
setIsMobileMenuOpen(false);
|
|
}}
|
|
>
|
|
ENTRAR
|
|
</Button>
|
|
<Button
|
|
className="w-full bg-purple-600 text-white hover:bg-purple-700 focus:ring-purple-500 rounded-lg"
|
|
size="lg"
|
|
onClick={() => {
|
|
onNavigate("cadastro");
|
|
setIsMobileMenuOpen(false);
|
|
}}
|
|
>
|
|
Cadastre-se agora
|
|
</Button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</nav>
|
|
|
|
|
|
</>
|
|
);
|
|
};
|