From 73a05debfcebb2da0b0c2023b3010287c3cbb041 Mon Sep 17 00:00:00 2001 From: Alex Mickelson Date: Mon, 30 Sep 2024 21:44:05 -0600 Subject: [PATCH] week numbers --- .../[courseName]/calendar/CalendarMonth.tsx | 29 +++++++++--- .../calendar/calendarMonthUtils.ts | 28 ++++++++++- .../calendar/calendarUtils.test.ts | 47 +++++++++++++++++++ .../[courseName]/calendar/calendarUtils.tsx | 0 4 files changed, 97 insertions(+), 7 deletions(-) create mode 100644 nextjs/src/app/course/[courseName]/calendar/calendarUtils.test.ts create mode 100644 nextjs/src/app/course/[courseName]/calendar/calendarUtils.tsx diff --git a/nextjs/src/app/course/[courseName]/calendar/CalendarMonth.tsx b/nextjs/src/app/course/[courseName]/calendar/CalendarMonth.tsx index bfdaf96..ba29591 100644 --- a/nextjs/src/app/course/[courseName]/calendar/CalendarMonth.tsx +++ b/nextjs/src/app/course/[courseName]/calendar/CalendarMonth.tsx @@ -1,8 +1,10 @@ "use client"; -import { CalendarMonthModel } from "./calendarMonthUtils"; +import { CalendarMonthModel, getWeekNumber } from "./calendarMonthUtils"; import { DayOfWeek } from "@/models/local/localCourse"; import Day from "./day/Day"; import { Expandable } from "@/components/Expandable"; +import { useLocalCourseSettingsQuery } from "@/hooks/localCourse/localCoursesHooks"; +import { getDateFromStringOrThrow } from "@/models/local/timeUtils"; export const CalendarMonth = ({ month }: { month: CalendarMonthModel }) => { const weekInMilliseconds = 604_800_000; @@ -35,7 +37,7 @@ export const CalendarMonth = ({ month }: { month: CalendarMonthModel }) => { )} > -
+
{weekDaysList.map((day) => (
{day} @@ -58,11 +60,26 @@ function CalendarWeek({ week: string[]; //date strings monthNumber: number; }) { + const { data: settings } = useLocalCourseSettingsQuery(); + const startDate = getDateFromStringOrThrow( + settings.startDate, + "week calculation start date" + ); + const firstDateString = getDateFromStringOrThrow( + week[0], + "week calculation first day of week" + ); + const weekNumber = getWeekNumber(startDate, firstDateString); return ( -
- {week.map((day, dayIndex) => ( - - ))} +
+
+ {weekNumber.toString().padStart(2, "0")} +
+
+ {week.map((day, dayIndex) => ( + + ))} +
); } diff --git a/nextjs/src/app/course/[courseName]/calendar/calendarMonthUtils.ts b/nextjs/src/app/course/[courseName]/calendar/calendarMonthUtils.ts index eb4f9c8..6b08958 100644 --- a/nextjs/src/app/course/[courseName]/calendar/calendarMonthUtils.ts +++ b/nextjs/src/app/course/[courseName]/calendar/calendarMonthUtils.ts @@ -37,7 +37,9 @@ function createCalendarMonth(year: number, month: number): CalendarMonthModel { new Date(year, month - 1, dayIndex - firstDayOfMonth + 1, 12, 0, 0) ); } else if (currentDay <= daysInMonth) { - return dateToMarkdownString(new Date(year, month - 1, currentDay++, 12, 0, 0)); + return dateToMarkdownString( + new Date(year, month - 1, currentDay++, 12, 0, 0) + ); } else { currentDay++; return dateToMarkdownString( @@ -74,3 +76,27 @@ export function getMonthsBetweenDates( return createCalendarMonth(year, month); }); } + +export const getWeekNumber = (startDate: Date, currentDate: Date) => { + const sundayBeforeStartDate = getPreviousSunday(startDate); + const daysBetween = daysBetweenDates(sundayBeforeStartDate, currentDate); + const weeksDiff = Math.floor(daysBetween / 7); + + if (weeksDiff >= 0) return weeksDiff + 1; + return weeksDiff; +}; + +const daysBetweenDates = (startDate: Date, endDate: Date) => { + const diffInTime = endDate.getTime() - startDate.getTime(); + const diffInDays = diffInTime / (1000 * 3600 * 24); + return Math.floor(diffInDays); +}; + +const getPreviousSunday = (date: Date) => { + const result = new Date(date); + const dayOfWeek = result.getDay(); + + result.setDate(result.getDate() - dayOfWeek); + + return result; +}; diff --git a/nextjs/src/app/course/[courseName]/calendar/calendarUtils.test.ts b/nextjs/src/app/course/[courseName]/calendar/calendarUtils.test.ts new file mode 100644 index 0000000..95745f3 --- /dev/null +++ b/nextjs/src/app/course/[courseName]/calendar/calendarUtils.test.ts @@ -0,0 +1,47 @@ +import { describe, expect, it } from "vitest"; +import { getWeekNumber } from "./calendarMonthUtils"; + + +// months are 0 based, days are 1 based +describe("testing week numbers", () => { + + it("can get before first day", () => { + const startDate = new Date(2024, 8, 3); + const firstDayOfFirstWeek = new Date(2024, 8, 1); + + const weekNumber = getWeekNumber(startDate, firstDayOfFirstWeek); + expect(weekNumber).toBe(1); + }); + + it("can get end of first week", () => { + const startDate = new Date(2024, 8, 3); + const firstDayOfFirstWeek = new Date(2024, 8, 7); + + const weekNumber = getWeekNumber(startDate, firstDayOfFirstWeek); + expect(weekNumber).toBe(1); + }); + + it("can get start of second week", () => { + const startDate = new Date(2024, 8, 3); + const firstDayOfFirstWeek = new Date(2024, 8, 8); + + const weekNumber = getWeekNumber(startDate, firstDayOfFirstWeek); + expect(weekNumber).toBe(2); + }); + + it("can get start of third week", () => { + const startDate = new Date(2024, 8, 3); + const firstDayOfFirstWeek = new Date(2024, 8, 15); + + const weekNumber = getWeekNumber(startDate, firstDayOfFirstWeek); + expect(weekNumber).toBe(3); + }); + it("can get previous week", () => { + const startDate = new Date(2024, 8, 3); + const firstDayOfFirstWeek = new Date(2024, 7, 29); + + const weekNumber = getWeekNumber(startDate, firstDayOfFirstWeek); + expect(weekNumber).toBe(-1); + }); + +}); diff --git a/nextjs/src/app/course/[courseName]/calendar/calendarUtils.tsx b/nextjs/src/app/course/[courseName]/calendar/calendarUtils.tsx new file mode 100644 index 0000000..e69de29