feat: 更新邮箱验证逻辑,添加用户姓名字段,优化组件交互
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
<script lang='ts' setup>
|
<script lang='ts' setup>
|
||||||
|
import type { InputCustomEvent } from "@ionic/vue";
|
||||||
import { toastController } from "@ionic/vue";
|
import { toastController } from "@ionic/vue";
|
||||||
import { logoGoogle, phonePortraitOutline } from "ionicons/icons";
|
import { logoGoogle, phonePortraitOutline } from "ionicons/icons";
|
||||||
import { authClient } from "@/auth";
|
import { authClient } from "@/auth";
|
||||||
@@ -8,31 +9,31 @@ const emit = defineEmits<{
|
|||||||
}>();
|
}>();
|
||||||
|
|
||||||
const model = defineModel({ type: String, required: true });
|
const model = defineModel({ type: String, required: true });
|
||||||
|
const inputInstance = useTemplateRef<InputInstance>("inputInstance");
|
||||||
|
|
||||||
function onEmailBlur() {
|
function markTouched() {
|
||||||
const isEmailValid = emailPattern.test(model.value);
|
inputInstance.value?.$el.classList.add("ion-touched");
|
||||||
if (!isEmailValid) {
|
|
||||||
toastController
|
|
||||||
.create({
|
|
||||||
message: "Please enter a valid email address.",
|
|
||||||
duration: 1500,
|
|
||||||
position: "bottom",
|
|
||||||
})
|
|
||||||
.then((toast) => {
|
|
||||||
toast.present();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
async function submitSendVerification() {
|
function validate(value: string) {
|
||||||
const isEmailValid = emailPattern.test(model.value);
|
inputInstance.value?.$el.classList.remove("ion-valid");
|
||||||
if (!isEmailValid) {
|
inputInstance.value?.$el.classList.remove("ion-invalid");
|
||||||
const toast = await toastController.create({
|
|
||||||
message: "Please enter a valid email address.",
|
|
||||||
duration: 1500,
|
|
||||||
position: "bottom",
|
|
||||||
});
|
|
||||||
|
|
||||||
await toast.present();
|
if (value === "") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const isEmailValid = emailPattern.test(model.value);
|
||||||
|
|
||||||
|
isEmailValid ? inputInstance.value?.$el.classList.add("ion-valid") : inputInstance.value?.$el.classList.add("ion-invalid");
|
||||||
|
|
||||||
|
return isEmailValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function submitSendVerification() {
|
||||||
|
const isEmailValid = validate(model.value);
|
||||||
|
if (!isEmailValid) {
|
||||||
|
inputInstance.value?.$el.classList.remove("ion-invalid");
|
||||||
|
inputInstance.value?.$el.classList.add("ion-invalid");
|
||||||
|
inputInstance.value?.$el.classList.add("ion-touched");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +61,7 @@ async function submitSendVerification() {
|
|||||||
<p>You'll use this email to login and access everything we have to offer.</p>
|
<p>You'll use this email to login and access everything we have to offer.</p>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<ui-input v-model="model" type="email" placeholder="Enter your email address" @ion-blur="onEmailBlur" />
|
<ui-input ref="inputInstance" v-model="model" type="email" placeholder="email@example.com" error-text="Please enter a valid email address." @ion-input="validate($event.target.value as string)" @ion-blur="markTouched" />
|
||||||
|
|
||||||
<ion-button expand="block" class="ion-margin-top" shape="round" @click="submitSendVerification">
|
<ion-button expand="block" class="ion-margin-top" shape="round" @click="submitSendVerification">
|
||||||
Sign up
|
Sign up
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
<script lang='ts' setup>
|
<script lang='ts' setup>
|
||||||
|
import type { PropType } from "vue";
|
||||||
|
import type { AuthUserSignup } from "@/auth/type";
|
||||||
import { toastController } from "@ionic/vue";
|
import { toastController } from "@ionic/vue";
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
email: string;
|
|
||||||
}>();
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: "success", value: string): void;
|
(e: "success", value: AuthUserSignup): void;
|
||||||
}>();
|
}>();
|
||||||
const model = defineModel({ type: String, required: true });
|
const model = defineModel({ type: Object as PropType<AuthUserSignup>, required: true });
|
||||||
|
|
||||||
async function submitSignup() {
|
async function submitSignup() {
|
||||||
if (model.value.length !== 6) {
|
if (model.value.verificationCode.length !== 6) {
|
||||||
const toast = await toastController.create({
|
const toast = await toastController.create({
|
||||||
message: "Please enter a valid 6-digit verification code.",
|
message: "Please enter a valid 6-digit verification code.",
|
||||||
duration: 1500,
|
duration: 1500,
|
||||||
@@ -27,12 +26,16 @@ async function submitSignup() {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<h1><strong>Verify your email</strong></h1>
|
<h1><strong>Verify your email</strong></h1>
|
||||||
<p>We have sent a verification code to {{ email }}. Please enter the code below to verify your email address.</p>
|
<p>We have sent a verification code to {{ model.email }}. Please enter the code below to verify your email address.</p>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<ion-item>
|
<ion-input-otp v-model="model.verificationCode" :length="6" />
|
||||||
<ion-input-otp v-model="model" :length="6" />
|
<!--
|
||||||
</ion-item>
|
<ui-input v-model="model.name" placeholder="Name" />
|
||||||
|
|
||||||
|
<ui-input v-model="model.password" placeholder="Password" />
|
||||||
|
|
||||||
|
<ui-input v-model="model.confirmPassword" placeholder="Confirm Password" /> -->
|
||||||
|
|
||||||
<ion-button expand="block" class="ion-margin-top" shape="round" @click="submitSignup">
|
<ion-button expand="block" class="ion-margin-top" shape="round" @click="submitSignup">
|
||||||
Submit
|
Submit
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import Step1 from "./email/step1.vue";
|
|||||||
import Step2 from "./email/step2.vue";
|
import Step2 from "./email/step2.vue";
|
||||||
|
|
||||||
const form = ref<AuthUserSignup>({
|
const form = ref<AuthUserSignup>({
|
||||||
|
name: "",
|
||||||
email: "",
|
email: "",
|
||||||
password: "",
|
password: "",
|
||||||
confirmPassword: "",
|
confirmPassword: "",
|
||||||
@@ -16,6 +17,7 @@ const step = ref(1);
|
|||||||
|
|
||||||
function reset() {
|
function reset() {
|
||||||
step.value = 1;
|
step.value = 1;
|
||||||
|
form.value.name = "";
|
||||||
form.value.email = "";
|
form.value.email = "";
|
||||||
form.value.password = "";
|
form.value.password = "";
|
||||||
form.value.confirmPassword = "";
|
form.value.confirmPassword = "";
|
||||||
@@ -52,7 +54,7 @@ async function submitSignup() {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Step1 v-if="step === 1" v-model="form.email" @success="step = 2" />
|
<Step1 v-if="step === 1" v-model="form.email" @success="step = 2" />
|
||||||
<Step2 v-else-if="step === 2" v-model="form.verificationCode" :email="form.email" @success="submitSignup" />
|
<Step2 v-else-if="step === 2" v-model="form" @success="submitSignup" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang='css' scoped></style>
|
<style lang='css' scoped></style>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
export interface AuthUserSignup {
|
export interface AuthUserSignup {
|
||||||
|
name: string;
|
||||||
email: string;
|
email: string;
|
||||||
password: string;
|
password: string;
|
||||||
confirmPassword: string;
|
confirmPassword: string;
|
||||||
|
|||||||
@@ -24,4 +24,7 @@ defineExpose({} as ComponentInstance<typeof IonInput>);
|
|||||||
--color: var(--ui-input-color, #000);
|
--color: var(--ui-input-color, #000);
|
||||||
--border-radius: 8px;
|
--border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
.ui-input + .ui-input {
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export const emailPattern = /^[^\s@]+@[^\s@][^\s.@]*\.[^\s@]+$/;
|
export const emailPattern = /^(?=.{1,254}$)(?=.{1,64}@)[\w!#$%&'*+/=?^`{|}~-]+(?:\.[\w!#$%&'*+/=?^`{|}~-]+)*@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i;
|
||||||
|
|||||||
@@ -1,13 +1,20 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { modelControllerSignup } from "@/auth";
|
import { authClient, modelControllerSignup } from "@/auth";
|
||||||
|
|
||||||
const page = useTemplateRef<PageInstance>("page");
|
const page = useTemplateRef<PageInstance>("page");
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
|
|
||||||
|
async function openSignin() {
|
||||||
|
const modal = await modelControllerSignup(page.value?.$el);
|
||||||
|
await modal.present();
|
||||||
|
}
|
||||||
async function openSignup() {
|
async function openSignup() {
|
||||||
const modal = await modelControllerSignup(page.value?.$el);
|
const modal = await modelControllerSignup(page.value?.$el);
|
||||||
await modal.present();
|
await modal.present();
|
||||||
}
|
}
|
||||||
|
async function handleLogout() {
|
||||||
|
await authClient.signOut();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -24,9 +31,15 @@ async function openSignup() {
|
|||||||
</IonToolbar>
|
</IonToolbar>
|
||||||
</IonHeader>
|
</IonHeader>
|
||||||
|
|
||||||
|
<IonButton @click="openSignin">
|
||||||
|
Signin
|
||||||
|
</IonButton>
|
||||||
<IonButton @click="openSignup">
|
<IonButton @click="openSignup">
|
||||||
Signup
|
Signup
|
||||||
</IonButton>
|
</IonButton>
|
||||||
|
<IonButton @click="handleLogout">
|
||||||
|
Log out
|
||||||
|
</IonButton>
|
||||||
|
|
||||||
{{ user }}
|
{{ user }}
|
||||||
</IonContent>
|
</IonContent>
|
||||||
|
|||||||
Reference in New Issue
Block a user