добавлена поддержка темной темы
This commit is contained in:
parent
f8f6fb991a
commit
5aa97a5255
2
.gitignore
vendored
2
.gitignore
vendored
@ -129,3 +129,5 @@ dist
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
ngrok.exe
|
12
src/app.tsx
12
src/app.tsx
@ -1,7 +1,17 @@
|
||||
import React from 'react';
|
||||
import React, {useEffect} from 'react';
|
||||
import Main from './container/main';
|
||||
import useTelegram from './container/hooks/useTelegram';
|
||||
|
||||
const App = () => {
|
||||
const { isScriptLoaded, onClose, onToggleButton, tg, user_id, username } = useTelegram();
|
||||
|
||||
useEffect(() => {
|
||||
if (isScriptLoaded && tg) {
|
||||
tg.ready(); // Инициализация WebApp после загрузки скрипта
|
||||
console.log('Telegram WebApp готов:', tg);
|
||||
}
|
||||
}, [isScriptLoaded, tg]);
|
||||
|
||||
return <Main />;
|
||||
};
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
@ -8,29 +9,53 @@ declare global {
|
||||
}
|
||||
|
||||
const useTelegram = () => {
|
||||
const [isScriptLoaded, setIsScriptLoaded] = useState(false);
|
||||
|
||||
const tg = window.Telegram.WebApp;
|
||||
const onClose = () => {
|
||||
tg.close()
|
||||
useEffect(() => {
|
||||
// Проверяем, был ли скрипт уже загружен
|
||||
if (!window.Telegram) {
|
||||
// Если Telegram API еще не доступен, загружаем скрипт
|
||||
const script = document.createElement('script');
|
||||
script.src = 'https://telegram.org/js/telegram-web-app.js';
|
||||
script.async = true;
|
||||
script.onload = () => {
|
||||
setIsScriptLoaded(true); // Скрипт загружен
|
||||
};
|
||||
script.onerror = () => {
|
||||
console.error('Ошибка при загрузке Telegram Web App SDK');
|
||||
};
|
||||
document.body.appendChild(script);
|
||||
} else {
|
||||
// Если Telegram Web App уже доступен, просто обновляем состояние
|
||||
setIsScriptLoaded(true);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Логика, которая будет выполняться, когда скрипт загружен
|
||||
const tg = window.Telegram?.WebApp;
|
||||
|
||||
const onClose = () => {
|
||||
tg?.close();
|
||||
};
|
||||
|
||||
const onToggleButton = () => {
|
||||
if(tg.MainButton.isVisible) {
|
||||
if (tg?.MainButton?.isVisible) {
|
||||
tg.MainButton.hide();
|
||||
} else {
|
||||
tg.MainButton.show();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
isScriptLoaded,
|
||||
onClose,
|
||||
onToggleButton,
|
||||
tg,
|
||||
user_id: tg.initDataUnsafe?.user?.id,
|
||||
user: tg.initDataUnsafe?.user,
|
||||
username: tg.initDataUnsafe?.user?.username,
|
||||
queryId: tg.initDataUnsafe?.query_id
|
||||
}
|
||||
}
|
||||
user_id: tg?.initDataUnsafe?.user?.id,
|
||||
user: tg?.initDataUnsafe?.user,
|
||||
username: tg?.initDataUnsafe?.user?.username,
|
||||
queryId: tg?.initDataUnsafe?.query_id,
|
||||
};
|
||||
};
|
||||
|
||||
export default useTelegram;
|
60
src/container/signup/about/index.style.ts
Normal file
60
src/container/signup/about/index.style.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import styled from '@emotion/styled';
|
||||
import TextField from '@mui/material/TextField';
|
||||
|
||||
export const AboutStyled = styled(TextField)`
|
||||
& .MuiInputBase-input {
|
||||
color: var(--tg-theme-text-color,rgba(0, 0, 0, 0.6));
|
||||
}
|
||||
|
||||
& .MuiFormLabel-root {
|
||||
color: var(--tg-theme-text-color, rgba(0, 0, 0, 0.6));
|
||||
}
|
||||
|
||||
& .Mui-focused .MuiFormLabel-root {
|
||||
color: var(--tg-theme-label-focus-color, #0066ff);
|
||||
}
|
||||
|
||||
|
||||
& .MuiOutlinedInput-root {
|
||||
fieldset {
|
||||
border-color: var(--tg-theme-border-color, #cccccc);
|
||||
}
|
||||
|
||||
&:hover fieldset {
|
||||
border-color: var(--tg-theme-border-hover, #888888);
|
||||
}
|
||||
|
||||
&.Mui-focused fieldset {
|
||||
border-color: var(--tg-theme-border-focused, #0066ff);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
& .MuiInputBase-input {
|
||||
color: var(--tg-theme-text-color-dark, #ffffff);
|
||||
}
|
||||
|
||||
& .MuiFormLabel-root {
|
||||
color: var(--tg-theme-label-color-dark, #ffffff);
|
||||
}
|
||||
|
||||
& .Mui-focused .MuiFormLabel-root {
|
||||
color: var(--tg-theme-label-focus-color-dark, #0066ff);
|
||||
}
|
||||
|
||||
& .MuiOutlinedInput-root {
|
||||
fieldset {
|
||||
border-color: var(--tg-theme-border-color-dark, #ffffff);
|
||||
}
|
||||
|
||||
&:hover fieldset {
|
||||
border-color: var(--tg-theme-border-hover-dark, #777777);
|
||||
}
|
||||
|
||||
&.Mui-focused fieldset {
|
||||
border-color: var(--tg-theme-border-focused-dark, #0066ff);
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
19
src/container/signup/about/index.tsx
Normal file
19
src/container/signup/about/index.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import * as React from 'react';
|
||||
import { AboutStyled } from './index.style';
|
||||
|
||||
const About = ({rows, id, label, name, placeholder="Введите текст...", className = null}): React.ReactElement => {
|
||||
return (
|
||||
<AboutStyled
|
||||
fullWidth
|
||||
multiline
|
||||
rows={rows}
|
||||
id={id}
|
||||
label={label}
|
||||
name={name}
|
||||
placeholder={placeholder}
|
||||
className={className}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default About;
|
7
src/container/signup/button/index.style.ts
Normal file
7
src/container/signup/button/index.style.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import styled from '@emotion/styled';
|
||||
import Button from '@mui/material/Button';
|
||||
|
||||
export const RegisterButtonStyled = styled(Button)`
|
||||
background-color: var(--tg-theme-button-color);
|
||||
color: var(--tg-theme-button-text-color);
|
||||
`;
|
19
src/container/signup/button/index.tsx
Normal file
19
src/container/signup/button/index.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import * as React from 'react';
|
||||
import { RegisterButtonStyled } from './index.style';
|
||||
|
||||
const RegisterButton = ({children, id = null, name = null, className = null}): React.ReactElement => {
|
||||
return (
|
||||
<RegisterButtonStyled
|
||||
id={id}
|
||||
name={name}
|
||||
className={className}
|
||||
type="submit"
|
||||
fullWidth
|
||||
variant="contained"
|
||||
>
|
||||
{children}
|
||||
</RegisterButtonStyled>
|
||||
);
|
||||
}
|
||||
|
||||
export default RegisterButton;
|
@ -1,7 +1,3 @@
|
||||
.upload-input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.basic-multi-select {
|
||||
width: 100%;
|
||||
}
|
9
src/container/signup/index.style.ts
Normal file
9
src/container/signup/index.style.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { Grid2 } from '@mui/material';
|
||||
|
||||
export const GridChildrenStyle = styled(Grid2)`
|
||||
display: flex;
|
||||
padding: 10px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
`;
|
@ -1,9 +1,12 @@
|
||||
import * as React from 'react';
|
||||
import {Button, TextField, Grid, Box,
|
||||
Typography, Container
|
||||
import {Button, Grid2, Box, Container
|
||||
} from '@mui/material';
|
||||
import Title from './title';
|
||||
import Name from './name';
|
||||
import About from './about';
|
||||
import Photo from './photo';
|
||||
import Interests from './interests';
|
||||
import RegisterButton from './button';
|
||||
import axios from 'axios';
|
||||
import student_icon from './student-icon.png';
|
||||
import "./index.css";
|
||||
@ -11,7 +14,7 @@ import "./index.css";
|
||||
import Select from 'react-select';
|
||||
import { useState } from 'react';
|
||||
import { useConstant } from '../Constant';
|
||||
|
||||
import { GridChildrenStyle } from './index.style';
|
||||
|
||||
const SingUpPage = (): React.ReactElement => {
|
||||
const [selectedPhoto, setSelectedPhoto] = useState(null);
|
||||
@ -60,76 +63,50 @@ const SingUpPage = (): React.ReactElement => {
|
||||
>
|
||||
<Title>Регистрация</Title>
|
||||
<Box component="form" noValidate sx={{ mt: 3 }}>
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<TextField
|
||||
required
|
||||
fullWidth
|
||||
id="lname"
|
||||
<Grid2 container>
|
||||
<GridChildrenStyle size={6}>
|
||||
<Name
|
||||
id="lastname"
|
||||
label="Фамилия"
|
||||
name="lname"
|
||||
name="lastname"
|
||||
autoComplete="family-name"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<TextField
|
||||
autoComplete="given-name"
|
||||
name="fname"
|
||||
required
|
||||
fullWidth
|
||||
id="fname"
|
||||
</GridChildrenStyle>
|
||||
<GridChildrenStyle size={6}>
|
||||
<Name
|
||||
id="firstname"
|
||||
label="Имя"
|
||||
autoFocus
|
||||
name="firstname"
|
||||
autoComplete="given-name"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<TextField
|
||||
fullWidth
|
||||
multiline
|
||||
</GridChildrenStyle>
|
||||
<GridChildrenStyle size={12}>
|
||||
<About
|
||||
rows={3}
|
||||
id="about"
|
||||
label="Обо мне"
|
||||
name="about"
|
||||
variant="outlined"
|
||||
placeholder="Напишите о себе"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid
|
||||
container
|
||||
spacing={0}
|
||||
direction="column"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
sx={{ paddingTop: 7, paddingLeft: 3 }}
|
||||
>
|
||||
<Photo defaultPhoto={student_icon} onPhotoChange={handlePhotoChange} />
|
||||
</Grid>
|
||||
<Grid
|
||||
container
|
||||
spacing={0}
|
||||
direction="column"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
sx={{ paddingTop: 7, ml: 3 }}
|
||||
>
|
||||
<Select
|
||||
onChange={handleChange}
|
||||
closeMenuOnSelect={false}
|
||||
isMulti
|
||||
options={interests}
|
||||
className="basic-multi-select"
|
||||
classNamePrefix="select"
|
||||
</GridChildrenStyle>
|
||||
<GridChildrenStyle size={12}>
|
||||
<Photo
|
||||
|
||||
onPhotoChange={handlePhotoChange}
|
||||
/>
|
||||
</Grid>
|
||||
<Button
|
||||
type="submit"
|
||||
fullWidth
|
||||
variant="contained"
|
||||
sx={{ mt: 3, mb: 2, ml: 3 }}
|
||||
>
|
||||
</GridChildrenStyle>
|
||||
<GridChildrenStyle size={12}>
|
||||
<Interests
|
||||
options={interests}
|
||||
placeholder='Выберите интересы...'
|
||||
/>
|
||||
</GridChildrenStyle>
|
||||
<GridChildrenStyle size={12}>
|
||||
<RegisterButton>
|
||||
Регистрация
|
||||
</Button>
|
||||
</Grid>
|
||||
</RegisterButton>
|
||||
</GridChildrenStyle>
|
||||
</Grid2>
|
||||
</Box>
|
||||
</Box>
|
||||
</Container>
|
||||
|
68
src/container/signup/interests/index.style.ts
Normal file
68
src/container/signup/interests/index.style.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import styled from '@emotion/styled';
|
||||
import Select from 'react-select';
|
||||
|
||||
export const InterestsStyled = styled(Select)`
|
||||
.select__control {
|
||||
background-color: var(--tg-theme-bg-color, #ffffff);
|
||||
border: 1px solid var(--tg-theme-border-color, #cccccc);
|
||||
color: var(--tg-theme-text-color, #000000);
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
box-shadow: none;
|
||||
|
||||
&:hover {
|
||||
border-color: var(--tg-theme-border-hover, #888888);
|
||||
}
|
||||
}
|
||||
|
||||
.select__menu {
|
||||
background-color: var(--tg-theme-bg-color, #ffffff);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.select__option {
|
||||
background-color: transparent;
|
||||
color: var(--tg-theme-text-color, #000000);
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--tg-theme-hover-color, #f2f2f2);
|
||||
}
|
||||
|
||||
&.select__option--is-selected {
|
||||
background-color: var(--tg-theme-selected-color, #0066ff);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
&.select__option--is-focused {
|
||||
background-color: var(--tg-theme-hover-color, #e0e0e0);
|
||||
}
|
||||
}
|
||||
|
||||
.select__placeholder {
|
||||
color: var(--tg-theme-placeholder-color, #888888);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.select__multi-value {
|
||||
background-color: var(--tg-theme-selected-color, #0066ff);
|
||||
color: #ffffff;
|
||||
border-radius: 4px;
|
||||
|
||||
.select__multi-value__label {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.select__multi-value__remove {
|
||||
color: #ffffff;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
27
src/container/signup/interests/index.tsx
Normal file
27
src/container/signup/interests/index.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
import * as React from 'react';
|
||||
import { useState } from 'react';
|
||||
import { InterestsStyled } from './index.style';
|
||||
|
||||
const Interests = ({options, placeholder = "Выберите..."}): React.ReactElement => {
|
||||
|
||||
const [selectedInterests, setSelectedInterests] = useState<string | null>(null);
|
||||
|
||||
const handleChange = (selectedInterests) => {
|
||||
setSelectedInterests(selectedInterests);
|
||||
};
|
||||
|
||||
return (
|
||||
<InterestsStyled
|
||||
onChange={handleChange}
|
||||
closeMenuOnSelect={false}
|
||||
isMulti
|
||||
options={options}
|
||||
className="basic-multi-select"
|
||||
classNamePrefix="select"
|
||||
placeholder={placeholder}
|
||||
value={selectedInterests}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default Interests;
|
60
src/container/signup/name/index.style.ts
Normal file
60
src/container/signup/name/index.style.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import styled from '@emotion/styled';
|
||||
import TextField from '@mui/material/TextField';
|
||||
|
||||
export const TextFieldStyled = styled(TextField)`
|
||||
& .MuiInputBase-input {
|
||||
color: var(--tg-theme-text-color,rgba(0, 0, 0, 0.6));
|
||||
}
|
||||
|
||||
& .MuiFormLabel-root {
|
||||
color: var(--tg-theme-text-color, rgba(0, 0, 0, 0.6));
|
||||
}
|
||||
|
||||
& .Mui-focused .MuiFormLabel-root {
|
||||
color: var(--tg-theme-label-focus-color, #0066ff);
|
||||
}
|
||||
|
||||
|
||||
& .MuiOutlinedInput-root {
|
||||
fieldset {
|
||||
border-color: var(--tg-theme-border-color, #cccccc);
|
||||
}
|
||||
|
||||
&:hover fieldset {
|
||||
border-color: var(--tg-theme-border-hover, #888888);
|
||||
}
|
||||
|
||||
&.Mui-focused fieldset {
|
||||
border-color: var(--tg-theme-border-focused, #0066ff);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
& .MuiInputBase-input {
|
||||
color: var(--tg-theme-text-color-dark, #ffffff);
|
||||
}
|
||||
|
||||
& .MuiFormLabel-root {
|
||||
color: var(--tg-theme-label-color-dark, #ffffff);
|
||||
}
|
||||
|
||||
& .Mui-focused .MuiFormLabel-root {
|
||||
color: var(--tg-theme-label-focus-color-dark, #0066ff);
|
||||
}
|
||||
|
||||
& .MuiOutlinedInput-root {
|
||||
fieldset {
|
||||
border-color: var(--tg-theme-border-color-dark, #ffffff);
|
||||
}
|
||||
|
||||
&:hover fieldset {
|
||||
border-color: var(--tg-theme-border-hover-dark, #777777);
|
||||
}
|
||||
|
||||
&.Mui-focused fieldset {
|
||||
border-color: var(--tg-theme-border-focused-dark, #0066ff);
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
18
src/container/signup/name/index.tsx
Normal file
18
src/container/signup/name/index.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
import * as React from 'react';
|
||||
import { TextFieldStyled } from './index.style';
|
||||
|
||||
const Name = ({id, label, name, autoComplete, className = null}): React.ReactElement => {
|
||||
return (
|
||||
<TextFieldStyled
|
||||
required
|
||||
fullWidth
|
||||
id={id}
|
||||
label={label}
|
||||
name={name}
|
||||
autoComplete={autoComplete}
|
||||
className={className}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default Name;
|
@ -1,7 +1,7 @@
|
||||
import styled from '@emotion/styled';
|
||||
import Avatar from "@mui/material/Avatar";
|
||||
|
||||
export const PhotoStyled = styled.div`
|
||||
export const PhotoStyled = styled.div<{ value: string | null }>`
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
|
@ -2,7 +2,7 @@ import * as React from 'react';
|
||||
import { useState } from 'react';
|
||||
import { AvatarStyled, PhotoStyled, InputStyled } from './index.style';
|
||||
|
||||
const Photo = ({ defaultPhoto, onPhotoChange }): React.ReactElement => {
|
||||
const Photo = ({ defaultPhoto = null, onPhotoChange }): React.ReactElement => {
|
||||
const [photo, setPhoto] = useState(defaultPhoto);
|
||||
|
||||
const handleFileChange = (event) => {
|
||||
|
6
src/container/signup/title/index.style.ts
Normal file
6
src/container/signup/title/index.style.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
export const TitleStyled = styled.h1`
|
||||
font-size: 28px;
|
||||
color: var(--tg-theme-text-color);
|
||||
`;
|
@ -1,11 +1,11 @@
|
||||
import * as React from 'react';;
|
||||
import Typography from '@mui/material/Typography';
|
||||
import { TitleStyled } from './index.style';
|
||||
|
||||
const Title = ({children}): React.ReactElement => {
|
||||
return (
|
||||
<Typography component="h1" variant="h5">
|
||||
<TitleStyled>
|
||||
{children}
|
||||
</Typography>
|
||||
</TitleStyled>
|
||||
);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user