From 80299d2906ff6421d59292c4f95c7a24f0ab27a8 Mon Sep 17 00:00:00 2001 From: RajuGangitla Date: Sat, 12 Oct 2024 11:17:55 +0530 Subject: [PATCH] feat: added last_used in login page (#718) * added last_used * improved last used * Update lib/webstorage.ts * Update lib/webstorage.ts * Update lib/webstorage.ts --------- Co-authored-by: Marc Seitz <4049052+mfts@users.noreply.github.com> --- app/(auth)/login/page.tsx | 145 ++++++++++++++++++------------- components/hooks/useLastUsed.tsx | 42 +++++++++ lib/webstorage.ts | 36 ++++++++ 3 files changed, 164 insertions(+), 59 deletions(-) create mode 100644 components/hooks/useLastUsed.tsx create mode 100644 lib/webstorage.ts diff --git a/app/(auth)/login/page.tsx b/app/(auth)/login/page.tsx index fe9d578c4..9837e03a0 100644 --- a/app/(auth)/login/page.tsx +++ b/app/(auth)/login/page.tsx @@ -15,9 +15,17 @@ import Passkey from "@/components/shared/icons/passkey"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; +import { LastUsed, useLastUsed } from "@/components/hooks/useLastUsed"; +import { Loader } from "lucide-react"; export default function Login() { const { next } = useParams as { next?: string }; + + const [isLoginWithEmail, setIsLoginWithEmail] = useState(false); + const [isLoginWithGoogle, setIsLoginWithGoogle] = useState(false); + const [isLoginWithLinkedIn, setIsLoginWithLinkedIn] = + useState(false); + const [lastUsed, setLastUsed] = useLastUsed(); const authMethods = ["google", "email", "linkedin", "passkey"] as const; type AuthMethod = (typeof authMethods)[number]; const [clickedMethod, setClickedMethod] = useState( @@ -28,6 +36,7 @@ export default function Login() { "Continue with Email", ); + return (
{/* Left part */} @@ -59,6 +68,7 @@ export default function Login() { }).then((res) => { if (res?.ok && !res?.error) { setEmail(""); + setLastUsed("credentials") setEmailButtonText("Email sent - check your inbox!"); toast.success("Email sent - check your inbox!"); } else { @@ -97,69 +107,86 @@ export default function Login() { )} Continue with Email */} - + } w-full focus:shadow-outline transform rounded px-4 py-2 text-white transition-colors duration-300 ease-in-out focus:outline-none`} + > + {emailButtonText} + {lastUsed === "credentials" && } + +

or

- - - +
+ +
+
+ +
+
+ +

By clicking continue, you acknowledge that you have read and agree @@ -212,6 +239,6 @@ export default function Login() { - + ); } diff --git a/components/hooks/useLastUsed.tsx b/components/hooks/useLastUsed.tsx new file mode 100644 index 000000000..428961b24 --- /dev/null +++ b/components/hooks/useLastUsed.tsx @@ -0,0 +1,42 @@ +import { classNames } from "@/lib/utils"; +import { localStorage } from "@/lib/webstorage"; +import { useState, useEffect } from "react"; + + + + +type LoginType = "saml" | "google" | "credentials" | "linkedin"; + +export function useLastUsed() { + const [lastUsed, setLastUsed] = useState(); + + useEffect(() => { + const storedValue = localStorage.getItem("last_papermark_login"); + if (storedValue) { + setLastUsed(storedValue as LoginType); + } + }, []); + + useEffect(() => { + if (lastUsed) { + localStorage.setItem("last_papermark_login", lastUsed); + } else { + localStorage.removeItem("last_papermark_login"); + } + }, [lastUsed]); + + return [lastUsed, setLastUsed] as const; +} + +export const LastUsed = ({ className }: { className?: string | undefined }) => { + return ( + <> +

+
+ Last used +
+
+
+ + ); +}; diff --git a/lib/webstorage.ts b/lib/webstorage.ts new file mode 100644 index 000000000..d3a090efa --- /dev/null +++ b/lib/webstorage.ts @@ -0,0 +1,36 @@ +/** + * Provides a wrapper around localStorage(and sessionStorage(TODO when needed)) to avoid errors in case of restricted storage access. + * + * TODO: In case of an embed if localStorage is not available(third party), use localStorage of parent(first party) that contains the iframe. + */ +export const localStorage = { + getItem(key: string) { + try { + // eslint-disable-next-line + return window.localStorage.getItem(key); + } catch (e) { + // In case storage is restricted. Possible reasons + // 1. Third Party Context in Chrome Incognito mode. + return null; + } + }, + setItem(key: string, value: string) { + try { + // eslint-disable-next-line + window.localStorage.setItem(key, value); + } catch (e) { + // In case storage is restricted. Possible reasons + // 1. Third Party Context in Chrome Incognito mode. + // 2. Storage limit reached + return; + } + }, + removeItem: (key: string) => { + try { + // eslint-disable-next-line + window.localStorage.removeItem(key); + } catch (e) { + return; + } + }, +};