mirror of
https://github.com/KevinMidboe/seasoned.git
synced 2026-03-11 11:55:38 +00:00
Ugraded all pages to vue 3 & typescript
This commit is contained in:
@@ -2,146 +2,159 @@
|
||||
<section>
|
||||
<h1>Register new user</h1>
|
||||
|
||||
<div class="form">
|
||||
<form class="form" ref="formElement">
|
||||
<seasoned-input
|
||||
ref="username"
|
||||
placeholder="username"
|
||||
icon="Email"
|
||||
type="email"
|
||||
:value.sync="username"
|
||||
@enter="submit"
|
||||
v-model="username"
|
||||
@keydown.enter="focusOnNextElement"
|
||||
/>
|
||||
|
||||
<seasoned-input
|
||||
placeholder="password"
|
||||
icon="Keyhole"
|
||||
type="password"
|
||||
:value.sync="password"
|
||||
@enter="submit"
|
||||
v-model="password"
|
||||
@keydown.enter="focusOnNextElement"
|
||||
/>
|
||||
<seasoned-input
|
||||
placeholder="repeat password"
|
||||
icon="Keyhole"
|
||||
type="password"
|
||||
:value.sync="passwordRepeat"
|
||||
@enter="submit"
|
||||
v-model="passwordRepeat"
|
||||
@keydown.enter="submit"
|
||||
/>
|
||||
|
||||
<seasoned-button @click="submit">Register</seasoned-button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<router-link class="link" to="/signin"
|
||||
>Have a user? Sign in here</router-link
|
||||
>
|
||||
|
||||
<seasoned-messages :messages.sync="messages"></seasoned-messages>
|
||||
<seasoned-messages v-model:messages="messages"></seasoned-messages>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
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";
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from "vue";
|
||||
import { useStore } from "vuex";
|
||||
import { useRouter } from "vue-router";
|
||||
import SeasonedButton from "@/components/ui/SeasonedButton.vue";
|
||||
import SeasonedInput from "@/components/ui/SeasonedInput.vue";
|
||||
import SeasonedMessages from "@/components/ui/SeasonedMessages.vue";
|
||||
import { register } from "../api";
|
||||
import { focusFirstFormInput, focusOnNextElement } from "../utils";
|
||||
import type { Ref } from "vue";
|
||||
import type IErrorMessage from "../interfaces/IErrorMessage";
|
||||
|
||||
export default {
|
||||
components: { SeasonedButton, SeasonedInput, SeasonedMessages },
|
||||
data() {
|
||||
return {
|
||||
messages: [],
|
||||
username: null,
|
||||
password: null,
|
||||
passwordRepeat: null
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
...mapActions("user", ["login"]),
|
||||
submit() {
|
||||
this.messages = [];
|
||||
let { username, password, passwordRepeat } = this;
|
||||
const username: Ref<string> = ref("");
|
||||
const password: Ref<string> = ref("");
|
||||
const passwordRepeat: Ref<string> = ref("");
|
||||
const messages: Ref<IErrorMessage[]> = ref([]);
|
||||
const formElement: Ref<HTMLFormElement> = ref(null);
|
||||
|
||||
if (username == null || username.length == 0) {
|
||||
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;
|
||||
} else if (passwordRepeat == null || passwordRepeat.length == 0) {
|
||||
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;
|
||||
const store = useStore();
|
||||
const router = useRouter();
|
||||
|
||||
onMounted(() => focusFirstFormInput(formElement.value));
|
||||
|
||||
function clearMessages() {
|
||||
messages.value = [];
|
||||
}
|
||||
|
||||
function addErrorMessage(message: string, title?: string) {
|
||||
messages.value.push({ message, title, type: "error" });
|
||||
}
|
||||
|
||||
function addWarningMessage(message: string, title?: string) {
|
||||
messages.value.push({ message, title, type: "warning" });
|
||||
}
|
||||
|
||||
function validate(): Promise<boolean> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!username.value || username?.value?.length === 0) {
|
||||
addWarningMessage("Missing username", "Validation error");
|
||||
return reject();
|
||||
}
|
||||
|
||||
this.registerUser(username, password);
|
||||
},
|
||||
registerUser(username, password) {
|
||||
register(username, password)
|
||||
.then(data => {
|
||||
if (data.success && this.login()) {
|
||||
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
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
try {
|
||||
this.$refs.username.$el.getElementsByTagName("input")[0].focus();
|
||||
} catch {}
|
||||
if (!password.value || password?.value?.length === 0) {
|
||||
addWarningMessage("Missing password", "Validation error");
|
||||
return reject();
|
||||
}
|
||||
|
||||
if (passwordRepeat.value == null || passwordRepeat.value.length == 0) {
|
||||
addWarningMessage("Missing repeat password", "Validation error");
|
||||
return reject();
|
||||
}
|
||||
if (passwordRepeat != password) {
|
||||
addWarningMessage("Passwords do not match", "Validation error");
|
||||
return reject();
|
||||
}
|
||||
|
||||
resolve(true);
|
||||
});
|
||||
}
|
||||
|
||||
function submit() {
|
||||
clearMessages();
|
||||
validate().then(registerUser);
|
||||
}
|
||||
|
||||
function registerUser() {
|
||||
register(username.value, password.value)
|
||||
.then(data => {
|
||||
if (data?.success && store.dispatch("user/login")) {
|
||||
router.push({ name: "profile" });
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
if (error?.status === 401) {
|
||||
return addErrorMessage(
|
||||
"Incorrect username or password",
|
||||
"Access denied"
|
||||
);
|
||||
}
|
||||
|
||||
addErrorMessage(error?.message, "Unexpected error");
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "src/scss/variables";
|
||||
@import "src/scss/variables";
|
||||
|
||||
section {
|
||||
padding: 1.3rem;
|
||||
section {
|
||||
padding: 1.3rem;
|
||||
|
||||
@include tablet-min {
|
||||
padding: 4rem;
|
||||
}
|
||||
@include tablet-min {
|
||||
padding: 4rem;
|
||||
}
|
||||
|
||||
.form > div,
|
||||
input,
|
||||
button {
|
||||
margin-bottom: 1rem;
|
||||
.form > div,
|
||||
input,
|
||||
button {
|
||||
margin-bottom: 1rem;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0px;
|
||||
&:last-child {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
line-height: 16px;
|
||||
color: $text-color;
|
||||
font-weight: 300;
|
||||
margin-bottom: 20px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.link {
|
||||
display: block;
|
||||
width: max-content;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
line-height: 16px;
|
||||
color: $text-color;
|
||||
font-weight: 300;
|
||||
margin-bottom: 20px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.link {
|
||||
display: block;
|
||||
width: max-content;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user