89 lines
1.8 KiB
Vue
89 lines
1.8 KiB
Vue
<script setup lang="ts">
|
|
import { ref } from "vue";
|
|
import { useRouter } from "vue-router";
|
|
import { useAuthStore } from "@/stores/auth";
|
|
|
|
const auth = useAuthStore();
|
|
const router = useRouter();
|
|
|
|
const email = ref("");
|
|
const displayName = ref("");
|
|
const submitting = ref(false);
|
|
|
|
async function handleSubmit() {
|
|
if (submitting.value) return;
|
|
submitting.value = true;
|
|
const ok = await auth.signup(email.value.trim(), displayName.value.trim());
|
|
submitting.value = false;
|
|
if (ok) router.push({ name: "check-email" });
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<section class="signup">
|
|
<h1>Sign up</h1>
|
|
<form @submit.prevent="handleSubmit">
|
|
<label>
|
|
<span>Email</span>
|
|
<input v-model="email" type="email" required autocomplete="email" />
|
|
</label>
|
|
<label>
|
|
<span>Display name</span>
|
|
<input
|
|
v-model="displayName"
|
|
type="text"
|
|
required
|
|
minlength="3"
|
|
maxlength="30"
|
|
pattern="[a-z0-9_-]+"
|
|
autocomplete="username"
|
|
/>
|
|
<small>3-30 chars, lowercase letters, digits, _ or -.</small>
|
|
</label>
|
|
<p v-if="auth.error" class="error">{{ auth.error }}</p>
|
|
<button type="submit" :disabled="submitting">Continue</button>
|
|
</form>
|
|
<p class="muted">
|
|
Already have an account?
|
|
<router-link :to="{ name: 'login' }">Log in</router-link>
|
|
</p>
|
|
</section>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.signup {
|
|
max-width: 360px;
|
|
margin: 32px auto;
|
|
}
|
|
|
|
form {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 16px;
|
|
margin-top: 16px;
|
|
}
|
|
|
|
label {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 6px;
|
|
font-size: 14px;
|
|
}
|
|
|
|
label small {
|
|
color: var(--color-secondary);
|
|
font-size: 12px;
|
|
}
|
|
|
|
.error {
|
|
color: #b00020;
|
|
font-size: 14px;
|
|
margin: 0;
|
|
}
|
|
|
|
.muted {
|
|
margin-top: 16px;
|
|
color: var(--color-secondary);
|
|
font-size: 14px;
|
|
}
|
|
</style>
|