From 2082f7912db0663d8927b6b3772d497b12b7eb1b Mon Sep 17 00:00:00 2001 From: Akshay Date: Wed, 19 Nov 2025 14:00:18 +0530 Subject: [PATCH 1/2] feat(hackathons): Update hackathon data schema and display fields - Consolidate start_date and end_date into single date field - Add registration_deadline field for tracking registration cutoff - Make location, mode, organizer, and team size fields optional - Replace registered_teams and max_teams with registered and capacity fields - Add total_registrations and duration fields to hackathon interface - Update date display to show full year and handle invalid dates with "TBA" fallback - Change duration display from calculated days to registration deadline or duration field - Update location display to prioritize location over mode with fallback - Simplify team registration display to show total registered count - Improve date validation with isNaN checks before formatting --- app/companies/[slug]/hackathons/page.tsx | 47 +++++++++++++----------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/app/companies/[slug]/hackathons/page.tsx b/app/companies/[slug]/hackathons/page.tsx index a9e423c2..dbba5f81 100644 --- a/app/companies/[slug]/hackathons/page.tsx +++ b/app/companies/[slug]/hackathons/page.tsx @@ -31,18 +31,20 @@ interface Hackathon { description: string excerpt: string image?: string - start_date: string - end_date: string - location: string - mode: string + date: string + registration_deadline?: string + location?: string + mode?: string prize_pool?: string - max_team_size: number - min_team_size: number - registered_teams: number - max_teams: number + max_team_size?: number + min_team_size?: number + registered?: number + capacity?: number status: string tags: string[] - organizer: string + organizer?: string + total_registrations?: number + duration?: string } export default function CompanyHackathonsPage() { @@ -336,27 +338,30 @@ export default function CompanyHackathonsPage() {
- {new Date(hackathon.start_date).toLocaleDateString("en-US", { - month: "short", - day: "numeric", - })} + {hackathon.date && !isNaN(new Date(hackathon.date).getTime()) + ? new Date(hackathon.date).toLocaleDateString("en-US", { + month: "short", + day: "numeric", + year: "numeric", + }) + : "TBA"}
- {Math.ceil( - (new Date(hackathon.end_date).getTime() - - new Date(hackathon.start_date).getTime()) / - (1000 * 60 * 60 * 24) - )}{" "} - days + {hackathon.registration_deadline && !isNaN(new Date(hackathon.registration_deadline).getTime()) + ? `Reg: ${new Date(hackathon.registration_deadline).toLocaleDateString("en-US", { + month: "short", + day: "numeric", + })}` + : hackathon.duration || "TBA"}
- {hackathon.mode} + {hackathon.location || hackathon.mode || "TBA"}
- {hackathon.registered_teams}/{hackathon.max_teams} teams + {hackathon.registered || 0} registered
From 1a7b0d5656b28efdfe9907410f62ac0667f931aa Mon Sep 17 00:00:00 2001 From: Akshay Date: Wed, 19 Nov 2025 14:35:49 +0530 Subject: [PATCH 2/2] feat(companies): Add hackathons count and total participants to company profiles - Add approved hackathons count to company API endpoint and service layer - Calculate total participants across both events and hackathons - Update CompanyCard to display hackathons count alongside events - Update CompanyProfile stats to show approved hackathons and total participants - Add approved_hackathons_count field to Company type definition - Rename "Registrations" label to "Participants" for clarity in company profile - Enrich company data with calculated fields in both API and service methods --- app/api/companies/[slug]/route.ts | 39 ++++++++++++++++++++----- components/companies/CompanyCard.tsx | 14 ++++++--- components/companies/CompanyProfile.tsx | 6 ++-- lib/services/company-service.ts | 27 ++++++++++++++++- types/company.ts | 1 + 5 files changed, 72 insertions(+), 15 deletions(-) diff --git a/app/api/companies/[slug]/route.ts b/app/api/companies/[slug]/route.ts index a8c5a38d..f1e03869 100644 --- a/app/api/companies/[slug]/route.ts +++ b/app/api/companies/[slug]/route.ts @@ -71,24 +71,49 @@ export async function GET( } } - // Get count of approved events for this company + // Get count of approved events and hackathons for this company const supabase = await createClient() - const { count: approvedCount } = await supabase + const { count: approvedEventsCount } = await supabase .from('events') .select('*', { count: 'exact', head: true }) .eq('company_id', company.id) .eq('approval_status', 'approved') - // Add approved_events_count to company object - const companyWithApprovedCount = { + const { count: approvedHackathonsCount } = await supabase + .from('hackathons') + .select('*', { count: 'exact', head: true }) + .eq('company_id', company.id) + .eq('approval_status', 'approved') + + // Get total participants from events + const { data: events } = await supabase + .from('events') + .select('registered') + .eq('company_id', company.id) + .eq('approval_status', 'approved') + + // Get total participants from hackathons + const { data: hackathons } = await supabase + .from('hackathons') + .select('registered') + .eq('company_id', company.id) + .eq('approval_status', 'approved') + + const eventParticipants = events?.reduce((sum, event) => sum + (event.registered || 0), 0) || 0 + const hackathonParticipants = hackathons?.reduce((sum, hackathon) => sum + (hackathon.registered || 0), 0) || 0 + + // Add calculated fields to company object + const enrichedCompany = { ...company, - approved_events_count: approvedCount || 0, + approved_events_count: approvedEventsCount || 0, + approved_hackathons_count: approvedHackathonsCount || 0, + total_participants: eventParticipants + hackathonParticipants, } // Cache the result - await UnifiedCache.set(cacheKey, { company: companyWithApprovedCount }, 'API_STANDARD') + await UnifiedCache.set(cacheKey, { company: enrichedCompany }, 'API_STANDARD') - return UnifiedCache.createResponse({ company: companyWithApprovedCount }, 'API_STANDARD') + return UnifiedCache.createResponse({ company: enrichedCompany }, 'API_STANDARD') } catch (error) { console.error('Error in GET /api/companies/[slug]:', error) diff --git a/components/companies/CompanyCard.tsx b/components/companies/CompanyCard.tsx index 675f1a45..303c953e 100644 --- a/components/companies/CompanyCard.tsx +++ b/components/companies/CompanyCard.tsx @@ -79,13 +79,19 @@ export function CompanyCard({ {showStats && (
-
- - {company.approved_events_count ?? company.total_events ?? 0} events +
+
+ + {company.approved_events_count ?? company.total_events ?? 0} events +
+
+ + {company.approved_hackathons_count ?? company.total_hackathons ?? 0} hackathons +
- {company.total_participants} participants + {company.total_participants ?? 0} participants
diff --git a/components/companies/CompanyProfile.tsx b/components/companies/CompanyProfile.tsx index 6034f094..81d55754 100644 --- a/components/companies/CompanyProfile.tsx +++ b/components/companies/CompanyProfile.tsx @@ -126,15 +126,15 @@ export function CompanyProfile({ company, isOwner = false, className }: CompanyP

- {company.total_hackathons || 0} + {company.approved_hackathons_count ?? company.total_hackathons ?? 0}

Hackathons

- {company.total_registrations || 0} + {company.total_participants ?? 0}

-

Registrations

+

Participants

diff --git a/lib/services/company-service.ts b/lib/services/company-service.ts index a5f177e6..4fb910a9 100644 --- a/lib/services/company-service.ts +++ b/lib/services/company-service.ts @@ -371,7 +371,7 @@ class CompanyService { ) } - // For each company, get the count of approved events + // For each company, get the count of approved events, hackathons, and total participants const companiesWithApprovedCount = await Promise.all( (companies || []).map(async (company) => { const { count: approvedCount } = await supabase @@ -380,9 +380,34 @@ class CompanyService { .eq('company_id', company.id) .eq('approval_status', 'approved') + const { count: hackathonsCount } = await supabase + .from('hackathons') + .select('*', { count: 'exact', head: true }) + .eq('company_id', company.id) + .eq('approval_status', 'approved') + + // Get total participants from events + const { data: events } = await supabase + .from('events') + .select('registered') + .eq('company_id', company.id) + .eq('approval_status', 'approved') + + // Get total participants from hackathons + const { data: hackathons } = await supabase + .from('hackathons') + .select('registered') + .eq('company_id', company.id) + .eq('approval_status', 'approved') + + const eventParticipants = events?.reduce((sum, event) => sum + (event.registered || 0), 0) || 0 + const hackathonParticipants = hackathons?.reduce((sum, hackathon) => sum + (hackathon.registered || 0), 0) || 0 + return { ...company, approved_events_count: approvedCount || 0, + approved_hackathons_count: hackathonsCount || 0, + total_participants: eventParticipants + hackathonParticipants, } }) ) diff --git a/types/company.ts b/types/company.ts index c60ae63f..3a7a0848 100644 --- a/types/company.ts +++ b/types/company.ts @@ -44,6 +44,7 @@ export interface Company { total_participants: number total_registrations: number approved_events_count?: number // Count of approved events only (for public display) + approved_hackathons_count?: number // Count of approved hackathons only (for public display) } export interface CompanyAddress {