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

Final bugs + features #97

Merged
merged 11 commits into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/Logo.svg" />
<link rel="icon" type="image/svg+xml" href="/Logo.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>AISS Schedule Planner</title>
</head>
Expand Down
14 changes: 14 additions & 0 deletions public/MoreInfoEvent.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
65 changes: 65 additions & 0 deletions public/MoreInfoTable.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -34,25 +34,27 @@ import PlannedEvent, { convertTimeToMinutes } from '../Planner/PlannedEvent';
import RemoveTimelineEventModal from '../Planner/RemoveTimelineEventModal';

const schema = yup.object({
startTime: yup.string().required('Start time is required').test('is-after-7-am', 'Start time cannot be earlier than 7 AM', function(startTime) {
return startTime && startTime >= "07:00";
startTime: yup.string().required('Start time is required').test('is-after-7-am', 'Start time cannot be earlier than 7 AM', function(startTime) {
return startTime && startTime >= "07:00";
}),
endTime: yup.string()
.required('End time is required')
.test('is-after', 'End time must be after start time', function(endTime) {
const startTime = this.parent.startTime;
return startTime && endTime && startTime < endTime;
}).test('is-before-11-pm', 'End time must be earlier than 11 PM', function(endTime) {
return endTime && endTime <= "23:00";
}),
endTime: yup.string()
.required('End time is required')
.test('is-after', 'End time must be after start time', function(endTime) {
const startTime = this.parent.startTime;
return startTime && endTime && startTime < endTime;
}).test('is-before-11-pm', 'End time must be earlier than 11 PM', function(endTime) {
return endTime && endTime <= "23:00";
}),
host: yup.string().max(50, 'Host exceeds 50 character limit').default('').nullable(),
title: yup.string().required('Title Required').max(50, 'Title exceeds 50 character limit'),
description: yup
.string()
.max(256, 'Description exceeds 256 character limit')
.default('')
.nullable(),
tentative: yup.boolean()
subject: yup.array().min(1, 'Please select at least one subject').required(),
eventType: yup.array().min(1, 'Please select at least one event type').required(),
host: yup.string().max(50, 'Host exceeds 50 character limit').default('').nullable(),
title: yup.string().required('Title Required').max(50, 'Title exceeds 50 character limit'),
description: yup
.string()
.max(256, 'Description exceeds 256 character limit')
.default('')
.nullable(),
tentative: yup.boolean()
});

const AddEventToPublishedScheduleForm = ({ closeForm }) => {
Expand Down Expand Up @@ -104,7 +106,14 @@ const AddEventToPublishedScheduleForm = ({ closeForm }) => {
} else {
setPlannedEvents(plannedEvents.filter(e => e.id != -1));
}
}, [formData])
}, [formData]);
michellelin1 marked this conversation as resolved.
Show resolved Hide resolved

useEffect(() => {
setValue('season', filterValues.season);
setValue('year', filterValues.year);
setValue('subject', filterValues.subject);
setValue('eventType', filterValues.eventType);
}, [filterValues]);
michellelin1 marked this conversation as resolved.
Show resolved Hide resolved

