Improve code quality with the help of Biome

This commit is contained in:
SKBotNL committed 2026-06-01 00:31:27 +02:00
1 parent 12ba17d062
commit f0a41f4cf0
17 files changed
+125 -59

No files matched your search

+5
View File
@@ -1,5 +1,10 @@
{
"$schema": "https://biomejs.dev/schemas/2.4.16/schema.json",
"css": {
"parser": {
"tailwindDirectives": true
}
},
"linter": {
"enabled": true,
"rules": {
+3 -3
View File
@@ -1,7 +1,7 @@
import { ErrorBoundary, type JSX } from "solid-js";
import { t } from "../lib/i18n";
import { AppError } from "../types/api";
import Error from "./Error";
import ErrorComponent from "./ErrorComponent";
export default function AppErrorBoundaryComponent(props: {
children: JSX.Element;
@@ -10,7 +10,7 @@ export default function AppErrorBoundaryComponent(props: {
return (
<ErrorBoundary
fallback={(e, reset) => {
let text;
let text: string;
let canReset = true;
if (e instanceof TypeError) {
text = t("error.networkError");
@@ -26,7 +26,7 @@ export default function AppErrorBoundaryComponent(props: {
}
return (
<Error
<ErrorComponent
text={text}
fillScreen={true}
reset={canReset ? reset : undefined}
+6 -5
View File
@@ -107,24 +107,25 @@ function App(props: ParentProps) {
<Show when={user()}>
{(u) => (
<li class="dropdown dropdown-top dropdown-center w-full">
<div
<button
type="button"
tabindex="0"
role="button"
class="flex flex-row items-center gap-2 max-w-full"
>
<img
src={u()["picture"]}
alt="Picture"
alt={u().name}
class="w-6 h-6 rounded"
></img>
<span class="truncate max-w-xs">{u()["name"]}</span>
</div>
<span class="truncate max-w-xs">{u().name}</span>
</button>
<ul
tabindex="-1"
class="dropdown-content menu bg-base-100 rounded-box z-1 w-full p-2 shadow-sm"
>
<li>
<button
type="button"
onClick={() =>
(window.location.href = `${BASE_URL}/logout`)
}
@@ -23,12 +23,20 @@ export default function ErrorComponent({
<div class="flex flex-row gap-2">
<Show when={reset}>
{(reset) => (
<button onClick={() => reset()()} class="btn btn-soft mt-4">
<button
type="button"
onClick={() => reset()()}
class="btn btn-soft mt-4"
>
{t("panel.tryAgain")}
</button>
)}
</Show>
<button onClick={() => navigate(-1)} class="btn btn-soft mt-4">
<button
type="button"
onClick={() => navigate(-1)}
class="btn btn-soft mt-4"
>
{t("panel.goBack")}
</button>
</div>
+4 -1
View File
@@ -11,8 +11,11 @@ export default function RolePickerComponent({
}) {
return (
<>
<label class="label">{t("panel.users.role")}</label>
<label for="role" class="label">
{t("panel.users.role")}
</label>
<select
id="role"
value={role() ?? ""}
onChange={(e) => setRole(e.target.value as Role)}
class="select w-full"
+6 -3
View File
@@ -15,7 +15,7 @@ export default function TotpComponent({
const [fatalError, setFatalError] = createSignal<Error | null>(null);
async function submit() {
let redirectUrl;
let redirectUrl: string;
try {
redirectUrl = await loginApi.totp(code(), rememberMe(), loginChallenge);
} catch (err) {
@@ -30,7 +30,7 @@ export default function TotpComponent({
setError(err.message);
return;
}
window.location.href = redirectUrl!;
window.location.href = redirectUrl;
}
return (
@@ -47,8 +47,11 @@ export default function TotpComponent({
}}
>
<fieldset class="fieldset">
<label class="label">{t("totp.code")}</label>
<label for="code" class="label">
{t("totp.code")}
</label>
<input
id="code"
type="text"
class="input validator w-full"
placeholder={t("totp.code")}
+1
View File
@@ -64,6 +64,7 @@ export const dict = {
glitchtip: "Glitchtip",
roundcube: "Roundcube",
},
icon: "icon",
},
tryAgain: "Try again",
goBack: "Go back",
+2 -2
View File
@@ -28,8 +28,8 @@ export const consentApi = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
consent: consent,
consentChallenge: consentChallenge,
consent,
consentChallenge,
}),
});
+2 -2
View File
@@ -38,12 +38,12 @@ export const inviteApi = {
return await response.json();
},
create: async (userData: CreateInviteData): Promise<InviteData> => {
create: async (inviteData: CreateInviteData): Promise<InviteData> => {
const response = await fetch(`${BASE_URL}/invite`, {
method: "POST",
credentials: "include",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(userData),
body: JSON.stringify(inviteData),
});
if (!response.ok) {
+5 -5
View File
@@ -29,7 +29,7 @@ export const loginApi = {
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
...credentials,
loginChallenge: loginChallenge,
loginChallenge,
}),
});
@@ -44,7 +44,7 @@ export const loginApi = {
const response = await fetch(`${BASE_URL}/login/minecraftcheck`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ loginChallenge: loginChallenge }),
body: JSON.stringify({ loginChallenge }),
});
if (!response.ok)
@@ -67,9 +67,9 @@ export const loginApi = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
code: code,
rememberMe: rememberMe,
loginChallenge: loginChallenge,
code,
rememberMe,
loginChallenge,
}),
});
+4 -4
View File
@@ -28,7 +28,7 @@ export const setupApi = {
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
...details,
token: token,
token,
}),
});
@@ -43,7 +43,7 @@ export const setupApi = {
const response = await fetch(`${BASE_URL}/setup/minecraftcheck`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ token: token }),
body: JSON.stringify({ token }),
});
if (!response.ok)
@@ -58,7 +58,7 @@ export const setupApi = {
const response = await fetch(`${BASE_URL}/setup/totpsetup`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ token: token }),
body: JSON.stringify({ token }),
});
if (!response.ok)
@@ -73,7 +73,7 @@ export const setupApi = {
const response = await fetch(`${BASE_URL}/setup/totpverify`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ code: code, token: token }),
body: JSON.stringify({ code, token }),
});
if (!response.ok)
+6 -5
View File
@@ -26,7 +26,7 @@ export default function ConsentPage() {
async function consent(consent: boolean, consentChallenge: string) {
const redirectUrl = await consentApi.consent(consent, consentChallenge);
window.location.href = redirectUrl!;
window.location.href = redirectUrl;
}
return (
@@ -37,7 +37,7 @@ export default function ConsentPage() {
<div class="flex min-h-screen items-center justify-center">
<div class="card bg-base-200 border-2 border-base-300 w-full max-w-md shrink-0 shadow-2xl">
<div class="card-body">
<img src="/logo.webp"></img>
<img src="/logo.webp" alt="TrueOG"></img>
<div class="flex flex-col items-center gap-4">
<h1 class="text-2xl font-bold">{t("consent.title")}</h1>
@@ -50,15 +50,15 @@ export default function ConsentPage() {
<For each={consentData()?.scopes}>
{(scope) => (
<li>
{scopeMap.has(scope)
? scopeMap.get(scope)!()
: t("consent.scopes.default", { scope: scope })}
{scopeMap.get(scope)?.() ??
t("consent.scopes.default", { scope })}
</li>
)}
</For>
</ul>
<div class="w-full py-2 flex flex-col gap-2">
<button
type="button"
onClick={() =>
consent(true, params.consent_challenge as string)
}
@@ -67,6 +67,7 @@ export default function ConsentPage() {
{t("consent.allow")}
</button>
<button
type="button"
onClick={() =>
consent(false, params.consent_challenge as string)
}
+5 -1
View File
@@ -57,7 +57,11 @@ export default function HomePage() {
<a href={app.link} target="_blank" rel="noopener noreferrer">
<div class="card bg-base-200 hover:bg-base-300 transition-colors border-2 border-base-300 shadow-2xl">
<div class="card-body flex items-center justify-center">
<img class="w-44 h-44" src={app.icon}></img>
<img
class="w-44 h-44"
src={app.icon}
alt={`${app.name} ${t("panel.home.icon")}`}
></img>
<h2 class="card-title">{app.name}</h2>
</div>
</div>
+21 -9
View File
@@ -30,6 +30,7 @@ function InviteRow({ invite }: { invite: InviteData }) {
}
>
<button
type="button"
class="btn btn-ghost"
onClick={() => {
navigator.clipboard.writeText(link);
@@ -56,6 +57,7 @@ function InviteRow({ invite }: { invite: InviteData }) {
</td>
<th>
<button
type="button"
onClick={async () => {
setDeleting(true);
await inviteApi.delete(invite.id.toString());
@@ -101,7 +103,7 @@ export default function InvitesPage() {
const [userId, setUserId] = createSignal<string>();
const [fatalError, setFatalError] = createSignal<Error | null>(null);
let modalRef: HTMLDialogElement;
let modalRef!: HTMLDialogElement;
async function create() {
setError(null);
@@ -109,9 +111,9 @@ export default function InvitesPage() {
setUpdating(true);
try {
await inviteApi.create({
invitedUserId: userId()!,
invitedUserId: userId() as string,
});
modalRef!.close();
modalRef.close();
revalidate("invites");
} catch (err) {
if (!(err instanceof AppError)) {
@@ -134,7 +136,11 @@ export default function InvitesPage() {
<section class="p-8">
<div class="flex justify-between">
<h1 class="text-2xl font-bold mb-4">{t("panel.invites.title")}</h1>
<button onClick={() => modalRef!.showModal()} class="btn btn-soft">
<button
type="button"
onClick={() => modalRef.showModal()}
class="btn btn-soft"
>
<FiPlus class="text-lg" />
{t("panel.invites.createNew")}
</button>
@@ -157,18 +163,21 @@ export default function InvitesPage() {
<dialog
onTransitionEnd={(e) => {
if (e.propertyName === "opacity" && !modalRef!.open) {
if (e.propertyName === "opacity" && !modalRef.open) {
setUserId(undefined);
setError(null);
}
}}
ref={modalRef!}
ref={modalRef}
id="create_invite_modal"
class="modal"
>
<div class="modal-box">
<form method="dialog">
<button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">
<button
type="button"
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
>
<FiX class="text-lg" />
</button>
</form>
@@ -181,8 +190,11 @@ export default function InvitesPage() {
}}
>
<fieldset class="fieldset">
<label class="label">{t("panel.invites.user")}</label>
<label for="user" class="label">
{t("panel.invites.user")}
</label>
<select
id="user"
value={userId() ?? ""}
onChange={(e) => setUserId(e.target.value as string)}
class="select w-full"
@@ -207,7 +219,7 @@ export default function InvitesPage() {
</form>
</div>
<form method="dialog" class="modal-backdrop">
<button>Close</button>
<button type="button">Close</button>
</form>
</dialog>
</>
+2 -2
View File
@@ -23,14 +23,14 @@ export default function LoginPage() {
const data = loginData();
if (!data) return;
if (data.skip) {
window.location.href = data.redirectUri!;
window.location.href = data.redirectUri as string;
}
});
const stage = createMemo(() => {
const data = loginData();
if (!data || data.skip) return;
const stage = getStage(data.currentStage!);
const stage = getStage(data.currentStage as string);
if (stage instanceof AppError) throw stage;
return stage;
});
+19 -4
View File
@@ -145,7 +145,11 @@ function User() {
<div class="flex flex-col w-full xl:w-1/2">
<div class="flex flex-row items-center mb-4">
<button onClick={() => navigate(-1)} class="btn btn-ghost mr-2">
<button
type="button"
onClick={() => navigate(-1)}
class="btn btn-ghost mr-2"
>
<FiChevronLeft class="text-2xl" />
</button>
<img
@@ -163,8 +167,11 @@ function User() {
}}
>
<fieldset class="fieldset">
<label class="label">{t("panel.users.email")}</label>
<label for="email" class="label">
{t("panel.users.email")}
</label>
<input
id="email"
type="text"
class="input w-full"
placeholder={t("panel.users.email")}
@@ -173,8 +180,11 @@ function User() {
required
/>
<label class="label">{t("panel.users.minecraftUuid")}</label>
<label for="minecraftUuid" class="label">
{t("panel.users.minecraftUuid")}
</label>
<input
id="minecraftUuid"
type="text"
class="input validator w-full"
placeholder={t("panel.users.minecraftUuid")}
@@ -199,8 +209,11 @@ function User() {
<RolePicker role={role} setRole={setRole} />
</div>
<label class="label">{t("panel.users.setUp")}</label>
<label for="setUp" class="label">
{t("panel.users.setUp")}
</label>
<input
id="setUp"
type="text"
class="input w-full"
placeholder={t("panel.users.setUp")}
@@ -232,6 +245,7 @@ function User() {
}
>
<button
type="button"
onClick={() => {
const deactivated = user()?.deactivated;
if (deactivated === undefined) return;
@@ -257,6 +271,7 @@ function User() {
}
>
<button
type="button"
onClick={deleteUser}
class="btn btn-error w-full"
disabled={
+24 -11
View File
@@ -72,7 +72,7 @@ export default function UsersPage() {
const [role, setRole] = createSignal<Role>();
const [fatalError, setFatalError] = createSignal<Error | null>(null);
let modalRef: HTMLDialogElement;
let modalRef!: HTMLDialogElement;
async function create() {
setError(null);
@@ -81,10 +81,10 @@ export default function UsersPage() {
try {
await userApi.create({
email: email(),
role: role()!,
minecraftUuid: minecraftUuid()!,
role: role() as Role,
minecraftUuid: minecraftUuid(),
});
modalRef!.close();
modalRef.close();
revalidate("users");
} catch (err) {
if (!(err instanceof AppError)) {
@@ -109,7 +109,11 @@ export default function UsersPage() {
<section class="p-8">
<div class="flex justify-between">
<h1 class="text-2xl font-bold mb-4">{t("panel.users.title")}</h1>
<button onClick={() => modalRef!.showModal()} class="btn btn-soft">
<button
type="button"
onClick={() => modalRef.showModal()}
class="btn btn-soft"
>
<FiPlus class="text-lg" />
{t("panel.users.createNew")}
</button>
@@ -130,20 +134,23 @@ export default function UsersPage() {
<dialog
onTransitionEnd={(e) => {
if (e.propertyName === "opacity" && !modalRef!.open) {
if (e.propertyName === "opacity" && !modalRef.open) {
setEmail("");
setMinecraftUuid("");
setRole();
setError(null);
}
}}
ref={modalRef!}
ref={modalRef}
id="create_user_modal"
class="modal"
>
<div class="modal-box">
<form method="dialog">
<button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">
<button
type="button"
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
>
<FiX class="text-lg" />
</button>
</form>
@@ -156,8 +163,11 @@ export default function UsersPage() {
}}
>
<fieldset class="fieldset">
<label class="label">{t("panel.users.email")}</label>
<label for="email" class="label">
{t("panel.users.email")}
</label>
<input
id="email"
type="text"
class="input w-full"
placeholder={t("panel.users.email")}
@@ -166,8 +176,11 @@ export default function UsersPage() {
required
/>
<label class="label">{t("panel.users.minecraftUuid")}</label>
<label for="minecraftUuid" class="label">
{t("panel.users.minecraftUuid")}
</label>
<input
id="minecraftUuid"
type="text"
class="input validator w-full"
placeholder={t("panel.users.minecraftUuid")}
@@ -196,7 +209,7 @@ export default function UsersPage() {
</form>
</div>
<form method="dialog" class="modal-backdrop">
<button>Close</button>
<button type="button">Close</button>
</form>
</dialog>
</>