Skip to content
Open
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
51 changes: 51 additions & 0 deletions src/components/subject-attendance-table/SubjectAttendanceTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Table, TableContainer, Tbody, Th, Thead, Tr } from "@chakra-ui/react";
import { ReactElement } from "react";
import { useNavigate } from "react-router-dom";
import { TableRow } from "../table-row/TableRow";

export interface StudentSubject {
subjectId: number;
name: string;
class: string;
attendance: number;
studentsCount: number;
}

interface SubjectTableProps {
data?: StudentSubject[];
isLoading?: boolean;
}

export function SubjectAttendanceTable({
data = [],
isLoading = false,
}: SubjectTableProps) {
const navigate = useNavigate();
const getTableRows = (subjects: StudentSubject[]): ReactElement[] => {
return subjects?.map((subject) => {
return (
<TableRow
key={subject.subjectId}
data={[subject.class, subject.name, subject.studentsCount, subject.attendance.toString() + "%"]}
onClick={() => navigate(`/`, { state: subject })}
/>
);
});
};

return (
<TableContainer width="100%">
<Table variant="simple">
<Thead>
<Tr>
<Th>CLASS</Th>
<Th>SUBJECT NAME</Th>
<Th>STUDENTS</Th>
<Th>ATTENDANCE</Th>
</Tr>
</Thead>
{!isLoading && <Tbody>{getTableRows(data)}</Tbody>}
</Table>
</TableContainer>
);
}
72 changes: 72 additions & 0 deletions src/components/teacher-class-list/TeacherClassList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { Table, TableContainer, Tbody, Th, Thead, Tr } from "@chakra-ui/react";
import { ReactElement } from "react";
import { TableRow } from "../table-row/TableRow";

export interface Student {
studentId: number;
name: string;
attendance: string;
pressent: string;
}

export function TeacherClassList({
studentNr = 20
}) {
const getName = () => {
const names = [
"Casper",
"Marie",
"Johanne",
"Kream",
"Buddah",
"JAnus",
"Frederikke",
"Camilla",
"Christoffer",
"Jannick",
"Neja",
"Amanda",
"Alex",
"Maccagnan",
"Jonas",
"Hannah"
];
return names[Math.floor(Math.random()*names.length)]
}
const getTableRows = (studentNr: number): ReactElement[] => {
let students: Student[] = []
for( let i = 0; i < studentNr; i++ ) {
const student: Student = {
studentId: i+1,
name: getName(),
attendance: (50 + Math.floor(Math.random()*50)).toString() + "%",
pressent: (Math.floor(Math.random()*10) % 2 === 0).toString()
}
students.push(student)
}

return students?.map((students) => {
return (
<TableRow
key={students.studentId}
data={[students.name, students.attendance, students.pressent]}
/>
);
});
};

return (
<TableContainer width="100%">
<Table variant="simple">
<Thead>
<Tr>
<Th>STUDENT</Th>
<Th>ATTENDANCE</Th>
<Th>PRESENT</Th>
</Tr>
</Thead>
<Tbody>{getTableRows(studentNr)}</Tbody>
</Table>
</TableContainer>
);
}
3 changes: 3 additions & 0 deletions src/layout/attendance-page/attendanceView/AttendanceView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ export function AttendanceView({ subject }: AttendanceViewProps) {
<Button variant="secondary" onClick={handleClick}>
Stop Attendance
</Button>
<Button variant="secondary" onClick={() => navigate(`/class-attendance-overview`, { state: subject.studentsCount })}>
See class attendance
</Button>
</>
);
}
20 changes: 20 additions & 0 deletions src/layout/class-attendance-overview/ClassAttendanceOverview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Button, HStack } from "@chakra-ui/react";
import { useLocation, useNavigate } from "react-router-dom";
import { MainCard } from "../../components/main-card/MainCard";
import { TeacherClassList } from "../../components/teacher-class-list/TeacherClassList";

