You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

156 lines
4.3 KiB

<template>
<div class="w-full sm:max-w-sm sm:mx-auto sm:my-auto p-6 space-y-4 bg-white rounded-lg shadow-md">
<div class="text-center font-thin text-4xl py-4">AUTOPLEX</div>
<div class="font-medium text-center text-xl">Sign Up</div>
<form @submit.prevent="register">
<div class="space-y-4">
<div>
<text-box label="Access Token" type="text" disabled
v-model="fields.token" :validator="validateToken" ref="token"/>
</div>
<div>
<text-box label="Your Name" type="text" placeholder="John Doe" :disabled="isSubmitting"
v-model="fields.name" :validator="constraints.name" ref="name"/>
</div>
<div>
<text-box label="Email" type="email" placeholder="john@example.com" :disabled="isSubmitting"
v-model="fields.email" :validator="validateEmail" ref="email"/>
</div>
<div>
<text-box label="Password" type="password" placeholder="············" :disabled="isSubmitting"
v-model="fields.password" :validator="constraints.password" ref="password"
/>
</div>
<div>
<text-box label="Re-type Password" type="password" placeholder="············" :disabled="isSubmitting"
v-model="fields.retypePassword" :validator="validateRetypePassword" ref="retypePassword"/>
</div>
<div>
<button type="submit" class="block w-full rounded-full bg-indigo-500 text-white p-3 focus:outline-none" :disabled="isSubmitting">Register</button>
</div>
</div>
</form>
</div>
</template>
<script lang="ts">
import { defineComponent, reactive } from "vue";
import CheckBox from "../components/CheckBox.vue";
import TextBox from "../components/TextBox.vue";
import { constraints } from "../../common/validation";
import { validateValue } from "../util";
export default defineComponent({
components: {
CheckBox,
TextBox
},
data() {
return {
isSubmitting : false,
fields: reactive({
token : <string>this.$route.query["token"],
name : "",
email : "",
password : "",
retypePassword: "",
}),
constraints: {
name: constraints.register.name,
email: constraints.register.email,
password: constraints.register.password
}
}
},
methods: {
/**
* Submit the registration form
*/
async register() {
if (this.isSubmitting) {
return;
}
this.isSubmitting = true;
fetch(`/auth/register`, {
method: "post",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(this.fields)
})
.then(async response => {
this.isSubmitting = false;
if (response.status !== 200) {
let body = await response.json();
if (body.errors) {
for (let fieldName in this.fields) {
let field = <any>this.$refs[fieldName];
let message = <string>(body.errors[fieldName] ?? [""])[0];
field.setErrorMessage(message);
}
}
return;
}
this.$router.push({ name: "Login" });
})
.catch(e => {
console.error("Error occurred during submission:", e);
this.isSubmitting = false;
});
},
/**
* Validate the provided registration token
*/
async validateToken(token: string) {
let response = await fetch(`/auth/register/validate_token/${token}`, { method: "post" });
if (response.status !== 200) {
return "A valid token is required to register";
}
},
/**
* Validate the provided email address field
*/
async validateEmail(email: string) {
let error = validateValue(email, constraints.register.email);
if (error) {
return error;
}
// Check email availability
let response = await fetch(`/auth/register/available_email/${email}`, { method: "post" });
if (response.status !== 200) {
return "An account with that email address already exists";
}
},
/**
* Validate the provided retype-password field
*/
validateRetypePassword(value: string) {
if (value.trim().length == 0) {
return constraints.register.retypePassword.presence.message;
}
if (value !== this.fields.password) {
return constraints.register.retypePassword.equality.message;
}
}
},
/**
* Navigation Guard
*/
beforeRouteEnter(to, from, next) {
if (to.query["token"] === undefined) {
next({ name: "Login" });
} else {
next();
}
}
});
</script>
<style lang="postcss">
button:focus-visible {
@apply ring-2 ring-indigo-500 ring-offset-2;
}
</style>