139 lines
3.9 KiB
Vue
139 lines
3.9 KiB
Vue
<script lang='ts' setup>
|
|
import { toastController } from "@ionic/vue";
|
|
import { Field, Form } from "vee-validate";
|
|
import IconParkOutlineInfo from "~icons/icon-park-outline/info";
|
|
import { authClient, emailSignupSchema } from "@/auth";
|
|
|
|
const { t } = useI18n();
|
|
const agreeToTerms = ref(false);
|
|
const route = useRoute();
|
|
|
|
async function handleSubmit(values: Record<string, any>) {
|
|
if (!agreeToTerms.value) {
|
|
toastController.create({
|
|
message: t("auth.signup.agreeTermsError"),
|
|
duration: 2000,
|
|
color: "danger",
|
|
}).then(toast => toast.present());
|
|
return;
|
|
}
|
|
try {
|
|
const { data } = await authClient.signUp.email({
|
|
name: values.name,
|
|
email: values.email,
|
|
password: values.password,
|
|
});
|
|
|
|
if (!data?.token) {
|
|
toastController.create({
|
|
message: t("auth.signup.signupFailed"),
|
|
duration: 2000,
|
|
color: "danger",
|
|
}).then(toast => toast.present());
|
|
}
|
|
else {
|
|
const userStore = useUserStore();
|
|
userStore.setToken(data.token);
|
|
userStore.updateProfile();
|
|
useNavigateToRedirect(route.query.redirect as string);
|
|
}
|
|
}
|
|
catch (err) {
|
|
toastController.create({
|
|
message: t("auth.signup.signupFailed"),
|
|
duration: 2000,
|
|
color: "danger",
|
|
}).then(toast => toast.present());
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<IonPage>
|
|
<IonHeader class="ion-no-border">
|
|
<IonToolbar class="ion-toolbar">
|
|
<ui-back-button slot="start" />
|
|
<ion-button slot="end" fill="clear" />
|
|
</IonToolbar>
|
|
</IonHeader>
|
|
<IonContent :fullscreen="true" class="ion-padding">
|
|
<div class="text-2xl font-semibold mb-8">
|
|
{{ t('auth.signup.title') }}
|
|
</div>
|
|
|
|
<Form :validation-schema="emailSignupSchema" class="mt-5" @submit="handleSubmit">
|
|
<Field v-slot="{ field, errorMessage }" name="name" type="text">
|
|
<div class="mb-4">
|
|
<ui-input
|
|
v-bind="field"
|
|
:placeholder="t('auth.signup.enterName')"
|
|
type="text"
|
|
/>
|
|
<div v-if="errorMessage" class="text-xs text-red-500 mt-1">
|
|
{{ errorMessage }}
|
|
</div>
|
|
</div>
|
|
</Field>
|
|
<Field v-slot="{ field, errorMessage }" name="email" type="email">
|
|
<div class="mb-4">
|
|
<ui-input
|
|
v-bind="field"
|
|
:placeholder="t('auth.signup.enterEmail')"
|
|
type="email"
|
|
/>
|
|
<div v-if="errorMessage" class="text-xs text-red-500 mt-1">
|
|
{{ errorMessage }}
|
|
</div>
|
|
</div>
|
|
</Field>
|
|
<Field v-slot="{ field, errorMessage }" name="password" type="password">
|
|
<div class="mb-4">
|
|
<ui-input
|
|
v-bind="field"
|
|
:placeholder="t('auth.signup.enterPassword')"
|
|
type="password"
|
|
/>
|
|
<div v-if="errorMessage" class="text-xs text-red-500 mt-1">
|
|
{{ errorMessage }}
|
|
</div>
|
|
</div>
|
|
</Field>
|
|
|
|
<ion-button
|
|
expand="block"
|
|
class="ion-margin-top"
|
|
shape="round"
|
|
type="submit"
|
|
>
|
|
{{ t('auth.login.signUpAndLogin') }}
|
|
</ion-button>
|
|
|
|
<ion-checkbox v-model="agreeToTerms" label-placement="end" class="mt-8 text-sm">
|
|
<span>{{ t('auth.login.agreeText') }}</span>
|
|
<a href="/auth/term" class="text-primary underline mx-2 underline-offset-3">
|
|
{{ t('auth.login.termsLink') }}
|
|
</a>
|
|
</ion-checkbox>
|
|
|
|
<div class="text-sm text-text-300 mt-1 flex items-center">
|
|
<IconParkOutlineInfo class="inline-block mr-1" />
|
|
{{ t('auth.login.autoRegisterTip') }}
|
|
</div>
|
|
</Form>
|
|
</IonContent>
|
|
</IonPage>
|
|
</template>
|
|
|
|
<style lang='css' scoped>
|
|
ion-checkbox {
|
|
--size: 18px;
|
|
}
|
|
ion-checkbox::part(label) {
|
|
margin-left: 4px;
|
|
}
|
|
|
|
.title {
|
|
margin-bottom: 30px;
|
|
}
|
|
</style>
|