Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement monthly view calendar for admin scheduling UI #207

Merged
merged 14 commits into from
Mar 31, 2022
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"@emotion/styled": "^11",
"@fontsource/inter": "^4.5.1",
"@fontsource/raleway": "^4.5.0",
"@fullcalendar/daygrid": "^5.10.1",
"@fullcalendar/interaction": "^5.10.1",
"@fullcalendar/react": "^5.10.1",
"@fullcalendar/timegrid": "^5.10.1",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* General Full Calendar styling */
a:hover {
text-decoration: none;
color: inherit;
Expand Down Expand Up @@ -70,3 +71,31 @@ a:hover {
.fc .fc-timegrid-col.fc-day-today {
background-color: inherit;
}

/* Month View Calendar */
#admin-calendar > .fc-theme-standard .fc-scrollgrid {
border: 1px solid #ddd;
}

.fc .fc-daygrid-day-number {
position: absolute;
top: 3px;
right: 3px;
}

.fc-daygrid-day.fc-day-other,
.fc-daygrid-day.fc-day-no-events {
background-color: #f4f4f4;
}

.fc-daygrid-event-dot.fc-event-saved {
border-color: #38a169;
}

.fc-daygrid-event-dot.fc-event-unsaved {
border-color: #e53e3e;
}

.fc .fc-daygrid-day.fc-day-today {
background-color: #faf5ff;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import React from "react";
import FullCalendar, {
DayCellContentArg,
EventContentArg,
EventInput,
} from "@fullcalendar/react";
import dayGridPlugin from "@fullcalendar/daygrid";
import { Box } from "@chakra-ui/react";

import { Event, MonthEvent } from "../../../types/CalendarTypes";
import colors from "../../../theme/colors";
import "./Calendar.css";

export const ADMIN_SHIFT_CALENDAR_TEST_EVENTS: MonthEvent[] = [
{
id: "1",
groupId: "unsaved",
start: new Date("2022-03-01 09:00:00 UTC"),
end: new Date("2022-03-01 10:00:00 UTC"),
},
{
id: "2",
groupId: "unsaved",
start: new Date("2022-03-01 10:00:00 UTC"),
end: new Date("2022-03-01 11:30:00 UTC"),
},
{
id: "3",
groupId: "saved",
start: new Date("2022-03-01 15:00:00 UTC"),
end: new Date("2022-03-01 17:00:00 UTC"),
},
{
id: "4",
groupId: "unsaved",
start: new Date("2022-03-01 17:15:00 UTC"),
end: new Date("2022-03-01 19:00:00 UTC"),
},
{
id: "5",
groupId: "saved",
start: new Date("2022-03-02 05:00:00 UTC"),
end: new Date("2022-03-02 13:00:00 UTC"),
},
{
id: "6",
groupId: "saved",
start: new Date("2022-03-14 14:00:00 UTC"),
end: new Date("2022-03-14 15:00:00 UTC"),
},
{
id: "7",
groupId: "unsaved",
start: new Date("2022-03-17 11:00:00 UTC"),
end: new Date("2022-03-17 13:00:00 UTC"),
},
{
id: "7",
groupId: "saved",
start: new Date("2022-03-17 09:00:00 UTC"),
end: new Date("2022-03-17 11:00:00 UTC"),
},
{
id: "7",
groupId: "unsaved",
start: new Date("2022-03-17 13:00:00 UTC"),
end: new Date("2022-03-17 15:00:00 UTC"),
},
];

// Events can be passed in any order (does not have to be sorted).
// AdminShiftCalendar assumes that all events are in the same month.
type AdminShiftCalendarProps = {
events: Event[];
};

const MonthlyViewShiftCalendar = ({
events,
}: AdminShiftCalendarProps): React.ReactElement => {
const displayCustomEvent = (content: EventContentArg) => {
return (
<>
{content.event.groupId === "saved" ? (
<div className="fc-daygrid-event-dot fc-event-saved" />
) : (
<div className="fc-daygrid-event-dot fc-event-unsaved" />
)}

{content.timeText}
</>
);
};

// applyCellClasses is used to compute the day cell background color.
const applyCellClasses = (day: DayCellContentArg) => {
// FullCalendar doesn't support retrieving events of a day, so we have to
// iterate through all events to find the ones that match the day.
const dayEvents = events.filter((event) => {
return event.start?.getUTCDate() === day.date.getUTCDate();
});

return dayEvents.length > 0 ? "fc-day-has-event" : "fc-day-no-events";
};

return (
<Box id="admin-calendar">
<FullCalendar
dayMaxEvents={3}
displayEventEnd
dayCellClassNames={(day: DayCellContentArg) => applyCellClasses(day)}
editable
// eventClick --> Show side panel, TODO in ticket #176
eventColor={colors.violet}
eventContent={displayCustomEvent}
events={events as EventInput[]}
eventTimeFormat={{
hour: "numeric",
minute: "2-digit",
meridiem: "short",
}}
fixedWeekCount={false}
headerToolbar={false}
initialDate={events.length > 0 ? events[0].start : new Date()}
initialView="dayGridMonth"
plugins={[dayGridPlugin]}
selectMirror
selectable
timeZone="UTC"
/>
</Box>
);
};

export default MonthlyViewShiftCalendar;
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,10 @@ import {
ModalOverlay,
} from "@chakra-ui/react";
import colors from "../../../theme/colors";
import "./ShiftCalendar.css";
import { Event } from "../../../types/CalendarTypes";
import "./Calendar.css";
import { getTime, getWeekday } from "../../../utils/DateTimeUtils";

export type Event = {
id: string;
start: Date;
end: Date;
};

type ShiftCalendarProps = {
events: Event[];
selectedEvent: Event | null;
Expand All @@ -38,7 +33,7 @@ type ShiftCalendarProps = {
initialDate?: string;
};

const ShiftCalendar = ({
const WeekViewShiftCalendar = ({
events,
selectedEvent,
setSelectedEvent,
Expand Down Expand Up @@ -127,4 +122,4 @@ const ShiftCalendar = ({
);
};

export default ShiftCalendar;
export default WeekViewShiftCalendar;
5 changes: 3 additions & 2 deletions frontend/src/components/admin/posting/CreatePostingShifts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ import {
ADMIN_POSTING_CREATE_SHIFTS_TIME,
} from "../../../constants/Copy";
import PostingContextDispatcherContext from "../../../contexts/admin/PostingContextDispatcherContext";
import ShiftCalendar, { Event } from "../ShiftCalendar/ShiftCalendar";
import WeekViewShiftCalendar from "../ShiftCalendar/WeekViewShiftCalendar";
import { Event } from "../../../types/CalendarTypes";
import { Shift } from "../../../types/PostingContextTypes";
import { RecurrenceInterval } from "../../../types/PostingTypes";
import {
Expand Down Expand Up @@ -262,7 +263,7 @@ const CreatePostingShifts: React.FC<CreatePostingShiftsProps> = ({
* https://github.com/fullcalendar/fullcalendar/issues/4684#issuecomment-620787260
*/}
<div key={startDate}>
<ShiftCalendar
<WeekViewShiftCalendar
events={events}
selectedEvent={selectedEvent}
setSelectedEvent={setSelectedEvent}
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/types/CalendarTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export type Event = {
id: string;
start: Date;
end: Date;
};

export type MonthEvent = Event & {
groupId: string;
};
2 changes: 1 addition & 1 deletion frontend/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1989,7 +1989,7 @@
dependencies:
tslib "^2.1.0"

"@fullcalendar/daygrid@~5.10.1":
"@fullcalendar/daygrid@^5.10.1", "@fullcalendar/daygrid@~5.10.1":
version "5.10.1"
resolved "https://registry.yarnpkg.com/@fullcalendar/daygrid/-/daygrid-5.10.1.tgz#bdee4f58364fdab631b2abf8b56094ab5776f203"
integrity sha512-sfUMP+rew0krsBffgNcWWKhBCiyytGfRKZJoc64E8ohX7VWjPcPZuB1xgO5U4wPLmNkT0rZiHoGeQGTXw1+ZKg==
Expand Down