196 lines
4.5 KiB
Vue
196 lines
4.5 KiB
Vue
<script lang="ts" setup>
|
|
import { ref, reactive } from "vue";
|
|
import {
|
|
Form as veeForm,
|
|
Field as veeField,
|
|
useField,
|
|
useForm,
|
|
useSetFieldValue,
|
|
useFormErrors,
|
|
useFormValues,
|
|
RuleExpression,
|
|
} from "vee-validate";
|
|
import * as yup from "yup";
|
|
import { useRecaptchaProvider } from "vue-recaptcha";
|
|
|
|
import { useChallengeV2 } from "vue-recaptcha";
|
|
import { notification } from "ant-design-vue";
|
|
import { log } from "@server/logger";
|
|
import termsOfServices from "~/components/tos.vue";
|
|
useRecaptchaProvider();
|
|
|
|
interface FormState {
|
|
username: string;
|
|
password: string;
|
|
email: string;
|
|
recaptcha?: string | null;
|
|
agree: boolean;
|
|
}
|
|
definePageMeta({
|
|
auth: {
|
|
unauthenticatedOnly: true,
|
|
navigateAuthenticatedTo: "/",
|
|
},
|
|
});
|
|
// const { execute } = useChallengeV3('submit');
|
|
const vschema = yup.object<FormState>().shape({
|
|
username: yup
|
|
.string()
|
|
.ensure()
|
|
.trim()
|
|
.min(1)
|
|
.required("Username is required!"),
|
|
password: yup
|
|
.string()
|
|
.ensure()
|
|
.trim()
|
|
.min(8)
|
|
.required("Password is required!"),
|
|
email: yup.string().ensure().trim().email().required("Email is required!"),
|
|
// recaptcha: yup.string().required('Please verify you are human.'),
|
|
agree: yup
|
|
.boolean()
|
|
.oneOf([true], "Please agree to the terms.")
|
|
.required("Please agree to the terms."),
|
|
});
|
|
const dv: FormState = {
|
|
username: "",
|
|
password: "",
|
|
email: "",
|
|
agree: false,
|
|
};
|
|
|
|
const dark = inject<boolean>("dark");
|
|
|
|
const { setValues, values, handleSubmit } = useForm({
|
|
validationSchema: vschema,
|
|
keepValuesOnUnmount: true,
|
|
});
|
|
|
|
const {
|
|
value: recaptchaValue,
|
|
errorMessage: recaptchaError,
|
|
name: recapName,
|
|
setValue: srv,
|
|
} = useField<string>("recaptcha", undefined, { syncVModel: true });
|
|
|
|
const { root, execute, onVerify, widgetID } = useChallengeV2({
|
|
options: {
|
|
size: "invisible",
|
|
},
|
|
});
|
|
onVerify((resp) => {
|
|
console.debug("onverify called", resp);
|
|
srv(resp);
|
|
});
|
|
const onFinish = handleSubmit(async (values: any, actions: any) => {
|
|
// log.debug(values, widgetID);
|
|
// log.debug(widgetID);
|
|
execute();
|
|
const { signUp } = useAuth();
|
|
let reso;
|
|
try {
|
|
reso = await signUp(values, { callbackUrl: "/" });
|
|
} catch (e: any) {
|
|
// log.debug(e.data);
|
|
if (e.data) {
|
|
notification["error"]({
|
|
message: h("div", { innerHTML: e.data.message }),
|
|
});
|
|
}
|
|
}
|
|
// log.debug(reso);
|
|
|
|
/* try {
|
|
{data: reso } = await useApiFetch("/auth/register", {
|
|
method: "post",
|
|
body: values
|
|
})
|
|
} catch (e: any) {
|
|
// log.debug(reso.error.data)
|
|
if (e.data) {
|
|
notification[ "error" ]({
|
|
message: h("div", { innerHTML: reso.error.data.message })
|
|
})
|
|
}
|
|
} */
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<form @submit="onFinish">
|
|
<vee-field name="username" v-slot="{ field, errorMessage, value }">
|
|
<a-form-item
|
|
label="Username"
|
|
:name="field.name"
|
|
:validate-status="!!errorMessage ? 'error' : ''"
|
|
:help="errorMessage"
|
|
>
|
|
<a-input v-bind="field" v-model:value="field.value" />
|
|
</a-form-item>
|
|
</vee-field>
|
|
<vee-field name="email" v-slot="{ field, errorMessage, value }">
|
|
<a-form-item
|
|
label="Email address"
|
|
:name="field.name"
|
|
:validate-status="!!errorMessage ? 'error' : ''"
|
|
:help="errorMessage"
|
|
>
|
|
<a-input v-bind="field" v-model:value="field.value" />
|
|
</a-form-item>
|
|
</vee-field>
|
|
<vee-field name="password" v-slot="{ field, errorMessage, value }">
|
|
<a-form-item
|
|
label="Password"
|
|
:name="field.name"
|
|
:validate-status="!!errorMessage ? 'error' : ''"
|
|
:help="errorMessage"
|
|
>
|
|
<a-input-password v-bind="field" v-model:value="field.value" />
|
|
</a-form-item>
|
|
</vee-field>
|
|
|
|
<a-typography-title :level="4" :style="{ textAlign: 'center' }"
|
|
>Terms</a-typography-title
|
|
>
|
|
<div class="maxHeightScroller">
|
|
<div style="height: 100%">
|
|
<terms-of-services />
|
|
<vee-field
|
|
name="agree"
|
|
:unchecked-value="false"
|
|
type="checkbox"
|
|
v-slot="{ field, value, errorMessage }"
|
|
>
|
|
<a-checkbox
|
|
@update:checked="
|
|
(n) => {
|
|
setValues({ agree: n });
|
|
if (!recaptchaValue) execute();
|
|
}
|
|
"
|
|
>
|
|
I agree to the Terms and am <b>18 years of age or older.</b>
|
|
</a-checkbox>
|
|
<div style="color: red">{{ errorMessage }}</div>
|
|
</vee-field>
|
|
</div>
|
|
</div>
|
|
<div ref="root" />
|
|
<a-row :align="'middle'" justify="center">
|
|
<a-col>
|
|
<a-button size="large" type="primary" html-type="submit"
|
|
>Sign me up!</a-button
|
|
>
|
|
</a-col>
|
|
</a-row>
|
|
</form>
|
|
</template>
|
|
<style scoped>
|
|
.maxHeightScroller {
|
|
max-height: 400px;
|
|
overflow-y: scroll;
|
|
display: block;
|
|
}
|
|
</style>
|