feat: Modularize event management system - 98.7% reduction in main file size

BREAKING CHANGES:
- Refactored monolithic manage.astro (7,623 lines) into modular architecture
- Original file backed up as manage-old.astro

NEW ARCHITECTURE:
 5 Utility Libraries:
  - event-management.ts: Event data operations & formatting
  - ticket-management.ts: Ticket CRUD operations & sales data
  - seating-management.ts: Seating map management & layout generation
  - sales-analytics.ts: Sales metrics, reporting & data export
  - marketing-kit.ts: Marketing asset generation & social media

 5 Shared Components:
  - TicketTypeModal.tsx: Reusable ticket type creation/editing
  - SeatingMapModal.tsx: Advanced seating map editor with drag-and-drop
  - EmbedCodeModal.tsx: Widget embedding with customization
  - OrdersTable.tsx: Comprehensive orders table with sorting/pagination
  - AttendeesTable.tsx: Attendee management with export capabilities

 11 Tab Components:
  - TicketsTab.tsx: Ticket management with card/list views
  - VenueTab.tsx: Seating map management & venue configuration
  - OrdersTab.tsx: Sales data & order management
  - AttendeesTab.tsx: Attendee check-in & management
  - PresaleTab.tsx: Presale code generation & tracking
  - DiscountTab.tsx: Discount code management
  - AddonsTab.tsx: Add-on product management
  - PrintedTab.tsx: Printed ticket barcode management
  - SettingsTab.tsx: Event configuration & custom fields
  - MarketingTab.tsx: Marketing kit with social media templates
  - PromotionsTab.tsx: Campaign & promotion management

 4 Infrastructure Components:
  - TabNavigation.tsx: Responsive tab navigation system
  - EventManagement.tsx: Main orchestration component
  - EventHeader.astro: Event information header
  - QuickStats.astro: Statistics dashboard

BENEFITS:
- 98.7% reduction in main file size (7,623 → ~100 lines)
- Dramatic improvement in maintainability and team collaboration
- Component-level testing now possible
- Reusable components across multiple features
- Lazy loading support for better performance
- Full TypeScript support with proper interfaces
- Separation of concerns: business logic separated from UI

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-07-08 18:30:26 -06:00
parent 23f190c7a7
commit e8b95231b7
76 changed files with 26728 additions and 7101 deletions

View File

@@ -49,6 +49,15 @@ import Navigation from '../../components/Navigation.astro';
<h2 class="text-2xl font-light text-white mb-6">Event Details</h2>
<div class="space-y-6">
<!-- Event Image Upload -->
<div>
<h3 class="text-lg font-medium text-white mb-4">Event Image</h3>
<div id="image-upload-container"></div>
<p class="text-sm text-white/60 mt-2">
Upload a horizontal image. Recommended: 1200×628px. Crop to fit.
</p>
</div>
<div>
<label for="title" class="block text-sm font-semibold text-white/90 mb-2">Event Title</label>
<input
@@ -289,6 +298,9 @@ import Navigation from '../../components/Navigation.astro';
<script>
import { supabase } from '../../lib/supabase';
import { createElement } from 'react';
import { createRoot } from 'react-dom/client';
import ImageUploadCropper from '../../components/ImageUploadCropper.tsx';
const eventForm = document.getElementById('event-form') as HTMLFormElement;
const errorMessage = document.getElementById('error-message') as HTMLDivElement;
@@ -298,6 +310,7 @@ import Navigation from '../../components/Navigation.astro';
let currentOrganizationId = null;
let selectedAddons = [];
let eventImageUrl = null;
// Check authentication
async function checkAuth() {
@@ -471,7 +484,8 @@ import Navigation from '../../components/Navigation.astro';
description,
created_by: user.id,
organization_id: organizationId,
seating_type: seatingType
seating_type: seatingType,
image_url: eventImageUrl
}
])
.select()
@@ -513,11 +527,25 @@ import Navigation from '../../components/Navigation.astro';
radio.addEventListener('change', handleVenueOptionChange);
});
// Initialize Image Upload Component
function initializeImageUpload() {
const container = document.getElementById('image-upload-container');
if (container) {
const root = createRoot(container);
root.render(createElement(ImageUploadCropper, {
onImageChange: (imageUrl) => {
eventImageUrl = imageUrl;
}
}));
}
}
// Initialize
checkAuth().then(session => {
if (session && currentOrganizationId) {
loadVenues();
}
handleVenueOptionChange(); // Set initial state
initializeImageUpload(); // Initialize image upload
});
</script>