Files
donetick/src/views/Authorization/AuthFields.jsx
2026-08-16 11:52:40 -04:00

168 lines
3.7 KiB
JavaScript

import VisibilityOffOutlined from '@mui/icons-material/VisibilityOffOutlined'
import VisibilityOutlined from '@mui/icons-material/VisibilityOutlined'
import {
Box,
Button,
FormControl,
FormHelperText,
FormLabel,
IconButton,
Input,
Link,
Typography,
} from '@mui/joy'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { authButtonSx, authInputSx } from './authStyles'
const labelSx = { fontSize: '0.875rem', fontWeight: 600, mb: 0.75 }
export const AuthField = ({ children, error, helper, label, ...formProps }) => (
<FormControl error={Boolean(error)} {...formProps}>
<FormLabel sx={labelSx}>{label}</FormLabel>
{children}
{(error || helper) && (
<FormHelperText
sx={{
fontSize: '0.8125rem',
color: error ? 'danger.plainColor' : 'text.secondary',
}}
>
{error || helper}
</FormHelperText>
)}
</FormControl>
)
export const AuthTextField = ({ error, helper, label, sx, ...inputProps }) => (
<AuthField label={label} error={error} helper={helper} id={inputProps.id}>
<Input size='lg' sx={{ ...authInputSx, ...sx }} {...inputProps} />
</AuthField>
)
export const AuthPasswordField = ({
error,
helper,
label,
sx,
...inputProps
}) => {
const { t } = useTranslation('auth')
const [visible, setVisible] = useState(false)
return (
<AuthField label={label} error={error} helper={helper} id={inputProps.id}>
<Input
size='lg'
type={visible ? 'text' : 'password'}
sx={{ ...authInputSx, ...sx }}
endDecorator={
<IconButton
variant='plain'
color='neutral'
size='sm'
tabIndex={-1}
aria-label={visible ? t('hidePassword') : t('showPassword')}
onClick={() => setVisible(v => !v)}
sx={{ borderRadius: '8px' }}
>
{visible ? (
<VisibilityOffOutlined fontSize='small' />
) : (
<VisibilityOutlined fontSize='small' />
)}
</IconButton>
}
{...inputProps}
/>
</AuthField>
)
}
export const AuthSubmitButton = ({ children, sx, ...props }) => (
<Button
type='submit'
size='lg'
variant='solid'
fullWidth
sx={{ ...authButtonSx, ...sx }}
{...props}
>
{children}
</Button>
)
export const SocialButton = ({ children, icon, sx, ...props }) => (
<Button
type='button'
size='lg'
variant='outlined'
color='neutral'
fullWidth
startDecorator={icon}
sx={{
...authButtonSx,
fontWeight: 500,
justifyContent: 'center',
...sx,
}}
{...props}
>
{children}
</Button>
)
export const AuthDivider = ({ children }) => {
const { t } = useTranslation('auth')
return (
<Box
role='separator'
sx={{
display: 'flex',
alignItems: 'center',
gap: 1.5,
my: 2.5,
'&::before, &::after': {
content: '""',
flex: 1,
height: '1px',
bgcolor: 'divider',
},
}}
>
<Typography level='body-xs' sx={{ color: 'text.secondary' }}>
{children ?? t('or')}
</Typography>
</Box>
)
}
export const LegalLinks = () => (
<Typography
level='body-xs'
sx={{ textAlign: 'center', color: 'text.secondary' }}
>
<Link
href='https://donetick.com/privacy'
target='_blank'
rel='noopener'
color='neutral'
underline='hover'
>
Privacy Policy
</Link>
{' · '}
<Link
href='https://donetick.com/terms'
target='_blank'
rel='noopener'
color='neutral'
underline='hover'
>
Terms of Use
</Link>
</Typography>
)