diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index b828ec8..9a468a0 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -73,6 +73,8 @@ services: build: context: . dockerfile: docker/postgres.Dockerfile + ports: + - 5432:5432 environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} diff --git a/docker-compose.yml b/docker-compose.yml index d79b2b7..86d9a16 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,3 +9,6 @@ services: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} + volumes: + - './database:/var/lib/postgresql/data:z' + restart: never diff --git a/src/app.d.ts b/src/app.d.ts index 5de50c2..61fd649 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -1,11 +1,9 @@ -import type { Database } from '$lib/server/db/connect'; import type { User } from '$lib/server/db/schema/user'; import type { Session } from '$lib/server/db/schema/session'; declare global { namespace App { interface Locals { - database: Database; user: User | null; session: Session | null; } diff --git a/src/hooks.server.ts b/src/hooks.server.ts index 760f480..9468998 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -35,6 +35,7 @@ export const handle: Handle = async ({ event, resolve }) => { } else { // If session is invalid, delete the session cookie deleteSessionTokenCookie(event); + // Redirect to the login page after session expiry if (event.url.pathname !== '/login') { return redirect(302, '/login'); diff --git a/src/lib/server/db/connect.ts b/src/lib/server/db/connect.ts index d50f7ea..9e09ae0 100644 --- a/src/lib/server/db/connect.ts +++ b/src/lib/server/db/connect.ts @@ -4,7 +4,7 @@ import { env } from '$env/dynamic/private'; import { connectDatabaseWithURL } from './connect_generic'; export type Database = PostgresJsDatabase>; -export type Client = postgres.Sql<{}>; +export type Client = postgres.Sql<{}>; // eslint-disable-line @typescript-eslint/no-empty-object-type // Connects to the database using the DATABASE_URL environment variable export async function connectDatabase(): Promise<{ diff --git a/src/routes/(dashboard)/+page.server.ts b/src/routes/(dashboard)/+page.server.ts index 331bd75..3a1a681 100644 --- a/src/routes/(dashboard)/+page.server.ts +++ b/src/routes/(dashboard)/+page.server.ts @@ -6,11 +6,10 @@ import { Employee, Student, type Person } from '$lib/types/person'; import { invalidateSession } from '$lib/server/db/session'; import { deleteSessionTokenCookie } from '$lib/server/session'; -export const load: PageServerLoad = async ({ url }) => { +export const load: PageServerLoad = async () => { try { - const searchQuery = url.searchParams.get('q') ?? undefined; - const studentsP = getStudents(1000, 0, searchQuery); - const employeesP = getEmployees(1000, 0, searchQuery); + const studentsP = getStudents(1000, 0); + const employeesP = getEmployees(1000, 0); const students = await studentsP; const employees = await employeesP; @@ -38,7 +37,6 @@ export const load: PageServerLoad = async ({ url }) => { ]; return { - searchQuery, persons }; } catch (err: unknown) { @@ -50,6 +48,50 @@ export const load: PageServerLoad = async ({ url }) => { }; export const actions: Actions = { + search: async ({ request }) => { + try { + const formData = await request.formData(); + const searchQuery = formData.get('q')?.toString() ?? undefined; + + const studentsP = getStudents(1000, 0, searchQuery); + const employeesP = getEmployees(1000, 0, searchQuery); + const students = await studentsP; + const employees = await employeesP; + + const persons: Person[] = [ + ...students.map((s) => ({ + id: s.id, + type: Student, + identifier: s.index, + fname: s.fname, + lname: s.lname, + department: s.department, + building: s.building, + state: s.state + })), + ...employees.map((e) => ({ + id: e.id, + type: Employee, + identifier: e.email, + fname: e.fname, + lname: e.lname, + department: e.department, + building: e.building, + state: e.state + })) + ]; + + return { + searchQuery, + persons + }; + } catch (err: unknown) { + console.debug(`Failed to search: ${(err as Error).message}`); + return fail(500, { + message: 'Failed to search' + }); + } + }, togglestate: async ({ request, locals }) => { try { const formData = await request.formData(); @@ -86,10 +128,14 @@ export const actions: Actions = { } else if (type === Employee) { await toggleEmployeeState(id, building, creator); } else { - return fail(400, { + return fail(500, { message: 'Invalid type (neither student nor employee)' }); } + + return { + message: 'Successfully toggled state' + }; } catch (err: unknown) { console.debug(`Failed to toggle state: ${(err as Error).message}`); return fail(400, { diff --git a/src/routes/(dashboard)/+page.svelte b/src/routes/(dashboard)/+page.svelte index 729056c..9bc35d6 100644 --- a/src/routes/(dashboard)/+page.svelte +++ b/src/routes/(dashboard)/+page.svelte @@ -5,33 +5,54 @@ import Search from 'lucide-svelte/icons/search'; import Reset from 'lucide-svelte/icons/list-restart'; import DataTable from './data-table.svelte'; + import { toast } from 'svelte-sonner'; + import { page } from '$app/stores'; import { columns } from './columns'; + import { enhance } from '$app/forms'; + import { goto } from '$app/navigation'; let { data, form: actionData } = $props(); - const searchQuery = data.searchQuery; - let searchBox: HTMLFormElement | null; + $effect(() => { + const msg = actionData?.message; + if (msg !== undefined) { + if ($page.status === 200) { + toast.success(msg); + } else { + toast.error(msg); + } + } + }); + + let searchQuery = $state(''); + const persons = $derived(actionData?.persons ?? data.persons ?? []);
{ - searchBox?.submit(); + method="POST" + action="?/search" + class="flex gap-2 px-4 py-2" + use:enhance={() => { + return async ({ update }) => { + await update({ reset: false }); + }; }} > -
- - - -

{actionData?.message}

-
+ + +
- +
diff --git a/src/routes/(dashboard)/data-table.svelte b/src/routes/(dashboard)/data-table.svelte index b5e97c0..86e460a 100644 --- a/src/routes/(dashboard)/data-table.svelte +++ b/src/routes/(dashboard)/data-table.svelte @@ -1,4 +1,4 @@ -