Continue working on Sign in with Apple button
This commit is contained in:
@ -48,10 +48,10 @@
|
|||||||
"@radix-ui/react-toggle": "^1.1.9",
|
"@radix-ui/react-toggle": "^1.1.9",
|
||||||
"@radix-ui/react-toggle-group": "^1.1.10",
|
"@radix-ui/react-toggle-group": "^1.1.10",
|
||||||
"@radix-ui/react-tooltip": "^1.2.7",
|
"@radix-ui/react-tooltip": "^1.2.7",
|
||||||
"@sentry/nextjs": "^9.31.0",
|
"@sentry/nextjs": "^9.32.0",
|
||||||
"@supabase-cache-helpers/postgrest-react-query": "^1.13.4",
|
"@supabase-cache-helpers/postgrest-react-query": "^1.13.4",
|
||||||
"@supabase/ssr": "^0.6.1",
|
"@supabase/ssr": "^0.6.1",
|
||||||
"@supabase/supabase-js": "^2.50.1",
|
"@supabase/supabase-js": "^2.50.2",
|
||||||
"@t3-oss/env-nextjs": "^0.12.0",
|
"@t3-oss/env-nextjs": "^0.12.0",
|
||||||
"@tanstack/react-query": "^5.81.2",
|
"@tanstack/react-query": "^5.81.2",
|
||||||
"@tanstack/react-table": "^8.21.3",
|
"@tanstack/react-table": "^8.21.3",
|
||||||
@ -92,9 +92,9 @@
|
|||||||
"eslint-config-next": "^15.3.4",
|
"eslint-config-next": "^15.3.4",
|
||||||
"eslint-config-prettier": "^10.1.5",
|
"eslint-config-prettier": "^10.1.5",
|
||||||
"eslint-plugin-drizzle": "^0.2.3",
|
"eslint-plugin-drizzle": "^0.2.3",
|
||||||
"eslint-plugin-prettier": "^5.5.0",
|
"eslint-plugin-prettier": "^5.5.1",
|
||||||
"postcss": "^8.5.6",
|
"postcss": "^8.5.6",
|
||||||
"prettier": "^3.6.0",
|
"prettier": "^3.6.1",
|
||||||
"prettier-plugin-tailwindcss": "^0.6.13",
|
"prettier-plugin-tailwindcss": "^0.6.13",
|
||||||
"tailwindcss": "^4.1.10",
|
"tailwindcss": "^4.1.10",
|
||||||
"tw-animate-css": "^1.3.4",
|
"tw-animate-css": "^1.3.4",
|
||||||
|
@ -4,3 +4,91 @@ import { StatusMessage, SubmitButton } from '@/components/default/forms';
|
|||||||
import { useAuth } from '@/lib/hooks/context';
|
import { useAuth } from '@/lib/hooks/context';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import Image from 'next/image';
|
||||||
|
import { type buttonVariants } from '@/components/ui';
|
||||||
|
import { type ComponentProps } from 'react';
|
||||||
|
import { type VariantProps } from 'class-variance-authority';
|
||||||
|
import { useSupabaseClient } from '@/utils/supabase';
|
||||||
|
|
||||||
|
type ButtonProps = ComponentProps<'button'> & VariantProps<typeof buttonVariants>;
|
||||||
|
type ImageProps = {
|
||||||
|
src: string;
|
||||||
|
alt: string;
|
||||||
|
className?: string;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
}
|
||||||
|
type FormProps = ComponentProps<'form'>;
|
||||||
|
type TextProps = ComponentProps<'p'>;
|
||||||
|
type SignInWithAppleProps = {
|
||||||
|
buttonProps?: ButtonProps;
|
||||||
|
imageProps?: ImageProps;
|
||||||
|
formProps?: FormProps;
|
||||||
|
textProps?: TextProps;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SignInWithApple = ({
|
||||||
|
buttonProps = {
|
||||||
|
className: 'w-full cursor-pointer',
|
||||||
|
type: 'submit',
|
||||||
|
},
|
||||||
|
imageProps = {
|
||||||
|
src: '/icons/auth/apple.svg',
|
||||||
|
alt: 'Apple',
|
||||||
|
className: 'invert-75 dark:invert-25',
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
},
|
||||||
|
formProps = {
|
||||||
|
className: 'my-4',
|
||||||
|
},
|
||||||
|
textProps = {
|
||||||
|
className: 'text-[1.0rem]',
|
||||||
|
},
|
||||||
|
} : SignInWithAppleProps) => {
|
||||||
|
const router = useRouter();
|
||||||
|
const { loading, refreshUser } = useAuth();
|
||||||
|
const [statusMessage, setStatusMessage] = useState('');
|
||||||
|
const [ isLoading, setIsLoading ] = useState(false);
|
||||||
|
const supabase = useSupabaseClient();
|
||||||
|
|
||||||
|
const handleSignInWithApple = async (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
try {
|
||||||
|
if (!supabase) throw new Error('Supabase client not found');
|
||||||
|
setStatusMessage('');
|
||||||
|
setIsLoading(true);
|
||||||
|
const result = await signInWithApple(supabase);
|
||||||
|
if (result.data.url) window.location.href = result.data.url;
|
||||||
|
else setStatusMessage(`There was a problem signing in with Apple!`);
|
||||||
|
} catch (error) {
|
||||||
|
setStatusMessage(`Error signing in: ${error as string}`);
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
await refreshUser();
|
||||||
|
router.push('');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form onSubmit={handleSignInWithApple} {...formProps}>
|
||||||
|
<SubmitButton
|
||||||
|
disabled={isLoading || loading}
|
||||||
|
pendingText='Signing in...'
|
||||||
|
{...buttonProps}
|
||||||
|
>
|
||||||
|
<div className='flex items-center gap-2'>
|
||||||
|
<Image
|
||||||
|
src={imageProps.src}
|
||||||
|
alt={imageProps.alt}
|
||||||
|
className={imageProps.className}
|
||||||
|
width={imageProps.width}
|
||||||
|
height={imageProps.height}
|
||||||
|
/>
|
||||||
|
<p className={textProps.className}>Sign In with Apple</p>
|
||||||
|
</div>
|
||||||
|
</SubmitButton>
|
||||||
|
{statusMessage && <StatusMessage message={{ error: statusMessage }} />}
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@ -3,7 +3,7 @@ type Message =
|
|||||||
| { error: string}
|
| { error: string}
|
||||||
| { message: string}
|
| { message: string}
|
||||||
|
|
||||||
export const StatusMessage = (message: Message) => {
|
export const StatusMessage = ({message}: {message: Message}) => {
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-col gap-2 w-full
|
<div className='flex flex-col gap-2 w-full
|
||||||
text-sm bg-accent rounded-md p-2 px-4'
|
text-sm bg-accent rounded-md p-2 px-4'
|
||||||
|
Reference in New Issue
Block a user