170 lines
6.5 KiB
Vue
170 lines
6.5 KiB
Vue
<script setup lang="ts">
|
|
import { Link, useForm } from '@inertiajs/vue3';
|
|
import Button from '@/components/ui/Button.vue';
|
|
import Checkbox from '@/components/ui/Checkbox.vue';
|
|
import Dialog from '@/components/ui/Dialog.vue';
|
|
import Input from '@/components/ui/Input.vue';
|
|
import Message from '@/components/ui/Message.vue';
|
|
import PasswordInput from '@/components/ui/PasswordInput.vue';
|
|
import { ref } from 'vue';
|
|
import ReCaptcha from '@/components/ReCaptcha.vue';
|
|
import SocialButtons from '@/components/SocialButtons.vue';
|
|
import TermsOfService from '@/components/TermsOfService.vue';
|
|
import { useSettings, useTranslations } from '@/composables/useVanguard';
|
|
import AuthLayout from '@/layouts/AuthLayout.vue';
|
|
|
|
defineProps<{
|
|
socialProviders: string[] | null;
|
|
captchaSitekey: string | null;
|
|
}>();
|
|
|
|
const { __ } = useTranslations();
|
|
const { setting } = useSettings();
|
|
|
|
const tosVisible = ref(false);
|
|
const captcha = ref<InstanceType<typeof ReCaptcha> | null>(null);
|
|
|
|
const form = useForm({
|
|
email: '',
|
|
username: '',
|
|
password: '',
|
|
password_confirmation: '',
|
|
tos: false,
|
|
'g-recaptcha-response': '',
|
|
});
|
|
|
|
function submit() {
|
|
form.post('/register', {
|
|
onError: () => {
|
|
captcha.value?.reset();
|
|
form['g-recaptcha-response'] = '';
|
|
},
|
|
onFinish: () => form.reset('password', 'password_confirmation'),
|
|
});
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<AuthLayout :title="__('Sign Up')">
|
|
<div class="rounded-lg border border-slate-200 bg-white shadow-sm">
|
|
<div class="p-6">
|
|
<h5 class="mt-2 mb-4 text-center text-sm font-semibold tracking-wider text-slate-600 uppercase">
|
|
{{ __('Register') }}
|
|
</h5>
|
|
|
|
<SocialButtons :providers="socialProviders" />
|
|
|
|
<form class="space-y-4" autocomplete="off" @submit.prevent="submit">
|
|
<div>
|
|
<Input
|
|
id="email"
|
|
v-model="form.email"
|
|
type="email"
|
|
class="w-full"
|
|
:placeholder="__('Email')"
|
|
:invalid="Boolean(form.errors.email)"
|
|
autocomplete="email"
|
|
/>
|
|
<small v-if="form.errors.email" class="text-red-600">{{ form.errors.email }}</small>
|
|
</div>
|
|
|
|
<div>
|
|
<Input
|
|
id="username"
|
|
v-model="form.username"
|
|
class="w-full"
|
|
:placeholder="__('Username')"
|
|
:invalid="Boolean(form.errors.username)"
|
|
autocomplete="username"
|
|
/>
|
|
<small v-if="form.errors.username" class="text-red-600">
|
|
{{ form.errors.username }}
|
|
</small>
|
|
</div>
|
|
|
|
<div>
|
|
<PasswordInput
|
|
id="password"
|
|
v-model="form.password"
|
|
class="w-full"
|
|
:placeholder="__('Password')"
|
|
:invalid="Boolean(form.errors.password)"
|
|
autocomplete="new-password"
|
|
/>
|
|
<small v-if="form.errors.password" class="text-red-600">
|
|
{{ form.errors.password }}
|
|
</small>
|
|
</div>
|
|
|
|
<div>
|
|
<PasswordInput
|
|
id="password_confirmation"
|
|
v-model="form.password_confirmation"
|
|
class="w-full"
|
|
:placeholder="__('Confirm Password')"
|
|
autocomplete="new-password"
|
|
/>
|
|
</div>
|
|
|
|
<div v-if="setting('tos')">
|
|
<div class="flex items-center gap-2">
|
|
<Checkbox
|
|
v-model="form.tos"
|
|
id="tos"
|
|
:invalid="Boolean(form.errors.tos)"
|
|
/>
|
|
<label for="tos" class="text-slate-600">
|
|
{{ __('I accept') }}
|
|
<button
|
|
type="button"
|
|
class="text-primary-600 cursor-pointer hover:underline"
|
|
@click="tosVisible = true"
|
|
>
|
|
{{ __('Terms of Service') }}
|
|
</button>
|
|
</label>
|
|
</div>
|
|
<small v-if="form.errors.tos" class="text-red-600">{{ form.errors.tos }}</small>
|
|
</div>
|
|
|
|
<div v-if="setting('registration.captcha.enabled') && captchaSitekey">
|
|
<ReCaptcha
|
|
ref="captcha"
|
|
:sitekey="captchaSitekey"
|
|
@verified="(token) => (form['g-recaptcha-response'] = token)"
|
|
/>
|
|
<Message
|
|
v-if="form.errors['g-recaptcha-response']"
|
|
severity="error"
|
|
class="mt-2"
|
|
>
|
|
{{ form.errors['g-recaptcha-response'] }}
|
|
</Message>
|
|
</div>
|
|
|
|
<Button
|
|
type="submit"
|
|
:label="__('Register')"
|
|
class="w-full"
|
|
size="large"
|
|
:loading="form.processing"
|
|
/>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<p class="mt-6 text-center text-slate-500">
|
|
{{ __('Already have an account?') }}
|
|
<Link href="/login" class="text-primary-600 font-bold">{{ __('Login') }}</Link>
|
|
</p>
|
|
|
|
<Dialog v-model:open="tosVisible" :header="__('Terms of Service')" width="40rem">
|
|
<TermsOfService />
|
|
|
|
<template #footer>
|
|
<Button :label="__('Close')" severity="secondary" @click="tosVisible = false" />
|
|
</template>
|
|
</Dialog>
|
|
</AuthLayout>
|
|
</template>
|