mirror of
https://github.com/Floriansylvain/RenewCMS.git
synced 2026-08-19 11:43:22 +02:00
Login page implementation
This commit is contained in:
@@ -3,5 +3,5 @@ import { RouterView } from 'vue-router'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<RouterView />
|
||||
<RouterView />
|
||||
</template>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
import { createApp } from 'vue'
|
||||
import { createPinia } from 'pinia'
|
||||
|
||||
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
|
||||
import './assets/main.css'
|
||||
import '@/assets/base.css'
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import Home from '@/views/Home.vue'
|
||||
import Debug from '@/views/Debug.vue'
|
||||
import Login from '@/views/Login.vue'
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
@@ -9,6 +11,16 @@ const router = createRouter({
|
||||
name: 'home',
|
||||
component: Home
|
||||
},
|
||||
{
|
||||
path: '/debug',
|
||||
name: 'debug',
|
||||
component: Debug
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
component: Login
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
|
||||
@@ -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 }
|
||||
})
|
||||
@@ -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>
|
||||
@@ -1,77 +1,9 @@
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user