From bf8b1d0d49703e82cf8162399405984bd0b3fe88 Mon Sep 17 00:00:00 2001
From: zwlucas <lucas.fariamo08@gmail.com>
Date: Fri, 29 May 2026 18:24:59 -0300
Subject: feat: implement static file serving and Docker support, update
 frontend build process

Signed-off-by: zwlucas <lucas.fariamo08@gmail.com>
---
 frontend/src/routes/login/+page.svelte | 61 ++++++++++++++++++++++++++++++----
 1 file changed, 55 insertions(+), 6 deletions(-)

(limited to 'frontend/src/routes/login/+page.svelte')

diff --git a/frontend/src/routes/login/+page.svelte b/frontend/src/routes/login/+page.svelte
index a472c89..2b12a75 100644
--- a/frontend/src/routes/login/+page.svelte
+++ b/frontend/src/routes/login/+page.svelte
@@ -1,5 +1,53 @@
 <script lang="ts">
-	let { form }: { form?: { error?: string } } = $props();
+	import { onMount } from 'svelte';
+	import { goto } from '$app/navigation';
+
+	let errorMsg = $state('');
+	let loading = $state(false);
+
+	async function handleSubmit(e: Event) {
+		e.preventDefault();
+		loading = true;
+		errorMsg = '';
+		const formData = new FormData(e.target as HTMLFormElement);
+		try {
+			const res = await fetch('/api/auth/login', {
+				method: 'POST',
+				headers: { 'Content-Type': 'application/json' },
+				body: JSON.stringify({
+					username: formData.get('username'),
+					password: formData.get('password')
+				})
+			});
+			if (!res.ok) {
+				const err = await res.json().catch(() => ({}));
+				errorMsg = err.error || 'Credenciais inválidas';
+				return;
+			}
+			const { token } = await res.json();
+			document.cookie = `auth_token=${token}; path=/; max-age=${7 * 24 * 60 * 60}; SameSite=Lax`;
+			goto('/admin');
+		} catch {
+			errorMsg = 'Erro de conexão com o servidor';
+		} finally {
+			loading = false;
+		}
+	}
+
+	onMount(async () => {
+		const hasToken = document.cookie.split(';').some(c => c.trim().startsWith('auth_token='));
+		if (!hasToken) return;
+		try {
+			const res = await fetch('/api/auth/verify', {
+				headers: { Authorization: `Bearer ${getCookie('auth_token')}` }
+			});
+			if (res.ok) goto('/admin');
+		} catch { /* ignore */ }
+	});
+
+	function getCookie(name: string) {
+		return document.cookie.split('; ').find(r => r.startsWith(name + '='))?.split('=')[1] ?? '';
+	}
 </script>
 
 <svelte:head>
@@ -14,7 +62,7 @@
 		</div>
 
 		<div class="rounded-2xl border border-[var(--border-color)] bg-[var(--bg-card)] p-6">
-			<form method="POST" class="space-y-4">
+			<form onsubmit={handleSubmit} class="space-y-4">
 				<div>
 					<label for="username" class="mb-1.5 block text-xs font-medium text-[var(--text-secondary)]">Usuário</label>
 					<input
@@ -41,15 +89,16 @@
 					/>
 				</div>
 
-				{#if form?.error}
-					<p class="rounded-lg bg-[var(--red)]/5 px-3 py-2 text-xs text-[var(--red)]">{form.error}</p>
+				{#if errorMsg}
+					<p class="rounded-lg bg-[var(--red)]/5 px-3 py-2 text-xs text-[var(--red)]">{errorMsg}</p>
 				{/if}
 
 				<button
 					type="submit"
-					class="w-full rounded-xl border border-[var(--green)]/50 bg-[var(--green)]/10 px-4 py-2.5 text-sm font-medium text-[var(--green)] transition-all hover:bg-[var(--green)]/20"
+					disabled={loading}
+					class="w-full rounded-xl border border-[var(--green)]/50 bg-[var(--green)]/10 px-4 py-2.5 text-sm font-medium text-[var(--green)] transition-all hover:bg-[var(--green)]/20 disabled:opacity-50"
 				>
-					Entrar
+					{loading ? 'Entrando…' : 'Entrar'}
 				</button>
 			</form>
 		</div>
-- 
cgit v1.2.3

