Login page implementation

This commit is contained in:
Florian Sylvain
2022-12-21 04:19:19 +01:00
parent 5d1ad603b8
commit 4d4116ae98
9 changed files with 260 additions and 71 deletions
+1 -1
View File
@@ -3,5 +3,5 @@ import { RouterView } from 'vue-router'
</script> </script>
<template> <template>
<RouterView /> <RouterView />
</template> </template>
+76
View File
@@ -0,0 +1,76 @@
@import url('https://fonts.googleapis.com/css2?family=Frank+Ruhl+Libre:wght@500&family=Hind:wght@400;500;600;700&family=Nunito:wght@500;600;700&display=swap');
:root {
--regular-weight: 400;
--medium-weight: 500;
--semibold-weight: 600;
--bold-weight: 700;
--radius: 10px;
--primary: #2CD358;
--primary-dark: #00BA2A;
--primary-light: #97E6A2;
--secondary: #D32CA6;
--secondary-dark: #BA0094;
--secondary-light: #E88DCA;
--neutral-dark: #121212;
--neutral-light: #aaaaaa;
}
body {
margin: 0;
}
h1 {
font-family: 'Frank Ruhl Libre', serif;
}
h2, h3, h4, h5, h6 {
font-family: 'Nunito', sans-serif;
}
* {
font-family: 'Hind', sans-serif;
box-sizing: border-box;
color: var(--neutral-dark);
}
.label-input {
display: flex;
flex-direction: column;
}
.label-input label {
font-weight: var(--medium-weight);
}
.label-input input {
height: 32px;
padding: 0 8px;
border: solid 1.25px var(--neutral-light);
border-radius: var(--radius);
}
.button-primary {
border-radius: var(--radius);
border: none;
height: 32px;
background-color: var(--primary);
font-weight: var(--medium-weight);
cursor: pointer;
}
.button-primary:hover {
background-color: var(--primary-light);
}
.button-primary:active {
background-color: var(--primary-dark);
}
View File
+1 -2
View File
@@ -1,11 +1,10 @@
import { createApp } from 'vue' import { createApp } from 'vue'
import { createPinia } from 'pinia' import { createPinia } from 'pinia'
import App from './App.vue' import App from './App.vue'
import router from './router' import router from './router'
import './assets/main.css' import '@/assets/base.css'
const app = createApp(App) const app = createApp(App)
+12
View File
@@ -1,5 +1,7 @@
import { createRouter, createWebHistory } from 'vue-router' import { createRouter, createWebHistory } from 'vue-router'
import Home from '@/views/Home.vue' import Home from '@/views/Home.vue'
import Debug from '@/views/Debug.vue'
import Login from '@/views/Login.vue'
const router = createRouter({ const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL), history: createWebHistory(import.meta.env.BASE_URL),
@@ -9,6 +11,16 @@ const router = createRouter({
name: 'home', name: 'home',
component: Home component: Home
}, },
{
path: '/debug',
name: 'debug',
component: Debug
},
{
path: '/login',
name: 'login',
component: Login
},
] ]
}) })
+15
View File
@@ -0,0 +1,15 @@
import { defineStore } from "pinia";
import { ref } from "vue";
export interface jwtFormat {
code: number,
expire: string,
token: string
}
export const useAuthStore = defineStore("AuthStore", () => {
const expire = ref("")
const token = ref("")
return { expire, token }
})
+63
View File
@@ -0,0 +1,63 @@
<script setup lang="ts">
// import EditorJS from '@editorjs/editorjs';
import { useAuthStore, type jwtFormat } from '@/stores/AuthStore';
import { ref } from 'vue';
const email = ref('')
const password = ref('')
function getArticles() {
fetch(`http://localhost:8080/articles/`, {
headers: { "Authorization": `Bearer ${useAuthStore().token}` }
})
.then(response => response.json())
.then(result => console.log(result))
}
function jwtHandler(apiResponse: jwtFormat): void {
if (apiResponse.code !== 200) {
console.log(apiResponse)
return
}
useAuthStore().token = apiResponse.token
useAuthStore().expire = apiResponse.expire
console.log('success! logged in.')
}
function login(email: string, password: string): void {
fetch(`http://localhost:8080/login/`, {
method: "POST",
body: JSON.stringify({
email: email,
password: password
})
})
.then(response => response.json())
.then(result => jwtHandler(result))
}
</script>
<template>
<h2>Connexion</h2>
<form @submit.prevent="login(email, password)">
<div>
<label for="email">Email address</label>
<input id="email" name="email" placeholder="email" type="text" v-model="email">
</div>
<div>
<label for="password">Password</label>
<input id="password" name="password" placeholder="password" type="password" v-model="password">
</div>
<button type="submit">Se connecter</button>
</form>
<div>
<div>
<button @click="getArticles()">get all articles</button>
<button @click="getArticles()">get all articles</button>
<button @click="getArticles()">get all articles</button>
<button @click="getArticles()">get all articles</button>
</div>
</div>
</template>
-68
View File
@@ -1,77 +1,9 @@
<script setup lang="ts"> <script setup lang="ts">
// import EditorJS from '@editorjs/editorjs';
import { pingApi } from '@/utils/ping';
import { onMounted, ref } from 'vue';
const inputArticleID = ref('')
const username = ref('')
const password = ref('')
onMounted(async function() {
console.log('ping...')
const pong = await pingApi()
console.log(pong)
})
function addArticle() {
fetch(`http://localhost:8080/articles/${Math.random() * 100}`, {
method: "POST",
headers: {"Authorization" : `Basic ${btoa(`${username.value}:${password.value}`)}`},
body: JSON.stringify({
content: {},
date: new Date().getTime()
})
})
.then(response => response.json())
.then(result => console.log(result))
}
function deleteArticle(articleID: String) {
fetch(`http://localhost:8080/articles/${articleID}`, {
method: "DELETE",
headers: {"Authorization" : `Basic ${btoa(`${username.value}:${password.value}`)}`},
body: JSON.stringify({
id_name: articleID
})
})
.then(response => response.json())
.then(result => console.log(result))
}
function getArticle(articleID: String) {
fetch(`http://localhost:8080/articles/${articleID}`, {
headers: {"Authorization" : `Basic ${btoa(`${username.value}:${password.value}`)}`},
})
.then(response => response.json())
.then(result => console.log(result))
}
function auth(type: string, username: string, password: string) {
fetch(`http://localhost:8080/${type}`, {
method: "POST",
body: JSON.stringify({
email: username,
password: password
})
})
.then(response => response.json())
.then(result => console.log(result))
}
</script> </script>
<template> <template>
<p>Salut à tous</p>
<button @click="addArticle">add rand article</button>
<button @click="getArticle('')">display articles in console</button> <br>
<label for="articleIDinput"></label>
<input id="articleIDinput" name="articleIDinput" type="text" placeholder="article ID" v-model="inputArticleID">
<button @click="deleteArticle(inputArticleID)">delete this article</button>
<button @click="getArticle(inputArticleID)">get this article</button> <br>
<input type="text" name="username" id="username" v-model="username" placeholder="username">
<input type="text" name="password" id="password" v-model="password" placeholder="password">
<button @click="auth('login', username, password)">login</button>
<button @click="auth('logout', username, password)">logout</button>
</template> </template>
<style scoped> <style scoped>
+92
View File
@@ -0,0 +1,92 @@
<script setup lang="ts">
import { useAuthStore, type jwtFormat } from '@/stores/AuthStore';
import { ref, type Ref } from 'vue';
import { useRouter } from 'vue-router';
const isTokenOK: Ref<boolean|undefined> = ref(undefined)
const router = useRouter()
function jwtHandler(apiResponse: jwtFormat): void {
if (apiResponse.code !== 200) {
console.error(apiResponse)
return
}
useAuthStore().token = apiResponse.token
useAuthStore().expire = apiResponse.expire
isTokenOK.value = true
}
function login(email: string, password: string): void {
fetch(`http://localhost:8080/login/`, {
method: "POST",
body: JSON.stringify({
email: email,
password: password
})
})
.then(response => response.json())
.then(result => {
jwtHandler(result)
if (isTokenOK.value === true) {
router.push('/')
}
})
}
const email = ref('')
const password = ref('')
</script>
<template>
<div class="login-page">
<div class="login-form">
<h2>Connexion à GohCMS</h2>
<form @submit.prevent="login(email, password)">
<div class="inputs-group">
<div class="label-input">
<label for="email">Adresse mail</label>
<input id="email" name="email" placeholder="E-mail" type="text" v-model="email">
</div>
<div class="label-input">
<label for="password">Mot de passe</label>
<input id="password" name="password" placeholder="Mot de passe" type="password" v-model="password">
</div>
</div>
<button class="button-primary" type="submit">Se connecter</button>
</form>
</div>
</div>
</template>
<style scoped>
h2 {
margin: 0 0 16px 0;
}
.login-page {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.login-form {
width: 100%;
max-width: 350px;
padding: 32px;
}
.inputs-group,
.login-form form {
display: flex;
flex-direction: column;
gap: 8px;
}
.login-form form {
gap: 32px;
}
</style>