From d60f89487ab3bc2390054efcd5d986a4aadd4291 Mon Sep 17 00:00:00 2001 From: Linnnus Date: Tue, 18 Feb 2025 18:01:09 +0100 Subject: =?UTF-8?q?Tilf=C3=B8j=20opgaver=20(assignments)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/lib/server/assignments.ts | 84 ++++++++++++++++++++++ app/src/routes/assignments/+page.server.ts | 16 +++++ app/src/routes/assignments/+page.svelte | 21 ++++++ .../assignments/[assignmentId]/+page.server.ts | 27 +++++++ .../routes/assignments/[assignmentId]/+page.svelte | 25 +++++++ app/src/routes/profile/+page.svelte | 7 +- 6 files changed, 178 insertions(+), 2 deletions(-) create mode 100644 app/src/lib/server/assignments.ts create mode 100644 app/src/routes/assignments/+page.server.ts create mode 100644 app/src/routes/assignments/+page.svelte create mode 100644 app/src/routes/assignments/[assignmentId]/+page.server.ts create mode 100644 app/src/routes/assignments/[assignmentId]/+page.svelte diff --git a/app/src/lib/server/assignments.ts b/app/src/lib/server/assignments.ts new file mode 100644 index 0000000..7622408 --- /dev/null +++ b/app/src/lib/server/assignments.ts @@ -0,0 +1,84 @@ +import type pg from "pg"; + +/** A row from the `cemetary_plot` table. */ +export interface CemetaryPlot { + id: number; + address: string; + ownerId: number; + //assignmentInterval: Date; +} + +/** A row from the `assignments` table. */ +export interface Assignment { + id: number; + gardenerId: number; + cemetaryPlotId: number; + date: Date; +} + +/** + * Retrieves all assignments for the given user. + * + * @param dbConn Connection to database. + * @param userId ID used to identify user. + */ +export async function getAssignments(dbConn: pg.ClientBase, userId: number): Promise { + const result = await dbConn.query( + "SELECT * FROM assignments WHERE gardener_id = $1 ORDER BY date", + [userId], + ); + return result.rows.map( + (r) => + ({ + id: r.id, + gardenerId: r.gardener_id, + cemetaryPlotId: r.cemetary_plot_id, + date: r.date, + }) satisfies Assignment, + ); +} + +type GetAssignmentResult = + | { assignment: Assignment; cemetaryPlot: CemetaryPlot } + | { assignment: null; cemetaryPlot: null }; + +/** + * Retrieves a specfic assignment, along with relevant cemetary plot. + */ +export async function getAssignmentAndCemetaryById( + dbConn: pg.ClientBase, + assignmentId: number, +): Promise { + const queryText = `SELECT + a.id, + a.gardener_id, + a.cemetary_plot_id, + a.date, + c.id, + c.address, + c.owner_id, + c.assignment_interval + FROM + assignments AS a + INNER JOIN + cemetary_plots AS C ON c.id = a.cemetary_plot_id + WHERE c.id = $1`; + const result = await dbConn.query({ rowMode: "array", text: queryText }, [assignmentId]); + if (result.rowCount == 0) { + return { assignment: null, cemetaryPlot: null }; + } + + const assignment: Assignment = { + id: result.rows[0][0], + gardenerId: result.rows[0][1], + cemetaryPlotId: result.rows[0][2], + date: result.rows[0][3], + }; + const cemetaryPlot: CemetaryPlot = { + id: result.rows[0][4], + address: result.rows[0][5], + ownerId: result.rows[0][6], + //assignmentInterval: result.rows[0][7], + }; + return { assignment, cemetaryPlot }; +} diff --git a/app/src/routes/assignments/+page.server.ts b/app/src/routes/assignments/+page.server.ts new file mode 100644 index 0000000..0b829cd --- /dev/null +++ b/app/src/routes/assignments/+page.server.ts @@ -0,0 +1,16 @@ +import type { PageServerLoad } from "./$types"; +import { getAssignments } from "$lib/server/assignments"; +import { redirect } from "@sveltejs/kit"; + +export const load = (async ({ url, locals }) => { + if (!locals.user) { + redirect(303, `/login?redirectTo=${encodeURIComponent(url.toString())}`); + } + + const assignments = await getAssignments(locals.dbConn, locals.user.id); + + return { + user: locals.user, + assignments, + }; +}) satisfies PageServerLoad; diff --git a/app/src/routes/assignments/+page.svelte b/app/src/routes/assignments/+page.svelte new file mode 100644 index 0000000..f43767d --- /dev/null +++ b/app/src/routes/assignments/+page.svelte @@ -0,0 +1,21 @@ + + + + +

Kommende opgaver for {data.user.firstName}

+ +
    + {#each data.assignments as assignment} +
  1. + {assignment.date} + Mere info +
  2. + {/each} +
+ + diff --git a/app/src/routes/assignments/[assignmentId]/+page.server.ts b/app/src/routes/assignments/[assignmentId]/+page.server.ts new file mode 100644 index 0000000..566dcd9 --- /dev/null +++ b/app/src/routes/assignments/[assignmentId]/+page.server.ts @@ -0,0 +1,27 @@ +import { getAssignmentAndCemetaryById } from "$lib/server/assignments"; +import type { PageServerLoad } from "./$types"; +import { error, redirect } from "@sveltejs/kit"; + +export const load = (async ({ params, url, locals }) => { + if (!locals.user) { + redirect(303, `/login?redirectTo=${encodeURIComponent(url.toString())}`); + } + + const { assignment, cemetaryPlot } = await getAssignmentAndCemetaryById( + locals.dbConn, + +params.assignmentId, + ); + if (!assignment) { + return error(404, `Cemetary plot with id ${params.assignmentId} not found`); + } + console.debug("Found assignment: ", assignment); + if (assignment.gardenerId !== locals.user.id) { + return error(403, "This assignment isn't for you!"); + } + + return { + user: locals.user, + assignment, + cemetaryPlot, + }; +}) satisfies PageServerLoad; diff --git a/app/src/routes/assignments/[assignmentId]/+page.svelte b/app/src/routes/assignments/[assignmentId]/+page.svelte new file mode 100644 index 0000000..0b36a19 --- /dev/null +++ b/app/src/routes/assignments/[assignmentId]/+page.svelte @@ -0,0 +1,25 @@ + + + + Opgave på {data.cemetaryPlot.address} + + +

Assignment #{data.assignment.id}

+

+ Gravstedet, der skal vedligeholdes er ved {data.cemetaryPlot.address}. +

+

Vedligeholdelsen skal finde sted

+ + diff --git a/app/src/routes/profile/+page.svelte b/app/src/routes/profile/+page.svelte index 0ee18f0..62078cc 100644 --- a/app/src/routes/profile/+page.svelte +++ b/app/src/routes/profile/+page.svelte @@ -8,5 +8,8 @@ Dummy profile picture

Hej, {data.user.firstName} {data.user.lastName}!

- +{#if data.user.role === "gardener"} +

Tjek dine opgaver her: Opgaver

+{/if} + + -- cgit v1.2.3