mirror of
https://github.com/formbricks/formbricks.git
synced 2026-04-29 03:13:19 -05:00
feat: Add last used indicator on login page (#3376)
Co-authored-by: Piyush Gupta <piyushguptaa2z123@gmail.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import { useRouter, useSearchParams } from "next/navigation";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { Controller, FormProvider, SubmitHandler, useForm } from "react-hook-form";
|
||||
import { cn } from "@formbricks/lib/cn";
|
||||
import { FORMBRICKS_LOGGED_IN_WITH_LS } from "@formbricks/lib/localStorage";
|
||||
import { Button } from "@formbricks/ui/components/Button";
|
||||
import { PasswordInput } from "@formbricks/ui/components/PasswordInput";
|
||||
import { AzureButton } from "@formbricks/ui/components/SignupOptions/components/AzureButton";
|
||||
@@ -53,7 +54,9 @@ export const SigninForm = ({
|
||||
const callbackUrl = searchParams?.get("callbackUrl");
|
||||
const onSubmit: SubmitHandler<TSigninFormState> = async (data) => {
|
||||
setLoggingIn(true);
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
localStorage.setItem(FORMBRICKS_LOGGED_IN_WITH_LS, "Email");
|
||||
}
|
||||
try {
|
||||
const signInResponse = await signIn("credentials", {
|
||||
callbackUrl: callbackUrl ?? "/",
|
||||
@@ -104,6 +107,13 @@ export const SigninForm = ({
|
||||
const formRef = useRef<HTMLFormElement>(null);
|
||||
const error = searchParams?.get("error");
|
||||
const inviteToken = callbackUrl ? new URL(callbackUrl).searchParams.get("token") : null;
|
||||
const [lastLoggedInWith, setLastLoginWith] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window !== "undefined") {
|
||||
setLastLoginWith(localStorage.getItem(FORMBRICKS_LOGGED_IN_WITH_LS) || "");
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (error) {
|
||||
@@ -139,6 +149,7 @@ export const SigninForm = ({
|
||||
<FormProvider {...formMethods}>
|
||||
<div className="text-center">
|
||||
<h1 className="mb-4 text-slate-700">{formLabel}</h1>
|
||||
|
||||
<div className="space-y-2">
|
||||
<form onSubmit={formMethods.handleSubmit(onSubmit)} className="space-y-2">
|
||||
{TwoFactorComponent}
|
||||
@@ -209,34 +220,41 @@ export const SigninForm = ({
|
||||
formRef.current.requestSubmit();
|
||||
}
|
||||
}}
|
||||
className="w-full justify-center"
|
||||
className="relative w-full justify-center"
|
||||
loading={loggingIn}>
|
||||
{totpLogin ? "Submit" : "Login with Email"}
|
||||
{lastLoggedInWith && lastLoggedInWith === "Email" ? (
|
||||
<span className="absolute right-3 text-xs">Last Used</span>
|
||||
) : null}
|
||||
</Button>
|
||||
)}
|
||||
</form>
|
||||
|
||||
{googleOAuthEnabled && !totpLogin && (
|
||||
<>
|
||||
<GoogleButton inviteUrl={callbackUrl} />
|
||||
<GoogleButton inviteUrl={callbackUrl} lastUsed={lastLoggedInWith === "Google"} />
|
||||
</>
|
||||
)}
|
||||
|
||||
{githubOAuthEnabled && !totpLogin && (
|
||||
<>
|
||||
<GithubButton inviteUrl={callbackUrl} />
|
||||
<GithubButton inviteUrl={callbackUrl} lastUsed={lastLoggedInWith === "Github"} />
|
||||
</>
|
||||
)}
|
||||
|
||||
{azureOAuthEnabled && !totpLogin && (
|
||||
<>
|
||||
<AzureButton inviteUrl={callbackUrl} />
|
||||
<AzureButton inviteUrl={callbackUrl} lastUsed={lastLoggedInWith === "Azure"} />
|
||||
</>
|
||||
)}
|
||||
|
||||
{oidcOAuthEnabled && !totpLogin && (
|
||||
<>
|
||||
<OpenIdButton inviteUrl={callbackUrl} text={`Continue with ${oidcDisplayName}`} />
|
||||
<OpenIdButton
|
||||
inviteUrl={callbackUrl}
|
||||
text={`Continue with ${oidcDisplayName}`}
|
||||
lastUsed={lastLoggedInWith === "OpenID"}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import formbricks from "@formbricks/js";
|
||||
import { env } from "@formbricks/lib/env";
|
||||
import { FORMBRICKS_LOGGED_IN_WITH_LS } from "@formbricks/lib/localStorage";
|
||||
|
||||
export const formbricksEnabled =
|
||||
typeof env.NEXT_PUBLIC_FORMBRICKS_API_HOST && env.NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID;
|
||||
|
||||
export const formbricksLogout = async () => {
|
||||
const loggedInWith = localStorage.getItem(FORMBRICKS_LOGGED_IN_WITH_LS);
|
||||
localStorage.clear();
|
||||
if (loggedInWith) {
|
||||
localStorage.setItem(FORMBRICKS_LOGGED_IN_WITH_LS, loggedInWith);
|
||||
}
|
||||
return await formbricks.logout();
|
||||
};
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
export const FORMBRICKS_SURVEYS_FILTERS_KEY_LS = "formbricks-surveys-filters";
|
||||
export const FORMBRICKS_ENVIRONMENT_ID_LS = "formbricks-environment-id";
|
||||
export const FORMBRICKS_LOGGED_IN_WITH_LS = "formbricks-logged-in-with";
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { signIn } from "next-auth/react";
|
||||
import { useCallback, useEffect } from "react";
|
||||
import { FORMBRICKS_LOGGED_IN_WITH_LS } from "@formbricks/lib/localStorage";
|
||||
import { Button } from "../../Button";
|
||||
import { MicrosoftIcon } from "../../icons";
|
||||
|
||||
@@ -7,12 +8,18 @@ export const AzureButton = ({
|
||||
text = "Continue with Azure",
|
||||
inviteUrl,
|
||||
directRedirect = false,
|
||||
lastUsed,
|
||||
}: {
|
||||
text?: string;
|
||||
inviteUrl?: string | null;
|
||||
directRedirect?: boolean;
|
||||
lastUsed?: boolean;
|
||||
}) => {
|
||||
const handleLogin = useCallback(async () => {
|
||||
if (typeof window !== "undefined") {
|
||||
localStorage.setItem(FORMBRICKS_LOGGED_IN_WITH_LS, "Azure");
|
||||
}
|
||||
|
||||
await signIn("azure-ad", {
|
||||
redirect: true,
|
||||
callbackUrl: inviteUrl ? inviteUrl : "/",
|
||||
@@ -32,8 +39,9 @@ export const AzureButton = ({
|
||||
startIconClassName="ml-2"
|
||||
onClick={handleLogin}
|
||||
variant="secondary"
|
||||
className="w-full justify-center">
|
||||
className="relative w-full justify-center">
|
||||
{text}
|
||||
{lastUsed && <span className="absolute right-3 text-xs">Last Used</span>}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
"use client";
|
||||
|
||||
import { signIn } from "next-auth/react";
|
||||
import { FORMBRICKS_LOGGED_IN_WITH_LS } from "@formbricks/lib/localStorage";
|
||||
import { Button } from "../../Button";
|
||||
import { GithubIcon } from "../../icons";
|
||||
|
||||
export const GithubButton = ({
|
||||
text = "Continue with Github",
|
||||
inviteUrl,
|
||||
lastUsed,
|
||||
}: {
|
||||
text?: string;
|
||||
inviteUrl?: string | null;
|
||||
lastUsed?: boolean;
|
||||
}) => {
|
||||
const handleLogin = async () => {
|
||||
if (typeof window !== "undefined") {
|
||||
localStorage.setItem(FORMBRICKS_LOGGED_IN_WITH_LS, "Github");
|
||||
}
|
||||
await signIn("github", {
|
||||
redirect: true,
|
||||
callbackUrl: inviteUrl ? inviteUrl : "/", // redirect after login to /
|
||||
@@ -25,8 +31,9 @@ export const GithubButton = ({
|
||||
startIconClassName="ml-2"
|
||||
onClick={handleLogin}
|
||||
variant="secondary"
|
||||
className="w-full justify-center">
|
||||
className="relative w-full justify-center">
|
||||
{text}
|
||||
{lastUsed && <span className="absolute right-3 text-xs">Last Used</span>}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
"use client";
|
||||
|
||||
import { signIn } from "next-auth/react";
|
||||
import { FORMBRICKS_LOGGED_IN_WITH_LS } from "@formbricks/lib/localStorage";
|
||||
import { Button } from "../../Button";
|
||||
import { GoogleIcon } from "../../icons";
|
||||
|
||||
export const GoogleButton = ({
|
||||
text = "Continue with Google",
|
||||
inviteUrl,
|
||||
lastUsed,
|
||||
}: {
|
||||
text?: string;
|
||||
inviteUrl?: string | null;
|
||||
lastUsed?: boolean;
|
||||
}) => {
|
||||
const handleLogin = async () => {
|
||||
if (typeof window !== "undefined") {
|
||||
localStorage.setItem(FORMBRICKS_LOGGED_IN_WITH_LS, "Google");
|
||||
}
|
||||
await signIn("google", {
|
||||
redirect: true,
|
||||
callbackUrl: inviteUrl ? inviteUrl : "/", // redirect after login to /
|
||||
@@ -25,8 +31,9 @@ export const GoogleButton = ({
|
||||
startIconClassName="ml-3"
|
||||
onClick={handleLogin}
|
||||
variant="secondary"
|
||||
className="w-full justify-center">
|
||||
className="relative w-full justify-center">
|
||||
{text}
|
||||
{lastUsed && <span className="absolute right-3 text-xs">Last Used</span>}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
import { signIn } from "next-auth/react";
|
||||
import { useCallback, useEffect } from "react";
|
||||
import { FORMBRICKS_LOGGED_IN_WITH_LS } from "@formbricks/lib/localStorage";
|
||||
import { Button } from "../../Button";
|
||||
|
||||
export const OpenIdButton = ({
|
||||
text = "Continue with OpenId Connect",
|
||||
inviteUrl,
|
||||
directRedirect = false,
|
||||
lastUsed,
|
||||
}: {
|
||||
text?: string;
|
||||
inviteUrl?: string | null;
|
||||
directRedirect?: boolean;
|
||||
lastUsed?: boolean;
|
||||
}) => {
|
||||
const handleLogin = useCallback(async () => {
|
||||
if (typeof window !== "undefined") {
|
||||
localStorage.setItem(FORMBRICKS_LOGGED_IN_WITH_LS, "OpenID");
|
||||
}
|
||||
await signIn("openid", {
|
||||
redirect: true,
|
||||
callbackUrl: inviteUrl ? inviteUrl : "/",
|
||||
@@ -30,8 +36,9 @@ export const OpenIdButton = ({
|
||||
startIconClassName="ml-2"
|
||||
onClick={handleLogin}
|
||||
variant="secondary"
|
||||
className="w-full justify-center">
|
||||
className="relative w-full justify-center">
|
||||
{text}
|
||||
{lastUsed && <span className="absolute right-3 text-xs">Last Used</span>}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user