diff --git a/scripts/favicon.sh b/scripts/favicon.sh index 31b63fd..4e740b5 100755 --- a/scripts/favicon.sh +++ b/scripts/favicon.sh @@ -4,15 +4,23 @@ set -eu cd "$(dirname "$0")" -cd ../public +main() { + if ! command -v magick > /dev/null; then + echo "ImageMagick required but not found" + exit 1 + fi -for size in 16 32; do - magick convert \ - -background none \ - -resize "${size}x${size}" \ - logo.svg "favicon-${size}.png" -done + cd ../public -magick convert favicon-*.png favicon.ico + for size in 16 32; do + magick convert \ + -background none \ + -resize "${size}x${size}" \ + logo.svg "favicon-${size}.png" + done -rm favicon-*.png + magick convert favicon-*.png favicon.ico + rm favicon-*.png +} + +main \ No newline at end of file diff --git a/src/components/Button.tsx b/src/components/Button.tsx index 2dafe9a..db1f306 100644 --- a/src/components/Button.tsx +++ b/src/components/Button.tsx @@ -12,7 +12,8 @@ export enum Size { large = "lg", } -interface ButtonProps extends React.ButtonHTMLAttributes { +export interface ButtonProps + extends React.ButtonHTMLAttributes { color?: `${Color}`; size?: `${Size}`; pill?: boolean; @@ -44,7 +45,7 @@ export function Button({ ); } -interface LinkButtonProps +export interface LinkButtonProps extends React.AnchorHTMLAttributes { color?: `${Color}`; size?: `${Size}`; @@ -63,9 +64,9 @@ export function LinkButton({ ); -const december = new Date(); -if (december.getMonth() === 0) { - // Use last year's December if it's January - december.setFullYear(december.getFullYear() - 1); +const now = new Date(); + +// Get December 1st. Use last year's December if it's January +const december = new Date( + now.getFullYear() - (now.getMonth() === 0 ? 1 : 0), + 11, // month is 0 indexed + 1 +); + +// Get the day at the beginning of the week for the calendar display +const beginningOfWeek = new Date(december); +beginningOfWeek.setDate(1 - december.getDay()); + +// All dates that will end up on the calendar +const dates: Date[] = []; +for ( + const currentDate = new Date(beginningOfWeek); + !(currentDate.getMonth() === 0 && currentDate.getDay() === 0); + currentDate.setDate(currentDate.getDate() + 1) +) { + dates.push(new Date(currentDate)); } -// set to 1st of December -december.setMonth(11, 1); -const decemberStartDayOfWeek = december.getDay(); -interface Props { +const daysOfWeek = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; + +export interface CalendarProps { current: number; className?: string; } -export function Calendar({ current, className }: Props) { - return ( -
- {Array.from({ length: decemberStartDayOfWeek }, () => ( -
// Spacer for days before Dec 1 - ))} - {Array.from({ length: 31 }, (_, i) => ( - - ))} -
- ); -} - -function GridDay({ day, current }: { day: number; current: number }) { +export function Calendar({ current, className }: CalendarProps) { return ( -
- +
December
+
day && "bg-yeti-dark-1 hover:bg-yeti-dark-3 text-white", - current === day && "bg-yeti-light-7 hover:bg-yeti-light-9" + "grid grid-cols-7 gap-px w-full bg-yeti-dark-3 border-yeti-dark-3 border rounded-lg", + className )} > - {day} -
{titles[day]}
- {current > day && ( - - )} - -
- ); -} - -/* -function TableCalendar({ current, className }: Props) { - return ( - - - {Array.from({ length: decemberStartDayOfWeek }, (_, i) => ( - // Spacer for days before Dec 1 - ))} - {Array.from({ length: 7 - decemberStartDayOfWeek }, (_, i) => ( - - ))} - - - {Array.from({ length: 7 }, (_, i) => ( - + {daysOfWeek.map((dow, i) => ( + + {dow[0]} + {dow.slice(1)} + ))} - -
+ + {dates.map((date, i) => { + const day = date.getDate(); + + if (date.getMonth() !== 11) { + return ( +
+ +
+ ); + } + + return ( + day && + "bg-yeti-dark-1 hover:bg-yeti-dark-3 !text-white", + i === dates.length - 7 && "rounded-bl-lg", + i === dates.length - 1 && "rounded-br-lg" + )} + > + + {day in titles && ( +
+ {titles[day]} +
+ )} + {current > day && ( + + )} + + ); + })} +
+ ); } -function TableDay({ day, current }: { day: number; current: number }) { - return ( - - day && "bg-yeti-dark-1 hover:bg-yeti-dark-3 text-white", - current === day && "bg-yeti-light-7 hover:bg-yeti-light-9" - )} - > - {day} -
{titles[day]}
- {current > day && ( - - )} -
- - ); +/** + * Format a date in YYYY-MM-DD format + */ +function yyyymmdd(date: Date): string { + return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, "0")}-${date.getDate().toString().padStart(2, "0")}`; } -*/ diff --git a/src/components/Link.tsx b/src/components/Link.tsx index 2850b34..9a82fb7 100644 --- a/src/components/Link.tsx +++ b/src/components/Link.tsx @@ -1,7 +1,8 @@ const { BASE_URL } = import.meta.env; const HAS_EXTENSION = /\.[0-9a-z]+$/i; -interface LinkProps extends React.AnchorHTMLAttributes { +export interface LinkProps + extends React.AnchorHTMLAttributes { href: string; } export function Link({ href, children, ...nativeProps }: LinkProps) { diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 92aad8f..4f785b8 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -4,33 +4,31 @@ import { Link } from "./Link"; const { BASE_URL } = import.meta.env; -interface Props { +export interface NavbarProps { day: number; } -export function Navbar({ day }: Props) { +export function Navbar({ day }: NavbarProps) { return (
-
+
LogoWCF + className="flex justify-center items-center gap-2 font-bold text-2xl !text-yeti-dark" + > + Logo + WCF +
{/* fullscreen background element that you can click to close when it's open */} -
-
+
-
diff --git a/src/components/SolutionChecker.tsx b/src/components/SolutionChecker.tsx deleted file mode 100644 index a16e04d..0000000 --- a/src/components/SolutionChecker.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { useState } from "react"; -import { Button } from "./Button"; - -interface Props { - solution: string; -} - -export function SolutionChecker({ solution }: Props) { - const [input, setInput] = useState(""); - - function checkSolution() { - if (input === solution) { - alert("Correct!"); - } else { - alert("Try again..."); - } - } - - return ( - <> - - - - ); -} diff --git a/src/components/solutions/1.tsx b/src/components/solutions/1.tsx index da78afe..1e600b7 100644 --- a/src/components/solutions/1.tsx +++ b/src/components/solutions/1.tsx @@ -2,7 +2,13 @@ import { useState } from "react"; import { Button } from "../Button"; export default function () { - function AnswerInput({ fileName, solution }: { fileName: string, solution: string }) { + function AnswerInput({ + fileName, + solution, + }: { + fileName: string; + solution: string; + }) { const [input, setInput] = useState(""); function checkSolution() { @@ -14,36 +20,46 @@ export default function () { } return ( - <> - {fileName}: -