Skip to content

Commit

Permalink
Merge branch 'main' into sign_up_skeleton
Browse files Browse the repository at this point in the history
  • Loading branch information
theNatePi authored Jan 27, 2025
2 parents caf3adf + 3c7a082 commit 3b2b3f3
Show file tree
Hide file tree
Showing 18 changed files with 988 additions and 16 deletions.
5 changes: 2 additions & 3 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,18 @@
"build": "tsc -b && vite build",
"lint": "eslint",
"format": "npx prettier --write .",
"preview": "vite preview",
"postinstall": "patch-package"
"preview": "vite preview"
},
"dependencies": {
"@chakra-ui/react": "^2.8.2",
"@emotion/react": "^11.13.0",
"@emotion/styled": "^11.13.0",
"@hookform/resolvers": "^3.9.0",
"@react-pdf/renderer": "^4.1.6",
"axios": "^1.7.4",
"firebase": "10.12.5",
"framer-motion": "^11.3.27",
"patch-package": "^8.0.0",
"postinstall-postinstall": "^2.1.0",
"react": "^18.3.1",
"react-cookie": "^7.2.0",
"react-dom": "^18.3.1",
Expand Down
8 changes: 7 additions & 1 deletion client/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import { Signup } from "./components/signup/Signup";
import { AuthProvider } from "./contexts/AuthContext";
import { BackendProvider } from "./contexts/BackendContext";
import { RoleProvider } from "./contexts/RoleContext";
import { ForgotPassword } from "./components/login/ForgotPassword";
import { PDFViewer } from "@react-pdf/renderer";

Check warning on line 20 in client/src/App.jsx

View workflow job for this annotation

GitHub Actions / run-checks

'PDFViewer' is defined but never used. Allowed unused vars must match /^_/u
import PDFButton from "./components/PDFButton";

Check warning on line 21 in client/src/App.jsx

View workflow job for this annotation

GitHub Actions / run-checks

'PDFButton' is defined but never used. Allowed unused vars must match /^_/u

const App = () => {
return (
Expand Down Expand Up @@ -50,7 +53,6 @@ const App = () => {
/>
}
/>

<Route
path="/"
element={
Expand All @@ -64,6 +66,10 @@ const App = () => {
path="*"
element={<ProtectedRoute element={<CatchAll />} />}
/>
<Route
path="/forgotpassword"
element={<ForgotPassword />}
/>
</Routes>
</Router>
</RoleProvider>
Expand Down
9 changes: 9 additions & 0 deletions client/src/assets/logo/Logo.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import LogoImg from "./logo.png";

// NOTE: Do not import logo.png, use Logo component instead

export const Logo = () => {
return (
<img src={LogoImg}></img>
);
};
Binary file added client/src/assets/logo/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
199 changes: 199 additions & 0 deletions client/src/components/AddClassModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
import {
useDisclosure,
Button,
Modal,
ModalOverlay,
ModalContent,
ModalHeader,
ModalFooter,
ModalCloseButton,
FormLabel,
Input,
FormControl,
ModalBody,
Select,
Flex,
IconButton,
Box
} from "@chakra-ui/react";
import React, { useState, useEffect } from 'react';

import { useBackendContext } from "../contexts/hooks/useBackendContext";


export const AddClassModal = () => {
const { isOpen, onOpen, onClose } = useDisclosure()
const { backend } = useBackendContext();

const [rooms, setRooms] = useState([]);
const [selectedDays, setSelectedDays] = useState([]);
const [startDate, setStartDate] = useState("");
const [endDate, setEndDate] = useState("");

//bookings part
//events part

const [bookingsForm, setBookingsForm] = useState({
event_id : "",
room_id : "",
start_time : "",
end_time : "",
date : "",
archived : false
})

const [eventsForm, setEventsForm] = useState({
name : "",
description : "",
archived: false
})

const getDatesForDays = (startDate, endDate, selectedDays) => {
const daysMap = { 'Su': 0, 'M': 1, 'Tu': 2, 'W': 3, 'Th': 4, 'F': 5, 'S': 6 };
const daysIndices = selectedDays.map((day) => daysMap[day]);

const dates = [];
const currentDate = new Date(startDate);
const lastDate = new Date(endDate);

while (currentDate <= lastDate) {
if (daysIndices.includes(currentDate.getUTCDay())) {
dates.push(new Date(currentDate).toISOString().split("T")[0]);
}
currentDate.setDate(currentDate.getDate() + 1);
}
return dates;
};

const handleSubmit = async () => {
try {

const eventResponse = await backend.post("/events", eventsForm);

const eventId = eventResponse.data.id;

const dates = getDatesForDays(startDate, endDate, selectedDays);

for (const date of dates) {
const bookingData = {
...bookingsForm,
event_id : eventId,
date: date,
};

const bookingsResponse = await backend.post("/bookings", bookingData);
console.log(bookingsResponse.data);
}


} catch (error) {
console.error("Error submitting form:", error);
}
}

useEffect(() => {
const fetchData = async () => {
try {
const response = await backend.get("/rooms");
setRooms(response.data);
} catch (error) {
console.error("Error fetching rooms:", error);
}
};

fetchData();
}, [backend]);

return (
<>
<Button onClick={onOpen}>Open Modal</Button>
<Modal
isOpen={isOpen}
onClose={onClose}
>
<ModalOverlay />
<ModalContent>
<ModalHeader>Add Class</ModalHeader>
<ModalCloseButton />
<ModalBody pb={6}>

<FormControl>
<FormLabel>Name</FormLabel>
<Input placeholder='Enter name' value={eventsForm.name} onChange={(e) => (setEventsForm({...eventsForm, "name" : e.target.value}))}/>
</FormControl>


<FormControl>
<FormLabel>Description</FormLabel>
<Input placeholder='Enter description' value={eventsForm.description} onChange={(e) => (setEventsForm({...eventsForm, "description" : e.target.value}))}/>
</FormControl>

<FormControl mt={4}>
<FormLabel>Room</FormLabel>
<Select placeholder='Select Room' onChange={(e) => {
setBookingsForm((prevForm) => ({
...prevForm,
room_id: e.target.value,
}));
}}>

{rooms.map(room => (
<option key={room.id} value={room.id}>{room.name}</option>)
)
}
</Select>
</FormControl>


<FormControl>
<FormLabel>Days</FormLabel>
<Flex justifyContent="space-evenly">
{["Su", "M", "Tu", "W", "Th", "F", "S"].map((day) => (
<IconButton
key={day} // Add a key for each button to avoid React warnings
isRound={true}
variant={selectedDays.includes(day) ? "solid" : "outline"}
aria-label={`Toggle ${day}`}
fontSize="20px"
icon={<Box as="span">{day}</Box>}
value={day}
onClick={() => {
if (selectedDays.includes(day)) {
setSelectedDays(selectedDays.filter((d) => d !== day));
} else {
setSelectedDays([...selectedDays, day]);
}
}}
/>
))}
</Flex>
</FormControl>


<FormControl>
<FormLabel>Start Date</FormLabel>
<Input placeholder='Select Date and Time' size='md' type='date' w="50%" value={startDate} onChange={(e) => setStartDate(e.target.value)}/>
<FormLabel>End Date</FormLabel>
<Input placeholder='Select Date and Time' size='md' type='date' w='50%' value={endDate} onChange={(e) => setEndDate(e.target.value)}/>
<FormLabel>Start Time</FormLabel>
<Input placeholder='Select Date and Time' size='md' type='time' w='50%' value={bookingsForm.start_time} onChange={(e) => setBookingsForm({...bookingsForm, start_time : e.target.value})}/>
<FormLabel>End Date</FormLabel>
<Input placeholder='Select Date and Time' size='md' type='time' w='50%' value={bookingsForm.end_time} onChange={(e) => setBookingsForm({...bookingsForm, end_time : e.target.value})}/>
</FormControl>

</ModalBody>


<ModalFooter>
<Button colorScheme='blue' mr={3} onClick={() => {
handleSubmit();
onClose();
}}>
Submit
</Button>
</ModalFooter>
</ModalContent>
</Modal>
</>
)
}
110 changes: 110 additions & 0 deletions client/src/components/EventsTable.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import {
Table,
Thead,
Tbody,
Tr,
Th,
Td,
Menu,
MenuButton,
MenuList,
MenuItem,
Button,
} from '@chakra-ui/react';
import React, { useState, useEffect } from 'react';
import { useBackendContext } from "../contexts/hooks/useBackendContext";

export const EventsTable = () => {
const { backend } = useBackendContext();
const [ events, setEvents ] = useState([]);

const fetchEvents = async () => {
try {
const eventsResponse = await backend.get('/events');
const eventsData = eventsResponse.data;
const eventsWithAssignments = [];

for (const event of eventsData) {
const instructors = [];
const payees = [];

try {
// Attempt to fetch assignment information for each event
const assignmentsResponse = await backend.get('/assignments/event/' + event.id);
const assignmentsData = assignmentsResponse.data;

// Process assignment information if available
if (Array.isArray(assignmentsData) && assignmentsData.length > 0) {
for (const assignment of assignmentsData) {
if (assignment.role.toLowerCase() === 'instructor') {
instructors.push(assignment.clientName);
} else if (assignment.role.toLowerCase() === 'payee') {
payees.push(assignment.clientName);
}
}
}
} catch {
console.error('Failed to fetch assignments for event', event.id);
}

// Add event with assignments to list
eventsWithAssignments.push({
id: event.id,
name: event.name,
description: event.description,
instructors: instructors.join(', '),
payees: payees.join(', ')
});
}

setEvents(eventsWithAssignments);
} catch {
console.error('Failed to fetch events');
}
}

useEffect(() => {
// call the fetch event here to fetch all events
fetchEvents();
}, []);

Check warning on line 69 in client/src/components/EventsTable.jsx

View workflow job for this annotation

GitHub Actions / run-checks

React Hook useEffect has a missing dependency: 'fetchEvents'. Either include it or remove the dependency array

return (
<Table variant="striped" colorScheme="teal">
<Thead>
<Tr>
<Th>Class</Th>
<Th>Description</Th>
<Th>Instructor</Th>
<Th>Payee</Th>
<Th>Actions</Th>
</Tr>
</Thead>
<Tbody>
{events.map((event) => (
<Tr key={event.id}>
<Td>{event.name}</Td>
<Td>{event.description}</Td>
<Td>{event.instructors}</Td>
<Td>{event.payees}</Td>
<Td>
<Menu>
<MenuButton
as={Button}
size="sm"
variant="outline"
>
Actions
</MenuButton>
<MenuList>
<MenuItem onClick={() => {}}>Edit</MenuItem>
<MenuItem onClick={() => {}}>Delete</MenuItem>
</MenuList>
</Menu>
</Td>
</Tr>
))}
</Tbody>
</Table>
);

};
Loading

0 comments on commit 3b2b3f3

Please sign in to comment.