Mega push vol 7 mvp lesgoooo
This commit is contained in:
301
src/lib/api/sponsors.ts
Normal file
301
src/lib/api/sponsors.ts
Normal file
@@ -0,0 +1,301 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user