Skip to content

Commit

Permalink
Create parent attendance display #130 (#132)
Browse files Browse the repository at this point in the history
  • Loading branch information
willji0023 authored Feb 24, 2023
1 parent d4554d6 commit 24982ef
Show file tree
Hide file tree
Showing 8 changed files with 326 additions and 10 deletions.
7 changes: 6 additions & 1 deletion components/Profile/ParentProfile/ParentProfileView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import axios from "axios";
import { ConnectStudentProfile } from "./ConnectStudentProfile";
import { ConnectedStudentDisplay } from "./ConnectedStudentDisplay";
import { AddStudentModal } from "./AddStudentModal";
import { StudentClasses } from "./StudentClasses";

// component that renders the admin/teacher profile page
type ParentProfileViewProps = {
Expand Down Expand Up @@ -126,7 +127,11 @@ const ParentProfileView: React.FC<ParentProfileViewProps> = ({ otherUser }) => {
renderStudentCards[currentStudentIndex]
)}
</div>
<div className={styles.rightPanel}></div>
<div className={styles.rightPanel}>
<StudentClasses
id={allStudents[currentStudentIndex] ? allStudents[currentStudentIndex].id : ""}
/>
</div>
</div>
</div>
</div>
Expand Down
94 changes: 94 additions & 0 deletions components/Profile/ParentProfile/StudentClasses.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
.spacer {
height: 30px;
}

.accordion {
height: 100%;
font-family: "Inter";
font-style: normal;
font-weight: 700;
font-size: 24px;
line-height: 29px;
padding: 1em 1.5em;
overflow-y: auto;
overflow-x: hidden;
color: #000000;
}

.item {
font-weight: 600;
font-size: 18px;
line-height: 22px;
background: #f3f3f3;
}

.item + .item {
margin-top: 2em;
border-top: 1px solid rgba(0, 0, 0, 0.1);
}

.button {
cursor: pointer;
padding: 18px;
width: 100%;
text-align: left;
border: none;
outline: none;
border-radius: 8px;
box-shadow: 0px 5px 10px -11px;
}

.button:hover {
background-color: #ddd;
}

.button:before {
float: right;
content: "▼";
height: 10px;
width: 10px;
margin-right: 12px;
}

.button[aria-expanded="true"]::before,
.button[aria-selected="true"]::before {
margin-top: 12px;
margin-right: 4px;
transform: rotate(180deg);
}

.panel {
font-size: 15px;
line-height: 18px;
padding: 20px;
animation: fadein 0.35s ease-in;
border-radius: 0px 0px 8px 8px;
}

.panel a {
color: blue;
}

/* -------------------------------------------------- */
/* ---------------- Animation part ------------------ */
/* -------------------------------------------------- */

@keyframes fadein {
0% {
opacity: 0;
}

100% {
opacity: 1;
}
}

.info {
display: inline-block;
vertical-align: super;
margin-bottom: 25px;
}

.info:last-child {
margin-bottom: 0px;
}
89 changes: 89 additions & 0 deletions components/Profile/ParentProfile/StudentClasses.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { Class } from "../../../models/";
import { APIContext } from "../../../context/APIContext";
import styles from "./StudentClasses.module.css";
import React, { useContext, useEffect, useState } from "react";
import RRule from "rrule";
import { DateTime } from "luxon";
import {
Accordion,
AccordionItem,
AccordionItemHeading,
AccordionItemButton,
AccordionItemPanel,
} from "react-accessible-accordion";
import AccessTime from "@mui/icons-material/AccessTime";
import CalendarMonth from "@mui/icons-material/CalendarMonth";
import School from "@mui/icons-material/School";

type StudentClassesProps = {
id: string;
};

