Refactored students

This commit is contained in:
Kevin FEDYNA
2025-01-27 13:11:13 +01:00
parent 4ff76fdf6f
commit e88045c952
13 changed files with 187 additions and 126 deletions
+8 -9
View File
@@ -1,15 +1,14 @@
create table promotions ( create table promotions (
id integer primary key autoincrement, id integer primary key autoincrement,
name text, endyear integer,
endyear integer, current integer
current integer
); );
create table students ( create table students (
userId text primary key, userId text primary key,
firstName text, firstName text,
lastName text, lastName text,
mail text, mail text,
promotionId integer, promotionId integer,
foreign key(promotionId) references promotions(id) foreign key(promotionId) references promotions(id)
); );
+4 -6
View File
@@ -13,12 +13,12 @@ import * as $_apps_notes_index from "./routes/(apps)/notes/index.tsx";
import * as $_apps_notes_partials_admin_courses from "./routes/(apps)/notes/partials/(admin)/courses.tsx"; import * as $_apps_notes_partials_admin_courses from "./routes/(apps)/notes/partials/(admin)/courses.tsx";
import * as $_apps_notes_partials_index from "./routes/(apps)/notes/partials/index.tsx"; import * as $_apps_notes_partials_index from "./routes/(apps)/notes/partials/index.tsx";
import * as $_apps_notes_partials_notes from "./routes/(apps)/notes/partials/notes.tsx"; import * as $_apps_notes_partials_notes from "./routes/(apps)/notes/partials/notes.tsx";
import * as $_apps_students_api_insert_students from "./routes/(apps)/students/api/insert_students.ts"; import * as $_apps_students_api_students from "./routes/(apps)/students/api/students.ts";
import * as $_apps_students_api_types_d from "./routes/(apps)/students/api/types.d.ts";
import * as $_apps_students_index from "./routes/(apps)/students/index.tsx"; import * as $_apps_students_index from "./routes/(apps)/students/index.tsx";
import * as $_apps_students_partials_admin_consult from "./routes/(apps)/students/partials/(admin)/consult.tsx"; import * as $_apps_students_partials_admin_consult from "./routes/(apps)/students/partials/(admin)/consult.tsx";
import * as $_apps_students_partials_admin_upload from "./routes/(apps)/students/partials/(admin)/upload.tsx"; import * as $_apps_students_partials_admin_upload from "./routes/(apps)/students/partials/(admin)/upload.tsx";
import * as $_apps_students_partials_index from "./routes/(apps)/students/partials/index.tsx"; import * as $_apps_students_partials_index from "./routes/(apps)/students/partials/index.tsx";
import * as $_apps_students_partials_overview from "./routes/(apps)/students/partials/overview.tsx";
import * as $_404 from "./routes/_404.tsx"; import * as $_404 from "./routes/_404.tsx";
import * as $_app from "./routes/_app.tsx"; import * as $_app from "./routes/_app.tsx";
import * as $_middleware from "./routes/_middleware.ts"; import * as $_middleware from "./routes/_middleware.ts";
@@ -55,8 +55,8 @@ const manifest = {
$_apps_notes_partials_admin_courses, $_apps_notes_partials_admin_courses,
"./routes/(apps)/notes/partials/index.tsx": $_apps_notes_partials_index, "./routes/(apps)/notes/partials/index.tsx": $_apps_notes_partials_index,
"./routes/(apps)/notes/partials/notes.tsx": $_apps_notes_partials_notes, "./routes/(apps)/notes/partials/notes.tsx": $_apps_notes_partials_notes,
"./routes/(apps)/students/api/insert_students.ts": "./routes/(apps)/students/api/students.ts": $_apps_students_api_students,
$_apps_students_api_insert_students, "./routes/(apps)/students/api/types.d.ts": $_apps_students_api_types_d,
"./routes/(apps)/students/index.tsx": $_apps_students_index, "./routes/(apps)/students/index.tsx": $_apps_students_index,
"./routes/(apps)/students/partials/(admin)/consult.tsx": "./routes/(apps)/students/partials/(admin)/consult.tsx":
$_apps_students_partials_admin_consult, $_apps_students_partials_admin_consult,
@@ -64,8 +64,6 @@ const manifest = {
$_apps_students_partials_admin_upload, $_apps_students_partials_admin_upload,
"./routes/(apps)/students/partials/index.tsx": "./routes/(apps)/students/partials/index.tsx":
$_apps_students_partials_index, $_apps_students_partials_index,
"./routes/(apps)/students/partials/overview.tsx":
$_apps_students_partials_overview,
"./routes/_404.tsx": $_404, "./routes/_404.tsx": $_404,
"./routes/_app.tsx": $_app, "./routes/_app.tsx": $_app,
"./routes/_middleware.ts": $_middleware, "./routes/_middleware.ts": $_middleware,
+2 -2
View File
@@ -6,12 +6,12 @@ import {
export const handler: MiddlewareHandler<AuthenticatedState>[] = [ export const handler: MiddlewareHandler<AuthenticatedState>[] = [
/** /**
* Check if user is authenticated and add session to context accordingly. * Get all available pages for current user.
* @param request The HTTP incomming request. * @param request The HTTP incomming request.
* @param context The Fresh context object with custom `AuthenticatedState`. * @param context The Fresh context object with custom `AuthenticatedState`.
* @returns The response from the next middleware. * @returns The response from the next middleware.
*/ */
async function checkAuthentication( async function getAllAvailablePages(
request: Request, request: Request,
context: FreshContext<AuthenticatedState>, context: FreshContext<AuthenticatedState>,
): Promise<Response> { ): Promise<Response> {
@@ -22,7 +22,7 @@ export default function ConsultStudents() {
useEffect(() => { useEffect(() => {
const fetchData = async () => { const fetchData = async () => {
try { try {
const response = await fetch("/students/api/insert_students"); const response = await fetch("/students/api/students");
if (!response.ok) { if (!response.ok) {
throw new Error(`Error fetching data: ${response.statusText}`); throw new Error(`Error fetching data: ${response.statusText}`);
} }
@@ -39,7 +39,7 @@ export default function UploadStudents() {
console.log(`Data from sheet ${sheetName}:`, data); console.log(`Data from sheet ${sheetName}:`, data);
const response = await fetch("/students/api/insert_students", { const response = await fetch("/students/api/students", {
method: "POST", method: "POST",
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
body: JSON.stringify({ promoName: sheetName, data }), body: JSON.stringify({ promoName: sheetName, data }),
-1
View File
@@ -5,7 +5,6 @@ const properties: AppProperties = {
icon: "badge", icon: "badge",
pages: { pages: {
index: "Homepage", index: "Homepage",
overview: "Students overview",
upload: "Upload students", upload: "Upload students",
consult: "Consult students", consult: "Consult students",
}, },
@@ -1,84 +0,0 @@
import { Handlers } from "$fresh/server.ts";
// import { Database } from "@db/sqlite";
import connect from "$root/databases/connect.ts";
export const handler: Handlers = {
// deno-lint-ignore require-await
async GET() {
try {
using connection = connect("students");
const promotions = connection.database.prepare(
"select id, name from promotions",
).all();
const students = connection.database
.prepare(
`select userId, firstName, lastName, mail, promotionId from students`,
)
.all();
return new Response(
JSON.stringify({ promotions, students }),
{
status: 200,
headers: { "Content-Type": "application/json" },
},
);
} catch (error) {
console.error("Error fetching data:", error);
return new Response("Failed to fetch data", { status: 500 });
}
},
async POST(request) {
console.log("API /students/api/insert_students called");
try {
const body = await request.json();
const { data, promoName } = body;
console.log("Received data:", { promoName, data });
if (!promoName || !Array.isArray(data)) {
throw new Error("Invalid request body");
}
using connection = connect("students");
connection.database.prepare(
"INSERT OR IGNORE INTO promotions (name) VALUES (?)",
).run(promoName);
const promoIdRow: { id: number } = connection.database
.prepare("SELECT id FROM promotions WHERE name = ?")
.get(promoName)!;
const promoId = promoIdRow.id;
console.log(`Promotion ID for "${promoName}":`, promoId);
const insertQuery = connection.database.prepare(
`INSERT INTO students
(userId, firstName, lastName, mail, promotionId)
VALUES (?, ?, ?, ?, ?)`,
);
for (const student of data) {
console.log("Inserting student:", student);
insertQuery.run(
student.Identifiant,
student.Nom,
student["Prénom"],
student.Mail,
promoId,
);
}
console.log("All data inserted successfully");
return new Response("Data inserted successfully", { status: 201 });
} catch (error) {
console.error("Error inserting data:", error);
return new Response("Failed to insert data", { status: 500 });
}
},
};
+155
View File
@@ -0,0 +1,155 @@
import { FreshContext, Handlers } from "$fresh/server.ts";
import connect from "$root/databases/connect.ts";
import { AuthenticatedState } from "$root/defaults/interfaces.ts";
import { Database } from "@db/sqlite";
/**
* Gets itself from the database.
* @param database The database connection
* @param userId The user ID.
* @returns Itself from the database.
*/
function getItself(
database: Database,
userId: string,
): { student: Student | null; promo: Promotion | null } {
const studentQuery = "select * from students where userId = ?";
const student: Student | undefined = database.prepare(studentQuery).get(
userId,
);
if (!student) {
return { student: null, promo: null };
}
const promoQuery = "select * from promotions where id = ?";
const promo: Promotion | undefined = database.prepare(promoQuery).get(
student.promotionId,
);
return { student, promo: promo ?? null };
}
/**
* Gets itself from the database.
* @param database The database connection
* @param userId The user ID.
* @returns Itself from the database.
*/
function getAll(
database: Database,
userId: string,
): { student: Student | null; promo: Promotion | null } {
const studentQuery = "select * from students where userId = ?";
const student: Student | undefined = database.prepare(studentQuery).get(
userId,
);
if (!student) {
return { student: null, promo: null };
}
const promoQuery = "select * from promotions where id = ?";
const promo: Promotion | undefined = database.prepare(promoQuery).get(
student.promotionId,
);
return { student, promo: promo ?? null };
}
export const handler: Handlers<null, AuthenticatedState> = {
/**
* The students the user can see.
* @param _request The HTTP request.
* @param _context The context with authenticated state.
* @returns All students our user can see.
*/
// deno-lint-ignore require-await
async GET(
_request: Request,
context: FreshContext<AuthenticatedState>,
): Promise<Response> {
using connection = connect("students");
const database = connection.database;
if (context.state.session.eduPersonPrimaryAffiliation == "student") {
return new Response(
JSON.stringify({
student: getItself(database, context.state.session.uid),
}),
{
headers: {
"content-type": "application/json",
},
},
);
}
const promotions = database.prepare("select id, name from promotions")
.all();
const students = database.prepare(
"select userId, firstName, lastName, mail, promotionId from students",
).all();
return new Response(
JSON.stringify({ promotions, students }),
{
status: 200,
headers: { "Content-Type": "application/json" },
},
);
},
async POST(request) {
console.log("API /students/api/insert_students called");
try {
const body = await request.json();
const { data, promoName } = body;
console.log("Received data:", { promoName, data });
if (!promoName || !Array.isArray(data)) {
throw new Error("Invalid request body");
}
using connection = connect("students");
connection.database.prepare(
"INSERT OR IGNORE INTO promotions (name) VALUES (?)",
).run(promoName);
const promoIdRow: { id: number } = connection.database
.prepare("SELECT id FROM promotions WHERE name = ?")
.get(promoName)!;
const promoId = promoIdRow.id;
console.log(`Promotion ID for "${promoName}":`, promoId);
const insertQuery = connection.database.prepare(
`INSERT INTO students
(userId, firstName, lastName, mail, promotionId)
VALUES (?, ?, ?, ?, ?)`,
);
for (const student of data) {
console.log("Inserting student:", student);
insertQuery.run(
student.Identifiant,
student.Nom,
student["Prénom"],
student.Mail,
promoId,
);
}
console.log("All data inserted successfully");
return new Response("Data inserted successfully", { status: 201 });
} catch (error) {
console.error("Error inserting data:", error);
return new Response("Failed to insert data", { status: 500 });
}
},
};
+13
View File
@@ -0,0 +1,13 @@
interface Student {
userId: string;
firstName: string;
lastName: string;
mail: string;
promotionId: number;
}
interface Promotion {
id: number;
endyear: number;
current: number;
}
@@ -4,8 +4,7 @@ import {
makePartials, makePartials,
} from "$root/defaults/makePartials.tsx"; } from "$root/defaults/makePartials.tsx";
import { FreshContext } from "$fresh/server.ts"; import { FreshContext } from "$fresh/server.ts";
import { State } from "$root/routes/_middleware.ts"; import { State } from "$root/defaults/interfaces.ts";
//import EditStudents from "../(_islands)/EditStudents.tsx";
// deno-lint-ignore require-await // deno-lint-ignore require-await
async function Students(_request: Request, _context: FreshContext<State>) { async function Students(_request: Request, _context: FreshContext<State>) {
@@ -4,8 +4,7 @@ import {
makePartials, makePartials,
} from "$root/defaults/makePartials.tsx"; } from "$root/defaults/makePartials.tsx";
import { FreshContext } from "$fresh/server.ts"; import { FreshContext } from "$fresh/server.ts";
import { State } from "$root/routes/_middleware.ts"; import { State } from "$root/defaults/interfaces.ts";
//import EditStudents from "../(_islands)/EditStudents.tsx";
// deno-lint-ignore require-await // deno-lint-ignore require-await
async function Students(_request: Request, _context: FreshContext<State>) { async function Students(_request: Request, _context: FreshContext<State>) {
+1 -1
View File
@@ -3,7 +3,7 @@ import {
makePartials, makePartials,
} from "$root/defaults/makePartials.tsx"; } from "$root/defaults/makePartials.tsx";
import { FreshContext } from "$fresh/server.ts"; import { FreshContext } from "$fresh/server.ts";
import { State } from "$root/routes/_middleware.ts"; import { State } from "$root/defaults/interfaces.ts";
// deno-lint-ignore require-await // deno-lint-ignore require-await
export async function Index(_request: Request, context: FreshContext<State>) { export async function Index(_request: Request, context: FreshContext<State>) {
@@ -1,17 +0,0 @@
import { Partial } from "$fresh/runtime.ts";
import { RouteConfig } from "$fresh/server.ts";
type ModulesProps = Record<string | number | symbol, never>;
export const config: RouteConfig = {
skipAppWrapper: true,
skipInheritedLayouts: true,
};
export default function Modules(_props: ModulesProps) {
return (
<Partial name="body">
<a href="students" f-partial={"notes/partials"}>students</a>
</Partial>
);
}