diff options
| author | ivarlovlie <git@ivarlovlie.no> | 2020-08-02 23:07:23 +0200 |
|---|---|---|
| committer | ivarlovlie <git@ivarlovlie.no> | 2020-08-02 23:07:38 +0200 |
| commit | 77352e518614cfeaf3bb649ed15b0d854076fe6e (patch) | |
| tree | 906fc99e8662f3d81bc24e825253a2cb870b43f4 /src/browser | |
| parent | 25c5dac6310d20ec9d2f3bee8efd9af0199fb699 (diff) | |
| download | dough-77352e518614cfeaf3bb649ed15b0d854076fe6e.tar.xz dough-77352e518614cfeaf3bb649ed15b0d854076fe6e.zip | |
Login: auth and save profile in vuex, show errors
Diffstat (limited to 'src/browser')
| -rw-r--r-- | src/browser/src/api/account.js | 27 | ||||
| -rw-r--r-- | src/browser/src/components/Alert/Alert.vue | 31 | ||||
| -rw-r--r-- | src/browser/src/components/Sidebar/Sidebar.vue | 21 | ||||
| -rw-r--r-- | src/browser/src/constants.js | 8 | ||||
| -rw-r--r-- | src/browser/src/router.js | 4 | ||||
| -rw-r--r-- | src/browser/src/store.js | 4 | ||||
| -rw-r--r-- | src/browser/src/views/Home.vue | 25 | ||||
| -rw-r--r-- | src/browser/src/views/Login.vue | 87 |
8 files changed, 120 insertions, 87 deletions
diff --git a/src/browser/src/api/account.js b/src/browser/src/api/account.js new file mode 100644 index 0000000..123ec09 --- /dev/null +++ b/src/browser/src/api/account.js @@ -0,0 +1,27 @@ +import constants from "../constants"; + +export default { + async loginAsync(username, password) { + let response = await fetch(constants.API_ADDRESS + "/account/login", { + method: "POST", + credentials: "include", + headers: { + "Content-Type": "application/json;charset=utf-8", + }, + body: JSON.stringify({ + username, + password, + }), + }); + + return response; + }, + async getProfileAsync() { + let response = await fetch(constants.API_ADDRESS + "/account/me", { + method: "GET", + credentials: "include", + }); + + return response; + }, +}; diff --git a/src/browser/src/components/Alert/Alert.vue b/src/browser/src/components/Alert/Alert.vue index ed00284..7f5a33d 100644 --- a/src/browser/src/components/Alert/Alert.vue +++ b/src/browser/src/components/Alert/Alert.vue @@ -1,18 +1,17 @@ <template> <div - class="alert js-alert" + class="alert js-alert alert--is-visible" v-bind:class="{ 'alert--success': isSuccess, 'alert--warning': isWarning, 'alert--error': isError, - 'alert--is-visible': isVisible, }" role="alert" > <div class="flex items-center justify-between"> <div class="flex items-center"> <p> - <strong>{{ model.title }}:</strong> {{ model.message }} + <strong>{{ title }}:</strong> {{ message }} </p> </div> @@ -37,29 +36,37 @@ </template> <script> -import { reactive, toRefs, readonly } from "vue"; +import { reactive, toRefs, onMounted } from "vue"; import initAlert from "./Alert"; export default { + props: { + title: String, + message: String, + type: String, + isVisible: Boolean, + }, + setup(props) { const model = reactive({ title: props.title, message: props.message, type: props.type ?? "info", - isSuccess: model.type === "success", - isWarning: model.type === "warning", - isError: model.type === "error", - isInfo: model.type === "info", - isVisible: props.isVisible ?? false, + isSuccess: props.type === "success", + isWarning: props.type === "warning", + isError: props.type === "error", + isInfo: props.type === "info", }); + onMounted(() => initAlert()); return { ...toRefs(model) }; }, - mounted() { - initAlert(); - }, }; </script> <style lang="scss" scoped> @import "Alert.scss"; + +.alert { + margin: var(--space-sm) 0; +} </style> diff --git a/src/browser/src/components/Sidebar/Sidebar.vue b/src/browser/src/components/Sidebar/Sidebar.vue index aa6efc3..a828e38 100644 --- a/src/browser/src/components/Sidebar/Sidebar.vue +++ b/src/browser/src/components/Sidebar/Sidebar.vue @@ -1,9 +1,5 @@ <template> - <div - class="bg border-right" - :class="{ 'is-hidden': !isLoggedIn }" - style="width: 250px; height: 100vh;" - > + <div class="bg border-right" v-if="isAuthencticated" style="width: 250px; height: 100vh;"> <nav class="sidenav sidenav--basic padding-y-sm text-sm@md"> <ul class="sidenav__list margin-bottom-sm"> <li class="sidenav__item"> @@ -38,10 +34,21 @@ <script> import "./Sidebar.js"; -import { mapState } from "vuex"; +import store from "../../store"; +import { reactive, onMounted, toRefs } from "vue"; export default { name: "Sidebar", - computed: mapState(["isLoggedIn"]), + setup() { + const model = reactive({ + isAuthencticated: false, + }); + + onMounted(() => { + model.isAuthencticated = store.state.profile.isAuthenticated; + }); + + return { ...toRefs(model) }; + }, }; </script> diff --git a/src/browser/src/constants.js b/src/browser/src/constants.js index 04b8d1e..ddeebe8 100644 --- a/src/browser/src/constants.js +++ b/src/browser/src/constants.js @@ -1,5 +1,13 @@ const constants = { API_ADDRESS: "http://localhost:5001/api", + storageKeys: { + COOKIE_LAST_SEEN: "cookie-last-seen", + }, + types: { + SET_PROFILE_DATA: "set-profile-data", + LOGIN_ASYNC: "login-async", + DONWLOAD_PROFILE_DATA: "download-profile-data-async", + }, }; export default constants; diff --git a/src/browser/src/router.js b/src/browser/src/router.js index 611b97f..c03dcf7 100644 --- a/src/browser/src/router.js +++ b/src/browser/src/router.js @@ -37,8 +37,8 @@ const router = createRouter({ }); router.beforeEach((to, from, next) => { - console.log("store.state.profile: " + store.state.profile); - if (to.path !== "/login" && !store.state.isLoggedIn) next("/login"); + console.log("store.state.profile.isAuthenticated: " + store.state.profile.isAuthenticated); + if (to.path !== "/login" && !store.state.profile.isAuthenticated) next("/login"); else next(); }); diff --git a/src/browser/src/store.js b/src/browser/src/store.js index 87f7b9d..0dd3195 100644 --- a/src/browser/src/store.js +++ b/src/browser/src/store.js @@ -20,8 +20,6 @@ export default createStore({ }; }, }, - actions: { - - }, + actions: {}, modules: {}, }); diff --git a/src/browser/src/views/Home.vue b/src/browser/src/views/Home.vue index 94e23cd..bca4ff5 100644 --- a/src/browser/src/views/Home.vue +++ b/src/browser/src/views/Home.vue @@ -1,16 +1,27 @@ <template> - <div id="home"> - <h1>Hjem</h1> - </div> + <div id="home"> + <h1>Hjem</h1> + <p>Hei {{ username }}, din id er {{ id }}</p> + </div> </template> <script> import Sidebar from "@/components/Sidebar/Sidebar.vue"; +import store from "../store"; +import { reactive, computed, toRefs } from "vue"; export default { - name: "Home", - components: { - Sidebar, - }, + name: "Home", + components: { + Sidebar, + }, + setup() { + const model = reactive({ + username: computed(() => store.state.profile.username), + id: computed(() => store.state.profile.id), + }); + + return { ...toRefs(model) }; + }, }; </script> diff --git a/src/browser/src/views/Login.vue b/src/browser/src/views/Login.vue index f1105dc..8131ba5 100644 --- a/src/browser/src/views/Login.vue +++ b/src/browser/src/views/Login.vue @@ -1,12 +1,10 @@ <template> <div class="container max-width-xs padding-y-lg"> <form class="login-form" @submit.prevent="submitForm()"> - <div v-if="isError"> - <Alert message="" title="" type="error" /> - </div> <div class="text-component text-center margin-bottom-sm"> <h1>dough</h1> </div> + <Alert v-if="isError" :title="error.title" :message="error.message" type="error" /> <div class="margin-bottom-sm"> <label class="form-label margin-bottom-xxxs" for="username">Email</label> <input @@ -71,6 +69,7 @@ import constants from "../constants"; import { reactive, toRefs } from "vue"; import store from "../store"; import router from "../router"; +import account from "../api/account"; export default { components: { @@ -91,72 +90,48 @@ export default { }, }); - function submitForm() { + async function submitForm() { document.getElementById("username").required = true; document.getElementById("password").required = true; if (model.input.username && model.input.password) { - // displayError() model.isLoading = true; - // loginAsync() + model.isError = false; + try { + let loginResponse = await account.loginAsync( + model.input.username, + model.input.password + ); + if (loginResponse.status === 200) { + let profileResponse = await account.getProfileAsync(); + let profileData = await profileResponse.json(); + if (profileResponse.status === 200) { + model.isLoading = false; + store.commit("setProfileData", profileData); + router.replace("/"); + } else { + displayError(profileData.title, profileData.message); + } + } else { + let errorData = await loginResponse.json(); + displayError(errorData.title, errorData.message); + } + } catch (error) { + console.error(error); + displayError(); + } } } - function displayError(title = "En feil oppstod", message = "Prøv igjen senere") { + function displayError( + title = "An unknown error ocurred", + message = "Please try again soon" + ) { model.isLoading = false; model.error.title = title; model.error.message = message; model.isError = true; } - async function loginAsync() { - try { - let response = await fetch(constants.API_ADDRESS + "/account/login", { - method: "POST", - credentials: "include", - headers: { - "Content-Type": "application/json;charset=utf-8", - }, - body: JSON.stringify(model.input), - }); - - if (response.status === 200) { - let profile = await getProfileAsync(); - store.commit("setProfileData", profile); - router.replace("/"); - } else { - console.error("An error ocurred when logging in"); - let data = await response.json(); - model.error.title = data.title; - model.error.message = data.message; - model.isError = true; - } - - model.isLoading = false; - } catch (err) { - displayError(err.title, err.message); - console.error(err); - } finally { - model.isLoading = false; - } - } - - async function getProfileAsync() { - try { - let response = await fetch(constants.API_ADDRESS + "/account/me", { - method: "GET", - credentials: "include", - }); - if (response.status === 200) { - let data = await response.json(); - if (data.id) return data; - else return null; - } - return null; - } catch (err) { - return null; - } - } - return { ...toRefs(model), submitForm }; }, }; |
