Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 107 additions & 19 deletions app/api/hackathons/[id]/register/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { NextRequest, NextResponse } from 'next/server'
import { createClient } from '@/lib/supabase/server'
import { createClient as createSupabaseClient } from '@supabase/supabase-js'

export async function POST(
request: NextRequest,
Expand Down Expand Up @@ -62,7 +63,7 @@ export async function POST(
.eq('user_id', user.id)
.eq('activity_type', 'hackathon')
.eq('activity_id', hackathon.id.toString())
.single()
.maybeSingle()

if (existingRegistration) {
return NextResponse.json(
Expand Down Expand Up @@ -101,14 +102,45 @@ export async function POST(
)
}

// Increment registered count
const { error: updateError } = await supabase
// Increment registered count using service role client to bypass RLS
console.log('Attempting to increment registered count:', {
hackathonId: hackathon.id,
currentCount: hackathon.registered,
newCount: (hackathon.registered || 0) + 1
})

// Create admin client with service role key to bypass RLS
const supabaseAdmin = createSupabaseClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!
)

const { data: updatedHackathon, error: updateError } = await supabaseAdmin
.from('hackathons')
.update({ registered: (hackathon.registered || 0) + 1 })
.update({
registered: (hackathon.registered || 0) + 1,
updated_at: new Date().toISOString()
})
.eq('id', hackathon.id)
.select('registered')
.single()

if (updateError) {
console.error('Error updating registered count:', updateError)
// Don't fail the registration if count update fails
} else if (updatedHackathon) {
console.log('Successfully updated registered count to:', updatedHackathon.registered)
} else {
console.error('No hackathon returned from update')
}

// Track registration in analytics
try {
const { AnalyticsService } = await import('@/lib/services/analytics-service')
await AnalyticsService.trackHackathonRegistration(hackathon.id)
} catch (error) {
console.error('Error tracking registration in analytics:', error)
// Don't fail the registration if analytics tracking fails
}

return NextResponse.json({
Expand Down Expand Up @@ -155,30 +187,86 @@ export async function DELETE(
)
}

// Delete registration from master_registrations
const { error: deleteError } = await supabase
.from('master_registrations')
.delete()
.eq('user_id', user.id)
.eq('activity_type', 'hackathon')
.eq('activity_id', hackathon.id.toString())
console.log('Attempting to unregister:', {
userId: user.id,
hackathonId: hackathon.id,
activityType: 'hackathon',
activityId: hackathon.id.toString()
})

if (deleteError) {
console.error('Error deleting registration:', deleteError)
return NextResponse.json(
{ error: 'Failed to unregister from hackathon' },
{ status: 500 }
// Use the master registrations service which should handle RLS properly
try {
const { masterRegistrationsService } = await import('@/lib/services/master-registrations')
await masterRegistrationsService.unregister(
user.id,
'hackathon',
hackathon.id.toString()
)
console.log('Successfully unregistered using service')
} catch (serviceError) {
console.error('Error using service, trying direct delete:', serviceError)

// Fallback to direct delete if service fails
const { data: deletedData, error: deleteError } = await supabase
.from('master_registrations')
.delete()
.eq('user_id', user.id)
.eq('activity_type', 'hackathon')
.eq('activity_id', hackathon.id.toString())
.select()

if (deleteError) {
console.error('Error deleting registration:', deleteError)
return NextResponse.json(
{ error: 'Failed to unregister from hackathon' },
{ status: 500 }
)
}

console.log('Direct delete result:', {
deletedCount: deletedData?.length || 0,
deletedData: deletedData
})

if (!deletedData || deletedData.length === 0) {
console.log('No registration found to delete')
return NextResponse.json({
success: true,
message: 'No active registration found',
})
}
}

// Decrement registered count
const { error: updateError } = await supabase
// Decrement registered count using service role client to bypass RLS
console.log('Attempting to decrement registered count:', {
hackathonId: hackathon.id,
currentCount: hackathon.registered,
newCount: Math.max(0, (hackathon.registered || 0) - 1)
})

// Create admin client with service role key to bypass RLS
const supabaseAdmin = createSupabaseClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!
)

const { data: updatedHackathon, error: updateError } = await supabaseAdmin
.from('hackathons')
.update({ registered: Math.max(0, (hackathon.registered || 0) - 1) })
.update({
registered: Math.max(0, (hackathon.registered || 0) - 1),
updated_at: new Date().toISOString()
})
.eq('id', hackathon.id)
.select('registered')
.single()

if (updateError) {
console.error('Error updating registered count:', updateError)
// Don't fail the unregistration if count update fails
} else if (updatedHackathon) {
console.log('Successfully updated registered count to:', updatedHackathon.registered)
} else {
console.log('No hackathon returned from update')
}

return NextResponse.json({
Expand Down
27 changes: 23 additions & 4 deletions app/api/hackathons/[id]/track-click/route.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { NextRequest, NextResponse } from 'next/server'
import { createClient } from '@/lib/supabase/server'
import { createClient as createSupabaseClient } from '@supabase/supabase-js'

export async function POST(
request: NextRequest,
_request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
Expand All @@ -23,11 +24,27 @@ export async function POST(
)
}

// Increment click count
const { error: updateError } = await supabase
console.log('Tracking click for hackathon:', {
hackathonId: hackathon.id,
currentClicks: hackathon.clicks,
newClicks: (hackathon.clicks || 0) + 1
})

// Increment click count using service role client to bypass RLS
const supabaseAdmin = createSupabaseClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!
)

const { data: updatedHackathon, error: updateError } = await supabaseAdmin
.from('hackathons')
.update({ clicks: (hackathon.clicks || 0) + 1 })
.update({
clicks: (hackathon.clicks || 0) + 1,
updated_at: new Date().toISOString()
})
.eq('id', hackathon.id)
.select('clicks')
.single()

if (updateError) {
console.error('Error updating click count:', updateError)
Expand All @@ -37,6 +54,8 @@ export async function POST(
)
}

console.log('Successfully updated click count to:', updatedHackathon?.clicks)

// Update company analytics if hackathon has a company
if (hackathon.company_id) {
const today = new Date().toISOString().split('T')[0]
Expand Down
27 changes: 23 additions & 4 deletions app/api/hackathons/[id]/track-view/route.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { NextRequest, NextResponse } from 'next/server'
import { createClient } from '@/lib/supabase/server'
import { createClient as createSupabaseClient } from '@supabase/supabase-js'

export async function POST(
request: NextRequest,
_request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
try {
Expand All @@ -23,11 +24,27 @@ export async function POST(
)
}

// Increment view count
const { error: updateError } = await supabase
console.log('Tracking view for hackathon:', {
hackathonId: hackathon.id,
currentViews: hackathon.views,
newViews: (hackathon.views || 0) + 1
})

// Increment view count using service role client to bypass RLS
const supabaseAdmin = createSupabaseClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!
)

const { data: updatedHackathon, error: updateError } = await supabaseAdmin
.from('hackathons')
.update({ views: (hackathon.views || 0) + 1 })
.update({
views: (hackathon.views || 0) + 1,
updated_at: new Date().toISOString()
})
.eq('id', hackathon.id)
.select('views')
.single()

if (updateError) {
console.error('Error updating view count:', updateError)
Expand All @@ -37,6 +54,8 @@ export async function POST(
)
}

console.log('Successfully updated view count to:', updatedHackathon?.views)

// Update company analytics if hackathon has a company
if (hackathon.company_id) {
const today = new Date().toISOString().split('T')[0]
Expand Down
43 changes: 29 additions & 14 deletions app/hackathons/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ export default function HackathonDetailPage() {
const checkRegistrationStatus = async () => {
if (!isAuthenticated || !hackathon?.id) {
setCheckingRegistration(false)
setIsRegistered(false)
return
}

Expand All @@ -150,20 +151,30 @@ export default function HackathonDetailPage() {

if (!user) {
setCheckingRegistration(false)
setIsRegistered(false)
return
}

const { data } = await supabase
// Check for this specific hackathon registration
const { data, error } = await supabase
.from('master_registrations')
.select('id')
.eq('user_id', user.id)
.eq('activity_type', 'hackathon')
.eq('activity_id', hackathon.id.toString())
.single()
.maybeSingle()

// If there's an error (other than not found), log it
if (error && error.code !== 'PGRST116') {
console.error('Error checking registration:', error)
}

// Set registration status based on whether data exists
setIsRegistered(!!data)
} catch (error) {
console.error('Error checking registration:', error)
// On error, assume not registered
setIsRegistered(false)
} finally {
setCheckingRegistration(false)
}
Expand All @@ -187,19 +198,21 @@ export default function HackathonDetailPage() {
},
})

const result = await response.json()

if (!response.ok) {
const errorData = await response.json()
throw new Error(errorData.error || 'Failed to register')
throw new Error(result.error || 'Failed to register')
}

toast.success('Successfully registered for the hackathon!')
// Update state immediately
setIsRegistered(true)
setCheckingRegistration(false)
toast.success('Successfully registered for the hackathon!')

// Refresh hackathon data to update registered count
window.location.reload()
// Force a hard reload to clear any cached state
window.location.href = window.location.href
} catch (err) {
toast.error(err instanceof Error ? err.message : 'Failed to register')
} finally {
setRegistering(false)
}
}
Expand All @@ -213,19 +226,21 @@ export default function HackathonDetailPage() {
method: 'DELETE',
})

const result = await response.json()

if (!response.ok) {
const errorData = await response.json()
throw new Error(errorData.error || 'Failed to unregister')
throw new Error(result.error || 'Failed to unregister')
}

toast.success('Successfully unregistered from the hackathon')
// Update state immediately
setIsRegistered(false)
setCheckingRegistration(false)
toast.success('Successfully unregistered from the hackathon')

// Refresh hackathon data to update registered count
window.location.reload()
// Force a hard reload to clear any cached state
window.location.href = window.location.href
} catch (err) {
toast.error(err instanceof Error ? err.message : 'Failed to unregister')
} finally {
setRegistering(false)
}
}
Expand Down
Loading
Loading