Fixed input when it has icon & refactored signin/register to reflect
changes in store
This commit is contained in:
		| @@ -2,23 +2,47 @@ | ||||
|   <section> | ||||
|     <h1>Register new user</h1> | ||||
|  | ||||
|     <seasoned-input placeholder="username" icon="Email" type="username" :value.sync="username" @enter="submit"/> | ||||
|     <div class="form"> | ||||
|       <seasoned-input | ||||
|         placeholder="username" | ||||
|         icon="Email" | ||||
|         type="email" | ||||
|         :value.sync="username" | ||||
|         @enter="submit" | ||||
|       /> | ||||
|  | ||||
|     <seasoned-input placeholder="password" icon="Keyhole" type="password" :value.sync="password" @enter="submit"/> | ||||
|     <seasoned-input placeholder="repeat password" icon="Keyhole" type="password" :value.sync="passwordRepeat" @enter="submit"/> | ||||
|       <seasoned-input | ||||
|         placeholder="password" | ||||
|         icon="Keyhole" | ||||
|         type="password" | ||||
|         :value.sync="password" | ||||
|         @enter="submit" | ||||
|       /> | ||||
|       <seasoned-input | ||||
|         placeholder="repeat password" | ||||
|         icon="Keyhole" | ||||
|         type="password" | ||||
|         :value.sync="passwordRepeat" | ||||
|         @enter="submit" | ||||
|       /> | ||||
|  | ||||
|       <seasoned-button @click="submit">Register</seasoned-button> | ||||
|     <router-link class="link" to="/signin">Have a user? Sign in here</router-link> | ||||
|     </div> | ||||
|  | ||||
|     <router-link class="link" to="/signin" | ||||
|       >Have a user? Sign in here</router-link | ||||
|     > | ||||
|  | ||||
|     <seasoned-messages :messages.sync="messages"></seasoned-messages> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import { register } from '@/api' | ||||
| import SeasonedButton from '@/components/ui/SeasonedButton' | ||||
| import SeasonedInput from '@/components/ui/SeasonedInput' | ||||
| import SeasonedMessages from '@/components/ui/SeasonedMessages' | ||||
| import { mapActions } from "vuex"; | ||||
| import { register } from "@/api"; | ||||
| import SeasonedButton from "@/components/ui/SeasonedButton"; | ||||
| import SeasonedInput from "@/components/ui/SeasonedInput"; | ||||
| import SeasonedMessages from "@/components/ui/SeasonedMessages"; | ||||
|  | ||||
| export default { | ||||
|   components: { SeasonedButton, SeasonedInput, SeasonedMessages }, | ||||
| @@ -28,58 +52,56 @@ export default { | ||||
|       username: null, | ||||
|       password: null, | ||||
|       passwordRepeat: null | ||||
|     } | ||||
|     }; | ||||
|   }, | ||||
|   methods: { | ||||
|     ...mapActions("user", ["login"]), | ||||
|     submit() { | ||||
|       this.messages = []; | ||||
|       let { username, password, passwordRepeat } = this; | ||||
|  | ||||
|       if (username == null || username.length == 0) { | ||||
|         this.messages.push({ type: 'error', title: 'Missing username' }) | ||||
|         return | ||||
|         this.messages.push({ type: "error", title: "Missing username" }); | ||||
|         return; | ||||
|       } else if (password == null || password.length == 0) { | ||||
|         this.messages.push({ type: 'error', title: 'Missing password' }) | ||||
|         return | ||||
|         this.messages.push({ type: "error", title: "Missing password" }); | ||||
|         return; | ||||
|       } else if (passwordRepeat == null || passwordRepeat.length == 0) { | ||||
|         this.messages.push({ type: 'error', title: 'Missing repeat password' }) | ||||
|         return | ||||
|         this.messages.push({ type: "error", title: "Missing repeat password" }); | ||||
|         return; | ||||
|       } else if (passwordRepeat != password) { | ||||
|         this.messages.push({ type: 'error', title: 'Passwords do not match' }) | ||||
|         return | ||||
|         this.messages.push({ type: "error", title: "Passwords do not match" }); | ||||
|         return; | ||||
|       } | ||||
|  | ||||
|       this.registerUser(username, password) | ||||
|       this.registerUser(username, password); | ||||
|     }, | ||||
|     registerUser(username, password) { | ||||
|       register(username, password, true) | ||||
|         .then(data => { | ||||
|           if (data.success){ | ||||
|             localStorage.setItem('token', data.token); | ||||
|             const jwtData = parseJwt(data.token) | ||||
|             localStorage.setItem('username', jwtData['username']); | ||||
|             localStorage.setItem('admin', jwtData['admin'] || false); | ||||
|  | ||||
|             eventHub.$emit('setUserStatus'); | ||||
|             this.$router.push({ name: 'profile' }) | ||||
|           if (data.success && this.login()) { | ||||
|             eventHub.$emit("setUserStatus"); | ||||
|             this.$router.push({ name: "profile" }); | ||||
|           } | ||||
|         }) | ||||
|         .catch(error => { | ||||
|           if (error.status === 401) { | ||||
|             this.messages.push({ type: 'error', title: 'Access denied', message: 'Incorrect username or password' }) | ||||
|           } | ||||
|           else { | ||||
|             this.messages.push({ type: 'error', title: 'Unexpected error', message: error.message }) | ||||
|             this.messages.push({ | ||||
|               type: "error", | ||||
|               title: "Access denied", | ||||
|               message: "Incorrect username or password" | ||||
|             }); | ||||
|           } else { | ||||
|             this.messages.push({ | ||||
|               type: "error", | ||||
|               title: "Unexpected error", | ||||
|               message: error.message | ||||
|             }); | ||||
|           } | ||||
|         }); | ||||
|     }, | ||||
|     logOut(){ | ||||
|       localStorage.clear(); | ||||
|       eventHub.$emit('setUserStatus'); | ||||
|       this.$router.push({ name: 'home' }); | ||||
|     } | ||||
|     } | ||||
|   } | ||||
| }; | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| @@ -92,6 +114,16 @@ section { | ||||
|     padding: 4rem; | ||||
|   } | ||||
|  | ||||
|   .form > div, | ||||
|   input, | ||||
|   button { | ||||
|     margin-bottom: 1rem; | ||||
|  | ||||
|     &:last-child { | ||||
|       margin-bottom: 0px; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   h1 { | ||||
|     margin: 0; | ||||
|     line-height: 16px; | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
|   <section> | ||||
|     <h1>Sign in</h1> | ||||
|  | ||||
|     <div class="form"> | ||||
|       <seasoned-input | ||||
|         placeholder="username" | ||||
|         icon="Email" | ||||
| @@ -18,6 +19,7 @@ | ||||
|       /> | ||||
|  | ||||
|       <seasoned-button @click="submit">sign in</seasoned-button> | ||||
|     </div> | ||||
|     <router-link class="link" to="/register" | ||||
|       >Don't have a user? Register here</router-link | ||||
|     > | ||||
| @@ -64,7 +66,7 @@ export default { | ||||
|     signin(username, password) { | ||||
|       login(username, password, true) | ||||
|         .then(data => { | ||||
|           if (data.success && this.login(data.token)) { | ||||
|           if (data.success && this.login()) { | ||||
|             this.$router.push({ name: "profile" }); | ||||
|           } | ||||
|         }) | ||||
| @@ -102,6 +104,16 @@ section { | ||||
|     padding: 4rem; | ||||
|   } | ||||
|  | ||||
|   .form > div, | ||||
|   input, | ||||
|   button { | ||||
|     margin-bottom: 1rem; | ||||
|  | ||||
|     &:last-child { | ||||
|       margin-bottom: 0px; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   h1 { | ||||
|     margin: 0; | ||||
|     line-height: 16px; | ||||
|   | ||||
| @@ -1,44 +1,55 @@ | ||||
| <template> | ||||
|   <div class="group" :class="{ completed: value }"> | ||||
|     <svg class="group__input-icon"> | ||||
|       <use v-bind="{ 'xlink:href': '#icon' + icon }"></use> | ||||
|     </svg> | ||||
|   <div class="group" :class="{ completed: value, focus }"> | ||||
|     <component :is="inputIcon" v-if="inputIcon" /> | ||||
|  | ||||
|     <input | ||||
|       class="group__input" | ||||
|       class="input" | ||||
|       :type="tempType || type" | ||||
|       @input="handleInput" | ||||
|       v-model="inputValue" | ||||
|       :placeholder="placeholder" | ||||
|       @keyup.enter="submit" | ||||
|       @keyup.enter="event => $emit('enter', event)" | ||||
|       @focus="focus = true" | ||||
|       @blur="focus = false" | ||||
|     /> | ||||
|  | ||||
|     <i | ||||
|       v-if="value && type === 'password'" | ||||
|       @click="toggleShowPassword" | ||||
|       class="group__input-show noselect" | ||||
|       @keydown.enter="toggleShowPassword" | ||||
|       class="show noselect" | ||||
|       tabindex="0" | ||||
|       >{{ tempType == "password" ? "show" : "hide" }}</i | ||||
|     > | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import IconKey from "../../icons/IconKey"; | ||||
| import IconEmail from "../../icons/IconEmail"; | ||||
|  | ||||
| export default { | ||||
|   components: { IconKey, IconEmail }, | ||||
|   props: { | ||||
|     placeholder: { type: String }, | ||||
|     icon: { type: String }, | ||||
|     type: { type: String, default: "text" }, | ||||
|     value: { type: String, default: undefined } | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       inputValue: this.value || undefined, | ||||
|       tempType: this.type | ||||
|       tempType: this.type, | ||||
|       focus: false | ||||
|     }; | ||||
|   }, | ||||
|   methods: { | ||||
|     submit(event) { | ||||
|       this.$emit("enter"); | ||||
|   computed: { | ||||
|     inputIcon() { | ||||
|       if (this.type === "password") return IconKey; | ||||
|       if (this.type === "email") return IconEmail; | ||||
|       return false; | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     handleInput(event) { | ||||
|       if (this.value !== undefined) { | ||||
|         this.$emit("update:value", this.inputValue); | ||||
| @@ -62,50 +73,50 @@ export default { | ||||
|  | ||||
| .group { | ||||
|   display: flex; | ||||
|   margin-bottom: 1rem; | ||||
|   width: 100%; | ||||
|   position: relative; | ||||
|   max-width: 35rem; | ||||
|   border: 1px solid var(--text-color-50); | ||||
|   background-color: var(--background-color-secondary); | ||||
|  | ||||
|   &.completed, | ||||
|   &.focus, | ||||
|   &:hover, | ||||
|   &:focus { | ||||
|     .group__input { | ||||
|       border-color: $text-color; | ||||
|     border-color: var(--text-color); | ||||
|  | ||||
|       &-icon { | ||||
|         fill: $text-color; | ||||
|       } | ||||
|     svg { | ||||
|       fill: var(--text-color); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   &.completed { | ||||
|     .group__input { | ||||
|       border-color: $text-color; | ||||
|  | ||||
|       &-icon { | ||||
|         fill: $text-color; | ||||
|       } | ||||
|     } | ||||
|   svg { | ||||
|     width: 24px; | ||||
|     height: 24px; | ||||
|     fill: var(--text-color-50); | ||||
|     pointer-events: none; | ||||
|     margin-top: 10px; | ||||
|     margin-left: 10px; | ||||
|     z-index: 8; | ||||
|   } | ||||
|  | ||||
|   &__input { | ||||
|   input { | ||||
|     width: 100%; | ||||
|     padding: 10px 10px 10px 45px; | ||||
|     padding: 10px; | ||||
|     outline: none; | ||||
|     background-color: $background-color-secondary; | ||||
|     color: $text-color; | ||||
|     background-color: var(--background-color-secondary); | ||||
|     color: var(--text-color); | ||||
|     font-weight: 100; | ||||
|     font-size: 1.2rem; | ||||
|     border: 1px solid $text-color-50; | ||||
|     margin: 0; | ||||
|     margin-left: -2.2rem !important; | ||||
|     z-index: 3; | ||||
|     transition: color 0.5s ease, background-color 0.5s ease, border 0.5s ease; | ||||
|     border: none; | ||||
|  | ||||
|     border-radius: 0; | ||||
|     -webkit-appearance: none; | ||||
|   } | ||||
|  | ||||
|     &-show { | ||||
|   .show { | ||||
|     position: absolute; | ||||
|     display: grid; | ||||
|     place-items: center; | ||||
| @@ -115,21 +126,9 @@ export default { | ||||
|     height: 100%; | ||||
|     font-size: 0.9rem; | ||||
|     cursor: pointer; | ||||
|       color: $text-color-50; | ||||
|     color: var(--text-color-50); | ||||
|     -webkit-user-select: none; | ||||
|     user-select: none; | ||||
|   } | ||||
| } | ||||
|  | ||||
|   &__input-icon { | ||||
|     width: 24px; | ||||
|     height: 24px; | ||||
|     fill: $text-color-50; | ||||
|     transition: fill 0.5s ease; | ||||
|     pointer-events: none; | ||||
|     margin-top: 10px; | ||||
|     margin-left: 10px; | ||||
|     z-index: 8; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user