Revert "[web] auth: add sign up reminder card (#1582)"

This reverts commit 28da8b950a.
This commit is contained in:
Yangshun 2025-08-07 19:00:21 +08:00
parent 3cdfa2f16a
commit 5697dfd7ee
9 changed files with 46 additions and 337 deletions

View File

@ -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}
<AuthOneClickSignup />
<AuthGoogleOneTap showOnMobileOnly={true} />
</>
);

View File

@ -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 (
<>
<GlobalBannerInterviews />
<AuthOneClickSignup />
<div className="flex flex-col">
<InterviewsNavbar />
<div className="flex">

View File

@ -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<string | null>(null);
const { dismissToast, showToast } = useToast();
const { isLoading: isUserLoading, session } = useSessionContext();
const [dismissedSignUpPrompt, setDismissedSignUpPrompt] =
useSessionStorage<boolean>('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: () => <AuthOneClickSignupCard onClose={handleClose} />,
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;
}

View File

@ -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 (
<div
aria-describedby={descriptionId}
aria-labelledby={titleId}
aria-modal="true"
className={clsx(
'w-full max-w-[294px]',
'rounded-lg',
'bg-neutral-800 dark:bg-white',
'border border-neutral-700 dark:border-neutral-200',
'px-4 pb-3 pt-4',
)}
role="dialog">
<div className="flex items-center justify-between gap-2">
<Text color="invert" id={titleId} size="body1" weight="bold">
{intl.formatMessage({
defaultMessage: 'Join GreatFrontEnd in 1 click',
description: 'Auth card title',
id: 'Lsk0wX',
})}
</Text>
<Button
className="group/button transition-all"
icon={RiCloseLine}
iconClassName={clsx(
themeTextInvertColor,
'group-hover/button:text-neutral-900 dark:group-hover/button:text-white',
)}
isLabelHidden={true}
label="Close"
size="xs"
variant="tertiary"
onClick={onClose}
/>
</div>
<Text
className="mb-4 mt-3 block"
color="invert"
id={descriptionId}
size="body3">
{intl.formatMessage({
defaultMessage:
'The place for front end engineers. Upskill, ace interviews, get inspired.',
description: 'Auth card description',
id: 'n1m6Nx',
})}
</Text>
<div className="flex items-center gap-2.5">
<Button
display="block"
icon={FcGoogle}
isDisabled={loading}
isLoading={loading}
label={intl.formatMessage({
defaultMessage: 'Sign up with',
description: 'Auth card button label',
id: 'z9Ymn4',
})}
variant="secondary"
onClick={() => signInWithProvider('google')}
/>
<Button
className="group/button transition-all"
icon={RiGithubFill}
iconClassName={clsx(
themeTextInvertColor,
'group-hover/button:text-neutral-900 dark:group-hover/button:text-white',
)}
isLabelHidden={true}
isLoading={loading}
label={intl.formatMessage({
defaultMessage: 'Sign up with Github',
description: 'Auth card button label',
id: 'iwMZfR',
})}
variant="tertiary"
onClick={() => signInWithProvider('github')}
/>
<Text className={themeTextFaintColor} color="inherit" size="body2">
{intl.formatMessage({
defaultMessage: 'or',
description: 'Label for or',
id: 'ZEPn1r',
})}
</Text>
<Button
className="group/button transition-all"
href={signInUpHref({
query: {
view: 'email',
},
})}
icon={RiMailLine}
iconClassName={clsx(
themeTextInvertColor,
'group-hover/button:text-neutral-900 dark:group-hover/button:text-white',
)}
isDisabled={loading}
isLabelHidden={true}
label={intl.formatMessage({
defaultMessage: 'Sign up with email',
description: 'Auth card button label',
id: 'sr38Pg',
})}
variant="tertiary"
/>
</div>
</div>
);
}

View File

@ -220,6 +220,7 @@ export default function SupabaseAuth({
layout={socialLayout}
next={next}
providers={providers}
supabaseClient={supabaseClient}
/>
)}
</div>

View File

@ -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<SupabaseProviderGFE>;
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);
}}
/>
</div>

View File

@ -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,
};
}

View File

@ -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) {
<>
<ProductThemeScript theme="projects" />
<AuthGoogleOneTap showOnMobileOnly={true} />
<AuthOneClickSignup />
{children}
</>
);

View File

@ -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 (
<li ref={ref} {...remainingProps} className={commonClass}>
<li ref={ref} className={commonClass} {...remainingProps}>
<Component />
</li>
);
@ -315,7 +311,7 @@ type BaseToastProps = Omit<
React.ComponentPropsWithoutRef<typeof ToastPrimitive.Root>,
'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 (
<ToastPrimitive.Root ref={ref} asChild={true} {...remainingProps}>
<ToastImpl
animateFrom={animateFrom}
className={className}
customComponent={customComponent}
side={side}
variant={variant}
/>
<ToastImpl customComponent={customComponent} variant={variant} />
</ToastPrimitive.Root>
);
}
@ -353,7 +336,6 @@ const Toast = React.forwardRef<
const {
addOnIcon,
addOnLabel,
animateFrom = 'left',
className,
description,
icon,
@ -370,7 +352,6 @@ const Toast = React.forwardRef<
<ToastImpl
addOnIcon={addOnIcon}
addOnLabel={addOnLabel}
animateFrom={animateFrom}
className={className}
description={description}
icon={icon}