const StudentClasses: React.FC<StudentClassesProps> = ({ id }) => {
const api = useContext(APIContext);
const [classes, setClasses] = useState<Class[]>([]);

useEffect(() => {
(async () => {
await getClasses();
})();
}, [id]);

const getClasses = async (): Promise<void> => {
if (id) {
const classesByUser = await api.getClassesByUser(id);
setClasses(classesByUser);
} else {
setClasses([]);
}
};

return (
<>
<Accordion className={styles.accordion} allowMultipleExpanded={true} allowZeroExpanded={true}>
Classes
<div className={styles.spacer} />
{classes.map((Class) => (
<AccordionItem className={styles.item} key={Class.eventInformationId + id}>
<AccordionItemHeading>
<AccordionItemButton className={styles.button}>
{Class.name}{" "}
{Class.minLevel == Class.maxLevel
? Class.minLevel
: Class.minLevel + "-" + Class.maxLevel}
</AccordionItemButton>
</AccordionItemHeading>
<AccordionItemPanel className={styles.panel}>
<AccessTime />{" "}
<div className={styles.info}>
{DateTime.fromFormat(Class.startTime, "HH:mm:ss.SSSZZ").toFormat("t") +
" - " +
DateTime.fromFormat(Class.endTime, "HH:mm:ss.SSSZZ").toFormat("t")}
</div>
<br />
<CalendarMonth />{" "}
<div className={styles.info}>
{
// Capitalize the first letter of the sentence
RRule.fromString(Class.rrstring).toText().charAt(0).toUpperCase() +
RRule.fromString(Class.rrstring).toText().slice(1) +
", start " +
DateTime.fromJSDate(RRule.fromString(Class.rrstring).options.dtstart).toFormat(
"DDD"
)
}
</div>
<br />
<School />{" "}
<div className={styles.info}>
<a href={"/class/" + Class.eventInformationId}>Class Link</a>
</div>
</AccordionItemPanel>
</AccordionItem>
))}
</Accordion>
</>
);
};

export { StudentClasses };
6 changes: 6 additions & 0 deletions context/LeagueAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,12 @@ class LeagueAPI {
const res = await this.client.get("api/class", { params: { userId: userId } });
return res.data;
}

async getClassesByUser(userId: string): Promise<Class[]> {
const res = await this.client.get(`api/users/${userId}/classes`);
return res.data;
}

async deleteClassEvent(userId: string): Promise<Class> {
const res = await this.client.delete(`api/events/class/${userId}`);
return res.data;
Expand Down
48 changes: 47 additions & 1 deletion lib/database/classes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ type ClassWithoutTeacherInfo = {
endTime: string;
language: string;
};
const ClassWithoutTeacherInfoSchema = t.type({
name: t.string,
eventInformationId: t.string,
minLevel: t.number,
maxLevel: t.number,
rrstring: t.string,
startTime: t.string,
endTime: t.string,
language: t.string,
});
const ClassWithoutTeacherInfoArraySchema = array(ClassWithoutTeacherInfoSchema);

const createClass = async (
eventInformationId: string,
Expand Down Expand Up @@ -196,4 +207,39 @@ const getAllClasses = async (): Promise<Class[]> => {
return classesArray;
};

export { createClass, getClass, updateClass, getAllClasses };
const getClassesByUser = async (id: string): Promise<Class[]> => {
const query = {
text:
"SELECT cl.min_level, cl.max_level, cl.rrstring, cl.start_time, cl.end_time, cl.language, cl.event_information_id, e.name " +
"FROM ((event_information e INNER JOIN classes cl ON e.id = cl.event_information_id) " +
"INNER JOIN commitments ON commitments.event_information_id = e.id) " +
"WHERE commitments.user_id = $1",
values: [id],
};
const res = await client.query(query);
let classesWithoutTeacher: TypeOf<typeof ClassWithoutTeacherInfoArraySchema>;
try {
classesWithoutTeacher = await decode(ClassWithoutTeacherInfoArraySchema, res.rows);
} catch (e) {
throw Error("Fields returned incorrectly from database");
}

const classesArray: Class[] = [];
classesWithoutTeacher.forEach((singleClass) => {
const currClass = {
name: singleClass.name,
eventInformationId: singleClass.eventInformationId,
minLevel: singleClass.minLevel,
maxLevel: singleClass.maxLevel,
rrstring: singleClass.rrstring,
startTime: singleClass.startTime,
endTime: singleClass.endTime,
language: singleClass.language,
teachers: [],
};
classesArray.push(currClass);
});
return classesArray;
};

export { createClass, getClass, updateClass, getAllClasses, getClassesByUser };
30 changes: 23 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"io-ts": "^2.2.16",
"io-ts-promise": "^2.0.2",
"jest-node-exports-resolver": "^1.1.6",
"luxon": "^2.3.1",
"luxon": "^2.5.2",
"moment": "^2.29.1",
"next": "^12.1.0",
"next-swagger-doc": "^0.3.6",
Expand All @@ -58,6 +58,7 @@
"pino-pretty": "^9.1.1",
"postgres-migrations": "^5.3.0",
"react": "17.0.2",
"react-accessible-accordion": "^5.0.0",
"react-color": "^2.19.3",
"react-datetime-picker": "^3.4.3",
"react-dom": "17.0.2",
Expand Down
Loading

0 comments on commit 24982ef

Please sign in to comment.