Commit e6e9197f authored by Patrick Ade's avatar Patrick Ade
Browse files

Implement authentication store using Pinia; create auth store with login,...

Implement authentication store using Pinia; create auth store with login, logout, and user fetching functionalities.

Update main entry point to reflect new store structure; change import path for auth store.

Add TypeScript support for Vue components; create shims-vue.d.ts for .vue file declarations.

Create Login and Register views with authentication logic; implement user login and registration forms with error handling.

Refactor HomeView to utilize authentication store; display user information and logout functionality based on authentication state.
parent 71123f58
Showing with 174 additions and 19 deletions
+174 -19
...@@ -2,11 +2,11 @@ import { ref, computed } from 'vue' ...@@ -2,11 +2,11 @@ import { ref, computed } from 'vue'
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => { export const useCounterStore = defineStore('counter', () => {
const count = ref(0) const count = ref(0)
const doubleCount = computed(() => count.value * 2) const doubleCount = computed(() => count.value * 2)
function increment() { function increment() {
count.value++ count.value++
} }
return { count, doubleCount, increment } return { count, doubleCount, increment }
}) })
<template> <template>
<div class="about"> <div class="about">
<h1>This is an about page</h1> <h1>This is an about page</h1>
</div> </div>
</template> </template>
<style> <style>
@media (min-width: 1024px) { @media (min-width: 1024px) {
.about { .about {
min-height: 100vh; min-height: 100vh;
display: flex; display: flex;
align-items: center; align-items: center;
} }
} }
</style> </style>
<script setup lang="ts"> <script lang="ts">
import TheWelcome from '../components/TheWelcome.vue' import { useAuthStore } from '../stores/auth'
import { useRouter } from 'vue-router'
export default {
setup() {
const authStore = useAuthStore()
const router = useRouter()
return {
authStore,
router,
}
},
methods: {
async logout() {
try {
await this.authStore.logout(this.$router)
} catch (error) {
console.error(error)
}
},
},
async mounted() {
await this.authStore.fetchUser()
},
}
</script> </script>
<template> <template>
<main> <h1>Welcome to the home page</h1>
<TheWelcome /> <div v-if="authStore.isAuthenticated">
</main> <p>Hi there {{ authStore.user?.username }}!</p>
<p>You are logged in .</p>
<button @click="logout">Logout</button>
</div>
<p v-else>You are not logged in . <router-link to="/login"> Login </router-link></p>
</template> </template>
<script setup lang="ts">
import TheWelcome from '../components/TheWelcome.vue'
</script>
<template>
<main>
<TheWelcome />
</main>
</template>
<script lang="ts">
import { useAuthStore } from '../stores/auth'
export default {
setup() {
const authStore = useAuthStore()
return {
authStore,
}
},
data() {
return {
email: '',
password: '',
error: '',
}
},
methods: {
async login() {
await this.authStore.login(this.email, this.password, this.$router)
if (!this.authStore.isAuthenticated) {
this.error = 'Login failed. Please check your credentials.'
}
},
resetError() {
this.error = ''
},
},
}
</script>
<template>
<div class="login">
<h1>Login</h1>
<form @submit.prevent="login">
<div>
<label for="email"> Email: </label>
<input v-model="email" id="email" type="text" required @input="resetError" />
</div>
<div>
<label for="password"> Password: </label>
<input
v-model="password"
id="password"
type="password"
required
@input="resetError"
/>
</div>
<button type="submit">Login</button>
</form>
<p v-if="error" class="error">{{ error }}</p>
</div>
<p v-if="error" class="error">{{ error }}</p>
</template>
<script lang="ts">
import { getCSRFToken } from '../stores/auth'
export default {
data() {
return {
email: '',
password: '',
error: '',
success: '',
}
},
methods: {
async register() {
try {
const response = await fetch('http://localhost:8000/api/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCSRFToken(),
},
body: JSON.stringify({
email: this.email,
password: this.password,
}),
credentials: 'include',
})
const data = await response.json()
if (response.ok) {
this.success = 'Registration successful! Please log in.'
setTimeout(() => {
this.$router.push('/login')
}, 1000)
} else {
this.error = data.error || 'Registration failed'
}
} catch (err) {
this.error = 'An error occurred during registration: ' + err
}
},
},
}
</script>
<template>
<div>
<h2>Register</h2>
<form @submit.prevent="register">
<div>
<label for="email"> Email: </label>
<input v-model="email" id="email" type="email" required />
</div>
<div>
<label for="password"> Password: </label>
<input v-model="password" id="password" type="password" required />
</div>
<button type="submit">Register</button>
</form>
<p v-if="error">{{ error }}</p>
<p v-if="success">{{ success }}</p>
</div>
</template>
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment