Skip to content

Commit

Permalink
Refactored API Endpoints
Browse files Browse the repository at this point in the history
Added API Endpoints to get Students and Classes from ID
Added Indication of No Results for Search Query
Added Indication of Invalid ID for Direct Navigation
Added RenovateBot
  • Loading branch information
Redfire75369 committed Jun 13, 2021
1 parent f02fbd9 commit 8e112ca
Show file tree
Hide file tree
Showing 13 changed files with 271 additions and 80 deletions.
2 changes: 2 additions & 0 deletions .tokeignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
## NPM
npm-shrinkwrap.json
14 changes: 8 additions & 6 deletions interfaces/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,20 @@ export type Attendance = {
export type Student = {
student_id: string,
student_name: string,
class_id: number
};

export type Class = {
class_id: number,
class_name: string,
level_id: number
};

export type Record = {
record_id: number,
date: string,
student_id: string,
attendance: boolean,
attendance: boolean
};

export type Class = {
class_id: number,
class_name: string,
level_id: number,
};
export * from "./requests";
13 changes: 13 additions & 0 deletions interfaces/requests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import {NextApiRequest} from "next";

export type NextStudentApiRequest = NextApiRequest & {
query: {
student_id: string
}
};

export type NextClassApiRequest = NextApiRequest & {
query: {
class_id: string
}
};
36 changes: 10 additions & 26 deletions pages/api/class/[class_id].ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,22 @@
import {NextApiRequest, NextApiResponse} from "next";
import {NextApiResponse} from "next";

import {updateStudentOnDates} from "../../../src/database/update/attendance";
import {NextClassApiRequest} from "../../../interfaces";

async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== "PUT") {
res.setHeader("Allow", "PUT");
res.status(405).end();
return;
}
import {classById} from "../../../src/database/read/classes";

if (!req.query.class_id || isNaN(parseInt(req.query.class_id as string))) {
res.status(400).end();
async function handler(req: NextClassApiRequest, res: NextApiResponse) {
if (req.method !== "GET") {
res.setHeader("Allow", "GET");
res.status(405).end();
return;
}

// let user = supabase.auth.api.getUserByCookie(req);

const students = Object.keys(req.body);

for (const student of students) {
const dates: Date[] = [];
const attendances: boolean[] = [];

const keys = Object.keys(req.body[student]);

for (const date of keys) {
dates.push(new Date(date));
attendances.push(req.body[student][date]);
}

await updateStudentOnDates(student, dates, attendances);
}
const class_ = await classById(parseInt(req.query.class_id));

res.status(200).end();
res.setHeader("Content-Type", "application/json");
res.status(class_ !== null ? 200 : 404).json({class: class_});
}

export default handler;
38 changes: 38 additions & 0 deletions pages/api/class/[class_id]/attendance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {NextApiRequest, NextApiResponse} from "next";

import {updateStudentOnDates} from "../../../../src/database/update/attendance";

async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== "PUT") {
res.setHeader("Allow", "PUT");
res.status(405).end();
return;
}

if (!req.query.class_id || isNaN(parseInt(req.query.class_id as string))) {
res.status(400).end();
return;
}

// let user = supabase.auth.api.getUserByCookie(req);

const students = Object.keys(req.body);

for (const student of students) {
const dates: Date[] = [];
const attendances: boolean[] = [];

const keys = Object.keys(req.body[student]);

for (const date of keys) {
dates.push(new Date(date));
attendances.push(req.body[student][date]);
}

await updateStudentOnDates(student, dates, attendances);
}

res.status(200).end();
}

export default handler;
33 changes: 10 additions & 23 deletions pages/api/student/[student_id].ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,22 @@
import {NextApiRequest, NextApiResponse} from "next";
import {NextApiResponse} from "next";

import {updateStudentOnDates} from "../../../src/database/update/attendance";
import {NextStudentApiRequest} from "../../../interfaces";

async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== "PUT") {
res.setHeader("Allow", "PUT");
res.status(405).end();
return;
}
import {studentById} from "../../../src/database/read/students";

if (!req.query.student_id) {
res.status(400).end();
async function handler(req: NextStudentApiRequest, res: NextApiResponse) {
if (req.method !== "GET") {
res.setHeader("Allow", "GET");
res.status(405).end();
return;
}

// let user = supabase.auth.api.getUserByCookie(req);

let dates: Date[] = [];
let attendances: boolean[] = [];

let keys = Object.keys(req.body);

for (const date of keys) {
dates.push(new Date(date));
attendances.push(req.body[date]);
}

await updateStudentOnDates(req.query.student_id as string, dates, attendances);
const student = await studentById(req.query.student_id);

res.statusCode = 200;
res.end();
res.setHeader("Content-Type", "application/json");
res.status(student !== null ? 200 : 404).json({student});
}

export default handler;
34 changes: 34 additions & 0 deletions pages/api/student/[student_id]/attendance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {NextApiRequest, NextApiResponse} from "next";

import {updateStudentOnDates} from "../../../../src/database/update/attendance";

async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== "PUT") {
res.setHeader("Allow", "PUT");
res.status(405).end();
return;
}

if (!req.query.student_id) {
res.status(400).end();
return;
}

// let user = supabase.auth.api.getUserByCookie(req);

let dates: Date[] = [];
let attendances: boolean[] = [];

let keys = Object.keys(req.body);

for (const date of keys) {
dates.push(new Date(date));
attendances.push(req.body[date]);
}

await updateStudentOnDates(req.query.student_id as string, dates, attendances);

res.status(200).end();
}

