|
@@ -0,0 +1,189 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <Form
|
|
|
|
|
+ class="flex flex-col gap-2 p-5"
|
|
|
|
|
+ v-slot="$form"
|
|
|
|
|
+ :initialValues="initialValues"
|
|
|
|
|
+ :resolver="resolver"
|
|
|
|
|
+ :validateOnValueUpdate="false"
|
|
|
|
|
+ :validateOnBlur="true"
|
|
|
|
|
+ @submit="onFormSubmit"
|
|
|
|
|
+ >
|
|
|
|
|
+ <div class="flex flex-col">
|
|
|
|
|
+ <label
|
|
|
|
|
+ for="signin_email"
|
|
|
|
|
+ class="ml-1 text-sm text-primary dark:text-primary"
|
|
|
|
|
+ >
|
|
|
|
|
+ Email Address
|
|
|
|
|
+ </label>
|
|
|
|
|
+
|
|
|
|
|
+ <InputText
|
|
|
|
|
+ name="email"
|
|
|
|
|
+ fluid
|
|
|
|
|
+ id="signin_email"
|
|
|
|
|
+ type="email"
|
|
|
|
|
+ placeholder="Email address"
|
|
|
|
|
+ autocomplete="email"
|
|
|
|
|
+ autofocus
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <Message
|
|
|
|
|
+ v-if="$form.email?.invalid"
|
|
|
|
|
+ severity="error"
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ variant="simple"
|
|
|
|
|
+ >
|
|
|
|
|
+ {{ $form.email?.error?.message }}
|
|
|
|
|
+ </Message>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="flex flex-col">
|
|
|
|
|
+ <label
|
|
|
|
|
+ for="signin_password"
|
|
|
|
|
+ class="ml-1 text-sm text-primary dark:text-primary"
|
|
|
|
|
+ >
|
|
|
|
|
+ Password
|
|
|
|
|
+ </label>
|
|
|
|
|
+
|
|
|
|
|
+ <Password
|
|
|
|
|
+ name="password"
|
|
|
|
|
+ :feedback="false"
|
|
|
|
|
+ fluid
|
|
|
|
|
+ inputId="signin_password"
|
|
|
|
|
+ toggleMask
|
|
|
|
|
+ autocomplete="current-password"
|
|
|
|
|
+ placeholder="Password"
|
|
|
|
|
+ >
|
|
|
|
|
+ <template #maskicon="{ toggleCallback }">
|
|
|
|
|
+ <Icon
|
|
|
|
|
+ class="absolute inset-e-3 top-1/2 -mt-2 h-4 w-4 text-surface-500
|
|
|
|
|
+ dark:text-surface-400"
|
|
|
|
|
+ name="ph:eye-slash-bold"
|
|
|
|
|
+ @click="toggleCallback"
|
|
|
|
|
+ />
|
|
|
|
|
+ </template>
|
|
|
|
|
+
|
|
|
|
|
+ <template #unmaskicon="{ toggleCallback }">
|
|
|
|
|
+ <Icon
|
|
|
|
|
+ class="absolute inset-e-3 top-1/2 -mt-2 h-4 w-4 text-surface-500
|
|
|
|
|
+ dark:text-surface-400"
|
|
|
|
|
+ name="ph:eye-bold"
|
|
|
|
|
+ @click="toggleCallback"
|
|
|
|
|
+ />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </Password>
|
|
|
|
|
+
|
|
|
|
|
+ <Message
|
|
|
|
|
+ v-if="$form.password?.invalid"
|
|
|
|
|
+ severity="error"
|
|
|
|
|
+ size="small"
|
|
|
|
|
+ variant="simple"
|
|
|
|
|
+ >
|
|
|
|
|
+ {{ $form.password?.error?.message }}
|
|
|
|
|
+ </Message>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <Button
|
|
|
|
|
+ label="Sign In"
|
|
|
|
|
+ type="submit"
|
|
|
|
|
+ fluid
|
|
|
|
|
+ :disabled="!$form.valid"
|
|
|
|
|
+ :loading="isLoading"
|
|
|
|
|
+ class="mt-5"
|
|
|
|
|
+ >
|
|
|
|
|
+ <template #icon>
|
|
|
|
|
+ <Icon name="ph:sign-in-bold" />
|
|
|
|
|
+ </template>
|
|
|
|
|
+
|
|
|
|
|
+ <template #loadingicon>
|
|
|
|
|
+ <Icon
|
|
|
|
|
+ class="animate-spin"
|
|
|
|
|
+ name="ph:circle-notch-bold"
|
|
|
|
|
+ />
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </Form>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="flex flex-col p-5 pt-0">
|
|
|
|
|
+ <Button
|
|
|
|
|
+ variant="text"
|
|
|
|
|
+ @click="resetPasswordRequest()"
|
|
|
|
|
+ >
|
|
|
|
|
+ Forgot Password
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script setup>
|
|
|
|
|
+import { zodResolver } from "@primeuix/forms/resolvers/zod"
|
|
|
|
|
+import { hydrateOnVisible } from "vue"
|
|
|
|
|
+
|
|
|
|
|
+const ResetPasswordRequestDialog = defineAsyncComponent({
|
|
|
|
|
+ loader: () => import("~/components/ResetPasswordRequestDialog.vue"),
|
|
|
|
|
+ hydrate: hydrateOnVisible()
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const { signIn } = useAuthClient()
|
|
|
|
|
+const dynamicDialog = useDynamicDialog()
|
|
|
|
|
+const toast = useToast()
|
|
|
|
|
+const dialogRef = inject("dialogRef")
|
|
|
|
|
+
|
|
|
|
|
+const resolver = ref(
|
|
|
|
|
+ zodResolver(
|
|
|
|
|
+ z.object({
|
|
|
|
|
+ email: z.email("Not an email address."),
|
|
|
|
|
+ password: z.string().min(1, "Password is required.")
|
|
|
|
|
+ })
|
|
|
|
|
+ )
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
|
|
+const isLoading = ref(false)
|
|
|
|
|
+const initialValues = ref({ email: "", password: "" })
|
|
|
|
|
+
|
|
|
|
|
+async function onFormSubmit({ valid, values }) {
|
|
|
|
|
+ if (valid) {
|
|
|
|
|
+ await signInWithPassword(values)
|
|
|
|
|
+ closeDialog()
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+async function signInWithPassword(values) {
|
|
|
|
|
+ if (isLoading.value) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ isLoading.value = true
|
|
|
|
|
+ const { error } = await signIn(values)
|
|
|
|
|
+ isLoading.value = false
|
|
|
|
|
+
|
|
|
|
|
+ if (error) {
|
|
|
|
|
+ console.error(error)
|
|
|
|
|
+
|
|
|
|
|
+ toast.add({
|
|
|
|
|
+ severity: "error",
|
|
|
|
|
+ summary: "SignIn Error.",
|
|
|
|
|
+ detail: error.data?.message || error.message
|
|
|
|
|
+ })
|
|
|
|
|
+ } else {
|
|
|
|
|
+ toast.add({
|
|
|
|
|
+ severity: "success",
|
|
|
|
|
+ summary: "Signed In.",
|
|
|
|
|
+ detail: "You are now signed in.",
|
|
|
|
|
+ life: 3000
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+async function resetPasswordRequest() {
|
|
|
|
|
+ closeDialog()
|
|
|
|
|
+ // noinspection JSUnresolvedReference
|
|
|
|
|
+ dynamicDialog.open(ResetPasswordRequestDialog)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function closeDialog() {
|
|
|
|
|
+ dialogRef.value.close()
|
|
|
|
|
+}
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped></style>
|