feat: add advanced analytics and territory management system

- Add comprehensive analytics components with export functionality
- Implement territory management with manager performance tracking
- Add seatmap components for venue layout management
- Create customer management features with modal interface
- Add advanced hooks for dashboard flags and territory data
- Implement seat selection and venue management utilities
- Add type definitions for ticketing and seatmap systems

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-08-26 09:25:10 -06:00
parent d5c3953888
commit aa81eb5adb
438 changed files with 90509 additions and 2787 deletions

View File

@@ -0,0 +1,247 @@
/**
* Focused test to diagnose why TicketsTab component logs aren't appearing
*/
const { test, expect } = require('@playwright/test');
test('Diagnose TicketsTab component mounting issue', async ({ page }) => {
const consoleMessages = [];
// Capture all console messages
page.on('console', msg => {
const text = msg.text();
consoleMessages.push({ type: msg.type(), text, timestamp: Date.now() });
// Log all TicketsTab, TicketingAccessTab and component-related messages
if (text.includes('TICKETS TAB') ||
text.includes('TICKETING ACCESS TAB') ||
text.includes('EventManagement') ||
text.includes('component rendered') ||
text.includes('TicketsTab') ||
text.includes('React')) {
console.log(`🔍 [${msg.type()}] ${text}`);
}
});
console.log('🚀 Starting TicketsTab component diagnosis...');
// Step 1: Navigate directly to event management page (assume user is already logged in)
console.log('📝 Step 1: Navigating directly to event management page...');
// Replace with an actual event ID from your system
const testEventId = 'test-event-or-first-available';
try {
// First, try to get to dashboard to find an event
await page.goto('http://localhost:3000/dashboard');
await page.waitForLoadState('networkidle');
await page.waitForTimeout(2000);
// Look for any event management links
const eventLinks = await page.locator('a[href*="/events/"][href*="/manage"]').all();
if (eventLinks.length === 0) {
console.log('❌ No event management links found on dashboard');
console.log('📄 Page content preview:');
const bodyText = await page.locator('body').textContent();
console.log(bodyText.substring(0, 500) + '...');
return;
}
const firstEventLink = await eventLinks[0].getAttribute('href');
console.log(`✅ Found event management link: ${firstEventLink}`);
// Navigate to the event management page
await page.goto(`http://localhost:3000${firstEventLink}`);
await page.waitForLoadState('networkidle');
} catch (error) {
console.log(`❌ Error navigating to event management: ${error.message}`);
return;
}
// Step 2: Wait for components to load and check console
console.log('⏳ Step 2: Waiting for React components to mount...');
await page.waitForTimeout(5000);
// Check what console messages we have so far
const componentMessages = consoleMessages.filter(msg =>
msg.text.includes('TICKETS TAB') ||
msg.text.includes('TICKETING ACCESS TAB') ||
msg.text.includes('EventManagement') ||
msg.text.includes('component rendered')
);
console.log(`\n📊 Component-related console messages found: ${componentMessages.length}`);
componentMessages.forEach((msg, i) => {
console.log(` ${i + 1}. [${msg.type}] ${msg.text}`);
});
// Step 3: Check if we're on the Ticketing & Access tab
console.log('\n📋 Step 3: Checking current tab state...');
// Look for active tab
const activeTab = page.locator('[aria-selected="true"], .tab-active, .active').first();
if (await activeTab.isVisible()) {
const activeTabText = await activeTab.textContent();
console.log(`Current active tab: "${activeTabText}"`);
if (!activeTabText.includes('Ticketing')) {
console.log('🎫 Clicking on Ticketing & Access tab...');
const ticketingTab = page.locator('text="Ticketing & Access"').first();
if (await ticketingTab.isVisible()) {
await ticketingTab.click();
await page.waitForTimeout(2000);
console.log('✅ Clicked Ticketing & Access tab');
} else {
console.log('❌ Ticketing & Access tab not found');
}
}
}
// Step 4: Check if we're on the correct sub-tab (Ticket Types)
console.log('\n🎟 Step 4: Checking sub-tab state...');
// Look for sub-tab navigation
const subTabs = await page.locator('button:has-text("Ticket Types"), button:has-text("Ticket")').all();
console.log(`Found ${subTabs.length} potential ticket-related sub-tabs`);
if (subTabs.length > 0) {
const ticketTypesTab = subTabs[0];
const isActive = await ticketTypesTab.evaluate(el => el.classList.contains('active') || el.getAttribute('aria-selected') === 'true');
console.log(`Ticket Types tab active: ${isActive}`);
if (!isActive) {
console.log('🎫 Clicking Ticket Types sub-tab...');
await ticketTypesTab.click();
await page.waitForTimeout(2000);
}
}
// Step 5: Check for React component mounting
console.log('\n⚛ Step 5: Checking for React component mounting...');
const reactCheck = await page.evaluate(() => {
// Check for astro islands that might contain TicketsTab
const islands = Array.from(document.querySelectorAll('astro-island'));
const islandInfo = islands.map(island => ({
component: island.getAttribute('component-export'),
url: island.getAttribute('component-url'),
props: island.getAttribute('props'),
hasContent: island.innerHTML.length > 0,
contentPreview: island.innerHTML.substring(0, 100)
}));
// Check for any elements that look like they should contain TicketsTab
const ticketElements = Array.from(document.querySelectorAll('[class*="ticket"], [id*="ticket"], [data-testid*="ticket"]'));
return {
islandCount: islands.length,
islandInfo,
ticketElementsCount: ticketElements.length,
bodyInnerHTMLLength: document.body.innerHTML.length
};
});
console.log('React mounting check:', JSON.stringify(reactCheck, null, 2));
// Step 6: Look specifically for TicketsTab component output
console.log('\n🔍 Step 6: Looking for TicketsTab-specific elements...');
// Look for elements that should be rendered by TicketsTab
const ticketTabElements = [
'text="No ticket types created yet"',
'text="Create Your First Ticket Type"',
'text="Add Ticket Type"',
'text="Ticket Types & Pricing"',
'[data-testid="tickets-tab"]'
];
const foundElements = [];
for (const selector of ticketTabElements) {
const element = page.locator(selector).first();
const isVisible = await element.isVisible();
foundElements.push({ selector, visible: isVisible });
if (isVisible) {
console.log(`✅ Found: ${selector}`);
}
}
const visibleCount = foundElements.filter(e => e.visible).length;
console.log(`Found ${visibleCount} out of ${foundElements.length} expected TicketsTab elements`);
// Step 7: Check for any error states
console.log('\n❌ Step 7: Checking for error states...');
const errorElements = await page.locator('.error, [class*="error"], text="Error"').all();
console.log(`Found ${errorElements.length} potential error elements`);
for (let i = 0; i < Math.min(errorElements.length, 3); i++) {
const errorText = await errorElements[i].textContent();
console.log(` Error ${i + 1}: ${errorText}`);
}
// Step 8: Try to force trigger TicketsTab by checking props
console.log('\n🔧 Step 8: Checking component props and state...');
const propsCheck = await page.evaluate(() => {
// Look for any global variables or state that might indicate what's happening
const urlParams = new URLSearchParams(window.location.search);
const pathname = window.location.pathname;
// Check if there are any global React states or props
const reactElements = document.querySelectorAll('[data-react*]');
return {
currentURL: window.location.href,
pathname,
urlParams: Object.fromEntries(urlParams.entries()),
reactElementsFound: reactElements.length,
documentTitle: document.title
};
});
console.log('Page state check:', JSON.stringify(propsCheck, null, 2));
// Step 9: Final diagnosis
console.log('\n📊 FINAL DIAGNOSIS:');
console.log('='.repeat(50));
const ticketsTabMessages = consoleMessages.filter(msg => msg.text.includes('TICKETS TAB'));
const ticketingAccessMessages = consoleMessages.filter(msg => msg.text.includes('TICKETING ACCESS TAB'));
const eventManagementMessages = consoleMessages.filter(msg => msg.text.includes('EventManagement'));
console.log(`TicketsTab console messages: ${ticketsTabMessages.length}`);
console.log(`TicketingAccessTab console messages: ${ticketingAccessMessages.length}`);
console.log(`EventManagement console messages: ${eventManagementMessages.length}`);
console.log(`Total component messages: ${componentMessages.length}`);
console.log(`React islands found: ${reactCheck.islandCount}`);
console.log(`TicketsTab elements visible: ${visibleCount}/${foundElements.length}`);
if (ticketsTabMessages.length === 0 && ticketingAccessMessages.length > 0) {
console.log('\n🚨 DIAGNOSIS: TicketingAccessTab is rendering but TicketsTab is NOT');
console.log('This suggests:');
console.log(' 1. TicketingAccessTab component is mounting correctly');
console.log(' 2. The sub-tab system is working');
console.log(' 3. But TicketsTab is not being rendered by TicketingAccessTab');
console.log(' 4. Check if activeSubTab state is set to "tickets"');
console.log(' 5. Check if TicketsTab component has rendering conditions that are failing');
} else if (ticketsTabMessages.length === 0 && ticketingAccessMessages.length === 0) {
console.log('\n🚨 DIAGNOSIS: Neither TicketingAccessTab nor TicketsTab are rendering');
console.log('This suggests:');
console.log(' 1. EventManagement component may not be passing correct props');
console.log(' 2. The tab navigation system is not working');
console.log(' 3. React components are not mounting at all');
console.log(' 4. Check if EventManagement is finding the correct tab configuration');
}
// Take screenshot
await page.screenshot({
path: '/home/tyler/apps/bct-whitelabel/tickets-tab-diagnosis.png',
fullPage: true
});
console.log('\n📸 Screenshot saved: tickets-tab-diagnosis.png');
console.log('\n✅ Diagnosis complete!');
await page.waitForTimeout(5000);
});