additional door states

This commit is contained in:
kritzl 2026-05-11 11:49:10 +02:00
commit 7935c54a60
Signed by: kritzl
SSH key fingerprint: SHA256:5BmINP9VjZWaUk5Z+2CTut1KFhwLtd0ZynMekKbtViM
3 changed files with 75 additions and 32 deletions

View file

@ -10,13 +10,16 @@ const t = useTranslations(lang)
<div <div
class:list={[ class:list={[
"card flex flex-col w-full group ring", "card flex flex-col w-full group ring",
"data-[state=open]:ring-success data-[state=open]:bg-success/5", "data-[state=unlocked]:ring-success data-[state=unlocked]:bg-success/5",
"data-[state=closed]:ring-error data-[state=closed]:bg-error/5", "data-[state=locked]:ring-error data-[state=locked]:bg-error/5",
"data-[state=unknown]:ring-warning data-[state=unknown]:bg-warning/5", "data-[state=unknown]:ring-warning data-[state=unknown]:bg-warning/5",
"data-[state=moving]:ring-info data-[state=moving]:bg-info/5", "data-[state=unlocking]:ring-info data-[state=unlocking]:bg-info/5",
"data-[state=locking]:ring-info data-[state=locking]:bg-info/5",
]} ]}
data-state data-state
data-battery data-battery
data-unreachable
data-jammed
data-active data-active
data-id data-id
> >
@ -24,10 +27,20 @@ const t = useTranslations(lang)
<div class="flex max-md:flex-wrap items-center gap-2"> <div class="flex max-md:flex-wrap items-center gap-2">
<div class="w-full flex justify-between"> <div class="w-full flex justify-between">
<h2 class="text-xl font-bold" data-label></h2> <h2 class="text-xl font-bold" data-label></h2>
<span class="badge badge-error hidden ms-auto group-data-battery:flex whitespace-nowrap"> <div class="ms-auto flex flex-wrap justify-end gap-1">
<TriangleAlert class="size-4"/> <span class="badge badge-error hidden group-data-battery:flex whitespace-nowrap">
{t("batteryLow")} <TriangleAlert class="size-4"/>
</span> {t("lock.batteryLow")}
</span>
<span class="badge badge-error hidden group-data-unreachable:flex whitespace-nowrap">
<TriangleAlert class="size-4"/>
{t("lock.unreachable")}
</span>
<span class="badge badge-error hidden group-data-jammed:flex whitespace-nowrap">
<TriangleAlert class="size-4"/>
{t("lock.jammed")}
</span>
</div>
</div> </div>
</div> </div>
<div class="hidden group-data-active:grid grid-cols-2 w-full items-center gap-2 mt-4"> <div class="hidden group-data-active:grid grid-cols-2 w-full items-center gap-2 mt-4">
@ -40,21 +53,25 @@ const t = useTranslations(lang)
</div> </div>
</div> </div>
<div> <div>
<span class="w-full rounded-t-none badge badge-lg badge-success hidden group-data-[state=open]:flex"> <span class="w-full rounded-t-none badge badge-lg badge-success hidden group-data-[state=unlocked]:flex">
<LockOpen class="size-4"/> <LockOpen class="size-4"/>
{t("state.open")} {t("state.unlocked")}
</span> </span>
<span class="w-full rounded-t-none badge badge-lg badge-error hidden group-data-[state=closed]:flex"> <span class="w-full rounded-t-none badge badge-lg badge-error hidden group-data-[state=locked]:flex">
<Lock class="size-4"/> <Lock class="size-4"/>
{t("state.closed")} {t("state.locked")}
</span> </span>
<span class="w-full rounded-t-none badge badge-lg badge-warning hidden group-data-[state=unknown]:flex"> <span class="w-full rounded-t-none badge badge-lg badge-warning hidden group-data-[state=unknown]:flex">
<CircleQuestionMark class="size-4"/> <CircleQuestionMark class="size-4"/>
{t("state.unknown")} {t("state.unknown")}
</span> </span>
<span class="w-full rounded-t-none badge badge-lg badge-info hidden group-data-[state=moving]:flex"> <span class="w-full rounded-t-none badge badge-lg badge-info hidden group-data-[state=unlocking]:flex">
<span class="loading loading-spinner loading-xs"></span> <span class="loading loading-spinner loading-xs"></span>
{t("state.moving")} {t("state.unlocking")}
</span>
<span class="w-full rounded-t-none badge badge-lg badge-info hidden group-data-[state=locking]:flex">
<span class="loading loading-spinner loading-xs"></span>
{t("state.locking")}
</span> </span>
</div> </div>
</div> </div>

View file