const toast = useToast();
const {
Expand Down Expand Up @@ -360,8 +369,8 @@ const AddEventToPublishedScheduleForm = ({ closeForm }) => {
<Flex justifyContent="space-between">
{/* SUBJECT */}
<Box mb="1rem">
<FormControl>
<FormLabel fontWeight="bold" color="gray.600">Subject</FormLabel>
<FormControl isInvalid={errors && errors.subject}>
<FormLabel fontWeight="bold" color="gray.600">Subject *</FormLabel>
<Dropdown
options={subjectOptions}
filter={subjectFilter}
Expand All @@ -370,13 +379,16 @@ const AddEventToPublishedScheduleForm = ({ closeForm }) => {
badgeColor="#E8D7FF"
width="28vw"
/>
<FormErrorMessage>
{errors.subject && errors.subject.message}
</FormErrorMessage>
</FormControl>
</Box>

{/* EVENT TYPE */}
<Box mb="1rem">
<FormControl>
<FormLabel fontWeight="bold" color="gray.600">Event Type</FormLabel>
<FormControl isInvalid={errors && errors.eventType}>
<FormLabel fontWeight="bold" color="gray.600">Event Type *</FormLabel>
<Dropdown
options={eventOptions}
filter={eventFilter}
Expand All @@ -385,6 +397,9 @@ const AddEventToPublishedScheduleForm = ({ closeForm }) => {
badgeColor="#CFDCFF"
width="28vw"
/>
<FormErrorMessage>
{errors.eventType && errors.eventType.message}
</FormErrorMessage>
</FormControl>
</Box>
</Flex>
Expand Down
26 changes: 22 additions & 4 deletions src/components/Catalog/CreateEventForm/CreateEventForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
} from '../../Catalog/SearchFilter/filterOptions';
import useSearchFilters from '../../Catalog/SearchFilter/useSearchFilters';
import Dropdown from '../../Dropdown/Dropdown';
import { useEffect } from 'react';

const schema = yup.object({
host: yup.string().max(50, 'Host exceeds 50 character limit').default('').nullable(),
Expand All @@ -32,11 +33,14 @@ const schema = yup.object({
.max(256, 'Description exceeds 256 character limit')
.default('')
.nullable(),
subject: yup.array().min(1, 'Please select at least one subject').required(),
eventType: yup.array().min(1, 'Please select at least one event type').required(),
});

const CreateEventForm = ({ eventData, setDataShouldRevalidate, closeModal }) => {
const toast = useToast();
const {
setValue,
handleSubmit,
register,
reset,
Expand All @@ -48,6 +52,7 @@ const CreateEventForm = ({ eventData, setDataShouldRevalidate, closeModal }) =>

const submitData = async data => {
const { host, title, description } = data;
console.log(data);
const season = filterValues.season;
const eventType = filterValues.eventType;
const year = filterValues.year;
Expand Down Expand Up @@ -111,6 +116,13 @@ const CreateEventForm = ({ eventData, setDataShouldRevalidate, closeModal }) =>
const { filters, filterValues } = useSearchFilters();
const [seasonFilter, yearFilter, subjectFilter, eventFilter] = filters;

useEffect(() => {
setValue('season', filterValues.season);
setValue('year', filterValues.year);
setValue('subject', filterValues.subject);
setValue('eventType', filterValues.eventType);
}, [filterValues]);
michellelin1 marked this conversation as resolved.
Show resolved Hide resolved

return (
<Box width="80%" m="auto" mt="20px">
<Box p="20px" border="1px" borderRadius="10px" borderColor="gray.200">
Expand Down Expand Up @@ -170,29 +182,35 @@ const CreateEventForm = ({ eventData, setDataShouldRevalidate, closeModal }) =>
<Flex justifyContent="space-between">
{/* SUBJECT */}
<Box mb="15px">
<FormControl>
<FormLabel fontWeight="bold" color="gray.600">Subject</FormLabel>
<FormControl isInvalid={errors && errors.subject}>
<FormLabel fontWeight="bold" color="gray.600">Subject *</FormLabel>
<Dropdown
options={subjectOptions}
filter={subjectFilter}
selected={filterValues.subject}
defaults={eventData && eventData.subject}
badgeColor="#E8D7FF"
/>
<FormErrorMessage>
{errors.subject && errors.subject.message}
</FormErrorMessage>
</FormControl>
</Box>

{/* EVENT TYPE */}
<Box mb="15px">
<FormControl>
<FormLabel fontWeight="bold" color="gray.600">Event Type</FormLabel>
<FormControl isInvalid={errors && errors.eventType}>
<FormLabel fontWeight="bold" color="gray.600">Event Type *</FormLabel>
<Dropdown
options={eventOptions}
filter={eventFilter}
selected={filterValues.eventType}
defaults={eventData && eventData.eventType}
badgeColor="#CFDCFF"
/>
<FormErrorMessage>
{errors.eventType && errors.eventType.message}
</FormErrorMessage>
</FormControl>
</Box>
</Flex>
Expand Down
3 changes: 3 additions & 0 deletions src/components/Catalog/SearchFilter/filterOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ const subjectOptions = [
{ value: 'engineering', name: 'Engineering' },
{ value: 'math', name: 'Math' },
{ value: 'college readiness', name: 'College Readiness' },
{ value: 'soft skills', name: 'Soft Skills' },
{ value: 'writing', name: 'Writing' },
{ value: 'other', name: 'Other' },
];
const eventOptions = [
{ value: 'guest speaker', name: 'Guest Speaker' },
Expand Down
147 changes: 33 additions & 114 deletions src/components/Events/PublishedScheduleTable.jsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,10 @@
import { NPOBackend } from '../../utils/auth_utils.js';
import Events from './Events.jsx';
import EventInfo from './EventInfo.jsx';
import PropTypes from 'prop-types';
import { useEffect, useState } from 'react';
import { Table, Thead, Tbody, Tr, Th, Td, TableContainer, Box, IconButton, useDisclosure } from '@chakra-ui/react';
import AddDayModal from '../../pages/PublishedSchedule/AddDayModal.jsx'
import StatModal from '../../pages/PublishedSchedule/StatisticsModal.jsx';
import { AddIcon } from '@chakra-ui/icons';
import { IoStatsChart } from "react-icons/io5";
import { useAuthContext } from '../../common/AuthContext.jsx';
import AUTH_ROLES from '../../utils/auth_config.js';
const { ADMIN_ROLE } = AUTH_ROLES.AUTH_ROLES;
import { Table, Thead, Tbody, Tr, Th, Td, TableContainer } from '@chakra-ui/react';


const PublishedScheduleTable = ({ season, allSeasons, dataShouldRevalidate, setShouldDataRevalidate}) => {
const {currentUser} = useAuthContext();
const [eventsInDay, setEventsInDay] = useState([]);
const seasonType = season.split(' ')[0];
const seasonYear = season.split(' ')[1];
const { isOpen: isOpenDay, onOpen: onOpenDay, onClose: onCloseDay } = useDisclosure();
const { isOpen: isOpenStats, onOpen: onOpenStats, onClose: onCloseStats } = useDisclosure();

const renderTable = async () => {
const { data } = await NPOBackend.get(
`/published-schedule/season?season=${seasonType}&year=${seasonYear}`,
);
setEventsInDay(data);
};

useEffect(() => {
renderTable();
}, [seasonType, seasonYear]);

useEffect(() => {
if (dataShouldRevalidate) {
renderTable();
setShouldDataRevalidate(false);
}
}, [dataShouldRevalidate, renderTable])

const PublishedScheduleTable = ({ eventData, setShouldDataRevalidate}) => {
const dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];

const formatDate = date => {
Expand All @@ -57,89 +23,42 @@ const PublishedScheduleTable = ({ season, allSeasons, dataShouldRevalidate, setS
}

return (
<Box>
{currentUser.type === ADMIN_ROLE &&
<>
<IconButton
bgColor="grey.700"
color="blue.700"
borderRadius="10rem"
position="fixed"
bottom="6rem"
right={{ base: '1rem', lg: '2rem', xl: '3rem' }}
fontSize="1.25rem"
w="3.25rem"
h="3.25rem"
_hover={{ bgColor: 'blue.500' }}
onClick={onOpenStats}
icon={<IoStatsChart />}
>
Stats
</IconButton>

<IconButton
bgColor="blue.700"
color="gray.50"
borderRadius="10rem"
position="fixed"
bottom="2rem"
right={{ base: '1rem', lg: '2rem', xl: '3rem' }}
fontSize="0.75rem"
w="3.25rem"
h="3.25rem"
_hover={{ bgColor: 'blue.500' }}
onClick={onOpenDay}
icon={<AddIcon />}
>
Create
</IconButton>
</>
}

<AddDayModal isOpenDay={isOpenDay} onCloseDay={onCloseDay} setShouldDataRevalidate={setShouldDataRevalidate}/>
{ season && allSeasons &&
<StatModal isOpen={isOpenStats} onClose={onCloseStats} season={season} allSeasons={allSeasons}/>
}

<TableContainer borderWidth={1} borderRadius="10px" mr="2rem">
<Table variant="simple">
<Thead>
<Tr>
<Th>Info</Th>
<Th>Event Schedule</Th>
<TableContainer borderWidth={1} borderRadius="10px" mr="2rem">
<Table variant="simple">
<Thead>
<Tr>
<Th>Info</Th>
<Th>Event Schedule</Th>
</Tr>
</Thead>
<Tbody>
{eventData.map(item => (
<Tr key={item.day.id} verticalAlign={'top'}>
<Td pr={0}>
<EventInfo
dayId={item.day.id}
eventDate={getUTCDate(item.day.eventDate).toLocaleDateString('en-US')}
day={dayNames[getUTCDate(item.day.eventDate).getDay()]}
startTime={formatDate(item.day.startTime)}
endTime={formatDate(item.day.endTime)}
location={item.day.location}
notes={item.day.notes}
setShouldDataRevalidate={setShouldDataRevalidate}
/>
</Td>
<Td style={{ textAlign: 'left' }} width="75%">
<Events eventData={item.data} />
</Td>
</Tr>
</Thead>
<Tbody>
{eventsInDay.map(item => (
<Tr key={item.day.id} verticalAlign={'top'}>
<Td pr={0}>
<EventInfo
dayId={item.day.id}
eventDate={getUTCDate(item.day.eventDate).toLocaleDateString('en-US')}
day={dayNames[getUTCDate(item.day.eventDate).getDay()]}
startTime={formatDate(item.day.startTime)}
endTime={formatDate(item.day.endTime)}
location={item.day.location}
notes={item.day.notes}
setShouldDataRevalidate={setShouldDataRevalidate}
/>
</Td>
<Td style={{ textAlign: 'left' }} width="75%">
<Events eventData={item.data} />
</Td>
</Tr>
))}
</Tbody>
</Table>
</TableContainer>
</Box>
))}
</Tbody>
</Table>
</TableContainer>
);
};

PublishedScheduleTable.propTypes = {
season: PropTypes.string.isRequired,
allSeasons: PropTypes.array.isRequired,
dataShouldRevalidate: PropTypes.bool.isRequired,
eventData: PropTypes.array.isRequired,
setShouldDataRevalidate: PropTypes.func.isRequired,
};

Expand Down
Loading
Loading