diff --git a/src/pages/EventPopup.tsx b/src/pages/EventPopup.tsx new file mode 100644 index 0000000..92e47df --- /dev/null +++ b/src/pages/EventPopup.tsx @@ -0,0 +1,69 @@ +import { cn } from "@/lib/utils"; +import { Clock, MapPin } from "lucide-react"; +import { ScheduleEvent } from "./ScheduleEvent"; + +/** + * EventPopupProp that allows onClose() to be passed in + */ +interface EventPopupProps extends ScheduleEvent { + onClose: () => void, + typeColors: Record +} + +export default function EventPopup(event: EventPopupProps){ + + return ( +
+ {/* If the user clicks anywhere, then the popup is closed */} + +
+ ); +}; \ No newline at end of file diff --git a/src/pages/Schedule.tsx b/src/pages/Schedule.tsx index 1334254..cf88a50 100644 --- a/src/pages/Schedule.tsx +++ b/src/pages/Schedule.tsx @@ -1,18 +1,43 @@ import { Layout } from "@/components/Layout"; import { useState } from "react"; import { cn } from "@/lib/utils"; -import { Clock, MapPin, Users } from "lucide-react"; +import { Clock, MapPin } from "lucide-react"; +import { ScheduleEvent } from "./ScheduleEvent"; +import EventPopup from "./EventPopup"; type Day = "friday" | "saturday" | "sunday"; -interface ScheduleEvent { - time: string; - title: string; - description: string; - location: string; - type: "social" | "main" | "food" | "activity"; -} +//----- Constants & Arrays for Event Data-----// +/** + * The time frame for events for the day in hours. + * (id) is only used for keys and does not matter the order, just don't repeat them. + */ +const times = [ + { id: 1, hour: '05', timeOfDay: "am"}, + { id: 2, hour: '06', timeOfDay: "am"}, + { id: 3, hour: '07', timeOfDay: "am"}, + { id: 4, hour: '08', timeOfDay: "am"}, + { id: 5, hour: '09', timeOfDay: "am"}, + { id: 6, hour: '10', timeOfDay: "am"}, + { id: 7, hour: '11', timeOfDay: "am"}, + { id: 8, hour: '12', timeOfDay: "pm"}, + { id: 9, hour: '01', timeOfDay: "pm"}, + { id: 10, hour: '02', timeOfDay: "pm"}, + { id: 11, hour: '03', timeOfDay: "pm"}, + { id: 12, hour: '04', timeOfDay: "pm"}, + { id: 13, hour: '05', timeOfDay: "pm"}, + { id: 14, hour: '06', timeOfDay: "pm"}, + { id: 15, hour: '07', timeOfDay: "pm"}, + { id: 16, hour: '08', timeOfDay: "pm"}, + { id: 17, hour: '09', timeOfDay: "pm"}, + { id: 18, hour: '10', timeOfDay: "pm"}, + { id: 19, hour: '11', timeOfDay: "pm"}, + { id: 20, hour: '12', timeOfDay: "am"}, + ] +/** + * Holds the data for events shown on the Schedule Page + */ // PLACEHOLDER: Update all event times, descriptions, and locations as they are finalized const scheduleData: Record = { friday: [ @@ -114,14 +139,189 @@ const dayLabels: Record = { }; const typeColors: Record = { - social: "bg-blue-500/20 text-blue-400 border-blue-500/30", + social: "bg-blue-500/70 text-blue-200 border-blue-500/30", main: "bg-gradient-csh text-primary-foreground", - food: "bg-amber-500/20 text-amber-400 border-amber-500/30", - activity: "bg-emerald-500/20 text-emerald-400 border-emerald-500/30", + food: "bg-amber-500/70 text-amber-200 border-amber-500/30", + activity: "bg-emerald-500/70 text-emerald-200 border-emerald-500/30", }; +/** + * The number of sections in the grid + */ +var SectionCount = 0; + +//----- Helper Functions -----// +/** + * // calculate the row index an event should start at given its start time (in military time) + * @param time accepts the following input format: "11:00 AM - 1:00 PM" + * @returns index of the row + */ +const baseHour = 5; // the first viable hour (currently 5am) +function timeToRowStart(time: string): number { + + const startWithTimeOfDay = time.split(" - ")[0]; + + var hhmm = startWithTimeOfDay.split(" "); // process the time into something usable by the function + + if(hhmm[1] == "PM"){ // convert to military time if needed + const startTime = hhmm[0].split(":"); + + if(parseInt(startTime[0], 10) != 12){ // ignore 12pm + hhmm[0] = (parseInt(startTime[0], 10) + 12).toString() + ":" + startTime[1]; + } + } + + const [hString, mString] = hhmm[0].split(":"); + const h = parseInt(hString, 10); + const m = parseInt(mString, 10); + const hourOffset = (h - baseHour) * 4; // calculate the hour + const quarterOffset = Math.floor(m / 15); // calculate the quarter in the hour + return hourOffset + quarterOffset + 1; // return the row index +} + +/** + * Duration in rows based on 15-minute slots. + * @param time accepts the following input format: "11:00 AM - 1:00 PM" + * @returns the number of rows that the given time frame spans + */ +function durationToRowSpan(time: string): number { + + const [startWithTimeOfDay, endWithTimeOfDay] = time.split(" - "); + + var start = startWithTimeOfDay.split(" "); // process the time into something usable by the function + var end = endWithTimeOfDay.split(" "); + + if(start[1] == "PM"){ // convert to military time if needed + const startTime = start[0].split(":"); + + if(parseInt(startTime[0], 10) != 12){ // ignore 12pm + start[0] = (parseInt(startTime[0], 10) + 12).toString() + ":" + startTime[1]; + } + } + if(end[1] == "PM"){ // convert to military time if needed + const endTime = end[0].split(":"); + + if(parseInt(endTime[0], 10) != 12){ // ignore 12pm + end[0] = (parseInt(endTime[0], 10) + 12).toString() + ":" + endTime[1]; + } + } + else if(end[1] == "AM"){ // convert to military time if needed + const endTime = end[0].split(":"); + if(endTime[0] == "12"){ // can end at 12AM + end[0] = (parseInt(endTime[0], 10) + 12).toString() + ":" + endTime[1]; + } + } + else if(end[0].toLowerCase() == "late"){ // treat late as if it was 1am + end[0] = "25:00"; + } + + const toMinutes = (t: string) => { // helper function for + const [hStr, mStr] = t.split(":"); + return parseInt(hStr, 10) * 60 + parseInt(mStr, 10); + }; + + const minutes = toMinutes(end[0]) - toMinutes(start[0]); + return Math.max(1, Math.ceil(minutes / 15)); +} + +/** + * Calculate the next column to place events in. (iterates between columns 2, 3, and 4) + */ +var currentCol = 2; +function nextColumn(): number { + if(currentCol > 4){ + currentCol = 2; + } + return currentCol++; +} + +/** + * Reset the currentCol to 2 + */ +function resetCurrentCol(): void { + currentCol = 2; +} + +/** + * Increments the SectionCount by 1 + */ +function incrementSectionCount(): void{ + SectionCount++; +} + +/** + * Increments the SectionCount by (i) + */ +function incrementSectionCountBy(i: number): void{ + SectionCount += i; +} + +/** + * Resets the SectionCount to 0 + */ +function resetSectionCount(){ + SectionCount = 0; +} + +/** + * Returns the number of unused cells in the grid + * @returns number + */ +function getEmptySpacesCount(): number{ + return (240);// - SectionCount; +} + +/** + * Given an index, returns the spacer's column + * @param index index of the spacer + * @returns number + */ +function setSpacerColumn(index: number): number { + if(index % 3 == 0){ + return 2; + } + else if((index - 1) % 3 == 0){ + return 3; + } + else if((index - 2) % 3 == 0){ + return 4; + } +} + +/** + * Given an index, returns the spacer's row + * @param index index of the spacer + * @returns number + */ +function setSpacerRow(index: number): number { + if(index % 3 == 0){ + return (index / 3) + 1; + } + else if((index - 1) % 3 == 0){ + return ((index - 1) / 3) + 1; + } + else if((index - 2) % 3 == 0){ + return ((index - 2) / 3) + 1; + } +} + +//----- Webpage HTML -----// const Schedule = () => { const [selectedDay, setSelectedDay] = useState("friday"); + const [openEvent, setOpenEvent] = useState(null); + + resetSectionCount(); // reset the section count on the page reloading + resetCurrentCol(); // reset the currentCol on page refresh + + /** + * Given an event, returns an EventPopup element + * @param event an event + * @returns EventPopup + */ + function openEventPopup(event: ScheduleEvent) { + console.log("I WAS RAN") + setOpenEvent(event); + } return ( @@ -133,7 +333,7 @@ const Schedule = () => { Event Schedule

- Three days of events, activities, and celebrations. Click on a day to see what's happening. + Three days of events, activities, and celebrations.

@@ -146,7 +346,7 @@ const Schedule = () => { {(Object.keys(scheduleData) as Day[]).map((day) => ( ))} + - + + + {openEvent && ( + setOpenEvent(null)} + typeColors = {typeColors} + /> + )} + - {/* Remove this portion */} - {/* Legend */} + {/* Remove this portion + {/* Legend }
@@ -251,9 +512,9 @@ const Schedule = () => {
-
+ */}
); -}; +}; export default Schedule; diff --git a/src/pages/ScheduleEvent.ts b/src/pages/ScheduleEvent.ts new file mode 100644 index 0000000..3b02c1a --- /dev/null +++ b/src/pages/ScheduleEvent.ts @@ -0,0 +1,10 @@ +/** + * Interface for an Event on the schedule + */ +export interface ScheduleEvent { + time: string, + title: string, + description: string, + location: string, + type: "social" | "main" | "food" | "activity" +} \ No newline at end of file