Skip to content

Commit

Permalink
Implement monthly view calendar for admin scheduling UI (#207)
Browse files Browse the repository at this point in the history
* Implement month view calendar

* Grey out days with no events

* Move event type to separate file

* Refactor calendar files to separate directory

* Move MonthEvent to types file

* Update CreatePostingShifts.tsx

* Update CalendarTypes.ts

* Implement month view calendar

* Grey out days with no events

* Remove unused imports

* Move event type to separate file

* Refactor calendar files to separate directory

* Remove calendar preview in Default.tsx

* Update Default.tsx
  • Loading branch information
7tint committed Mar 31, 2022
1 parent f9094c4 commit 3db1450
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 12 deletions.
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

0 comments on commit 3db1450

Please sign in to comment.