From 86d3e9bbf4a351df72ffcbae57a532bbf47b7247 Mon Sep 17 00:00:00 2001 From: Arseniy Sitnikov Date: Thu, 12 Dec 2024 15:21:19 +0300 Subject: [PATCH] fixes of bugs, loading animation, add max storage --- frontend/.DS_Store | Bin 6148 -> 6148 bytes frontend/public/.DS_Store | Bin 6148 -> 6148 bytes frontend/src/.DS_Store | Bin 6148 -> 6148 bytes frontend/src/App.tsx | 1 + frontend/src/assets/.DS_Store | Bin 0 -> 6148 bytes frontend/src/main.global.css | 2 + .../shared/Clicker/ClickerBtn/ClickerBtn.tsx | 26 ++++-- .../Clicker/ClickerBtn/clickerbtn.module.css | 17 ++++ .../clickerbtnfooter.module.css | 1 + .../Clicker/ClickerFooter/ClickerFooter.tsx | 9 +-- .../shared/Clicker/PointsZoom/PointsZoom.tsx | 17 +++- .../Clicker/PointsZoom/pointszoom.module.css | 4 + .../src/shared/Clicker/Profile/Profile.tsx | 19 +++-- .../Clicker/SectionsBlock/SectionsBlock.tsx | 39 +++++---- .../SectionsBlock/sectionsblock.module.css | 8 ++ .../src/shared/Elements/DevPopup/DevPopup.tsx | 13 +-- .../Elements/StylesSwiper/StylesSwiper.tsx | 2 +- .../shared/Pages/ClickerPage/ClickerPage.tsx | 9 +-- frontend/src/shared/Pages/DevPage/DevPage.tsx | 39 +++++++++ .../shared/Pages/DevPage/devpage.module.css | 38 +++++++++ frontend/src/shared/Pages/DevPage/index.ts | 1 + .../src/shared/Pages/RoutePage/RoutePage.tsx | 12 +-- .../shared/Pages/StoragePage/StoragePage.tsx | 11 +-- .../shared/Pages/StylesPage/StylesPage.tsx | 6 +- .../StoragePageBlock/StoragePageBlock.tsx | 37 +++++---- .../Storage/StorageScale/StorageScale.tsx | 58 ++++++++++--- frontend/src/shared/texts/Text.tsx | 6 ++ frontend/src/store/me/actions.ts | 76 ++++++++++++++---- frontend/src/store/reducer.ts | 8 +- frontend/src/utils/checkMobile.js | 22 +++++ frontend/src/utils/updateBackground.js | 4 +- 31 files changed, 366 insertions(+), 119 deletions(-) create mode 100644 frontend/src/assets/.DS_Store create mode 100644 frontend/src/shared/Pages/DevPage/DevPage.tsx create mode 100644 frontend/src/shared/Pages/DevPage/devpage.module.css create mode 100644 frontend/src/shared/Pages/DevPage/index.ts create mode 100644 frontend/src/utils/checkMobile.js diff --git a/frontend/.DS_Store b/frontend/.DS_Store index a6500821479b9f30f79e547f57e01483e489f542..9a9ce6d0fa0bd21eeb6ab77125674268cfd75f15 100644 GIT binary patch delta 17 YcmZoMXfc=&$H+J_-ky$ delta 12 TcmZoMXfc?ugppz6(s*$I9j*jw diff --git a/frontend/src/.DS_Store b/frontend/src/.DS_Store index dcd4dc89d57160cf1ac6489f325c17924f9c964e..926ef31574c46953eb6afba9c2d516f20f707dd2 100644 GIT binary patch delta 64 zcmZoMXfc=|#>CJ*u~2NHo+2aj!~knX=E*!vGMjCfPqS=pV4lLXnVo~51E^$kA@g_U U$^0UQj0}@)c%(PSh^$}+05@zAEdT%j delta 347 zcmaiwyAA} /> } /> } /> + } /> } /> diff --git a/frontend/src/assets/.DS_Store b/frontend/src/assets/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0(state => state.urlClick); const token = useAppSelector(state => state.token); const [fill, setFill] = useState(0); @@ -35,6 +36,7 @@ export function ClickerBtn({ coins, setCoins, energy, setMult }: IClickerBtn) { const [error, setError] = useState(false); const [animClose, setAnimClose] = useState(false); const dispatch = useDispatch(); + const [loading, setLoading] = useState(false); useEffect(() => { const savedEnergy = sessionStorage.getItem('eg'); @@ -45,6 +47,12 @@ export function ClickerBtn({ coins, setCoins, energy, setMult }: IClickerBtn) { setFill((maxEnergy - initEnergy) / maxEnergy * 100); }, []); + useEffect(() => { + if (initEnergy === 0 || fill === 100) { + setCloseError(true); + } + }, [initEnergy, fill]); + useEffect(() => { setGradient(getGradient()) }, [styleIndex]); @@ -58,7 +66,8 @@ export function ClickerBtn({ coins, setCoins, energy, setMult }: IClickerBtn) { }; const sendClick = () => { - if(token) { + if (token && !loading) { + setLoading(true); axios.post(`${urlClick}/api/v1/click/`, {}, { @@ -69,6 +78,7 @@ export function ClickerBtn({ coins, setCoins, energy, setMult }: IClickerBtn) { ).then((resp) => { //console.log(resp); if(resp.data) { + setLoading(false); const click = Number(resp.data.click.value); // const encodeMult = btoa(click.toString()); @@ -80,7 +90,7 @@ export function ClickerBtn({ coins, setCoins, energy, setMult }: IClickerBtn) { const newFill = (maxEnergy - newEnergy) / maxEnergy * 100; if (newFill <= 100) { const newCoins = Number(coins + click); - dispatch(updateCoinsRequestAsync(newCoins, newEnergy)) + dispatch(updateEnergyRequestAsync(newEnergy)) setCoins(newCoins); setEnergy(newEnergy) setFill(newFill); @@ -104,6 +114,7 @@ export function ClickerBtn({ coins, setCoins, energy, setMult }: IClickerBtn) { setError(false) } }).catch((err) => { + setLoading(false); setCloseError(false); setError(true); console.log(err); @@ -120,7 +131,7 @@ export function ClickerBtn({ coins, setCoins, energy, setMult }: IClickerBtn) { }, { title: 'Как продолжить кликать', - text: Чтобы охладиться, нужно нужно закрыть приложение, нажав по кнопке ниже., + text: Чтобы охладиться, нужно закрыть приложение, нажав по кнопке ниже., img: 'assets/Monocle.png' }, { @@ -133,7 +144,8 @@ export function ClickerBtn({ coins, setCoins, energy, setMult }: IClickerBtn) { return (
-
+ {!loading &&
} + {loading &&
} @@ -144,7 +156,7 @@ export function ClickerBtn({ coins, setCoins, energy, setMult }: IClickerBtn) { } />} {!closeError && + } />}
); diff --git a/frontend/src/shared/Clicker/ClickerBtn/clickerbtn.module.css b/frontend/src/shared/Clicker/ClickerBtn/clickerbtn.module.css index 3306b9a..0bd36c9 100644 --- a/frontend/src/shared/Clicker/ClickerBtn/clickerbtn.module.css +++ b/frontend/src/shared/Clicker/ClickerBtn/clickerbtn.module.css @@ -66,4 +66,21 @@ .borderNone { border: none; +} + +.loadingContainer { + user-select: none; + z-index: 1; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background-color: var(--grey27); + width: 230px; + height: 230px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 50%; + border: 2px solid var(--white); } \ No newline at end of file diff --git a/frontend/src/shared/Clicker/ClickerBtnFooter/clickerbtnfooter.module.css b/frontend/src/shared/Clicker/ClickerBtnFooter/clickerbtnfooter.module.css index 4695c7b..ca7549e 100644 --- a/frontend/src/shared/Clicker/ClickerBtnFooter/clickerbtnfooter.module.css +++ b/frontend/src/shared/Clicker/ClickerBtnFooter/clickerbtnfooter.module.css @@ -7,6 +7,7 @@ background-color: rgba(0, 0, 0, 0.6);*/ background: rgba(0, 0, 0, 0.6); border-radius: 12px; + cursor: pointer; } .content { diff --git a/frontend/src/shared/Clicker/ClickerFooter/ClickerFooter.tsx b/frontend/src/shared/Clicker/ClickerFooter/ClickerFooter.tsx index 9858e57..0760dc5 100644 --- a/frontend/src/shared/Clicker/ClickerFooter/ClickerFooter.tsx +++ b/frontend/src/shared/Clicker/ClickerFooter/ClickerFooter.tsx @@ -3,25 +3,18 @@ import styles from './clickerfooter.module.css'; import { ClickerBtnFooter } from '../ClickerBtnFooter'; import { EIcons, Icon } from '../../Icons'; import { useNavigate } from 'react-router-dom'; -import { ModalWindow } from '../../ModalWindow'; -import { DevPopup } from '../../Elements/DevPopup'; export function ClickerFooter() { const navigate = useNavigate(); - const [closeAnimOut, setCloseAnimOut] = useState(false); - const [closeDev, setCloseDev] = useState(true); const isDev = true; return (
navigate('/styles')}/> - { !isDev ? navigate('/auction') : setCloseDev(false) }}/> + { !isDev ? navigate('/auction') : navigate('/dev?type=auction') }}/> { !isDev &&
} - {!closeDev && - } />}
); } diff --git a/frontend/src/shared/Clicker/PointsZoom/PointsZoom.tsx b/frontend/src/shared/Clicker/PointsZoom/PointsZoom.tsx index b9f02c4..0fa17c8 100644 --- a/frontend/src/shared/Clicker/PointsZoom/PointsZoom.tsx +++ b/frontend/src/shared/Clicker/PointsZoom/PointsZoom.tsx @@ -3,33 +3,42 @@ import styles from './pointszoom.module.css'; import { formatNumber } from '../../../utils/formatNumber'; import { ETextStyles } from '../../texts'; import ReactDOM from 'react-dom'; +import { useDispatch } from 'react-redux'; +import { updatePointsRequestAsync } from '../../../store/me/actions'; +import { checkIOS } from '../../../utils/checkMobile'; interface IPointsZoom { points: number, setClose(a:boolean): void, className ?: string, closePointsAnim: boolean, - setClosePointsAnim(a: boolean): void + setClosePointsAnim(a: boolean): void, + setCoins(a:number):void } -export function PointsZoom({ points, setClose, className, closePointsAnim, setClosePointsAnim }: IPointsZoom) { +export function PointsZoom({ points, setClose, setCoins, className, closePointsAnim, setClosePointsAnim }: IPointsZoom) { const [open, setOpen] = useState(true); const node = document.querySelector('#modal_root'); if (!node) return null; + const dispatch = useDispatch(); useEffect(() => { const timer = setInterval(() => { setOpen(false); clearInterval(timer); }, 400); + + console.log(checkIOS()) }, []); useEffect(() => { if (closePointsAnim) { + dispatch(updatePointsRequestAsync()); const timer = setTimeout(() => { setClosePointsAnim(false); setClose(true); clearTimeout(timer); + setCoins(0); }, 400); } }, [closePointsAnim]); @@ -37,9 +46,9 @@ export function PointsZoom({ points, setClose, className, closePointsAnim, setCl return (
{ReactDOM.createPortal(( -
+
-

{formatNumber(Number(points.toFixed(2)))}

+

{`+${formatNumber(Number(points.toFixed(2)))}`}

), node)}
diff --git a/frontend/src/shared/Clicker/PointsZoom/pointszoom.module.css b/frontend/src/shared/Clicker/PointsZoom/pointszoom.module.css index ece51cb..63fa9e5 100644 --- a/frontend/src/shared/Clicker/PointsZoom/pointszoom.module.css +++ b/frontend/src/shared/Clicker/PointsZoom/pointszoom.module.css @@ -24,6 +24,10 @@ box-shadow: 0px 0px 30px 15px rgba(128, 135, 192, 0.25); } +.ios { + top: 40px !important; +} + .icon { width: 40px; height: 40px; diff --git a/frontend/src/shared/Clicker/Profile/Profile.tsx b/frontend/src/shared/Clicker/Profile/Profile.tsx index f26f490..a5e9125 100644 --- a/frontend/src/shared/Clicker/Profile/Profile.tsx +++ b/frontend/src/shared/Clicker/Profile/Profile.tsx @@ -4,25 +4,30 @@ import { ETextStyles } from '../../texts'; import { formatNumber } from '../../../utils/formatNumber'; import { PersonIcon } from '../../Elements/PersonIcon'; import { EIcons, Icon } from '../../Icons'; +import { useAppSelector } from '../../hooks/useAppSelector'; +import { Spinner } from '../../Elements/Spinner'; interface IProfileClicker { name: string, - points: number, img: string, className ?: string } -export function Profile({ name, points, img, className }: IProfileClicker) { +export function Profile({ name, img, className }: IProfileClicker) { + const points = useAppSelector(state => state.me.data.points); + const loading = useAppSelector(state => state.me.loading); + return (
- {img ? :
} + {img ? : }

{name}

-

- {formatNumber(Number(points.toFixed(2)))} -

-
+ {points &&

+ {formatNumber(Number(Number(points).toFixed(2)))} +

} + {!loading &&
} + {loading && }
diff --git a/frontend/src/shared/Clicker/SectionsBlock/SectionsBlock.tsx b/frontend/src/shared/Clicker/SectionsBlock/SectionsBlock.tsx index 3212c56..b7c93ab 100644 --- a/frontend/src/shared/Clicker/SectionsBlock/SectionsBlock.tsx +++ b/frontend/src/shared/Clicker/SectionsBlock/SectionsBlock.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import styles from './sectionsblock.module.css'; import { CardSection } from '../../Elements/CardSection'; import { ETextStyles } from '../../texts'; @@ -8,30 +8,40 @@ import { ClickerPopup } from '../ClickerPopup'; import { useNavigate } from 'react-router-dom'; import { UsersIcons } from '../../Elements/UsersIcons'; import { formatNumber } from '../../../utils/formatNumber'; -import { DevPopup } from '../../Elements/DevPopup'; +import { useAppSelector } from '../../hooks/useAppSelector'; interface ISectionsBlock { mult:number; } export function SectionsBlock({ mult }: ISectionsBlock) { - const scaleRef = 70; const [close, setClose] = useState(true); const navigate = useNavigate(); - const [closeAnimOut, setCloseAnimOut] = useState(false); - const [closeDev, setCloseDev] = useState(true); + const referralStorage = Number(useAppSelector(state => state.me.data.referralStorage)); + //const referralStorage = 500; + const maxReferralStorage = useAppSelector(state => state.me.data.maxStorage); + const [referralPercent, serReferralPercent] = useState(0); + + useEffect(() => { + if(referralStorage >= maxReferralStorage) { + serReferralPercent(100); + } else { + serReferralPercent(referralStorage / maxReferralStorage * 100); + } + + }, [referralStorage, maxReferralStorage]); const isDev = true; const multipCards = [ { title: 'Что он делает', - text: Увеличивает получение баллов с одного клика в столько раз, сколько указано в рамке внизу экрана., + text: Увеличивает получение баллов с одного клика в столько раз, сколько указано в рамке., img: 'assets/Rocket.png' }, { title: 'Как его увеличить', - text: Чем выше концентрация — клики в час, тем выше мультипликатор, он рассчитывается по формуле., + text: Чем выше концентрация — клики в час, тем выше множитель, он рассчитывается по формуле., img: 'assets/Monocle.png' }, { @@ -44,7 +54,7 @@ export function SectionsBlock({ mult }: ISectionsBlock) { return (
- {!isDev ? navigate('/rating') : setCloseDev(false)}}> + {!isDev ? navigate('/rating') : navigate('/dev?type=rating')}}> {
# @@ -61,22 +71,19 @@ export function SectionsBlock({ mult }: ISectionsBlock) {
{ navigate('/referral') }}> - {
- + {
+
-
+
-

- Хранилище заполнено, заберите коины +

+ {referralPercent === 100 ? 'Хранилище заполнено, заберите коины' : 'Когда хранилище заполнится, вы сможете забрать баллы'}

} {!close && } />} - {!closeDev && - } />}
); } diff --git a/frontend/src/shared/Clicker/SectionsBlock/sectionsblock.module.css b/frontend/src/shared/Clicker/SectionsBlock/sectionsblock.module.css index 0b7d52e..7612b44 100644 --- a/frontend/src/shared/Clicker/SectionsBlock/sectionsblock.module.css +++ b/frontend/src/shared/Clicker/SectionsBlock/sectionsblock.module.css @@ -48,6 +48,10 @@ color: var(--grey6C); } +.textFull { + color: var(--white); +} + .scale { position: absolute; top: 0; @@ -56,6 +60,10 @@ background: var(--primary); } +.scaleFull { + background: var(--purple); +} + .dev { position: relative; } diff --git a/frontend/src/shared/Elements/DevPopup/DevPopup.tsx b/frontend/src/shared/Elements/DevPopup/DevPopup.tsx index 7cca1f7..1e3a569 100644 --- a/frontend/src/shared/Elements/DevPopup/DevPopup.tsx +++ b/frontend/src/shared/Elements/DevPopup/DevPopup.tsx @@ -5,18 +5,19 @@ import { ETextStyles } from '../../texts'; interface IDevPopup { setClose(a: boolean): void - type: 'error' | 'dev' + title: string, + text: string, } -export function DevPopup({ setClose, type }: IDevPopup) { +export function DevPopup({ setClose, title, text }: IDevPopup) { return (
-
+
-

{type === 'dev' ? 'Скоро откроем' : 'Возникла ошибка'}

-

{type === 'dev' ? Подготавливаем что-то особенное для вас. Скоро увидимся на новом уровне! : 'Мы пока не можем принимать клики, но скоро всё починим.'}

-
); } diff --git a/frontend/src/shared/Elements/StylesSwiper/StylesSwiper.tsx b/frontend/src/shared/Elements/StylesSwiper/StylesSwiper.tsx index 5014f8f..515e411 100644 --- a/frontend/src/shared/Elements/StylesSwiper/StylesSwiper.tsx +++ b/frontend/src/shared/Elements/StylesSwiper/StylesSwiper.tsx @@ -68,7 +68,7 @@ export const StylesSwiper: React.FC = memo(({ selectedStyle, setC return (
(slideRefs.current[index] = el as HTMLDivElement)} - className={`${styles.card} ${cardStyle} ${selectedStyle === index && styles.selected} ${index > 0 && styles.disabled}`} + className={`${styles.card} ${cardStyle} ${selectedStyle === index && styles.selected}`} style={{ transform: `rotate(${isActive ? 0 : deg}deg)`, filter: `blur(${isActive ? 0 : 3}px)` diff --git a/frontend/src/shared/Pages/ClickerPage/ClickerPage.tsx b/frontend/src/shared/Pages/ClickerPage/ClickerPage.tsx index 86cc53b..7b16ee4 100644 --- a/frontend/src/shared/Pages/ClickerPage/ClickerPage.tsx +++ b/frontend/src/shared/Pages/ClickerPage/ClickerPage.tsx @@ -7,7 +7,6 @@ import { SectionsBlock } from '../../Clicker/SectionsBlock'; import { ClickerFooter } from '../../Clicker/ClickerFooter'; import { StyleElements } from '../../Clicker/StyleElements'; import { PointsZoom } from '../../Clicker/PointsZoom'; -import { Timer } from '../../Auction/Timer'; import { useWindowSize } from 'usehooks-ts'; import { useAppSelector } from '../../hooks/useAppSelector'; @@ -20,7 +19,7 @@ interface IClickerPageInterface { export function ClickerPage({ name, points, img, energy }: IClickerPageInterface) { const styleIndex = Number(localStorage.getItem('selectedStyle')); - const [coins, setCoins] = useState(points); + const [coins, setCoins] = useState(0); const [mult, setMult] = useState(1); const [closePoints, setClosePoints] = useState(true); const [closePointsAnim, setClosePointsAnim] = useState(false); @@ -35,7 +34,7 @@ export function ClickerPage({ name, points, img, energy }: IClickerPageInterface //@ts-ignore let timer; - if (points !== coins) { + if (points !== coins && coins != 0) { setClosePoints(false); timer = setTimeout(() => { setClosePointsAnim(true); @@ -50,8 +49,8 @@ export function ClickerPage({ name, points, img, energy }: IClickerPageInterface return (
- {!closePoints && } - + {!closePoints && } +

Мои рекорды

diff --git a/frontend/src/shared/Pages/DevPage/DevPage.tsx b/frontend/src/shared/Pages/DevPage/DevPage.tsx new file mode 100644 index 0000000..3228a08 --- /dev/null +++ b/frontend/src/shared/Pages/DevPage/DevPage.tsx @@ -0,0 +1,39 @@ +import React, { useEffect, useState } from 'react'; +import styles from './devpage.module.css'; +import { ETextStyles } from '../../texts'; +import { Button } from '../../Button'; +import { useNavigate } from 'react-router-dom'; + + +export function DevPage() { + const [type, setType] = useState(''); + const navigate = useNavigate(); + + useEffect(() => { + const currentUrl = new URL(window.location.href); + const typeURL = currentUrl.searchParams.get("type"); + if (typeURL) + setType(typeURL) + }, []); + + + const icons = ['assets/shopping.png', 'assets/compass.png', 'assets/friends.png']; + const titles = ['Упаковываем товары!', 'Рейтинг игроков формируется', 'Рейтинг друзей формируется']; + const texts = [ + 'Собираем подборку самых желанных подарков для тебя! Копи баллы, чтобы выигрывать в аукционах!', + 'Рейтинг откроется, когда накопится достаточное количество пользователей.', + 'Рейтинг откроется, когда накопится достаточное количество пользователей.' + ] + return ( +
+
+
+
+
+

{type === 'auction' ? titles[0] : (type === 'rating' ? titles[1] : titles[2])}

+

{type === 'auction' ? texts[0] : (type === 'rating' ? texts[1] : texts[2])}

+
+
+ ); +} diff --git a/frontend/src/shared/Pages/DevPage/devpage.module.css b/frontend/src/shared/Pages/DevPage/devpage.module.css new file mode 100644 index 0000000..c05a0d2 --- /dev/null +++ b/frontend/src/shared/Pages/DevPage/devpage.module.css @@ -0,0 +1,38 @@ +.container { + height: 100vh; + display: flex; + align-items: center; + justify-content: center; +} + +.innerContainer { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.iconContainer { + margin-bottom: 16px; + display: flex; + align-items: center; + justify-content: center; +} + +.icon { + width: 72px; + height: 72px; + background-position: center; + background-size: contain; + background-repeat: no-repeat; +} + +.title { + margin-bottom: 12px; + text-align: center; +} + +.descr { + margin-bottom: 24px; + text-align: center; +} \ No newline at end of file diff --git a/frontend/src/shared/Pages/DevPage/index.ts b/frontend/src/shared/Pages/DevPage/index.ts new file mode 100644 index 0000000..db005a5 --- /dev/null +++ b/frontend/src/shared/Pages/DevPage/index.ts @@ -0,0 +1 @@ +export * from './DevPage'; diff --git a/frontend/src/shared/Pages/RoutePage/RoutePage.tsx b/frontend/src/shared/Pages/RoutePage/RoutePage.tsx index ac27988..b4b7cfa 100644 --- a/frontend/src/shared/Pages/RoutePage/RoutePage.tsx +++ b/frontend/src/shared/Pages/RoutePage/RoutePage.tsx @@ -13,6 +13,7 @@ import { Spinner } from '../../Elements/Spinner'; import { updateBackground } from '../../../utils/updateBackground'; import { ErrorPage } from '../ErrorPage'; import { useNavigate } from 'react-router-dom'; +import { DevPage } from '../DevPage'; interface IRoutePage { page: string @@ -44,11 +45,12 @@ export function RoutePage({ page }: IRoutePage) {
{!verified ? :
{ //@ts-ignore - page === 'main' && !loadingUser && !errorUser && dataUser.name && } - {page === 'rating' && !loadingUser && !errorUser && } - {page === 'referral' && !loadingUser && !errorUser && } - {page === 'auction' && !loadingUser && !errorUser && } - {page === 'styles' && !loadingUser && !errorUser && } + page === 'main' && (!loadingUser || dataUser.username) && !errorUser && dataUser.name && } + {page === 'rating' && (!loadingUser || dataUser.username) && !errorUser && } + {page === 'referral' && (!loadingUser || dataUser.username) && !errorUser && } + {page === 'auction' && (!loadingUser || dataUser.username) && !errorUser && } + {page === 'styles' && (!loadingUser || dataUser.username) && !errorUser && } + {page === 'dev' && } {(loadingUser) &&
} {errorUser && !loadingUser && }
} diff --git a/frontend/src/shared/Pages/StoragePage/StoragePage.tsx b/frontend/src/shared/Pages/StoragePage/StoragePage.tsx index 3845246..e4c1d11 100644 --- a/frontend/src/shared/Pages/StoragePage/StoragePage.tsx +++ b/frontend/src/shared/Pages/StoragePage/StoragePage.tsx @@ -9,16 +9,14 @@ import { Notification } from '../../Notification'; import { StoragePageBlock } from '../../Storage/StoragePageBlock'; import { FriendsPageBlock } from '../../Storage/FriendsPageBlock'; import { useAppSelector } from '../../hooks/useAppSelector'; -import { DevPopup } from '../../Elements/DevPopup'; -import { ModalWindow } from '../../ModalWindow'; +import { useNavigate } from 'react-router-dom'; export function StoragePage() { const userId = useAppSelector(state => state.userTg.id); const [page, setPage] = useState('storage'); const refLink = `https://t.me/sapphirecrown_bot?start=user_${userId}`; const [showNotif, setShow] = useState(false); - const [closeAnimOut, setCloseAnimOut] = useState(false); - const [closeDev, setCloseDev] = useState(true); + const navigate = useNavigate(); return (
@@ -26,7 +24,7 @@ export function StoragePage() {
setPage('storage')}/> { - setCloseDev(false); + navigate('/dev?type=friends') //setPage('friends') } } /> @@ -34,9 +32,6 @@ export function StoragePage() { {page === 'storage' ? : }
); } diff --git a/frontend/src/shared/Pages/StylesPage/StylesPage.tsx b/frontend/src/shared/Pages/StylesPage/StylesPage.tsx index 6fa95a9..8cb0842 100644 --- a/frontend/src/shared/Pages/StylesPage/StylesPage.tsx +++ b/frontend/src/shared/Pages/StylesPage/StylesPage.tsx @@ -11,10 +11,8 @@ export function StylesPage() { const [selectedStyle, setSelectedStyle] = useState(selectedIndex ? selectedIndex : 0); const [currentSlide, setCurrentSlide] = useState(0); const [showNotif, setShow] = useState(false); - const isDev = true; - //const stylesNames = ['Черно-синий', 'Grapefruit', 'Tropic mamba', 'Mamba & Grapefruit']; - const stylesNames = ['Черно-синий', 'Скоро будет доступен', 'Скоро будет доступен', 'Скоро будет доступен']; + const stylesNames = ['Черно-синий', 'Grapefruit', 'Tropic mamba', 'Mamba & Grapefruit']; const colors = ['#7EB4DB', '#FE744B', '#F2D06B', '#EA9C55']; const gradients = ['linear-gradient(90deg, #90D7ED 13.05%, #6887C4 91.06%, #8085C0 172.24%)', 'linear-gradient(302deg, #FF5421 -59.57%, #FF7248 43.7%, #FF9576 163.26%)', 'linear-gradient(302deg, #6ACB54 -59.57%, #DCBB5A 43.7%, #E2883D 163.26%)', 'linear-gradient(302deg, #FF805A -1.15%, #DEAE53 83.89%)']; @@ -57,7 +55,7 @@ export function StylesPage() { Будь круче — будь на стиле!

{stylesNames[currentSlide]}

- {!isDev &&
); diff --git a/frontend/src/shared/Storage/StoragePageBlock/StoragePageBlock.tsx b/frontend/src/shared/Storage/StoragePageBlock/StoragePageBlock.tsx index 5fb8600..219be89 100644 --- a/frontend/src/shared/Storage/StoragePageBlock/StoragePageBlock.tsx +++ b/frontend/src/shared/Storage/StoragePageBlock/StoragePageBlock.tsx @@ -1,33 +1,38 @@ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import styles from './storagepageblock.module.css'; import { StorageScale } from '../StorageScale'; import { ETextStyles } from '../../texts'; import { PopupCard } from '../../Elements/PopupCard'; -import { ModalWindow } from '../../ModalWindow'; -import { DevPopup } from '../../Elements/DevPopup'; +import { useAppSelector } from '../../hooks/useAppSelector'; export function StoragePageBlock() { - const [closeAnimOut, setCloseAnimOut] = useState(false); - const [closeDev, setCloseDev] = useState(true); - const isDev = true; + const referralStorage = Number(useAppSelector(state => state.me.data.referralStorage)); + const maxReferralStorage = useAppSelector(state => state.me.data.maxStorage); + const [referralPercent, serReferralPercent] = useState(0); + + useEffect(() => { + if (referralStorage > maxReferralStorage) { + serReferralPercent(100); + } else { + serReferralPercent(referralStorage / maxReferralStorage * 100); + } + + }, [referralStorage, maxReferralStorage]); + return (

Хранилище

-
setCloseDev(false)}> - - {!isDev &&

- В хранилище приходит часть коинов, заработанная вашими друзьями. Считаем так: количество коинов * 5%. Хранилище пополняется каждый вечер. -

} - {isDev &&
} +
+ +

+ В хранилище приходит часть коинов, заработанных вашими друзьями. Считаем так: количество коинов * 5%. Хранилище пополняется каждый вечер. +

Как пригласить друга?

Друг присоединяется по пригласительной ссылке и становится рефералом, как только совершает активность в приложении.} /> - Друг кликает, ты получаешь 5% его кликов, а он 3% с твоих. Не забывай забирать коины из хранилища!} /> + Друг кликает, ты получаешь 5% его кликов, а он — 3% с твоих. Не забывай забирать коины из хранилища!} />
- {!closeDev && - } />}
); } diff --git a/frontend/src/shared/Storage/StorageScale/StorageScale.tsx b/frontend/src/shared/Storage/StorageScale/StorageScale.tsx index 4643914..7b31e21 100644 --- a/frontend/src/shared/Storage/StorageScale/StorageScale.tsx +++ b/frontend/src/shared/Storage/StorageScale/StorageScale.tsx @@ -1,8 +1,14 @@ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import styles from './storagescale.module.css'; import { PointsBlock } from '../../Elements/PointsBlock'; import { ETextStyles } from '../../texts'; import { Notification } from '../../Notification'; +import { useDispatch } from 'react-redux'; +import { emptyReferralStorage } from '../../../store/me/actions'; +import { useAppSelector } from '../../hooks/useAppSelector'; +import axios from 'axios'; +import { ModalWindow } from '../../ModalWindow'; +import { DevPopup } from '../../Elements/DevPopup'; interface IStorageScale { percent: number, @@ -13,26 +19,54 @@ interface IStorageScale { export function StorageScale({ percent, points, className, isDev=false }: IStorageScale) { const [showNotif, setShow] = useState(false); - const [initpercent, setPercent] = useState(percent); + const [savedPoints, setSavedPoints] = useState(points); + const URL = useAppSelector(state => state.url); + const token = useAppSelector(state => state.token); + const [closeError, setCloseError] = useState(true); + const [error, setError] = useState(false); + const [animClose, setAnimClose] = useState(false); + const dispatch = useDispatch(); const click = () => { if(percent === 100) { - setShow(true); - setPercent(0); + setError(false); + + if(token) { + axios.post(`${URL}/api/v1/users/empty-storage/`, + {}, + { + headers: { + "Authorization": `TelegramToken ${token}` + } + } + ).then(resp => { + if (!error) { + setShow(true); + dispatch(emptyReferralStorage()); + //console.log(resp); + } + }).catch(err => { + setError(true); + setCloseError(false); + console.log(err); + }); + } } }; return ( -
click()}> +
click()}>
- {initpercent ===100 &&

Забрать

} - {initpercent > 0 && } - {initpercent === 0 && !isDev &&
} - {initpercent === 0 && !isDev &&

Больше друзей — быстрее заполнение

} - {isDev &&

Скоро откроем

} + {percent === 100 &&

Забрать

} + {percent > 0 && } + {percent === 0 &&
} + {percent === 0 &&

{!isDev ? 'Больше друзей — быстрее заполнение' : 'Успевай привести друзей без лимитов'}

}
-
- {showNotif && } +
+ {showNotif && } + {!closeError && + } />}
); } diff --git a/frontend/src/shared/texts/Text.tsx b/frontend/src/shared/texts/Text.tsx index 749c2ec..b53d61b 100644 --- a/frontend/src/shared/texts/Text.tsx +++ b/frontend/src/shared/texts/Text.tsx @@ -87,6 +87,12 @@ export const ETextStyles = { fontSize: '14px', lineHeight: '120%', }, + InRg16130: { + fontFamily: 'Inter, sans-serif', + fontWeight: '400', + fontSize: '16px', + lineHeight: '130%', + }, //SemiBold InSb10120: { fontFamily: 'Inter, sans-serif', diff --git a/frontend/src/store/me/actions.ts b/frontend/src/store/me/actions.ts index 43834a3..84956bc 100644 --- a/frontend/src/store/me/actions.ts +++ b/frontend/src/store/me/actions.ts @@ -9,8 +9,10 @@ export interface IUserData { username?: string; name?: string; avatar?: string; - points?: string + points?: string; energy?: string; + referralStorage?: string; + maxStorage: number; } export const ME_REQUEST = 'ME_REQUEST'; @@ -53,9 +55,15 @@ export const meRequestAsync = (): ThunkAction { axios.post(`${URLClick}/api/v1/click/`, @@ -77,9 +85,9 @@ export const meRequestAsync = (): ThunkAction { @@ -152,8 +162,8 @@ export const meRequestAsync = (): ThunkAction { const user = resp.data; let avatar = user.avatar; - avatar = null; if (!avatar) { avatar = ''; } @@ -221,7 +230,9 @@ export const meRequestAsync = (): ThunkAction { @@ -249,11 +260,48 @@ export const meRequestAsync = (): ThunkAction> => (dispatch, getState) => { +export const updateEnergyRequestAsync = (energy: number): ThunkAction> => (dispatch, getState) => { const meData = getState().me.data; let newData = meData; - newData.points = coins.toString(); newData.energy = energy.toString(); dispatch(meRequestSuccess(newData)); +} + +export const updatePointsRequestAsync = (): ThunkAction> => (dispatch, getState) => { + const meData = getState().me.data; + const tgId = getState().userTg.id; + const URL = getState().url; + const token = getState().token; + + if(token) { + dispatch(meRequest()); + axios.get(`${URL}/api/v1/users/${tgId}/`, { + headers: { + "Content-type": "application/json", + "Authorization": `TelegramToken ${token}` + } + }, + ).then(resp => { + const user = resp.data; + const points = user.points; + const newData = meData; + newData.points = points; + dispatch(meRequestSuccess(newData)); + }).catch((err) => { + console.log(err); + dispatch(meRequestError(String(err))); + }) + } +} + + +export const emptyReferralStorage = (): ThunkAction> => (dispatch, getState) => { + const meData = getState().me.data; + + let newData = meData; + const referralPoints = Number(newData.referralStorage); + newData.referralStorage = '0'; + newData.points = (Number(newData.points) + referralPoints).toString(); + dispatch(meRequestSuccess(newData)); } \ No newline at end of file diff --git a/frontend/src/store/reducer.ts b/frontend/src/store/reducer.ts index 61f6e2f..4bfe9bc 100644 --- a/frontend/src/store/reducer.ts +++ b/frontend/src/store/reducer.ts @@ -15,7 +15,7 @@ export type RootState = { styleIndex: number, me: MeState, referral: string, - mult: number + mult: number, }; //'http://127.0.0.1:8000' @@ -35,10 +35,12 @@ const initialState: RootState = { me: { loading: false, error: '', - data: {} + data: { + maxStorage: 0 + } }, referral: '', - mult: 1 + mult: 1, }; export const RESET_STATE = 'RESET_STATE'; diff --git a/frontend/src/utils/checkMobile.js b/frontend/src/utils/checkMobile.js new file mode 100644 index 0000000..33743c4 --- /dev/null +++ b/frontend/src/utils/checkMobile.js @@ -0,0 +1,22 @@ +export const checkMobile = () => { + const devices = new RegExp( + "Android|webOS|iPhone|iPad|iPod|BlackBerry|BB|PlayBook|IEMobile|Windows Phone|Kindle|Silk|Opera Mini", + "i" + ); + + if(devices.test(navigator.userAgent)) { + return true + }; + + return false; +}; + +export const checkIOS = () => { + const devicesIpone = new RegExp("iPhone|iPad|iPod", "i"); + + if (devicesIpone.test(navigator.userAgent)) { + return true; + } + + return false; +}; \ No newline at end of file diff --git a/frontend/src/utils/updateBackground.js b/frontend/src/utils/updateBackground.js index 54b0003..4dd36cf 100644 --- a/frontend/src/utils/updateBackground.js +++ b/frontend/src/utils/updateBackground.js @@ -7,9 +7,7 @@ export const updateBackground = (page) => { back.style.background = 'linear-gradient(180deg, #0D0D0D 0%, #222 100%) fixed'; } else if (page === 'auction') { back.style.background = '#0D0D0D'; - } else if (page === 'referral') { - back.style.background = 'linear-gradient(167deg, #000 8.46%, #474747 96.84%) fixed'; - } else if (page === 'rating') { + } else { back.style.background = 'linear-gradient(167deg, #000 8.46%, #474747 96.84%) fixed' } } else if (selectedStyle === 1) {