Add authentication
This commit is contained in:
26
apps/builder/components/auth/AuthSwitcher.tsx
Normal file
26
apps/builder/components/auth/AuthSwitcher.tsx
Normal file
@ -0,0 +1,26 @@
|
||||
import React from 'react'
|
||||
import { NextChakraLink } from '../nextChakra/NextChakraLink'
|
||||
import { Text } from '@chakra-ui/react'
|
||||
|
||||
type Props = {
|
||||
type: 'register' | 'signin'
|
||||
}
|
||||
export const AuthSwitcher = ({ type }: Props) => (
|
||||
<>
|
||||
{type === 'signin' ? (
|
||||
<Text>
|
||||
Don't have an account?{' '}
|
||||
<NextChakraLink href="/register" color="blue.500" textDecor="underline">
|
||||
Sign up for free
|
||||
</NextChakraLink>
|
||||
</Text>
|
||||
) : (
|
||||
<Text>
|
||||
Already have an account?{' '}
|
||||
<NextChakraLink href="/signin" color="blue.500" textDecor="underline">
|
||||
Sign in
|
||||
</NextChakraLink>
|
||||
</Text>
|
||||
)}
|
||||
</>
|
||||
)
|
25
apps/builder/components/auth/DividerWithText.tsx
Normal file
25
apps/builder/components/auth/DividerWithText.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
import { FlexProps, Flex, Box, Divider, Text } from '@chakra-ui/react'
|
||||
import { useColorModeValue } from '@chakra-ui/system'
|
||||
import React from 'react'
|
||||
|
||||
export const DividerWithText = (props: FlexProps) => {
|
||||
const { children, ...flexProps } = props
|
||||
return (
|
||||
<Flex align="center" color="gray.300" {...flexProps}>
|
||||
<Box flex="1">
|
||||
<Divider borderColor="currentcolor" />
|
||||
</Box>
|
||||
<Text
|
||||
as="span"
|
||||
px="3"
|
||||
color={useColorModeValue('gray.600', 'gray.400')}
|
||||
fontWeight="medium"
|
||||
>
|
||||
{children}
|
||||
</Text>
|
||||
<Box flex="1">
|
||||
<Divider borderColor="currentcolor" />
|
||||
</Box>
|
||||
</Flex>
|
||||
)
|
||||
}
|
76
apps/builder/components/auth/SignInForm.tsx
Normal file
76
apps/builder/components/auth/SignInForm.tsx
Normal file
@ -0,0 +1,76 @@
|
||||
import {
|
||||
Button,
|
||||
HTMLChakraProps,
|
||||
Input,
|
||||
Stack,
|
||||
HStack,
|
||||
useToast,
|
||||
} from '@chakra-ui/react'
|
||||
import React, { ChangeEvent, FormEvent, useEffect } from 'react'
|
||||
import { useState } from 'react'
|
||||
import { signIn, useSession } from 'next-auth/react'
|
||||
import { DividerWithText } from './DividerWithText'
|
||||
import { SocialLoginButtons } from './SocialLoginButtons'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
type Props = {
|
||||
defaultEmail?: string
|
||||
}
|
||||
export const SignInForm = ({
|
||||
defaultEmail,
|
||||
}: Props & HTMLChakraProps<'form'>) => {
|
||||
const router = useRouter()
|
||||
const { status } = useSession()
|
||||
const [authLoading, setAuthLoading] = useState(false)
|
||||
const [emailValue, setEmailValue] = useState(defaultEmail ?? '')
|
||||
const toast = useToast({
|
||||
position: 'top-right',
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (status === 'authenticated') router.replace('/typebots')
|
||||
}, [status, router])
|
||||
|
||||
const handleEmailChange = (e: ChangeEvent<HTMLInputElement>) =>
|
||||
setEmailValue(e.target.value)
|
||||
|
||||
const handleEmailSubmit = async (e: FormEvent) => {
|
||||
e.preventDefault()
|
||||
setAuthLoading(true)
|
||||
await signIn('email', {
|
||||
email: emailValue,
|
||||
redirect: false,
|
||||
})
|
||||
toast({
|
||||
status: 'success',
|
||||
title: 'Success!',
|
||||
description: 'Check your inbox to sign in',
|
||||
})
|
||||
setAuthLoading(false)
|
||||
}
|
||||
return (
|
||||
<Stack spacing="4">
|
||||
<SocialLoginButtons />
|
||||
<DividerWithText mt="6">Or with your email</DividerWithText>
|
||||
<HStack as="form" onSubmit={handleEmailSubmit}>
|
||||
<Input
|
||||
name="email"
|
||||
type="email"
|
||||
autoComplete="email"
|
||||
placeholder="email@company.com"
|
||||
required
|
||||
value={emailValue}
|
||||
onChange={handleEmailChange}
|
||||
/>
|
||||
<Button
|
||||
type="submit"
|
||||
isLoading={
|
||||
['loading', 'authenticated'].includes(status) || authLoading
|
||||
}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</HStack>
|
||||
</Stack>
|
||||
)
|
||||
}
|
46
apps/builder/components/auth/SocialLoginButtons.tsx
Normal file
46
apps/builder/components/auth/SocialLoginButtons.tsx
Normal file
@ -0,0 +1,46 @@
|
||||
import { FacebookLogo, GithubLogo, GoogleLogo } from 'assets/logos'
|
||||
import { Stack, Button } from '@chakra-ui/react'
|
||||
import { signIn, useSession } from 'next-auth/react'
|
||||
import React from 'react'
|
||||
|
||||
export const SocialLoginButtons = () => {
|
||||
const { status } = useSession()
|
||||
|
||||
const handleGitHubClick = async () => signIn('github')
|
||||
|
||||
const handleGoogleClick = async () => signIn('google')
|
||||
|
||||
const handleFacebookClick = async () => signIn('facebook')
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<Button
|
||||
leftIcon={<GithubLogo />}
|
||||
colorScheme="gray"
|
||||
onClick={handleGitHubClick}
|
||||
data-testid="github"
|
||||
isLoading={['loading', 'authenticated'].includes(status)}
|
||||
>
|
||||
Continue with GitHub
|
||||
</Button>
|
||||
<Button
|
||||
leftIcon={<GoogleLogo />}
|
||||
colorScheme="gray"
|
||||
onClick={handleGoogleClick}
|
||||
data-testid="google"
|
||||
isLoading={['loading', 'authenticated'].includes(status)}
|
||||
>
|
||||
Continue with Google
|
||||
</Button>
|
||||
<Button
|
||||
leftIcon={<FacebookLogo />}
|
||||
colorScheme="gray"
|
||||
onClick={handleFacebookClick}
|
||||
data-testid="facebook"
|
||||
isLoading={['loading', 'authenticated'].includes(status)}
|
||||
>
|
||||
Continue with Facebook
|
||||
</Button>
|
||||
</Stack>
|
||||
)
|
||||
}
|
Reference in New Issue
Block a user