new design register/login panel(inputs)
This commit is contained in:
90
src/renderer/components/GradientTextField.tsx
Normal file
90
src/renderer/components/GradientTextField.tsx
Normal file
@ -0,0 +1,90 @@
|
||||
// GradientTextField.tsx
|
||||
import React from 'react';
|
||||
import TextField, { TextFieldProps } from '@mui/material/TextField';
|
||||
|
||||
const GRADIENT =
|
||||
'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)';
|
||||
|
||||
const GradientTextField: React.FC<TextFieldProps> = ({ sx, ...props }) => {
|
||||
return (
|
||||
<TextField
|
||||
{...props}
|
||||
variant={props.variant ?? 'outlined'}
|
||||
sx={{
|
||||
width: '100%',
|
||||
position: 'relative',
|
||||
mt: '1.5vw',
|
||||
mb: '1.5vw',
|
||||
|
||||
// Рамка инпута
|
||||
'& .MuiOutlinedInput-root': {
|
||||
position: 'relative',
|
||||
zIndex: 1,
|
||||
background: 'transparent',
|
||||
borderRadius: '3.5vw',
|
||||
|
||||
'&:hover fieldset': {
|
||||
borderColor: 'transparent',
|
||||
},
|
||||
'&.Mui-focused fieldset': {
|
||||
borderColor: 'transparent',
|
||||
},
|
||||
'& fieldset': {
|
||||
borderColor: 'transparent',
|
||||
},
|
||||
},
|
||||
|
||||
// Градиентная рамка через псевдоэлемент
|
||||
'& .MuiOutlinedInput-root::before': {
|
||||
content: '""',
|
||||
position: 'absolute',
|
||||
inset: 0,
|
||||
padding: '0.4vw', // толщина рамки
|
||||
borderRadius: '3.5vw',
|
||||
background: GRADIENT,
|
||||
WebkitMask:
|
||||
'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',
|
||||
WebkitMaskComposite: 'xor',
|
||||
maskComposite: 'exclude',
|
||||
zIndex: 0,
|
||||
},
|
||||
|
||||
// Вводимый текст
|
||||
'& .MuiInputBase-input': {
|
||||
color: 'white',
|
||||
padding: '1rem 1.5rem 1.1rem',
|
||||
fontFamily: 'Benzin-Bold',
|
||||
},
|
||||
|
||||
// Лейбл как плейсхолдер, который уезжает вверх
|
||||
'& .MuiInputLabel-root': {
|
||||
fontFamily: 'Benzin-Bold',
|
||||
fontSize: '0.95rem',
|
||||
background: 'black',
|
||||
|
||||
// позиция "по умолчанию" — внутри инпута
|
||||
transform: 'translate(1.5rem, 1.1rem) scale(1)',
|
||||
|
||||
// градиентный текст
|
||||
color: 'transparent',
|
||||
backgroundImage: GRADIENT,
|
||||
backgroundClip: 'text',
|
||||
WebkitBackgroundClip: 'text',
|
||||
|
||||
// когда лейбл "съежился" (есть фокус или значение)
|
||||
'&.MuiInputLabel-shrink': {
|
||||
transform: 'translate(1.5rem, -1.3rem) scale(0.75)',
|
||||
},
|
||||
|
||||
'&.Mui-focused': {
|
||||
color: 'transparent', // не даём MUI перекрашивать
|
||||
},
|
||||
},
|
||||
|
||||
...(sx as object),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default GradientTextField;
|
||||
@ -1,4 +1,5 @@
|
||||
import { Box, Button, TextField, Typography } from '@mui/material';
|
||||
import GradientTextField from '../../components/GradientTextField';
|
||||
|
||||
interface AuthFormProps {
|
||||
config: {
|
||||
@ -19,72 +20,38 @@ const AuthForm = ({ config, handleInputChange, onLogin }: AuthFormProps) => {
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<Typography variant="h6">Логин</Typography>
|
||||
<TextField
|
||||
<GradientTextField
|
||||
label="Никнейм"
|
||||
required
|
||||
name="username"
|
||||
variant="outlined"
|
||||
value={config.username}
|
||||
onChange={handleInputChange}
|
||||
sx={{
|
||||
width: '100%',
|
||||
// '& .MuiFormLabel-root': {
|
||||
// color: 'white',
|
||||
// },
|
||||
'& .MuiInputBase-input': {
|
||||
color: 'white',
|
||||
},
|
||||
'& .MuiInput-underline:after': {
|
||||
borderBottomColor: '#B2BAC2',
|
||||
},
|
||||
'& .MuiOutlinedInput-root': {
|
||||
'& fieldset': {
|
||||
borderColor: '#E0E3E7',
|
||||
color: 'white',
|
||||
},
|
||||
'&:hover fieldset': {
|
||||
borderColor: '#B2BAC2',
|
||||
},
|
||||
'&.Mui-focused fieldset': {
|
||||
borderColor: '#6F7E8C',
|
||||
},
|
||||
},
|
||||
mt: '2.5vw',
|
||||
mb: '0vw'
|
||||
}}
|
||||
/>
|
||||
<Typography variant="h6">Пароль</Typography>
|
||||
<TextField
|
||||
<GradientTextField
|
||||
label="Пароль"
|
||||
required
|
||||
type="password"
|
||||
name="password"
|
||||
variant="outlined"
|
||||
value={config.password}
|
||||
onChange={handleInputChange}
|
||||
sx={{
|
||||
width: '100%',
|
||||
// '& .MuiFormLabel-root': {
|
||||
// color: 'white',
|
||||
// },
|
||||
'& .MuiInputBase-input': {
|
||||
color: 'white',
|
||||
},
|
||||
'& .MuiInput-underline:after': {
|
||||
borderBottomColor: '#B2BAC2',
|
||||
},
|
||||
'& .MuiOutlinedInput-root': {
|
||||
'& fieldset': {
|
||||
borderColor: '#E0E3E7',
|
||||
color: 'white',
|
||||
},
|
||||
'&:hover fieldset': {
|
||||
borderColor: '#B2BAC2',
|
||||
},
|
||||
'&.Mui-focused fieldset': {
|
||||
borderColor: '#6F7E8C',
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<Button onClick={onLogin} variant="contained">
|
||||
<Button onClick={onLogin} variant="contained"
|
||||
sx={{
|
||||
transition: 'transform 0.3s ease',
|
||||
width: '60%',
|
||||
mt: 2,
|
||||
background: 'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)',
|
||||
fontFamily: 'Benzin-Bold',
|
||||
borderRadius: '2.5vw',
|
||||
fontSize: '2vw',
|
||||
'&:hover': {
|
||||
transform: 'scale(1.1)',
|
||||
|
||||
},
|
||||
}}>
|
||||
Войти
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
@ -24,6 +24,7 @@ import {
|
||||
} from '../api';
|
||||
import QRCodeStyling from 'qr-code-styling';
|
||||
import popalogo from '../../../assets/icons/popa-popa.svg';
|
||||
import GradientTextField from '../components/GradientTextField';
|
||||
|
||||
const ColorlibConnector = styled(StepConnector)(({ theme }) => ({
|
||||
[`&.${stepConnectorClasses.alternativeLabel}`]: {
|
||||
@ -32,7 +33,8 @@ const ColorlibConnector = styled(StepConnector)(({ theme }) => ({
|
||||
[`&.${stepConnectorClasses.active}`]: {
|
||||
[`& .${stepConnectorClasses.line}`]: {
|
||||
backgroundImage:
|
||||
'linear-gradient( 95deg,rgb(242,113,33) 0%,rgb(233,64,87) 50%,rgb(138,35,135) 100%)',
|
||||
//'linear-gradient( 95deg,rgb(242,113,33) 0%,rgb(233,64,87) 50%,rgb(138,35,135) 100%)',
|
||||
'linear-gradient( 95deg,rgb(150,150,150) 0%, rgb(242,113,33) 80%,rgb(233,64,87) 110%,rgb(138,35,135) 150%)'
|
||||
},
|
||||
},
|
||||
[`&.${stepConnectorClasses.completed}`]: {
|
||||
@ -44,8 +46,9 @@ const ColorlibConnector = styled(StepConnector)(({ theme }) => ({
|
||||
[`& .${stepConnectorClasses.line}`]: {
|
||||
height: 3,
|
||||
border: 0,
|
||||
backgroundColor: '#eaeaf0',
|
||||
backgroundImage: 'linear-gradient( 275deg,rgb(150,150,150) 0%, rgb(242,113,33) 80%,rgb(233,64,87) 110%,rgb(138,35,135) 150%)',
|
||||
borderRadius: 1,
|
||||
transition: 'background-image 1s ease, background-color 1s ease',
|
||||
...theme.applyStyles('dark', {
|
||||
backgroundColor: theme.palette.grey[800],
|
||||
}),
|
||||
@ -55,7 +58,7 @@ const ColorlibConnector = styled(StepConnector)(({ theme }) => ({
|
||||
const ColorlibStepIconRoot = styled('div')<{
|
||||
ownerState: { completed?: boolean; active?: boolean };
|
||||
}>(({ theme }) => ({
|
||||
backgroundColor: '#ccc',
|
||||
backgroundColor: '#adadad',
|
||||
zIndex: 1,
|
||||
color: '#fff',
|
||||
width: 50,
|
||||
@ -64,6 +67,7 @@ const ColorlibStepIconRoot = styled('div')<{
|
||||
borderRadius: '50%',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
transition: 'background-image 1s ease, box-shadow 1s ease, transform 1s ease',
|
||||
...theme.applyStyles('dark', {
|
||||
backgroundColor: theme.palette.grey[700],
|
||||
}),
|
||||
@ -74,13 +78,14 @@ const ColorlibStepIconRoot = styled('div')<{
|
||||
backgroundImage:
|
||||
'linear-gradient( 136deg, rgb(242,113,33) 0%, rgb(233,64,87) 50%, rgb(138,35,135) 100%)',
|
||||
boxShadow: '0 4px 10px 0 rgba(0,0,0,.25)',
|
||||
transform: 'scale(1.08)',
|
||||
},
|
||||
},
|
||||
{
|
||||
props: ({ ownerState }) => ownerState.completed,
|
||||
style: {
|
||||
backgroundImage:
|
||||
'linear-gradient( 136deg, rgb(242,113,33) 0%, rgb(233,64,87) 50%, rgb(138,35,135) 100%)',
|
||||
'#adadad',
|
||||
},
|
||||
},
|
||||
],
|
||||
@ -142,6 +147,7 @@ export const Registration = () => {
|
||||
const [activeStep, setActiveStep] = useState(0);
|
||||
const [username, setUsername] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [enterpassword, setEnterPassword] = useState('');
|
||||
const [open, setOpen] = useState(false);
|
||||
const [message, setMessage] = useState('');
|
||||
const [verificationCode, setVerificationCode] = useState<string | null>(null);
|
||||
@ -162,7 +168,22 @@ export const Registration = () => {
|
||||
}, [url]);
|
||||
|
||||
const handleCreateAccount = async () => {
|
||||
// простая валидация на фронте
|
||||
if (!username || !password || !enterpassword) {
|
||||
setOpen(true);
|
||||
setMessage('Заполните все поля');
|
||||
return;
|
||||
}
|
||||
|
||||
if (password !== enterpassword) {
|
||||
setOpen(true);
|
||||
setMessage('Пароли не совпадают');
|
||||
return;
|
||||
}
|
||||
|
||||
// тут уже точно всё ок — отправляем запрос
|
||||
const response = await registerUser(username, password);
|
||||
|
||||
if (response.status === 'success') {
|
||||
setActiveStep(1);
|
||||
} else {
|
||||
@ -253,27 +274,33 @@ export const Registration = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
|
||||
<>
|
||||
<Stepper
|
||||
activeStep={activeStep}
|
||||
alternativeLabel
|
||||
connector={<ColorlibConnector />}
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: '10%',
|
||||
}} // чтобы отделить степпер от формы
|
||||
>
|
||||
{steps.map((label) => (
|
||||
<Step key={label}>
|
||||
<StepLabel
|
||||
sx={{
|
||||
'& .MuiStepLabel-label': {
|
||||
color: 'white',
|
||||
color: '#adadad !important',
|
||||
transition: 'color 1s ease',
|
||||
},
|
||||
'& .Mui-completed': {
|
||||
color: 'white !important',
|
||||
color: '#adadad !important',
|
||||
},
|
||||
'& .Mui-active': {
|
||||
backgroundImage:
|
||||
'linear-gradient( 136deg, rgb(242,113,33) 0%, rgb(233,64,87) 50%, rgb(138,35,135) 100%)',
|
||||
WebkitBackgroundClip: 'text',
|
||||
WebkitTextFillColor: 'transparent',
|
||||
transition: 'all 1s ease',
|
||||
},
|
||||
}}
|
||||
StepIconComponent={ColorlibStepIcon}
|
||||
@ -283,145 +310,136 @@ export const Registration = () => {
|
||||
</Step>
|
||||
))}
|
||||
</Stepper>
|
||||
{activeStep === 0 && (
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: 2,
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<Typography variant="h6">Создание аккаунта</Typography>
|
||||
<Typography variant="body1">Введите ваш никнейм</Typography>
|
||||
<TextField
|
||||
required
|
||||
name="username"
|
||||
variant="outlined"
|
||||
value={username}
|
||||
onChange={(e) => setUsername(e.target.value)}
|
||||
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2, width: '50vw', mt: activeStep === 1 ? '20%' : '0%' }}>
|
||||
{activeStep === 0 && (
|
||||
<Box
|
||||
sx={{
|
||||
width: '100%',
|
||||
// '& .MuiFormLabel-root': {
|
||||
// color: 'white',
|
||||
// },
|
||||
'& .MuiInputBase-input': {
|
||||
color: 'white',
|
||||
},
|
||||
'& .MuiInput-underline:after': {
|
||||
borderBottomColor: '#B2BAC2',
|
||||
},
|
||||
'& .MuiOutlinedInput-root': {
|
||||
'& fieldset': {
|
||||
borderColor: '#E0E3E7',
|
||||
color: 'white',
|
||||
},
|
||||
'&:hover fieldset': {
|
||||
borderColor: '#B2BAC2',
|
||||
},
|
||||
'&.Mui-focused fieldset': {
|
||||
borderColor: '#6F7E8C',
|
||||
},
|
||||
},
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
/>
|
||||
<Typography variant="body1">Введите ваш пароль</Typography>
|
||||
<TextField
|
||||
required
|
||||
name="password"
|
||||
type="password"
|
||||
variant="outlined"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
>
|
||||
<GradientTextField
|
||||
label="Никнейм"
|
||||
required
|
||||
name="username"
|
||||
value={username}
|
||||
onChange={(e) => setUsername(e.target.value)}
|
||||
/>
|
||||
<GradientTextField
|
||||
label="Пароль"
|
||||
required
|
||||
name="password"
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
/>
|
||||
<GradientTextField
|
||||
label="Подтвердите пароль"
|
||||
required
|
||||
name="enterpassword"
|
||||
type="password"
|
||||
value={enterpassword}
|
||||
onChange={(e) => setEnterPassword(e.target.value)}
|
||||
error={Boolean(enterpassword) && password !== enterpassword}
|
||||
helperText={
|
||||
Boolean(enterpassword) && password !== enterpassword
|
||||
? 'Пароли не совпадают'
|
||||
: '⠀'
|
||||
}
|
||||
sx={{ mb: '0vw' }}
|
||||
/>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
sx={{
|
||||
transition: 'transform 0.3s ease',
|
||||
width: '60%',
|
||||
mt: 2,
|
||||
background: 'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)',
|
||||
fontFamily: 'Benzin-Bold',
|
||||
borderRadius: '2.5vw',
|
||||
fontSize: '2vw',
|
||||
'&:hover': {
|
||||
transform: 'scale(1.1)',
|
||||
|
||||
},
|
||||
}}
|
||||
onClick={handleCreateAccount}
|
||||
>
|
||||
Создать
|
||||
</Button>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{activeStep === 1 && (
|
||||
<Box
|
||||
sx={{
|
||||
width: '100%',
|
||||
// '& .MuiFormLabel-root': {
|
||||
// color: 'white',
|
||||
// },
|
||||
'& .MuiInputBase-input': {
|
||||
color: 'white',
|
||||
},
|
||||
'& .MuiInput-underline:after': {
|
||||
borderBottomColor: '#B2BAC2',
|
||||
},
|
||||
'& .MuiOutlinedInput-root': {
|
||||
'& fieldset': {
|
||||
borderColor: '#E0E3E7',
|
||||
color: 'white',
|
||||
},
|
||||
'&:hover fieldset': {
|
||||
borderColor: '#B2BAC2',
|
||||
},
|
||||
'&.Mui-focused fieldset': {
|
||||
borderColor: '#6F7E8C',
|
||||
},
|
||||
},
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: 2,
|
||||
alignItems: 'center',
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
sx={{ width: '100%', mt: 2 }}
|
||||
onClick={handleCreateAccount}
|
||||
>
|
||||
Создать
|
||||
</Button>
|
||||
</Box>
|
||||
)}
|
||||
{activeStep === 1 && (
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: 2,
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<Typography variant="h6">Откройте бота в телеграмме</Typography>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
sx={{ width: '100%', mt: 2 }}
|
||||
onClick={handleOpenBot}
|
||||
>
|
||||
Открыть бота
|
||||
</Button>
|
||||
<div
|
||||
ref={ref}
|
||||
style={{
|
||||
minHeight: 300,
|
||||
}}
|
||||
/>
|
||||
<Typography variant="body1">
|
||||
Введите код верификации в боте
|
||||
</Typography>
|
||||
{verificationCode ? (
|
||||
<>
|
||||
<Typography
|
||||
variant="h2"
|
||||
sx={{
|
||||
backgroundImage:
|
||||
'linear-gradient( 136deg, rgb(242,113,33) 0%, rgb(233,64,87) 50%, rgb(138,35,135) 100%)',
|
||||
WebkitBackgroundClip: 'text',
|
||||
WebkitTextFillColor: 'transparent',
|
||||
}}
|
||||
>
|
||||
{verificationCode}
|
||||
</Typography>
|
||||
<Typography variant="body1">Ждем ответа от бота</Typography>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
sx={{
|
||||
transition: 'transform 0.3s ease',
|
||||
width: '60%',
|
||||
mt: 2,
|
||||
background: 'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)',
|
||||
fontFamily: 'Benzin-Bold',
|
||||
borderRadius: '2.5vw',
|
||||
fontSize: '2vw',
|
||||
'&:hover': {
|
||||
transform: 'scale(1.1)',
|
||||
|
||||
},
|
||||
}}
|
||||
onClick={handleOpenBot}
|
||||
>
|
||||
Открыть бота
|
||||
</Button>
|
||||
<div
|
||||
ref={ref}
|
||||
style={{
|
||||
minHeight: 300,
|
||||
}}
|
||||
/>
|
||||
<Typography variant="body1">
|
||||
Введите код верификации в боте
|
||||
</Typography>
|
||||
{verificationCode ? (
|
||||
<>
|
||||
<Typography
|
||||
variant="h2"
|
||||
sx={{
|
||||
backgroundImage:
|
||||
'linear-gradient( 136deg, rgb(242,113,33) 0%, rgb(233,64,87) 50%, rgb(138,35,135) 100%)',
|
||||
WebkitBackgroundClip: 'text',
|
||||
WebkitTextFillColor: 'transparent',
|
||||
}}
|
||||
>
|
||||
{verificationCode}
|
||||
</Typography>
|
||||
<Typography variant="body1">Ждем ответа от бота</Typography>
|
||||
<CircularProgress />
|
||||
</>
|
||||
) : (
|
||||
<CircularProgress />
|
||||
</>
|
||||
) : (
|
||||
<CircularProgress />
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
<Snackbar
|
||||
open={open}
|
||||
autoHideDuration={6000}
|
||||
onClose={handleClose}
|
||||
message={message}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
|
||||
<Snackbar
|
||||
open={open}
|
||||
autoHideDuration={6000}
|
||||
onClose={handleClose}
|
||||
message={message}
|
||||
/>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user