Fix login error feedback + load basecoat toast module

- inline error message on the login form (401 shows a visible French
  message, hidden again on submit)
- import basecoat-css/toast in BaseLayout: every showToast in the app
  was silently no-oping because the toast JS was never loaded
This commit is contained in:
2026-07-28 23:30:18 +02:00
parent c5378f6008
commit fd2d5408d6
3 changed files with 22 additions and 18 deletions
+14 -14
View File
@@ -27,6 +27,12 @@
required required
/> />
</div> </div>
<p
id="login-error"
class="hidden text-sm m-0"
style="color: var(--destructive)"
role="alert"
></p>
</form> </form>
</section> </section>
<footer class="flex-col gap-2"> <footer class="flex-col gap-2">
@@ -46,20 +52,18 @@
const submitBtn = document.getElementById( const submitBtn = document.getElementById(
"login-submit", "login-submit",
) as HTMLButtonElement; ) as HTMLButtonElement;
const toaster = document.getElementById("toaster") as ToasterElement; const errorEl = document.getElementById("login-error");
const showToast = ( const showError = (message: string) => {
category: "success" | "error", if (errorEl) {
title: string, errorEl.textContent = message;
description: string, errorEl.classList.remove("hidden");
) => {
if (toaster?.toast) {
toaster.toast({ category, title, description });
} }
}; };
form?.addEventListener("submit", async (e) => { form?.addEventListener("submit", async (e) => {
e.preventDefault(); e.preventDefault();
errorEl?.classList.add("hidden");
const formData = new FormData(form as HTMLFormElement); const formData = new FormData(form as HTMLFormElement);
const username = formData.get("username"); const username = formData.get("username");
@@ -80,16 +84,12 @@
window.location.href = "/"; window.location.href = "/";
} else { } else {
const data = await res.json(); const data = await res.json();
showToast( showError(data.error ?? "Email ou mot de passe incorrect");
"error",
"Erreur",
data.error ?? "Identifiants incorrects",
);
submitBtn.disabled = false; submitBtn.disabled = false;
submitBtn.innerHTML = originalText; submitBtn.innerHTML = originalText;
} }
} catch { } catch {
showToast("error", "Erreur", "Erreur réseau"); showError("Erreur réseau, veuillez réessayer.");
submitBtn.disabled = false; submitBtn.disabled = false;
submitBtn.innerHTML = originalText; submitBtn.innerHTML = originalText;
} }
+1
View File
@@ -68,6 +68,7 @@ if (themePreference === "Dark") {
import "basecoat-css/basecoat"; import "basecoat-css/basecoat";
import "basecoat-css/tabs"; import "basecoat-css/tabs";
import "basecoat-css/dropdown-menu"; import "basecoat-css/dropdown-menu";
import "basecoat-css/toast";
</script> </script>
<script is:inline> <script is:inline>
// Register the service worker so the browser offers "Install app" // Register the service worker so the browser offers "Install app"
+5 -2
View File
@@ -69,9 +69,12 @@ export const POST: APIRoute = async ({ request, cookies }) => {
}); });
} catch (err) { } catch (err) {
console.error("Login failed:", err); console.error("Login failed:", err);
return new Response(JSON.stringify({ error: "Invalid credentials" }), { return new Response(
JSON.stringify({ error: "Email ou mot de passe incorrect" }),
{
status: 401, status: 401,
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
}); },
);
} }
}; };