|
@@ -1,8 +1,156 @@
|
|
|
|
|
+<script>
|
|
|
|
|
+ import {onMount} from 'svelte';
|
|
|
|
|
+ import {auth} from '../store.js';
|
|
|
|
|
+
|
|
|
|
|
+ let isAuthenticated = false;
|
|
|
|
|
+ let isLoading = true;
|
|
|
|
|
+ let user = null;
|
|
|
|
|
+
|
|
|
|
|
+ $: auth.subscribe(value => {
|
|
|
|
|
+ isAuthenticated = !!value;
|
|
|
|
|
+ if (value) {
|
|
|
|
|
+ user = value;
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ onMount(() => {
|
|
|
|
|
+ const storedAuth = localStorage.getItem('auth');
|
|
|
|
|
+ if (storedAuth) {
|
|
|
|
|
+ auth.set(JSON.parse(storedAuth));
|
|
|
|
|
+ }
|
|
|
|
|
+ isLoading = false;
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ async function submit(event) {
|
|
|
|
|
+ event.preventDefault();
|
|
|
|
|
+
|
|
|
|
|
+ const formData = new FormData(event.target);
|
|
|
|
|
+ const username = formData.get("username");
|
|
|
|
|
+ const password = formData.get("password");
|
|
|
|
|
+
|
|
|
|
|
+ if (!username || !password) {
|
|
|
|
|
+ alert("Please enter both username and password.");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const data = {
|
|
|
|
|
+ username: username,
|
|
|
|
|
+ password: password
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ const response = await fetch(import.meta.env.VITE_AUTH_HOST + '/api/authenticate', {
|
|
|
|
|
+ method: 'POST',
|
|
|
|
|
+ headers: {
|
|
|
|
|
+ 'Content-Type': 'application/json',
|
|
|
|
|
+ },
|
|
|
|
|
+ body: JSON.stringify(data),
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ if (response.ok) {
|
|
|
|
|
+ const result = await response.json();
|
|
|
|
|
+ auth.set(result);
|
|
|
|
|
+ localStorage.setItem('auth', JSON.stringify(result));
|
|
|
|
|
+ } else {
|
|
|
|
|
+ const error = await response.json();
|
|
|
|
|
+ console.error('Login failed:', error);
|
|
|
|
|
+ alert('Login failed: ' + error.message);
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (err) {
|
|
|
|
|
+ console.error('Error during login:', err);
|
|
|
|
|
+ alert('An error occurred. Please try again.');
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function logout() {
|
|
|
|
|
+ auth.set(null);
|
|
|
|
|
+ localStorage.removeItem('auth');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
<svelte:head>
|
|
<svelte:head>
|
|
|
- <title>Login</title>
|
|
|
|
|
- <meta name="description" content="Login page" />
|
|
|
|
|
|
|
+ <title>Login</title>
|
|
|
|
|
+ <meta name="description" content="Login page"/>
|
|
|
</svelte:head>
|
|
</svelte:head>
|
|
|
|
|
|
|
|
<div class="text-column">
|
|
<div class="text-column">
|
|
|
- <h1>Login</h1>
|
|
|
|
|
|
|
+ {#if isLoading}
|
|
|
|
|
+ <p>Loading...</p>
|
|
|
|
|
+ {:else}
|
|
|
|
|
+ {#if !isAuthenticated}
|
|
|
|
|
+ <div class="card">
|
|
|
|
|
+ <form on:submit={submit}>
|
|
|
|
|
+ <input type="text" name="username" placeholder="username" class="input-field"/>
|
|
|
|
|
+ <input type="password" name="password" placeholder="password" class="input-field"/>
|
|
|
|
|
+ <button type="submit" class="login-button">Login</button>
|
|
|
|
|
+ <button type="button" class="register-button">Register</button>
|
|
|
|
|
+ </form>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ {:else}
|
|
|
|
|
+ <p>You are logged in as {user.username}!</p>
|
|
|
|
|
+ <button class="logout-button" on:click={logout}>Logout</button>
|
|
|
|
|
+ {/if}
|
|
|
|
|
+ {/if}
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+
|
|
|
|
|
+<style>
|
|
|
|
|
+ .text-column {
|
|
|
|
|
+ text-align: center; /* Center align text */
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .card {
|
|
|
|
|
+ background-color: #ffffff; /* White background for the card */
|
|
|
|
|
+ border-radius: 12px; /* Rounded corners */
|
|
|
|
|
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); /* Subtle shadow for depth */
|
|
|
|
|
+ padding: 20px; /* Padding inside the card */
|
|
|
|
|
+ width: 300px; /* Fixed width for the card */
|
|
|
|
|
+ transition: transform 0.3s; /* Transition for hover effect */
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .card:hover {
|
|
|
|
|
+ transform: translateY(-5px); /* Slight lift effect on hover */
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .input-field {
|
|
|
|
|
+ width: 90%; /* Full width for inputs */
|
|
|
|
|
+ padding: 12px; /* Padding for input fields */
|
|
|
|
|
+ margin: 10px 0; /* Margin between input fields */
|
|
|
|
|
+ border: 1px solid #ccc; /* Light border */
|
|
|
|
|
+ border-radius: 6px; /* Rounded corners for input fields */
|
|
|
|
|
+ font-size: 16px; /* Font size for input text */
|
|
|
|
|
+ outline: none; /* Remove outline on focus */
|
|
|
|
|
+ transition: border-color 0.3s; /* Transition for border color */
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .input-field:focus {
|
|
|
|
|
+ border-color: #007bff; /* Change border color on focus */
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ button {
|
|
|
|
|
+ width: 100%; /* Full width for the button */
|
|
|
|
|
+ margin: 5px 0;
|
|
|
|
|
+ padding: 12px; /* Padding for the button */
|
|
|
|
|
+ background-color: #007bff; /* Button color */
|
|
|
|
|
+ color: white; /* White text color */
|
|
|
|
|
+ border: none; /* No border */
|
|
|
|
|
+ border-radius: 6px; /* Rounded corners for button */
|
|
|
|
|
+ font-size: 16px; /* Font size for button text */
|
|
|
|
|
+ cursor: pointer; /* Change cursor to pointer */
|
|
|
|
|
+ transition: background-color 0.3s; /* Transition for button color */
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .login-button {
|
|
|
|
|
+ background-color: #007bff; /* Button color */
|
|
|
|
|
+ color: white; /* White text color */
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .register-button {
|
|
|
|
|
+ background-color: #20bf6b; /* Button color */
|
|
|
|
|
+ color: white; /* White text color */
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .login-button:hover {
|
|
|
|
|
+ background-color: #0056b3; /* Darker button color on hover */
|
|
|
|
|
+ }
|
|
|
|
|
+</style>
|