diff --git a/apps/site/src/app/(home)/sections/FAQ/FAQ.module.scss b/apps/site/src/app/(home)/sections/FAQ/FAQ.module.scss index 40c67b31..700ae872 100644 --- a/apps/site/src/app/(home)/sections/FAQ/FAQ.module.scss +++ b/apps/site/src/app/(home)/sections/FAQ/FAQ.module.scss @@ -61,7 +61,8 @@ $item-padding-x: 3rem; padding: $mobile-item-padding-y $mobile-item-padding-x; } -.faq-header, .faq-header > * { +.faq-header, +.faq-header > * { font-weight: 600; } diff --git a/apps/site/src/app/schedule/Assets/Circle.module.scss b/apps/site/src/app/schedule/Assets/Circle.module.scss new file mode 100644 index 00000000..cf67b9c7 --- /dev/null +++ b/apps/site/src/app/schedule/Assets/Circle.module.scss @@ -0,0 +1,77 @@ +@use "bootstrap-utils" as bootstrap; +@use "zothacks-theme" as theme; + +.outerCircle { + background-color: theme.$white; + border: 5px solid theme.$lighter-black; + width: 50px; + height: 50px; + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; + z-index: 1; + bottom: 0; + position: absolute; +} + +.innerCircle { + background-color: theme.$red; + min-width: 30px; + min-height: 30px; + border-radius: 50%; + transition-duration: 0.5s; +} + +.textContainer { + top: 45px; + left: 20px; + position: absolute; + min-width: 150px; + transform: translateX(-50%); + text-align: center; + display: flex; + flex-direction: column; + align-items: center; +} + +.location { + width: 300px; + text-align: center; + padding: 0; + margin: 0; + font-size: 1.25rem; + @include bootstrap.media-breakpoint-down(md) { + font-size: 1rem; + width: 160px; + } +} + +.title { + text-align: center; + width: 200px; +} + +.time { + text-align: center; + padding: 0; + margin: 0; + font-size: 1.25rem; + @include bootstrap.media-breakpoint-down(md) { + font-size: 1rem; + } +} + +.virtual { + display: flex; + align-items: baseline; + gap: 5px; + text-decoration: none; + color: theme.$purple; + p { + margin: 0; + padding: 0; + font-weight: bold; + font-size: 1.25rem; + } +} diff --git a/apps/site/src/app/schedule/Assets/Circle.tsx b/apps/site/src/app/schedule/Assets/Circle.tsx new file mode 100644 index 00000000..457b22ab --- /dev/null +++ b/apps/site/src/app/schedule/Assets/Circle.tsx @@ -0,0 +1,81 @@ +"use client"; + +import Image from "next/image"; + +import convertTime from "../convertTime"; + +import cross from "@/assets/images/map2/cross.svg"; +import openNewWindow from "@/assets/icons/open_new_window_purple.svg"; + +import styles from "./Circle.module.scss"; + +interface CircleProps { + title: String; + location: String; + startTime: Date; + endTime: Date; + position: object; + up: boolean; + time: number; + virtual: String; +} + +const EventCircle: React.FC = ({ + title, + location, + startTime, + endTime, + position, + up, + time, + virtual, +}) => { + let curTime = new Date(time); + return ( +
+ {title == "Hacking Ends" ? ( + x + ) : ( +
= startTime + ? curTime > endTime + ? { backgroundColor: "#01a7c5" } + : { backgroundColor: "#ffd600" } + : { backgroundColor: "#bd5a5a" } + } + >
+ )} +
+
{title}
+

{location}

+

{convertTime(startTime, endTime)}

+ {virtual && ( + +

Zoom

+ open +
+ )} +
+
+ ); +}; + +export default EventCircle; diff --git a/apps/site/src/app/schedule/ClipboardSchedule/ClipboardSchedule.module.scss b/apps/site/src/app/schedule/ClipboardSchedule/ClipboardSchedule.module.scss deleted file mode 100644 index 3e58b24c..00000000 --- a/apps/site/src/app/schedule/ClipboardSchedule/ClipboardSchedule.module.scss +++ /dev/null @@ -1,55 +0,0 @@ -@use "bootstrap-utils" as bootstrap; -@use "zothacks-theme" as theme; - -.accordion { - padding-bottom: 120px; - --bs-accordion-btn-icon: url("~@/assets/icons/accordion-btn.svg"); - --bs-accordion-btn-active-icon: url("~@/assets/icons/accordion-btn.svg"); - --bs-accordion-btn-icon-width: 25px; - - button::after { - margin-left: 1rem; - } -} - -.clip { - position: absolute; - width: 75%; - top: 1%; - left: 50%; - transform: translate(-50%, -55%); - z-index: 10; - - @include bootstrap.media-breakpoint-up(lg) { - width: 60%; - } -} -.clipboard { - padding-top: 50px; - @include bootstrap.rfs(8.5rem, border-radius); - background-color: theme.$brown; - padding: 5px; - border: 1.25rem solid theme.$brown; -} - -.clipboardPaper { - @include bootstrap.rfs(7.5rem, border-radius); - background-color: white; -} - -.accordionItem { - border-top: 2px solid theme.$light-blue; - border-bottom: 2px solid theme.$light-blue; -} - -.eventTitle { - font-size: 24px; -} - -.mobileLocation { - text-align: left; - - @include bootstrap.media-breakpoint-up(lg) { - text-align: right; - } -} diff --git a/apps/site/src/app/schedule/ClipboardSchedule/ClipboardSchedule.tsx b/apps/site/src/app/schedule/ClipboardSchedule/ClipboardSchedule.tsx deleted file mode 100644 index 5a21bf47..00000000 --- a/apps/site/src/app/schedule/ClipboardSchedule/ClipboardSchedule.tsx +++ /dev/null @@ -1,170 +0,0 @@ -"use client"; - -import { useState, useEffect } from "react"; - -import Image from "next/image"; -import Accordion from "react-bootstrap/Accordion"; -import Col from "react-bootstrap/Col"; -import Container from "react-bootstrap/Container"; -import Row from "react-bootstrap/Row"; -import { cubicBezier, motion, Variants } from "framer-motion"; -import { toZonedTime } from "date-fns-tz"; -import Confetti from "react-confetti"; -import useWindowSize from "react-use/lib/useWindowSize"; - -import clip from "@/assets/images/clip.svg"; - -import styles from "./ClipboardSchedule.module.scss"; -import Countdown from "./Countdown"; - -const dateTimeFormat = new Intl.DateTimeFormat("en", { - hour: "numeric", - minute: "numeric", -}); - -const monthDayFormat = new Intl.DateTimeFormat("en", { - month: "long", - day: "numeric", -}); - -const weekdayFormat = new Intl.DateTimeFormat("en", { - weekday: "long", -}); - -const variant: Variants = { - initial: { - y: 200, - transformOrigin: "top center", - rotateX: 20, - }, - animate: { - y: 0, - rotateX: 0, - transition: { - duration: 0.7, - ease: cubicBezier(0.85, 0, 0.15, 1), - }, - }, -}; - -interface ClipboardScheduleProps { - schedule: { - title: string; - location?: string | undefined; - virtual?: string | undefined; - startTime: Date; - endTime: Date; - organization?: string | undefined; - hosts?: string[] | undefined; - description: JSX.Element; - }[][]; -} - -// 10/4/23 10AM in UTC -const hackingStarts = new Date(Date.UTC(2023, 10, 4, 17, 0, 0)); -const hackingEnds = new Date(Date.UTC(2023, 10, 5, 5, 0, 0)); - -const ClipboardSchedule: React.FC = ({ schedule }) => { - const { width, height } = useWindowSize(); - const [currDate, setCurrDate] = useState(new Date()); - - useEffect(() => { - const timeUpdater = setInterval(() => setCurrDate(new Date()), 1000); - return () => clearInterval(timeUpdater || undefined); - }, []); - - return ( - <> - {currDate && currDate.getTime() >= hackingEnds.getTime() && ( - - )} - -
- Clipboard clip -
-
- - {currDate.getTime() < hackingStarts.getTime() ? ( - - ) : ( - - )} - - {schedule.map((day, i) => ( -
-

- {weekdayFormat.format( - toZonedTime(day[0].startTime, "America/Los_Angeles"), - )} -

-

- {monthDayFormat.format( - toZonedTime(day[0].startTime, "America/Los_Angeles"), - )} -

- {day.map( - ({ - title, - description, - location, - hosts, - startTime, - endTime, - }) => { - const startTimeZoned = toZonedTime( - startTime, - "America/Los_Angeles", - ), - endTimeZoned = toZonedTime( - endTime, - "America/Los_Angeles", - ); - return ( - - - - - - {title} - - - {/* {hosts?.join()} */} - - - - {location},{" "} - {dateTimeFormat.formatRange( - startTimeZoned, - endTimeZoned, - )} - - - - - {description} - - ); - }, - )} -
- ))} -
-
-
-
- - ); -}; - -export default ClipboardSchedule; diff --git a/apps/site/src/app/schedule/ClipboardSchedule/index.ts b/apps/site/src/app/schedule/ClipboardSchedule/index.ts deleted file mode 100644 index 7e9e66b2..00000000 --- a/apps/site/src/app/schedule/ClipboardSchedule/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from "./ClipboardSchedule"; diff --git a/apps/site/src/app/schedule/ClipboardSchedule/Countdown.module.scss b/apps/site/src/app/schedule/Countdown/Countdown.module.scss similarity index 92% rename from apps/site/src/app/schedule/ClipboardSchedule/Countdown.module.scss rename to apps/site/src/app/schedule/Countdown/Countdown.module.scss index 09a73b68..5cd0b32c 100644 --- a/apps/site/src/app/schedule/ClipboardSchedule/Countdown.module.scss +++ b/apps/site/src/app/schedule/Countdown/Countdown.module.scss @@ -2,12 +2,13 @@ .countdown { margin: 0; - padding: 96px 0 32px 0; + padding-bottom: 50px; opacity: 0; transition: opacity 225ms cubic-bezier(0.32, 0, 0.67, 0); span { text-align: center; + color: white; font-weight: 600; &.time { diff --git a/apps/site/src/app/schedule/ClipboardSchedule/Countdown.tsx b/apps/site/src/app/schedule/Countdown/Countdown.tsx similarity index 94% rename from apps/site/src/app/schedule/ClipboardSchedule/Countdown.tsx rename to apps/site/src/app/schedule/Countdown/Countdown.tsx index bef82fd9..1a8f2d31 100644 --- a/apps/site/src/app/schedule/ClipboardSchedule/Countdown.tsx +++ b/apps/site/src/app/schedule/Countdown/Countdown.tsx @@ -36,7 +36,9 @@ const Countdown: React.FC = ({ > - {Math.floor(remainingSeconds / (60 * 60))} + {Math.floor(remainingSeconds / (60 * 60)) + .toString() + .padStart(2, "0")} : diff --git a/apps/site/src/app/schedule/DayOne/DayOne.module.scss b/apps/site/src/app/schedule/DayOne/DayOne.module.scss new file mode 100644 index 00000000..1ea77cc3 --- /dev/null +++ b/apps/site/src/app/schedule/DayOne/DayOne.module.scss @@ -0,0 +1,86 @@ +@use "bootstrap-utils" as bootstrap; + +.mapContainer { + width: 100vw; + position: relative; + display: flex; + justify-content: center; + align-items: center; + height: 1300px; + @include bootstrap.media-breakpoint-down(md) { + height: 1500px; + } +} + +.map1 { + position: absolute; + width: 80%; + min-width: 1000px; + @include bootstrap.media-breakpoint-down(md) { + display: none; + } +} + +.title { + position: absolute; + top: -70px; + left: 50%; + transform: translateX(-50%); +} + +.mapPath { + position: absolute; + aspect-ratio: 1 / 1; + @include bootstrap.media-breakpoint-down(md) { + width: 265px; + height: 592px; + } +} + +.mobileMap { + position: absolute; + width: 80%; + min-width: 1000px; + height: 70%; + @include bootstrap.media-breakpoint-up(md) { + display: none; + } +} + +.mobilePath { + position: absolute; + height: 100%; + width: 100%; + @include bootstrap.media-breakpoint-up(md) { + display: none; + } +} + +.pathImage { + width: 100%; + height: 100%; + @include bootstrap.media-breakpoint-down(md) { + display: none; + } +} + +@media screen and (min-width: 1501px) { + .mapPath { + width: 966px; + height: 793px; + } +} + +@media screen and (min-width: 1000px) and (max-width: 1500px) { + .mapPath { + width: 772px; + height: 634px; + } +} + +@media screen and (min-width: 768px) and (max-width: 999px) { + .mapPath { + width: 627px; + height: 515px; + } +} diff --git a/apps/site/src/app/schedule/DayOne/DayOne.tsx b/apps/site/src/app/schedule/DayOne/DayOne.tsx new file mode 100644 index 00000000..08fb153f --- /dev/null +++ b/apps/site/src/app/schedule/DayOne/DayOne.tsx @@ -0,0 +1,61 @@ +"use client"; +import Image from "next/image"; + +import EventCircle from "../Assets/Circle"; + +import Map1 from "@/assets/images/map1/map_1.svg"; +import MobileMap from "@/assets/images/map1/mobile_map.svg"; +import MobilePath from "@/assets/images/map1/mobile_path.png"; +import Path from "@/assets/images/map1/map_1_path.png"; + +import styles from "./DayOne.module.scss"; + +interface DayOneProps { + schedule: Array; + time: number; +} + +const DayOne: React.FC = ({ schedule, time }) => { + const positions = [ + { top: "-5px", left: "-10px" }, + { top: "calc(36% - 25px)", left: "50%" }, + { top: "calc(100% - 25px)", left: "calc(100% - 25px)" }, + ]; + return ( + <> +
+ zothacks-map + zothacks-map +
+ zothacks-path + zothacks-path + + {schedule.map((event, i) => ( + + ))} +

Day One

+
+
+ + ); +}; + +export default DayOne; diff --git a/apps/site/src/app/schedule/DayThree/DayThree.module.scss b/apps/site/src/app/schedule/DayThree/DayThree.module.scss new file mode 100644 index 00000000..93c49c58 --- /dev/null +++ b/apps/site/src/app/schedule/DayThree/DayThree.module.scss @@ -0,0 +1,93 @@ +@use "bootstrap-utils" as utils; + +.mapContainer { + width: 100vw; + position: relative; + display: flex; + justify-content: center; + align-items: center; + height: 1300px; +} + +.map3 { + position: absolute; + width: 120%; + min-width: 1400px; +} + +.title { + position: absolute; + top: -250px; + left: 50%; + transform: translateX(-50%); +} + +.mapPath { + position: absolute; +} + +.pathImage { + position: relative; + top: -160px; + left: 15%; + + width: 70%; + height: 160%; + + @include utils.media-breakpoint-down(sm) { + display: none; + } +} + +.mobilePath { + position: relative; + top: -40%; + left: 20%; + + width: 65%; + height: 600px; + + @include utils.media-breakpoint-up(sm) { + display: none; + } +} + +@include utils.media-breakpoint-up(sm) { + .pathImage { + top: 0; + left: 0; + width: 100%; + height: 100%; + } + + .map3 { + position: absolute; + width: 80%; + min-width: 1100px; + } + + .title { + top: -100px; + } +} + +@media screen and (min-width: 1751px) { + .mapPath { + width: 1168px; + height: 598px; + } +} + +@media screen and (min-width: 1450px) and (max-width: 1750px) { + .mapPath { + width: 934px; + height: 478px; + } +} + +@media screen and (max-width: 1451px) { + .mapPath { + width: min(70%, 747px); + height: 382px; + } +} diff --git a/apps/site/src/app/schedule/DayThree/DayThree.tsx b/apps/site/src/app/schedule/DayThree/DayThree.tsx new file mode 100644 index 00000000..0efede02 --- /dev/null +++ b/apps/site/src/app/schedule/DayThree/DayThree.tsx @@ -0,0 +1,66 @@ +"use client"; + +import React from "react"; +import Image from "next/image"; + +import EventCircle from "../Assets/Circle"; +import useWindowWidth from "@/lib/useWindowWidth"; + +import Map3 from "@/assets/images/map3/map_3.svg"; +import Path from "@/assets/images/map3/map_3_path.png"; +import MobilePath from "@/assets/images/map3/map_3_path_mobile.png"; + +import styles from "./DayThree.module.scss"; + +interface DayThreeProps { + schedule: Array; + time: number; +} + +const DayThree: React.FC = ({ schedule, time }) => { + const windowWidth = useWindowWidth(); + const positions = + windowWidth > 576 + ? [ + { top: "-5px", left: "-10px" }, + { top: "calc(53% - 25px)", left: "50%" }, + { top: "calc(100% - 25px)", left: "calc(100% - 50px)" }, + ] + : [ + { top: "-200px", left: "22px" }, + { top: "calc(14% - 25px)", left: "63%" }, + { top: "calc(117% - 25px)", left: "calc(90% - 50px)" }, + ]; + + return ( + <> +
+ zothacks-map +
+ zothacks-path + zothacks-path + {schedule.map((event, i) => ( + + ))} +

Day Three

+
+
+ + ); +}; + +export default DayThree; diff --git a/apps/site/src/app/schedule/DayTwo/DayTwo.module.scss b/apps/site/src/app/schedule/DayTwo/DayTwo.module.scss new file mode 100644 index 00000000..e1eff408 --- /dev/null +++ b/apps/site/src/app/schedule/DayTwo/DayTwo.module.scss @@ -0,0 +1,74 @@ +@use "bootstrap-utils" as bootstrap; + +.mapContainer { + width: 100vw; + position: relative; + display: flex; + justify-content: center; + align-items: center; + height: auto; +} + +.map2 { + position: absolute; + width: 90%; + min-width: 1400px; +} + +.title { + position: absolute; + top: -60px; + left: 50%; + transform: translateX(-50%); +} + +.mapPath { + position: absolute; +} + +.pathImage { + height: 100%; + width: 100%; + @include bootstrap.media-breakpoint-down(md) { + display: none; + } +} + +.mobilePath { + width: 100%; + height: 2690px; + @include bootstrap.media-breakpoint-up(md) { + display: none; + } +} + +@media screen and (min-width: 1601px) { + .mapPath { + width: 1145px; + height: 3049px; + } + .mapContainer { + height: 4000px; + } +} + +@media screen and (min-width: 1351px) and (max-width: 1600px) { + .mapPath { + width: 817px; + height: 2439px; + } + .mapContainer { + height: 3000px; + } +} + +@media screen and (max-width: 1350px) { + .mapPath { + width: min(80%, 677px); + height: 2690px; + } + + .mapContainer { + height: 3000px; + } +} diff --git a/apps/site/src/app/schedule/DayTwo/DayTwo.tsx b/apps/site/src/app/schedule/DayTwo/DayTwo.tsx new file mode 100644 index 00000000..7073808d --- /dev/null +++ b/apps/site/src/app/schedule/DayTwo/DayTwo.tsx @@ -0,0 +1,85 @@ +"use client"; + +import React from "react"; +import Image from "next/image"; + +import EventCircle from "../Assets/Circle"; +import useWindowWidth from "@/lib/useWindowWidth"; + +import Map2 from "@/assets/images/map2/map_2.svg"; +import Path from "@/assets/images/map2/map_2_path.png"; +import MobilePath from "@/assets/images/map2/map_2_path_mobile.png"; + +import styles from "./DayTwo.module.scss"; + +interface DayTwoProps { + schedule: Array; + time: number; +} + +const DayTwo: React.FC = ({ schedule, time }) => { + const windowWidth = useWindowWidth(); + const positions = + windowWidth > 768 + ? [ + { top: "-0.5%", left: "16%" }, + { top: "1.5%", left: "60%" }, + { top: "13.5%", left: "65%" }, + { top: "24%", left: "55%" }, + { top: "28.5%", left: "32%" }, + { top: "43%", left: "23%" }, + { top: "44.8%", left: "60%" }, + { top: "59.5%", left: "38%" }, + { top: "70%", left: "30%" }, + { top: "80.5%", left: "70%" }, + { top: "82.5%", left: "20%" }, + { top: "95%", left: "50%" }, + { top: "99%", left: "92%" }, + ] + : [ + { top: "-0.5%", left: "16%" }, + { top: "-0.4%", left: "70%" }, + { top: "13.5%", left: "65%" }, + { top: "20%", left: "18%" }, + { top: "28%", left: "32%" }, + { top: "43%", left: "23%" }, + { top: "50%", left: "74%" }, + { top: "59%", left: "38%" }, + { top: "71%", left: "30%" }, + { top: "80.5%", left: "70%" }, + { top: "82.5%", left: "20%" }, + { top: "94%", left: "10%" }, + { top: "98.5%", left: windowWidth < 576 ? "79%" : "90%" }, + ]; + return ( + <> +
+ zothacks-map +
+ zothacks-path + zothacks-path + {schedule.map((event, i) => ( + + ))} +

Day Two

+
+
+ + ); +}; + +export default DayTwo; diff --git a/apps/site/src/app/schedule/Header/Header.module.scss b/apps/site/src/app/schedule/Header/Header.module.scss new file mode 100644 index 00000000..2101401d --- /dev/null +++ b/apps/site/src/app/schedule/Header/Header.module.scss @@ -0,0 +1,8 @@ +.header { + margin-top: 200px; + height: auto; + display: flex; + flex-direction: column; + gap: 50px; + align-items: center; +} diff --git a/apps/site/src/app/schedule/Header/Header.tsx b/apps/site/src/app/schedule/Header/Header.tsx new file mode 100644 index 00000000..2fef4767 --- /dev/null +++ b/apps/site/src/app/schedule/Header/Header.tsx @@ -0,0 +1,35 @@ +"use client"; + +import Countdown from "../Countdown/Countdown"; + +import Image from "next/image"; +import Chest from "@/assets/images/schedule-chest.png"; +import OpenChest from "@/assets/images/schedule-chest-open.svg"; +import Title from "@/assets/images/schedule-title.png"; +import styles from "./Header.module.scss"; + +interface HeaderProps { + time: number; +} + +const Header: React.FC = ({ time }) => { + const hackingStarts = new Date("2024-11-02T10:00:00"); + const hackingEnds = new Date("2024-11-02T22:00:00"); + return ( + <> +
+ title + {time < hackingEnds.getTime() && Chest} + {time >= hackingEnds.getTime() && Chest} + = hackingStarts.getTime() ? hackingEnds : hackingStarts + } + isHackingStarted={time >= hackingStarts.getTime()} + /> +
+ + ); +}; + +export default Header; diff --git a/apps/site/src/app/schedule/Schedule.tsx b/apps/site/src/app/schedule/Schedule.tsx index 3795187e..9e7acd6e 100644 --- a/apps/site/src/app/schedule/Schedule.tsx +++ b/apps/site/src/app/schedule/Schedule.tsx @@ -1,23 +1,9 @@ -import { PortableText } from "@portabletext/react"; -import ClipboardSchedule from "./ClipboardSchedule"; import { getSchedule } from "./getSchedule"; import styles from "./Schedule.module.scss"; +import ScheduleTimer from "./ScheduleTimer"; export default async function Schedule() { - const days = await getSchedule(); - - const schedule = days.map((events) => - events.map(({ description, ...event }) => ({ - ...event, - description: , - })), - ); - - return ( -
-

Schedule

- -
- ); + const schedule = await getSchedule(); + return ; } diff --git a/apps/site/src/app/schedule/ScheduleTimer.tsx b/apps/site/src/app/schedule/ScheduleTimer.tsx new file mode 100644 index 00000000..52cc1457 --- /dev/null +++ b/apps/site/src/app/schedule/ScheduleTimer.tsx @@ -0,0 +1,50 @@ +"use client"; + +import Header from "./Header/Header"; +import DayOne from "./DayOne/DayOne"; +import DayTwo from "./DayTwo/DayTwo"; +import DayThree from "./DayThree/DayThree"; +import { useEffect, useState } from "react"; + +interface ScheduleProps { + schedule: Array; +} + +const ScheduleTimer: React.FC = ({ schedule }) => { + const [time, setTime] = useState(Date.now()); + + useEffect(() => { + function updatePerSecond() { + setTime(Date.now()); + } + let ret = setInterval(updatePerSecond, 1000); + + return () => clearInterval(ret); + }); + + const scheduleFlat = schedule.flat(); + const dayOne = scheduleFlat.filter( + (s) => s.startTime.getTime() < new Date("2024-11-2"), + ); + const dayTwo = scheduleFlat.filter( + (s) => + s.startTime.getTime() < new Date("2024-11-3") && + s.startTime.getTime() > new Date("2024-11-2"), + ); + const dayThree = scheduleFlat.filter( + (s) => + s.startTime.getTime() < new Date("2024-11-4") && + s.startTime.getTime() > new Date("2024-11-3"), + ); + + return ( + <> +
+ + + + + ); +}; + +export default ScheduleTimer; diff --git a/apps/site/src/app/schedule/convertTime.ts b/apps/site/src/app/schedule/convertTime.ts new file mode 100644 index 00000000..a27fce4f --- /dev/null +++ b/apps/site/src/app/schedule/convertTime.ts @@ -0,0 +1,17 @@ +function convertTime(start: Date, end: Date) { + let startHour = ((start.getHours() + 11) % 12) + 1; + let endHour = ((end.getHours() + 11) % 12) + 1; + + let startStr = `${startHour.toString()}:${start.getMinutes().toString().padStart(2, "0")}`; + let endStr = `${endHour.toString()}:${end.getMinutes().toString().padStart(2, "0")}`; + let suffix = end.getHours() <= 11 ? "am" : "pm"; + let prefix = ""; + + if (start.getHours() == 11 && end.getHours() > 11) prefix = "am"; + if (start.getHours() == 23 && end.getHours() <= 11) prefix = "pm"; + + if (start.getTime() == end.getTime()) return `${endStr}${suffix}`; + return `${startStr}${prefix}-${endStr}${suffix}`; +} + +export default convertTime; diff --git a/apps/site/src/assets/icons/open_new_window_purple.svg b/apps/site/src/assets/icons/open_new_window_purple.svg new file mode 100644 index 00000000..9d8e039a --- /dev/null +++ b/apps/site/src/assets/icons/open_new_window_purple.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/site/src/assets/images/map1/map_1.svg b/apps/site/src/assets/images/map1/map_1.svg new file mode 100644 index 00000000..50f8d144 --- /dev/null +++ b/apps/site/src/assets/images/map1/map_1.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/site/src/assets/images/map1/map_1_path.png b/apps/site/src/assets/images/map1/map_1_path.png new file mode 100644 index 00000000..859164e7 Binary files /dev/null and b/apps/site/src/assets/images/map1/map_1_path.png differ diff --git a/apps/site/src/assets/images/map1/mobile_map.svg b/apps/site/src/assets/images/map1/mobile_map.svg new file mode 100644 index 00000000..c51b9260 --- /dev/null +++ b/apps/site/src/assets/images/map1/mobile_map.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/site/src/assets/images/map1/mobile_path.png b/apps/site/src/assets/images/map1/mobile_path.png new file mode 100644 index 00000000..b1986b10 Binary files /dev/null and b/apps/site/src/assets/images/map1/mobile_path.png differ diff --git a/apps/site/src/assets/images/map2/cross.svg b/apps/site/src/assets/images/map2/cross.svg new file mode 100644 index 00000000..73169729 --- /dev/null +++ b/apps/site/src/assets/images/map2/cross.svg @@ -0,0 +1,4 @@ + + + + diff --git a/apps/site/src/assets/images/map2/map_2.svg b/apps/site/src/assets/images/map2/map_2.svg new file mode 100644 index 00000000..b25a6a2c --- /dev/null +++ b/apps/site/src/assets/images/map2/map_2.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/site/src/assets/images/map2/map_2_path.png b/apps/site/src/assets/images/map2/map_2_path.png new file mode 100644 index 00000000..fb89311a Binary files /dev/null and b/apps/site/src/assets/images/map2/map_2_path.png differ diff --git a/apps/site/src/assets/images/map2/map_2_path_mobile.png b/apps/site/src/assets/images/map2/map_2_path_mobile.png new file mode 100644 index 00000000..b45b2da9 Binary files /dev/null and b/apps/site/src/assets/images/map2/map_2_path_mobile.png differ diff --git a/apps/site/src/assets/images/map3/map_3.svg b/apps/site/src/assets/images/map3/map_3.svg new file mode 100644 index 00000000..83575fc6 --- /dev/null +++ b/apps/site/src/assets/images/map3/map_3.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/site/src/assets/images/map3/map_3_path.png b/apps/site/src/assets/images/map3/map_3_path.png new file mode 100644 index 00000000..604eedb1 Binary files /dev/null and b/apps/site/src/assets/images/map3/map_3_path.png differ diff --git a/apps/site/src/assets/images/map3/map_3_path_mobile.png b/apps/site/src/assets/images/map3/map_3_path_mobile.png new file mode 100644 index 00000000..5bd5651b Binary files /dev/null and b/apps/site/src/assets/images/map3/map_3_path_mobile.png differ diff --git a/apps/site/src/assets/images/schedule-chest-open.svg b/apps/site/src/assets/images/schedule-chest-open.svg new file mode 100644 index 00000000..cdc879dc --- /dev/null +++ b/apps/site/src/assets/images/schedule-chest-open.svg @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/site/src/assets/images/schedule-chest.png b/apps/site/src/assets/images/schedule-chest.png new file mode 100644 index 00000000..bbc4f775 Binary files /dev/null and b/apps/site/src/assets/images/schedule-chest.png differ diff --git a/apps/site/src/assets/images/schedule-title.png b/apps/site/src/assets/images/schedule-title.png new file mode 100644 index 00000000..75fee73f Binary files /dev/null and b/apps/site/src/assets/images/schedule-title.png differ diff --git a/apps/site/src/lib/useWindowWidth.tsx b/apps/site/src/lib/useWindowWidth.tsx index cad6a061..7c208ea9 100644 --- a/apps/site/src/lib/useWindowWidth.tsx +++ b/apps/site/src/lib/useWindowWidth.tsx @@ -1,13 +1,15 @@ import { useState, useEffect } from "react"; export default function useWindowWidth() { - const [windowWidth, setWindowWidth] = useState(window.innerWidth); + const [windowWidth, setWindowWidth] = useState(0); useEffect(() => { function handleResize() { setWindowWidth(window.innerWidth); } + handleResize(); + window.addEventListener("resize", handleResize); return () => window.removeEventListener("resize", handleResize); });