feat: melhoria de layout e ajuste de calendario
This commit is contained in:
parent
cc6c45c6fe
commit
a3655d2068
12 changed files with 1013 additions and 871 deletions
|
|
@ -77,20 +77,22 @@ const AppContent: React.FC = () => {
|
|||
<main>{renderPage()}</main>
|
||||
|
||||
{currentPage === "home" && (
|
||||
<footer className="bg-gradient-to-br from-brand-purple to-brand-purple/90 text-brand-black py-16 md:py-20">
|
||||
<div className="w-full max-w-[1600px] mx-auto px-6 sm:px-8 md:px-12 lg:px-16 xl:px-20">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-8 sm:gap-10 md:gap-12 lg:gap-16 xl:gap-20 mb-12 md:mb-16">
|
||||
<footer className="bg-gradient-to-br from-brand-purple to-brand-purple/90 text-brand-black py-12 sm:py-16 md:py-20">
|
||||
<div className="w-full max-w-[1600px] mx-auto px-4 sm:px-6 md:px-8 lg:px-12 xl:px-16">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6 sm:gap-8 md:gap-10 lg:gap-12 xl:gap-16 mb-8 sm:mb-12 md:mb-16">
|
||||
{/* Logo e Descrição */}
|
||||
<div className="lg:col-span-1">
|
||||
<img
|
||||
src="/logo.png"
|
||||
alt="Photum Formaturas"
|
||||
className="h-40 sm:h-34 md:h-28 lg:h-42 mb-4 md:mb-6"
|
||||
/>
|
||||
<p className="text-brand-black/80 text-sm sm:text-base md:text-lg leading-relaxed">
|
||||
Eternizando momentos únicos com excelência e profissionalismo
|
||||
desde 2020.
|
||||
</p>
|
||||
<div className="lg:col-span-1 text-center sm:text-left">
|
||||
<div className="flex flex-col items-center sm:items-start">
|
||||
<img
|
||||
src="/logo.png"
|
||||
alt="Photum Formaturas"
|
||||
className="h-24 sm:h-28 md:h-32 lg:h-36 mb-4 md:mb-6"
|
||||
/>
|
||||
<p className="text-brand-black/80 text-xs sm:text-sm md:text-base leading-relaxed">
|
||||
Eternizando momentos únicos com excelência e profissionalismo
|
||||
desde 2020.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Serviços */}
|
||||
|
|
|
|||
|
|
@ -17,17 +17,17 @@ export const Button: React.FC<ButtonProps> = ({
|
|||
const baseStyles = "inline-flex items-center justify-center font-medium transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed";
|
||||
|
||||
const variants = {
|
||||
primary: "bg-brand-black text-white hover:bg-gray-800 focus:ring-brand-black",
|
||||
primary: "bg-[#492E61] text-white hover:bg-[#3a2450] focus:ring-[#492E61]",
|
||||
secondary: "bg-[#B9CF32] text-white hover:bg-[#a5bd2e] focus:ring-[#B9CF32]",
|
||||
outline: "border border-brand-black text-brand-black hover:bg-gray-50 focus:ring-brand-black",
|
||||
ghost: "text-brand-black hover:bg-gray-100 hover:text-gray-900"
|
||||
outline: "border border-[#492E61] text-[#492E61] hover:bg-[#492E61]/5 focus:ring-[#492E61]",
|
||||
ghost: "text-[#492E61] hover:bg-[#492E61]/10 hover:text-[#3a2450]"
|
||||
};
|
||||
|
||||
const sizes = {
|
||||
sm: "text-xs px-3 py-1.5 rounded-sm",
|
||||
md: "text-sm px-5 py-2.5 rounded-sm",
|
||||
lg: "text-base px-8 py-3 rounded-sm",
|
||||
xl: "text-lg px-10 py-4 rounded-md font-semibold"
|
||||
sm: "text-xs px-3 py-1.5 rounded-md",
|
||||
md: "text-sm px-5 py-2.5 rounded-lg",
|
||||
lg: "text-base px-8 py-3 rounded-lg",
|
||||
xl: "text-lg px-10 py-4 rounded-xl font-semibold"
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -14,85 +14,85 @@ export const EventCard: React.FC<EventCardProps> = ({ event, onClick }) => {
|
|||
const fullAddress = `${event.address.street}, ${event.address.number} - ${event.address.city}/${event.address.state}`;
|
||||
|
||||
return (
|
||||
<div
|
||||
<div
|
||||
className="group bg-white rounded-lg border border-gray-100 overflow-hidden hover:shadow-xl transition-all duration-300 cursor-pointer flex flex-col h-full"
|
||||
onClick={onClick}
|
||||
>
|
||||
<div className="relative h-48 overflow-hidden bg-gray-100">
|
||||
<div className="relative h-40 sm:h-44 md:h-48 overflow-hidden bg-gray-100">
|
||||
{/* Skeleton / Loading State */}
|
||||
{!imageLoaded && (
|
||||
<div className="absolute inset-0 bg-gray-200 animate-pulse flex items-center justify-center">
|
||||
<div className="w-8 h-8 border-2 border-gray-300 border-t-brand-gold rounded-full animate-spin"></div>
|
||||
<div className="w-6 h-6 sm:w-8 sm:h-8 border-2 border-gray-300 border-t-brand-gold rounded-full animate-spin"></div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<img
|
||||
src={event.coverImage}
|
||||
alt={event.name}
|
||||
<img
|
||||
src={event.coverImage}
|
||||
alt={event.name}
|
||||
className={`w-full h-full object-cover transition-all duration-700 group-hover:scale-105 ${imageLoaded ? 'opacity-100' : 'opacity-0'}`}
|
||||
onLoad={() => setImageLoaded(true)}
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent opacity-60"></div>
|
||||
<div className="absolute top-3 right-3">
|
||||
<span className={`text-xs font-semibold px-2 py-1 rounded-sm uppercase tracking-wide ${STATUS_COLORS[event.status]}`}>
|
||||
<div className="absolute top-2 sm:top-3 right-2 sm:right-3">
|
||||
<span className={`text-[10px] sm:text-xs font-semibold px-1.5 sm:px-2 py-0.5 sm:py-1 rounded-sm uppercase tracking-wide ${STATUS_COLORS[event.status]}`}>
|
||||
{event.status}
|
||||
</span>
|
||||
</div>
|
||||
<div className="absolute bottom-3 left-4 text-white">
|
||||
<p className="text-xs font-light uppercase tracking-widest opacity-90">{event.type}</p>
|
||||
<h3 className="text-lg font-serif font-medium drop-shadow-md">{event.name}</h3>
|
||||
<div className="absolute bottom-2 sm:bottom-3 left-3 sm:left-4 text-white">
|
||||
<p className="text-[10px] sm:text-xs font-light uppercase tracking-widest opacity-90">{event.type}</p>
|
||||
<h3 className="text-base sm:text-lg font-serif font-medium drop-shadow-md line-clamp-1">{event.name}</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="p-5 flex-1 flex flex-col justify-between">
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center text-gray-500 text-sm">
|
||||
<Calendar size={16} className="mr-2 text-brand-gold" />
|
||||
<span>{new Date(event.date).toLocaleDateString()} às {event.time}</span>
|
||||
|
||||
<div className="p-3 sm:p-4 md:p-5 flex-1 flex flex-col justify-between">
|
||||
<div className="space-y-2 sm:space-y-3">
|
||||
<div className="flex items-center text-gray-500 text-xs sm:text-sm">
|
||||
<Calendar size={14} className="sm:w-4 sm:h-4 mr-1.5 sm:mr-2 text-brand-gold flex-shrink-0" />
|
||||
<span className="truncate">{new Date(event.date).toLocaleDateString()} às {event.time}</span>
|
||||
</div>
|
||||
|
||||
|
||||
{/* Location with Tooltip */}
|
||||
<div className="relative group/tooltip">
|
||||
<div
|
||||
className="flex items-center text-gray-500 text-sm"
|
||||
<div
|
||||
className="flex items-center text-gray-500 text-xs sm:text-sm"
|
||||
title={fullAddress} // Native tooltip fallback
|
||||
>
|
||||
<MapPin size={16} className="mr-2 text-brand-gold flex-shrink-0" />
|
||||
<MapPin size={14} className="sm:w-4 sm:h-4 mr-1.5 sm:mr-2 text-brand-gold flex-shrink-0" />
|
||||
<span className="truncate">{event.address.city}, {event.address.state}</span>
|
||||
</div>
|
||||
|
||||
{/* Custom Tooltip */}
|
||||
<div className="absolute bottom-full left-0 mb-2 hidden group-hover/tooltip:block z-20 pointer-events-none">
|
||||
{/* Custom Tooltip - Hidden on mobile */}
|
||||
<div className="absolute bottom-full left-0 mb-2 hidden sm:group-hover/tooltip:block z-20 pointer-events-none">
|
||||
<div className="bg-brand-black text-white text-xs rounded py-1.5 px-3 whitespace-nowrap shadow-xl">
|
||||
{event.address.street}, {event.address.number}
|
||||
<br/>
|
||||
{event.address.city} - {event.address.state}
|
||||
{/* Arrow */}
|
||||
<div className="absolute top-full left-3 -mt-1 border-4 border-transparent border-t-brand-black"></div>
|
||||
{event.address.street}, {event.address.number}
|
||||
<br />
|
||||
{event.address.city} - {event.address.state}
|
||||
{/* Arrow */}
|
||||
<div className="absolute top-full left-3 -mt-1 border-4 border-transparent border-t-brand-black"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{event.contacts.length > 0 && (
|
||||
<div className="flex items-center text-gray-500 text-sm">
|
||||
<UserCheck size={16} className="mr-2 text-brand-gold" />
|
||||
<span>{event.contacts.length} {event.contacts.length === 1 ? 'Fornecedor/Contato' : 'Fornecedores/Contatos'}</span>
|
||||
<div className="flex items-center text-gray-500 text-xs sm:text-sm">
|
||||
<UserCheck size={14} className="sm:w-4 sm:h-4 mr-1.5 sm:mr-2 text-brand-gold flex-shrink-0" />
|
||||
<span className="truncate">{event.contacts.length} {event.contacts.length === 1 ? 'Contato' : 'Contatos'}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="mt-5 pt-4 border-t border-gray-50 flex items-center justify-between">
|
||||
<div className="flex -space-x-2">
|
||||
{[1,2,3].map(i => (
|
||||
<div key={i} className="w-8 h-8 rounded-full border-2 border-white bg-gray-200" style={{backgroundImage: `url(https://i.pravatar.cc/100?img=${i})`, backgroundSize: 'cover'}}></div>
|
||||
))}
|
||||
<div className="w-8 h-8 rounded-full border-2 border-white bg-gray-100 flex items-center justify-center text-xs text-gray-500 font-medium">
|
||||
+4
|
||||
</div>
|
||||
</div>
|
||||
<button className="text-brand-black group-hover:text-brand-gold transition-colors">
|
||||
<ArrowRight size={20} />
|
||||
</button>
|
||||
|
||||
<div className="mt-3 sm:mt-4 md:mt-5 pt-3 sm:pt-4 border-t border-gray-50 flex items-center justify-between">
|
||||
<div className="flex -space-x-1.5 sm:-space-x-2">
|
||||
{[1, 2, 3].map(i => (
|
||||
<div key={i} className="w-6 h-6 sm:w-7 sm:h-7 md:w-8 md:h-8 rounded-full border-2 border-white bg-gray-200" style={{ backgroundImage: `url(https://i.pravatar.cc/100?img=${i})`, backgroundSize: 'cover' }}></div>
|
||||
))}
|
||||
<div className="w-6 h-6 sm:w-7 sm:h-7 md:w-8 md:h-8 rounded-full border-2 border-white bg-gray-100 flex items-center justify-center text-[10px] sm:text-xs text-gray-500 font-medium">
|
||||
+4
|
||||
</div>
|
||||
</div>
|
||||
<button className="text-brand-black group-hover:text-brand-gold transition-colors">
|
||||
<ArrowRight size={18} className="sm:w-5 sm:h-5" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -92,13 +92,13 @@ export const EventForm: React.FC<EventFormProps> = ({
|
|||
const formTitle = initialData
|
||||
? "Editar Evento"
|
||||
: isClientRequest
|
||||
? "Solicitar Orçamento/Evento"
|
||||
: "Cadastrar Novo Evento";
|
||||
? "Solicitar Orçamento/Evento"
|
||||
: "Cadastrar Novo Evento";
|
||||
const submitLabel = initialData
|
||||
? "Salvar Alterações"
|
||||
: isClientRequest
|
||||
? "Enviar Solicitação"
|
||||
: "Criar Evento";
|
||||
? "Enviar Solicitação"
|
||||
: "Criar Evento";
|
||||
|
||||
// Address Autocomplete Logic using Mapbox
|
||||
useEffect(() => {
|
||||
|
|
@ -264,11 +264,11 @@ export const EventForm: React.FC<EventFormProps> = ({
|
|||
<div className="bg-white rounded-lg shadow-xl overflow-hidden max-w-4xl mx-auto border border-gray-100 slide-up relative">
|
||||
{/* Success Toast */}
|
||||
{showToast && (
|
||||
<div className="absolute top-4 right-4 z-50 bg-brand-black text-white px-6 py-4 rounded shadow-2xl flex items-center space-x-3 fade-in">
|
||||
<CheckCircle className="text-brand-gold h-6 w-6" />
|
||||
<div className="absolute top-4 right-4 z-50 bg-brand-black text-white px-4 sm:px-6 py-3 sm:py-4 rounded shadow-2xl flex items-center space-x-2 sm:space-x-3 fade-in">
|
||||
<CheckCircle className="text-brand-gold h-5 w-5 sm:h-6 sm:w-6" />
|
||||
<div>
|
||||
<h4 className="font-bold text-sm">Sucesso!</h4>
|
||||
<p className="text-xs text-gray-300">
|
||||
<h4 className="font-bold text-xs sm:text-sm">Sucesso!</h4>
|
||||
<p className="text-[10px] sm:text-xs text-gray-300">
|
||||
As informações foram salvas.
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -276,40 +276,67 @@ export const EventForm: React.FC<EventFormProps> = ({
|
|||
)}
|
||||
|
||||
{/* Form Header */}
|
||||
<div className="bg-gray-50 border-b px-8 py-6 flex justify-between items-center">
|
||||
<div>
|
||||
<h2 className="text-2xl font-serif text-brand-black">{formTitle}</h2>
|
||||
<p className="text-sm text-gray-500 mt-1">
|
||||
{isClientRequest
|
||||
? "Preencha os detalhes do seu sonho. Nossa equipe analisará em breve."
|
||||
: "Preencha as informações técnicas do evento."}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex space-x-2">
|
||||
{["details", "location", "briefing", "files"].map((tab, idx) => (
|
||||
<div
|
||||
key={tab}
|
||||
className={`flex flex-col items-center ${
|
||||
activeTab === tab ? "opacity-100" : "opacity-40"
|
||||
}`}
|
||||
>
|
||||
<span
|
||||
className={`w-8 h-8 rounded-full flex items-center justify-center text-xs font-bold mb-1 ${
|
||||
activeTab === tab
|
||||
? "bg-brand-black text-white"
|
||||
: "bg-gray-200 text-gray-600"
|
||||
}`}
|
||||
<div className="bg-gray-50 border-b px-4 sm:px-6 md:px-8 py-4 sm:py-5 md:py-6">
|
||||
<div className="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-3 sm:gap-0">
|
||||
<div>
|
||||
<h2 className="text-xl sm:text-2xl font-serif text-brand-black">{formTitle}</h2>
|
||||
<p className="text-xs sm:text-sm text-gray-500 mt-1">
|
||||
{isClientRequest
|
||||
? "Preencha os detalhes do seu sonho. Nossa equipe analisará em breve."
|
||||
: "Preencha as informações técnicas do evento."}
|
||||
</p>
|
||||
</div>
|
||||
{/* Step indicators - Hidden on mobile, shown on tablet+ */}
|
||||
<div className="hidden sm:flex space-x-2">
|
||||
{["details", "location", "briefing", "files"].map((tab, idx) => (
|
||||
<div
|
||||
key={tab}
|
||||
className={`flex flex-col items-center ${activeTab === tab ? "opacity-100" : "opacity-40"
|
||||
}`}
|
||||
>
|
||||
{idx + 1}
|
||||
</span>
|
||||
</div>
|
||||
<span
|
||||
className={`w-7 h-7 sm:w-8 sm:h-8 rounded-full flex items-center justify-center text-xs font-bold mb-1 ${activeTab === tab
|
||||
? "bg-[#492E61] text-white"
|
||||
: "bg-gray-200 text-gray-600"
|
||||
}`}
|
||||
>
|
||||
{idx + 1}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Mobile Tabs - Horizontal */}
|
||||
<div className="lg:hidden border-b border-gray-200 bg-white overflow-x-auto scrollbar-hide">
|
||||
<div className="flex min-w-max">
|
||||
{[
|
||||
{ id: "details", label: "Detalhes", icon: "1" },
|
||||
{ id: "location", label: "Localização", icon: "2" },
|
||||
{ id: "briefing", label: isClientRequest ? "Desejos" : "Briefing", icon: "3" },
|
||||
{ id: "files", label: "Arquivos", icon: "4" },
|
||||
].map((item) => (
|
||||
<button
|
||||
key={item.id}
|
||||
onClick={() => setActiveTab(item.id as any)}
|
||||
className={`flex-1 px-4 py-3 text-xs sm:text-sm font-medium transition-colors border-b-2 whitespace-nowrap ${activeTab === item.id
|
||||
? "text-brand-gold border-brand-gold bg-brand-gold/5"
|
||||
: "text-gray-500 border-transparent hover:bg-gray-50"
|
||||
}`}
|
||||
>
|
||||
<span className="inline-block w-5 h-5 rounded-full text-[10px] leading-5 text-center mr-1.5 ${
|
||||
activeTab === item.id ? 'bg-brand-gold text-white' : 'bg-gray-200 text-gray-600'
|
||||
}">{item.icon}</span>
|
||||
{item.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-4 min-h-[500px]">
|
||||
{/* Sidebar Navigation for Form */}
|
||||
<div className="col-span-1 border-r border-gray-100 bg-gray-50/50 p-4 space-y-2">
|
||||
<div className="lg:grid lg:grid-cols-4 min-h-[500px]">
|
||||
{/* Desktop Sidebar Navigation */}
|
||||
<div className="hidden lg:block lg:col-span-1 border-r border-gray-100 bg-gray-50/50 p-4 space-y-2">
|
||||
{[
|
||||
{ id: "details", label: "Detalhes & Data" },
|
||||
{ id: "location", label: "Localização" },
|
||||
|
|
@ -322,11 +349,10 @@ export const EventForm: React.FC<EventFormProps> = ({
|
|||
<button
|
||||
key={item.id}
|
||||
onClick={() => setActiveTab(item.id as any)}
|
||||
className={`w-full text-left px-4 py-3 rounded-sm text-sm font-medium transition-colors ${
|
||||
activeTab === item.id
|
||||
? "bg-white shadow-sm text-brand-gold border-l-4 border-brand-gold"
|
||||
: "text-gray-500 hover:bg-gray-100"
|
||||
}`}
|
||||
className={`w-full text-left px-4 py-3 rounded-sm text-sm font-medium transition-colors ${activeTab === item.id
|
||||
? "bg-white shadow-sm text-brand-gold border-l-4 border-brand-gold"
|
||||
: "text-gray-500 hover:bg-gray-100"
|
||||
}`}
|
||||
>
|
||||
{item.label}
|
||||
</button>
|
||||
|
|
@ -334,7 +360,7 @@ export const EventForm: React.FC<EventFormProps> = ({
|
|||
</div>
|
||||
|
||||
{/* Form Content */}
|
||||
<div className="col-span-3 p-8">
|
||||
<div className="lg:col-span-3 p-4 sm:p-6 md:p-8">
|
||||
{activeTab === "details" && (
|
||||
<div className="space-y-6 fade-in">
|
||||
<div className="grid grid-cols-1 gap-6">
|
||||
|
|
@ -355,7 +381,7 @@ export const EventForm: React.FC<EventFormProps> = ({
|
|||
}
|
||||
/>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<Input
|
||||
label="Horário de Início*"
|
||||
type="time"
|
||||
|
|
@ -509,11 +535,11 @@ export const EventForm: React.FC<EventFormProps> = ({
|
|||
<div className="flex items-center justify-between w-full px-2">
|
||||
<span className="text-sm text-gray-500 truncate max-w-[200px]">
|
||||
{formData.coverImage &&
|
||||
!formData.coverImage.startsWith("http")
|
||||
!formData.coverImage.startsWith("http")
|
||||
? "Imagem selecionada"
|
||||
: formData.coverImage
|
||||
? "Imagem atual (URL)"
|
||||
: "Clique para selecionar..."}
|
||||
? "Imagem atual (URL)"
|
||||
: "Clique para selecionar..."}
|
||||
</span>
|
||||
<div className="bg-gray-100 p-1.5 rounded hover:bg-gray-200">
|
||||
<Upload size={16} className="text-gray-600" />
|
||||
|
|
@ -535,8 +561,8 @@ export const EventForm: React.FC<EventFormProps> = ({
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end mt-8">
|
||||
<Button onClick={() => setActiveTab("location")}>
|
||||
<div className="flex flex-col sm:flex-row justify-end gap-3 sm:gap-0 mt-8">
|
||||
<Button onClick={() => setActiveTab("location")} className="w-full sm:w-auto">
|
||||
Próximo: Localização
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -605,8 +631,8 @@ export const EventForm: React.FC<EventFormProps> = ({
|
|||
)}
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<div className="col-span-2">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
|
||||
<div className="sm:col-span-2">
|
||||
<Input
|
||||
label="Rua"
|
||||
value={formData.address.street}
|
||||
|
|
@ -639,7 +665,7 @@ export const EventForm: React.FC<EventFormProps> = ({
|
|||
inputMode="numeric"
|
||||
/>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<Input
|
||||
label="Cidade"
|
||||
value={formData.address.city}
|
||||
|
|
@ -683,7 +709,8 @@ export const EventForm: React.FC<EventFormProps> = ({
|
|||
initialLat={formData.address.lat || -22.7394}
|
||||
initialLng={formData.address.lng || -47.3314}
|
||||
onLocationChange={handleMapLocationChange}
|
||||
height="450px"
|
||||
height="300px"
|
||||
className="sm:h-[400px] md:h-[450px]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
@ -704,14 +731,15 @@ export const EventForm: React.FC<EventFormProps> = ({
|
|||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex justify-between mt-8">
|
||||
<div className="flex flex-col sm:flex-row justify-between gap-3 mt-8">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setActiveTab("details")}
|
||||
className="w-full sm:w-auto"
|
||||
>
|
||||
Voltar
|
||||
</Button>
|
||||
<Button onClick={() => setActiveTab("briefing")}>
|
||||
<Button onClick={() => setActiveTab("briefing")} className="w-full sm:w-auto">
|
||||
Próximo
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -777,9 +805,8 @@ export const EventForm: React.FC<EventFormProps> = ({
|
|||
/>
|
||||
<button
|
||||
onClick={() => removeContact(idx)}
|
||||
className={`mt-1 p-2 text-gray-400 hover:text-red-500 ${
|
||||
idx === 0 ? "mt-7" : ""
|
||||
}`}
|
||||
className={`mt-1 p-2 text-gray-400 hover:text-red-500 ${idx === 0 ? "mt-7" : ""
|
||||
}`}
|
||||
>
|
||||
<X size={16} />
|
||||
</button>
|
||||
|
|
@ -788,14 +815,15 @@ export const EventForm: React.FC<EventFormProps> = ({
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between mt-8">
|
||||
<div className="flex flex-col sm:flex-row justify-between gap-3 mt-8">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setActiveTab("location")}
|
||||
className="w-full sm:w-auto"
|
||||
>
|
||||
Voltar
|
||||
</Button>
|
||||
<Button onClick={() => setActiveTab("files")}>Próximo</Button>
|
||||
<Button onClick={() => setActiveTab("files")} className="w-full sm:w-auto">Próximo</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -845,14 +873,15 @@ export const EventForm: React.FC<EventFormProps> = ({
|
|||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex justify-between mt-8">
|
||||
<div className="flex flex-col sm:flex-row justify-between gap-3 mt-8">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setActiveTab("briefing")}
|
||||
className="w-full sm:w-auto"
|
||||
>
|
||||
Voltar
|
||||
</Button>
|
||||
<Button onClick={handleSubmit} variant="secondary">
|
||||
<Button onClick={handleSubmit} variant="secondary" className="w-full sm:w-auto">
|
||||
{submitLabel}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { UserRole } from "../types";
|
||||
import { useAuth } from "../contexts/AuthContext";
|
||||
import { Menu, X, LogOut, User } from "lucide-react";
|
||||
import { Menu, X, LogOut, User, Settings, Camera, Mail, Phone } from "lucide-react";
|
||||
import { Button } from "./Button";
|
||||
|
||||
interface NavbarProps {
|
||||
|
|
@ -14,6 +14,13 @@ export const Navbar: React.FC<NavbarProps> = ({ onNavigate, currentPage }) => {
|
|||
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 || "",
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = () => {
|
||||
|
|
@ -60,196 +67,441 @@ export const Navbar: React.FC<NavbarProps> = ({ onNavigate, currentPage }) => {
|
|||
};
|
||||
|
||||
return (
|
||||
<nav className="fixed w-full z-50 bg-white shadow-sm py-3">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex justify-between items-center h-16">
|
||||
{/* Logo */}
|
||||
<div
|
||||
className="flex-shrink-0 flex items-center cursor-pointer"
|
||||
onClick={() => onNavigate("home")}
|
||||
>
|
||||
<img
|
||||
src="/logo.png"
|
||||
alt="Photum Formaturas"
|
||||
className="h-30 mb-6 w-auto object-contain"
|
||||
/>
|
||||
</div>
|
||||
<>
|
||||
<nav className="fixed w-full z-50 bg-white shadow-sm py-3">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex justify-between items-center h-16">
|
||||
{/* Logo */}
|
||||
<div
|
||||
className="flex-shrink-0 flex items-center cursor-pointer"
|
||||
onClick={() => onNavigate("home")}
|
||||
>
|
||||
<img
|
||||
src="/logo.png"
|
||||
alt="Photum Formaturas"
|
||||
className="h-16 md:h-28 mb-0 md:mb-6 w-auto object-contain"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Desktop Navigation */}
|
||||
{user && (
|
||||
<div className="hidden md:flex items-center space-x-6">
|
||||
{getLinks().map((link) => (
|
||||
<button
|
||||
key={link.path}
|
||||
onClick={() => onNavigate(link.path)}
|
||||
className={`text-sm font-medium tracking-wide uppercase hover:text-brand-gold transition-colors pb-1 ${
|
||||
currentPage === link.path
|
||||
{/* Desktop Navigation */}
|
||||
{user && (
|
||||
<div className="hidden md:flex items-center space-x-6">
|
||||
{getLinks().map((link) => (
|
||||
<button
|
||||
key={link.path}
|
||||
onClick={() => onNavigate(link.path)}
|
||||
className={`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>
|
||||
)}
|
||||
|
||||
{/* Right Side Actions */}
|
||||
<div className="hidden md:flex items-center space-x-4">
|
||||
{user ? (
|
||||
<div className="flex items-center space-x-4 pl-4 border-l border-gray-200">
|
||||
<div className="flex flex-col items-end mr-2">
|
||||
<span className="text-sm font-bold text-brand-black leading-tight">
|
||||
{user.name}
|
||||
</span>
|
||||
<span className="text-[10px] uppercase tracking-wider text-brand-gold leading-tight">
|
||||
{getRoleLabel()}
|
||||
</span>
|
||||
</div>
|
||||
<div className="h-9 w-9 rounded-full bg-gray-100 overflow-hidden border border-gray-200 ring-2 ring-transparent hover:ring-brand-gold transition-all">
|
||||
<img
|
||||
src={user.avatar}
|
||||
alt="Avatar"
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
onClick={logout}
|
||||
className="text-gray-400 hover:text-red-500 transition-colors p-1"
|
||||
title="Sair"
|
||||
>
|
||||
<LogOut size={18} />
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<div className="relative">
|
||||
<button
|
||||
onClick={() =>
|
||||
setIsAccountDropdownOpen(!isAccountDropdownOpen)
|
||||
}
|
||||
className="flex items-center gap-2 p-2 rounded-full hover:bg-gray-100 transition-colors"
|
||||
>
|
||||
<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-sm font-medium text-brand-black">
|
||||
Entrar / Cadastrar
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
{/* Dropdown Popup - Centralizado */}
|
||||
{isAccountDropdownOpen && (
|
||||
<div className="absolute left-1/2 -translate-x-1/2 top-full mt-2 w-64 bg-white rounded-xl shadow-xl border border-gray-200 overflow-hidden z-50 fade-in">
|
||||
<div className="p-4 space-y-3">
|
||||
<Button
|
||||
onClick={() => {
|
||||
onNavigate("login");
|
||||
setIsAccountDropdownOpen(false);
|
||||
}}
|
||||
variant="secondary"
|
||||
className="w-full rounded-xl"
|
||||
>
|
||||
ENTRAR
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={() => {
|
||||
onNavigate("register");
|
||||
setIsAccountDropdownOpen(false);
|
||||
}}
|
||||
className="w-full bg-purple-600 text-white hover:bg-purple-700 focus:ring-purple-500 rounded-xl"
|
||||
>
|
||||
Cadastre-se agora
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
}`}
|
||||
>
|
||||
{link.name}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Mobile Button */}
|
||||
<div className="md:hidden flex items-center">
|
||||
<button
|
||||
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
|
||||
className="text-brand-black hover:text-brand-gold p-2"
|
||||
>
|
||||
{isMobileMenuOpen ? <X size={24} /> : <Menu size={24} />}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Mobile Menu */}
|
||||
{isMobileMenuOpen && (
|
||||
<div className="md:hidden absolute top-full left-0 w-full bg-white border-b border-gray-100 shadow-lg fade-in">
|
||||
<div className="px-4 py-4 space-y-3">
|
||||
{user &&
|
||||
getLinks().map((link) => (
|
||||
<button
|
||||
key={link.path}
|
||||
onClick={() => {
|
||||
onNavigate(link.path);
|
||||
setIsMobileMenuOpen(false);
|
||||
}}
|
||||
className="block w-full text-left 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">
|
||||
{/* Right Side Actions */}
|
||||
<div className="hidden md:flex items-center space-x-4">
|
||||
{user ? (
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center">
|
||||
<img
|
||||
src={user.avatar}
|
||||
className="w-8 h-8 rounded-full mr-2"
|
||||
/>
|
||||
<div>
|
||||
<span className="font-bold text-sm block">
|
||||
{user.name}
|
||||
</span>
|
||||
<span className="text-xs text-brand-gold">
|
||||
{getRoleLabel()}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex flex-col items-end mr-2">
|
||||
<span className="text-sm font-bold text-brand-black leading-tight">
|
||||
{user.name}
|
||||
</span>
|
||||
<span className="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-9 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={user.avatar}
|
||||
alt="Avatar"
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</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={user.avatar}
|
||||
alt={user.name}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</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("settings");
|
||||
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>
|
||||
<Button variant="ghost" size="sm" onClick={logout}>
|
||||
Sair
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col gap-2">
|
||||
<Button
|
||||
className="w-full rounded-lg"
|
||||
size="lg"
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
onNavigate("login");
|
||||
setIsMobileMenuOpen(false);
|
||||
}}
|
||||
<div className="relative">
|
||||
<button
|
||||
onClick={() =>
|
||||
setIsAccountDropdownOpen(!isAccountDropdownOpen)
|
||||
}
|
||||
className="flex items-center gap-2 p-2 rounded-full hover:bg-gray-100 transition-colors"
|
||||
>
|
||||
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("register");
|
||||
setIsMobileMenuOpen(false);
|
||||
}}
|
||||
>
|
||||
Cadastre-se agora
|
||||
</Button>
|
||||
<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-sm font-medium text-brand-black">
|
||||
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/90 text-sm mb-1">Olá, bem-vindo(a)</p>
|
||||
</div>
|
||||
|
||||
{/* Botões */}
|
||||
<div className="p-5 space-y-3 bg-gray-50">
|
||||
<Button
|
||||
onClick={() => {
|
||||
onNavigate("login");
|
||||
setIsAccountDropdownOpen(false);
|
||||
}}
|
||||
variant="secondary"
|
||||
className="w-full rounded-xl shadow-sm hover:shadow-md transition-shadow"
|
||||
>
|
||||
ENTRAR
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={() => {
|
||||
onNavigate("register");
|
||||
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 Button */}
|
||||
<div className="md:hidden flex items-center">
|
||||
<button
|
||||
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
|
||||
className="text-brand-black hover:text-brand-gold p-2"
|
||||
>
|
||||
{isMobileMenuOpen ? <X size={24} /> : <Menu size={24} />}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</nav>
|
||||
|
||||
{/* Mobile Menu */}
|
||||
{isMobileMenuOpen && (
|
||||
<div className="md:hidden absolute top-full left-0 w-full bg-white border-b border-gray-100 shadow-lg fade-in">
|
||||
<div className="px-4 py-4 space-y-3">
|
||||
{user &&
|
||||
getLinks().map((link) => (
|
||||
<button
|
||||
key={link.path}
|
||||
onClick={() => {
|
||||
onNavigate(link.path);
|
||||
setIsMobileMenuOpen(false);
|
||||
}}
|
||||
className="block w-full text-left 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">
|
||||
{/* 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={user.avatar}
|
||||
className="w-10 h-10 rounded-full mr-3 border-2 border-gray-200"
|
||||
alt={user.name}
|
||||
/>
|
||||
<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={() => {
|
||||
setIsEditProfileModalOpen(true);
|
||||
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("login");
|
||||
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("register");
|
||||
setIsMobileMenuOpen(false);
|
||||
}}
|
||||
>
|
||||
Cadastre-se agora
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</nav>
|
||||
|
||||
{/* Modal de Edição de Perfil - Apenas para Fotógrafos e Clientes */}
|
||||
{
|
||||
isEditProfileModalOpen && (user?.role === UserRole.PHOTOGRAPHER || user?.role === UserRole.EVENT_OWNER) && (
|
||||
<div
|
||||
className="fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-[100] p-4 fade-in"
|
||||
onClick={() => setIsEditProfileModalOpen(false)}
|
||||
>
|
||||
<div
|
||||
className="bg-white rounded-2xl shadow-2xl max-w-2xl w-full max-h-[90vh] overflow-y-auto"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{/* Header */}
|
||||
<div className="bg-gradient-to-r from-[#492E61] to-[#5a3a7a] p-6 sm:p-8 text-center relative">
|
||||
<button
|
||||
onClick={() => setIsEditProfileModalOpen(false)}
|
||||
className="absolute top-4 right-4 text-white/80 hover:text-white transition-colors"
|
||||
>
|
||||
<X size={24} />
|
||||
</button>
|
||||
<div className="w-24 h-24 mx-auto mb-4 rounded-full bg-white/20 backdrop-blur-sm flex items-center justify-center border-4 border-white/30 overflow-hidden relative group">
|
||||
<img
|
||||
src={profileData.avatar}
|
||||
alt="Avatar"
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black/40 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center cursor-pointer">
|
||||
<Camera size={28} className="text-white" />
|
||||
</div>
|
||||
</div>
|
||||
<h2 className="text-2xl font-bold text-white mb-1">Editar Perfil</h2>
|
||||
<p className="text-white/80 text-sm">Atualize suas informações pessoais</p>
|
||||
</div>
|
||||
|
||||
{/* Form */}
|
||||
<form
|
||||
className="p-6 sm:p-8 space-y-6"
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
// Aqui você pode adicionar a lógica para salvar os dados
|
||||
alert("Perfil atualizado com sucesso!");
|
||||
setIsEditProfileModalOpen(false);
|
||||
}}
|
||||
>
|
||||
{/* Nome Completo */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Nome Completo
|
||||
</label>
|
||||
<div className="relative">
|
||||
<User size={20} className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400" />
|
||||
<input
|
||||
type="text"
|
||||
value={profileData.name}
|
||||
onChange={(e) => setProfileData({ ...profileData, name: e.target.value })}
|
||||
className="w-full pl-11 pr-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-[#492E61] focus:border-transparent transition-all"
|
||||
placeholder="Seu nome completo"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Email */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Email
|
||||
</label>
|
||||
<div className="relative">
|
||||
<Mail size={20} className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400" />
|
||||
<input
|
||||
type="email"
|
||||
value={profileData.email}
|
||||
onChange={(e) => setProfileData({ ...profileData, email: e.target.value })}
|
||||
className="w-full pl-11 pr-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-[#492E61] focus:border-transparent transition-all"
|
||||
placeholder="seu@email.com"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Telefone */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
Telefone
|
||||
</label>
|
||||
<div className="relative">
|
||||
<Phone size={20} className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400" />
|
||||
<input
|
||||
type="tel"
|
||||
value={profileData.phone}
|
||||
onChange={(e) => setProfileData({ ...profileData, phone: e.target.value })}
|
||||
className="w-full pl-11 pr-4 py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-[#492E61] focus:border-transparent transition-all"
|
||||
placeholder="(00) 00000-0000"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Botões */}
|
||||
<div className="flex flex-col sm:flex-row gap-3 pt-4 border-t border-gray-200">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setIsEditProfileModalOpen(false)}
|
||||
className="flex-1 px-6 py-3 border border-gray-300 text-gray-700 rounded-xl hover:bg-gray-50 transition-colors font-medium"
|
||||
>
|
||||
Cancelar
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="flex-1 px-6 py-3 bg-[#492E61] text-white rounded-xl hover:bg-[#3a2450] transition-colors font-medium shadow-lg hover:shadow-xl"
|
||||
>
|
||||
Salvar Alterações
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -229,6 +229,16 @@
|
|||
padding: 15px !important;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
|
||||
}
|
||||
|
||||
/* Hide scrollbar for mobile tabs */
|
||||
.scrollbar-hide {
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.scrollbar-hide::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Calendar, Clock, MapPin, User, ChevronLeft, ChevronRight } from 'lucide-react';
|
||||
import { Calendar as CalendarIcon, Clock, MapPin, User, ChevronLeft, ChevronRight, Plus, Filter, Search } from 'lucide-react';
|
||||
|
||||
interface Event {
|
||||
id: string;
|
||||
|
|
@ -78,61 +78,32 @@ const MOCK_EVENTS: Event[] = [
|
|||
export const CalendarPage: React.FC = () => {
|
||||
const [selectedMonth, setSelectedMonth] = useState(new Date());
|
||||
const [selectedEvent, setSelectedEvent] = useState<Event | null>(null);
|
||||
const [selectedDate, setSelectedDate] = useState<Date | null>(null);
|
||||
const [viewMode, setViewMode] = useState<'month' | 'week'>('month');
|
||||
|
||||
const getStatusColor = (status: Event['status']) => {
|
||||
switch (status) {
|
||||
case 'confirmed':
|
||||
return 'bg-green-100 text-green-800';
|
||||
case 'pending':
|
||||
return 'bg-yellow-100 text-yellow-800';
|
||||
case 'completed':
|
||||
return 'bg-gray-100 text-gray-800';
|
||||
case 'confirmed': return 'bg-green-100 text-green-700 border-green-200';
|
||||
case 'pending': return 'bg-yellow-100 text-yellow-700 border-yellow-200';
|
||||
case 'completed': return 'bg-gray-100 text-gray-700 border-gray-200';
|
||||
}
|
||||
};
|
||||
|
||||
const getStatusLabel = (status: Event['status']) => {
|
||||
switch (status) {
|
||||
case 'confirmed':
|
||||
return 'Confirmado';
|
||||
case 'pending':
|
||||
return 'Pendente';
|
||||
case 'completed':
|
||||
return 'Concluído';
|
||||
case 'confirmed': return 'Confirmado';
|
||||
case 'pending': return 'Pendente';
|
||||
case 'completed': return 'Concluído';
|
||||
}
|
||||
};
|
||||
|
||||
const getTypeColor = (type: Event['type']) => {
|
||||
switch (type) {
|
||||
case 'formatura':
|
||||
return 'bg-blue-100 text-blue-800';
|
||||
case 'casamento':
|
||||
return 'bg-pink-100 text-pink-800';
|
||||
case 'evento':
|
||||
return 'bg-purple-100 text-purple-800';
|
||||
case 'formatura': return 'bg-[#492E61] text-white';
|
||||
case 'casamento': return 'bg-pink-500 text-white';
|
||||
case 'evento': return 'bg-blue-500 text-white';
|
||||
}
|
||||
};
|
||||
|
||||
const getTypeLabel = (type: Event['type']) => {
|
||||
switch (type) {
|
||||
case 'formatura':
|
||||
return 'Formatura';
|
||||
case 'casamento':
|
||||
return 'Casamento';
|
||||
case 'evento':
|
||||
return 'Evento';
|
||||
}
|
||||
};
|
||||
|
||||
const formatDate = (dateString: string) => {
|
||||
const date = new Date(dateString + 'T00:00:00');
|
||||
return date.toLocaleDateString('pt-BR', {
|
||||
day: '2-digit',
|
||||
month: 'long',
|
||||
year: 'numeric'
|
||||
});
|
||||
};
|
||||
|
||||
const nextMonth = () => {
|
||||
setSelectedMonth(new Date(selectedMonth.getFullYear(), selectedMonth.getMonth() + 1));
|
||||
};
|
||||
|
|
@ -141,110 +112,129 @@ export const CalendarPage: React.FC = () => {
|
|||
setSelectedMonth(new Date(selectedMonth.getFullYear(), selectedMonth.getMonth() - 1));
|
||||
};
|
||||
|
||||
const currentMonthName = selectedMonth.toLocaleDateString('pt-BR', {
|
||||
month: 'long',
|
||||
year: 'numeric'
|
||||
});
|
||||
|
||||
// Generate calendar days
|
||||
const generateCalendarDays = () => {
|
||||
const year = selectedMonth.getFullYear();
|
||||
const month = selectedMonth.getMonth();
|
||||
|
||||
const firstDay = new Date(year, month, 1);
|
||||
const lastDay = new Date(year, month + 1, 0);
|
||||
|
||||
const firstDayOfWeek = firstDay.getDay();
|
||||
const daysInMonth = lastDay.getDate();
|
||||
|
||||
const startingDayOfWeek = firstDay.getDay();
|
||||
|
||||
const days: (Date | null)[] = [];
|
||||
|
||||
// Add empty cells for days before month starts
|
||||
for (let i = 0; i < firstDayOfWeek; i++) {
|
||||
|
||||
// Add empty cells for days before the first day of the month
|
||||
for (let i = 0; i < startingDayOfWeek; i++) {
|
||||
days.push(null);
|
||||
}
|
||||
|
||||
|
||||
// Add all days of the month
|
||||
for (let day = 1; day <= daysInMonth; day++) {
|
||||
days.push(new Date(year, month, day));
|
||||
}
|
||||
|
||||
|
||||
return days;
|
||||
};
|
||||
|
||||
const getEventsForDate = (date: Date) => {
|
||||
return MOCK_EVENTS.filter(event => {
|
||||
const eventDate = new Date(event.date + 'T00:00:00');
|
||||
return eventDate.getDate() === date.getDate() &&
|
||||
eventDate.getMonth() === date.getMonth() &&
|
||||
eventDate.getFullYear() === date.getFullYear();
|
||||
return eventDate.toDateString() === date.toDateString();
|
||||
});
|
||||
};
|
||||
|
||||
const isToday = (date: Date) => {
|
||||
const today = new Date();
|
||||
return date.getDate() === today.getDate() &&
|
||||
date.getMonth() === today.getMonth() &&
|
||||
date.getFullYear() === today.getFullYear();
|
||||
return date.toDateString() === today.toDateString();
|
||||
};
|
||||
|
||||
const currentMonthName = selectedMonth.toLocaleDateString('pt-BR', { month: 'long', year: 'numeric' });
|
||||
const calendarDays = generateCalendarDays();
|
||||
|
||||
// Filter events for selected month
|
||||
const monthEvents = MOCK_EVENTS.filter(event => {
|
||||
const eventDate = new Date(event.date + 'T00:00:00');
|
||||
return eventDate.getMonth() === selectedMonth.getMonth() &&
|
||||
eventDate.getFullYear() === selectedMonth.getFullYear();
|
||||
});
|
||||
|
||||
// Sort events by date
|
||||
const sortedEvents = [...MOCK_EVENTS].sort((a, b) =>
|
||||
new Date(a.date).getTime() - new Date(b.date).getTime()
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50 pt-20 sm:pt-24 md:pt-32 pb-8 sm:pb-12">
|
||||
<div className="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100 pt-20 sm:pt-24 md:pt-32 pb-8 sm:pb-12">
|
||||
<div className="max-w-7xl mx-auto px-3 sm:px-4 md:px-6 lg:px-8">
|
||||
{/* Header */}
|
||||
<div className="mb-6 sm:mb-8">
|
||||
<h1 className="text-2xl sm:text-3xl font-serif font-bold text-brand-black mb-1 sm:mb-2">
|
||||
Minha Agenda
|
||||
</h1>
|
||||
<p className="text-sm sm:text-base text-gray-600">
|
||||
Gerencie seus eventos e compromissos fotográficos
|
||||
</p>
|
||||
<div className="mb-4 sm:mb-6 md:mb-8 flex flex-col gap-3 sm:gap-4">
|
||||
<div>
|
||||
<h1 className="text-2xl sm:text-3xl md:text-4xl font-bold text-[#492E61] mb-1 sm:mb-2">
|
||||
Minha Agenda
|
||||
</h1>
|
||||
<p className="text-xs sm:text-sm md:text-base text-gray-600">
|
||||
Gerencie seus eventos e compromissos fotográficos
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<button className="flex items-center gap-2 px-3 sm:px-4 py-2 sm:py-2.5 bg-[#492E61] text-white rounded-xl hover:bg-[#3a2450] transition-colors shadow-lg text-sm sm:text-base">
|
||||
<Plus size={18} className="sm:w-5 sm:h-5" />
|
||||
<span className="hidden xs:inline">Novo Evento</span>
|
||||
<span className="xs:hidden">Novo</span>
|
||||
</button>
|
||||
<button className="p-2 sm:p-2.5 border border-gray-300 rounded-xl hover:bg-gray-50 transition-colors">
|
||||
<Filter size={18} className="sm:w-5 sm:h-5 text-gray-600" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4 sm:gap-6">
|
||||
{/* Full Calendar Grid */}
|
||||
<div className="lg:col-span-2">
|
||||
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-3 sm:p-4">
|
||||
<div className="flex items-center justify-between mb-3 sm:mb-4">
|
||||
<button
|
||||
onClick={prevMonth}
|
||||
className="p-1 sm:p-1.5 hover:bg-gray-100 rounded-full transition-colors"
|
||||
>
|
||||
<ChevronLeft className="w-4 h-4 sm:w-5 sm:h-5" />
|
||||
</button>
|
||||
<h2 className="text-base sm:text-lg font-bold capitalize" style={{ color: '#B9CF33' }}>
|
||||
{currentMonthName}
|
||||
</h2>
|
||||
<button
|
||||
onClick={nextMonth}
|
||||
className="p-1 sm:p-1.5 hover:bg-gray-100 rounded-full transition-colors"
|
||||
>
|
||||
<ChevronRight className="w-4 h-4 sm:w-5 sm:h-5" />
|
||||
</button>
|
||||
{/* Calendar Section */}
|
||||
<div className="lg:col-span-2 space-y-4 sm:space-y-6">
|
||||
{/* Calendar Card */}
|
||||
<div className="bg-white rounded-2xl shadow-xl border border-gray-200 overflow-hidden">
|
||||
{/* Calendar Header */}
|
||||
<div className="bg-gradient-to-r from-[#492E61] to-[#5a3a7a] p-4 sm:p-6">
|
||||
<div className="flex items-center justify-between mb-3 sm:mb-4">
|
||||
<button
|
||||
onClick={prevMonth}
|
||||
className="p-1.5 sm:p-2 hover:bg-white/20 rounded-lg transition-colors"
|
||||
>
|
||||
<ChevronLeft className="w-5 h-5 sm:w-6 sm:h-6 text-white" />
|
||||
</button>
|
||||
<h2 className="text-lg sm:text-xl md:text-2xl font-bold text-white capitalize">
|
||||
{currentMonthName}
|
||||
</h2>
|
||||
<button
|
||||
onClick={nextMonth}
|
||||
className="p-1.5 sm:p-2 hover:bg-white/20 rounded-lg transition-colors"
|
||||
>
|
||||
<ChevronRight className="w-5 h-5 sm:w-6 sm:h-6 text-white" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Stats */}
|
||||
<div className="grid grid-cols-3 gap-2 sm:gap-4">
|
||||
<div className="bg-white/10 backdrop-blur-sm rounded-lg p-2 sm:p-3 text-center">
|
||||
<p className="text-white/80 text-[10px] sm:text-xs mb-0.5 sm:mb-1">Total</p>
|
||||
<p className="text-xl sm:text-2xl font-bold text-white">{monthEvents.length}</p>
|
||||
</div>
|
||||
<div className="bg-white/10 backdrop-blur-sm rounded-lg p-2 sm:p-3 text-center">
|
||||
<p className="text-white/80 text-[10px] sm:text-xs mb-0.5 sm:mb-1">Confirmados</p>
|
||||
<p className="text-xl sm:text-2xl font-bold text-green-300">
|
||||
{monthEvents.filter(e => e.status === 'confirmed').length}
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-white/10 backdrop-blur-sm rounded-lg p-2 sm:p-3 text-center">
|
||||
<p className="text-white/80 text-[10px] sm:text-xs mb-0.5 sm:mb-1">Pendentes</p>
|
||||
<p className="text-xl sm:text-2xl font-bold text-yellow-300">
|
||||
{monthEvents.filter(e => e.status === 'pending').length}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Calendar Grid */}
|
||||
<div className="mb-3 sm:mb-4">
|
||||
<div className="p-3 sm:p-4 md:p-6">
|
||||
{/* Week Days Header */}
|
||||
<div className="grid grid-cols-7 gap-0.5 sm:gap-1 mb-1">
|
||||
<div className="grid grid-cols-7 gap-1 sm:gap-2 mb-1 sm:mb-2">
|
||||
{['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'].map((day) => (
|
||||
<div
|
||||
key={day}
|
||||
className="text-center text-[10px] sm:text-xs font-semibold text-gray-600 py-1"
|
||||
className="text-center text-[10px] sm:text-xs md:text-sm font-bold text-gray-600 py-1 sm:py-2"
|
||||
>
|
||||
{day}
|
||||
</div>
|
||||
|
|
@ -252,332 +242,147 @@ export const CalendarPage: React.FC = () => {
|
|||
</div>
|
||||
|
||||
{/* Calendar Days */}
|
||||
<div className="grid grid-cols-7 gap-0.5 sm:gap-1">
|
||||
{calendarDays.map((date, index) => {
|
||||
if (!date) {
|
||||
return (
|
||||
<div
|
||||
key={`empty-${index}`}
|
||||
className="h-10 sm:h-12 bg-gray-50 rounded"
|
||||
/>
|
||||
);
|
||||
<div className="grid grid-cols-7 gap-1 sm:gap-2">
|
||||
{calendarDays.map((day, index) => {
|
||||
if (!day) {
|
||||
return <div key={`empty-${index}`} className="aspect-square" />;
|
||||
}
|
||||
|
||||
const dayEvents = getEventsForDate(date);
|
||||
const hasEvents = dayEvents.length > 0;
|
||||
const today = isToday(date);
|
||||
const dayEvents = getEventsForDate(day);
|
||||
const today = isToday(day);
|
||||
|
||||
return (
|
||||
<button
|
||||
<div
|
||||
key={index}
|
||||
onClick={() => setSelectedDate(date)}
|
||||
className={`
|
||||
h-10 sm:h-12 rounded p-0.5 sm:p-1 transition-all duration-200
|
||||
${today ? 'bg-[#B9CF33] text-white font-bold' : 'hover:bg-gray-100 active:bg-gray-200'}
|
||||
${hasEvents && !today ? 'bg-blue-50 border border-[#B9CF33] sm:border-2' : 'bg-white border border-gray-200'}
|
||||
relative group
|
||||
`}
|
||||
className={`aspect-square rounded-lg sm:rounded-xl border-2 p-1 sm:p-2 transition-all cursor-pointer hover:shadow-lg ${today
|
||||
? 'border-[#492E61] bg-[#492E61]/5'
|
||||
: dayEvents.length > 0
|
||||
? 'border-[#B9CF32] bg-[#B9CF32]/5 hover:bg-[#B9CF32]/10'
|
||||
: 'border-gray-200 hover:border-gray-300 hover:bg-gray-50'
|
||||
}`}
|
||||
>
|
||||
<div className="flex flex-col items-center justify-center h-full">
|
||||
<span className={`text-[10px] sm:text-xs ${today ? 'text-white' : 'text-gray-700'}`}>
|
||||
{date.getDate()}
|
||||
<div className="h-full flex flex-col">
|
||||
<span
|
||||
className={`text-xs sm:text-sm font-semibold mb-0.5 sm:mb-1 ${today
|
||||
? 'text-[#492E61]'
|
||||
: dayEvents.length > 0
|
||||
? 'text-gray-900'
|
||||
: 'text-gray-600'
|
||||
}`}
|
||||
>
|
||||
{day.getDate()}
|
||||
</span>
|
||||
{hasEvents && (
|
||||
<div className="flex gap-0.5 mt-0.5">
|
||||
{dayEvents.slice(0, 3).map((event, i) => (
|
||||
{dayEvents.length > 0 && (
|
||||
<div className="flex-1 flex flex-col gap-0.5 sm:gap-1">
|
||||
{dayEvents.slice(0, 1).map((event) => (
|
||||
<div
|
||||
key={i}
|
||||
className={`w-0.5 h-0.5 sm:w-1 sm:h-1 rounded-full ${
|
||||
event.status === 'confirmed' ? 'bg-green-500' :
|
||||
event.status === 'pending' ? 'bg-yellow-500' :
|
||||
'bg-gray-400'
|
||||
}`}
|
||||
/>
|
||||
key={event.id}
|
||||
className={`text-[6px] sm:text-[8px] px-0.5 sm:px-1 py-0.5 rounded ${getTypeColor(event.type)} truncate leading-tight`}
|
||||
>
|
||||
{event.title}
|
||||
</div>
|
||||
))}
|
||||
{dayEvents.length > 1 && (
|
||||
<span className="text-[6px] sm:text-[8px] text-gray-500 font-medium">
|
||||
+{dayEvents.length - 1}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Tooltip on hover - hide on mobile */}
|
||||
{hasEvents && (
|
||||
<div className="absolute bottom-full left-1/2 transform -translate-x-1/2 mb-2 hidden sm:group-hover:block z-10">
|
||||
<div className="bg-gray-900 text-white text-xs rounded py-1 px-2 whitespace-nowrap">
|
||||
{dayEvents.length} evento{dayEvents.length > 1 ? 's' : ''}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-3 sm:mt-4 pt-3 sm:pt-4 border-t border-gray-200">
|
||||
<div className="grid grid-cols-2 gap-2 text-xs">
|
||||
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between">
|
||||
<span className="text-gray-600 text-[10px] sm:text-xs">Eventos este mês:</span>
|
||||
<span className="font-bold text-sm sm:text-base" style={{ color: '#B9CF33' }}>{monthEvents.length}</span>
|
||||
</div>
|
||||
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between">
|
||||
<span className="text-gray-600 text-[10px] sm:text-xs">Total:</span>
|
||||
<span className="font-semibold text-sm sm:text-base">{MOCK_EVENTS.length}</span>
|
||||
</div>
|
||||
{/* Legend */}
|
||||
<div className="bg-white rounded-2xl shadow-lg border border-gray-200 p-4 sm:p-6">
|
||||
<h3 className="text-base sm:text-lg font-bold text-gray-900 mb-3 sm:mb-4">Legenda</h3>
|
||||
<div className="grid grid-cols-2 sm:grid-cols-3 gap-3 sm:gap-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-3 h-3 sm:w-4 sm:h-4 rounded bg-green-500"></div>
|
||||
<span className="text-xs sm:text-sm text-gray-700">Confirmado</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-3 h-3 sm:w-4 sm:h-4 rounded bg-yellow-500"></div>
|
||||
<span className="text-xs sm:text-sm text-gray-700">Pendente</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-3 h-3 sm:w-4 sm:h-4 rounded bg-gray-400"></div>
|
||||
<span className="text-xs sm:text-sm text-gray-700">Concluído</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-3 h-3 sm:w-4 sm:h-4 rounded bg-[#492E61]"></div>
|
||||
<span className="text-xs sm:text-sm text-gray-700">Formatura</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-3 h-3 sm:w-4 sm:h-4 rounded bg-pink-500"></div>
|
||||
<span className="text-xs sm:text-sm text-gray-700">Casamento</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-3 h-3 sm:w-4 sm:h-4 rounded bg-blue-500"></div>
|
||||
<span className="text-xs sm:text-sm text-gray-700">Evento</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Legend and Info Sidebar */}
|
||||
<div className="lg:col-span-1">
|
||||
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-3 sm:p-4 lg:sticky lg:top-24">
|
||||
<h3 className="text-sm font-bold mb-2 sm:mb-3" style={{ color: '#492E61' }}>Legenda</h3>
|
||||
<div className="grid grid-cols-2 sm:grid-cols-1 gap-2 mb-3 sm:mb-4">
|
||||
<div className="flex items-center gap-2 text-xs">
|
||||
<div className="w-3 h-3 rounded-full bg-green-500 flex-shrink-0"></div>
|
||||
<span>Confirmado</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-xs">
|
||||
<div className="w-3 h-3 rounded-full bg-yellow-500 flex-shrink-0"></div>
|
||||
<span>Pendente</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-xs">
|
||||
<div className="w-3 h-3 rounded-full bg-gray-500 flex-shrink-0"></div>
|
||||
<span>Concluído</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-xs">
|
||||
<div className="w-3 h-3 rounded flex-shrink-0" style={{ backgroundColor: '#B9CF33' }}></div>
|
||||
<span>Hoje</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-xs col-span-2 sm:col-span-1">
|
||||
<div className="w-3 h-3 rounded bg-blue-50 border-2 flex-shrink-0" style={{ borderColor: '#B9CF33' }}></div>
|
||||
<span>Com eventos</span>
|
||||
</div>
|
||||
{/* Events List Sidebar */}
|
||||
<div className="space-y-4 sm:space-y-6">
|
||||
{/* Search */}
|
||||
<div className="bg-white rounded-2xl shadow-lg border border-gray-200 p-3 sm:p-4">
|
||||
<div className="relative">
|
||||
<Search className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400" size={18} />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Buscar eventos..."
|
||||
className="w-full pl-9 sm:pl-10 pr-3 sm:pr-4 py-2 sm:py-3 border border-gray-300 rounded-xl focus:outline-none focus:ring-2 focus:ring-[#492E61] focus:border-transparent text-sm"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{selectedDate && (
|
||||
<div className="pt-3 sm:pt-4 border-t border-gray-200">
|
||||
<h3 className="text-xs font-bold mb-2" style={{ color: '#492E61' }}>
|
||||
{selectedDate.toLocaleDateString('pt-BR', {
|
||||
day: '2-digit',
|
||||
month: 'long',
|
||||
year: 'numeric'
|
||||
})}
|
||||
</h3>
|
||||
{getEventsForDate(selectedDate).length > 0 ? (
|
||||
<div className="space-y-2">
|
||||
{getEventsForDate(selectedDate).map(event => (
|
||||
<div
|
||||
key={event.id}
|
||||
className="p-2 bg-gray-50 rounded cursor-pointer hover:bg-gray-100 active:bg-gray-200 transition-colors"
|
||||
onClick={() => setSelectedEvent(event)}
|
||||
>
|
||||
<div className="font-medium text-xs text-gray-900 mb-1 line-clamp-1">
|
||||
{event.title}
|
||||
</div>
|
||||
<div className="text-xs text-gray-600 flex items-center">
|
||||
<Clock size={10} className="inline mr-1 flex-shrink-0" />
|
||||
{event.time}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
{/* Upcoming Events */}
|
||||
<div className="bg-white rounded-2xl shadow-lg border border-gray-200 p-4 sm:p-6">
|
||||
<h3 className="text-base sm:text-lg font-bold text-gray-900 mb-3 sm:mb-4 flex items-center gap-2">
|
||||
<CalendarIcon size={18} className="sm:w-5 sm:h-5 text-[#492E61]" />
|
||||
Próximos Eventos
|
||||
</h3>
|
||||
<div className="space-y-2 sm:space-y-3 max-h-[400px] sm:max-h-[600px] overflow-y-auto">
|
||||
{MOCK_EVENTS.slice(0, 5).map((event) => (
|
||||
<div
|
||||
key={event.id}
|
||||
className="p-3 sm:p-4 border-l-4 rounded-lg bg-gray-50 hover:bg-gray-100 transition-colors cursor-pointer"
|
||||
style={{ borderLeftColor: event.type === 'formatura' ? '#492E61' : event.type === 'casamento' ? '#ec4899' : '#3b82f6' }}
|
||||
>
|
||||
<div className="flex items-start justify-between mb-2 gap-2">
|
||||
<h4 className="font-semibold text-gray-900 text-xs sm:text-sm flex-1">{event.title}</h4>
|
||||
<span className={`text-[10px] sm:text-xs px-1.5 sm:px-2 py-0.5 sm:py-1 rounded-full border whitespace-nowrap ${getStatusColor(event.status)}`}>
|
||||
{getStatusLabel(event.status)}
|
||||
</span>
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-xs text-gray-500">Nenhum evento neste dia</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Events List */}
|
||||
<div className="lg:col-span-3 mt-4 sm:mt-6">
|
||||
<div className="bg-white rounded-lg shadow-sm border border-gray-200">
|
||||
<div className="p-4 sm:p-6 border-b border-gray-200">
|
||||
<h2 className="text-lg sm:text-xl font-bold" style={{ color: '#492E61' }}>Próximos Eventos</h2>
|
||||
</div>
|
||||
|
||||
<div className="divide-y divide-gray-200">
|
||||
{sortedEvents.length === 0 ? (
|
||||
<div className="p-8 sm:p-12 text-center text-gray-500">
|
||||
<Calendar className="w-10 h-10 sm:w-12 sm:h-12 mx-auto mb-3 sm:mb-4 text-gray-300" />
|
||||
<p className="text-sm sm:text-base">Nenhum evento agendado</p>
|
||||
</div>
|
||||
) : (
|
||||
sortedEvents.map((event) => (
|
||||
<div
|
||||
key={event.id}
|
||||
className="p-4 sm:p-6 hover:bg-gray-50 active:bg-gray-100 transition-colors cursor-pointer"
|
||||
onClick={() => setSelectedEvent(event)}
|
||||
>
|
||||
<div className="flex items-start justify-between mb-2 sm:mb-3 gap-3 sm:gap-4">
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-start sm:items-center gap-2 mb-2 flex-col sm:flex-row">
|
||||
<h3 className="text-base sm:text-lg font-semibold text-brand-black line-clamp-2">
|
||||
{event.title}
|
||||
</h3>
|
||||
<span className={`px-2 py-1 rounded-full text-xs font-medium ${getTypeColor(event.type)} whitespace-nowrap`}>
|
||||
{getTypeLabel(event.type)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-1.5 sm:gap-2">
|
||||
<div className="flex items-center text-xs sm:text-sm text-gray-600">
|
||||
<Calendar className="w-3 h-3 sm:w-4 sm:h-4 mr-1.5 sm:mr-2 flex-shrink-0" style={{ color: '#B9CF33' }} />
|
||||
<span className="truncate">{formatDate(event.date)}</span>
|
||||
</div>
|
||||
<div className="flex items-center text-xs sm:text-sm text-gray-600">
|
||||
<Clock className="w-3 h-3 sm:w-4 sm:h-4 mr-1.5 sm:mr-2 flex-shrink-0" style={{ color: '#B9CF33' }} />
|
||||
<span>{event.time}</span>
|
||||
</div>
|
||||
<div className="flex items-center text-xs sm:text-sm text-gray-600">
|
||||
<MapPin className="w-3 h-3 sm:w-4 sm:h-4 mr-1.5 sm:mr-2 flex-shrink-0" style={{ color: '#B9CF33' }} />
|
||||
<span className="truncate">{event.location}</span>
|
||||
</div>
|
||||
<div className="flex items-center text-xs sm:text-sm text-gray-600">
|
||||
<User className="w-3 h-3 sm:w-4 sm:h-4 mr-1.5 sm:mr-2 flex-shrink-0" style={{ color: '#B9CF33' }} />
|
||||
<span className="truncate">{event.client}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span className={`px-2 sm:px-3 py-1 rounded-full text-[10px] sm:text-xs font-medium whitespace-nowrap ${getStatusColor(event.status)} flex-shrink-0`}>
|
||||
{getStatusLabel(event.status)}
|
||||
</span>
|
||||
<div className="space-y-1">
|
||||
<div className="flex items-center gap-1.5 sm:gap-2 text-[10px] sm:text-xs text-gray-600">
|
||||
<Clock size={12} className="sm:w-3.5 sm:h-3.5 flex-shrink-0" />
|
||||
<span>{new Date(event.date).toLocaleDateString('pt-BR')} às {event.time}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5 sm:gap-2 text-[10px] sm:text-xs text-gray-600">
|
||||
<MapPin size={12} className="sm:w-3.5 sm:h-3.5 flex-shrink-0" />
|
||||
<span className="truncate">{event.location}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5 sm:gap-2 text-[10px] sm:text-xs text-gray-600">
|
||||
<User size={12} className="sm:w-3.5 sm:h-3.5 flex-shrink-0" />
|
||||
<span>{event.client}</span>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Event Detail Modal - Improved & Centered */}
|
||||
{selectedEvent && (
|
||||
<div
|
||||
className="fixed inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center z-50 p-4 animate-fadeIn"
|
||||
onClick={() => setSelectedEvent(null)}
|
||||
>
|
||||
<div
|
||||
className="bg-white rounded-2xl max-w-lg w-full shadow-2xl transform transition-all duration-300 animate-slideUp overflow-hidden"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{/* Header with gradient */}
|
||||
<div className="relative p-6 pb-8 bg-gradient-to-br from-[#B9CF33] to-[#a5bd2e]">
|
||||
<button
|
||||
onClick={() => setSelectedEvent(null)}
|
||||
className="absolute top-4 right-4 w-8 h-8 flex items-center justify-center rounded-full bg-white/20 hover:bg-white/30 text-white transition-colors"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
|
||||
<div className="text-white">
|
||||
<h2 className="text-xl sm:text-2xl font-bold mb-3 pr-8">
|
||||
{selectedEvent.title}
|
||||
</h2>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<span className="px-3 py-1 rounded-full text-xs font-medium bg-white/90 text-gray-800">
|
||||
{getTypeLabel(selectedEvent.type)}
|
||||
</span>
|
||||
<span className={`px-3 py-1 rounded-full text-xs font-medium ${getStatusColor(selectedEvent.status)}`}>
|
||||
{getStatusLabel(selectedEvent.status)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="p-6 space-y-4">
|
||||
{/* Date */}
|
||||
<div className="flex items-center gap-4 p-4 bg-gray-50 rounded-xl hover:bg-gray-100 transition-colors group">
|
||||
<div className="w-12 h-12 rounded-xl bg-[#B9CF33]/10 flex items-center justify-center group-hover:scale-110 transition-transform">
|
||||
<Calendar className="w-6 h-6" style={{ color: '#B9CF33' }} />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<p className="text-xs text-gray-500 mb-0.5">Data</p>
|
||||
<p className="font-semibold text-gray-900">{formatDate(selectedEvent.date)}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Time */}
|
||||
<div className="flex items-center gap-4 p-4 bg-gray-50 rounded-xl hover:bg-gray-100 transition-colors group">
|
||||
<div className="w-12 h-12 rounded-xl bg-[#B9CF33]/10 flex items-center justify-center group-hover:scale-110 transition-transform">
|
||||
<Clock className="w-6 h-6" style={{ color: '#B9CF33' }} />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<p className="text-xs text-gray-500 mb-0.5">Horário</p>
|
||||
<p className="font-semibold text-gray-900">{selectedEvent.time}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Location */}
|
||||
<div className="flex items-center gap-4 p-4 bg-gray-50 rounded-xl hover:bg-gray-100 transition-colors group">
|
||||
<div className="w-12 h-12 rounded-xl bg-[#B9CF33]/10 flex items-center justify-center group-hover:scale-110 transition-transform">
|
||||
<MapPin className="w-6 h-6" style={{ color: '#B9CF33' }} />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<p className="text-xs text-gray-500 mb-0.5">Local</p>
|
||||
<p className="font-semibold text-gray-900">{selectedEvent.location}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Client */}
|
||||
<div className="flex items-center gap-4 p-4 bg-gray-50 rounded-xl hover:bg-gray-100 transition-colors group">
|
||||
<div className="w-12 h-12 rounded-xl bg-[#B9CF33]/10 flex items-center justify-center group-hover:scale-110 transition-transform">
|
||||
<User className="w-6 h-6" style={{ color: '#B9CF33' }} />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<p className="text-xs text-gray-500 mb-0.5">Cliente</p>
|
||||
<p className="font-semibold text-gray-900">{selectedEvent.client}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Actions */}
|
||||
<div className="p-6 pt-4 bg-gray-50 flex flex-col sm:flex-row gap-3">
|
||||
<button
|
||||
onClick={() => setSelectedEvent(null)}
|
||||
className="flex-1 px-6 py-3 bg-white border-2 border-gray-200 text-gray-700 rounded-xl hover:bg-gray-50 hover:border-gray-300 active:scale-95 transition-all font-medium"
|
||||
>
|
||||
Fechar
|
||||
</button>
|
||||
<button
|
||||
className="flex-1 px-6 py-3 text-white rounded-xl transition-all font-medium shadow-lg hover:shadow-xl active:scale-95"
|
||||
style={{ backgroundColor: '#B9CF33' }}
|
||||
onMouseEnter={(e) => e.currentTarget.style.backgroundColor = '#a5bd2e'}
|
||||
onMouseLeave={(e) => e.currentTarget.style.backgroundColor = '#B9CF33'}
|
||||
>
|
||||
Ver Detalhes
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<style>{`
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes slideUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px) scale(0.95);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.animate-fadeIn {
|
||||
animation: fadeIn 0.2s ease-out;
|
||||
}
|
||||
|
||||
.animate-slideUp {
|
||||
animation: slideUp 0.3s ease-out;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -236,33 +236,31 @@ export const Dashboard: React.FC<DashboardProps> = ({
|
|||
|
||||
{(user.role === UserRole.BUSINESS_OWNER ||
|
||||
user.role === UserRole.SUPERADMIN) && (
|
||||
<div className="flex space-x-2 bg-white p-1 rounded border border-gray-200">
|
||||
<button
|
||||
onClick={() => setActiveFilter("all")}
|
||||
className={`px-3 py-1 text-xs font-medium rounded-sm ${
|
||||
activeFilter === "all"
|
||||
<div className="flex space-x-2 bg-white p-1 rounded border border-gray-200">
|
||||
<button
|
||||
onClick={() => setActiveFilter("all")}
|
||||
className={`px-3 py-1 text-xs font-medium rounded-sm ${activeFilter === "all"
|
||||
? "bg-brand-black text-white"
|
||||
: "text-gray-600 hover:bg-gray-100"
|
||||
}`}
|
||||
>
|
||||
Todos
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveFilter("pending")}
|
||||
className={`px-3 py-1 text-xs font-medium rounded-sm flex items-center ${
|
||||
activeFilter === "pending"
|
||||
}`}
|
||||
>
|
||||
Todos
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveFilter("pending")}
|
||||
className={`px-3 py-1 text-xs font-medium rounded-sm flex items-center ${activeFilter === "pending"
|
||||
? "bg-brand-gold text-white"
|
||||
: "text-gray-600 hover:bg-gray-100"
|
||||
}`}
|
||||
>
|
||||
<Clock size={12} className="mr-1" /> Pendentes
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
}`}
|
||||
>
|
||||
<Clock size={12} className="mr-1" /> Pendentes
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Grid */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-2 xl:grid-cols-3 gap-4 sm:gap-6 md:gap-8">
|
||||
{filteredEvents.map((event) => (
|
||||
<div key={event.id} className="relative group">
|
||||
{renderAdminActions(event)}
|
||||
|
|
@ -334,31 +332,33 @@ export const Dashboard: React.FC<DashboardProps> = ({
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className="p-8">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||
<div className="col-span-2 space-y-8">
|
||||
<div className="p-4 sm:p-6 md:p-8">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6 md:gap-8">
|
||||
<div className="lg:col-span-2 space-y-6 md:space-y-8">
|
||||
{/* Actions Toolbar */}
|
||||
<div className="flex flex-wrap gap-3 border-b pb-4">
|
||||
<div className="flex flex-wrap gap-2 sm:gap-3 border-b pb-4">
|
||||
{(user.role === UserRole.BUSINESS_OWNER ||
|
||||
user.role === UserRole.SUPERADMIN) && (
|
||||
<>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setView("edit")}
|
||||
>
|
||||
<Edit size={16} className="mr-2" /> Editar Detalhes
|
||||
</Button>
|
||||
<Button variant="outline" onClick={handleManageTeam}>
|
||||
<Users size={16} className="mr-2" /> Gerenciar
|
||||
Equipe
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
<>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setView("edit")}
|
||||
className="text-sm"
|
||||
>
|
||||
<Edit size={16} className="mr-2" /> Editar Detalhes
|
||||
</Button>
|
||||
<Button variant="outline" onClick={handleManageTeam} className="text-sm">
|
||||
<Users size={16} className="mr-2" /> Gerenciar
|
||||
Equipe
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
{user.role === UserRole.EVENT_OWNER &&
|
||||
selectedEvent.status !== EventStatus.ARCHIVED && (
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setView("edit")}
|
||||
className="text-sm"
|
||||
>
|
||||
<Edit size={16} className="mr-2" /> Editar
|
||||
Informações
|
||||
|
|
@ -467,11 +467,10 @@ export const Dashboard: React.FC<DashboardProps> = ({
|
|||
)}
|
||||
</div>
|
||||
|
||||
<div className="col-span-1 space-y-6">
|
||||
<div className="lg:col-span-1 space-y-4 sm:space-y-6">
|
||||
<div
|
||||
className={`p-6 rounded-sm border ${
|
||||
STATUS_COLORS[selectedEvent.status]
|
||||
} bg-opacity-10`}
|
||||
className={`p-6 rounded-sm border ${STATUS_COLORS[selectedEvent.status]
|
||||
} bg-opacity-10`}
|
||||
>
|
||||
<h4 className="font-bold uppercase tracking-widest text-xs mb-2 opacity-70">
|
||||
Status Atual
|
||||
|
|
@ -518,43 +517,43 @@ export const Dashboard: React.FC<DashboardProps> = ({
|
|||
|
||||
{(selectedEvent.photographerIds.length > 0 ||
|
||||
user.role === UserRole.BUSINESS_OWNER) && (
|
||||
<div className="border p-6 rounded-sm">
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<h4 className="font-bold uppercase tracking-widest text-xs text-gray-400">
|
||||
Equipe Designada
|
||||
</h4>
|
||||
{(user.role === UserRole.BUSINESS_OWNER ||
|
||||
user.role === UserRole.SUPERADMIN) && (
|
||||
<button
|
||||
onClick={handleManageTeam}
|
||||
className="text-brand-gold hover:text-brand-black"
|
||||
>
|
||||
<PlusCircle size={16} />
|
||||
</button>
|
||||
<div className="border p-6 rounded-sm">
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<h4 className="font-bold uppercase tracking-widest text-xs text-gray-400">
|
||||
Equipe Designada
|
||||
</h4>
|
||||
{(user.role === UserRole.BUSINESS_OWNER ||
|
||||
user.role === UserRole.SUPERADMIN) && (
|
||||
<button
|
||||
onClick={handleManageTeam}
|
||||
className="text-brand-gold hover:text-brand-black"
|
||||
>
|
||||
<PlusCircle size={16} />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{selectedEvent.photographerIds.length > 0 ? (
|
||||
<div className="flex -space-x-2">
|
||||
{selectedEvent.photographerIds.map((id, idx) => (
|
||||
<div
|
||||
key={id}
|
||||
className="w-10 h-10 rounded-full border-2 border-white bg-gray-300"
|
||||
style={{
|
||||
backgroundImage: `url(https://i.pravatar.cc/100?u=${id})`,
|
||||
backgroundSize: "cover",
|
||||
}}
|
||||
title={id}
|
||||
></div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-sm text-gray-400 italic">
|
||||
Nenhum profissional atribuído.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{selectedEvent.photographerIds.length > 0 ? (
|
||||
<div className="flex -space-x-2">
|
||||
{selectedEvent.photographerIds.map((id, idx) => (
|
||||
<div
|
||||
key={id}
|
||||
className="w-10 h-10 rounded-full border-2 border-white bg-gray-300"
|
||||
style={{
|
||||
backgroundImage: `url(https://i.pravatar.cc/100?u=${id})`,
|
||||
backgroundSize: "cover",
|
||||
}}
|
||||
title={id}
|
||||
></div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-sm text-gray-400 italic">
|
||||
Nenhum profissional atribuído.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -172,26 +172,26 @@ export const FinancePage: React.FC = () => {
|
|||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50 pt-32 pb-12">
|
||||
<div className="min-h-screen bg-gray-50 pt-20 sm:pt-24 md:pt-28 lg:pt-32 pb-8 sm:pb-12">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
{/* Header */}
|
||||
<div className="mb-8 flex items-center justify-between">
|
||||
<div className="mb-6 sm:mb-8 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
||||
<div>
|
||||
<h1 className="text-3xl font-serif font-bold text-brand-black mb-2">
|
||||
<h1 className="text-2xl sm:text-3xl font-serif font-bold text-brand-black mb-2">
|
||||
Financeiro
|
||||
</h1>
|
||||
<p className="text-gray-600">
|
||||
<p className="text-sm sm:text-base text-gray-600">
|
||||
Acompanhe receitas, despesas e fluxo de caixa
|
||||
</p>
|
||||
</div>
|
||||
<button className="flex items-center gap-2 px-4 py-2 bg-brand-gold text-white rounded-md hover:bg-[#a5bd2e] transition-colors font-medium">
|
||||
<Download size={20} />
|
||||
Exportar Relatório
|
||||
<button className="flex items-center justify-center gap-2 px-4 py-2 bg-brand-gold text-white rounded-md hover:bg-[#a5bd2e] transition-colors font-medium text-sm sm:text-base whitespace-nowrap">
|
||||
<Download size={18} className="sm:w-5 sm:h-5" />
|
||||
Exportar
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Stats Cards */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4 md:gap-6 mb-6 sm:mb-8">
|
||||
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<p className="text-sm text-gray-600">Receitas</p>
|
||||
|
|
@ -232,14 +232,14 @@ export const FinancePage: React.FC = () => {
|
|||
</div>
|
||||
|
||||
{/* Filters */}
|
||||
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6 mb-6">
|
||||
<div className="flex flex-col md:flex-row gap-4">
|
||||
<div className="flex gap-2">
|
||||
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-3 sm:p-4 md:p-6 mb-4 sm:mb-6">
|
||||
<div className="flex flex-col gap-3 sm:gap-4">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<button
|
||||
onClick={() => setFilterType('all')}
|
||||
className={`px-4 py-2 rounded-md font-medium transition-colors ${filterType === 'all'
|
||||
? 'bg-brand-gold text-white'
|
||||
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
|
||||
? 'bg-brand-gold text-white'
|
||||
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
|
||||
}`}
|
||||
>
|
||||
Todas
|
||||
|
|
@ -247,8 +247,8 @@ export const FinancePage: React.FC = () => {
|
|||
<button
|
||||
onClick={() => setFilterType('income')}
|
||||
className={`px-4 py-2 rounded-md font-medium transition-colors ${filterType === 'income'
|
||||
? 'bg-green-600 text-white'
|
||||
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
|
||||
? 'bg-green-600 text-white'
|
||||
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
|
||||
}`}
|
||||
>
|
||||
Receitas
|
||||
|
|
@ -256,19 +256,19 @@ export const FinancePage: React.FC = () => {
|
|||
<button
|
||||
onClick={() => setFilterType('expense')}
|
||||
className={`px-4 py-2 rounded-md font-medium transition-colors ${filterType === 'expense'
|
||||
? 'bg-red-600 text-white'
|
||||
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
|
||||
? 'bg-red-600 text-white'
|
||||
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
|
||||
}`}
|
||||
>
|
||||
Despesas
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<button
|
||||
onClick={() => setFilterStatus('all')}
|
||||
className={`px-4 py-2 rounded-md font-medium transition-colors ${filterStatus === 'all'
|
||||
? 'bg-brand-black text-white'
|
||||
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
|
||||
? 'bg-brand-black text-white'
|
||||
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
|
||||
}`}
|
||||
>
|
||||
Todos Status
|
||||
|
|
@ -276,8 +276,8 @@ export const FinancePage: React.FC = () => {
|
|||
<button
|
||||
onClick={() => setFilterStatus('paid')}
|
||||
className={`px-4 py-2 rounded-md font-medium transition-colors ${filterStatus === 'paid'
|
||||
? 'bg-green-600 text-white'
|
||||
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
|
||||
? 'bg-green-600 text-white'
|
||||
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
|
||||
}`}
|
||||
>
|
||||
Pagos
|
||||
|
|
@ -285,8 +285,8 @@ export const FinancePage: React.FC = () => {
|
|||
<button
|
||||
onClick={() => setFilterStatus('pending')}
|
||||
className={`px-4 py-2 rounded-md font-medium transition-colors ${filterStatus === 'pending'
|
||||
? 'bg-yellow-600 text-white'
|
||||
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
|
||||
? 'bg-yellow-600 text-white'
|
||||
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
|
||||
}`}
|
||||
>
|
||||
Pendentes
|
||||
|
|
|
|||
|
|
@ -98,11 +98,11 @@ export const Home: React.FC<HomeProps> = ({ onEnter }) => {
|
|||
<div className={`inline-flex items-center justify-center w-24 h-24 sm:w-32 sm:h-32 md:w-36 md:h-36 mb-6 sm:mb-8 transform transition-all duration-700 ease-out ${albumsVisible ? 'opacity-100 scale-100 rotate-0' : 'opacity-0 scale-75 -rotate-12'} hover:scale-110 hover:rotate-3`}>
|
||||
<img src="/HOME_17.png" alt="Álbuns" className="w-full h-full object-contain drop-shadow-2xl" />
|
||||
</div>
|
||||
|
||||
<h2 className={`text-3xl sm:text-4xl md:text-5xl lg:text-6xl font-bold mb-4 sm:mb-6 md:mb-8 leading-tight transition-all duration-700 ease-out delay-100 ${albumsVisible ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-10'}`} style={{color: '#B9CF33'}}>
|
||||
ÁLBUNS<br/>PERSONALIZADOS
|
||||
|
||||
<h2 className={`text-3xl sm:text-4xl md:text-5xl lg:text-6xl font-bold mb-4 sm:mb-6 md:mb-8 leading-tight transition-all duration-700 ease-out delay-100 ${albumsVisible ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-10'}`} style={{ color: '#B9CF33' }}>
|
||||
ÁLBUNS<br />PERSONALIZADOS
|
||||
</h2>
|
||||
|
||||
|
||||
<div className={`space-y-2 sm:space-y-3 text-gray-700 transition-all duration-700 ease-out delay-200 ${albumsVisible ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-10'}`}>
|
||||
<p className="text-sm sm:text-base md:text-lg leading-relaxed">
|
||||
Escolha a cor, tamanho, tecido, acabamento, modelo,
|
||||
|
|
@ -117,7 +117,7 @@ export const Home: React.FC<HomeProps> = ({ onEnter }) => {
|
|||
</div>
|
||||
|
||||
{/* Right side - CTA */}
|
||||
<div ref={ctaRef} className={`w-full lg:w-2/8 flex flex-col items-center lg:items-start justify-center lg:ml-40 mt-8 lg:mt-0 transition-all duration-700 ease-out delay-300 ${ctaVisible ? 'opacity-100 translate-x-0 scale-100' : 'opacity-0 translate-x-20 scale-90'}`}>
|
||||
<div ref={ctaRef} className={`w-full lg:w-1/2 flex flex-col items-center justify-center mt-8 lg:mt-0 transition-all duration-700 ease-out delay-300 ${ctaVisible ? 'opacity-100 translate-x-0 scale-100' : 'opacity-0 translate-x-20 scale-90'}`}>
|
||||
<div className="bg-white rounded-lg shadow-2xl p-6 sm:p-8 md:p-10 border-t-4 transform transition-all duration-300 hover:shadow-xl hover:-translate-y-2 w-full max-w-sm" style={{ borderColor: '#B9CF33' }}>
|
||||
<div className={`flex justify-center mb-4 sm:mb-6 transition-all duration-700 ease-out delay-400 ${ctaVisible ? 'opacity-100 scale-100' : 'opacity-0 scale-80'}`}>
|
||||
<div className="w-38 h-38 sm:w-38 sm:h-38 md:w-50 md:h-50 transform transition-transform duration-300 hover:scale-110">
|
||||
|
|
@ -138,7 +138,7 @@ export const Home: React.FC<HomeProps> = ({ onEnter }) => {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{/* Decorative elements */}
|
||||
<div className="hidden sm:block absolute top-10 right-10 w-32 h-32 rounded-full opacity-10" style={{ backgroundColor: '#B9CF33' }}></div>
|
||||
<div className="hidden sm:block absolute bottom-10 left-10 w-24 h-24 rounded-full opacity-10" style={{ backgroundColor: '#C2388B' }}></div>
|
||||
|
|
@ -149,30 +149,30 @@ export const Home: React.FC<HomeProps> = ({ onEnter }) => {
|
|||
{/* Decorative gradient circles */}
|
||||
<div className="hidden md:block absolute -top-24 -right-24 w-96 h-96 rounded-full opacity-10 blur-3xl" style={{ backgroundColor: '#B9CF33' }}></div>
|
||||
<div className="hidden md:block absolute -bottom-24 -left-24 w-96 h-96 rounded-full opacity-10 blur-3xl" style={{ backgroundColor: '#C2388B' }}></div>
|
||||
|
||||
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 md:px-8 lg:px-12 xl:px-20 relative z-10">
|
||||
<div className={`text-center mb-8 sm:mb-10 md:mb-12 transition-all duration-700 ${contactVisible ? 'opacity-100 translate-y-0' : 'opacity-0 -translate-y-10'}`}>
|
||||
<h2 className="text-2xl sm:text-3xl md:text-4xl font-bold text-[#B9CF32] mb-2 sm:mb-3 tracking-wide">ENTRE EM CONTATO</h2>
|
||||
<p className="text-sm sm:text-base text-white/90">Envie sua mensagem, ligue ou faça uma visita em nossa empresa!</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4 sm:gap-6 items-start max-w-7xl mx-auto">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4 sm:gap-6 items-end max-w-7xl mx-auto">
|
||||
{/* Left side - Location Info */}
|
||||
<div className={`space-y-2.5 sm:space-y-3 text-white transition-all duration-700 delay-200 ${contactVisible ? 'opacity-100 translate-x-0' : 'opacity-0 -translate-x-20'}`}>
|
||||
<div className="group">
|
||||
<div className="flex items-start gap-2 p-2 sm:p-2.5 rounded-lg transition-all duration-300 hover:bg-white/10 hover:shadow-lg cursor-pointer border border-white/5 hover:border-white/20">
|
||||
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-white/20 flex items-center justify-center transition-transform duration-300 group-hover:scale-110">
|
||||
<svg className="w-5 h-5 text-white" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/>
|
||||
<path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<p className="font-bold mb-0.5 text-sm">Rua Bom Recreio, 305</p>
|
||||
<p className="text-white/80 text-xs">Jd. Boer II • Americana SP</p>
|
||||
<p className="text-white/80 text-xs mb-1">CEP 13477-720</p>
|
||||
<a
|
||||
href="https://www.google.com/maps/place/Photum+Formaturas/@-22.7442887,-47.290221,21z/data=!4m12!1m5!3m4!2zMjLCsDQ0JzM5LjMiUyA0N8KwMTcnMjQuOCJX!8m2!3d-22.744247!4d-47.290221!3m5!1s0x94c89755cd9e70a9:0x15496eb4ec405483!8m2!3d-22.7442757!4d-47.2902662!16s%2Fg%2F11g6my_mm1?hl=pt&entry=ttu&g_ep=EgoyMDI1MTEyMy4xIKXMDSoASAFQAw%3D%3D"
|
||||
target="_blank"
|
||||
<a
|
||||
href="https://www.google.com/maps/place/Photum+Formaturas/@-22.7442887,-47.290221,21z/data=!4m12!1m5!3m4!2zMjLCsDQ0JzM5LjMiUyA0N8KwMTcnMjQuOCJX!8m2!3d-22.744247!4d-47.290221!3m5!1s0x94c89755cd9e70a9:0x15496eb4ec405483!8m2!3d-22.7442757!4d-47.2902662!16s%2Fg%2F11g6my_mm1?hl=pt&entry=ttu&g_ep=EgoyMDI1MTEyMy4xIKXMDSoASAFQAw%3D%3D"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-xs underline hover:text-white transition-colors inline-flex items-center gap-1 font-medium"
|
||||
>
|
||||
|
|
@ -184,7 +184,7 @@ export const Home: React.FC<HomeProps> = ({ onEnter }) => {
|
|||
|
||||
{/* Mini Map */}
|
||||
<div className="rounded-lg overflow-hidden shadow-lg border border-white/10 h-32 sm:h-36">
|
||||
<iframe
|
||||
<iframe
|
||||
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d235.28736842715582!2d-47.29022099999999!3d-22.7442887!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x94c89755cd9e70a9%3A0x15496eb4ec405483!2sPhotum%20Formaturas!5e0!3m2!1spt-BR!2sbr!4v1701234567890!5m2!1spt-BR!2sbr"
|
||||
width="100%"
|
||||
height="100%"
|
||||
|
|
@ -199,7 +199,7 @@ export const Home: React.FC<HomeProps> = ({ onEnter }) => {
|
|||
<div className="flex items-center gap-2 p-2 sm:p-2.5 rounded-lg transition-all duration-300 hover:bg-white/10 hover:shadow-lg cursor-pointer border border-white/5 hover:border-white/20">
|
||||
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-white/20 flex items-center justify-center transition-transform duration-300 group-hover:scale-110">
|
||||
<svg className="w-5 h-5 text-white" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M20 15.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.59l2.2-2.21c.28-.26.36-.65.25-1C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1zM19 12h2c0-4.97-4.03-9-9-9v2c3.87 0 7 3.13 7 7zm-4 0h2c0-2.76-2.24-5-5-5v2c1.66 0 3 1.34 3 3z"/>
|
||||
<path d="M20 15.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.59l2.2-2.21c.28-.26.36-.65.25-1C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1zM19 12h2c0-4.97-4.03-9-9-9v2c3.87 0 7 3.13 7 7zm-4 0h2c0-2.76-2.24-5-5-5v2c1.66 0 3 1.34 3 3z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
|
|
@ -213,7 +213,7 @@ export const Home: React.FC<HomeProps> = ({ onEnter }) => {
|
|||
<div className="flex items-center gap-2 p-2 sm:p-2.5 rounded-lg transition-all duration-300 hover:bg-white/10 hover:shadow-lg cursor-pointer border border-white/5 hover:border-white/20">
|
||||
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-white/20 flex items-center justify-center transition-transform duration-300 group-hover:scale-110">
|
||||
<svg className="w-5 h-5 text-white" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/>
|
||||
<path d="M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
|
|
@ -226,7 +226,7 @@ export const Home: React.FC<HomeProps> = ({ onEnter }) => {
|
|||
</div>
|
||||
|
||||
{/* Center - Contact Form */}
|
||||
<div className={`space-y-2.5 bg-gradient-to-br from-white/10 to-white/5 p-4 sm:p-5 rounded-xl backdrop-blur-md border border-white/10 shadow-2xl transition-all duration-700 delay-250 ${contactVisible ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-10'}`}>
|
||||
<div className={`space-y-2.5 bg-gradient-to-br from-white/10 to-white/5 p-6 sm:p-8 rounded-2xl backdrop-blur-md border border-white/10 shadow-2xl transition-all duration-700 delay-250 ${contactVisible ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-10'}`}>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Nome"
|
||||
|
|
@ -261,19 +261,19 @@ export const Home: React.FC<HomeProps> = ({ onEnter }) => {
|
|||
|
||||
{/* Right side - WhatsApp Card */}
|
||||
<div className={`transition-all duration-700 delay-300 ${contactVisible ? 'opacity-100 translate-x-0' : 'opacity-0 translate-x-20'}`}>
|
||||
<div className="bg-gradient-to-br from-[#25D366]/20 to-[#128C7E]/20 p-5 sm:p-6 rounded-xl backdrop-blur-md border border-[#25D366]/30 shadow-2xl hover:shadow-[#25D366]/20 hover:-translate-y-1 transition-all duration-300">
|
||||
<div className="flex flex-col items-center text-center space-y-3">
|
||||
<div className="bg-gradient-to-br from-white/10 to-white/5 p-6 sm:p-8 rounded-2xl backdrop-blur-md border border-white/10 shadow-2xl hover:shadow-[#25D366]/20 hover:-translate-y-1 transition-all duration-300">
|
||||
<div className="flex flex-col items-center text-center space-y-4">
|
||||
{/* WhatsApp Icon */}
|
||||
<div className="w-16 h-16 sm:w-20 sm:h-20 rounded-full bg-[#25D366] flex items-center justify-center shadow-lg transform hover:scale-110 transition-transform duration-300">
|
||||
<svg className="w-10 h-10 sm:w-12 sm:h-12 text-white" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z"/>
|
||||
<div className="w-20 h-20 sm:w-24 sm:h-24 rounded-full bg-[#25D366] flex items-center justify-center shadow-lg transform hover:scale-110 transition-transform duration-300">
|
||||
<svg className="w-12 h-12 sm:w-14 sm:h-14 text-white" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
{/* Text */}
|
||||
<div className="space-y-1">
|
||||
<h3 className="text-lg sm:text-xl font-bold text-white">Tire suas dúvidas</h3>
|
||||
<p className="text-xs sm:text-sm text-white/90 leading-snug">
|
||||
<div className="space-y-2">
|
||||
<h3 className="text-xl sm:text-2xl font-bold text-white">Tire suas dúvidas</h3>
|
||||
<p className="text-sm sm:text-base text-white/80 leading-relaxed">
|
||||
Faça orçamento direto no nosso WhatsApp
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -283,18 +283,18 @@ export const Home: React.FC<HomeProps> = ({ onEnter }) => {
|
|||
href="https://wa.me/5519999999999"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="w-full bg-[#25D366] hover:bg-[#128C7E] text-white font-bold py-2.5 px-4 rounded-lg transition-all duration-300 transform hover:scale-105 hover:shadow-xl active:scale-95 flex items-center justify-center gap-2 group text-sm"
|
||||
className="w-full bg-[#25D366] hover:bg-[#128C7E] text-white font-bold py-3.5 px-6 rounded-xl transition-all duration-300 transform hover:scale-105 hover:shadow-xl active:scale-95 flex items-center justify-center gap-2 group text-base shadow-lg"
|
||||
>
|
||||
<svg className="w-5 h-5 transform group-hover:rotate-12 transition-transform duration-300" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z"/>
|
||||
<svg className="w-6 h-6 transform group-hover:rotate-12 transition-transform duration-300" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z" />
|
||||
</svg>
|
||||
<span>Falar no WhatsApp</span>
|
||||
</a>
|
||||
|
||||
{/* Additional Info */}
|
||||
<div className="flex items-center gap-1.5 text-xs text-white/80">
|
||||
<div className="flex items-center gap-2 text-sm text-white/70 bg-white/5 px-4 py-2 rounded-full">
|
||||
<div className="w-2 h-2 bg-[#25D366] rounded-full animate-pulse"></div>
|
||||
<span>Resposta rápida garantida</span>
|
||||
<span className="font-medium">Resposta rápida garantida</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -42,28 +42,76 @@ export const SettingsPage: React.FC = () => {
|
|||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50 pt-32 pb-12">
|
||||
<div className="min-h-screen bg-gray-50 pt-20 sm:pt-24 md:pt-28 lg:pt-32 pb-8 sm:pb-12">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
{/* Header */}
|
||||
<div className="mb-8">
|
||||
<h1 className="text-3xl font-serif font-bold text-brand-black mb-2">
|
||||
<div className="mb-6 sm:mb-8">
|
||||
<h1 className="text-2xl sm:text-3xl font-serif font-bold text-brand-black mb-2">
|
||||
Configurações
|
||||
</h1>
|
||||
<p className="text-gray-600">
|
||||
<p className="text-sm sm:text-base text-gray-600">
|
||||
Gerencie suas preferências e informações da conta
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-4 gap-6">
|
||||
{/* Sidebar */}
|
||||
<div className="lg:col-span-1">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-4 gap-4 sm:gap-6">
|
||||
{/* Mobile Tabs - Horizontal */}
|
||||
<div className="lg:hidden">
|
||||
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-2">
|
||||
<nav className="flex overflow-x-auto gap-1 scrollbar-hide">
|
||||
<button
|
||||
onClick={() => setActiveTab('profile')}
|
||||
className={`flex items-center gap-2 px-3 py-2 rounded-md transition-colors whitespace-nowrap text-sm ${activeTab === 'profile'
|
||||
? 'bg-brand-gold text-white'
|
||||
: 'text-gray-700 hover:bg-gray-100'
|
||||
}`}
|
||||
>
|
||||
<User size={18} />
|
||||
<span className="font-medium">Perfil</span>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab('account')}
|
||||
className={`flex items-center gap-2 px-3 py-2 rounded-md transition-colors whitespace-nowrap text-sm ${activeTab === 'account'
|
||||
? 'bg-brand-gold text-white'
|
||||
: 'text-gray-700 hover:bg-gray-100'
|
||||
}`}
|
||||
>
|
||||
<Lock size={18} />
|
||||
<span className="font-medium">Conta</span>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab('notifications')}
|
||||
className={`flex items-center gap-2 px-3 py-2 rounded-md transition-colors whitespace-nowrap text-sm ${activeTab === 'notifications'
|
||||
? 'bg-brand-gold text-white'
|
||||
: 'text-gray-700 hover:bg-gray-100'
|
||||
}`}
|
||||
>
|
||||
<Bell size={18} />
|
||||
<span className="font-medium">Notificações</span>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab('appearance')}
|
||||
className={`flex items-center gap-2 px-3 py-2 rounded-md transition-colors whitespace-nowrap text-sm ${activeTab === 'appearance'
|
||||
? 'bg-brand-gold text-white'
|
||||
: 'text-gray-700 hover:bg-gray-100'
|
||||
}`}
|
||||
>
|
||||
<Palette size={18} />
|
||||
<span className="font-medium">Aparência</span>
|
||||
</button>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Desktop Sidebar - Vertical */}
|
||||
<div className="hidden lg:block lg:col-span-1">
|
||||
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-4">
|
||||
<nav className="space-y-1">
|
||||
<button
|
||||
onClick={() => setActiveTab('profile')}
|
||||
className={`w-full flex items-center gap-3 px-4 py-3 rounded-md transition-colors ${activeTab === 'profile'
|
||||
? 'bg-brand-gold text-white'
|
||||
: 'text-gray-700 hover:bg-gray-100'
|
||||
? 'bg-brand-gold text-white'
|
||||
: 'text-gray-700 hover:bg-gray-100'
|
||||
}`}
|
||||
>
|
||||
<User size={20} />
|
||||
|
|
@ -72,8 +120,8 @@ export const SettingsPage: React.FC = () => {
|
|||
<button
|
||||
onClick={() => setActiveTab('account')}
|
||||
className={`w-full flex items-center gap-3 px-4 py-3 rounded-md transition-colors ${activeTab === 'account'
|
||||
? 'bg-brand-gold text-white'
|
||||
: 'text-gray-700 hover:bg-gray-100'
|
||||
? 'bg-brand-gold text-white'
|
||||
: 'text-gray-700 hover:bg-gray-100'
|
||||
}`}
|
||||
>
|
||||
<Lock size={20} />
|
||||
|
|
@ -82,8 +130,8 @@ export const SettingsPage: React.FC = () => {
|
|||
<button
|
||||
onClick={() => setActiveTab('notifications')}
|
||||
className={`w-full flex items-center gap-3 px-4 py-3 rounded-md transition-colors ${activeTab === 'notifications'
|
||||
? 'bg-brand-gold text-white'
|
||||
: 'text-gray-700 hover:bg-gray-100'
|
||||
? 'bg-brand-gold text-white'
|
||||
: 'text-gray-700 hover:bg-gray-100'
|
||||
}`}
|
||||
>
|
||||
<Bell size={20} />
|
||||
|
|
@ -92,8 +140,8 @@ export const SettingsPage: React.FC = () => {
|
|||
<button
|
||||
onClick={() => setActiveTab('appearance')}
|
||||
className={`w-full flex items-center gap-3 px-4 py-3 rounded-md transition-colors ${activeTab === 'appearance'
|
||||
? 'bg-brand-gold text-white'
|
||||
: 'text-gray-700 hover:bg-gray-100'
|
||||
? 'bg-brand-gold text-white'
|
||||
: 'text-gray-700 hover:bg-gray-100'
|
||||
}`}
|
||||
>
|
||||
<Palette size={20} />
|
||||
|
|
@ -105,28 +153,28 @@ export const SettingsPage: React.FC = () => {
|
|||
|
||||
{/* Content */}
|
||||
<div className="lg:col-span-3">
|
||||
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-8">
|
||||
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-4 sm:p-6 md:p-8">
|
||||
{/* Profile Tab */}
|
||||
{activeTab === 'profile' && (
|
||||
<div>
|
||||
<h2 className="text-2xl font-semibold mb-6">Informações do Perfil</h2>
|
||||
<h2 className="text-xl sm:text-2xl font-semibold mb-4 sm:mb-6">Informações do Perfil</h2>
|
||||
|
||||
<div className="mb-8">
|
||||
<div className="flex items-center gap-6">
|
||||
<div className="mb-6 sm:mb-8">
|
||||
<div className="flex flex-col sm:flex-row items-center sm:items-start gap-4 sm:gap-6">
|
||||
<div className="relative">
|
||||
<img
|
||||
src={profileData.avatar}
|
||||
alt="Avatar"
|
||||
className="w-24 h-24 rounded-full object-cover"
|
||||
className="w-20 h-20 sm:w-24 sm:h-24 rounded-full object-cover"
|
||||
/>
|
||||
<button className="absolute bottom-0 right-0 w-8 h-8 bg-brand-gold text-white rounded-full flex items-center justify-center hover:bg-[#a5bd2e] transition-colors">
|
||||
<Camera size={16} />
|
||||
<button className="absolute bottom-0 right-0 w-7 h-7 sm:w-8 sm:h-8 bg-brand-gold text-white rounded-full flex items-center justify-center hover:bg-[#a5bd2e] transition-colors">
|
||||
<Camera size={14} className="sm:w-4 sm:h-4" />
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-semibold text-lg">{profileData.name}</h3>
|
||||
<p className="text-sm text-gray-600">{profileData.email}</p>
|
||||
<button className="text-sm text-brand-gold hover:underline mt-1">
|
||||
<div className="text-center sm:text-left">
|
||||
<h3 className="font-semibold text-base sm:text-lg">{profileData.name}</h3>
|
||||
<p className="text-xs sm:text-sm text-gray-600">{profileData.email}</p>
|
||||
<button className="text-xs sm:text-sm text-brand-gold hover:underline mt-1">
|
||||
Alterar foto
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -188,20 +188,20 @@ export const TeamPage: React.FC = () => {
|
|||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50 pt-32 pb-12">
|
||||
<div className="min-h-screen bg-gray-50 pt-20 sm:pt-24 md:pt-28 lg:pt-32 pb-8 sm:pb-12">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
{/* Header */}
|
||||
<div className="mb-8">
|
||||
<h1 className="text-3xl font-serif font-bold text-brand-black mb-2">
|
||||
<div className="mb-6 sm:mb-8">
|
||||
<h1 className="text-2xl sm:text-3xl font-serif font-bold text-brand-black mb-2">
|
||||
Equipe & Fotógrafos
|
||||
</h1>
|
||||
<p className="text-gray-600">
|
||||
<p className="text-sm sm:text-base text-gray-600">
|
||||
Gerencie sua equipe de fotógrafos profissionais
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Stats */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
|
||||
<div className="grid grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4 md:gap-6 mb-6 sm:mb-8">
|
||||
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
|
|
@ -251,8 +251,8 @@ export const TeamPage: React.FC = () => {
|
|||
</div>
|
||||
|
||||
{/* Filters and Search */}
|
||||
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6 mb-6">
|
||||
<div className="flex flex-col md:flex-row gap-4">
|
||||
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-3 sm:p-4 md:p-6 mb-4 sm:mb-6">
|
||||
<div className="flex flex-col gap-3 sm:gap-4">
|
||||
<div className="flex-1 relative">
|
||||
<Search
|
||||
className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400"
|
||||
|
|
@ -266,34 +266,31 @@ export const TeamPage: React.FC = () => {
|
|||
className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-brand-gold"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<button
|
||||
onClick={() => setStatusFilter("all")}
|
||||
className={`px-4 py-2 rounded-md font-medium transition-colors ${
|
||||
statusFilter === "all"
|
||||
className={`px-4 py-2 rounded-md font-medium transition-colors ${statusFilter === "all"
|
||||
? "bg-brand-gold text-white"
|
||||
: "bg-gray-100 text-gray-700 hover:bg-gray-200"
|
||||
}`}
|
||||
}`}
|
||||
>
|
||||
Todos
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setStatusFilter("active")}
|
||||
className={`px-4 py-2 rounded-md font-medium transition-colors ${
|
||||
statusFilter === "active"
|
||||
className={`px-4 py-2 rounded-md font-medium transition-colors ${statusFilter === "active"
|
||||
? "bg-green-600 text-white"
|
||||
: "bg-gray-100 text-gray-700 hover:bg-gray-200"
|
||||
}`}
|
||||
}`}
|
||||
>
|
||||
Disponíveis
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setStatusFilter("busy")}
|
||||
className={`px-4 py-2 rounded-md font-medium transition-colors ${
|
||||
statusFilter === "busy"
|
||||
className={`px-4 py-2 rounded-md font-medium transition-colors ${statusFilter === "busy"
|
||||
? "bg-yellow-600 text-white"
|
||||
: "bg-gray-100 text-gray-700 hover:bg-gray-200"
|
||||
}`}
|
||||
}`}
|
||||
>
|
||||
Em Evento
|
||||
</button>
|
||||
|
|
@ -310,7 +307,7 @@ export const TeamPage: React.FC = () => {
|
|||
</div>
|
||||
|
||||
{/* Photographers Grid */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 sm:gap-6">
|
||||
{filteredPhotographers.map((photographer) => (
|
||||
<div
|
||||
key={photographer.id}
|
||||
|
|
@ -419,11 +416,11 @@ export const TeamPage: React.FC = () => {
|
|||
e.preventDefault();
|
||||
alert(
|
||||
"Fotógrafo adicionado com sucesso!\n\n" +
|
||||
JSON.stringify(
|
||||
{ ...newPhotographer, avatarFile: avatarFile?.name },
|
||||
null,
|
||||
2
|
||||
)
|
||||
JSON.stringify(
|
||||
{ ...newPhotographer, avatarFile: avatarFile?.name },
|
||||
null,
|
||||
2
|
||||
)
|
||||
);
|
||||
setShowAddModal(false);
|
||||
setNewPhotographer({
|
||||
|
|
|
|||
Loading…
Reference in a new issue