Compare commits
4
Commits
fa7fe83866
...
fdbc7a2b23
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fdbc7a2b23 | ||
|
|
524e9fab7e | ||
|
|
6e06161939 | ||
|
|
a87cc4018c |
@@ -0,0 +1 @@
|
|||||||
|
API_BASE=http://your-server-ip-or-domain:8000
|
||||||
+60
-3
@@ -1,10 +1,67 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { onMounted } from 'vue'
|
||||||
|
import { useState, useRuntimeConfig } from '#imports'
|
||||||
|
|
||||||
|
// Using Nuxt's useState composable instead of Vue's ref
|
||||||
|
const config = useRuntimeConfig()
|
||||||
|
const apiBase = config.public.apiBase
|
||||||
|
|
||||||
|
const user = useState('user', () => ({}))
|
||||||
|
const isLoggedIn = useState('isLoggedIn', () => false)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// Checking if code is running in browser environment before accessing localStorage
|
||||||
|
if (process.client) {
|
||||||
|
try {
|
||||||
|
const userData = JSON.parse(localStorage.getItem('user') || '{}')
|
||||||
|
user.value = userData
|
||||||
|
if (Object.keys(userData).length > 0) {
|
||||||
|
isLoggedIn.value = true
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error accessing localStorage:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const logout = () => {
|
||||||
|
if (process.client) {
|
||||||
|
try {
|
||||||
|
localStorage.removeItem('user')
|
||||||
|
isLoggedIn.value = false
|
||||||
|
user.value = {}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error during logout:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<header class="p-4 shadow-md flex justify-between bg-slate-100">
|
<header class="p-4 shadow-md flex justify-between bg-slate-100">
|
||||||
<h1><NuxtLink to="/">Eurovision 2025</NuxtLink></h1>
|
<h1><NuxtLink to="/">Eurovision 2025</NuxtLink></h1>
|
||||||
<nav>
|
<nav>
|
||||||
<ul class="flex gap-4">
|
<ul class="flex items-center gap-4">
|
||||||
<li><NuxtLink to="/profile">Profile</NuxtLink></li>
|
<li v-if="isLoggedIn" class="flex items-center gap-2">
|
||||||
<li><NuxtLink to="/login">Login</NuxtLink></li>
|
<NuxtLink to="/profile">
|
||||||
|
<NuxtImg
|
||||||
|
v-if="'avatar_id' in user"
|
||||||
|
:src="`${apiBase}/static/avatars/${user.avatar_id}.webp`"
|
||||||
|
class="w-4 h-4 rounded-full object-cover"
|
||||||
|
:alt="user.username"
|
||||||
|
/></NuxtLink>
|
||||||
|
</li>
|
||||||
|
<li v-if="!isLoggedIn">
|
||||||
|
<NuxtLink to="/login" class="flex items-center gap-1">
|
||||||
|
<Icon name="qlementine-icons:log-in-16" class="w-5 h-5" />
|
||||||
|
</NuxtLink>
|
||||||
|
</li>
|
||||||
|
<li v-if="isLoggedIn">
|
||||||
|
<button @click="logout" class="flex items-center gap-1">
|
||||||
|
<Icon name="qlementine-icons:log-out-16" class="w-5 h-5" />
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@ import tailwindcss from "@tailwindcss/vite";
|
|||||||
|
|
||||||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
compatibilityDate: '2024-11-01',
|
compatibilityDate: '2025-05-10',
|
||||||
devtools: { enabled: true },
|
devtools: { enabled: true },
|
||||||
|
|
||||||
modules: [
|
modules: [
|
||||||
|
|||||||
+32
-2
@@ -3,9 +3,36 @@ definePageMeta({
|
|||||||
layout: 'login'
|
layout: 'login'
|
||||||
})
|
})
|
||||||
|
|
||||||
const login = () => {
|
const errorMessage = ref('')
|
||||||
console.log('login')
|
|
||||||
|
const login = async () => {
|
||||||
|
// Clear any previous error messages
|
||||||
|
errorMessage.value = ''
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
username: document.getElementById('username')?.value,
|
||||||
|
password: document.getElementById('password')?.value
|
||||||
|
}
|
||||||
|
const config = useRuntimeConfig()
|
||||||
|
const apiBase = config.public.apiBase
|
||||||
|
const api_url = `${apiBase}/auth/token`
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { data: user } = await useFetch(api_url, {
|
||||||
|
method: 'POST',
|
||||||
|
body: payload
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!user.value) {
|
||||||
|
errorMessage.value = 'Kirjautuminen epäonnistui. Tarkista käyttäjätunnus ja salasana.'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
localStorage.setItem('user', JSON.stringify(user.value))
|
||||||
navigateTo('/')
|
navigateTo('/')
|
||||||
|
} catch (error) {
|
||||||
|
errorMessage.value = 'Kirjautuminen epäonnistui. Palvelimeen ei saada yhteyttä.'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -14,6 +41,9 @@ const login = () => {
|
|||||||
<div class="flex flex-col gap-4 m-6 bg-slate-300 rounded-2xl p-6 shadow-md text-sm">
|
<div class="flex flex-col gap-4 m-6 bg-slate-300 rounded-2xl p-6 shadow-md text-sm">
|
||||||
<h1 class="text-center font-bold text-lg">Kirjaudu</h1>
|
<h1 class="text-center font-bold text-lg">Kirjaudu</h1>
|
||||||
<form @submit.prevent="login" class="">
|
<form @submit.prevent="login" class="">
|
||||||
|
<div v-if="errorMessage" class="error-message p-2 my-2 bg-red-100 text-red-700 rounded border border-red-300">
|
||||||
|
{{ errorMessage }}
|
||||||
|
</div>
|
||||||
<label>Käyttäjätunnus
|
<label>Käyttäjätunnus
|
||||||
<input class="textfield" type="text" id="username" placeholder="Käyttäjätunnus" />
|
<input class="textfield" type="text" id="username" placeholder="Käyttäjätunnus" />
|
||||||
</label>
|
</label>
|
||||||
|
|||||||
Reference in New Issue
Block a user