Skip to content

Commit 5f3194d

Browse files
authored
Merge pull request #21 from foundersandcoders/fix/event
Fix/event
2 parents 9fb7e29 + f147068 commit 5f3194d

4 files changed

Lines changed: 30 additions & 28 deletions

File tree

src/lib/airtable/airtable.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export interface ApprenticeRecord {
1414
id: string;
1515
name: string;
1616
email: string;
17-
cohortId: string | null; // Record ID of cohort
17+
cohortIds: string[]; // Record IDs of cohorts (apprentice may belong to multiple)
1818
}
1919

2020
export interface Cohort {
@@ -199,15 +199,15 @@ export function createAirtableClient(apiKey: string, baseId: string) {
199199
}
200200

201201
/**
202-
* Check if email exists in Apprentices table
202+
* Check if email exists in Apprentices table (case-insensitive)
203203
* Note: filterByFormula requires field NAME "Learner email" - this would break if renamed in Airtable
204204
*/
205205
async function findApprenticeByEmail(email: string): Promise<boolean> {
206206
const apprenticesTable = base(TABLES.APPRENTICES);
207207

208208
const apprenticeRecords = await apprenticesTable
209209
.select({
210-
filterByFormula: `{Learner email} = "${email}"`,
210+
filterByFormula: `LOWER({Learner email}) = LOWER("${email}")`,
211211
maxRecords: 1,
212212
returnFieldsByFieldId: true,
213213
})
@@ -224,7 +224,7 @@ export function createAirtableClient(apiKey: string, baseId: string) {
224224

225225
const records = await apprenticesTable
226226
.select({
227-
filterByFormula: `{Learner email} = "${email}"`,
227+
filterByFormula: `LOWER({Learner email}) = LOWER("${email}")`,
228228
maxRecords: 1,
229229
returnFieldsByFieldId: true,
230230
})
@@ -242,7 +242,7 @@ export function createAirtableClient(apiKey: string, baseId: string) {
242242
id: record.id,
243243
name: record.get(APPRENTICE_FIELDS.NAME) as string,
244244
email: emailLookup?.[0] ?? email,
245-
cohortId: cohortLink?.[0] ?? null,
245+
cohortIds: cohortLink ?? [],
246246
};
247247
}
248248

@@ -332,7 +332,7 @@ export function createAirtableClient(apiKey: string, baseId: string) {
332332
id: record.id,
333333
name: record.get(APPRENTICE_FIELDS.NAME) as string,
334334
email: emailLookup?.[0] ?? '',
335-
cohortId: cohortLink?.[0] ?? null,
335+
cohortIds: cohortLink ?? [],
336336
};
337337
});
338338
}
@@ -362,7 +362,7 @@ export function createAirtableClient(apiKey: string, baseId: string) {
362362
id: record.id,
363363
name: record.get(APPRENTICE_FIELDS.NAME) as string,
364364
email: emailLookup?.[0] ?? '',
365-
cohortId: cohortLink?.[0] ?? null,
365+
cohortIds: cohortLink ?? [],
366366
};
367367
});
368368
}