@ -13,11 +13,14 @@ export const ui = {
"unauthenticated.title": "Unauthenticated", "unauthenticated.title": "Unauthenticated",
"unauthenticated.description": `To use the locks you have to log in with your CCCHH ID and have the "intern@" status.<br> "unauthenticated.description": `To use the locks you have to log in with your CCCHH ID and have the "intern@" status.<br>
More infos: <a class='underline' href='https://wiki.hamburg.ccc.de/club:prozesse:aufnahmeprozesse-fuer-berechtigungsgruppen'>CCCHH Wiki</a>`, More infos: <a class='underline' href='https://wiki.hamburg.ccc.de/club:prozesse:aufnahmeprozesse-fuer-berechtigungsgruppen'>CCCHH Wiki</a>`,
"state.open": "Open", "state.unlocked": "Open",
"state.closed": "Closed", "state.locked": "Closed",
"state.unknown": "Unknown", "state.unknown": "Unknown",
"state.moving": "Moving", "state.unlocking": "Unlocking",
"batteryLow": "Battery low", "state.locking": "Locking",
"lock.batteryLow": "Battery low",
"lock.unreachable": "Unreachable",
"lock.jammed": "Lock jammed",
"button.open": "Open", "button.open": "Open",
"button.close": "Close", "button.close": "Close",
"login": "Login", "login": "Login",
@ -29,11 +32,14 @@ export const ui = {
"unauthenticated.title": "Nicht angemeldet", "unauthenticated.title": "Nicht angemeldet",
"unauthenticated.description": `Um die Schlösser bedienen zu können, musst du dich mit deiner CCCHH ID anmelden und den "intern@" Status haben.<br> "unauthenticated.description": `Um die Schlösser bedienen zu können, musst du dich mit deiner CCCHH ID anmelden und den "intern@" Status haben.<br>
Weitere Infos: <a class='underline' href='https://wiki.hamburg.ccc.de/club:prozesse:aufnahmeprozesse-fuer-berechtigungsgruppen'>CCCHH Wiki</a>`, Weitere Infos: <a class='underline' href='https://wiki.hamburg.ccc.de/club:prozesse:aufnahmeprozesse-fuer-berechtigungsgruppen'>CCCHH Wiki</a>`,
"state.open": "Offen", "state.unlocked": "Offen",
"state.closed": "Geschlossen", "state.locked": "Geschlossen",
"state.unknown": "Unbekannt", "state.unknown": "Unbekannt",
"state.moving": "In Bewegung", "state.unlocking": "Öffnet",
"batteryLow": "Batterie fast leer", "state.locking": "Schließt",
"lock.batteryLow": "Batterie fast leer",
"lock.unreachable": "Nicht erreichbar",
"lock.jammed": "Schloss blockiert",
"button.open": "Öffnen", "button.open": "Öffnen",
"button.close": "Schließen", "button.close": "Schließen",
"login": "Anmelden", "login": "Anmelden",

View file

@ -59,8 +59,10 @@ const t = useTranslations(lang)
type DoorType = { type DoorType = {
id: string; id: string;
label: string; label: string;
state: "open" | "closed" | "unknown" | "moving"; state: "unlocked" | "locked" | "unknown" | "unlocking" | "locking";
batteryLow: boolean; batteryLow: boolean;
unreachable: boolean;
jammed: boolean;
} }
type AuthType = { type AuthType = {
username: string; username: string;
@ -79,14 +81,18 @@ const t = useTranslations(lang)
{ {
id: "abcdef", id: "abcdef",
label: "Hauptraum", label: "Hauptraum",
state: "open", state: "unlocked",
batteryLow: false, batteryLow: false,
unreachable: false,
jammed: false,
}, },
{ {
id: "12345", id: "12345",
label: "Werkstatt", label: "Werkstatt",
state: "closed", state: "locked",
batteryLow: true, batteryLow: true,
unreachable: false,
jammed: false,
}, },
] ]
@ -94,12 +100,10 @@ const t = useTranslations(lang)
const getUserInfo = fetcher.path("/api/user-info/").method("get").create() const getUserInfo = fetcher.path("/api/user-info/").method("get").create()
try { try {
const {status, data: userInfo} = await getUserInfo({ const {status, data: userInfo} = await getUserInfo({})
status: ["available", "pending"],
})
auth.authenticated = userInfo.is_logged_in auth.authenticated = userInfo.is_logged_in
auth.authorized = false auth.authorized = true
auth.until = userInfo.guaranteed_session_until ? new Date(userInfo.guaranteed_session_until) : null auth.until = userInfo.guaranteed_session_until ? new Date(userInfo.guaranteed_session_until) : null
auth.username = userInfo.user_info?.username ?? '' auth.username = userInfo.user_info?.username ?? ''
} catch (e) { } catch (e) {
@ -140,10 +144,22 @@ const t = useTranslations(lang)
delete doorElement.dataset.battery delete doorElement.dataset.battery
} }
if (door.unreachable) {
doorElement.dataset.unreachable = ""
} else {
delete doorElement.dataset.unreachable
}
if (door.jammed) {
doorElement.dataset.jammed = ""
} else {
delete doorElement.dataset.jammed
}
labelElement.innerHTML = door.label labelElement.innerHTML = door.label
buttonElements.forEach(button => { buttonElements.forEach(button => {
button.disabled = door.state === "moving" button.disabled = ["unlocking", "locking"].includes(door.state)
}) })
} }
@ -184,13 +200,17 @@ const t = useTranslations(lang)
id: "abcdef", id: "abcdef",
label: "Hauptraum", label: "Hauptraum",
state: "unknown", state: "unknown",
batteryLow: false, batteryLow: true,
unreachable: false,
jammed: true,
} }
doors[1] = { doors[1] = {
id: "12345", id: "12345",
label: "Werkstatt", label: "Werkstatt",
state: "moving", state: "unlocking",
batteryLow: true, batteryLow: false,
unreachable: true,
jammed: false,
} }
refresh() refresh()
}, 2000) }, 2000)