180 lines
3.1 KiB
Vue
180 lines
3.1 KiB
Vue
<template>
|
|
<div class="content">
|
|
<h2 class="heading">Create new account</h2>
|
|
|
|
<form
|
|
class="form create"
|
|
@submit.prevent="signup"
|
|
>
|
|
<div
|
|
v-if="errorMsg"
|
|
class="form-section form-error"
|
|
>{{ errorMsg }}</div>
|
|
|
|
<div class="form-section">
|
|
<div class="form-row">
|
|
<input
|
|
v-model="username"
|
|
placeholder="Username"
|
|
maxlength="32"
|
|
class="input"
|
|
>
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<input
|
|
v-model="email"
|
|
type="email"
|
|
placeholder="E-mail"
|
|
maxlength="500"
|
|
class="input"
|
|
>
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<input
|
|
v-model="password"
|
|
type="password"
|
|
minlength="8"
|
|
maxlength="500"
|
|
placeholder="Password"
|
|
class="input"
|
|
>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
v-if="config.captchaEnabled"
|
|
class="form-row captcha"
|
|
>
|
|
<VueHcaptcha
|
|
:sitekey="config.captchaKey"
|
|
@verify="(token) => captchaToken = token"
|
|
@expired="() => captchaToken = null"
|
|
@error="() => captchaToken = null"
|
|
/>
|
|
</div>
|
|
|
|
<div class="form-section">
|
|
<label class="check-container noselect">
|
|
<span>
|
|
<span class="description">I have read and accept the <a
|
|
href="/help/user-agreement"
|
|
target="_blank"
|
|
class="link"
|
|
>User Agreement</a></span>
|
|
</span>
|
|
|
|
<Checkbox
|
|
:checked="agreeTos"
|
|
@change="(checked) => agreeTos = checked"
|
|
/>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="form-row form-actions">
|
|
<button
|
|
:disabled="!username || !email || !password || !agreeTos || (config.captchaEnabled && !captchaToken)"
|
|
class="button button-submit"
|
|
>Sign up</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref } from 'vue';
|
|
import VueHcaptcha from '@hcaptcha/vue3-hcaptcha';
|
|
|
|
import Checkbox from '../../components/form/checkbox.vue';
|
|
|
|
import { navigate } from '../../assets/js/navigate';
|
|
import { post } from '../../assets/js/api';
|
|
|
|
const config = CONFIG;
|
|
|
|
const username = ref('');
|
|
const email = ref('');
|
|
const password = ref('');
|
|
|
|
const agreeTos = ref(false);
|
|
const captchaToken = ref(null);
|
|
|
|
const errorMsg = ref(null);
|
|
|
|
async function signup() {
|
|
try {
|
|
await post('/users', {
|
|
username: username.value,
|
|
email: email.value,
|
|
password: password.value,
|
|
captchaToken: captchaToken.value,
|
|
});
|
|
|
|
navigate('/account/login');
|
|
} catch (error) {
|
|
errorMsg.value = error.message;
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.content {
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
flex-grow: 1;
|
|
align-items: center;
|
|
}
|
|
|
|
.create {
|
|
background: var(--background);
|
|
padding: 1rem;
|
|
border-radius: .5rem;
|
|
}
|
|
|
|
.name {
|
|
position: relative;
|
|
|
|
.input {
|
|
padding-left: 1.65rem;
|
|
}
|
|
|
|
.prefix {
|
|
color: var(--shadow);
|
|
position: absolute;
|
|
top: 1px;
|
|
left: .25rem;
|
|
letter-spacing: .1rem;
|
|
padding: .5rem;
|
|
}
|
|
}
|
|
|
|
.access {
|
|
font-weight: bold;
|
|
margin-bottom: .75rem;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.access-description {
|
|
margin: .25rem 0 0 1.25rem;
|
|
color: var(--shadow);
|
|
font-size: .9rem;
|
|
font-weight: normal;
|
|
}
|
|
|
|
.nsfw {
|
|
margin-right: .5rem;
|
|
font-weight: bold;
|
|
color: var(--error);
|
|
}
|
|
|
|
.captcha {
|
|
justify-content: center;
|
|
}
|
|
|
|
.form-actions {
|
|
justify-content: center;
|
|
}
|
|
</style>
|