From 99ed4f2b4a5e85cce51f615745e73f418a86f7b5 Mon Sep 17 00:00:00 2001 From: Kartik Pingle Date: Sun, 6 Apr 2025 16:58:37 -0400 Subject: [PATCH] Display semester half hours as Q1/Q2 or Q3/Q4 based on semester --- src/components/App.tsx | 2 ++ src/components/SelectedActivities.tsx | 17 ++++++++++++-- src/lib/schema.ts | 4 ++++ src/lib/state.ts | 32 ++++++++++++++++++++++++++- 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/components/App.tsx b/src/components/App.tsx index a79ec30e..293f7248 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -276,6 +276,8 @@ function HydrantApp() { selectedActivities={state.selectedActivities} units={state.units} hours={state.hours} + hoursFirstHalf={state.hoursFirstHalf} + hoursSecondHalf={state.hoursSecondHalf} warnings={state.warnings} state={hydrant} /> diff --git a/src/components/SelectedActivities.tsx b/src/components/SelectedActivities.tsx index 8c3f390e..5ae2691b 100644 --- a/src/components/SelectedActivities.tsx +++ b/src/components/SelectedActivities.tsx @@ -47,16 +47,29 @@ export function SelectedActivities(props: { selectedActivities: Array; units: number; hours: number; + hoursFirstHalf: number; + hoursSecondHalf: number; warnings: Array; state: State; }) { - const { selectedActivities, units, hours, warnings, state } = props; + const { selectedActivities, units, hours, hoursFirstHalf, hoursSecondHalf, warnings, state } = props; + + const formatHours = () => { + if (hoursFirstHalf === hoursSecondHalf) { + return `${hours.toFixed(1)} hours`; + } + + // Use Q1/Q2 for fall semester, Q3/Q4 for spring semester + const [firstLabel, secondLabel] = state.term.semester === 'f' ? ['Q1', 'Q2'] : ['Q3', 'Q4']; + + return `\u2264 ${hours.toFixed(1)} hours (${hoursFirstHalf.toFixed(1)} ${firstLabel}, ${hoursSecondHalf.toFixed(1)} ${secondLabel})`; + }; return ( {units} units - {hours.toFixed(1)} hours + {formatHours()} {selectedActivities.map((activity) => ( diff --git a/src/lib/schema.ts b/src/lib/schema.ts index de18b644..0e069f97 100644 --- a/src/lib/schema.ts +++ b/src/lib/schema.ts @@ -33,6 +33,8 @@ export type HydrantState = { totalOptions: number; units: number; hours: number; + hoursFirstHalf: number; + hoursSecondHalf: number; warnings: Array; saveId: string; saves: Array; @@ -47,6 +49,8 @@ export const DEFAULT_STATE: HydrantState = { totalOptions: 0, units: 0, hours: 0, + hoursFirstHalf: 0, + hoursSecondHalf: 0, warnings: [], saveId: "", saves: [], diff --git a/src/lib/state.ts b/src/lib/state.ts index 001f13df..2925fd74 100644 --- a/src/lib/state.ts +++ b/src/lib/state.ts @@ -196,13 +196,42 @@ export class State { * localStorage. */ updateState(save: boolean = true): void { + // Calculate hours for each half + const firstHalfHours = sum( + this.selectedActivities + .filter(act => { + if ('rawClass' in act) { + // Include if class is full semester or first half + return !act.rawClass.half || act.rawClass.half === 1; + } + // Include all non-class activities in both halves + return true; + }) + .map(activity => activity.hours) + ); + + const secondHalfHours = sum( + this.selectedActivities + .filter(act => { + if ('rawClass' in act) { + // Include if class is full semester or second half + return !act.rawClass.half || act.rawClass.half === 2; + } + // Include all non-class activities in both halves + return true; + }) + .map(activity => activity.hours) + ); + this.callback?.({ selectedActivities: this.selectedActivities, viewedActivity: this.viewedActivity, selectedOption: this.selectedOption, totalOptions: this.options.length, units: sum(this.selectedClasses.map((cls) => cls.totalUnits)), - hours: sum(this.selectedActivities.map((activity) => activity.hours)), + hours: Math.max(firstHalfHours, secondHalfHours), // Use max for total hours + hoursFirstHalf: firstHalfHours, + hoursSecondHalf: secondHalfHours, warnings: Array.from( new Set(this.selectedClasses.flatMap((cls) => cls.warnings.messages)), ), @@ -210,6 +239,7 @@ export class State { saves: this.saves, preferences: this.preferences, }); + if (save) { this.storeSave(this.saveId, false); }