export function ClassAttendanceOverview() {
const location = useLocation();
const studentNr = location.state as number;
const navigate = useNavigate();

return (
<HStack mx="40px" spacing="40px" key="page-container">
<MainCard key="Class">
<div>Student list</div>
<TeacherClassList studentNr={studentNr}/>
</MainCard>
<Button onClick={() => navigate(-1)}>Back</Button>
</HStack>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { screen } from "@testing-library/react";
import { UserDetail } from "../../provider/UserProvider";
import { UserType } from "../navigation-bar/authorized-navigation-bar/AuthorizedNavigationBar";
import { StudentAttendanceOverview } from "./StudentAttendanceOverview";
import { createMemoryHistory } from "history";
import { Router } from "react-router-dom";
import { renderWithUseContextUser } from "../../test-util";

describe("student attendance overview page", () => {
const studentDetail: UserDetail = {
userId: "10",
username: "student test",
role: UserType.STUDENT,
};
it("contains the correct titles", () => {
const history = createMemoryHistory();

renderWithUseContextUser(
<Router location={history.location} navigator={history}>
<StudentAttendanceOverview />
</Router>,
studentDetail
);

screen.getByText("CLASS");
screen.getByText("SUBJECT NAME");
screen.getByText("STUDENTS");
screen.getByText("ATTENDANCE");
})
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { HStack } from "@chakra-ui/react";
import { MainCard } from "../../components/main-card/MainCard";
import { StudentSubject, SubjectAttendanceTable } from "../../components/subject-attendance-table/SubjectAttendanceTable";

export function StudentAttendanceOverview() {
const subjects: StudentSubject[] = [
{
subjectId: 1,
name: "Testing",
class: "SW20",
attendance: 95,
studentsCount: 38,
},
{
subjectId: 2,
name: "Web Development",
class: "SW20",
attendance: 82,
studentsCount: 38,
},
{
subjectId: 3,
name: "Databases",
class: "SW20",
attendance: 88,
studentsCount: 38,
},
];

const getAttendanceAverage = (subjects: StudentSubject[]) => {
let sum = 0;
let i = 0;
for( i; i < subjects.length; i++ ) {
sum += subjects[i].attendance;
}
const average = sum / i;
return average.toFixed(2);
}

return (
<HStack mx="40px" spacing="40px" key="page-container">
<MainCard>
<h3><strong>Total attendance: {getAttendanceAverage(subjects)} %</strong></h3>
<SubjectAttendanceTable data={subjects} />
</MainCard>
</HStack>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { SubjectTable } from "../../components/subject-table/SubjectTable";
import { useSubject } from "../../api/useSubject";
import { useContext } from "react";
import { UserContext } from "../../provider/UserProvider";

export function TeacherSubjectManagement() {
const { userDetail } = useContext(UserContext);
const { data: subjects, isLoading } = useSubject(userDetail.userId!!);
Expand All @@ -15,7 +16,7 @@ export function TeacherSubjectManagement() {
<MainCard>
<HStack width={"100%"} key="card-header">
<SearchInput />
<PrimaryButton width={"15vw"}>Add</PrimaryButton>
<PrimaryButton key="addClass" width={"15vw"}>Add</PrimaryButton>
</HStack>
<SubjectTable data={subjects?.data} isLoading={isLoading} />
</MainCard>
Expand Down
6 changes: 5 additions & 1 deletion src/route/SwitchGuard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { LoginSuccess } from "../layout/login-page/login-success/LoginSuccess";
import { AttendancePage } from "../layout/attendance-page/AttendancePage";
import { useContext } from "react";
import { UserContext } from "../provider/UserProvider";
import { StudentAttendanceOverview } from "../layout/student-attendance-overview/StudentAttendanceOverview";
import { ClassAttendanceOverview } from "../layout/class-attendance-overview/ClassAttendanceOverview";

export function SwitchGuard() {
const { userDetail, setUserDetail } = useContext(UserContext);
Expand All @@ -24,14 +26,16 @@ export function SwitchGuard() {
return (
<Switch>
<Route path="/" element={<StudentHomepage />} />
<Route path="/checkatt" element={<StudentAttendanceOverview />} />
<Route path="/*" element={<NotFoundPage />} />
</Switch>
);
case UserType.TEACHER:
return (
<Switch>
<Route path="/" element={<TeacherSubjectManagement />} />
<Route element={<AttendancePage />} path="/attendance-code" />
<Route path="/attendance-code" element={<AttendancePage />} />
<Route path="/class-attendance-overview" element={<ClassAttendanceOverview />} />
<Route path="/*" element={<NotFoundPage />} />
</Switch>
);
Expand Down