import type { PageServerLoad, Actions } from "./$types"; import { SQLiteError } from "bun:sqlite"; import type { FileProperties } from "$lib/server/docstore" import type { RecordEntry, EstimatesEntry } from "$lib/db_types"; import { fail, redirect } from '@sveltejs/kit'; import Logs from "$lib/server/log" import { toInt, parseDate, isTimeValidHHMM } from "$lib/util" import { getRecordFiles } from "$lib/server/docstore"; export const load: PageServerLoad = async ({ locals }) => { if (!locals.user) { Logs.route.warn("An unauthorized user tried to access the record page") return fail(403, { message: "Unauthorized user" }); } let records = locals.user.get_entries().map((v) => ({ entry: v, parsedDate: parseDate(v.date) ?? new Date(0) })); let estimates = locals.user.get_estimates() let documents = (await getRecordFiles(locals.user)).map((v) => { return { year: toInt(v.identifier.substring(0, 4)), month: toInt(v.identifier.substring(5, 7)), file: v }; }); let records_grouped: Map> = new Map() Map.groupBy(records, (v) => { return v.parsedDate.getFullYear() } ).forEach((value, key, _) => { let month_map: Map = new Map() Map.groupBy(value, (v) => v.parsedDate.getMonth()).forEach((value, key, _) => { // remove parsed date month_map.set(key, value.map((v) => v.entry)); }); records_grouped.set(key, month_map); }); let estimates_grouped: Map>= new Map(); Map.groupBy(estimates, (v) => { return v.year }).forEach((value, key, _) => { let arr = value.map((v) => [ { key: ((v.quarter - 1) * 3 + 2), value: v["estimate_2"] }, { key: ((v.quarter - 1) * 3 + 1), value: v["estimate_1"] }, { key: ((v.quarter - 1) * 3 + 0), value: v["estimate_0"] }, ]).flat(); let m: Map = new Map(); Map.groupBy(arr, (e) => e.key).forEach((value, key, _) => { m.set(key, value[0].value); }) estimates_grouped.set(key, m); }) let documents_grouped: Map> = new Map(); Map.groupBy(documents, (v) => v.year ).forEach((value, key, _) => { let m: Map = new Map() Map.groupBy(value, (v) => v.month).forEach((value, key, _) => { m.set(key, value.map((v) => v.file)[0]); }) documents_grouped.set(key, m); }) return { records: records_grouped, estimates: estimates_grouped, documents: documents_grouped }; } export const actions = { new_entry: async ({locals, request}) => { if (!locals.user) { Logs.route.warn("An unauthorized user tried to add a new record") return fail(403, { message: "Unauthorized user" }) } const ok = "ok"; const missing = "missing"; const invalid = "invalid"; const data = await request.formData(); let date = data.get("date") as string; let start = data.get("start") as string; let end = data.get("end") as string; let comment = data.get("comment") as string; let return_obj: Map = new Map(Object.entries({ date : { status: ok, value: date }, start : { status: ok, value: start }, end : { status: ok, value: end }, comment : { status: ok, value: comment }, })) if (date == null) { return_obj.get("date")!.status = missing; } else if (parseDate(date) == null) { return_obj.get("date")!.status = invalid; } if (start == null) { return_obj.get("start")!.status = missing; } else if (!isTimeValidHHMM(start)) { return_obj.get("start")!.status = invalid; } if (end == null) { return_obj.get("end")!.status = missing; } else if (!isTimeValidHHMM(end)) { return_obj.get("end")!.status = invalid; } let invalid_values = [...return_obj.entries()].filter(([_, v]) => { return v.status != ok; }).map(([key, value]) => `${key}: ${value.status}`) if (invalid_values.length > 0) { Logs.user.info(`User id ${locals.user.id} failed to add a new record. Failed: ${invalid_values.join(", ")}`) return fail(400, { new_entry: return_obj }); } let res = locals.user.insert_entry(date, start, end, comment); if (!res) { Logs.user.error(`Failed to add new entry for user id ${locals.user.id} to database.`) return fail(500, { }) } Logs.user.info(`User id ${locals.user.id} created a new record`) return { success: true, new_entry: return_obj }; }, edit_entry: async ({locals, request}) => { if (!locals.user) { Logs.route.warn("An unauthorized user tried to edit a record") return fail(403, { message: "Unauthorized user" }) } const ok = "ok"; const missing = "missing"; const invalid = "invalid"; const data = await request.formData(); let id = data.get("id") as string; let date = data.get("date") as string; let start = data.get("start") as string; let end = data.get("end") as string; let comment = data.get("comment") as string; let return_obj : Map = new Map(Object.entries({ id: { status: ok, value: id, }, date : { status: ok, value: date }, start : { status: ok, value: start }, end : { status: ok, value: end }, comment : { status: ok, value: comment }, })) if (id == null) { return_obj.get("id")!.status = missing; } else if (isNaN(toInt(id))) { return_obj.get("id")!.status = invalid; } if (date == null) { return_obj.get("date")!.status = missing; } else if (parseDate(date) == null) { return_obj.get("date")!.status = invalid; } if (start == null) { return_obj.get("start")!.status = missing; } else if (!isTimeValidHHMM(start)) { return_obj.get("start")!.status = invalid; } if (end == null) { return_obj.get("end")!.status = missing; } else if (!isTimeValidHHMM(end)) { return_obj.get("end")!.status = invalid; } let invalid_values = [...return_obj.entries()].filter(([_, v]) => { return v.status != ok; }).map(([key, value]) => `${key}: ${value.status}`) if (invalid_values.length > 0) { Logs.user.info(`User id ${locals.user.id} failed to edit an entry. Failed: ${invalid_values.join(", ")}`) return fail(400, { edit_entry: return_obj }); } let user_id = toInt(id); let current = locals.user.get_entry(user_id); if (!current) { return fail(404, { edit_entry: return_obj }); } if (current.id == user_id && current.date == date && current.start == start && current.end == end && current.comment == comment) { return { success: false, edit_entry: return_obj } } let res = false; try { res = locals.user.update_entry(user_id, date, start, end, comment); } catch (e) { if (!(e instanceof SQLiteError)) { throw e; } } if (!res) { Logs.user.error(`Failed to edit an entry for user id ${locals.user.id} in database.`) return fail(500, { }) } redirect(303, '/'); return { success: true }; }, remove_entry: async ({ locals, request })=> { if (!locals.user) { Logs.route.warn("An unauthorized user tried to delete a record") return fail(403, { message: "Unauthorized user" }) } const data = await request.formData(); let id = data.get("id") as string; if (id == null) { Logs.user.info(`User id ${locals.user.id} failed to remove an entry. Failed: id is missing`) return fail(400, { id: id }); } let user_id = toInt(id); if (isNaN(user_id)) { Logs.user.info(`User id ${locals.user.id} failed to remove an entry. Failed: id is not a Number`) return fail(400, { id: id }); } let res = false; try { res = locals.user.remove_entry(user_id); } catch (e) { if (!(e instanceof SQLiteError)) { throw e; } } if (!res) { Logs.user.error(`Failed to remove an entry for user id ${locals.user.id} from database.`) return fail(500, { }); } return { success: true } } } satisfies Actions;