parent
07b050b45c
commit
10881598de
|
After Width: | Height: | Size: 1.2 KiB |
@ -0,0 +1,79 @@ |
||||
import { |
||||
useEffect, |
||||
useRef, |
||||
useState, |
||||
useCallback, |
||||
FormEvent, |
||||
FocusEvent, |
||||
ChangeEvent, |
||||
} from 'react' |
||||
|
||||
import { isValidEmail } from 'features/AuthServiceApp/helpers/isValidEmail' |
||||
|
||||
import { API_ROOT } from '../../config/routes' |
||||
|
||||
export const useOauth = () => { |
||||
const [email, setEmail] = useState('') |
||||
const [error, setError] = useState('') |
||||
const [showEmailField, showShowEmailField] = useState(false) |
||||
|
||||
const formRef = useRef<HTMLFormElement>(null) |
||||
|
||||
const authorize = useCallback(async () => { |
||||
if (!formRef.current) return |
||||
|
||||
const url = `${API_ROOT}/oauth` |
||||
|
||||
const res = await fetch(url, { |
||||
body: new FormData(formRef.current), |
||||
method: 'POST', |
||||
}) |
||||
|
||||
if (res.ok && res.redirected) { |
||||
formRef.current.submit() |
||||
} else { |
||||
const data = await res.json() |
||||
|
||||
if (data.error === 'Token missing email field') { |
||||
showShowEmailField(true) |
||||
} |
||||
} |
||||
}, []) |
||||
|
||||
const handleEmailChange = ({ target: { value } }: ChangeEvent<HTMLInputElement>) => { |
||||
setEmail(value) |
||||
} |
||||
|
||||
const handleEmailFocus = () => { |
||||
setError('') |
||||
} |
||||
|
||||
const handleEmailBlur = ({ target: { value } }: FocusEvent<HTMLInputElement>) => { |
||||
if (!isValidEmail(value) && value) { |
||||
setError('error_invalid_email_format') |
||||
} |
||||
} |
||||
|
||||
const handleSubmit = (e: FormEvent<HTMLFormElement>) => { |
||||
e.preventDefault() |
||||
|
||||
if (error) return |
||||
|
||||
authorize() |
||||
} |
||||
|
||||
useEffect(() => { |
||||
authorize() |
||||
}, [authorize]) |
||||
|
||||
return { |
||||
email, |
||||
error, |
||||
formRef, |
||||
handleEmailBlur, |
||||
handleEmailChange, |
||||
handleEmailFocus, |
||||
handleSubmit, |
||||
showEmailField, |
||||
} |
||||
} |
||||
@ -0,0 +1,137 @@ |
||||
import { Link } from 'react-router-dom' |
||||
|
||||
import styled, { css } from 'styled-components/macro' |
||||
|
||||
import { isMobileDevice } from 'config/userAgent' |
||||
|
||||
import { ButtonSolid } from 'features/Common' |
||||
import { Error as ErrorBase } from 'features/AuthServiceApp/styled' |
||||
import { HeaderLogo as HeaderLogoBase } from 'features/ProfileHeader/styled' |
||||
|
||||
import { Input as InputBase } from 'components/Input' |
||||
|
||||
export const Header = styled.div` |
||||
position: absolute; |
||||
padding: 30px 25px 0; |
||||
` |
||||
|
||||
export const HeaderLogo = styled(HeaderLogoBase)` |
||||
${isMobileDevice |
||||
? css` |
||||
top: 20px; |
||||
` |
||||
: ''}; |
||||
` |
||||
|
||||
export const Content = styled.div` |
||||
display: flex; |
||||
flex-direction: column; |
||||
justify-content: center; |
||||
align-items: center; |
||||
height: 100vh; |
||||
padding: 20px 25px; |
||||
text-align: center; |
||||
` |
||||
|
||||
export const DoneIcon = styled.div` |
||||
width: 88px; |
||||
height: 88px; |
||||
margin-bottom: 20px; |
||||
background-image: url(/images/done.svg); |
||||
background-size: cover; |
||||
|
||||
${isMobileDevice |
||||
? css` |
||||
width: 65px; |
||||
height: 65px; |
||||
` |
||||
: ''}; |
||||
` |
||||
|
||||
export const Title = styled.div` |
||||
margin-bottom: 40px; |
||||
font-size: 24px; |
||||
font-weight: bold; |
||||
color: ${({ theme }) => theme.colors.white}; |
||||
|
||||
${isMobileDevice |
||||
? css` |
||||
margin-bottom: 15px; |
||||
line-height: 20px; |
||||
font-size: 16px; |
||||
` |
||||
: ''}; |
||||
` |
||||
|
||||
export const Subtitle = styled.div` |
||||
margin-bottom: 40px; |
||||
font-size: 18px; |
||||
line-height: 18px; |
||||
color: ${({ theme }) => theme.colors.white}; |
||||
|
||||
${isMobileDevice |
||||
? css` |
||||
margin-bottom: 15px; |
||||
font-size: 12px; |
||||
` |
||||
: ''}; |
||||
` |
||||
|
||||
export const Form = styled.form` |
||||
position: relative; |
||||
display: flex; |
||||
gap: 20px; |
||||
margin-bottom: 30px; |
||||
|
||||
${isMobileDevice |
||||
? css` |
||||
gap: 10px; |
||||
width: 100%; |
||||
flex-direction: column; |
||||
` |
||||
: ''}; |
||||
` |
||||
|
||||
export const Input = styled(InputBase)` |
||||
width: 406px; |
||||
height: 50px; |
||||
|
||||
${isMobileDevice |
||||
? css` |
||||
width: 100%; |
||||
height: 32px; |
||||
` |
||||
: ''}; |
||||
` |
||||
|
||||
export const SubmitButton = styled(ButtonSolid)` |
||||
width: 117.65px; |
||||
height: 50px; |
||||
font-size: 20px; |
||||
font-weight: 600; |
||||
|
||||
${isMobileDevice |
||||
? css` |
||||
width: 100%; |
||||
height: 32px; |
||||
font-size: 12px; |
||||
` |
||||
: ''}; |
||||
` |
||||
|
||||
export const Text = styled.div` |
||||
font-size: 12px; |
||||
white-space: nowrap; |
||||
color: rgba(255, 255, 255, 0.7); |
||||
` |
||||
|
||||
export const StyledLink = styled(Link)` |
||||
color: rgba(255, 255, 255, 0.7); |
||||
text-decoration: underline; |
||||
` |
||||
|
||||
export const Error = styled(ErrorBase)` |
||||
position: absolute; |
||||
left: 0; |
||||
bottom: -25px; |
||||
` |
||||
@ -0,0 +1,11 @@ |
||||
export const getRandomString = (length: number) => { |
||||
let result = '' |
||||
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' |
||||
const charactersLength = characters.length |
||||
|
||||
for (let i = 0; i < length; i++) { |
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength)) |
||||
} |
||||
|
||||
return result |
||||
} |
||||
Loading…
Reference in new issue