feat: Complete platform enhancement with multi-tenant architecture
Major additions: - Territory manager system with application workflow - Custom pricing and page builder with Craft.js - Enhanced Stripe Connect onboarding - CodeReadr QR scanning integration - Kiosk mode for venue sales - Super admin dashboard and analytics - MCP integration for AI-powered operations Infrastructure improvements: - Centralized API client and routing system - Enhanced authentication with organization context - Comprehensive theme management system - Advanced event management with custom tabs - Performance monitoring and accessibility features Database schema updates: - Territory management tables - Custom pages and pricing structures - Kiosk PIN system - Enhanced organization profiles - CodeReadr integration tables 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -51,8 +51,9 @@ const WhatsHotEvents: React.FC<WhatsHotEventsProps> = ({
|
||||
|
||||
setTrendingEvents(trending);
|
||||
} catch (err) {
|
||||
console.error('Trending events loading error:', err);
|
||||
setError('Failed to load trending events');
|
||||
console.error('Error loading trending events:', err);
|
||||
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
@@ -101,18 +102,18 @@ const WhatsHotEvents: React.FC<WhatsHotEventsProps> = ({
|
||||
};
|
||||
|
||||
const getPopularityBadge = (score: number) => {
|
||||
if (score >= 100) return { text: 'Super Hot', color: 'bg-red-500' };
|
||||
if (score >= 50) return { text: 'Hot', color: 'bg-orange-500' };
|
||||
if (score >= 25) return { text: 'Trending', color: 'bg-yellow-500' };
|
||||
return { text: 'Popular', color: 'bg-blue-500' };
|
||||
if (score >= 100) return { text: 'Super Hot', color: 'var(--error-color)' };
|
||||
if (score >= 50) return { text: 'Hot', color: 'var(--warning-color)' };
|
||||
if (score >= 25) return { text: 'Trending', color: 'var(--premium-gold)' };
|
||||
return { text: 'Popular', color: 'var(--glass-text-accent)' };
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className={`bg-white rounded-lg shadow-md p-6 ${className}`}>
|
||||
<div className={`rounded-lg shadow-md p-6 ${className}`} style={{background: 'var(--ui-bg-elevated)'}}>
|
||||
<div className="flex items-center justify-center h-32">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-indigo-600"></div>
|
||||
<span className="ml-3 text-gray-600">Loading hot events...</span>
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2" style={{borderColor: 'var(--glass-text-accent)'}}></div>
|
||||
<span className="ml-3" style={{color: 'var(--ui-text-secondary)'}}>Loading hot events...</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -120,16 +121,19 @@ const WhatsHotEvents: React.FC<WhatsHotEventsProps> = ({
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div className={`bg-white rounded-lg shadow-md p-6 ${className}`}>
|
||||
<div className={`rounded-lg shadow-md p-6 ${className}`} style={{background: 'var(--ui-bg-elevated)'}}>
|
||||
<div className="text-center">
|
||||
<svg className="mx-auto h-12 w-12 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<svg className="mx-auto h-12 w-12" style={{color: 'var(--ui-text-muted)'}} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z" />
|
||||
</svg>
|
||||
<h3 className="mt-2 text-sm font-medium text-gray-900">Unable to load events</h3>
|
||||
<p className="mt-1 text-sm text-gray-500">{error}</p>
|
||||
<h3 className="mt-2 text-sm font-medium" style={{color: 'var(--ui-text-primary)'}}>Unable to load events</h3>
|
||||
<p className="mt-1 text-sm" style={{color: 'var(--ui-text-secondary)'}}>{error}</p>
|
||||
<button
|
||||
onClick={loadTrendingEvents}
|
||||
className="mt-2 text-sm text-indigo-600 hover:text-indigo-700 font-medium"
|
||||
className="mt-2 text-sm font-medium transition-colors"
|
||||
style={{color: 'var(--glass-text-accent)'}}
|
||||
onMouseEnter={(e) => e.target.style.color = 'var(--premium-primary)'}
|
||||
onMouseLeave={(e) => e.target.style.color = 'var(--glass-text-accent)'}
|
||||
>
|
||||
Try again
|
||||
</button>
|
||||
@@ -140,13 +144,13 @@ const WhatsHotEvents: React.FC<WhatsHotEventsProps> = ({
|
||||
|
||||
if (trendingEvents.length === 0) {
|
||||
return (
|
||||
<div className={`bg-white rounded-lg shadow-md p-6 ${className}`}>
|
||||
<div className={`rounded-lg shadow-md p-6 ${className}`} style={{background: 'var(--ui-bg-elevated)'}}>
|
||||
<div className="text-center">
|
||||
<svg className="mx-auto h-12 w-12 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<svg className="mx-auto h-12 w-12" style={{color: 'var(--ui-text-muted)'}} fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7V3a4 4 0 118 0v4m-4 12v-6m-4 0h8m-8 0v6a4 4 0 108 0v-6" />
|
||||
</svg>
|
||||
<h3 className="mt-2 text-sm font-medium text-gray-900">No trending events found</h3>
|
||||
<p className="mt-1 text-sm text-gray-500">
|
||||
<h3 className="mt-2 text-sm font-medium" style={{color: 'var(--ui-text-primary)'}}>No trending events found</h3>
|
||||
<p className="mt-1 text-sm" style={{color: 'var(--ui-text-secondary)'}}>
|
||||
Try expanding your search radius or check back later
|
||||
</p>
|
||||
</div>
|
||||
@@ -155,16 +159,16 @@ const WhatsHotEvents: React.FC<WhatsHotEventsProps> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`bg-white rounded-lg shadow-md overflow-hidden ${className}`}>
|
||||
<div className={`rounded-lg shadow-md overflow-hidden ${className}`} style={{background: 'var(--ui-bg-elevated)'}}>
|
||||
{/* Header */}
|
||||
<div className="bg-gradient-to-r from-orange-400 to-red-500 px-6 py-4">
|
||||
<div className="px-6 py-4" style={{background: 'linear-gradient(to right, var(--warning-color), var(--error-color))'}}>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="text-2xl">🔥</div>
|
||||
<h2 className="text-xl font-bold text-white">What's Hot</h2>
|
||||
<h2 className="text-xl font-bold" style={{color: 'var(--glass-text-primary)'}}>What's Hot</h2>
|
||||
</div>
|
||||
{userLocation && (
|
||||
<span className="text-orange-100 text-sm">
|
||||
<span className="text-sm" style={{color: 'var(--glass-text-secondary)'}}>
|
||||
Within {radius} miles
|
||||
</span>
|
||||
)}
|
||||
@@ -174,22 +178,34 @@ const WhatsHotEvents: React.FC<WhatsHotEventsProps> = ({
|
||||
{/* Events Grid */}
|
||||
<div className="p-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
|
||||
{trendingEvents.map((event, index) => {
|
||||
{trendingEvents.map((event, _index) => {
|
||||
const popularityBadge = getPopularityBadge(event.popularityScore);
|
||||
return (
|
||||
<div
|
||||
key={event.eventId}
|
||||
onClick={() => handleEventClick(event)}
|
||||
className="group cursor-pointer bg-gray-50 rounded-lg p-4 hover:bg-gray-100 transition-colors duration-200 border border-gray-200 hover:border-gray-300 relative overflow-hidden"
|
||||
className="group cursor-pointer rounded-lg p-4 transition-colors duration-200 border relative overflow-hidden backdrop-blur-lg"
|
||||
style={{
|
||||
background: 'var(--ui-bg-secondary)',
|
||||
borderColor: 'var(--ui-border-primary)'
|
||||
}}
|
||||
onMouseEnter={(e) => {
|
||||
e.target.style.background = 'var(--ui-bg-elevated)';
|
||||
e.target.style.borderColor = 'var(--ui-border-secondary)';
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.target.style.background = 'var(--ui-bg-secondary)';
|
||||
e.target.style.borderColor = 'var(--ui-border-primary)';
|
||||
}}
|
||||
>
|
||||
{/* Popularity Badge */}
|
||||
<div className={`absolute top-2 right-2 px-2 py-1 rounded-full text-xs font-medium text-white ${popularityBadge.color}`}>
|
||||
<div className={`absolute top-2 right-2 px-2 py-1 rounded-full text-xs font-medium`} style={{color: 'var(--glass-text-primary)', backgroundColor: popularityBadge.color}}>
|
||||
{popularityBadge.text}
|
||||
</div>
|
||||
|
||||
{/* Event Image */}
|
||||
{event.imageUrl && (
|
||||
<div className="w-full h-32 bg-gray-200 rounded-lg mb-3 overflow-hidden">
|
||||
<div className="w-full h-32 rounded-lg mb-3 overflow-hidden" style={{background: 'var(--ui-bg-muted)'}}>
|
||||
<img
|
||||
src={event.imageUrl}
|
||||
alt={event.title}
|
||||
@@ -201,12 +217,12 @@ const WhatsHotEvents: React.FC<WhatsHotEventsProps> = ({
|
||||
{/* Event Content */}
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-start justify-between">
|
||||
<h3 className="text-sm font-semibold text-gray-900 line-clamp-2 pr-8">
|
||||
<h3 className="text-sm font-semibold line-clamp-2 pr-8" style={{color: 'var(--ui-text-primary)'}}>
|
||||
{event.title}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div className="text-xs text-gray-600 space-y-1">
|
||||
<div className="text-xs space-y-1" style={{color: 'var(--ui-text-secondary)'}}>
|
||||
<div className="flex items-center">
|
||||
<svg className="h-3 w-3 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
|
||||
@@ -233,7 +249,7 @@ const WhatsHotEvents: React.FC<WhatsHotEventsProps> = ({
|
||||
</div>
|
||||
|
||||
{/* Event Stats */}
|
||||
<div className="flex items-center justify-between text-xs text-gray-500 pt-2 border-t border-gray-200">
|
||||
<div className="flex items-center justify-between text-xs pt-2 border-t" style={{color: 'var(--ui-text-tertiary)', borderColor: 'var(--ui-border-secondary)'}}>
|
||||
<div className="flex items-center space-x-3">
|
||||
<div className="flex items-center">
|
||||
<svg className="h-3 w-3 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
@@ -252,10 +268,10 @@ const WhatsHotEvents: React.FC<WhatsHotEventsProps> = ({
|
||||
|
||||
{event.isFeature && (
|
||||
<div className="flex items-center">
|
||||
<svg className="h-3 w-3 mr-1 text-yellow-500" fill="currentColor" viewBox="0 0 20 20">
|
||||
<svg className="h-3 w-3 mr-1" style={{color: 'var(--premium-gold)'}} fill="currentColor" viewBox="0 0 20 20">
|
||||
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
|
||||
</svg>
|
||||
<span className="text-yellow-600 font-medium">Featured</span>
|
||||
<span className="font-medium" style={{color: 'var(--premium-gold)'}}>Featured</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -269,7 +285,13 @@ const WhatsHotEvents: React.FC<WhatsHotEventsProps> = ({
|
||||
<div className="mt-6 text-center">
|
||||
<button
|
||||
onClick={() => window.location.href = '/calendar'}
|
||||
className="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-gradient-to-r from-orange-400 to-red-500 hover:from-orange-500 hover:to-red-600 transition-colors duration-200"
|
||||
className="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md transition-colors duration-200"
|
||||
style={{
|
||||
color: 'var(--glass-text-primary)',
|
||||
background: 'linear-gradient(to right, var(--warning-color), var(--error-color))'
|
||||
}}
|
||||
onMouseEnter={(e) => e.target.style.background = 'linear-gradient(to right, var(--warning-color-dark), var(--error-color-dark))'}
|
||||
onMouseLeave={(e) => e.target.style.background = 'linear-gradient(to right, var(--warning-color), var(--error-color))'}
|
||||
>
|
||||
View All Events
|
||||
<svg className="ml-2 h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
|
||||
Reference in New Issue
Block a user