Files
seasoned/src/pages/RegisterPage.vue
Kevin 8e586811ec Feat: vite & upgraded dependencies (#100)
* On every route change, update local variables from query params

* ResultSection is keyed to query to force re-render

* Resolved lint warnings

* replace webpack w/ vite

* update all imports with alias @ and scss

* vite environment variables, also typed

* upgraded eslint, defined new rules & added ignore comments

* resolved linting issues

* moved index.html to project root

* updated dockerfile w/ build stage before runtime image definition

* sign drone config
2026-02-23 20:53:19 +01:00

169 lines
4.1 KiB
Vue

<template>
<section>
<h1>Register new user</h1>
<form ref="formElement" class="form">
<seasoned-input
v-model="username"
placeholder="username"
icon="Email"
type="email"
@keydown.enter="focusOnNextElement"
/>
<seasoned-input
v-model="password"
placeholder="password"
icon="Keyhole"
type="password"
@keydown.enter="focusOnNextElement"
/>
<seasoned-input
v-model="passwordRepeat"
placeholder="repeat password"
icon="Keyhole"
type="password"
@keydown.enter="submit"
/>
<seasoned-button @click="submit">Register</seasoned-button>
</form>
<router-link class="link" to="/signin"
>Have a user? Sign in here</router-link
>
<seasoned-messages v-model:messages="messages"></seasoned-messages>
</section>
</template>
<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 type { Ref } from "vue";
import { register } from "../api";
import { focusFirstFormInput, focusOnNextElement } from "../utils";
import { ErrorMessageTypes } from "../interfaces/IErrorMessage";
import type { IErrorMessage } from "../interfaces/IErrorMessage";
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);
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: ErrorMessageTypes.Error
} as IErrorMessage);
}
function addWarningMessage(message: string, title?: string) {
messages.value.push({
message,
title,
type: ErrorMessageTypes.Warning
} as IErrorMessage);
}
function validate(): Promise<boolean> {
return new Promise((resolve, reject) => {
if (!username.value || username?.value?.length === 0) {
addWarningMessage("Missing username", "Validation error");
reject();
}
if (!password.value || password?.value?.length === 0) {
addWarningMessage("Missing password", "Validation error");
reject();
}
if (passwordRepeat.value == null || passwordRepeat.value.length === 0) {
addWarningMessage("Missing repeat password", "Validation error");
reject();
}
if (passwordRepeat.value !== password.value) {
addWarningMessage("Passwords do not match", "Validation error");
reject();
}
resolve(true);
});
}
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) {
addErrorMessage("Incorrect username or password", "Access denied");
return null;
}
addErrorMessage(error?.message, "Unexpected error");
return null;
});
}
function submit() {
clearMessages();
validate().then(registerUser);
}
</script>
<style lang="scss" scoped>
@import "scss/variables";
section {
padding: 1.3rem;
@include tablet-min {
padding: 4rem;
}
.form > div,
input,
button {
margin-bottom: 1rem;
&: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;
}
}
</style>