From 4abf5405589b3a61bcef180962fee448d41bc11c Mon Sep 17 00:00:00 2001 From: Clayzxr Date: Wed, 22 Jan 2025 15:09:22 +0100 Subject: [PATCH] Init mobility DB --- databases/init/mobility.sql | 11 ++ databases/init/students.sql | 2 +- fresh.gen.ts | 6 +- .../mobility/(_islands)/EditMobility.tsx | 157 ++++++++++++++++++ routes/(apps)/mobility/(_props)/props.ts | 4 +- routes/(apps)/mobility/api/insert_mobility.ts | 96 +++++++++++ .../partials/(admin)/edit_mobility.tsx | 16 ++ .../mobility/partials/(admin)/mobility.tsx | 17 -- 8 files changed, 286 insertions(+), 23 deletions(-) create mode 100644 routes/(apps)/mobility/api/insert_mobility.ts create mode 100644 routes/(apps)/mobility/partials/(admin)/edit_mobility.tsx delete mode 100644 routes/(apps)/mobility/partials/(admin)/mobility.tsx diff --git a/databases/init/mobility.sql b/databases/init/mobility.sql index e69de29..fe503d4 100644 --- a/databases/init/mobility.sql +++ b/databases/init/mobility.sql @@ -0,0 +1,11 @@ +CREATE TABLE mobility ( + id integer primary key autoincrement, + studentId text, + startDate date, + endDate date, + weeksCount integer, + destinationCountry text, + destinationName text, + mobilityStatus text default 'N/A', + foreign key (studentId) references students(userId) +); \ No newline at end of file diff --git a/databases/init/students.sql b/databases/init/students.sql index 63fffe4..4dbc7e8 100644 --- a/databases/init/students.sql +++ b/databases/init/students.sql @@ -1,6 +1,6 @@ create table promotions ( id integer primary key autoincrement, - name text, + name text, endyear integer, current integer ); diff --git a/fresh.gen.ts b/fresh.gen.ts index 654e3be..58412fb 100644 --- a/fresh.gen.ts +++ b/fresh.gen.ts @@ -4,7 +4,7 @@ import * as $_apps_layout from "./routes/(apps)/_layout.tsx"; import * as $_apps_mobility_index from "./routes/(apps)/mobility/index.tsx"; -import * as $_apps_mobility_partials_admin_mobility from "./routes/(apps)/mobility/partials/(admin)/mobility.tsx"; +import * as $_apps_mobility_partials_admin_edit_mobility from "./routes/(apps)/mobility/partials/(admin)/edit_mobility.tsx"; import * as $_apps_mobility_partials_admin_consult_students_test from "./routes/(apps)/mobility/partials/(admin)/consult_students_test.tsx"; import * as $_apps_mobility_partials_index from "./routes/(apps)/mobility/partials/index.tsx"; import * as $_apps_mobility_partials_overview from "./routes/(apps)/mobility/partials/overview.tsx"; @@ -42,8 +42,8 @@ const manifest = { routes: { "./routes/(apps)/_layout.tsx": $_apps_layout, "./routes/(apps)/mobility/index.tsx": $_apps_mobility_index, - "./routes/(apps)/mobility/partials/(admin)/mobility.tsx": - $_apps_mobility_partials_admin_mobility, + "./routes/(apps)/mobility/partials/(admin)/edit_mobility.tsx": + $_apps_mobility_partials_admin_edit_mobility, "./routes/(apps)/mobility/partials/(admin)/consult_students_test.tsx": $_apps_mobility_partials_admin_consult_students_test, "./routes/(apps)/mobility/partials/index.tsx": diff --git a/routes/(apps)/mobility/(_islands)/EditMobility.tsx b/routes/(apps)/mobility/(_islands)/EditMobility.tsx index e69de29..43b80ef 100644 --- a/routes/(apps)/mobility/(_islands)/EditMobility.tsx +++ b/routes/(apps)/mobility/(_islands)/EditMobility.tsx @@ -0,0 +1,157 @@ +import { useEffect, useState } from "preact/hooks"; + +interface MobilityData { + id: number; + studentId: string; + firstName: string; + lastName: string; + startDate: string | null; + endDate: string | null; + weeksCount: number | null; + destinationCountry: string | null; + destinationName: string | null; + mobilityStatus: string; +} + +export default function EditMobility() { + const [mobilityData, setMobilityData] = useState([]); + const [isSaving, setIsSaving] = useState(false); + + useEffect(() => { + async function fetchMobilityData() { + const response = await fetch("/mobility/api/insert_mobility"); + const data = await response.json(); + setMobilityData(data.mobilities || []); + } + + fetchMobilityData(); + }, []); + + const handleChange = ( + id: number, + field: keyof MobilityData, + value: string | number | null, + ) => { + setMobilityData((prev) => + prev.map((entry) => + entry.id === id ? { ...entry, [field]: value } : entry, + ) + ); + }; + + const handleSave = async () => { + setIsSaving(true); + + try { + const response = await fetch("/mobility/api/insert_mobility", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ data: mobilityData }), + }); + + if (response.ok) { + alert("Data saved successfully!"); + } else { + alert("Failed to save data."); + } + } catch (error) { + console.error("Error saving data:", error); + alert("An error occurred while saving data."); + } finally { + setIsSaving(false); + } + }; + + return ( +
+ + + + + + + + + + + + + + + {mobilityData.map((mobility) => ( + + + + + + + + + + + ))} + +
First NameLast NameStart DateEnd DateWeeks CountDestination CountryDestination NameStatus
{mobility.firstName}{mobility.lastName} + + handleChange(mobility.id, "startDate", e.target.value) + } + /> + + + handleChange(mobility.id, "endDate", e.target.value) + } + /> + + + handleChange( + mobility.id, + "weeksCount", + Number(e.target.value) || null, + ) + } + /> + + + handleChange(mobility.id, "destinationCountry", e.target.value) + } + /> + + + handleChange(mobility.id, "destinationName", e.target.value) + } + /> + + +
+ +
+ ); +} diff --git a/routes/(apps)/mobility/(_props)/props.ts b/routes/(apps)/mobility/(_props)/props.ts index 82165f2..75a91b4 100644 --- a/routes/(apps)/mobility/(_props)/props.ts +++ b/routes/(apps)/mobility/(_props)/props.ts @@ -7,10 +7,10 @@ const properties: AppProperties = { pages: { index: "Homepage", overview: "Mobility overview", - mobility: "Mobility management", + edit_mobility: "Mobility management", consult_students_test: "Test consult students", }, - adminOnly: ["mobility", "consult_students_test"], + adminOnly: ["edit_mobility", "consult_students_test"], }; export default properties; diff --git a/routes/(apps)/mobility/api/insert_mobility.ts b/routes/(apps)/mobility/api/insert_mobility.ts new file mode 100644 index 0000000..2d5b3f9 --- /dev/null +++ b/routes/(apps)/mobility/api/insert_mobility.ts @@ -0,0 +1,96 @@ +import { Handlers } from "$fresh/server.ts"; +import connect from "$root/databases/connect.ts"; + +export const handler: Handlers = { + async GET() { + try { + using connection = connect("mobility"); + + const mobilities = connection.database.prepare( + `SELECT + mobility.id, + mobility.studentId, + students.firstName, + students.lastName, + mobility.startDate, + mobility.endDate, + mobility.weeksCount, + mobility.destinationCountry, + mobility.destinationName, + mobility.mobilityStatus + FROM mobility + LEFT JOIN students ON mobility.studentId = students.userId`, + ).all(); + + return new Response( + JSON.stringify({ mobilities }), + { + status: 200, + headers: { "Content-Type": "application/json" }, + }, + ); + } catch (error) { + console.error("Error fetching mobility data:", error); + return new Response("Failed to fetch data", { status: 500 }); + } + }, + + async POST(request) { + console.log("API /mobility/api/update_mobility called"); + + try { + const body = await request.json(); + const { data } = body; + + if (!Array.isArray(data)) { + throw new Error("Invalid request body"); + } + + using connection = connect("mobility"); + + const updateQuery = connection.database.prepare( + `INSERT INTO mobility ( + id, studentId, startDate, endDate, weeksCount, destinationCountry, destinationName, mobilityStatus + ) + VALUES (?, ?, ?, ?, ?, ?, ?, ?) + ON CONFLICT(id) DO UPDATE SET + startDate = excluded.startDate, + endDate = excluded.endDate, + weeksCount = excluded.weeksCount, + destinationCountry = excluded.destinationCountry, + destinationName = excluded.destinationName, + mobilityStatus = excluded.mobilityStatus` + ); + + for (const mobility of data) { + const { + id, + studentId, + startDate, + endDate, + weeksCount, + destinationCountry, + destinationName, + mobilityStatus = "N/A", + } = mobility; + + updateQuery.run( + id, + studentId, + startDate, + endDate, + weeksCount, + destinationCountry, + destinationName, + mobilityStatus + ); + } + + console.log("Mobility data updated successfully"); + return new Response("Data updated successfully", { status: 200 }); + } catch (error) { + console.error("Error updating mobility data:", error); + return new Response("Failed to update data", { status: 500 }); + } + }, +}; diff --git a/routes/(apps)/mobility/partials/(admin)/edit_mobility.tsx b/routes/(apps)/mobility/partials/(admin)/edit_mobility.tsx new file mode 100644 index 0000000..e7a1df1 --- /dev/null +++ b/routes/(apps)/mobility/partials/(admin)/edit_mobility.tsx @@ -0,0 +1,16 @@ +import EditMobility from "$root/routes/(apps)/mobility/(_islands)/EditMobility.tsx"; +import { getPartialsConfig, makePartials } from "$root/defaults/makePartials.tsx"; +import { FreshContext } from "$fresh/server.ts"; +import { State } from "$root/routes/_middleware.ts"; + +async function Mobility(_request: Request, _context: FreshContext) { + return ( + <> +

Edit mobility

+ + + ); +} + +export const config = getPartialsConfig(); +export default makePartials(Mobility); diff --git a/routes/(apps)/mobility/partials/(admin)/mobility.tsx b/routes/(apps)/mobility/partials/(admin)/mobility.tsx deleted file mode 100644 index a73c859..0000000 --- a/routes/(apps)/mobility/partials/(admin)/mobility.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { Partial } from "$fresh/runtime.ts"; -import { RouteConfig } from "$fresh/server.ts"; - -type ModulesProps = Record; - -export const config: RouteConfig = { - skipAppWrapper: true, - skipInheritedLayouts: true, -}; - -export default function Modules(_props: ModulesProps) { - return ( - - mobility - - ); -}