Files
root-org/src/lib/api/sponsors.ts

366 lines
9.2 KiB
TypeScript

import type { SupabaseClient } from '@supabase/supabase-js';
import type { SponsorTier, Sponsor, SponsorDeliverable } from '$lib/supabase/types';
import { createLogger } from '$lib/utils/logger';
const log = createLogger('api.sponsors');
// Helper to cast supabase for tables not yet in generated types
function db(supabase: SupabaseClient) {
return supabase as any;
}
export const SPONSOR_STATUSES = ['prospect', 'contacted', 'confirmed', 'declined', 'active'] as const;
export type SponsorStatus = (typeof SPONSOR_STATUSES)[number];
export const STATUS_LABELS: Record<string, string> = {
prospect: 'Prospect',
contacted: 'Contacted',
confirmed: 'Confirmed',
declined: 'Declined',
active: 'Active',
};
export const STATUS_COLORS: Record<string, string> = {
prospect: '#94a3b8',
contacted: '#F59E0B',
confirmed: '#10B981',
declined: '#EF4444',
active: '#6366f1',
};
// ============================================================
// Sponsor Tiers
// ============================================================
export async function fetchSponsorTiers(
supabase: SupabaseClient,
departmentId: string
): Promise<SponsorTier[]> {
const { data, error } = await db(supabase)
.from('sponsor_tiers')
.select('*')
.eq('department_id', departmentId)
.order('sort_order');
if (error) {
log.error('fetchSponsorTiers failed', { error, data: { departmentId } });
throw error;
}
return (data ?? []) as SponsorTier[];
}
export async function createSponsorTier(
supabase: SupabaseClient,
departmentId: string,
name: string,
amount?: number,
color?: string
): Promise<SponsorTier> {
const { data, error } = await db(supabase)
.from('sponsor_tiers')
.insert({
department_id: departmentId,
name,
amount: amount ?? 0,
color: color ?? '#F59E0B',
})
.select()
.single();
if (error) {
log.error('createSponsorTier failed', { error, data: { departmentId, name } });
throw error;
}
return data as SponsorTier;
}
export async function updateSponsorTier(
supabase: SupabaseClient,
tierId: string,
params: Partial<Pick<SponsorTier, 'name' | 'amount' | 'color' | 'sort_order'>>
): Promise<SponsorTier> {
const { data, error } = await db(supabase)
.from('sponsor_tiers')
.update(params)
.eq('id', tierId)
.select()
.single();
if (error) {
log.error('updateSponsorTier failed', { error, data: { tierId } });
throw error;
}
return data as SponsorTier;
}
export async function deleteSponsorTier(
supabase: SupabaseClient,
tierId: string
): Promise<void> {
const { error } = await db(supabase)
.from('sponsor_tiers')
.delete()
.eq('id', tierId);
if (error) {
log.error('deleteSponsorTier failed', { error, data: { tierId } });
throw error;
}
}
// ============================================================
// Event-wide Tier + Sponsor fetching
// ============================================================
export async function fetchEventSponsorTiers(
supabase: SupabaseClient,
eventId: string
): Promise<SponsorTier[]> {
const { data, error } = await db(supabase)
.from('sponsor_tiers')
.select('*, event_departments!inner(event_id)')
.eq('event_departments.event_id', eventId)
.order('sort_order');
if (error) {
log.error('fetchEventSponsorTiers failed', { error, data: { eventId } });
throw error;
}
return (data ?? []).map((d: any) => {
const { event_departments, ...tier } = d;
return tier;
}) as SponsorTier[];
}
export async function fetchEventSponsors(
supabase: SupabaseClient,
eventId: string
): Promise<Sponsor[]> {
const { data, error } = await db(supabase)
.from('sponsors')
.select('*, event_departments!inner(event_id)')
.eq('event_departments.event_id', eventId)
.order('name');
if (error) {
log.error('fetchEventSponsors failed', { error, data: { eventId } });
throw error;
}
return (data ?? []).map((d: any) => {
const { event_departments, ...sponsor } = d;
return sponsor;
}) as Sponsor[];
}
export async function fetchEventDeliverables(
supabase: SupabaseClient,
eventId: string
): Promise<SponsorDeliverable[]> {
const { data, error } = await db(supabase)
.from('sponsor_deliverables')
.select('*, sponsors!inner(department_id, event_departments!inner(event_id))')
.eq('sponsors.event_departments.event_id', eventId)
.order('sort_order');
if (error) {
log.error('fetchEventDeliverables failed', { error, data: { eventId } });
throw error;
}
return (data ?? []).map((d: any) => {
const { sponsors, ...del } = d;
return del;
}) as SponsorDeliverable[];
}
// ============================================================
// Sponsors
// ============================================================
export async function fetchSponsors(
supabase: SupabaseClient,
departmentId: string
): Promise<Sponsor[]> {
const { data, error } = await db(supabase)
.from('sponsors')
.select('*')
.eq('department_id', departmentId)
.order('name');
if (error) {
log.error('fetchSponsors failed', { error, data: { departmentId } });
throw error;
}
return (data ?? []) as Sponsor[];
}
export async function createSponsor(
supabase: SupabaseClient,
departmentId: string,
params: {
name: string;
tier_id?: string | null;
contact_name?: string;
contact_email?: string;
contact_phone?: string;
website?: string;
logo_url?: string;
status?: SponsorStatus;
amount?: number;
notes?: string;
}
): Promise<Sponsor> {
const { data, error } = await db(supabase)
.from('sponsors')
.insert({
department_id: departmentId,
name: params.name,
tier_id: params.tier_id ?? null,
contact_name: params.contact_name ?? null,
contact_email: params.contact_email ?? null,
contact_phone: params.contact_phone ?? null,
website: params.website ?? null,
logo_url: params.logo_url ?? null,
status: params.status ?? 'prospect',
amount: params.amount ?? 0,
notes: params.notes ?? null,
})
.select()
.single();
if (error) {
log.error('createSponsor failed', { error, data: { departmentId, name: params.name } });
throw error;
}
return data as Sponsor;
}
export async function updateSponsor(
supabase: SupabaseClient,
sponsorId: string,
params: Partial<Pick<Sponsor, 'name' | 'tier_id' | 'contact_name' | 'contact_email' | 'contact_phone' | 'website' | 'logo_url' | 'status' | 'amount' | 'notes'>>
): Promise<Sponsor> {
const { data, error } = await db(supabase)
.from('sponsors')
.update({ ...params, updated_at: new Date().toISOString() })
.eq('id', sponsorId)
.select()
.single();
if (error) {
log.error('updateSponsor failed', { error, data: { sponsorId } });
throw error;
}
return data as Sponsor;
}
export async function deleteSponsor(
supabase: SupabaseClient,
sponsorId: string
): Promise<void> {
const { error } = await db(supabase)
.from('sponsors')
.delete()
.eq('id', sponsorId);
if (error) {
log.error('deleteSponsor failed', { error, data: { sponsorId } });
throw error;
}
}
// ============================================================
// Sponsor Deliverables
// ============================================================
export async function fetchDeliverables(
supabase: SupabaseClient,
sponsorId: string
): Promise<SponsorDeliverable[]> {
const { data, error } = await db(supabase)
.from('sponsor_deliverables')
.select('*')
.eq('sponsor_id', sponsorId)
.order('sort_order');
if (error) {
log.error('fetchDeliverables failed', { error, data: { sponsorId } });
throw error;
}
return (data ?? []) as SponsorDeliverable[];
}
export async function fetchAllDeliverables(
supabase: SupabaseClient,
sponsorIds: string[]
): Promise<SponsorDeliverable[]> {
if (sponsorIds.length === 0) return [];
const { data, error } = await db(supabase)
.from('sponsor_deliverables')
.select('*')
.in('sponsor_id', sponsorIds)
.order('sort_order');
if (error) {
log.error('fetchAllDeliverables failed', { error, data: { sponsorIds } });
throw error;
}
return (data ?? []) as SponsorDeliverable[];
}
export async function createDeliverable(
supabase: SupabaseClient,
sponsorId: string,
description: string,
dueDate?: string
): Promise<SponsorDeliverable> {
const { data, error } = await db(supabase)
.from('sponsor_deliverables')
.insert({
sponsor_id: sponsorId,
description,
due_date: dueDate ?? null,
})
.select()
.single();
if (error) {
log.error('createDeliverable failed', { error, data: { sponsorId, description } });
throw error;
}
return data as SponsorDeliverable;
}
export async function updateDeliverable(
supabase: SupabaseClient,
deliverableId: string,
params: Partial<Pick<SponsorDeliverable, 'description' | 'is_completed' | 'due_date' | 'sort_order'>>
): Promise<SponsorDeliverable> {
const { data, error } = await db(supabase)
.from('sponsor_deliverables')
.update({ ...params, updated_at: new Date().toISOString() })
.eq('id', deliverableId)
.select()
.single();
if (error) {
log.error('updateDeliverable failed', { error, data: { deliverableId } });
throw error;
}
return data as SponsorDeliverable;
}
export async function deleteDeliverable(
supabase: SupabaseClient,
deliverableId: string
): Promise<void> {
const { error } = await db(supabase)
.from('sponsor_deliverables')
.delete()
.eq('id', deliverableId);
if (error) {
log.error('deleteDeliverable failed', { error, data: { deliverableId } });
throw error;
}
}