Initial state for GitNexus analysis

This commit is contained in:
Zaid Marzguioui
2026-03-29 19:44:57 +02:00
parent 9d7c7f8030
commit 61ff48cb73
155 changed files with 23483 additions and 1722 deletions

View File

@@ -0,0 +1,145 @@
import type { Database } from '@kit/supabase/database';
import type { SupabaseClient } from '@supabase/supabase-js';
import type { CreateCourseInput, EnrollParticipantInput } from '../schema/course.schema';
/* eslint-disable @typescript-eslint/no-explicit-any */
export function createCourseManagementApi(client: SupabaseClient<Database>) {
const db = client;
return {
// --- Courses ---
async listCourses(accountId: string, opts?: { status?: string; search?: string; page?: number; pageSize?: number }) {
let query = client.from('courses').select('*', { count: 'exact' })
.eq('account_id', accountId).order('start_date', { ascending: false });
if (opts?.status) query = query.eq('status', opts.status);
if (opts?.search) query = query.or(`name.ilike.%${opts.search}%,course_number.ilike.%${opts.search}%`);
const page = opts?.page ?? 1;
const pageSize = opts?.pageSize ?? 25;
query = query.range((page - 1) * pageSize, page * pageSize - 1);
const { data, error, count } = await query;
if (error) throw error;
return { data: data ?? [], total: count ?? 0, page, pageSize };
},
async getCourse(courseId: string) {
const { data, error } = await client.from('courses').select('*').eq('id', courseId).single();
if (error) throw error;
return data;
},
async createCourse(input: CreateCourseInput) {
const { data, error } = await client.from('courses').insert({
account_id: input.accountId, course_number: input.courseNumber, name: input.name,
description: input.description, category_id: input.categoryId, instructor_id: input.instructorId,
location_id: input.locationId, start_date: input.startDate, end_date: input.endDate,
fee: input.fee, reduced_fee: input.reducedFee, capacity: input.capacity,
min_participants: input.minParticipants, status: input.status,
registration_deadline: input.registrationDeadline, notes: input.notes,
}).select().single();
if (error) throw error;
return data;
},
// --- Enrollment ---
async enrollParticipant(input: EnrollParticipantInput) {
// Check capacity
const { count } = await client.from('course_participants').select('*', { count: 'exact', head: true })
.eq('course_id', input.courseId).in('status', ['enrolled']);
const course = await this.getCourse(input.courseId);
const status = (count ?? 0) >= course.capacity ? 'waitlisted' : 'enrolled';
const { data, error } = await client.from('course_participants').insert({
course_id: input.courseId, member_id: input.memberId,
first_name: input.firstName, last_name: input.lastName,
email: input.email, phone: input.phone, status,
}).select().single();
if (error) throw error;
return data;
},
async cancelEnrollment(participantId: string) {
const { error } = await client.from('course_participants')
.update({ status: 'cancelled', cancelled_at: new Date().toISOString() })
.eq('id', participantId);
if (error) throw error;
},
async getParticipants(courseId: string) {
const { data, error } = await client.from('course_participants').select('*')
.eq('course_id', courseId).order('enrolled_at');
if (error) throw error;
return data ?? [];
},
// --- Sessions ---
async getSessions(courseId: string) {
const { data, error } = await client.from('course_sessions').select('*')
.eq('course_id', courseId).order('session_date');
if (error) throw error;
return data ?? [];
},
async createSession(input: { courseId: string; sessionDate: string; startTime: string; endTime: string; locationId?: string }) {
const { data, error } = await client.from('course_sessions').insert({
course_id: input.courseId, session_date: input.sessionDate,
start_time: input.startTime, end_time: input.endTime, location_id: input.locationId,
}).select().single();
if (error) throw error;
return data;
},
// --- Attendance ---
async getAttendance(sessionId: string) {
const { data, error } = await client.from('course_attendance').select('*').eq('session_id', sessionId);
if (error) throw error;
return data ?? [];
},
async markAttendance(sessionId: string, participantId: string, present: boolean) {
const { error } = await client.from('course_attendance').upsert({
session_id: sessionId, participant_id: participantId, present,
}, { onConflict: 'session_id,participant_id' });
if (error) throw error;
},
// --- Categories, Instructors, Locations ---
async listCategories(accountId: string) {
const { data, error } = await client.from('course_categories').select('*')
.eq('account_id', accountId).order('sort_order');
if (error) throw error;
return data ?? [];
},
async listInstructors(accountId: string) {
const { data, error } = await client.from('course_instructors').select('*')
.eq('account_id', accountId).order('last_name');
if (error) throw error;
return data ?? [];
},
async listLocations(accountId: string) {
const { data, error } = await client.from('course_locations').select('*')
.eq('account_id', accountId).order('name');
if (error) throw error;
return data ?? [];
},
// --- Statistics ---
async getStatistics(accountId: string) {
const { data: courses } = await client.from('courses').select('status').eq('account_id', accountId);
const { count: totalParticipants } = await client.from('course_participants')
.select('*', { count: 'exact', head: true })
.in('course_id', (courses ?? []).map((c: any) => c.id));
const stats = { totalCourses: 0, openCourses: 0, completedCourses: 0, totalParticipants: totalParticipants ?? 0 };
for (const c of (courses ?? [])) {
stats.totalCourses++;
if (c.status === 'open' || c.status === 'running') stats.openCourses++;
if (c.status === 'completed') stats.completedCourses++;
}
return stats;
},
};
}