From 6cd25464474c8bbe8d64438faaa12571f805311a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Aleksa=20Siri=C5=A1ki?=
<31509435+aleksasiriski@users.noreply.github.com>
Date: Wed, 1 Jan 2025 19:09:12 +0100
Subject: [PATCH] fix(stats): show all building even if empty and count per
type
---
.../insideCountPerBuilding.svelte | 59 ++++++++++++++++++-
src/lib/server/db/person.ts | 29 ++++++---
src/lib/types/person.ts | 10 ++++
3 files changed, 88 insertions(+), 10 deletions(-)
diff --git a/src/lib/components/custom/inside_counter/insideCountPerBuilding.svelte b/src/lib/components/custom/inside_counter/insideCountPerBuilding.svelte
index 2700860..422efc0 100644
--- a/src/lib/components/custom/inside_counter/insideCountPerBuilding.svelte
+++ b/src/lib/components/custom/inside_counter/insideCountPerBuilding.svelte
@@ -1,26 +1,79 @@
Building |
- People |
+ {#each allTypes as { type }}
+ {type} |
+ {/each}
- {#each data as { building, insideCount }}
+ {#each buildings as { building, types }}
{building} |
- {insideCount} |
+ {#each types as { insideCount }}
+ {insideCount} |
+ {/each}
{/each}
diff --git a/src/lib/server/db/person.ts b/src/lib/server/db/person.ts
index 26d0d45..175df54 100644
--- a/src/lib/server/db/person.ts
+++ b/src/lib/server/db/person.ts
@@ -7,7 +7,7 @@ import { isInside } from '../isInside';
import { DB as db } from './connect';
import { capitalizeString, sanitizeString } from '$lib/utils/sanitize';
import { building } from './schema/building';
-import type { PersonType } from '$lib/types/person';
+import { isPersonType, type PersonType } from '$lib/types/person';
// Gets all persons using optional filters
export async function getPersons(
@@ -178,6 +178,7 @@ export async function getPersons(
// Gets the count of all persons that are inside, per building
export async function getPersonsCountPerBuilding(): Promise<
{
+ type: PersonType | null;
building: string;
insideCount: number;
}[]
@@ -185,27 +186,41 @@ export async function getPersonsCountPerBuilding(): Promise<
try {
const personInsideSubquery = db
.select({
- personId: personEntry.personId,
+ personId: person.id,
+ type: person.type,
entryBuilding: personEntry.building,
maxEntryTimestamp: max(personEntry.timestamp),
maxExitTimestamp: max(personExit.timestamp)
})
- .from(personEntry)
- .leftJoin(personExit, eq(personEntry.personId, personExit.personId))
- .groupBy(personEntry.personId, personEntry.building)
+ .from(person)
+ .leftJoin(personEntry, eq(personEntry.personId, person.id))
+ .leftJoin(personExit, eq(personExit.personId, person.id))
+ .groupBy(person.id, person.type, personEntry.building)
.having(({ maxEntryTimestamp, maxExitTimestamp }) =>
or(isNull(maxExitTimestamp), gt(maxEntryTimestamp, maxExitTimestamp))
)
.as('person_inside');
- return await db
+ const persons = await db
.select({
+ type: personInsideSubquery.type,
building: building.name,
insideCount: count(personInsideSubquery.personId)
})
.from(building)
.leftJoin(personInsideSubquery, eq(building.name, personInsideSubquery.entryBuilding))
- .groupBy(building.name);
+ .groupBy(personInsideSubquery.type, building.name);
+
+ return persons.map((p) => {
+ if (p.type !== null && !isPersonType(p.type)) {
+ throw new Error('Invalid type from DB (not PersonType)');
+ }
+ return {
+ type: p.type,
+ building: p.building,
+ insideCount: p.insideCount
+ };
+ });
} catch (err: unknown) {
throw new Error(
`Failed to get inside count of persons from database: ${(err as Error).message}}`
diff --git a/src/lib/types/person.ts b/src/lib/types/person.ts
index 83d331f..3619032 100644
--- a/src/lib/types/person.ts
+++ b/src/lib/types/person.ts
@@ -4,6 +4,16 @@ export type PersonType = 'Student' | 'Employee';
export const Student: PersonType = 'Student';
export const Employee: PersonType = 'Employee';
+export function isPersonType(s: string): s is PersonType {
+ switch (s) {
+ case Student:
+ case Employee:
+ return true;
+ default:
+ return false;
+ }
+}
+
export type Person = {
id: number;
type: PersonType;