Files
community-rule/app/contexts/AuthModalContext.tsx
T

110 lines
2.8 KiB
TypeScript

"use client";
import {
createContext,
useCallback,
useContext,
useMemo,
useState,
type ReactNode,
} from "react";
import { useTranslation } from "./MessagesContext";
import Login from "../components/modals/Login";
import LoginForm from "../components/modals/Login/LoginForm";
export type AuthModalLoginVariant =
| "default"
| "saveProgress"
| "keepRule"
| "invite";
export type AuthModalBackdropVariant = "solid" | "blurredYellow";
export type OpenLoginOptions = {
variant?: AuthModalLoginVariant;
/** Passed to `requestMagicLink` as `next` (internal path). */
nextPath?: string;
backdropVariant?: AuthModalBackdropVariant;
/**
* `keepRule` only: **Continue without saving**. Default is close the overlay.
* Guest completed Save & Exit passes leave-the-flow.
*/
onDismiss?: () => void;
};
type AuthModalContextValue = {
openLogin: (_opts?: OpenLoginOptions) => void;
closeLogin: () => void;
};
const AuthModalContext = createContext<AuthModalContextValue | null>(null);
export function AuthModalProvider({ children }: { children: ReactNode }) {
const tLogin = useTranslation("pages.login");
const [open, setOpen] = useState(false);
const [opts, setOpts] = useState<OpenLoginOptions>({});
const openLogin = useCallback((o?: OpenLoginOptions) => {
setOpts(o ?? {});
setOpen(true);
}, []);
const closeLogin = useCallback(() => {
setOpen(false);
setOpts({});
}, []);
const value = useMemo(
() => ({ openLogin, closeLogin }),
[openLogin, closeLogin],
);
const backdropVariant = opts.backdropVariant ?? "blurredYellow";
const keepRuleDismiss =
opts.variant === "keepRule"
? () => {
const extra = opts.onDismiss;
closeLogin();
extra?.();
}
: undefined;
return (
<AuthModalContext.Provider value={value}>
{children}
<Login
isOpen={open}
onClose={closeLogin}
backdropVariant={backdropVariant}
usePortal
ariaLabelledBy="login-modal-heading"
belowCard={
opts.variant === "invite" ? (
<button
type="button"
onClick={closeLogin}
className="w-full text-center text-small-paragraph text-[var(--color-content-default-tertiary)]"
>
{tLogin("backToYourRule")}
</button>
) : undefined
}
>
<LoginForm
variant={opts.variant ?? "default"}
magicLinkNextPath={opts.nextPath}
onDismiss={keepRuleDismiss}
/>
</Login>
</AuthModalContext.Provider>
);
}
export function useAuthModal(): AuthModalContextValue {
const ctx = useContext(AuthModalContext);
if (!ctx) {
throw new Error("useAuthModal must be used within AuthModalProvider");
}
return ctx;
}