@@ -1,153 +0,0 @@ -import React, { useState } from 'react' -import { Box } from '@mui/material' -import { ThemeProvider } from '@mui/material/styles' -import Head from 'next/head' -import { useRouter } from 'next/router' -import { useSession } from 'next-auth/react' - -import { getUserBalance } from '#/entities/balance' -import { useTheme } from '#/entities/theme' -import { getAllInfo } from '#/entities/user-account' -import { isSettingExist } from '#/entities/user-account/lib/helpers/is-setting-exist' -import { getUserAccountSettings, setSettings } from '#/entities/user-account/model/settings' -import InfoBar from '#/app/layout/ui/info-bar' -import { useAppDispatch, useAppSelector } from '#/app/store/store' -import { Loader } from '#/shared' -import { pingFangFont } from '#/shared/lib/constants/font/font' -import { Device } from '#/shared/lib/types/entities' -import { MainMenuMobile } from '#/widgets/main-menu' -import { SideMenu } from '#/widgets/side-menu' -import { getDeviceType } from '#/shared/lib/helpers' - -const freeRoutes = ['/login', '/register', '/reset', '/change-password'] - -interface Props { - children: React.ReactNode - titlePage: string - isAuthPage?: boolean - title?: string | React.ReactNode | null - isLoader?: boolean -} - -export const Layout: React.FC = ({ children, isAuthPage = false, titlePage, title = titlePage, isLoader }) => { - const { data: sessionData } = useSession() - const appState = useAppSelector((state) => state) - const dispatch = useAppDispatch() - - const device = getDeviceType() - - const desktop = device === 'desktop' - - const [sidemenuDefaultOpen, setSidemenuDefaultOpen] = useState(true) - - useTheme() - - const { data, status } = useSession() - - const router = useRouter() - - React.useEffect(() => { - dispatch(getUserBalance(data?.access)) - dispatch(getAllInfo(data?.access)) - }, [data]) - - React.useEffect(() => { - if ( - (sessionData && !sessionStorage.getItem('firstRender')) || - (sessionData && !localStorage.getItem('global_settings')) - ) { - dispatch(getUserAccountSettings(sessionData.access)) - sessionStorage.setItem('firstRender', 'true') - } - }, [sessionData]) - - React.useEffect(() => { - const lsData = localStorage.getItem('global_settings') - if (lsData !== null) { - dispatch(setSettings(JSON.parse(lsData))) - } - - window.addEventListener('beforeunload', () => { - sessionStorage.removeItem('firstRender') - sessionStorage.clear() - }) - }, []) - - React.useEffect(() => { - if (appState.settings.state !== null && device) { - let setting = isSettingExist({ - settings: appState.settings.state, - targetDevice: device, - targetType: 'sidemenu', - }) - if (setting) - setting?.value?.sidemenu_state === 'opened' - ? setSidemenuDefaultOpen(true) - : setSidemenuDefaultOpen(false) - } - }, [appState.settings.state]) - - if (status === 'loading' || isLoader) { - return ( - - - - ) - } - - return ( - <> - - {titlePage} - - - - - - - - - - {!isAuthPage ? ( - desktop ? ( - - - - - - {children} - - - - ) : ( - - - {children} - - ) - ) : ( - <>{children} - )} - - - - - ) -} @@ -1 +0,0 @@ -export { Layout } from '#/app/layout/ui/layout' @@ -0,0 +1 @@ +export * from './settings.routes' \ No newline at end of file @@ -0,0 +1,16 @@ +import { api } from '#/shared/api' +import { API_URL } from '#/shared/lib/constants' +import { Agent } from 'https' +import { IUserSetting } from '../model/types' + +export function getUserSettings() { + return api.get('/api/users/settings/') +} + +export function postUserSettings(option: Omit) { + return api.post('/api/users/settings/', option) +} + +export function updateUserSettings(id: string, value: any) { + return api.put(`/api/users/settings/${id}`, { value }) +} @@ -0,0 +1,2 @@ +export * from './settings-context' +export * from './use-global-settings' \ No newline at end of file @@ -0,0 +1,9 @@ +import { createUseContext } from '#/shared' +import { createContext } from 'react' +import { useGlobalSettings } from './use-global-settings' + +export const UserSettingsContext = createContext | null>(null) + +export const useUserSettingsContext = createUseContext(UserSettingsContext) + +export const UserSettingsContextProvider = UserSettingsContext.Provider @@ -6,6 +6,7 @@ import { updateUserSettings } from '../api/update-user-settings' import { getUpdatedSettingsLocal } from '../lib/helpers/update-setting-local' import { IUserSetting, SettingValueType } from './types' +import { useLocalStorageSave } from '#/shared/lib/helpers/local-storage-helper' interface IAddSettings { token: string | undefined | null @@ -2,7 +2,7 @@ import { Device } from '#/shared/lib/types/entities' export type AccountType = 'regular' | 'business_host' | 'business_account' -export type SettingType = 'sidemenu' +export type SettingType = 'sidemenu' | string export type SettingValueType = { sidemenu_state?: 'opened' | 'closed' @@ -12,5 +12,5 @@ export interface IUserSetting { id: string device: Device type: SettingType - value: SettingValueType + value: SettingValueType | any } @@ -0,0 +1,66 @@ +import { useLocalStorage } from 'usehooks-ts' +import { IUserSetting } from './types' +import { makePrivateRequest } from '#/shared/api' +import { getUserSettings, postUserSettings, updateUserSettings } from '../api' + +import { getDeviceType } from '#/shared' +import { useCallback, useEffect, useRef, useState } from 'react' +import { useSession } from 'next-auth/react' +import { useShowDataStore } from '#/shared/lib/hooks/use-show-data' + +export function useGlobalSettings() { + const [settings, setSettings] = useLocalStorage('global_settings', []) + + const { showMessage } = useShowDataStore() + + const device = getDeviceType() + + const { data } = useSession() + + const addSettings = makePrivateRequest(async (type: string, value: any) => { + const { status, data } = await postUserSettings({ device, type, value }) + + if (status !== 200) return showMessage('Ошибка создания настроек') + + setSettings((s) => [...s, data]) + }) + + const updateSettings = useCallback( + makePrivateRequest(async (type: string, value: any) => { + const option = settings.find((x) => x.type === type) + + if (!option) return showMessage('Ошибка присвоения настроек') + + const { status } = await updateUserSettings(option.id, value) + + if (status !== 204) return showMessage('Ошибка создания настроек') + + setSettings((s) => [...s.filter((x) => x.type !== type), { ...option, value }]) + }), + [settings, data] + ) + + const fetchUserSettings = makePrivateRequest(async () => { + const { status, data } = await getUserSettings() + + const device = getDeviceType() + + if (status !== 200) return showMessage('Ошибка загрузки данных пользователя') + + setSettings(data.filter((s) => s.device === device)) + }) + + const getOptionValue = (type: string, initial: any) => { + const option = settings.find((o) => o.type === type) + return option ? option.value : initial + } + + return { + settings, + setSettings, + addSettings, + fetchUserSettings, + updateSettings, + getOptionValue, + } +} @@ -1 +1,2 @@ export { getAllInfo, userSlice } from './model/user-type-slice' +export * from './model' \ No newline at end of file @@ -1,30 +0,0 @@ -.card { - background-color: var(--new-ui-main-color); - width: 381px; - height: 227px; - border-radius: 15px; - margin-right: 20px; - margin-top: 20px; - - cursor: pointer; - padding: 30px; - box-sizing: border-box; - - @media (max-width: 768px) { - width: 100%; - } - .description { - margin-top: 20px; - - .title { - font-weight: 600; - } - - .text { - color: var(--new-ui-gray-color); - font-weight: 400; - margin-top: 6px; - font-size: 15px; - } - } -} @@ -1,48 +0,0 @@ -import React from 'react' -import { Avatar, Box, Typography } from '@mui/material' -import Image from 'next/image' -import Link from 'next/link' - -import styles from './card.module.scss' - -export type CardProps = { - title: string - icon: string - changeFavorite: (uid: string) => Promise - isFavorite: boolean - text: string - link: string - uid: string - companies: string -} - -const Card = ({ changeFavorite, isFavorite, text, icon, title, link, uid, companies }: CardProps) => { - return ( - - - - - { - e.preventDefault() - changeFavorite(uid) - }} - src={isFavorite ? '/svg/sub_menu/favourite.svg' : '/svg/sub_menu/favourite_off.svg'} - width={25} - height={25} - alt={''} - /> - - - {title} - {text} - - {companies} - - - - - ) -} - -export default Card @@ -1,278 +0,0 @@ -import * as React from 'react' -import { useState } from 'react' -import { Stack, Typography } from '@mui/material' -import Box from '@mui/material/Box' -import Button from '@mui/material/Button' -import dynamic from 'next/dynamic' -import Image from 'next/image' -import { getSession } from 'next-auth/react' - -import { toEditorState } from '#/domains/copywrite/lib/helper' -import { useCopy } from '#/features/use-copy/use-copy' -import { languages, target_audiences, tovs, useTemplate } from '#/features/use-copy/use-template' -import { Layout } from '#/app/layout' -import { Input, Loader, TooltipCustom } from '#/shared' -import { api } from '#/shared/api/endpoints' -import { getTypeDevice } from '#/shared/lib/helpers' -import { Message } from '#/shared/lib/types/model' -import { IDalleProps } from '#/shared/lib/types/types-dalle' -import { SelectUI } from '#/shared/ui/select' - -import Title from '../../features/title/title' - -import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css' - -const toolbarOptions = { - options: ['inline', 'blockType', 'list', 'textAlign', 'history'], - inline: { - options: ['bold', 'italic', 'underline'], - }, - blockType: { - options: ['Normal', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'Blockquote'], - }, - fontSize: { - options: [12, 14, 16, 18, 24, 30, 36], - }, - fontFamily: { - options: ['Arial', 'Georgia', 'Impact', 'Tahoma', 'Times New Roman', 'Verdana'], - }, - list: { - options: ['unordered', 'ordered'], - }, - textAlign: { - options: ['left', 'center', 'right'], - }, -} - -export async function getServerSideProps(context: any): Promise<{ props: IDalleProps }> { - const device = getTypeDevice(context) - - const { req } = context - - const session = await getSession({ req }) - - const token = session?.access || null - - const favorites = await api.getFavoritesModel(token, session) - - return { - props: { - device, - token, - favorites, - }, - } -} - -const Create: React.FC = ({ device, token, favorites }) => { - const desktop = device === 'desktop' - - const [showGeneration, setShowGeneration] = useState(false) - - const [isCopy, setIsCopy] = useState(false) - - const copy = (text: string) => { - navigator.clipboard.writeText(text) - setIsCopy(true) - } - - const { currentTemplate, generations, pickGeneration, setPickGeneration, createEmpty } = useCopy() - - const { - tov, - lang, - setLang, - setTov, - setTargetAudiences, - targetAudiences, - setResourceUrls, - resource_urls, - setTheme, - theme, - keywords, - setKeywords, - createText, - text, - clearSetting, - isLoading, - content, - setContent, - onEditorChange, - } = useTemplate(currentTemplate) - - const onSetGeneration = (message: Message) => { - setPickGeneration(message) - onEditorChange(toEditorState(message.content)) - setShowGeneration(false) - } - - const Editor = dynamic(() => import('react-draft-wysiwyg').then((res) => res.Editor), { - ssr: false, - }) - - const EditorWrap = (): JSX.Element | null => { - if (showGeneration) { - if (!generations || generations.length === 0) { - return null - } - - //@ts-ignore - return generations.map((el) => ( - onSetGeneration(el)} - display='flex' - justifyContent='space-between' - className='border-bottom-1px-gray' - sx={{ cursor: 'pointer' }} - padding='10px' - key={el.uid} - > - {el.content.slice(0, 60)}... - - copy(el.content)} - src={'/svg/copy.svg'} - width={22} - height={22} - alt={'copy'} - /> - - - )) - } - - return ( - - ) - } - - return ( - - - <Box - display={'flex'} - justifyContent='space-between' - flexDirection={desktop ? 'row' : 'column-reverse'} - sx={{ - marginBottom: desktop ? 0 : 3, - width: desktop ? '98%' : '100%', - marginTop: desktop ? 3 : 0, - }} - > - <Box className='pd-30 bg-color-block border-radius-main' width='100%' position='relative'> - <Box height='95%' sx={{ overflowY: 'auto' }}> - <Box width='50%' display='flex' marginBottom={2}> - {!showGeneration && ( - <Button - fullWidth - className='btn-classic' - onClick={() => setShowGeneration(true)} - > - Мои генерации - </Button> - )} - <Button - fullWidth - sx={{ marginLeft: 1 }} - className='btn-classic' - onClick={() => { - onEditorChange(toEditorState('')) - setShowGeneration(false) - }} - > - Пустой шаблон - </Button> - </Box> - <EditorWrap /> - </Box> - </Box> - <Box - height='auto' - className='pd-30 bg-color-block border-radius-main' - width='500px' - marginLeft={1.5} - > - <Typography className='font-16 color-gray'>Настройки генерации</Typography> - <Stack spacing={0.5} sx={{ marginTop: 2.5 }}> - <Typography className='title-main-gray'>Ваш запрос</Typography> - <textarea value={content} onChange={(e) => setContent(e.target.value)} /> - </Stack> - <Box sx={{ marginTop: 1 }}> - <SelectUI - title={'Тон'} - value={tov} - onChange={(e) => setTov(e.target.value)} - list={tovs} - /> - </Box> - <Box sx={{ marginTop: 1 }}> - <SelectUI - title={'Язык'} - value={lang} - onChange={(e) => setLang(e.target.value)} - list={Object.keys(languages)} - /> - </Box> - <Box sx={{ marginTop: 1 }}> - <SelectUI - title={'Аудитория'} - value={targetAudiences} - onChange={(e) => setTargetAudiences(e.target.value)} - list={target_audiences} - /> - </Box> - <Stack spacing={0.5} sx={{ marginTop: 1 }}> - <Typography className='title-main-gray'>Тема</Typography> - <Input value={theme} onChange={(e) => setTheme(e.target.value)} /> - </Stack> - <Stack spacing={0.5} sx={{ marginTop: 1 }}> - <Typography className='title-main-gray'>Ключевые слова (через запятую)</Typography> - <Input value={keywords} onChange={(e) => setKeywords(e.target.value.split(','))} /> - </Stack> - <Stack spacing={0.5} sx={{ marginTop: 1 }}> - <Typography className='title-main-gray'>Ресурсы (ссылки, через запятую)</Typography> - <Input - value={resource_urls} - onChange={(e) => setResourceUrls(e.target.value.split(','))} - /> - </Stack> - <Stack sx={{ marginTop: 1 }}> - <Typography - onClick={clearSetting} - className='text' - color='#FF2372 !important' - sx={{ cursor: 'pointer' }} - > - Сбросить настройки - </Typography> - </Stack> - <Stack sx={{ marginTop: 3 }}> - {isLoading ? ( - <Box width='100%' display='flex' justifyContent='center'> - <Loader /> - </Box> - ) : ( - <Button className='btn-classic' onClick={createText}> - Сгенерировать - </Button> - )} - </Stack> - </Box> - </Box> - </Layout> - ) -} - -export default Create @@ -1,83 +0,0 @@ -import * as React from 'react' -import { useEffect } from 'react' -import { Typography } from '@mui/material' -import Box from '@mui/material/Box' -import { getSession, useSession } from 'next-auth/react' - -import { loadTemplates } from '#/features/use-copy/copy-slice' -import { Layout } from '#/app/layout' -import { useAppDispatch, useAppSelector } from '#/app/store/store' -import { api } from '#/shared/api/endpoints' -import { getTypeDevice } from '#/shared/lib/helpers' -import { IDalleProps } from '#/shared/lib/types/types-dalle' - -import Card from './card' - -export async function getServerSideProps(context: any): Promise<{ props: IDalleProps }> { - const device = getTypeDevice(context) - - const { req } = context - - const session = await getSession({ req }) - - const token = session?.access || null - - const favorites = await api.getFavoritesModel(token, session) - - return { - props: { - device, - token, - favorites, - }, - } -} - -const CopyPage: React.FC<IDalleProps> = ({ device, token, favorites }) => { - const desktop = device === 'desktop' - - const { data } = useSession() - - const templates = useAppSelector((state) => state.copy.templates) - - const dispatch = useAppDispatch() - - useEffect(() => { - if (data?.access) { - dispatch(loadTemplates(data.access)) - } - }, [data?.access]) - - return ( - <Layout titlePage={'Копирайтинг'}> - <Typography sx={{ fontSize: 24, fontWeight: 'bold', marginTop: '25px' }}>Копирайтинг</Typography> - <Box - display={'flex'} - flexDirection={desktop ? 'row' : 'column-reverse'} - sx={{ - marginBottom: desktop ? 0 : 3, - width: desktop ? '98%' : '100%', - marginTop: desktop ? 3 : 0, - }} - > - {templates?.map((el) => { - return ( - <Card - icon={el.picture} - key={el.id} - changeFavorite={async () => {}} - link={`/copy/create?id=${el.id}`} - isFavorite={false} - text={el.description} - title={el.title} - uid={el.id.toString()} - companies={''} - /> - ) - })} - </Box> - </Layout> - ) -} - -export default CopyPage @@ -19,21 +19,7 @@ import { NextPage } from 'next' import { pingFangFont } from '#/shared/lib/constants/font/font' import { useBlockTelegram } from '#/shared/lib/hooks/use-block-telegram' import { Error } from '#/shared' - -// import fetch from 'cross-fetch' - -// global.fetch = (...params: Parameters<typeof fetch>) => { -// let url = params[0] - -// const baseUrl = process.env.NEXT_PUBLIC_NEXTAUTH_URL! - -// if (typeof url === 'string' && !(url as string).startsWith(baseUrl) && !(url as string).includes('http')) { -// url = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) + params[0] : baseUrl + params[0] -// console.log(url) -// } - -// return fetch(url, params[1]) -// } +import { Providers } from '#/widgets/providers' axios.defaults.httpsAgent = new https.Agent({ rejectUnauthorized: false, @@ -75,20 +61,8 @@ export interface AppPropsWithLayout extends AppProps { function App({ Component, pageProps: { session, ...pageProps } }: AppPropsWithLayout) { useBlockTelegram() - const getLayout = Component.getLayout ?? ((page) => page) - if ('serviceWorker' in navigator) { - navigator.serviceWorker - .getRegistrations() - .then(function (registrations) { - for (let registration of registrations) { - registration.unregister() - } - }) - .catch(function (error) { - console.error('Ошибка при размонтировании service worker:', error) - }) - } + const getLayout = Component.getLayout ?? ((page) => page) return ( <> @@ -103,8 +77,10 @@ function App({ Component, pageProps: { session, ...pageProps } }: AppPropsWithLa <Provider store={store}> <SessionProvider session={session} refetchInterval={5 * 60}> <ThemeProvider theme={pingFangFont}> - {getLayout(<Component {...pageProps} />)} - <Error /> + <Providers> + {getLayout(<Component {...pageProps} />)} + <Error /> + </Providers> </ThemeProvider> </SessionProvider> </Provider> @@ -1,258 +0,0 @@ -import React from 'react' -import { Box, Card, CardMedia, Stack, TextField, Typography } from '@mui/material' -import Button from '@mui/material/Button' -import axios from 'axios' -import Head from 'next/head' -import Image from 'next/image' -import Link from 'next/link' -import { useRouter } from 'next/router' - -import { Layout } from '#/app/layout' -import { useAppSelector } from '#/app/store/store' -import { API_URL } from '#/shared/lib/constants/constants' -import { getRandomImage, getTypeDevice } from '#/shared/lib/helpers' -import { TDeviceProp } from '#/shared/lib/types/entities' - -export async function getServerSideProps(context: any): Promise<{ props: TDeviceProp }> { - const device = getTypeDevice(context) - - return { - props: { - device, - }, - } -} - -const ChangePassword: React.FC<TDeviceProp> = ({ device }) => { - const [password1, setPassword1] = React.useState<string>('') - - const [password2, setPassword2] = React.useState<string>('') - - const [isChange, setIsChange] = React.useState(false) - - const { query, push } = useRouter() - - const changePassword = async () => { - let formData: any = new FormData() - - formData.append('password_1', password1) - formData.append('password_2', password2) - - if (password1.trim() && password2.trim()) { - try { - await axios.post(API_URL + `/auth/change-pass?token=${query.token}`, formData, { - headers: { - 'content-type': 'multipart/form-data ', - }, - }) - setIsChange(true) - setTimeout(() => push('/login'), 5000) - } catch (err) {} - } - } - - const desktop = device === 'desktop' - - const refImage = React.useRef(getRandomImage()) - - const theme = useAppSelector((state) => state.theme.theme) - - return ( - <Layout titlePage={'Авторизация'} isAuthPage={true}> - <Head> - <title>Восстановление аккаунта - - - - - - - {''} - - {desktop && ( - - - - - Midjourney - - - by honeynek - - - - - )} - {isChange ? ( - - - Ваш пароль успешно изменён! - - - Войти в аккаунт - - - ) : ( - - - Восстановление пароля - - - Новый пароль - - setPassword1(e.target.value)} - > - - Подтверждение пароля - - setPassword2(e.target.value)} - > - - - - - )} - - - ) -} - -export default ChangePassword @@ -0,0 +1,13 @@ +import { useContext } from "react" + +export function createUseContext(context: React.Context) { + return () => { + const contextValue = useContext(context) + if (!contextValue) { + throw new Error("useContext must be inside a Provider with a value") + } + return contextValue + } +} + + @@ -5,3 +5,4 @@ export * from './get-type-device' export * from './get-random-image' export * from './string' export * from './date-helper' +export * from './context' @@ -18,7 +18,6 @@ import { useSession } from 'next-auth/react' import { getAll, ResponseAllInfo } from '#/entities/user-account/model/user-type-slice' import { ApiKeyModal } from '#/features/api-key-modal/api-key-modal' -import { Layout } from '#/app/layout' import { useAppSelector } from '#/app/store/store' import { TooltipCustom } from '#/shared' import { accountApi } from '#/shared/api/account-endpoints' @@ -8,7 +8,6 @@ import styles from './image-model.module.scss' import { ChatSelect } from '#/app/components/chat_select' import { ResetFilters } from '#/app/components/filters/reset_filters' -import { Layout } from '#/app/layout' import BlockedSvg from '#/assets/svg/blocked.svg?react' import LockSvg from '#/assets/svg/lock.svg?react' import { useImageBot } from '#/entities/model-entity/model/use-image-bot' @@ -5,7 +5,6 @@ import Button from '@mui/material/Button' import axios from 'axios' import Image from 'next/image' import Router from 'next/router' -import { Layout } from '#/app/layout' import { useAppSelector } from '#/app/store/store' import { Error, Input } from '#/shared' import { API_URL } from '#/shared/lib/constants/constants' @@ -1,10 +1,10 @@ -import { Device } from "#/shared/lib/types/entities" - +import { Device } from '#/shared/lib/types/entities' export interface LayoutProps { - children: React.ReactNode - titlePage?: string - title?: string | React.ReactNode | null - device?: Device - isLoader?: boolean -} \ No newline at end of file + children: React.ReactNode + titlePage?: string + title?: string | React.ReactNode | null + device?: Device + isLoader?: boolean + height?: string +} @@ -1,37 +1,27 @@ -import React, { useCallback, useEffect, useRef, useState } from 'react' +import React, { useEffect, useRef, useState } from 'react' import { Box } from '@mui/material' -import { ThemeProvider } from '@mui/material/styles' import Head from 'next/head' import { useRouter } from 'next/router' import { signOut, useSession } from 'next-auth/react' -import * as Sentry from '@sentry/browser' import { getUserBalance } from '#/entities/balance' import { useTheme } from '#/entities/theme' import { getAllInfo } from '#/entities/user-account' -import { isSettingExist } from '#/entities/user-account/lib/helpers/is-setting-exist' -import { getUserAccountSettings, setSettings } from '#/entities/user-account/model/settings' import InfoBar from '#/app/layout/ui/info-bar' import { useAppDispatch, useAppSelector } from '#/app/store/store' import { Loader } from '#/shared' -import { pingFangFont } from '#/shared/lib/constants/font/font' -import { Device } from '#/shared/lib/types/entities' import { MainMenuMobile } from '#/widgets/main-menu' import { SideMenu } from '#/widgets/side-menu' import { getDeviceType } from '#/shared/lib/helpers' import { LayoutProps } from '../types' import { change } from '#/features/pending' import { ChangePasswordPlate } from '#/features/change-password-corp' -import { ResendInvationPlate } from '#/features/resend-invation-corp ' import { ErrorReportPlate } from '#/features/error-report' import { CSSTransition, SwitchTransition } from 'react-transition-group' -import { CommonButton } from '#/shared/ui/button' import styles from './default.module.scss' import { SlowLoading } from '#/features/slow-loading' -export const Layout: React.FC = ({ children, titlePage, title = titlePage, isLoader, device = getDeviceType() }) => { - const { data: sessionData } = useSession() - const appState = useAppSelector((state) => state) +export const Layout: React.FC = ({ children, titlePage, isLoader, height, device = getDeviceType() }) => { const dispatch = useAppDispatch() const meStatus = useAppSelector((state) => state.user.status) @@ -40,8 +30,6 @@ export const Layout: React.FC = ({ children, titlePage, title = tit const desktop = device === 'desktop' - const [sidemenuDefaultOpen, setSidemenuDefaultOpen] = useState(true) - useTheme() const { data, status } = useSession() @@ -77,36 +65,6 @@ export const Layout: React.FC = ({ children, titlePage, title = tit getUserData(data.access) }, [data]) - useEffect(() => { - if ((sessionData && !sessionStorage.getItem('firstRender')) || (sessionData && !localStorage.getItem('global_settings'))) { - dispatch(getUserAccountSettings(sessionData.access)) - sessionStorage.setItem('firstRender', 'true') - } - }, [sessionData]) - - React.useEffect(() => { - const lsData = localStorage.getItem('global_settings') - if (lsData !== null) { - dispatch(setSettings(JSON.parse(lsData))) - } - - window.addEventListener('beforeunload', () => { - sessionStorage.removeItem('firstRender') - sessionStorage.clear() - }) - }, []) - - React.useEffect(() => { - if (appState.settings.state !== null && device) { - let setting = isSettingExist({ - settings: appState.settings.state, - targetDevice: device, - targetType: 'sidemenu', - }) - if (setting) setting?.value?.sidemenu_state === 'opened' ? setSidemenuDefaultOpen(true) : setSidemenuDefaultOpen(false) - } - }, [appState.settings.state]) - const [requestDelay, setRequestDelay] = useState(false) const transitionRef = useRef(null) @@ -148,7 +106,7 @@ export const Layout: React.FC = ({ children, titlePage, title = tit id={'layout'} sx={{ width: '100%', - height: desktop ? '100%' : '100dvh', + height: desktop ? (height ? height : '100%') : '100dvh', padding: desktop ? '0px' : '10px', }} > @@ -159,7 +117,7 @@ export const Layout: React.FC = ({ children, titlePage, title = tit > {desktop ? ( - + = ({ children, titlePage, title = tit - @@ -0,0 +1 @@ +export * from './providers' \ No newline at end of file @@ -0,0 +1,24 @@ +import { useGlobalSettings, UserSettingsContextProvider } from '#/entities/user-account' +import { useSession } from 'next-auth/react' +import React, { PropsWithChildren, useEffect } from 'react' + +interface ProvidersProps extends PropsWithChildren {} + +export const Providers = ({ children }: ProvidersProps) => { + const { settings, fetchUserSettings, ...rest } = useGlobalSettings() + + const { data } = useSession() + + useEffect(() => { + if(!data) return + console.log(settings.length) + if (settings.length > 0) return + fetchUserSettings() + }, [data]) + + return ( + + {children} + + ) +} @@ -0,0 +1 @@ +export * from './ui' \ No newline at end of file @@ -8,25 +8,19 @@ import ListItemButton from '@mui/material/ListItemButton' import ListItemIcon from '@mui/material/ListItemIcon' import ListItemText from '@mui/material/ListItemText' import { CSSObject, styled, Theme } from '@mui/material/styles' -import dynamic from 'next/dynamic' import Image from 'next/image' import Link from 'next/link' -import { usePathname } from 'next/navigation' import { useRouter } from 'next/router' -import { signOut, useSession } from 'next-auth/react' +import { useSession } from 'next-auth/react' -import { addUserSettings } from '#/entities/user-account/api/add-user-settings' -import { updateUserSettings } from '#/entities/user-account/api/update-user-settings' -import { isSettingExist } from '#/entities/user-account/lib/helpers/is-setting-exist' -import { addUserAccountSettings, updateUserAccountSettings } from '#/entities/user-account/model/settings' import { getAll, ResponseAllInfo } from '#/entities/user-account/model/user-type-slice' import { useAppDispatch, useAppSelector } from '#/app/store/store' -import { TooltipCustom } from '#/shared' import { Device } from '#/shared/lib/types/entities' import '../styles/styles.module.css' import styles from '../styles/styles.module.css' import { ERROR_REPORT, getModalById } from '#/features/modals' +import { useUserSettingsContext } from '#/entities/user-account' export const menuListTop = [ { title: 'Дашборд', link: '/', icon: '/svg/side-menu/market', activeList: [] }, @@ -104,80 +98,23 @@ const Drawer = styled(MuiDrawer, { shouldForwardProp: (prop) => prop !== 'open' }), })) -export const SideMenu = ({ device, sidemenuDefaultOpen }: { device: Device; sidemenuDefaultOpen: boolean }) => { - const [open, setOpen] = React.useState(sidemenuDefaultOpen) - const [isInitialValueSet, setIsInitialValueSet] = React.useState(false) +export const SideMenu = ({}) => { + const { status } = useSession() - const { status, data } = useSession() - const dispatch = useAppDispatch() + const { pathname, asPath } = useRouter() - const { pathname, basePath, asPath, push } = useRouter() + const { theme } = useAppSelector((state) => state) - const { theme, settings } = useAppSelector((state) => state) - - const handleDrawerOpen = () => { - setOpen(true) - } - - const handleDrawerClose = () => { - setOpen(false) - } + const { getOptionValue, settings, updateSettings } = useUserSettingsContext() const error_report = getModalById(ERROR_REPORT) const match = useMediaQuery('(min-height:800px)') - const [userInfo, setUserInfo] = useState() - - useEffect(() => { - getAll(data?.access).then((res) => setUserInfo(res)) - }, [data?.access]) - - useEffect(() => { - if (settings.state !== null && isInitialValueSet) { - let response = isSettingExist({ - settings: settings.state, - targetDevice: device, - targetType: 'sidemenu', - }) - - if (response && data?.access) { - dispatch( - updateUserAccountSettings({ - token: data.access, - id: response.id, - value: { sidemenu_state: open ? 'opened' : 'closed' }, - settings: settings.state, - }) - ) - } else if (data?.access) { - dispatch( - addUserAccountSettings({ - token: data.access, - setting: { - device, - type: 'sidemenu', - value: { sidemenu_state: open ? 'opened' : 'closed' }, - }, - }) - ) - } - } - }, [open]) - - useEffect(() => { - if (settings.state !== null && !isInitialValueSet) { - let setting = isSettingExist({ - settings: settings.state, - targetDevice: device, - targetType: 'sidemenu', - }) - if (setting) { - setting?.value?.sidemenu_state === 'opened' ? setOpen(true) : setOpen(false) - } - setIsInitialValueSet(true) - } - }, [settings.state]) + const open = useMemo( + () => getOptionValue('sidemenu', { sidemenu_state: 'opened' }).sidemenu_state, + [settings] + ) return ( { + updateSettings('sidemenu', { + sidemenu_state: open === 'opened' ? 'closed' : 'opened', + }) + }} width='100%' display={'flex'} alignItems={'center'} @@ -223,7 +164,7 @@ export const SideMenu = ({ device, sidemenuDefaultOpen }: { device: Device; side marginLeft: -1, marginRight: 5, transition: 'transform 0.4s ease', - transform: !open ? 'rotate(180deg)' : 'rotate(0deg)', + transform: open === 'closed' ? 'rotate(180deg)' : 'rotate(0deg)', }} src={'/arrow-left.svg'} width={20} @@ -239,7 +180,7 @@ export const SideMenu = ({ device, sidemenuDefaultOpen }: { device: Device; side return ( - { - error_report.setState(true) - }}> + { + error_report.setState(true) + }} + > )} - - {open && ( + + {open === 'opened' && (