This repository has been archived on 2025-08-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
lcm-potty-chart/contexts/NewCalenderContext.tsx

263 lines
6.0 KiB
TypeScript

import React, { createContext, useState, ReactNode } from "react";
import {
format,
startOfMonth,
endOfMonth,
getDate,
add,
sub,
set,
isAfter,
isBefore
} from "date-fns";
// TODO: import types
type Days =
| "Sunday"
| "Monday"
| "Tuesday"
| "Wednesday"
| "Thursday"
| "Friday"
| "Saturday";
type DaysOfWeek = Days[];
interface WeekDays {
startOfWeek: {
sunday: DaysOfWeek;
monday: DaysOfWeek;
};
}
interface Month {
week1: Date[];
week2: Date[];
week3: Date[];
week4: Date[];
week5: Date[];
week6: Date[];
}
interface MonthInfo {
date: Date;
title: string;
startDay: string;
endDay: string;
days: number;
prevMonth: {
date: Date;
endDay: number;
days: number;
};
}
interface MonthContext extends MonthInfo {
startOfWeek: {
sunday: {
layout: DaysOfWeek;
month: Month;
};
monday: {
layout: DaysOfWeek;
month: Month;
};
};
}
interface CalenderContextState {
selectedMonth: MonthContext;
}
const NewCalenderContext = createContext({} as CalenderContextState);
const NewCalenderContextProvider = ({
children,
}: {
children: ReactNode;
}): JSX.Element => {
const weekDays: WeekDays = {
startOfWeek: {
sunday: [
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
],
monday: [
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday",
],
},
};
const ISOToIndex = {
sunday: {
Sun: 0,
Mon: 1,
Tue: 2,
Wed: 3,
Thu: 4,
Fri: 5,
Sat: 6,
},
monday: {
Mon: -1,
Tue: 0,
Wed: 1,
Thu: 2,
Fri: 3,
Sat: 4,
Sun: 5,
},
};
const [selectedDate, setSelectedMonth] = useState<Date>(new Date());
const [prevMonth, setPrevMonth] = useState<Date>(
sub(selectedDate, { months: 1 })
);
const [selectedMonthInfo, setSelectedMonthInfo] = useState<MonthContext>({
date: selectedDate,
title: format(selectedDate, "LLLL uuuu"),
startDay: format(startOfMonth(selectedDate), "iii"), // TODO: Update to use the ISOToIndex dynamically with the user's start day preferences.
endDay: format(endOfMonth(selectedDate), "iii"), // TODO: Update to use the ISOToIndex dynamically with the user's start day preferences.
days: getDate(endOfMonth(selectedDate)),
prevMonth: {
date: prevMonth,
endDay: getDate(endOfMonth(prevMonth)),
days: getDate(endOfMonth(prevMonth)),
},
startOfWeek: {
sunday: {
layout: weekDays.startOfWeek.sunday,
month: {} as Month,
},
monday: {
layout: weekDays.startOfWeek.monday,
month: {} as Month,
},
},
});
//TODO: Add a function that will populate the "MONTH" layout for the context. It should take in the start of the week (Sunday, Monday) and output the appropriate layout based on that preference.
const isOverflow = (selectedDate: Date, currDate: Date) => {
let flag = false;
const start = startOfMonth(selectedDate);
const end = endOfMonth(selectedDate);
if (isBefore(currDate, start) || isAfter(currDate, end)) {
flag = true;
}
return flag;
}
const populateMonth = (
selectedDate: Date,
startOfMonth: string,
prevMonth: {
date: Date;
endDay: number;
days: number;
}
): void => {
const sundays = {
week1: new Array(7).fill(null),
week2: new Array(7).fill(null),
week3: new Array(7).fill(null),
week4: new Array(7).fill(null),
week5: new Array(7).fill(null),
week6: new Array(7).fill(null),
};
const sunStartDay =
prevMonth.endDay - (ISOToIndex.sunday[startOfMonth] - 1);
let sunCurrDate = set(sub(selectedDate, { months: 1 }), {
date: sunStartDay,
});
for (let week in sundays) {
const thisWeek = sundays[week];
thisWeek.forEach((e, i, a) => {
const day = {
isOverflow: isOverflow(selectedDate, sunCurrDate),
date: sunCurrDate,
};
sunCurrDate = add(sunCurrDate, { days: 1 })
sundays[week][i] = day;
});
}
const mondays = {
week1: new Array(7).fill(null),
week2: new Array(7).fill(null),
week3: new Array(7).fill(null),
week4: new Array(7).fill(null),
week5: new Array(7).fill(null),
week6: new Array(7).fill(null),
};
const monStartDay =
prevMonth.endDay - (ISOToIndex.monday[startOfMonth]);
// console.log(`Start date: ${monStartDay}`);
let monCurrDate = set(sub(selectedDate, { months: 1 }), {
date: monStartDay,
});
// console.log(`Start date: ${currDate}`);
for (let week in mondays) {
const thisWeek = mondays[week];
thisWeek.forEach((e, i, a) => {
const day = {
isOverflow: isOverflow(selectedDate, monCurrDate),
date: monCurrDate,
};
monCurrDate = add(monCurrDate, { days: 1 })
mondays[week][i] = day;
});
}
console.log("mondays after loop and map", mondays);
};
populateMonth(
selectedDate,
format(startOfMonth(selectedDate), "iii"),
selectedMonthInfo.prevMonth
);
//TODO: Update the MonthInfo to use the new month population function on first render.
//TODO: Add a new navigation function that will take in either a direction (next, prev) or a date to go directly to. That will update the selected month and trigger the use effects below.
//TODO: Add a function that will update the MonthInfo state when the selected month changes. This should use the populate month function that will be made above.
//TODO: Add a useEffect that will trigger the update function(s) to run when the selected date is updated.
const calenderContextValues = {
selectedMonthInfo,
};
return (
<NewCalenderContext.Provider value={calenderContextValues}>
{children}
</NewCalenderContext.Provider>
);
};
export { NewCalenderContextProvider, NewCalenderContext };