(null)
- const user = useAppSelector((state) => state.user)
- const { data } = useSession()
-
- useEffect(() => {
- if (!data?.access) {
- return
- }
-
- model_api.getImages(data?.access).then((res) => setBots(res))
- }, [data?.access])
-
- return (
-
- Изображения
-
- {bots ? (
- bots.map((item, idx) => {
- return (
-
- )
- })
- ) : (
-
- )}
-
-
- )
-}
-
-export default Images
+export default ImageModelsPage
\ No newline at end of file
@@ -1,47 +1,7 @@
-import React, { useEffect } from 'react'
-import { useDispatch } from 'react-redux'
-import { Box } from '@mui/material'
-import CircularProgress from '@mui/material/CircularProgress'
-import { useRouter } from 'next/router'
-
-import { addReferral } from '@/src/entities/user-account/model/user-type-slice'
+import { ReferralPage } from '#/views/referral'
export async function getServerSideProps({ params }: { params: Promise<{ email: string }> }) {
- const email = (await params).email
-
- return {
- props: {
- email,
- },
- }
-}
-
-function ReferralRegister({ email }: { email: string }) {
- const dispatch = useDispatch()
- const { push } = useRouter()
-
- useEffect(() => {
- localStorage.setItem('referral', email)
- dispatch(addReferral(email))
- push('/register')
- }, [])
-
- return (
-
-
-
- )
+ return { props: { email: (await params).email } }
}
-export default ReferralRegister
+export default ReferralPage
@@ -1,56 +1,3 @@
-import React from 'react'
-import { Box, Typography } from '@mui/material'
-import Link from 'next/link'
-import { useRouter } from 'next/router'
+import { NotFoundPage } from '#/views/not-found'
-import { Layout } from '@/src/main/layout'
-import { useAppSelector } from '@/src/main/store/store'
-
-const Custom404 = () => {
- const theme = useAppSelector((state) => state.theme.theme)
-
- const { push } = useRouter()
-
- React.useEffect(() => {
- setTimeout(() => push('/'), 7000)
- }, [])
-
- return (
-
-
-
-
- Ошибка 404
-
-
- К сожалению, такая страница не найдена 😢
-
-
-
- Вернуться на главную
-
-
-
-
-
- )
-}
-
-export default Custom404
+export default NotFoundPage
@@ -1,6 +1,6 @@
-import React from 'react'
+import React, { ReactElement, ReactNode } from 'react'
import { Provider } from 'react-redux'
-import { StyledEngineProvider } from '@mui/material'
+import { StyledEngineProvider, ThemeProvider } from '@mui/material'
import axios from 'axios'
import * as https from 'https'
import type { AppProps } from 'next/app'
@@ -8,12 +8,14 @@ import { Raleway } from 'next/font/google'
import { SessionProvider } from 'next-auth/react'
import { appWithTranslation } from 'next-i18next'
-import { store } from '@/src/main/store/store'
+import { store } from '#/app/store/store'
import ErrorBoundary from './error-boundary'
-import '@/src/main/styles/globals.css'
-import '@/src/main/styles/styles-pages/system.scss'
+import '#/app/styles/globals.css'
+import '#/app/styles/styles-pages/system.scss'
+import { NextPage } from 'next'
+import { pingFangFont } from '#/shared/lib/constants/font/font'
axios.defaults.httpsAgent = new https.Agent({
rejectUnauthorized: false,
@@ -21,7 +23,17 @@ axios.defaults.httpsAgent = new https.Agent({
const inter = Raleway({ subsets: ['latin'] })
-function App({ Component, pageProps: { session, ...pageProps } }: AppProps) {
+export type NextPageWithLayout = NextPage
& {
+ getLayout?: (page: ReactElement) => ReactNode
+ dynamicProps?: DP
+}
+
+export interface AppPropsWithLayout extends AppProps {
+ Component: NextPageWithLayout
+}
+
+function App({ Component, pageProps: { session, ...pageProps } }: AppPropsWithLayout) {
+ const getLayout = Component.getLayout ?? ((page) => page)
return (
<>
@@ -35,7 +47,9 @@ function App({ Component, pageProps: { session, ...pageProps } }: AppProps) {
-
+
+ {getLayout()}
+
@@ -27,7 +27,11 @@ export default function Document() {
@@ -1,581 +1,6 @@
-import * as React from 'react'
-import { useEffect, useMemo, useRef, useState } from 'react'
-import { Avatar, Box, Button, Stack, Tab, Tabs, Typography } from '@mui/material'
-import CircularProgress from '@mui/material/CircularProgress'
-import axios from 'axios'
-import Image from 'next/image'
-import { useRouter } from 'next/router'
-import { getServerSession } from 'next-auth'
-import { signOut, useSession } from 'next-auth/react'
+import { AccountPage } from '#/views/account'
+import { getDefaultLayout } from '#/widgets/layouts'
-import { getUserBalance } from '@/src/entities/balance'
-import { getAllInfo, unfollowEmail } from '@/src/entities/user-account/model/user-type-slice'
-import { Layout } from '@/src/main/layout'
-import { useAppDispatch, useAppSelector } from '@/src/main/store/store'
-import styles2 from '@/src/main/styles/accountTabs.module.css'
-import styles from '@/src/main/styles/business.module.scss'
-import { ButtonUI, Input, Loader, Modal, Success, SwitchCustom, useShowData } from '@/src/shared'
-import { accountApi } from '@/src/shared/api/account-endpoints'
-import { API_URL } from '@/src/shared/lib/constants/constants'
-import { getAccessToken, getTypeDevice } from '@/src/shared/lib/helpers'
-import { IProps } from '@/src/shared/lib/types/entities'
-import { ScreenForInactive } from '@/src/widgets/business'
-import BusinessHost from '@/src/widgets/business-host/business-host'
-import { Info } from '@/src/widgets/business-info'
-import { Subscription } from '@/src/widgets/payment/model/payment'
-import { Referral } from '@/src/widgets/referral'
+AccountPage.getLayout = getDefaultLayout({ titlePage: 'Аккаунт' })
-import { DownloadModal } from '../features/business-security-download/ui/download-modal'
-
-const scopes = [
- { title: 'Настройки', scope: 'setting' },
- { title: 'Управление оплатой', scope: 'subscribe' },
- { title: 'Корпоративный аккаунт', scope: 'business' },
- { title: 'Реферальная программа', scope: 'referral' },
-]
-
-export interface IPaymentsPlan {
- uid: string
- price: string
- tokens_per_plan: string
-}
-
-interface IAccountProps extends IProps {
- plans: IPaymentsPlan[] | null
- redirect?: {
- destination: string
- permanent: boolean
- }
-}
-
-export async function getServerSideProps(context: any): Promise<{ props: IAccountProps }> {
- const device = getTypeDevice(context)
-
- const token = (await getAccessToken(context.req)) || null
-
- //@ts-ignore
- const session = await getServerSession(context.req, context.res)
-
- const plans = token ? await accountApi.getPaymentsPlans(token) : null
-
- //@ts-ignore
- if (!session) {
- return {
- //@ts-ignore
- redirect: {
- destination: '/',
- permanent: false,
- },
- }
- }
- return {
- props: {
- device,
- token,
- plans,
- },
- }
-}
-
-const Account: React.FC = ({ device, token, plans }) => {
- const {
- email,
- is_subscribed_to_emails,
- account_type,
- first_name,
- last_name,
- username,
- profile_picture_link,
- is_social,
- status: userInfoLoaded,
- referral_code,
- } = useAppSelector((state) => state.user)
-
- const { status, account_type: type } = useAppSelector((state) => state.user)
-
- const [name, setName] = useState('')
-
- const [lastName, setLastName] = useState('')
-
- const fileInputRef = useRef(null)
-
- const [loading, setLoading] = useState(false)
-
- const { data } = useSession()
- const handleDivClick = () => {
- ;(fileInputRef.current! as any).click()
- }
-
- const dispatch = useAppDispatch()
-
- const { error, showError, isError } = useShowData()
-
- const handleFileChange = async (event: any) => {
- const formData = new FormData()
- formData.append('new_picture', event.target.files[0])
-
- try {
- setLoading(true)
- await axios.put(API_URL + '/auth/reset-profile-pic', formData, {
- headers: {
- Authorization: `Bearer ${data?.access}`,
- 'Content-Type': 'multipart/form-data',
- },
- })
- dispatch(getAllInfo(data?.access))
- showError('Изображение успешно загружено!')
- setLoading(false)
- } catch (e) {
- setLoading(false)
- showError('Ошибка загрузки изображения на сервере!', true)
- }
- }
-
- const [currentPassword, setCurrentPassword] = React.useState('')
-
- const [newPassword1, setNewPassword1] = React.useState('')
-
- const [newPassword2, setNewPassword2] = React.useState('')
-
- const [promocode, setPromocode] = React.useState('')
-
- const [success, setSuccess] = React.useState('')
-
- const [confirmDeleteModal, setConfirmDeleteModal] = useState(false)
-
- const { push, query } = useRouter()
-
- const [scope, setScope] = useState(query['scope'] || 'setting')
-
- const [downloadModal, setDownloadModal] = useState(false)
-
- const desktop = device === 'desktop'
-
- const changeScope = async (scope: string) => {
- setScope(scope)
- await addQueryParams(scope)
- }
-
- async function addQueryParams(scope: string) {
- await push({
- pathname: '/account',
- query: { scope },
- })
- }
-
- useEffect(() => {
- if (query['scope'] !== undefined && scope !== query['scope']) {
- changeScope(query['scope'] as string)
- }
- }, [query])
-
- useEffect(() => {
- if (Object.keys(query).length === 0) addQueryParams('setting')
- }, [])
-
- const changePassword = async () => {
- if (newPassword1 !== newPassword2) {
- showError('Укажите одинаковые новы пароли!', true)
- return
- }
- const status = await accountApi.changePassword(token, newPassword1, newPassword2, currentPassword)
-
- if (status === 200) {
- showError('Пароль успешно изменён!')
- setNewPassword1('')
- setNewPassword2('')
- setCurrentPassword('')
- setTimeout(() => setSuccess(''), 6000)
- return
- }
-
- showError('К сожалению, произошла ошибка', true)
- }
-
- function body() {
- if (type === 'regular') {
- return (
-
-
-
- )
- }
- if (type === 'business_account') {
- return Информация о корп.аккаунте доступна только владельцу и администраторам.
- }
- if (type === 'business_host') {
- return
- }
- if (type === 'business_admin') {
- return
- }
- if (type === 'business_security') {
- return (
- <>
-
-
-
-
- Раздел 1. Запросы сотрудников по моделям
-
-
- {
- setDownloadModal(true)
- }}
- sx={{ marginTop: '20px' }}
- text={'Скачать'}
- />
-
-
- >
- )
- }
- }
-
- const isUserDataChange = useMemo(() => name !== first_name || last_name !== lastName, [name, lastName])
-
- const promocodeActivate = async () => {
- if (!promocode.trim()) {
- showError('Введите корректный промокод', true)
- return
- }
- let resStatus = 404
- try {
- const { status } = await axios.post(
- API_URL + '/payments/promocode',
- { code: promocode },
- { headers: { Authorization: `Bearer ${token}` } }
- )
- resStatus = status
- } catch (e) {}
-
- if (resStatus === 200) {
- showError('Промокод успешно активирован! Токены уже зачислены!')
- dispatch(getUserBalance(data?.access))
- return
- }
-
- if (resStatus === 403) {
- showError('Промокод уже был активирован!', true)
- return
- }
-
- if (resStatus === 404) {
- showError('Промокод не найден!', true)
- return
- }
- }
-
- async function changeUserData() {
- if (!isUserDataChange) {
- showError('Вы не изменили данные', true)
- return
- }
-
- try {
- await axios.put(
- API_URL + '/auth/user-data',
- {
- username: username,
- email: email,
- first_name: name,
- last_name: lastName,
- },
- { headers: { Authorization: `Bearer ${token}` } }
- )
-
- showError('Данные успешно изменены!')
- dispatch(getAllInfo(token))
- } catch (e) {}
- }
-
- const deleteAccount = async () => {
- try {
- const { status } = await axios.delete(API_URL + '/auth/remove', {
- headers: {
- Authorization: `Bearer ${token}`,
- },
- })
-
- if (status === 200) await signOut()
- } catch (err) {}
- }
-
- useEffect(() => {
- setName(first_name)
- setLastName(last_name)
- }, [first_name, last_name])
-
- return (
-
-
-
-
- Ваш аккаунт
-
- {scopes.map((el) => {
- if (!desktop && el.scope === 'business') {
- return null
- }
- if (el.scope === 'referral' && account_type !== 'regular') {
- return null
- }
- return (
- changeScope(el.scope)}
- key={el.title}
- className={scope === el.scope ? styles2.wrap_toggle_button_active : styles2.wrap_toggle_button}
- value={el.scope}
- label={el.title}
- />
- )
- })}
-
- {scope === 'setting' ? (
- <>
-
- Основные
-
-
-
-
-
- {!loading || !(userInfoLoaded === 'succeeded') ? (
-
- ) : (
-
- )}
-
-
- {''}
-
-
-
-
-
- Имя
- setName(e.target.value)}
- fullWidth
- />
-
-
- Фамилия
- setLastName(e.target.value)}
- fullWidth
- />
-
-
-
- Email
-
- {
- await dispatch(unfollowEmail(token))
- showError('Данные изменены!')
- }}
- />
-
- Отписаться от рассылки
-
-
-
-
-
-
- Никнейм
-
-
-
- {/*referral_code.code.trim() && (
-
- Ваша реферальная ссылка:
-
-
- navigator.clipboard.writeText(referral_code.code.trim())}
- className='text'
- sx={{ color: '#8280FF !important', cursor: 'pointer' }}
- >
- {referral_code.code}
-
-
-
-) */}
-
-
-
-
- Активация промокода
- setPromocode(e.target.value)}
- fullWidth
- />
-
-
- {!is_social && (
-
- Изменить пароль
-
-
- Текущий пароль
- setCurrentPassword(e.target.value)}
- fullWidth
- />
-
-
-
- Новый пароль
- setNewPassword1(e.target.value)}
- fullWidth
- />
-
-
- Подтвердить пароль
- setNewPassword2(e.target.value)}
- fullWidth
- />
-
-
-
-
-
- )}
-
- Удаление аккаунта
- Удаление аккаунта приведет к потере всех настроек
- setConfirmDeleteModal(true)}
- sx={{ marginTop: '20px' }}
- text={'Удалить аккаунт'}
- style={{
- width: '100%',
- backgroundColor: 'rgba(255, 35, 114, 0.10)',
- color: '#FF2372',
- }}
- />
-
-
- setConfirmDeleteModal(false)}>
-
- Удаление аккаунта
- Вы действительно хотите удалить ваш аккаунт?
-
-
-
- >
- ) : scope === 'business' ? (
-
- {status == 'pending' || type === null ? (
-
-
-
- ) : (
- {body()}
- )}
-
- ) : scope === 'subscribe' ? (
-
- ) : scope === 'referral' && account_type === 'regular' ? (
-
- ) : (
- <>>
- )}
-
-
-
-
-
- )
-}
-
-export default Account
+export default AccountPage
@@ -1,49 +1,6 @@
-import React from 'react'
-import { Stack } from '@mui/material'
-import { getSession } from 'next-auth/react'
+import { AdminPage } from '#/views/admin'
+import { getDefaultLayout } from '#/widgets/layouts'
-import { Layout } from '@/src/main/layout'
-import { useAppSelector } from '@/src/main/store/store'
-import { getAccessToken, getTypeDevice } from '@/src/shared/lib/helpers'
-import { IProps } from '@/src/shared/lib/types/entities'
-import { StatsField } from '@/src/widgets/stats-field'
+AdminPage.getLayout = getDefaultLayout({ titlePage: 'Админка' })
-export async function getServerSideProps(context: any): Promise<{ props: any }> {
- const device = getTypeDevice(context)
-
- const token = (await getAccessToken(context.req)) || null
-
- const { req } = context
- const session = await getSession({ req })
-
- if (true) {
- return {
- //@ts-ignore
- redirect: {
- destination: '/',
- permanent: false,
- },
- }
- }
-
- return {
- props: {
- device,
- token,
- },
- }
-}
-
-const Admin: React.FC = ({ token, device }) => {
- const theme = useAppSelector((state) => state.theme.theme)
-
- return (
-
-
-
-
-
- )
-}
-
-export default Admin
+export default AdminPage
@@ -1,219 +1,6 @@
-import React, { useEffect, useState } from 'react'
-import { Box, Stack, Table, TableBody, TableHead, TableRow, TextField, Typography } from '@mui/material'
-import Button from '@mui/material/Button'
-import TableCell from '@mui/material/TableCell'
-import axios from 'axios'
-import Image from 'next/image'
-import Link from 'next/link'
-import { useSession } from 'next-auth/react'
+import { ApiKeysPage } from '#/views/api-keys'
+import { getDefaultLayout } from '#/widgets/layouts'
-import { getAll, ResponseAllInfo } from '@/src/entities/user-account/model/user-type-slice'
-import { ApiKeyModal } from '@/src/features/api-key-modal/api-key-modal'
-import { Layout } from '@/src/main/layout'
-import { useAppSelector } from '@/src/main/store/store'
-import { TooltipCustom } from '@/src/shared'
-import { accountApi } from '@/src/shared/api/account-endpoints'
-import { API_URL } from '@/src/shared/lib/constants'
-import styles from '@/src/shared/styles/api-keys.module.scss'
-import { InputStyleSmallDark, InputStyleSmallLight } from '@/src/shared/ui/input'
+ApiKeysPage.getLayout = getDefaultLayout({ device: 'desktop', titlePage: 'API-ключи' })
-const ApiKeys: React.FC = () => {
- const [keys, setKeys] = useState | null>(null)
- const [loading, setLoading] = useState(false)
- const { data, status } = useSession()
- const [modal, setModal] = useState(false)
- const [userInfo, setUserInfo] = useState()
- const [disabled, setDisabled] = React.useState(true)
-
- useEffect(() => {
- getAll(data?.access).then((res) => setUserInfo(res))
- }, [data?.access])
-
- useEffect(() => {
- if (status === 'authenticated') {
- setLoading(true)
- accountApi.getApiKeys(data?.access).then((res) => {
- setKeys(res)
- setLoading(false)
- })
- }
- }, [status])
-
- React.useEffect(() => {
- if (
- userInfo?.account_type === 'business_security' ||
- userInfo?.account_type === 'business_account' ||
- status !== 'authenticated' ||
- loading
- ) {
- setDisabled(true)
- } else {
- setDisabled(false)
- }
- }, [status, userInfo, loading])
-
- const deleteKey = async (name: string) => {
- if (keys === null || status !== 'authenticated') {
- return
- }
-
- setLoading(true)
- const result = await accountApi.deleteApiKey(name, data?.access)
- if (result !== null && result === 200) {
- accountApi.getApiKeys(data?.access).then((res) => {
- setKeys(res)
- setLoading(false)
- })
- }
- setLoading(false)
- }
-
- return (
- <>
-
-
-
- API ключи
-
-
-
-
- API-ключ — это инструмент, который идентифицирует пользователя или программу, запрашивающих доступ к API платформы.
- С помощью ключа можно отслеживать, кто и когда пользуется API, рассчитывать оплату.
-
-
-
-
-
- Документация
-
-
-
-
-
- {keys && keys.length !== 0 ? (
-
- Мои ключи
-
-
-
- Имя
- Ключ
- Лимит токенов
- Создан
- Действителен до
-
-
-
- {keys &&
- keys.map((el) => {
- return (
-
- )
- })}
-
-
-
- ) : (
-
-
- У вас пока нет ключей 😞
- Создайте первый ключ
-
-
- )}
-
-
- >
- )
-}
-
-const KeyRow = (props: any) => {
- const [isCopy, setIsCopy] = useState(false)
- const [limit, setLimit] = useState(props.limit)
- const theme = useAppSelector((state) => state.theme.theme)
- const { data: session } = useSession()
-
- const copy = (text: string) => {
- navigator.clipboard.writeText(text)
- setIsCopy(true)
- setTimeout(() => setIsCopy(false), 3000)
- }
-
- useEffect(() => {
- let timeout = window.setTimeout(() => {
- if (limit !== props.limit) {
- axios.patch(
- API_URL + '/public/api-key',
- { token_limit: Number(limit), name: props.name },
- { headers: { Authorization: `Bearer ${session?.access}` } }
- )
- }
- }, 1000)
- return () => window.clearTimeout(timeout)
- }, [limit])
-
- return (
-
-
- {props.name}
-
-
- {props.keyValue}
-
-
- setLimit(e.target.value)}
- sx={theme === 'light' ? { ...InputStyleSmallLight } : { ...InputStyleSmallDark }}
- />
-
-
- {props.created_at.split('T')[0]}
-
-
- {props.expires_at !== null ? props.expires_at : 'Бессрочно'}
-
-
-
- {isCopy ? (
-
- ) : (
-
- copy(props.keyValue)}
- src={'/svg/copy.svg'}
- width={20}
- height={20}
- style={{ cursor: 'pointer' }}
- alt={'copy'}
- />
-
- )}
- props.deleteKey(props.name)}
- style={{ cursor: 'pointer' }}
- src='/svg/main_menu/trash.svg'
- width={20}
- height={20}
- alt='Удалить'
- />
-
-
-
- )
-}
-
-export default ApiKeys
+export default ApiKeysPage
@@ -1,50 +1,6 @@
-import React, { useEffect } from 'react'
-import { Box } from '@mui/system'
-import axios from 'axios'
-import { useRouter } from 'next/router'
-import process from 'process'
+import AuthSocial from '#/views/auth-social/ui/auth-social'
+import { getDefaultLayout } from '#/widgets/layouts'
-import { Layout } from '@/src/main/layout'
-import { API_URL } from '@/src/shared/lib/constants'
-import { getTypeDevice } from '@/src/shared/lib/helpers'
-import { Device } from '@/src/shared/lib/types/entities'
-
-const client_secret = process.env.NEXT_PUBLIC_DJANGO_GOOGLE_APP_CLIENT_SECRET
-const client_id = process.env.NEXT_PUBLIC_DJANGO_GOOGLE_APP_CLIENT_ID
-
-export async function getServerSideProps(context: any): Promise<{ props: { device: Device } }> {
- const device = getTypeDevice(context)
-
- return {
- props: {
- device,
- },
- }
-}
-
-async function getTokenByAPIGoogle(token: string) {
- const { data } = await axios.post(API_URL + '/auth/login-social/convert-token', {
- grant_type: 'convert_token',
- client_id: client_id,
- client_secret: client_secret,
- backend: 'google-oauth2',
- token: token,
- })
-
- return data
-}
-
-const AuthSocial: React.FC<{ device: Device }> = ({ device }) => {
- useEffect(() => {
- const token = new URLSearchParams(window.location.href.replace('#', '&')).get('access_token') || ''
- getTokenByAPIGoogle(token).then((res) => res)
- }, [])
-
- return (
-
-
-
- )
-}
+AuthSocial.getLayout = getDefaultLayout({ titlePage: 'Редирект' })
export default AuthSocial
@@ -0,0 +1,6 @@
+import { ChangePasswordPage } from '#/views/change-password'
+import { getLayout, LayoutWithoutSideMenu } from '#/widgets/layouts'
+
+ChangePasswordPage.getLayout = getLayout(LayoutWithoutSideMenu, { titlePage: 'Смена пароля' })
+
+export default ChangePasswordPage
@@ -1,83 +1,6 @@
-import React from 'react'
-import { Box, Typography } from '@mui/material'
-import axios from 'axios'
-import Link from 'next/link'
-import { useRouter } from 'next/router'
+import { ConfirmPage } from '#/views/confirm'
+import { getLayout, LayoutWithoutSideMenu } from '#/widgets/layouts'
-import { Layout } from '@/src/main/layout'
-import { API_URL } from '@/src/shared/lib/constants/constants'
+ConfirmPage.getLayout = getLayout(LayoutWithoutSideMenu, { titlePage: 'Подтверждение' })
-export async function getServerSideProps(context: any): Promise<{ props: any }> {
- const UA = context.req.headers['user-agent']
- const isMobile = Boolean(UA.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile|WPDesktop/i))
- return {
- props: {
- device: isMobile ? 'mobile' : 'desktop',
- },
- }
-}
-
-const Confirm: React.FC = () => {
- const { push, query } = useRouter()
- const [success, setSuccess] = React.useState(false)
-
- React.useEffect(() => {
- let formData: any = new FormData()
-
- formData.append('token', query.token)
-
- axios.post(API_URL + '/auth/confirm', formData, {
- headers: {
- 'Content-Type': 'multipart/form-data',
- },
- })
- .then(() => {
- setSuccess(true)
- })
- .catch(() => {
- push('/')
- })
- }, [])
-
- React.useEffect(() => {
- if (success) {
- setTimeout(() => push('/login'), 10000)
- }
- }, [success])
-
- return (
-
-
-
- {' '}
- {success ? (
- <>
-
- Ваша почта подтверждена, вы будете перенаправлены на страницу авторизации
-
-
- Войти в аккаунт
-
- >
- ) : (
- 'Подтверждение...'
- )}
-
-
-
- )
-}
-
-export default Confirm
+export default ConfirmPage
@@ -1,88 +1,7 @@
-import * as React from 'react'
-import { useMemo } from 'react'
-import { useCookies } from 'react-cookie'
-import { Box, Stack, Typography } from '@mui/material'
-import { serialize } from 'cookie'
-import { GetServerSidePropsContext } from 'next'
-import { useRouter } from 'next/router'
-import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
+import { MainPage } from '#/views/index'
+import { getDefaultLayout } from '#/widgets/layouts'
-import { Layout } from '@/src/main/layout'
-import { useAppSelector } from '@/src/main/store/store'
-import styles from '@/src/main/styles/styles-pages/index-styles.module.scss'
-import { ReferralBlock } from '@/src/shared'
-import { getTypeDevice } from '@/src/shared/lib/helpers'
-import { getCurrentTimeAndGreeting } from '@/src/shared/lib/helpers/getCurrentDateForMainScreen'
-import { TelegramBlock } from '@/src/shared/ui/telegram-block'
-import { DemoInfo } from '../shared/ui/demo-info'
-import { SocialMedia } from '../shared/ui/social-media-block'
-import { Statistics } from '../widgets/stats/stats'
+MainPage.getLayout = getDefaultLayout({ titlePage: 'AIR' })
-export async function getServerSideProps(context: GetServerSidePropsContext): Promise<{ props: any }> {
- const deviceType = getTypeDevice(context)
-
- const { res, query } = context
-
- const allCookies = Object.entries(query).map((key, value) => serialize(key.toString(), value.toString()))
-
- res.setHeader('Set-Cookie', allCookies)
- res.setHeader('Set-Cookie', '111')
- return {
- props: {
- ...(await serverSideTranslations((context as any).locale, ['common'])),
- deviceType,
- },
- }
-}
-
-export const Main: React.FC = ({ deviceType }) => {
- const { first_name, account_type } = useAppSelector((state) => state.user)
-
- const [, setCookie] = useCookies()
-
- const { query, push } = useRouter()
-
- React.useEffect(() => {
- Object.entries(query).forEach(([key, value]) => setCookie(key, value))
- }, [])
-
- const [greeting, time] = useMemo(() => getCurrentTimeAndGreeting(first_name), [first_name])
-
- return (
-
-
-
- {time}
- {greeting}
-
-
-
- {/**/}
-
- {account_type === 'regular' && }
-
-
- Полезная статья
-
-
- {' '}
- Что такое токен ?
-
-
- Токен — это цифровая валюта для оплаты ИИ-продуктов и услуг. Юзеры используют эту валюту, чтобы
- получить либо доступ к нейросетям, либо результат генерации — текст, картинку и т.д. Еще токенами
- называют единицы текста, на которых обучается нейросеть. Например, в предложении «Я люблю шоколад»
- слова «Я», «люблю» и «шоколад» могут быть токенами.
-
-
-
-
-
-
-
-
- )
-}
-
-export default Main
+export default MainPage
@@ -1,47 +1,6 @@
-import React from 'react'
-import { getSession } from 'next-auth/react'
+import { RegisterBusinessPage } from '#/views/register-business'
+import { getLayout, LayoutWithoutSideMenu } from '#/widgets/layouts'
-import { Stepper } from '@/src/features/register-business'
-import { Layout } from '@/src/main/layout'
-import { getAccessToken, getTypeDevice } from '@/src/shared/lib/helpers'
-import { Device } from '@/src/shared/lib/types/entities'
+RegisterBusinessPage.getLayout = getLayout(LayoutWithoutSideMenu, { titlePage: 'Регистрация' })
-type BusinessProps = {
- device: Device
- token: string | null
-}
-export async function getServerSideProps(context: any): Promise<{ props: BusinessProps }> {
- const token = (await getAccessToken(context.req)) || null
-
- const device = getTypeDevice(context)
-
- const { req } = context
- const session = await getSession({ req })
-
- //@ts-ignore
- if (!token) {
- return {
- //@ts-ignore
- redirect: {
- destination: '/',
- permanent: false,
- },
- }
- }
-
- return {
- props: {
- device,
- token,
- },
- }
-}
-const Register: React.FC = ({ device }) => {
- return (
-
-
-
- )
-}
-
-export default Register
+export default RegisterBusinessPage
@@ -1,246 +1,6 @@
-import React, { ChangeEvent } from 'react'
-import AttachFileIcon from '@mui/icons-material/AttachFile'
-import CloseIcon from '@mui/icons-material/Close'
-import { Box, Button, Stack, TextField, Typography } from '@mui/material'
-import axios from 'axios'
-import { useSession } from 'next-auth/react'
+import { ReportsMobilePage } from '#/views/reports-mobile'
+import { getDefaultLayout } from '#/widgets/layouts'
-import { Layout } from '@/src/main/layout'
-import { useAppSelector } from '@/src/main/store/store'
-import { API_URL } from '@/src/shared/lib/constants/constants'
+ReportsMobilePage.getLayout = getDefaultLayout({ titlePage: 'Сообщить об ошибке', device: 'mobile' })
-const styleSend = {
- position: 'absolute' as 'absolute',
- top: '50%',
- left: '50%',
- transform: 'translate(-50%, -65%)',
- width: 300,
- height: 'auto',
- bgcolor: 'background.paper',
- borderRadius: 5,
- boxShadow: 16,
- p: 4,
- textAlign: 'center',
-}
-
-const styleSendDark = {
- position: 'absolute' as 'absolute',
- top: '50%',
- left: '50%',
- transform: 'translate(-50%, -65%)',
- width: 300,
- height: 'auto',
- bgcolor: '#2B2828',
- borderRadius: 5,
- boxShadow: 16,
- p: 4,
- textAlign: 'center',
-}
-
-const styleMobile = {
- width: '100%',
- position: 'absolute' as 'absolute',
- top: '35%',
- left: '50%',
- transform: 'translate(-50%, -50%)',
- p: 4,
- zIndex: 99,
-}
-
-const ReportsMobile = () => {
- const [errorMessage, setErrorMessage] = React.useState('')
-
- const [error, setError] = React.useState(false)
-
- const [isSend, setIsSend] = React.useState(false)
-
- const [file, setFile] = React.useState()
-
- const { data: session } = useSession()
-
- const theme = useAppSelector((state) => state.theme.theme)
-
- const email = useAppSelector((state) => state.user.email)
-
- const sendError = async () => {
- if (errorMessage.trim() === '') {
- setError(true)
- setTimeout(() => setError(false), 3000)
- return
- }
-
- let formData: any = new FormData()
-
- formData.append('report_text', `${email}: ${errorMessage}`) //append the values with key, value pair
- if (file) {
- formData.append('images', file)
- }
-
- try {
- const { status } = await axios.post(API_URL + '/reports/', formData, {
- headers: {
- 'content-type': 'multipart/form-data ',
- 'content-length': file ? `${file.size}` : '',
- Authorization: `Bearer ${session?.access}`,
- },
- })
-
- if (status === 201) {
- setErrorMessage('')
- setIsSend(true)
- setTimeout(() => {
- setIsSend(false)
- }, 4000)
- }
- } catch (err) {
- setError(true)
- setTimeout(() => setError(false), 3000)
- }
- }
-
- const handleFileChange = (e: ChangeEvent) => {
- if (e.target.files) {
- setFile(e.target.files[0])
- }
- }
-
- return (
-
- {isSend ? (
-
- Спасибо!
-
- Ваше сообщение направлено нашим специалистам. Ответ придет на почту, указанную при регистрации
-
-
- ) : (
-
-
- Сообщить об ошибке
-
- setErrorMessage(evt.target.value)}
- InputProps={{
- startAdornment: (
- <>
-
- >
- ),
- }}
- sx={{
- marginTop: 2.5,
- marginBottom: 1.2,
- fontSize: 13,
- '& label': { color: 'red' },
- backgroundColor: theme === 'light' ? 'transparent' : '#3D3D3D',
- input: {
- color: theme === 'light' ? '#272727' : '#E1E1E1',
- },
- }}
- />
- {file && (
-
- Добавлено 1 изображение: {file.name}
- setFile(undefined)}
- sx={{
- width: '18px',
- height: '18px',
- cursor: 'pointer',
- marginLeft: '3px',
- marginTop: '2px',
- }}
- />
-
- )}
-
-
-
-
-
- )}
-
- )
-}
-
-export default ReportsMobile
+export default ReportsMobilePage
@@ -1,173 +1,6 @@
-import * as React from 'react'
-import { useState } from 'react'
-import { Box, Card, CardMedia, Link, Stack, TextField, Typography } from '@mui/material'
-import Button from '@mui/material/Button'
-import axios from 'axios'
-import Image from 'next/image'
-import Router from 'next/router'
+import { ResetPage } from '#/views/reset'
+import { getLayout, LayoutWithoutSideMenu } from '#/widgets/layouts'
-import { Layout } from '@/src/main/layout'
-import { useAppSelector } from '@/src/main/store/store'
-import { getRandomImage } from '@/src/pages/login'
-import { Error, Input } from '@/src/shared'
-import { API_URL } from '@/src/shared/lib/constants/constants'
-import { getTypeDevice } from '@/src/shared/lib/helpers'
-import { TDeviceProp } from '@/src/shared/lib/types/entities'
+ResetPage.getLayout = getLayout(LayoutWithoutSideMenu, { titlePage: 'Сброс пароля' })
-export async function getServerSideProps(context: any): Promise<{ props: TDeviceProp }> {
- const device = getTypeDevice(context)
-
- return {
- props: {
- device,
- },
- }
-}
-
-const Reset: React.FC = ({ device }) => {
- const [input_email, set_Email] = useState('')
- const [isSend, setIsSend] = useState(false)
- const [isError, setIsError] = React.useState(false)
- const sendMail = () => {
- axios.post(API_URL + '/auth/update-pass', {
- email: input_email,
- })
- .then(function (response) {
- if (response.status === 200) {
- setIsSend(true)
- setTimeout(() => Router.push('/login'), 10000)
- }
- })
- .catch(function (error) {
- setIsError(true)
- setTimeout(() => setIsError(false), 4000)
- })
- }
-
- const desktop = device === 'desktop'
-
- const refImage = React.useRef(getRandomImage())
-
- const theme = useAppSelector((state) => state.theme.theme)
-
- return (
-
-
- {desktop && (
-
-
-
-
- Midjourney
-
-
- by honeynek
-
-
-
-
- )}
- {!isSend ? (
-
-
- Забыли пароль?
-
-
- Введите адрес электронной почты, которую вы использовали для регистрации в сервисе
-
-
-
- Email
-
-
- set_Email(event.target.value)} type={'email'} fullWidth />
-
-
-
-
-
-
-
-
-
- ) : (
-
-
- Письмо для восстановления пароля отправлено вам на почту!
-
-
- )}
-
-
- )
-}
-
-export default Reset
+export default ResetPage
@@ -1,30 +1,6 @@
-import React from 'react'
-import { Box } from '@mui/material'
+import { WhisperPage } from '#/views/whisper'
+import { getDefaultLayout } from '#/widgets/layouts'
-import { Layout } from '@/src/main/layout'
-import { getTypeDevice } from '@/src/shared/lib/helpers'
-import { Device } from '@/src/shared/lib/types/entities'
-import { WhisperWidget } from '@/src/widgets/whisper'
+WhisperPage.getLayout = getDefaultLayout({ titlePage: 'Whisper' })
-export async function getServerSideProps(context: any): Promise<{ props: { device: Device } }> {
- const device = getTypeDevice(context)
-
- return {
- props: {
- device,
- },
- }
-}
-const Whisper: React.FC<{ device: Device }> = ({ device }) => {
- return (
-
-
-
-
-
-
-
- )
-}
-
-export default Whisper
+export default WhisperPage
@@ -1,7 +1,7 @@
import axios from 'axios'
-import { IModel, IShortModel } from '@/src/shared/api/models/models'
-import { API_URL } from '@/src/shared/lib/constants'
+import { IModel, IShortModel } from '#/shared/api/models/models'
+import { API_URL } from '#/shared/lib/constants'
const model_api = {
async getBots(token?: string): Promise {
@@ -4,12 +4,12 @@ import base64 from 'base64-encode-file'
import { useSession } from 'next-auth/react'
import process from 'process'
-import { getUserBalance } from '@/src/entities/balance'
-import { useAppDispatch } from '@/src/main/store/store'
-import { API_URL } from '@/src/shared/lib/constants'
-import { Device } from '@/src/shared/lib/types/entities'
-import { Message, MessageSend } from '@/src/shared/lib/types/model'
-import { IMessageRequest } from '@/src/shared/lib/types/types-gpt'
+import { getUserBalance } from '#/entities/balance'
+import { useAppDispatch } from '#/app/store/store'
+import { API_URL } from '#/shared/lib/constants'
+import { Device } from '#/shared/lib/types/entities'
+import { Message, MessageSend } from '#/shared/lib/types/model'
+import { IMessageRequest } from '#/shared/lib/types/types-gpt'
const formDataHelper = (file: File, dataForSend: MessageSend): FormData => {
const FD = new FormData()
@@ -23,11 +23,14 @@ const formDataHelper = (file: File, dataForSend: MessageSend): FormData =>
export const ModelsWithChatsEndpoints = {
getData: async (chatUid: string, offset: number, token?: string) => {
try {
- const { data } = await axios.get(API_URL + `/chats/${chatUid}/messages/?limit=10&offset=${offset}`, {
- headers: {
- Authorization: `Bearer ${token}`,
- },
- })
+ const { data } = await axios.get(
+ API_URL + `/chats/${chatUid}/messages/?limit=10&offset=${offset}`,
+ {
+ headers: {
+ Authorization: `Bearer ${token}`,
+ },
+ }
+ )
return data
} catch (err: any) {
return {
@@ -41,13 +44,17 @@ export const ModelsWithChatsEndpoints = {
const HeaderDataType = dataForSend instanceof FormData ? 'multipart/form-data' : 'application/json'
try {
- const { data } = await axios.post>(API_URL + `/chats/${chatUid}/messages/`, dataForSend, {
- withCredentials: true,
- headers: {
- Authorization: `Bearer ${token}`,
- 'Content-Type': HeaderDataType,
- },
- })
+ const { data } = await axios.post>(
+ API_URL + `/chats/${chatUid}/messages/`,
+ dataForSend,
+ {
+ withCredentials: true,
+ headers: {
+ Authorization: `Bearer ${token}`,
+ 'Content-Type': HeaderDataType,
+ },
+ }
+ )
return data
} catch (err: any) {
@@ -165,7 +172,7 @@ export function useModel(
setMessages((prev) => [...prev!, userMessage])
try {
//@ts-ignore
- const message = (result.details as AxiosError).response.data.trim() ?? 'Ошибка отправки сообщения'
+ const message = (result.details as AxiosError).response!.data.trim() ?? 'Ошибка отправки сообщения'
showError(message)
return
} catch (e) {
@@ -212,13 +219,17 @@ export const ModelsWithImagesEndpoints = {
const HeaderDataType = dataForSend instanceof FormData ? 'multipart/form-data' : 'application/json'
try {
- const { data } = await axios.post>(API_URL + `/media/image/${type}`, dataForSend, {
- withCredentials: true,
- headers: {
- Authorization: `Bearer ${token}`,
- 'Content-Type': HeaderDataType,
- },
- })
+ const { data } = await axios.post>(
+ API_URL + `/media/image/${type}`,
+ dataForSend,
+ {
+ withCredentials: true,
+ headers: {
+ Authorization: `Bearer ${token}`,
+ 'Content-Type': HeaderDataType,
+ },
+ }
+ )
return data
} catch (err: any) {
@@ -375,12 +386,16 @@ export const ModelsMediaApi = {
},
sendData: async (type: string | null, dataForSend: MessageSend | FormData, token?: string) => {
try {
- const { data } = await axios.post>(API_URL + `/media/audio/${type}`, dataForSend, {
- withCredentials: true,
- headers: {
- Authorization: `Bearer ${token}`,
- },
- })
+ const { data } = await axios.post>(
+ API_URL + `/media/audio/${type}`,
+ dataForSend,
+ {
+ withCredentials: true,
+ headers: {
+ Authorization: `Bearer ${token}`,
+ },
+ }
+ )
return data
} catch (err: any) {
@@ -1,8 +1,8 @@
import axios, { AxiosResponse } from 'axios'
import { User } from 'next-auth'
-import { API_URL } from '@/src/shared/lib/constants'
-import { IOffer } from '@/src/widgets/payment/model/payment'
+import { API_URL } from '#/shared/lib/constants'
+import { IOffer } from '#/widgets/payment/model/payment'
interface IUserBalance {
current_token_balance: number
@@ -61,7 +61,12 @@ export const accountApi = {
}
},
- async changePassword(token: string | null, password_1: string, password_2: string, current_password: string): Promise {
+ async changePassword(
+ token: string | null,
+ password_1: string,
+ password_2: string,
+ current_password: string
+ ): Promise {
try {
const { status } = await axios.put(
API_URL + '/auth/reset-pass',
@@ -2,10 +2,10 @@ import axios, { AxiosResponse } from 'axios'
import { Session } from 'next-auth'
import * as process from 'process'
-import { Chat } from '@/src/shared/api/type-model-chats'
-import { Error } from '@/src/shared/lib/types/entities'
-import { IImagesResponse } from '@/src/shared/lib/types/types-dalle'
-import { IMessageRequest, ISendMessageResponse } from '@/src/shared/lib/types/types-gpt'
+import { Chat } from '#/shared/api/type-model-chats'
+import { Error } from '#/shared/lib/types/entities'
+import { IImagesResponse } from '#/shared/lib/types/types-dalle'
+import { IMessageRequest, ISendMessageResponse } from '#/shared/lib/types/types-gpt'
import { Message } from '../lib/types/model'
@@ -96,12 +96,16 @@ export const api = {
async sendMessageChatGPT(token: string, message: any, uid: string): Promise {
try {
- const { data } = await axios.post>(API_URL + `/chats/${uid}/messages/`, message, {
- withCredentials: true,
- headers: {
- Authorization: `Bearer ${token}`,
- },
- })
+ const { data } = await axios.post>(
+ API_URL + `/chats/${uid}/messages/`,
+ message,
+ {
+ withCredentials: true,
+ headers: {
+ Authorization: `Bearer ${token}`,
+ },
+ }
+ )
return { data, isError: false }
} catch (err) {
@@ -157,7 +161,9 @@ export const createChat = async (model: string, token?: string) => {
export const getAllChats = async (model: string, token?: string): Promise => {
try {
- const { data } = await axios.get(API_URL + `/chats/?model=${model}`, { headers: { Authorization: `Bearer ${token}` } })
+ const { data } = await axios.get(API_URL + `/chats/?model=${model}`, {
+ headers: { Authorization: `Bearer ${token}` },
+ })
if (data.length === 0) {
const newChat = await createChat(model, token)
@@ -1,32 +1,30 @@
.card {
- width: 381px;
- overflow: hidden;
- position: relative;
- height: 290px;
- border-radius: 15px;
- background-color: var(--new-ui-main-color);
- margin-top: 15px;
- margin-right: 20px;
+ width: 381px;
+ overflow: hidden;
+ position: relative;
+ height: 290px;
+ border-radius: 15px;
+ background-color: var(--new-ui-main-color);
+ margin-top: 15px;
+ margin-right: 20px;
- @media (max-width:420px) {
- width: 92vw;
- height: 300px;
- }
-
- .description {
- padding: 15px 20px;
+ @media (max-width: 420px) {
+ width: 92vw;
+ height: 300px;
+ }
- .title {
- color: var(--new-ui-text-color);
- font-weight: 600;
- font-size: 21px;
- }
- .text {
- margin-top: 15px;
- font-size: 15px;
- color: var(--new-ui-gray-color);
- }
- }
+ .description {
+ padding: 15px 20px;
-
-}
\ No newline at end of file
+ .title {
+ color: var(--new-ui-text-color);
+ font-weight: 600;
+ font-size: 21px;
+ }
+ .text {
+ margin-top: 15px;
+ font-size: 15px;
+ color: var(--new-ui-gray-color);
+ }
+ }
+}
@@ -16,9 +16,7 @@ interface IProps {
export const Card = ({ text, icon, title, uid, slug, accessed_models }: IProps) => {
const link = useMemo(() => {
- return accessed_models && !accessed_models.includes(slug)
- ? '/account?scope=subscribe'
- : `/images/${slug}`
+ return accessed_models && !accessed_models.includes(slug) ? '/account?scope=subscribe' : `/images/${slug}`
}, [accessed_models])
return (
@@ -63,11 +61,7 @@ export const Card = ({ text, icon, title, uid, slug, accessed_models }: IProps)
textAlign: 'center',
}}
>
-