src/lib/airtable/attendance.ts

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -397,20 +397,21 @@ export function createAttendanceClient(apiKey: string, baseId: string) {
397397
// ============================================
398398

399399
/**
400-
* Get events for a specific cohort, optionally filtered by date range
400+
* Get events for cohorts, optionally filtered by date range
401401
* This is THE source of truth for which events count toward an apprentice's stats
402+
* Accepts multiple cohort IDs - returns events that match ANY of the cohorts
402403
*/
403-
function getEventsForCohort(
404+
function getEventsForCohorts(
404405
allEvents: EventForStats[],
405-
cohortId: string | null,
406+
cohortIds: string[],
406407
options?: { startDate?: Date; endDate?: Date },
407408
): EventForStats[] {
408-
// Filter by cohort (if no cohort, return empty - apprentice must belong to a cohort)
409-
if (!cohortId) {
409+
// Filter by cohorts (if no cohorts, return empty - apprentice must belong to at least one cohort)
410+
if (cohortIds.length <= 0) {
410411
return [];
411412
}
412413

413-
let events = allEvents.filter(e => e.cohortIds.includes(cohortId));
414+
let events = allEvents.filter(e => e.cohortIds.some(c => cohortIds.includes(c)));
414415

415416
// Filter by date range if provided
416417
if (options?.startDate && options?.endDate) {
@@ -475,14 +476,15 @@ export function createAttendanceClient(apiKey: string, baseId: string) {
475476
const apprentice = apprenticeRecords[0];
476477
const apprenticeName = apprentice.get(APPRENTICE_FIELDS.NAME) as string;
477478
const cohortLink = apprentice.get(APPRENTICE_FIELDS.COHORT) as string[] | undefined;
478-
const cohortId = cohortLink?.[0] ?? null;
479+
const cohortIds = cohortLink ?? [];
480+
const primaryCohortId = cohortIds[0] ?? null; // For display purposes
479481

480-
// Get cohort name if available
482+
// Get primary cohort name if available (for display)
481483
let cohortName: string | null = null;
482-
if (cohortId) {
484+
if (primaryCohortId) {
483485
const cohortRecords = await cohortsTable
484486
.select({
485-
filterByFormula: `RECORD_ID() = "${cohortId}"`,
487+
filterByFormula: `RECORD_ID() = "${primaryCohortId}"`,
486488
maxRecords: 1,
487489
returnFieldsByFieldId: true,
488490
})
@@ -492,9 +494,9 @@ export function createAttendanceClient(apiKey: string, baseId: string) {
492494
}
493495
}
494496

495-
// Get events for this cohort (with optional date filter)
497+
// Get events for all of the apprentice's cohorts (with optional date filter)
496498
const allEvents = await getAllEvents();
497-
const relevantEvents = getEventsForCohort(allEvents, cohortId, options);
499+
const relevantEvents = getEventsForCohorts(allEvents, cohortIds, options);
498500
const relevantEventIds = new Set(relevantEvents.map(e => e.id));
499501

500502
// Get attendance for this apprentice, filtered to cohort events only
@@ -542,7 +544,7 @@ export function createAttendanceClient(apiKey: string, baseId: string) {
542544
...stats,
543545
apprenticeId,
544546
apprenticeName,
545-
cohortId,
547+
cohortId: primaryCohortId,
546548
cohortName,
547549
trend: calculateTrend(recentRate, previousRate),
548550
};
@@ -827,11 +829,11 @@ export function createAttendanceClient(apiKey: string, baseId: string) {
827829

828830
const apprentice = apprenticeRecords[0];
829831
const cohortLink = apprentice.get(APPRENTICE_FIELDS.COHORT) as string[] | undefined;
830-
const cohortId = cohortLink?.[0] ?? null;
832+
const cohortIds = cohortLink ?? [];
831833

832-
// Get events for this cohort (with optional date filter)
834+
// Get events for all of the apprentice's cohorts (with optional date filter)
833835
const allEvents = await getAllEvents();
834-
const relevantEvents = getEventsForCohort(allEvents, cohortId, options);
836+
const relevantEvents = getEventsForCohorts(allEvents, cohortIds, options);
835837
const relevantEventIds = new Set(relevantEvents.map(e => e.id));
836838

837839
// Get attendance for this apprentice, filtered to cohort events only

src/routes/api/checkin/events/+server.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ export const GET: RequestHandler = async ({ cookies }) => {
2525
const allEvents = await listEvents({ startDate: today.toISOString() });
2626

2727
if (apprentice) {
28-
// User has apprentice record: show cohort + public events
28+
// User has apprentice record: show events from any of their cohorts + public events
2929
const relevantEvents = allEvents.filter(
30-
event => event.isPublic || (apprentice.cohortId && event.cohortIds.includes(apprentice.cohortId)),
30+
event => event.isPublic || event.cohortIds.some(c => apprentice.cohortIds.includes(c)),
3131
);
3232

3333
// Check attendance status for each event

src/routes/checkin/+page.server.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ export const load: PageServerLoad = async ({ locals }) => {
5656

5757
// Filter events based on user type
5858
let availableEvents;
59-
if (apprentice?.cohortId) {
60-
// User with apprentice record: show cohort events + public events
59+
if (apprentice?.cohortIds.length) {
60+
// User with apprentice record: show events from any of their cohorts + public events
6161
availableEvents = allEvents.filter(
62-
event => event.cohortIds.includes(apprentice.cohortId!) || event.isPublic,
62+
event => event.cohortIds.some(c => apprentice.cohortIds.includes(c)) || event.isPublic,
6363
);
6464
}
6565
else {

0 commit comments

Comments
 (0)