From 5697dfd7ee3fe817ad1828f5af2a618e392cd55c Mon Sep 17 00:00:00 2001 From: Yangshun Date: Thu, 7 Aug 2025 19:00:21 +0800 Subject: [PATCH] Revert "[web] auth: add sign up reminder card (#1582)" This reverts commit 28da8b950a18d7804dbfd73f755eaf043a3773fc. --- .../src/app/[locale]/(interviews)/layout.tsx | 2 - apps/web/src/app/[locale]/blog/layout.tsx | 2 - .../components/auth/AuthOneClickSignUp.tsx | 80 --------- .../auth/AuthOneClickSignupCard.tsx | 159 ------------------ apps/web/src/components/auth/SupabaseAuth.tsx | 1 + .../components/auth/SupabaseAuthSocial.tsx | 44 ++++- .../src/components/auth/useOAuthSignIn.tsx | 62 ------- .../common/layout/ProjectsRootLayout.tsx | 2 - apps/web/src/components/ui/Toast/Toast.tsx | 31 +--- 9 files changed, 46 insertions(+), 337 deletions(-) delete mode 100644 apps/web/src/components/auth/AuthOneClickSignUp.tsx delete mode 100644 apps/web/src/components/auth/AuthOneClickSignupCard.tsx delete mode 100644 apps/web/src/components/auth/useOAuthSignIn.tsx diff --git a/apps/web/src/app/[locale]/(interviews)/layout.tsx b/apps/web/src/app/[locale]/(interviews)/layout.tsx index 22292391a..7219fccba 100644 --- a/apps/web/src/app/[locale]/(interviews)/layout.tsx +++ b/apps/web/src/app/[locale]/(interviews)/layout.tsx @@ -1,5 +1,4 @@ import AuthGoogleOneTap from '~/components/auth/AuthGoogleOneTap'; -import AuthOneClickSignup from '~/components/auth/AuthOneClickSignUp'; type Props = Readonly<{ children: React.ReactNode; @@ -15,7 +14,6 @@ export default function InterviewsLayout({ children }: Props) { return ( <> {children} - ); diff --git a/apps/web/src/app/[locale]/blog/layout.tsx b/apps/web/src/app/[locale]/blog/layout.tsx index 17058d3c1..9462f8ed1 100644 --- a/apps/web/src/app/[locale]/blog/layout.tsx +++ b/apps/web/src/app/[locale]/blog/layout.tsx @@ -1,4 +1,3 @@ -import AuthOneClickSignup from '~/components/auth/AuthOneClickSignUp'; import BlogSidebarContainer from '~/components/blog/layout/BlogSidebarContainer'; import { GlobalBannerInterviews } from '~/components/global/banners/GlobalBannerInterviews'; import InterviewsFooter from '~/components/interviews/common/InterviewsFooter'; @@ -18,7 +17,6 @@ export default function BlogLayout({ children }: Props) { return ( <> -
diff --git a/apps/web/src/components/auth/AuthOneClickSignUp.tsx b/apps/web/src/components/auth/AuthOneClickSignUp.tsx deleted file mode 100644 index 5703b2662..000000000 --- a/apps/web/src/components/auth/AuthOneClickSignUp.tsx +++ /dev/null @@ -1,80 +0,0 @@ -'use client'; - -import { useSessionContext } from '@supabase/auth-helpers-react'; -import { useCallback, useEffect, useRef } from 'react'; -import { useSessionStorage } from 'usehooks-ts'; -import { useMediaQuery } from 'usehooks-ts'; - -import { useToast } from '~/components/global/toasts/useToast'; - -import { useI18nPathname } from '~/next-i18nostic/src'; - -import AuthOneClickSignupCard from './AuthOneClickSignupCard'; - -const SIGN_UP_TOAST_DELAY = 15_000; -const TOAST_DURATION = 60 * 60 * 1000; // 1 hour - -export default function AuthOneClickSignup() { - const isMobile = useMediaQuery('(max-width: 640px)'); - const { pathname } = useI18nPathname(); - const lastToastId = useRef(null); - const { dismissToast, showToast } = useToast(); - - const { isLoading: isUserLoading, session } = useSessionContext(); - const [dismissedSignUpPrompt, setDismissedSignUpPrompt] = - useSessionStorage('gfe:auth:sign-up-prompt', false); - - // Don't show it on homepage - const isHomepage = pathname === '/' || pathname === '/projects'; - - const handleClose = useCallback(() => { - setDismissedSignUpPrompt(true); - }, [setDismissedSignUpPrompt]); - - useEffect(() => { - if ( - session || - isUserLoading || - dismissedSignUpPrompt || - isHomepage || - isMobile - ) { - if (lastToastId.current) { - dismissToast(lastToastId.current); - } - - return; - } - - // Show popup after delay - const timer = setTimeout(() => { - const { id } = showToast({ - animateFrom: 'bottom', - customComponent: () => , - duration: TOAST_DURATION, - side: 'end', - variant: 'custom', - }); - - lastToastId.current = id; - }, SIGN_UP_TOAST_DELAY); - - return () => { - if (lastToastId.current) { - dismissToast(lastToastId.current); - } - clearTimeout(timer); - }; - }, [ - session, - isUserLoading, - dismissedSignUpPrompt, - isHomepage, - showToast, - handleClose, - dismissToast, - isMobile, - ]); - - return null; -} diff --git a/apps/web/src/components/auth/AuthOneClickSignupCard.tsx b/apps/web/src/components/auth/AuthOneClickSignupCard.tsx deleted file mode 100644 index efc71d726..000000000 --- a/apps/web/src/components/auth/AuthOneClickSignupCard.tsx +++ /dev/null @@ -1,159 +0,0 @@ -import clsx from 'clsx'; -import { useId } from 'react'; -import { FcGoogle } from 'react-icons/fc'; -import { RiCloseLine, RiGithubFill, RiMailLine } from 'react-icons/ri'; - -import { useAuthSignInUp } from '~/hooks/user/useAuthFns'; - -import { useToast } from '~/components/global/toasts/useToast'; -import { useIntl } from '~/components/intl'; -import Button from '~/components/ui/Button'; -import Text from '~/components/ui/Text'; -import { - themeTextFaintColor, - themeTextInvertColor, -} from '~/components/ui/theme'; - -import { useI18nPathname } from '~/next-i18nostic/src'; -import { mergeURLWithCurrentParamsHash } from '~/utils/merge-url-params-hash'; - -import { useOAuthSignIn } from './useOAuthSignIn'; - -type Props = Readonly<{ - onClose?: () => void; -}>; - -export default function AuthOneClickSignupCard({ onClose }: Props) { - const intl = useIntl(); - const descriptionId = useId(); - const titleId = useId(); - const { pathname } = useI18nPathname(); - const { signInUpHref } = useAuthSignInUp(); - const { showToast } = useToast(); - - const { loading, signInWithProvider } = useOAuthSignIn({ - next: mergeURLWithCurrentParamsHash(pathname ?? ''), - onError: (errorMessage) => { - showToast({ - title: - errorMessage || - intl.formatMessage({ - defaultMessage: 'Something went wrong', - description: 'Error message', - id: 'sbXDK4', - }), - variant: 'danger', - }); - }, - }); - - return ( -
-
- - {intl.formatMessage({ - defaultMessage: 'Join GreatFrontEnd in 1 click', - description: 'Auth card title', - id: 'Lsk0wX', - })} - -
- - {intl.formatMessage({ - defaultMessage: - 'The place for front end engineers. Upskill, ace interviews, get inspired.', - description: 'Auth card description', - id: 'n1m6Nx', - })} - -
-
-
- ); -} diff --git a/apps/web/src/components/auth/SupabaseAuth.tsx b/apps/web/src/components/auth/SupabaseAuth.tsx index 18016ced0..a0d54e103 100644 --- a/apps/web/src/components/auth/SupabaseAuth.tsx +++ b/apps/web/src/components/auth/SupabaseAuth.tsx @@ -220,6 +220,7 @@ export default function SupabaseAuth({ layout={socialLayout} next={next} providers={providers} + supabaseClient={supabaseClient} /> )}
diff --git a/apps/web/src/components/auth/SupabaseAuthSocial.tsx b/apps/web/src/components/auth/SupabaseAuthSocial.tsx index 225f94f74..60aaf576e 100644 --- a/apps/web/src/components/auth/SupabaseAuthSocial.tsx +++ b/apps/web/src/components/auth/SupabaseAuthSocial.tsx @@ -1,14 +1,16 @@ import type { Provider } from '@supabase/supabase-js'; import clsx from 'clsx'; +import { useState } from 'react'; import { RiGithubFill, RiGoogleFill } from 'react-icons/ri'; +import url from 'url'; import { useIntl } from '~/components/intl'; import Button from '~/components/ui/Button'; import logEvent from '~/logging/logEvent'; +import type { SupabaseClientGFE } from '~/supabase/SupabaseServerGFE'; import Alert from '../ui/Alert'; -import { useOAuthSignIn } from './useOAuthSignIn'; export type SupabaseProviderGFE = 'github' | 'google'; @@ -41,17 +43,49 @@ export type SocialAuthProps = { layout?: 'horizontal' | 'vertical'; next: string; providers?: Array; + supabaseClient: SupabaseClientGFE; }; export default function SupabaseAuthSocial({ layout, next, providers, + supabaseClient, }: SocialAuthProps) { const intl = useIntl(); - const { errorMessage, loading, signInWithProvider } = useOAuthSignIn({ - next, - }); + const [loading, setLoading] = useState(false); + const [errorMessage, setErrorMessage] = useState(''); + + async function handleProviderSignIn(provider: SupabaseProviderGFE) { + setLoading(true); + + const redirectTo = + window.location.origin + + url.format({ + pathname: '/auth/login-redirect', + query: { + next, + }, + }); + + const { error } = await supabaseClient.auth.signInWithOAuth({ + options: { redirectTo }, + provider, + }); + + if (error) { + setErrorMessage(error.message); + logEvent('auth.sign_in.fail', { + message: error.message, + name: error.name, + namespace: 'auth', + stack: error.stack, + type: provider, + }); + } + + setLoading(false); + } if (!providers || providers.length === 0) { return null; @@ -97,7 +131,7 @@ export default function SupabaseAuthSocial({ label, namespace: 'auth', }); - signInWithProvider(provider); + handleProviderSignIn(provider); }} />
diff --git a/apps/web/src/components/auth/useOAuthSignIn.tsx b/apps/web/src/components/auth/useOAuthSignIn.tsx deleted file mode 100644 index 71d4265cf..000000000 --- a/apps/web/src/components/auth/useOAuthSignIn.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { useState } from 'react'; -import url from 'url'; - -import logEvent from '~/logging/logEvent'; -import { i18nHref, useI18n } from '~/next-i18nostic/src'; -import { useSupabaseClientGFE } from '~/supabase/SupabaseClientGFE'; - -import type { SupabaseProviderGFE } from './SupabaseAuthSocial'; - -export function useOAuthSignIn(opts?: { - next?: string; - onError?: (errorMessage: string) => void; -}) { - const supabaseClient = useSupabaseClientGFE(); - const [loading, setLoading] = useState(false); - const [errorMessage, setErrorMessage] = useState(''); - const { locale } = useI18n(); - - async function signInWithProvider(provider: SupabaseProviderGFE) { - setLoading(true); - - const redirectTo = - window.location.origin + - url.format( - i18nHref( - { - pathname: '/auth/login-redirect', - query: { - next: opts?.next || window.location.pathname, - }, - }, - locale, - ), - ); - - const { error } = await supabaseClient.auth.signInWithOAuth({ - options: { redirectTo }, - provider, - }); - - setLoading(false); - - if (error) { - setErrorMessage(error.message); - opts?.onError?.(error.message); - - logEvent('auth.sign_in.fail', { - message: error.message, - name: error.name, - namespace: 'auth', - stack: error.stack, - type: provider, - }); - } - } - - return { - errorMessage, - loading, - signInWithProvider, - }; -} diff --git a/apps/web/src/components/projects/common/layout/ProjectsRootLayout.tsx b/apps/web/src/components/projects/common/layout/ProjectsRootLayout.tsx index 60c77a09f..a0ad6f42e 100644 --- a/apps/web/src/components/projects/common/layout/ProjectsRootLayout.tsx +++ b/apps/web/src/components/projects/common/layout/ProjectsRootLayout.tsx @@ -3,7 +3,6 @@ import { useEffect } from 'react'; import AuthGoogleOneTap from '~/components/auth/AuthGoogleOneTap'; -import AuthOneClickSignup from '~/components/auth/AuthOneClickSignUp'; import { ProductThemeScript } from '~/components/global/product-theme/ProductThemeScript'; import { useProductMenuUnseenIndicator } from '~/components/global/product-theme/useProductMenuUnseenIndicator'; @@ -26,7 +25,6 @@ export default function ProjectsRootLayout({ children }: Props) { <> - {children} ); diff --git a/apps/web/src/components/ui/Toast/Toast.tsx b/apps/web/src/components/ui/Toast/Toast.tsx index e04f9e287..8d0b1a39b 100644 --- a/apps/web/src/components/ui/Toast/Toast.tsx +++ b/apps/web/src/components/ui/Toast/Toast.tsx @@ -193,14 +193,10 @@ export const ToastImpl = React.forwardRef< 'data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)]', 'data-[swipe=move]:transition-none', 'data-[state=open]:animate-in', - props.animateFrom === 'left' - ? 'data-[state=open]:sm:slide-in-from-left-full' - : 'data-[state=open]:sm:slide-in-from-bottom-full', + 'data-[state=open]:sm:slide-in-from-left-full', 'data-[state=closed]:animate-out', 'data-[state=closed]:fade-out-80', - props.animateFrom === 'left' - ? 'data-[state=closed]:slide-out-to-left-full' - : 'data-[state=closed]:slide-out-to-bottom-full', + 'data-[state=closed]:slide-out-to-left-full', 'flex', props.side === 'start' && 'self-start', props.side === 'end' && 'self-end justify-end', @@ -210,7 +206,7 @@ export const ToastImpl = React.forwardRef< const { customComponent: Component, ...remainingProps } = props; return ( -
  • +
  • ); @@ -315,7 +311,7 @@ type BaseToastProps = Omit< React.ComponentPropsWithoutRef, 'children' | 'title' > & - Readonly<{ animateFrom?: 'bottom' | 'left'; side?: 'end' | 'start' }>; + Readonly<{ side?: 'end' | 'start' }>; export type DefaultToastProps = BaseToastProps & DefaultProps; @@ -328,24 +324,11 @@ const Toast = React.forwardRef< ToastProps >((props, ref) => { if (props.variant === 'custom') { - const { - animateFrom = 'left', - className, - customComponent, - side, - variant, - ...remainingProps - } = props; + const { customComponent, variant, ...remainingProps } = props; return ( - + ); } @@ -353,7 +336,6 @@ const Toast = React.forwardRef< const { addOnIcon, addOnLabel, - animateFrom = 'left', className, description, icon, @@ -370,7 +352,6 @@ const Toast = React.forwardRef<