export default handler;
5 changes: 3 additions & 2 deletions pages/class/[class_id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,10 @@ function ClassAttendancePage(
async function updateAttendance() {
await fetch(`/api/class/${class_.class_id}`, {
method: "PUT",
headers: {
headers: new Headers({
"Content-Type": "application/json"
},
}),
credentials: "same-origin",
body: JSON.stringify(modifications.current)
});
window.location.reload();
Expand Down
16 changes: 14 additions & 2 deletions pages/classes.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Button, HStack, Input, Table, Tbody, Td, Th, Thead, Tr, VStack} from "@chakra-ui/react";
import {Button, Center, HStack, Input, Table, Tbody, Td, Text, Th, Thead, Tr, VStack} from "@chakra-ui/react";
import {GetServerSideProps, InferGetServerSidePropsType} from "next";
import {useRouter} from "next/router";
import {useState} from "react";
Expand Down Expand Up @@ -65,7 +65,19 @@ function ClassesPage(
await router.push(`/classes?page=1&q=${query}`);
}

return (
return classes.length === 0 ? (
<Layout title="Attendance System (Classes)">
<VStack justify="start">
<HStack>
<Input value={query} onChange={(event) => setQuery(event.target.value)} placeholder="Search" colorScheme="blue" size="sm"/>
<Button onClick={handleSearch} colorScheme="blue">Search</Button>
</HStack>
<HStack>
<Text><Center>No Results</Center></Text>
</HStack>
</VStack>
</Layout>
) : (
<Layout title="Attendance System (Classes)">
<VStack justify="start">
<HStack justify="start">
Expand Down
58 changes: 42 additions & 16 deletions pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ function IndexPage() {
const [studentId, setStudentId] = useState("");
const [classId, setClassId] = useState("");

const [invalidStudentId, setInvalidStudentId] = useState(false);
const [invalidClassId, setInvalidClassId] = useState(false);

useEffect(function () {
const authSession = anonSupabase.auth.session();
setSession(authSession);
Expand All @@ -39,7 +42,7 @@ function IndexPage() {
})
});

setSession(authSession)
setSession(authSession);
setUser(authSession?.user ?? null);
});

Expand All @@ -62,21 +65,36 @@ function IndexPage() {

async function goToStudent() {
if (studentId !== "") {
await router.push(`/student/${studentId}`);
const res = await fetch(`/api/student/${studentId}`, {
method: "GET",
headers: new Headers({
"Content-Type": "application/json"
}),
credentials: "same-origin"
});
if (res.status === 200) {
setInvalidStudentId(false);
await router.push(`/student/${studentId}`);
} else {
setInvalidStudentId(true);
}
}
}
async function browseStudents() {
await router.push(`/students?page=1`);
}

async function goToClass() {
if (classId !== "") {
await router.push(`/class/${classId}`);
const res = await fetch(`/api/class/${classId}`, {
method: "GET",
credentials: "same-origin"
});
if (res.status === 200) {
setInvalidClassId(false);
await router.push(`/class/${classId}`);
} else {
setInvalidClassId(true);
}
}
}
async function browseClasses() {
await router.push(`/classes?page=1`);
}

return !user ? (
<Layout title="Attendance System (Sign In)">
Expand All @@ -93,18 +111,26 @@ function IndexPage() {
<Text>{user.email?.split("@")[0]}</Text>
<Button onClick={signOut} colorScheme="blue">Sign Out</Button>
</HStack>
<VStack justify="start" spacing={3}>
<HStack spacing={3}>
<VStack w="100vw" justify="start" spacing={3}>
<HStack spacing={3} isInline>
<Text>Student: </Text>
<Input value={studentId} onChange={(event) => setStudentId(event.target.value)} resize="none" placeholder="Student ID" colorScheme="blue" size="sm"/>
{invalidStudentId ? (
<Input value={studentId} onChange={(event) => setStudentId(event.target.value)} resize="none" placeholder="Student ID" colorScheme="blue" size="sm" borderColor="red"/>
) : (
<Input value={studentId} onChange={(event) => setStudentId(event.target.value)} resize="none" placeholder="Student ID" colorScheme="blue" size="sm"/>
)}
<Button onClick={goToStudent} colorScheme="blue">Go to</Button>
<Button onClick={browseStudents} colorScheme="blue">Browse</Button>
<Button onClick={async () => await router.push("/students?page=1")} colorScheme="blue">Browse</Button>
</HStack>
<HStack spacing={3}>
<HStack spacing={3} isInline>
<Text>Class: </Text>
<Input value={classId} onChange={(event) => setClassId(event.target.value)} resize="none" placeholder="Class ID" colorScheme="blue" size="sm"/>
{invalidClassId ? (
<Input value={classId} onChange={(event) => setClassId(event.target.value)} resize="none" placeholder="Class ID" colorScheme="blue" size="sm" borderColor="red"/>
) : (
<Input value={classId} onChange={(event) => setClassId(event.target.value)} resize="none" placeholder="Class ID" colorScheme="blue" size="sm"/>
)}
<Button onClick={goToClass} colorScheme="blue">Go to</Button>
<Button onClick={browseClasses} colorScheme="blue">Browse</Button>
<Button onClick={async () => await router.push("/classes?page=1")} colorScheme="blue">Browse</Button>
</HStack>
</VStack>
</VStack>
Expand Down
7 changes: 4 additions & 3 deletions pages/student/[student_id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,12 @@ function StudentAttendancePage(
}

async function updateAttendance() {
await fetch(`/api/student/${student.student_id}`, {
await fetch(`/api/student/${student.student_id}/attendance`, {
method: "PUT",
headers: {
headers: new Headers({
"Content-Type": "application/json"
},
}),
credentials: "same-origin",
body: JSON.stringify(modifications.current)
});
window.location.reload();
Expand Down
16 changes: 14 additions & 2 deletions pages/students.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Button, HStack, Input, Table, Tbody, Td, Th, Thead, Tr, VStack} from "@chakra-ui/react";
import {Button, Center, HStack, Input, Table, Tbody, Td, Text, Th, Thead, Tr, VStack} from "@chakra-ui/react";
import {GetServerSideProps, InferGetServerSidePropsType} from "next";
import {useRouter} from "next/router";
import {useState} from "react";
Expand Down Expand Up @@ -75,7 +75,19 @@ function StudentsPage(
await router.push(`/students?page=1&q=${query}`);
}

return (
return students.length === 0 ? (
<Layout title="Attendance System (Students)">
<VStack justify="start">
<HStack>
<Input value={query} onChange={(event) => setQuery(event.target.value)} placeholder="Search" colorScheme="blue" size="sm"/>
<Button onClick={handleSearch} colorScheme="blue">Search</Button>
</HStack>
<HStack>
<Text><Center>No Results</Center></Text>
</HStack>
</VStack>
</Layout>
) : (
<Layout title="Attendance System (Students)">
<VStack justify="start">
<HStack justify="start">
Expand Down
Loading

0 comments on commit 8e112ca

Please sign in to comment.