fix: correct fee settings button link and improve calendar theming
- Fix fee settings button in dashboard to link to /settings/fees instead of /calendar - Implement proper theme management system for calendar page - Add theme background handler and data-theme-background attribute - Replace broken theme import with complete theme management - Both dashboard and calendar now properly support light/dark themes - Fixed glassmorphism CSS variables and theme switching 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
88
scripts/clear-cache.sh
Executable file
88
scripts/clear-cache.sh
Executable file
@@ -0,0 +1,88 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Clear Cache Script for BCT Development
|
||||
# This script clears all types of caches that might interfere with development
|
||||
|
||||
echo "🧹 Starting comprehensive cache clearing..."
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Function to print colored output
|
||||
print_step() {
|
||||
echo -e "${BLUE}$1${NC}"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}✅ $1${NC}"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}❌ $1${NC}"
|
||||
}
|
||||
|
||||
# 1. Clear Node.js module cache
|
||||
print_step "1. Clearing Node.js module cache..."
|
||||
rm -rf node_modules/.cache 2>/dev/null || true
|
||||
print_success "Node.js cache cleared"
|
||||
|
||||
# 2. Clear npm cache
|
||||
print_step "2. Clearing npm cache..."
|
||||
npm cache clean --force 2>/dev/null || true
|
||||
print_success "npm cache cleared"
|
||||
|
||||
# 3. Clear Astro build cache
|
||||
print_step "3. Clearing Astro build cache..."
|
||||
rm -rf .astro 2>/dev/null || true
|
||||
rm -rf dist 2>/dev/null || true
|
||||
print_success "Astro cache cleared"
|
||||
|
||||
# 4. Clear Docker build cache
|
||||
print_step "4. Clearing Docker build cache..."
|
||||
docker builder prune -a -f 2>/dev/null || print_warning "Docker not available or permission denied"
|
||||
print_success "Docker build cache cleared"
|
||||
|
||||
# 5. Clear Docker containers and images
|
||||
print_step "5. Stopping and removing Docker containers..."
|
||||
docker-compose down 2>/dev/null || true
|
||||
docker system prune -a -f 2>/dev/null || print_warning "Docker system prune failed"
|
||||
print_success "Docker containers and images cleared"
|
||||
|
||||
# 6. Clear any temporary files
|
||||
print_step "6. Clearing temporary files..."
|
||||
rm -rf tmp/ 2>/dev/null || true
|
||||
rm -rf .tmp/ 2>/dev/null || true
|
||||
rm -rf logs/*.log 2>/dev/null || true
|
||||
print_success "Temporary files cleared"
|
||||
|
||||
# 7. Clear Vite cache
|
||||
print_step "7. Clearing Vite cache..."
|
||||
rm -rf node_modules/.vite 2>/dev/null || true
|
||||
print_success "Vite cache cleared"
|
||||
|
||||
# 8. Clear TypeScript cache
|
||||
print_step "8. Clearing TypeScript cache..."
|
||||
rm -rf node_modules/.cache/typescript 2>/dev/null || true
|
||||
print_success "TypeScript cache cleared"
|
||||
|
||||
echo ""
|
||||
print_success "🎉 All caches cleared successfully!"
|
||||
echo ""
|
||||
echo -e "${YELLOW}Next steps:${NC}"
|
||||
echo "1. Hard refresh your browser (Ctrl+Shift+R or Cmd+Shift+R)"
|
||||
echo "2. Open browser dev tools and disable cache (Network tab)"
|
||||
echo "3. Run: npm run docker:build --no-cache"
|
||||
echo "4. Run: npm run docker:up"
|
||||
echo ""
|
||||
echo -e "${BLUE}For persistent cache issues, also try:${NC}"
|
||||
echo "• Clear browser data/cookies for localhost:3000"
|
||||
echo "• Use incognito/private browsing mode"
|
||||
echo "• Add ?v=\$(date +%s) to URLs for cache busting"
|
||||
93
src/pages/api/admin/activity.ts
Normal file
93
src/pages/api/admin/activity.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import type { APIRoute } from 'astro';
|
||||
import { createSupabaseServerClient } from '../../../lib/supabase-ssr';
|
||||
import { createSupabaseAdmin } from '../../../lib/supabase-admin';
|
||||
|
||||
export const GET: APIRoute = async ({ request, cookies }) => {
|
||||
try {
|
||||
// Check authentication
|
||||
const supabase = createSupabaseServerClient(cookies);
|
||||
const { data: { session }, error: sessionError } = await supabase.auth.getSession();
|
||||
|
||||
if (sessionError || !session) {
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
error: 'Authentication required'
|
||||
}), {
|
||||
status: 401,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
|
||||
// Use admin client to bypass RLS
|
||||
const serviceClient = createSupabaseAdmin();
|
||||
|
||||
// Get recent activity data
|
||||
const [eventsResult, ticketsResult, usersResult] = await Promise.all([
|
||||
serviceClient.from('events').select('*, organizations(name)').order('created_at', { ascending: false }).limit(5),
|
||||
serviceClient.from('tickets').select('*, events(title)').order('created_at', { ascending: false }).limit(10),
|
||||
serviceClient.from('users').select('*, organizations(name)').order('created_at', { ascending: false }).limit(5)
|
||||
]);
|
||||
|
||||
const activities = [];
|
||||
|
||||
// Add recent events
|
||||
if (eventsResult.data) {
|
||||
eventsResult.data.forEach(event => {
|
||||
activities.push({
|
||||
type: 'event',
|
||||
title: `New event created: ${event.title}`,
|
||||
subtitle: `by ${event.organizations?.name || 'Unknown'}`,
|
||||
time: new Date(event.created_at),
|
||||
icon: '📅'
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Add recent users
|
||||
if (usersResult.data) {
|
||||
usersResult.data.forEach(user => {
|
||||
activities.push({
|
||||
type: 'user',
|
||||
title: `New user registered: ${user.name || user.email}`,
|
||||
subtitle: `Organization: ${user.organizations?.name || 'None'}`,
|
||||
time: new Date(user.created_at),
|
||||
icon: '👤'
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Add recent tickets
|
||||
if (ticketsResult.data) {
|
||||
ticketsResult.data.slice(0, 5).forEach(ticket => {
|
||||
activities.push({
|
||||
type: 'ticket',
|
||||
title: `Ticket sold: $${ticket.price}`,
|
||||
subtitle: `for ${ticket.events?.title || 'Unknown Event'}`,
|
||||
time: new Date(ticket.created_at),
|
||||
icon: '🎫'
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Sort by time and take the most recent 10
|
||||
activities.sort((a, b) => b.time - a.time);
|
||||
const recentActivities = activities.slice(0, 10);
|
||||
|
||||
return new Response(JSON.stringify({
|
||||
success: true,
|
||||
data: recentActivities
|
||||
}), {
|
||||
status: 200,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Admin activity error:', error);
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
error: 'Failed to load recent activity'
|
||||
}), {
|
||||
status: 500,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
};
|
||||
73
src/pages/api/admin/admin-events.ts
Normal file
73
src/pages/api/admin/admin-events.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import type { APIRoute } from 'astro';
|
||||
import { createSupabaseServerClient } from '../../../lib/supabase-ssr';
|
||||
import { createSupabaseAdmin } from '../../../lib/supabase-admin';
|
||||
|
||||
export const GET: APIRoute = async ({ request, cookies }) => {
|
||||
try {
|
||||
// Check authentication
|
||||
const supabase = createSupabaseServerClient(cookies);
|
||||
const { data: { session }, error: sessionError } = await supabase.auth.getSession();
|
||||
|
||||
if (sessionError || !session) {
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
error: 'Authentication required'
|
||||
}), {
|
||||
status: 401,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
|
||||
// Use admin client to bypass RLS
|
||||
const serviceClient = createSupabaseAdmin();
|
||||
|
||||
// Get events with organization and user details
|
||||
const { data: events, error } = await serviceClient
|
||||
.from('events')
|
||||
.select(`
|
||||
*,
|
||||
organizations(name),
|
||||
users!events_created_by_fkey(name, email)
|
||||
`)
|
||||
.order('created_at', { ascending: false });
|
||||
|
||||
if (error) {
|
||||
console.error('Events query error:', error);
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
error: 'Failed to fetch events'
|
||||
}), {
|
||||
status: 500,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
|
||||
// Get ticket type counts for each event
|
||||
if (events) {
|
||||
for (const event of events) {
|
||||
const { data: ticketTypes } = await serviceClient
|
||||
.from('ticket_types')
|
||||
.select('id')
|
||||
.eq('event_id', event.id);
|
||||
event.ticket_type_count = ticketTypes ? ticketTypes.length : 0;
|
||||
}
|
||||
}
|
||||
|
||||
return new Response(JSON.stringify({
|
||||
success: true,
|
||||
data: events || []
|
||||
}), {
|
||||
status: 200,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Admin events error:', error);
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
error: 'Failed to load events'
|
||||
}), {
|
||||
status: 500,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
};
|
||||
73
src/pages/api/admin/admin-tickets.ts
Normal file
73
src/pages/api/admin/admin-tickets.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import type { APIRoute } from 'astro';
|
||||
import { createSupabaseServerClient } from '../../../lib/supabase-ssr';
|
||||
import { createSupabaseAdmin } from '../../../lib/supabase-admin';
|
||||
|
||||
export const GET: APIRoute = async ({ request, cookies }) => {
|
||||
try {
|
||||
// Check authentication
|
||||
const supabase = createSupabaseServerClient(cookies);
|
||||
const { data: { session }, error: sessionError } = await supabase.auth.getSession();
|
||||
|
||||
if (sessionError || !session) {
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
error: 'Authentication required'
|
||||
}), {
|
||||
status: 401,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
|
||||
// Use admin client to bypass RLS
|
||||
const serviceClient = createSupabaseAdmin();
|
||||
|
||||
// Get tickets with event and organization details
|
||||
const { data: tickets, error } = await serviceClient
|
||||
.from('tickets')
|
||||
.select(`
|
||||
*,
|
||||
ticket_types (
|
||||
name,
|
||||
price
|
||||
),
|
||||
events (
|
||||
title,
|
||||
venue,
|
||||
start_time,
|
||||
organizations (
|
||||
name
|
||||
)
|
||||
)
|
||||
`)
|
||||
.order('created_at', { ascending: false })
|
||||
.limit(100);
|
||||
|
||||
if (error) {
|
||||
console.error('Tickets query error:', error);
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
error: 'Failed to fetch tickets'
|
||||
}), {
|
||||
status: 500,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
|
||||
return new Response(JSON.stringify({
|
||||
success: true,
|
||||
data: tickets || []
|
||||
}), {
|
||||
status: 200,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Admin tickets error:', error);
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
error: 'Failed to load tickets'
|
||||
}), {
|
||||
status: 500,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
};
|
||||
69
src/pages/api/admin/organizations.ts
Normal file
69
src/pages/api/admin/organizations.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import type { APIRoute } from 'astro';
|
||||
import { createSupabaseServerClient } from '../../../lib/supabase-ssr';
|
||||
import { createSupabaseAdmin } from '../../../lib/supabase-admin';
|
||||
|
||||
export const GET: APIRoute = async ({ request, cookies }) => {
|
||||
try {
|
||||
// Check authentication
|
||||
const supabase = createSupabaseServerClient(cookies);
|
||||
const { data: { session }, error: sessionError } = await supabase.auth.getSession();
|
||||
|
||||
if (sessionError || !session) {
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
error: 'Authentication required'
|
||||
}), {
|
||||
status: 401,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
|
||||
// Use admin client to bypass RLS
|
||||
const serviceClient = createSupabaseAdmin();
|
||||
|
||||
// Get organizations
|
||||
const { data: orgs, error } = await serviceClient
|
||||
.from('organizations')
|
||||
.select('*')
|
||||
.order('created_at', { ascending: false });
|
||||
|
||||
if (error) {
|
||||
console.error('Organizations query error:', error);
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
error: 'Failed to fetch organizations'
|
||||
}), {
|
||||
status: 500,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
|
||||
// Get user counts for each organization
|
||||
if (orgs) {
|
||||
for (const org of orgs) {
|
||||
const { data: users } = await serviceClient
|
||||
.from('users')
|
||||
.select('id')
|
||||
.eq('organization_id', org.id);
|
||||
org.user_count = users ? users.length : 0;
|
||||
}
|
||||
}
|
||||
|
||||
return new Response(JSON.stringify({
|
||||
success: true,
|
||||
data: orgs || []
|
||||
}), {
|
||||
status: 200,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Admin organizations error:', error);
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
error: 'Failed to load organizations'
|
||||
}), {
|
||||
status: 500,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
};
|
||||
64
src/pages/api/admin/stats.ts
Normal file
64
src/pages/api/admin/stats.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import type { APIRoute } from 'astro';
|
||||
import { createSupabaseServerClient } from '../../../lib/supabase-ssr';
|
||||
import { createSupabaseAdmin } from '../../../lib/supabase-admin';
|
||||
|
||||
export const GET: APIRoute = async ({ request, cookies }) => {
|
||||
try {
|
||||
// Check authentication
|
||||
const supabase = createSupabaseServerClient(cookies);
|
||||
const { data: { session }, error: sessionError } = await supabase.auth.getSession();
|
||||
|
||||
if (sessionError || !session) {
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
error: 'Authentication required'
|
||||
}), {
|
||||
status: 401,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
|
||||
// Use admin client to bypass RLS
|
||||
const serviceClient = createSupabaseAdmin();
|
||||
|
||||
// Get platform statistics
|
||||
const [organizationsResult, eventsResult, ticketsResult, usersResult] = await Promise.all([
|
||||
serviceClient.from('organizations').select('id'),
|
||||
serviceClient.from('events').select('id'),
|
||||
serviceClient.from('tickets').select('price'),
|
||||
serviceClient.from('users').select('id')
|
||||
]);
|
||||
|
||||
const organizations = organizationsResult.data?.length || 0;
|
||||
const events = eventsResult.data?.length || 0;
|
||||
const tickets = ticketsResult.data || [];
|
||||
const users = usersResult.data?.length || 0;
|
||||
const ticketCount = tickets.length;
|
||||
const revenue = tickets.reduce((sum, ticket) => sum + (ticket.price || 0), 0);
|
||||
const platformFees = revenue * 0.05; // Assuming 5% platform fee
|
||||
|
||||
return new Response(JSON.stringify({
|
||||
success: true,
|
||||
data: {
|
||||
organizations,
|
||||
events,
|
||||
tickets: ticketCount,
|
||||
revenue,
|
||||
platformFees,
|
||||
users
|
||||
}
|
||||
}), {
|
||||
status: 200,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Admin stats error:', error);
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
error: 'Failed to load platform statistics'
|
||||
}), {
|
||||
status: 500,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
};
|
||||
89
src/pages/api/user/events.ts
Normal file
89
src/pages/api/user/events.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import type { APIRoute } from 'astro';
|
||||
import { verifyAuth } from '../../../lib/auth';
|
||||
import { createSupabaseServerClient } from '../../../lib/supabase-ssr';
|
||||
|
||||
export const GET: APIRoute = async ({ cookies }) => {
|
||||
try {
|
||||
// Verify authentication using server-side auth
|
||||
const auth = await verifyAuth(cookies);
|
||||
|
||||
if (!auth) {
|
||||
return new Response(JSON.stringify({
|
||||
error: 'Not authenticated'
|
||||
}), {
|
||||
status: 401,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
|
||||
// Create Supabase client for server-side queries
|
||||
const supabase = createSupabaseServerClient(cookies);
|
||||
|
||||
// Get user profile to check if they're admin
|
||||
const { data: userProfile, error: profileError } = await supabase
|
||||
.from('users')
|
||||
.select('role, organization_id')
|
||||
.eq('id', auth.user.id)
|
||||
.single();
|
||||
|
||||
if (profileError) {
|
||||
console.error('Error loading user profile:', profileError);
|
||||
return new Response(JSON.stringify({
|
||||
error: 'Error loading user profile'
|
||||
}), {
|
||||
status: 500,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
|
||||
// Check if user is admin or has organization_id
|
||||
const isAdmin = userProfile?.role === 'admin';
|
||||
if (!isAdmin && !userProfile?.organization_id) {
|
||||
return new Response(JSON.stringify({
|
||||
success: true,
|
||||
data: []
|
||||
}), {
|
||||
status: 200,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
|
||||
// Load events based on user permissions
|
||||
let query = supabase.from('events').select('*');
|
||||
|
||||
if (!isAdmin) {
|
||||
// Regular users see only their organization's events
|
||||
query = query.eq('organization_id', userProfile.organization_id);
|
||||
}
|
||||
// Admins see all events (no filter)
|
||||
|
||||
const { data: events, error } = await query.order('created_at', { ascending: false });
|
||||
|
||||
if (error) {
|
||||
console.error('Error loading events:', error);
|
||||
return new Response(JSON.stringify({
|
||||
error: 'Error loading events'
|
||||
}), {
|
||||
status: 500,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
|
||||
return new Response(JSON.stringify({
|
||||
success: true,
|
||||
data: events || []
|
||||
}), {
|
||||
status: 200,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('User events API error:', error);
|
||||
return new Response(JSON.stringify({
|
||||
error: 'Internal server error'
|
||||
}), {
|
||||
status: 500,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -23,7 +23,7 @@ const search = url.searchParams.get('search');
|
||||
---
|
||||
|
||||
<Layout title="Event Calendar - Black Canyon Tickets">
|
||||
<div class="min-h-screen">
|
||||
<div class="min-h-screen" data-theme-background>
|
||||
<!-- Hero Section with Dynamic Background -->
|
||||
<section id="hero-section" class="relative overflow-hidden sticky top-0 z-40" style="background: var(--bg-gradient);">
|
||||
<PublicHeader showCalendarNav={true} />
|
||||
@@ -406,6 +406,9 @@ const search = url.searchParams.get('search');
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
/* Import glassmorphism theme styles */
|
||||
@import '../styles/glassmorphism.css';
|
||||
|
||||
/* Custom animations */
|
||||
@keyframes float {
|
||||
0%, 100% { transform: translateY(0px); }
|
||||
@@ -502,14 +505,46 @@ const search = url.searchParams.get('search');
|
||||
<script>
|
||||
console.log('=== CALENDAR SCRIPT STARTING ===');
|
||||
|
||||
// Simple theme toggle function
|
||||
window.toggleTheme = function() {
|
||||
const html = document.documentElement;
|
||||
const currentTheme = html.getAttribute('data-theme') || 'light';
|
||||
const newTheme = currentTheme === 'light' ? 'dark' : 'light';
|
||||
// Theme management system
|
||||
function getCurrentTheme() {
|
||||
if (typeof window === 'undefined') return 'dark';
|
||||
|
||||
html.setAttribute('data-theme', newTheme);
|
||||
localStorage.setItem('theme', newTheme);
|
||||
const savedTheme = localStorage.getItem('theme');
|
||||
if (savedTheme) return savedTheme;
|
||||
|
||||
return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
||||
}
|
||||
|
||||
function setTheme(theme) {
|
||||
if (typeof window === 'undefined') return;
|
||||
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
document.documentElement.classList.remove('light', 'dark');
|
||||
document.documentElement.classList.add(theme);
|
||||
|
||||
document.body.classList.remove('light', 'dark');
|
||||
document.body.classList.add(theme);
|
||||
|
||||
localStorage.setItem('theme', theme);
|
||||
|
||||
// Dispatch theme change event
|
||||
window.dispatchEvent(new CustomEvent('themeChanged', {
|
||||
detail: { theme }
|
||||
}));
|
||||
}
|
||||
|
||||
function initializeTheme() {
|
||||
if (typeof window === 'undefined') return;
|
||||
|
||||
const savedTheme = getCurrentTheme();
|
||||
setTheme(savedTheme);
|
||||
}
|
||||
|
||||
// Theme toggle function
|
||||
window.toggleTheme = function() {
|
||||
const currentTheme = getCurrentTheme();
|
||||
const newTheme = currentTheme === 'light' ? 'dark' : 'light';
|
||||
setTheme(newTheme);
|
||||
|
||||
// Update icon
|
||||
const toggle = document.getElementById('theme-toggle');
|
||||
@@ -523,12 +558,30 @@ const search = url.searchParams.get('search');
|
||||
}
|
||||
|
||||
console.log('Theme toggled to:', newTheme);
|
||||
return newTheme;
|
||||
};
|
||||
|
||||
// Initialize theme on page load
|
||||
const savedTheme = localStorage.getItem('theme') ||
|
||||
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
|
||||
document.documentElement.setAttribute('data-theme', savedTheme);
|
||||
// Initialize theme immediately
|
||||
initializeTheme();
|
||||
|
||||
// Handle theme changes and update background
|
||||
function updateBackground() {
|
||||
const theme = getCurrentTheme();
|
||||
const bgElement = document.querySelector('[data-theme-background]');
|
||||
if (bgElement) {
|
||||
if (theme === 'light') {
|
||||
bgElement.style.background = '#f8fafc';
|
||||
} else {
|
||||
bgElement.style.background = 'var(--bg-gradient)';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Listen for theme changes
|
||||
window.addEventListener('themeChanged', updateBackground);
|
||||
|
||||
// Initial background update
|
||||
updateBackground();
|
||||
|
||||
// Import geolocation utilities - get from environment or default to empty
|
||||
const MAPBOX_TOKEN = '';
|
||||
|
||||
@@ -142,7 +142,7 @@ if (!auth) {
|
||||
<span id="view-text">Calendar View</span>
|
||||
</button>
|
||||
<a
|
||||
href="/calendar"
|
||||
href="/settings/fees"
|
||||
class="glass-card px-6 py-3 rounded-xl text-sm font-medium transition-all duration-200 shadow-lg flex items-center gap-2 hover:shadow-xl hover:scale-105 hover:opacity-80"
|
||||
style="color: var(--glass-text-primary);"
|
||||
>
|
||||
@@ -291,6 +291,7 @@ if (!auth) {
|
||||
|
||||
<script>
|
||||
import { supabase } from '../lib/supabase';
|
||||
import { ApiRouter } from '../lib/api-router';
|
||||
|
||||
const eventsContainer = document.getElementById('events-container');
|
||||
const loading = document.getElementById('loading');
|
||||
@@ -437,21 +438,8 @@ if (!auth) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Load events based on user permissions
|
||||
let query = supabase.from('events').select('*');
|
||||
|
||||
if (!isAdmin) {
|
||||
// Regular users see only their organization's events
|
||||
query = query.eq('organization_id', userProfile.organization_id);
|
||||
}
|
||||
// Admins see all events (no filter)
|
||||
|
||||
const { data: events, error } = await query.order('created_at', { ascending: false });
|
||||
|
||||
if (error) {
|
||||
// Error loading events from database
|
||||
throw error;
|
||||
}
|
||||
// Load events using the API router to avoid CORS issues
|
||||
const events = await ApiRouter.loadUserEvents();
|
||||
|
||||
// Successfully loaded events
|
||||
allEvents = events || [];
|
||||
|
||||
Reference in New Issue
Block a user