feat(pages): create registration page
This commit is contained in:
		
							parent
							
								
									bed696b8ae
								
							
						
					
					
						commit
						3bfa7611bc
					
				
							
								
								
									
										195
									
								
								pages/register.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								pages/register.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,195 @@ | |||||||
|  | <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 "~/lib/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) => { | ||||||
|  | 		// log.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' : undefined" | ||||||
|  | 				: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' : undefined" | ||||||
|  | 				: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' : undefined" | ||||||
|  | 				: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> | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user