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