holiday editing works

This commit is contained in:
2024-10-29 14:13:30 -06:00
parent 590a245536
commit b4daeb52b0
6 changed files with 201 additions and 51 deletions

View File

@@ -1,15 +1,22 @@
"use client";
import TextInput from "@/components/form/TextInput";
import { SuspenseAndErrorHandling } from "@/components/SuspenseAndErrorHandling";
import {
useLocalCourseSettingsQuery,
useUpdateLocalCourseSettingsMutation,
} from "@/hooks/localCourse/localCoursesHooks";
import {
dateToMarkdownString,
getDateFromString,
getDateFromStringOrThrow,
getDateOnlyMarkdownString,
} from "@/models/local/timeUtils";
import { useState } from "react";
import { useEffect, useState } from "react";
import {
holidaysToString,
parseHolidays,
} from "../../../../models/local/settingsUtils";
const exampleString = `springBreak:
- 10/12/2024
@@ -18,68 +25,126 @@ const exampleString = `springBreak:
laborDay:
- 9/1/2024`;
export const holidaysAreEqual = (
obj1: { [key: string]: string[] },
obj2: { [key: string]: string[] }
): boolean => {
const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);
if (keys1.length !== keys2.length) return false;
for (const key of keys1) {
if (!obj2.hasOwnProperty(key)) return false;
const arr1 = obj1[key];
const arr2 = obj2[key];
if (arr1.length !== arr2.length) return false;
const sortedArr1 = [...arr1].sort();
const sortedArr2 = [...arr2].sort();
for (let i = 0; i < sortedArr1.length; i++) {
if (sortedArr1[i] !== sortedArr2[i]) return false;
}
}
return true;
};
export default function HolidayConfig() {
return (
<SuspenseAndErrorHandling>
<InnerHolidayConfig />
</SuspenseAndErrorHandling>
);
}
function InnerHolidayConfig() {
const { data: settings } = useLocalCourseSettingsQuery();
const updateSettings = useUpdateLocalCourseSettingsMutation();
const [rawText, setRawText] = useState("");
const [rawText, setRawText] = useState(holidaysToString(settings.holidays));
const parsedText = parseHolidays(rawText);
useEffect(() => {
const id = setTimeout(() => {
try {
const parsed = parseHolidays(rawText);
if (!holidaysAreEqual(settings.holidays, parsed))
updateSettings.mutate({
...settings,
holidays: parsed,
});
} catch (error: any) {}
}, 500);
return () => clearTimeout(id);
}, [rawText, settings, updateSettings]);
return (
<div className="flex flex-row gap-3 border w-fit p-3 m-3 rounded-md">
<TextInput
value={rawText}
setValue={setRawText}
label={"Holiday Days"}
isTextArea={true}
/>
<div>
Format your holidays like so:
<pre>
<code>{exampleString}</code>
</pre>
<div className=" border w-fit p-3 m-3 rounded-md">
<div className="flex flex-row gap-3">
<TextInput
value={rawText}
setValue={setRawText}
label={"Holiday Days"}
isTextArea={true}
/>
<div>
Format your holidays like so:
<pre>
<code>{exampleString}</code>
</pre>
</div>
</div>
<div>
{Object.keys(parsedText).map((k) => (
<div key={k}>
<div>{k}</div>
<div>
{parsedText[k].map((day) => {
const parsedDate = getDateFromStringOrThrow(
day,
"holiday preview display"
);
return <div key={day}>{dateToMarkdownString(parsedDate)}</div>;
})}
</div>
</div>
))}
<SuspenseAndErrorHandling>
<ParsedHolidaysDisplay value={rawText} />
</SuspenseAndErrorHandling>
</div>
</div>
);
}
const parseHolidays = (
inputText: string
): { [holidayName: string]: string[] } => {
const holidays: { [holidayName: string]: string[] } = {};
const lines = inputText.split("\n").filter(line => line.trim() !== "");
let currentHoliday: string | null = null;
function ParsedHolidaysDisplay({ value }: { value: string }) {
const [parsedHolidays, setParsedHolidays] = useState<{
[holidayName: string]: string[];
}>({});
const [error, setError] = useState("");
lines.forEach(line => {
if (line.includes(":")) {
// It's a holiday name
const holidayName = line.split(":")[0].trim();
currentHoliday = holidayName;
holidays[currentHoliday] = [];
} else if (currentHoliday && line.startsWith("-")) {
// It's a date under the current holiday
const date = line.replace("-", "").trim();
holidays[currentHoliday].push(date);
}
});
useEffect(() => {
try {
const parsed = parseHolidays(value);
setParsedHolidays(parsed);
setError("");
} catch (error: any) {
setError(error + "");
}
}, [value]);
return holidays;
};
return (
<div>
<div className="text-rose-500">{error}</div>
{Object.keys(parsedHolidays).map((k) => (
<div key={k}>
<div>{k}</div>
<div>
{parsedHolidays[k].map((day) => {
const date = getDateFromString(day);
return (
<div key={day}>
{date?.toLocaleDateString("en-us", {
weekday: "short",
year: "numeric",
month: "short",
day: "numeric",
})}
</div>
);
})}
</div>
</div>
))}
</div>
);
}

View File

@@ -1,5 +1,4 @@
import React from "react";
import { useCourseContext } from "../context/courseContext";
import StartAndEndDate from "./StartAndEndDate";
import SettingsHeader from "./SettingsHeader";
import DefaultDueTime from "./DefaultDueTime";