@oberoncms/core
Version:
OberonCMS is a cloud deployable CMS written in typescript based on the Puck visual editor
147 lines (146 loc) • 4.84 kB
JavaScript
"use client";
import { jsx, jsxs } from "react/jsx-runtime";
import { Form, FormField, FormItem, FormLabel, FormControl } from "@tohuhono/ui/form";
import { z } from "zod";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { Input } from "@tohuhono/ui/input";
import { Button } from "@tohuhono/ui/button";
import { InputOTP, InputOTPGroup, InputOTPSlot } from "@tohuhono/ui/input-otp";
import { useRouter } from "next/navigation";
import { useState } from "react";
import { useDebouncedCallback } from "use-debounce";
import { cn } from "@tohuhono/utils";
import { useToast } from "@tohuhono/ui/toast";
import { useOberonActions } from "../hooks/use-oberon.js";
const LoginSchema = z.object({
email: z.string().email(),
token: z.string().max(6).optional()
});
function Login({
callbackUrl,
email,
token
}) {
const { signIn } = useOberonActions();
const router = useRouter();
const { toast } = useToast();
const form = useForm({
resolver: zodResolver(LoginSchema),
defaultValues: {
email,
token
}
});
const [sending, setSending] = useState(false);
const [submitting, setSubmitting] = useState(false);
const [sent, setSent] = useState(!!email && !!token);
const debouncedSetSending = useDebouncedCallback(
(loading) => setSending(loading),
3e3
);
const sendOnCLick = form.handleSubmit(async ({ email: email2 }) => {
setSending(true);
try {
await signIn({
email: typeof email2 === "string" ? email2 : ""
});
form.resetField("token");
setSent(true);
} catch (error) {
setSending(false);
throw error;
}
toast({
title: `Token sent to ${email2}`,
description: "Please check your emails"
});
debouncedSetSending(false);
});
const tokenOnClick = form.handleSubmit(async ({ email: email2, token: token2 }) => {
setSubmitting(true);
const response = await fetch(
`/cms/api/auth/callback/email?email=${email2}&token=${token2}`
);
if (response.ok) {
router.push(callbackUrl || "/cms/pages");
}
if (!response.ok) {
toast({
variant: "destructive",
title: "Authentication failed",
description: "Please check your credentials and try again"
});
}
form.resetField("token");
setSubmitting(false);
});
return /* @__PURE__ */ jsx("div", { className: "grid h-screen place-content-center gap-3", children: /* @__PURE__ */ jsx(Form, { ...form, children: /* @__PURE__ */ jsxs("form", { className: "contents", children: [
/* @__PURE__ */ jsx(
FormField,
{
control: form.control,
name: "email",
render: ({ field }) => {
var _a;
return /* @__PURE__ */ jsxs(FormItem, { children: [
/* @__PURE__ */ jsx(FormLabel, { children: ((_a = form.formState.errors.email) == null ? void 0 : _a.message) ?? "Email adress" }),
/* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(Input, { ...field }) })
] });
}
}
),
/* @__PURE__ */ jsx(
FormField,
{
control: form.control,
name: "token",
render: ({ field }) => /* @__PURE__ */ jsx(
FormItem,
{
className: cn(sent ? "visible animate-fade-in" : "hidden"),
children: /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(InputOTP, { maxLength: 6, ...field, children: /* @__PURE__ */ jsxs(InputOTPGroup, { children: [
/* @__PURE__ */ jsx(InputOTPSlot, { index: 0 }),
/* @__PURE__ */ jsx(InputOTPSlot, { index: 1 }),
/* @__PURE__ */ jsx(InputOTPSlot, { index: 2 }),
/* @__PURE__ */ jsx(InputOTPSlot, { index: 3 }),
/* @__PURE__ */ jsx(InputOTPSlot, { index: 4 }),
/* @__PURE__ */ jsx(InputOTPSlot, { index: 5 })
] }) }) })
}
)
}
),
!sent && /* @__PURE__ */ jsx(Button, { disabled: sending, variant: "default", onClick: sendOnCLick, children: "Sign in" }),
/* @__PURE__ */ jsx(
Button,
{
disabled: submitting,
className: cn(
"pt-2",
sent ? "visible animate-fade-in" : "collapse",
sending ? "transition-none" : "transition-opacity"
),
onClick: tokenOnClick,
children: "Complete Sign in"
}
),
/* @__PURE__ */ jsx(
Button,
{
disabled: sending,
className: cn(
"animate-fade-in-half duration-1000",
sent ? "visible" : "collapse",
sending ? "transition-none" : "transition-opacity"
),
variant: "secondary",
onClick: sendOnCLick,
children: "Resend OTP Token"
}
)
] }) }) });
}
export {
Login
};