fixes of bugs, loading animation, add max storage

This commit is contained in:
Arseniy Sitnikov 2024-12-12 15:21:19 +03:00
parent 26633b4b55
commit 86d3e9bbf4
31 changed files with 366 additions and 119 deletions

BIN
frontend/.DS_Store vendored

Binary file not shown.

Binary file not shown.

BIN
frontend/src/.DS_Store vendored

Binary file not shown.

View File

@ -32,6 +32,7 @@ function AppComponent() {
<Route path='/referral' element={<RoutePage page='referral' />} /> <Route path='/referral' element={<RoutePage page='referral' />} />
<Route path='/auction' element={<RoutePage page='auction' />} /> <Route path='/auction' element={<RoutePage page='auction' />} />
<Route path='/styles' element={<RoutePage page='styles' />} /> <Route path='/styles' element={<RoutePage page='styles' />} />
<Route path='/dev' element={<RoutePage page='dev' />} />
<Route path='*' element={<RoutePage page='main' />} /> <Route path='*' element={<RoutePage page='main' />} />
</Routes> </Routes>
<AuctionMainPopups /> <AuctionMainPopups />

BIN
frontend/src/assets/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -83,6 +83,7 @@
--grey9A: #9A9A9A; --grey9A: #9A9A9A;
--grey93: #939393; --grey93: #939393;
--grey1F: #1F1F1F; --grey1F: #1F1F1F;
--grey27: #272727;
} }
body { body {
@ -98,6 +99,7 @@ body {
html { html {
scroll-behavior: smooth; scroll-behavior: smooth;
overflow-x: hidden;
} }
p, h1, h2, h3 { p, h1, h2, h3 {

View File

@ -5,10 +5,11 @@ import { ClickerPopup } from '../ClickerPopup';
import { getGradient } from '../../../utils/getGradient'; import { getGradient } from '../../../utils/getGradient';
import { useAppSelector } from '../../hooks/useAppSelector'; import { useAppSelector } from '../../hooks/useAppSelector';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { updateCoinsRequestAsync } from '../../../store/me/actions'; import { updateEnergyRequestAsync } from '../../../store/me/actions';
import axios from 'axios'; import axios from 'axios';
import { DevPopup } from '../../Elements/DevPopup'; import { DevPopup } from '../../Elements/DevPopup';
import { saveMult } from '../../../store/mult'; import { saveMult } from '../../../store/mult';
import { Spinner } from '../../Elements/Spinner';
interface IClickerBtn { interface IClickerBtn {
coins: number, coins: number,
@ -17,7 +18,7 @@ interface IClickerBtn {
setMult(a: number): void setMult(a: number): void
} }
export function ClickerBtn({ coins, setCoins, energy, setMult }: IClickerBtn) { export function ClickerBtn({ setCoins, energy, setMult, coins }: IClickerBtn) {
const urlClick = useAppSelector<string>(state => state.urlClick); const urlClick = useAppSelector<string>(state => state.urlClick);
const token = useAppSelector<string>(state => state.token); const token = useAppSelector<string>(state => state.token);
const [fill, setFill] = useState(0); const [fill, setFill] = useState(0);
@ -35,6 +36,7 @@ export function ClickerBtn({ coins, setCoins, energy, setMult }: IClickerBtn) {
const [error, setError] = useState(false); const [error, setError] = useState(false);
const [animClose, setAnimClose] = useState(false); const [animClose, setAnimClose] = useState(false);
const dispatch = useDispatch(); const dispatch = useDispatch();
const [loading, setLoading] = useState(false);
useEffect(() => { useEffect(() => {
const savedEnergy = sessionStorage.getItem('eg'); const savedEnergy = sessionStorage.getItem('eg');
@ -45,6 +47,12 @@ export function ClickerBtn({ coins, setCoins, energy, setMult }: IClickerBtn) {
setFill((maxEnergy - initEnergy) / maxEnergy * 100); setFill((maxEnergy - initEnergy) / maxEnergy * 100);
}, []); }, []);
useEffect(() => {
if (initEnergy === 0 || fill === 100) {
setCloseError(true);
}
}, [initEnergy, fill]);
useEffect(() => { useEffect(() => {
setGradient(getGradient()) setGradient(getGradient())
}, [styleIndex]); }, [styleIndex]);
@ -58,7 +66,8 @@ export function ClickerBtn({ coins, setCoins, energy, setMult }: IClickerBtn) {
}; };
const sendClick = () => { const sendClick = () => {
if(token) { if (token && !loading) {
setLoading(true);
axios.post(`${urlClick}/api/v1/click/`, axios.post(`${urlClick}/api/v1/click/`,
{}, {},
{ {
@ -69,6 +78,7 @@ export function ClickerBtn({ coins, setCoins, energy, setMult }: IClickerBtn) {
).then((resp) => { ).then((resp) => {
//console.log(resp); //console.log(resp);
if(resp.data) { if(resp.data) {
setLoading(false);
const click = Number(resp.data.click.value); const click = Number(resp.data.click.value);
// //
const encodeMult = btoa(click.toString()); const encodeMult = btoa(click.toString());
@ -80,7 +90,7 @@ export function ClickerBtn({ coins, setCoins, energy, setMult }: IClickerBtn) {
const newFill = (maxEnergy - newEnergy) / maxEnergy * 100; const newFill = (maxEnergy - newEnergy) / maxEnergy * 100;
if (newFill <= 100) { if (newFill <= 100) {
const newCoins = Number(coins + click); const newCoins = Number(coins + click);
dispatch<any>(updateCoinsRequestAsync(newCoins, newEnergy)) dispatch<any>(updateEnergyRequestAsync(newEnergy))
setCoins(newCoins); setCoins(newCoins);
setEnergy(newEnergy) setEnergy(newEnergy)
setFill(newFill); setFill(newFill);
@ -104,6 +114,7 @@ export function ClickerBtn({ coins, setCoins, energy, setMult }: IClickerBtn) {
setError(false) setError(false)
} }
}).catch((err) => { }).catch((err) => {
setLoading(false);
setCloseError(false); setCloseError(false);
setError(true); setError(true);
console.log(err); console.log(err);
@ -120,7 +131,7 @@ export function ClickerBtn({ coins, setCoins, energy, setMult }: IClickerBtn) {
}, },
{ {
title: 'Как продолжить кликать', title: 'Как продолжить кликать',
text: <span>Чтобы охладиться, нужно нужно закрыть приложение, нажав по&nbsp;кнопке ниже.</span>, text: <span>Чтобы охладиться, нужно закрыть приложение, нажав по&nbsp;кнопке ниже.</span>,
img: 'assets/Monocle.png' img: 'assets/Monocle.png'
}, },
{ {
@ -133,7 +144,8 @@ export function ClickerBtn({ coins, setCoins, energy, setMult }: IClickerBtn) {
return ( return (
<div className={styles.ringContainer}> <div className={styles.ringContainer}>
<div className={`${styles.ringBig} ${fill === 100 && styles.borderNone}`}></div> <div className={`${styles.ringBig} ${fill === 100 && styles.borderNone}`}></div>
<div className={`${styles.ringSmall} ${fill === 100 && styles.borderNone}`} style={{ backgroundImage: `url(${img})`, backgroundSize: `${size}px` }} onClick={btnClick}></div> {!loading && <div className={`${styles.ringSmall} ${fill === 100 && styles.borderNone}`} style={{ backgroundImage: `url(${img})`, backgroundSize: `${size}px` }} onClick={btnClick}></div>}
{loading && <div className={styles.loadingContainer}> <Spinner size='50px' thickness='10px' color='var(--primary)'/> </div> }
<svg className={styles.svg} width="270" height="270" viewBox="0 0 270 270" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg className={styles.svg} width="270" height="270" viewBox="0 0 270 270" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="135" cy="135" r="125" stroke={fill < 100 ? "url(#paint0_linear_619_10702)" : '#FF0000'} strokeWidth="20" strokeLinecap="round" style={{ strokeDasharray: `${dashArray} ${circumference}` }} /> <circle cx="135" cy="135" r="125" stroke={fill < 100 ? "url(#paint0_linear_619_10702)" : '#FF0000'} strokeWidth="20" strokeLinecap="round" style={{ strokeDasharray: `${dashArray} ${circumference}` }} />
<defs> <defs>
@ -144,7 +156,7 @@ export function ClickerBtn({ coins, setCoins, energy, setMult }: IClickerBtn) {
<ClickerPopup title='Кнопка перегрелась' cards={hotCards} setClose={setClose} isBtn={true}/> <ClickerPopup title='Кнопка перегрелась' cards={hotCards} setClose={setClose} isBtn={true}/>
} />} } />}
{!closeError && <ModalWindow removeBtn={true} setCloseAnimOut={setAnimClose} closeAnimOut={animClose} setClose={setCloseError} modalBlock={ {!closeError && <ModalWindow removeBtn={true} setCloseAnimOut={setAnimClose} closeAnimOut={animClose} setClose={setCloseError} modalBlock={
<DevPopup setClose={setAnimClose} type='error'/> <DevPopup setClose={setAnimClose} title='Возникла ошибка' text='Мы пока не можем принимать клики, но скоро всё починим.'/>
} />} } />}
</div> </div>
); );

View File

@ -67,3 +67,20 @@
.borderNone { .borderNone {
border: none; 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);
}

View File

@ -7,6 +7,7 @@
background-color: rgba(0, 0, 0, 0.6);*/ background-color: rgba(0, 0, 0, 0.6);*/
background: rgba(0, 0, 0, 0.6); background: rgba(0, 0, 0, 0.6);
border-radius: 12px; border-radius: 12px;
cursor: pointer;
} }
.content { .content {

View File

@ -3,25 +3,18 @@ import styles from './clickerfooter.module.css';
import { ClickerBtnFooter } from '../ClickerBtnFooter'; import { ClickerBtnFooter } from '../ClickerBtnFooter';
import { EIcons, Icon } from '../../Icons'; import { EIcons, Icon } from '../../Icons';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { ModalWindow } from '../../ModalWindow';
import { DevPopup } from '../../Elements/DevPopup';
export function ClickerFooter() { export function ClickerFooter() {
const navigate = useNavigate(); const navigate = useNavigate();
const [closeAnimOut, setCloseAnimOut] = useState(false);
const [closeDev, setCloseDev] = useState(true);
const isDev = true; const isDev = true;
return ( return (
<div className={styles.container}> <div className={styles.container}>
<ClickerBtnFooter text='Стили' className={styles.btn} onClick={() => navigate('/styles')}/> <ClickerBtnFooter text='Стили' className={styles.btn} onClick={() => navigate('/styles')}/>
<ClickerBtnFooter text='Аукцион' className={styles.btn} onClick={() => { !isDev ? navigate('/auction') : setCloseDev(false) }}/> <ClickerBtnFooter text='Аукцион' className={styles.btn} onClick={() => { !isDev ? navigate('/auction') : navigate('/dev?type=auction') }}/>
{ !isDev && <div className={styles.fire}> { !isDev && <div className={styles.fire}>
<Icon icon={EIcons.FireIcon}/> <Icon icon={EIcons.FireIcon}/>
</div>} </div>}
{!closeDev && <ModalWindow removeBtn={true} setCloseAnimOut={setCloseAnimOut} closeAnimOut={closeAnimOut} setClose={setCloseDev} modalBlock={
<DevPopup setClose={setCloseAnimOut} type='dev' />
} />}
</div> </div>
); );
} }

View File

@ -3,33 +3,42 @@ import styles from './pointszoom.module.css';
import { formatNumber } from '../../../utils/formatNumber'; import { formatNumber } from '../../../utils/formatNumber';
import { ETextStyles } from '../../texts'; import { ETextStyles } from '../../texts';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { useDispatch } from 'react-redux';
import { updatePointsRequestAsync } from '../../../store/me/actions';
import { checkIOS } from '../../../utils/checkMobile';
interface IPointsZoom { interface IPointsZoom {
points: number, points: number,
setClose(a:boolean): void, setClose(a:boolean): void,
className ?: string, className ?: string,
closePointsAnim: boolean, 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 [open, setOpen] = useState(true);
const node = document.querySelector('#modal_root'); const node = document.querySelector('#modal_root');
if (!node) return null; if (!node) return null;
const dispatch = useDispatch();
useEffect(() => { useEffect(() => {
const timer = setInterval(() => { const timer = setInterval(() => {
setOpen(false); setOpen(false);
clearInterval(timer); clearInterval(timer);
}, 400); }, 400);
console.log(checkIOS())
}, []); }, []);
useEffect(() => { useEffect(() => {
if (closePointsAnim) { if (closePointsAnim) {
dispatch<any>(updatePointsRequestAsync());
const timer = setTimeout(() => { const timer = setTimeout(() => {
setClosePointsAnim(false); setClosePointsAnim(false);
setClose(true); setClose(true);
clearTimeout(timer); clearTimeout(timer);
setCoins(0);
}, 400); }, 400);
} }
}, [closePointsAnim]); }, [closePointsAnim]);
@ -37,9 +46,9 @@ export function PointsZoom({ points, setClose, className, closePointsAnim, setCl
return ( return (
<div className={`${styles.container} ${className} ${open ? styles.animBack : ''} ${closePointsAnim ? styles.animBackClose : ''}`}> <div className={`${styles.container} ${className} ${open ? styles.animBack : ''} ${closePointsAnim ? styles.animBackClose : ''}`}>
{ReactDOM.createPortal(( {ReactDOM.createPortal((
<div className={`${styles.innerContainer} ${open ? styles.animBlock : ''} ${closePointsAnim ? styles.animBlockClose : ''}`}> <div className={`${styles.innerContainer} ${open ? styles.animBlock : ''} ${closePointsAnim ? styles.animBlockClose : ''} ${checkIOS() && styles.ios}`}>
<div className={styles.icon} style={{ backgroundImage: `url('assets/btnIcon.png')` }}></div> <div className={styles.icon} style={{ backgroundImage: `url('assets/btnIcon.png')` }}></div>
<p className={styles.point} style={ETextStyles.InSb18100}>{formatNumber(Number(points.toFixed(2)))}</p> <p className={styles.point} style={ETextStyles.InSb18100}>{`+${formatNumber(Number(points.toFixed(2)))}`}</p>
</div> </div>
), node)} ), node)}
</div> </div>

View File

@ -24,6 +24,10 @@
box-shadow: 0px 0px 30px 15px rgba(128, 135, 192, 0.25); box-shadow: 0px 0px 30px 15px rgba(128, 135, 192, 0.25);
} }
.ios {
top: 40px !important;
}
.icon { .icon {
width: 40px; width: 40px;
height: 40px; height: 40px;

View File

@ -4,25 +4,30 @@ import { ETextStyles } from '../../texts';
import { formatNumber } from '../../../utils/formatNumber'; import { formatNumber } from '../../../utils/formatNumber';
import { PersonIcon } from '../../Elements/PersonIcon'; import { PersonIcon } from '../../Elements/PersonIcon';
import { EIcons, Icon } from '../../Icons'; import { EIcons, Icon } from '../../Icons';
import { useAppSelector } from '../../hooks/useAppSelector';
import { Spinner } from '../../Elements/Spinner';
interface IProfileClicker { interface IProfileClicker {
name: string, name: string,
points: number,
img: string, img: string,
className ?: string className ?: string
} }
export function Profile({ name, points, img, className }: IProfileClicker) { export function Profile({ name, img, className }: IProfileClicker) {
const points = useAppSelector<string | undefined>(state => state.me.data.points);
const loading = useAppSelector<boolean>(state => state.me.loading);
return ( return (
<div className={`${styles.container} ${className}`}> <div className={`${styles.container} ${className}`}>
{img ? <PersonIcon img={`${img}`} size={30}/> : <div className={styles.emptyIcon}><Icon icon={EIcons.ProfileIcon}/></div> } {img ? <PersonIcon img={`${img}`} size={30} /> : <Icon icon={EIcons.ProfileIcon} /> }
<div className={styles.content}> <div className={styles.content}>
<p style={ETextStyles.RwSb12120} className={styles.name}>{name}</p> <p style={ETextStyles.RwSb12120} className={styles.name}>{name}</p>
<div className={styles.pointsContainer}> <div className={styles.pointsContainer}>
<p className={styles.points} style={ETextStyles.InSb10120}> {points && <p className={styles.points} style={ETextStyles.InSb10120}>
{formatNumber(Number(points.toFixed(2)))} {formatNumber(Number(Number(points).toFixed(2)))}
</p> </p>}
<div className={styles.icon} style={{ backgroundImage: "url('assets/btnIcon.png')"}}></div> {!loading && <div className={styles.icon} style={{ backgroundImage: "url('assets/btnIcon.png')"}}></div>}
{loading && <Spinner size='14px' color='#FFFFFF' thickness='2px' />}
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,4 +1,4 @@
import React, { useState } from 'react'; import React, { useEffect, useState } from 'react';
import styles from './sectionsblock.module.css'; import styles from './sectionsblock.module.css';
import { CardSection } from '../../Elements/CardSection'; import { CardSection } from '../../Elements/CardSection';
import { ETextStyles } from '../../texts'; import { ETextStyles } from '../../texts';
@ -8,30 +8,40 @@ import { ClickerPopup } from '../ClickerPopup';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { UsersIcons } from '../../Elements/UsersIcons'; import { UsersIcons } from '../../Elements/UsersIcons';
import { formatNumber } from '../../../utils/formatNumber'; import { formatNumber } from '../../../utils/formatNumber';
import { DevPopup } from '../../Elements/DevPopup'; import { useAppSelector } from '../../hooks/useAppSelector';
interface ISectionsBlock { interface ISectionsBlock {
mult:number; mult:number;
} }
export function SectionsBlock({ mult }: ISectionsBlock) { export function SectionsBlock({ mult }: ISectionsBlock) {
const scaleRef = 70;
const [close, setClose] = useState(true); const [close, setClose] = useState(true);
const navigate = useNavigate(); const navigate = useNavigate();
const [closeAnimOut, setCloseAnimOut] = useState(false); const referralStorage = Number(useAppSelector<string | undefined>(state => state.me.data.referralStorage));
const [closeDev, setCloseDev] = useState(true); //const referralStorage = 500;
const maxReferralStorage = useAppSelector<number>(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 isDev = true;
const multipCards = [ const multipCards = [
{ {
title: 'Что он делает', title: 'Что он делает',
text: <span>Увеличивает получение баллов с&nbsp;одного клика в&nbsp;столько раз, сколько указано в&nbsp;рамке внизу экрана.</span>, text: <span>Увеличивает получение баллов с&nbsp;одного клика в&nbsp;столько раз, сколько указано в&nbsp;рамке.</span>,
img: 'assets/Rocket.png' img: 'assets/Rocket.png'
}, },
{ {
title: 'Как его увеличить', title: 'Как его увеличить',
text: <span>Чем выше концентрация&nbsp;&mdash; клики в&nbsp;час, тем выше мультипликатор, он&nbsp;рассчитывается по&nbsp;формуле.</span>, text: <span>Чем выше концентрация&nbsp;&mdash; клики в&nbsp;час, тем выше множитель, он&nbsp;рассчитывается по&nbsp;формуле.</span>,
img: 'assets/Monocle.png' img: 'assets/Monocle.png'
}, },
{ {
@ -44,7 +54,7 @@ export function SectionsBlock({ mult }: ISectionsBlock) {
return ( return (
<div className={styles.sectionContainer}> <div className={styles.sectionContainer}>
<div className={styles.leftContainer}> <div className={styles.leftContainer}>
<CardSection title='Место в топе' onClick={() => {!isDev ? navigate('/rating') : setCloseDev(false)}}> <CardSection title='Место в топе' onClick={() => {!isDev ? navigate('/rating') : navigate('/dev?type=rating')}}>
{<div className={`${styles.bottomRank} ${isDev ? styles.dev : ''}`}> {<div className={`${styles.bottomRank} ${isDev ? styles.dev : ''}`}>
<div style={ETextStyles.InSb12120}> <div style={ETextStyles.InSb12120}>
<span className={styles.rank1}>#</span> <span className={styles.rank1}>#</span>
@ -61,22 +71,19 @@ export function SectionsBlock({ mult }: ISectionsBlock) {
</CardSection> </CardSection>
</div> </div>
<CardSection title='Реферальное хранилище' className={styles.rigthEl} onClick={() => { navigate('/referral') }}> <CardSection title='Реферальное хранилище' className={styles.rigthEl} onClick={() => { navigate('/referral') }}>
{<div className={isDev ? styles.dev : ''}> {<div>
<PointsBlock points={formatNumber(800)} className={styles.scalePoints} /> <PointsBlock points={formatNumber(referralStorage.toFixed(2))} className={styles.scalePoints} />
<div className={styles.scaleContainer}> <div className={styles.scaleContainer}>
<div className={styles.scale} style={{ width: `${scaleRef}px` }}></div> <div className={`${styles.scale} ${referralPercent === 100 ? styles.scaleFull : ''}`} style={{ width: `${referralPercent}%` }}></div>
</div> </div>
<p className={styles.scaleText}> <p className={`${styles.scaleText} ${referralPercent === 100 ? styles.textFull : ''}`}>
Хранилище заполнено, заберите коины {referralPercent === 100 ? 'Хранилище заполнено, заберите коины' : 'Когда хранилище заполнится, вы сможете забрать баллы'}
</p> </p>
</div>} </div>}
</CardSection> </CardSection>
{!close && <ModalWindow setCloseAnimOut={setClose} setClose={setClose} modalBlock={ {!close && <ModalWindow setCloseAnimOut={setClose} setClose={setClose} modalBlock={
<ClickerPopup title='Что такое множитель' cards={multipCards} setClose={setClose}/> <ClickerPopup title='Что такое множитель' cards={multipCards} setClose={setClose}/>
} />} } />}
{!closeDev && <ModalWindow removeBtn={true} setCloseAnimOut={setCloseAnimOut} closeAnimOut={closeAnimOut} setClose={setCloseDev} modalBlock={
<DevPopup setClose={setCloseAnimOut} type='dev' />
} />}
</div> </div>
); );
} }

View File

@ -48,6 +48,10 @@
color: var(--grey6C); color: var(--grey6C);
} }
.textFull {
color: var(--white);
}
.scale { .scale {
position: absolute; position: absolute;
top: 0; top: 0;
@ -56,6 +60,10 @@
background: var(--primary); background: var(--primary);
} }
.scaleFull {
background: var(--purple);
}
.dev { .dev {
position: relative; position: relative;
} }

View File

@ -5,18 +5,19 @@ import { ETextStyles } from '../../texts';
interface IDevPopup { interface IDevPopup {
setClose(a: boolean): void 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 ( return (
<div className={styles.container}> <div className={styles.container}>
<div className={styles.iconContainer}> <div className={styles.iconContainer}>
<div className={styles.icon} style={{backgroundImage: "url('assets/dev.png')"}}></div> <div className={styles.icon} style={{backgroundImage: "url('assets/programming.gif')"}}></div>
</div> </div>
<h2 className={styles.title} style={ETextStyles.RwSb24100}>{type === 'dev' ? 'Скоро откроем' : 'Возникла ошибка'}</h2> <h2 className={styles.title} style={ETextStyles.RwSb24100}>{title}</h2>
<p className={styles.text} style={ETextStyles.RwSb14120}>{type === 'dev' ? <span>Подготавливаем что-то особенное для вас. Скоро увидимся на&nbsp;новом уровне!</span> : 'Мы пока не можем принимать клики, но скоро всё починим.'}</p> <p className={styles.text} style={ETextStyles.RwSb14120}>{text}</p>
<Button text={type === 'dev' ? 'Продолжить кликать' : 'Принято'} onClick={() => setClose(true)}/> <Button text='Принято' onClick={() => setClose(true)}/>
</div> </div>
); );
} }

View File

@ -68,7 +68,7 @@ export const StylesSwiper: React.FC<IStylesSwiper> = memo(({ selectedStyle, setC
return ( return (
<div <div
ref={(el) => (slideRefs.current[index] = el as HTMLDivElement)} ref={(el) => (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={{ style={{
transform: `rotate(${isActive ? 0 : deg}deg)`, transform: `rotate(${isActive ? 0 : deg}deg)`,
filter: `blur(${isActive ? 0 : 3}px)` filter: `blur(${isActive ? 0 : 3}px)`

View File

@ -7,7 +7,6 @@ import { SectionsBlock } from '../../Clicker/SectionsBlock';
import { ClickerFooter } from '../../Clicker/ClickerFooter'; import { ClickerFooter } from '../../Clicker/ClickerFooter';
import { StyleElements } from '../../Clicker/StyleElements'; import { StyleElements } from '../../Clicker/StyleElements';
import { PointsZoom } from '../../Clicker/PointsZoom'; import { PointsZoom } from '../../Clicker/PointsZoom';
import { Timer } from '../../Auction/Timer';
import { useWindowSize } from 'usehooks-ts'; import { useWindowSize } from 'usehooks-ts';
import { useAppSelector } from '../../hooks/useAppSelector'; import { useAppSelector } from '../../hooks/useAppSelector';
@ -20,7 +19,7 @@ interface IClickerPageInterface {
export function ClickerPage({ name, points, img, energy }: IClickerPageInterface) { export function ClickerPage({ name, points, img, energy }: IClickerPageInterface) {
const styleIndex = Number(localStorage.getItem('selectedStyle')); const styleIndex = Number(localStorage.getItem('selectedStyle'));
const [coins, setCoins] = useState(points); const [coins, setCoins] = useState(0);
const [mult, setMult] = useState(1); const [mult, setMult] = useState(1);
const [closePoints, setClosePoints] = useState(true); const [closePoints, setClosePoints] = useState(true);
const [closePointsAnim, setClosePointsAnim] = useState(false); const [closePointsAnim, setClosePointsAnim] = useState(false);
@ -35,7 +34,7 @@ export function ClickerPage({ name, points, img, energy }: IClickerPageInterface
//@ts-ignore //@ts-ignore
let timer; let timer;
if (points !== coins) { if (points !== coins && coins != 0) {
setClosePoints(false); setClosePoints(false);
timer = setTimeout(() => { timer = setTimeout(() => {
setClosePointsAnim(true); setClosePointsAnim(true);
@ -50,8 +49,8 @@ export function ClickerPage({ name, points, img, energy }: IClickerPageInterface
return ( return (
<div className={styles.container}> <div className={styles.container}>
<div className={styles.records}> <div className={styles.records}>
{!closePoints && <PointsZoom points={coins} setClosePointsAnim={setClosePointsAnim} setClose={setClosePoints} className={styles.pointsAnim} closePointsAnim={closePointsAnim}/>} {!closePoints && <PointsZoom setCoins={setCoins} points={coins} setClosePointsAnim={setClosePointsAnim} setClose={setClosePoints} className={styles.pointsAnim} closePointsAnim={closePointsAnim}/>}
<Profile name={name} points={coins} className={styles.profile} img={img}/> <Profile name={name} className={styles.profile} img={img}/>
<h1 style={ETextStyles.RwSb24100} className={styles.title}>Мои рекорды</h1> <h1 style={ETextStyles.RwSb24100} className={styles.title}>Мои рекорды</h1>
<SectionsBlock mult={mult}/> <SectionsBlock mult={mult}/>
</div> </div>

View File

@ -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 (
<div className={styles.container}>
<div className={styles.innerContainer}>
<div className={styles.iconContainer}>
<div className={styles.icon} style={{ backgroundImage: `url(${type === 'auction' ? icons[0] : (type === 'rating' ? icons[1] : icons[2])})` }}></div>
</div>
<h1 style={ETextStyles.RwSb26100} className={styles.title}>{type === 'auction' ? titles[0] : (type === 'rating' ? titles[1] : titles[2])}</h1>
<p className={styles.descr} style={ETextStyles.InRg16130}>{type === 'auction' ? texts[0] : (type === 'rating' ? texts[1] : texts[2])}</p>
<Button text='Продолжить кликать' onClick={() => navigate('/')}/>
</div>
</div>
);
}

View File

@ -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;
}

View File

@ -0,0 +1 @@
export * from './DevPage';

View File

@ -13,6 +13,7 @@ import { Spinner } from '../../Elements/Spinner';
import { updateBackground } from '../../../utils/updateBackground'; import { updateBackground } from '../../../utils/updateBackground';
import { ErrorPage } from '../ErrorPage'; import { ErrorPage } from '../ErrorPage';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { DevPage } from '../DevPage';
interface IRoutePage { interface IRoutePage {
page: string page: string
@ -44,11 +45,12 @@ export function RoutePage({ page }: IRoutePage) {
<div> <div>
{!verified ? <WrongSourcePage /> : <div> {!verified ? <WrongSourcePage /> : <div>
{ //@ts-ignore { //@ts-ignore
page === 'main' && !loadingUser && !errorUser && dataUser.name && <ClickerPage name={dataUser.name} points={Number(dataUser.points)} img={dataUser.avatar} energy={Number(dataUser.energy)}/>} page === 'main' && (!loadingUser || dataUser.username) && !errorUser && dataUser.name && <ClickerPage name={dataUser.name} points={Number(dataUser.points)} img={dataUser.avatar} energy={Number(dataUser.energy)}/>}
{page === 'rating' && !loadingUser && !errorUser && <RatingPage />} {page === 'rating' && (!loadingUser || dataUser.username) && !errorUser && <RatingPage />}
{page === 'referral' && !loadingUser && !errorUser && <StoragePage />} {page === 'referral' && (!loadingUser || dataUser.username) && !errorUser && <StoragePage />}
{page === 'auction' && !loadingUser && !errorUser && <AuctionPage />} {page === 'auction' && (!loadingUser || dataUser.username) && !errorUser && <AuctionPage />}
{page === 'styles' && !loadingUser && !errorUser && <StylesPage />} {page === 'styles' && (!loadingUser || dataUser.username) && !errorUser && <StylesPage />}
{page === 'dev' && <DevPage/>}
{(loadingUser) && <div className={styles.spinnerContainer}><Spinner color='#FFFFFF' size='50px' thickness='6px' className={styles.spinner} /></div> } {(loadingUser) && <div className={styles.spinnerContainer}><Spinner color='#FFFFFF' size='50px' thickness='6px' className={styles.spinner} /></div> }
{errorUser && !loadingUser && <ErrorPage detail={errorUser}/>} {errorUser && !loadingUser && <ErrorPage detail={errorUser}/>}
</div>} </div>}

View File

@ -9,16 +9,14 @@ import { Notification } from '../../Notification';
import { StoragePageBlock } from '../../Storage/StoragePageBlock'; import { StoragePageBlock } from '../../Storage/StoragePageBlock';
import { FriendsPageBlock } from '../../Storage/FriendsPageBlock'; import { FriendsPageBlock } from '../../Storage/FriendsPageBlock';
import { useAppSelector } from '../../hooks/useAppSelector'; import { useAppSelector } from '../../hooks/useAppSelector';
import { DevPopup } from '../../Elements/DevPopup'; import { useNavigate } from 'react-router-dom';
import { ModalWindow } from '../../ModalWindow';
export function StoragePage() { export function StoragePage() {
const userId = useAppSelector<string>(state => state.userTg.id); const userId = useAppSelector<string>(state => state.userTg.id);
const [page, setPage] = useState('storage'); const [page, setPage] = useState('storage');
const refLink = `https://t.me/sapphirecrown_bot?start=user_${userId}`; const refLink = `https://t.me/sapphirecrown_bot?start=user_${userId}`;
const [showNotif, setShow] = useState(false); const [showNotif, setShow] = useState(false);
const [closeAnimOut, setCloseAnimOut] = useState(false); const navigate = useNavigate();
const [closeDev, setCloseDev] = useState(true);
return ( return (
<div> <div>
@ -26,7 +24,7 @@ export function StoragePage() {
<div className={styles.btnGroup}> <div className={styles.btnGroup}>
<StorageBtn active={page === 'storage'} type={'storage'} onClick={() => setPage('storage')}/> <StorageBtn active={page === 'storage'} type={'storage'} onClick={() => setPage('storage')}/>
<StorageBtn isDev={true} active={page === 'friends'} type={'friends'} onClick={() => { <StorageBtn isDev={true} active={page === 'friends'} type={'friends'} onClick={() => {
setCloseDev(false); navigate('/dev?type=friends')
//setPage('friends') //setPage('friends')
} }
} /> } />
@ -34,9 +32,6 @@ export function StoragePage() {
{page === 'storage' ? <StoragePageBlock/> : <FriendsPageBlock/>} {page === 'storage' ? <StoragePageBlock/> : <FriendsPageBlock/>}
<Button className={styles.btn} icon={<Icon icon={EIcons.CopyIcon} />} text='Пригласить друга' onClick={() => { сopyTextToClipboard(refLink); setShow(true)}}/> <Button className={styles.btn} icon={<Icon icon={EIcons.CopyIcon} />} text='Пригласить друга' onClick={() => { сopyTextToClipboard(refLink); setShow(true)}}/>
{showNotif && <Notification title='Успешно' text='Пригласительная ссылка скопирована' setShow={setShow} />} {showNotif && <Notification title='Успешно' text='Пригласительная ссылка скопирована' setShow={setShow} />}
{!closeDev && <ModalWindow removeBtn={true} setCloseAnimOut={setCloseAnimOut} closeAnimOut={closeAnimOut} setClose={setCloseDev} modalBlock={
<DevPopup setClose={setCloseAnimOut} type='dev' />
} />}
</div> </div>
); );
} }

View File

@ -11,10 +11,8 @@ export function StylesPage() {
const [selectedStyle, setSelectedStyle] = useState(selectedIndex ? selectedIndex : 0); const [selectedStyle, setSelectedStyle] = useState(selectedIndex ? selectedIndex : 0);
const [currentSlide, setCurrentSlide] = useState(0); const [currentSlide, setCurrentSlide] = useState(0);
const [showNotif, setShow] = useState(false); const [showNotif, setShow] = useState(false);
const isDev = true;
//const stylesNames = ['Черно-синий', 'Grapefruit', 'Tropic mamba', 'Mamba & Grapefruit']; const stylesNames = ['Черно-синий', 'Grapefruit', 'Tropic mamba', 'Mamba & Grapefruit'];
const stylesNames = ['Черно-синий', 'Скоро будет доступен', 'Скоро будет доступен', 'Скоро будет доступен'];
const colors = ['#7EB4DB', '#FE744B', '#F2D06B', '#EA9C55']; 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%)']; 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() {
<span>Будь круче&nbsp;&mdash;</span> будь на&nbsp;стиле!</h1> <span>Будь круче&nbsp;&mdash;</span> будь на&nbsp;стиле!</h1>
<StylesSwiper selectedStyle={selectedStyle} setCurrentSlide={setCurrentSlide}/> <StylesSwiper selectedStyle={selectedStyle} setCurrentSlide={setCurrentSlide}/>
<p style={ETextStyles.RwSb16120} className={styles.styleName}>{stylesNames[currentSlide]}</p> <p style={ETextStyles.RwSb16120} className={styles.styleName}>{stylesNames[currentSlide]}</p>
{!isDev && <Button onClick={selectStyle} disabled={currentSlide === selectedStyle} text={currentSlide === selectedStyle ? 'Уже выбран' : 'Выбрать этот стиль'} className={styles.btn}/>} <Button onClick={selectStyle} disabled={currentSlide === selectedStyle} text={currentSlide === selectedStyle ? 'Уже выбран' : 'Выбрать этот стиль'} className={styles.btn}/>
{showNotif && <Notification title={`Стиль ${stylesNames[selectedStyle]} выбран`} text='Можете вернуться на&nbsp;главную, чтобы увидеть изменения' setShow={setShow} />} {showNotif && <Notification title={`Стиль ${stylesNames[selectedStyle]} выбран`} text='Можете вернуться на&nbsp;главную, чтобы увидеть изменения' setShow={setShow} />}
</div> </div>
); );

View File

@ -1,33 +1,38 @@
import React, { useState } from 'react'; import React, { useEffect, useState } from 'react';
import styles from './storagepageblock.module.css'; import styles from './storagepageblock.module.css';
import { StorageScale } from '../StorageScale'; import { StorageScale } from '../StorageScale';
import { ETextStyles } from '../../texts'; import { ETextStyles } from '../../texts';
import { PopupCard } from '../../Elements/PopupCard'; import { PopupCard } from '../../Elements/PopupCard';
import { ModalWindow } from '../../ModalWindow'; import { useAppSelector } from '../../hooks/useAppSelector';
import { DevPopup } from '../../Elements/DevPopup';
export function StoragePageBlock() { export function StoragePageBlock() {
const [closeAnimOut, setCloseAnimOut] = useState(false); const referralStorage = Number(useAppSelector<string | undefined>(state => state.me.data.referralStorage));
const [closeDev, setCloseDev] = useState(true); const maxReferralStorage = useAppSelector<number>(state => state.me.data.maxStorage);
const isDev = true; const [referralPercent, serReferralPercent] = useState(0);
useEffect(() => {
if (referralStorage > maxReferralStorage) {
serReferralPercent(100);
} else {
serReferralPercent(referralStorage / maxReferralStorage * 100);
}
}, [referralStorage, maxReferralStorage]);
return ( return (
<div> <div>
<h2 style={ETextStyles.RwSb18120} className={styles.title}>Хранилище</h2> <h2 style={ETextStyles.RwSb18120} className={styles.title}>Хранилище</h2>
<div className={`${styles.containerStorage}`} onClick={() => setCloseDev(false)}> <div className={`${styles.containerStorage}`}>
<StorageScale points='0' percent={0} className={styles.scale} isDev={true}/> <StorageScale points={referralStorage.toString()} percent={referralPercent} className={styles.scale}/>
{!isDev && <p style={ETextStyles.RwRg10120} className={styles.descr}> <p style={ETextStyles.RwRg10120} className={styles.descr}>
В&nbsp;хранилище приходит часть коинов, заработанная вашими друзьями. Считаем так: количество коинов * 5%. Хранилище пополняется каждый вечер. В&nbsp;хранилище приходит часть коинов, заработанных вашими друзьями. Считаем так: количество коинов * 5%. Хранилище пополняется каждый вечер.
</p>} </p>
{isDev && <div style={{height: '30px'}}></div> }
</div> </div>
<h2 style={ETextStyles.RwSb18120} className={styles.title}>Как пригласить друга?</h2> <h2 style={ETextStyles.RwSb18120} className={styles.title}>Как пригласить друга?</h2>
<div className={styles.cards}> <div className={styles.cards}>
<PopupCard img='assets/Chain.png' title='Отправляй ссылку другу' text={<span>Друг присоединяется по&nbsp;пригласительной ссылке и&nbsp;становится рефералом, как только совершает активность в&nbsp;приложении.</span>} /> <PopupCard img='assets/Chain.png' title='Отправляй ссылку другу' text={<span>Друг присоединяется по&nbsp;пригласительной ссылке и&nbsp;становится рефералом, как только совершает активность в&nbsp;приложении.</span>} />
<PopupCard img='assets/Money.png' title='Зарабатывайте вместе' text={<span>Друг кликает, ты&nbsp;получаешь&nbsp;5% его кликов, а&nbsp;он&nbsp;3% с&nbsp;твоих. Не&nbsp;забывай забирать коины из&nbsp;хранилища!</span>} /> <PopupCard img='assets/Money.png' title='Зарабатывайте вместе' text={<span>Друг кликает, ты&nbsp;получаешь&nbsp;5% его кликов, а&nbsp;он&nbsp;&mdash; 3%&nbsp;с&nbsp;твоих. Не&nbsp;забывай забирать коины из&nbsp;хранилища!</span>} />
</div> </div>
{!closeDev && <ModalWindow removeBtn={true} setCloseAnimOut={setCloseAnimOut} closeAnimOut={closeAnimOut} setClose={setCloseDev} modalBlock={
<DevPopup setClose={setCloseAnimOut} type='dev' />
} />}
</div> </div>
); );
} }

View File

@ -1,8 +1,14 @@
import React, { useState } from 'react'; import React, { useEffect, useState } from 'react';
import styles from './storagescale.module.css'; import styles from './storagescale.module.css';
import { PointsBlock } from '../../Elements/PointsBlock'; import { PointsBlock } from '../../Elements/PointsBlock';
import { ETextStyles } from '../../texts'; import { ETextStyles } from '../../texts';
import { Notification } from '../../Notification'; 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 { interface IStorageScale {
percent: number, percent: number,
@ -13,26 +19,54 @@ interface IStorageScale {
export function StorageScale({ percent, points, className, isDev=false }: IStorageScale) { export function StorageScale({ percent, points, className, isDev=false }: IStorageScale) {
const [showNotif, setShow] = useState(false); const [showNotif, setShow] = useState(false);
const [initpercent, setPercent] = useState(percent); const [savedPoints, setSavedPoints] = useState(points);
const URL = useAppSelector<string>(state => state.url);
const token = useAppSelector<string>(state => state.token);
const [closeError, setCloseError] = useState(true);
const [error, setError] = useState(false);
const [animClose, setAnimClose] = useState(false);
const dispatch = useDispatch();
const click = () => { const click = () => {
if(percent === 100) { if(percent === 100) {
setShow(true); setError(false);
setPercent(0);
if(token) {
axios.post(`${URL}/api/v1/users/empty-storage/`,
{},
{
headers: {
"Authorization": `TelegramToken ${token}`
}
}
).then(resp => {
if (!error) {
setShow(true);
dispatch<any>(emptyReferralStorage());
//console.log(resp);
}
}).catch(err => {
setError(true);
setCloseError(false);
console.log(err);
});
}
} }
}; };
return ( return (
<div className={`${styles.container} ${initpercent === 100 && styles.full} ${className}`} onClick={() => click()}> <div className={`${styles.container} ${percent === 100 && styles.full} ${className}`} onClick={() => click()}>
<div className={styles.content} style={ETextStyles.InSb16120}> <div className={styles.content} style={ETextStyles.InSb16120}>
{initpercent ===100 && <p>Забрать</p>} {percent === 100 && <p>Забрать</p>}
{initpercent > 0 && <PointsBlock points={points} sizeIcon={20} sizeText={16} />} {percent > 0 && <PointsBlock points={(Number(points).toFixed(2)).toString()} sizeIcon={20} sizeText={16} />}
{initpercent === 0 && !isDev && <div className={styles.imgVolt} style={{backgroundImage: "url('assets/Volt.png')"}}></div>} {percent === 0 && <div className={styles.imgVolt} style={{backgroundImage: "url('assets/Volt.png')"}}></div>}
{initpercent === 0 && !isDev && <p style={ETextStyles.InRg14120}>Больше друзей быстрее заполнение</p> } {percent === 0 && <p style={ETextStyles.InRg14120}>{!isDev ? 'Больше друзей — быстрее заполнение' : 'Успевай привести друзей без лимитов'}</p> }
{isDev && <p style={ETextStyles.InRg14120}>Скоро откроем</p>}
</div> </div>
<div className={styles.scale} style={{ width: `${initpercent}%`}}></div> <div className={styles.scale} style={{ width: `${percent}%`}}></div>
{showNotif && <Notification title='Пополнение' text={`Баланс баллов увеличен на ${points}`} setShow={setShow} />} {showNotif && <Notification title='Пополнение' text={`Баланс баллов увеличен на ${savedPoints}`} setShow={setShow} />}
{!closeError && <ModalWindow removeBtn={true} setCloseAnimOut={setAnimClose} closeAnimOut={animClose} setClose={setCloseError} modalBlock={
<DevPopup setClose={setAnimClose} title='Возникла ошибка' text='Не получилось забрать баллы из реферального хранилища, но скоро всё починим.' />
} />}
</div> </div>
); );
} }

View File

@ -87,6 +87,12 @@ export const ETextStyles = {
fontSize: '14px', fontSize: '14px',
lineHeight: '120%', lineHeight: '120%',
}, },
InRg16130: {
fontFamily: 'Inter, sans-serif',
fontWeight: '400',
fontSize: '16px',
lineHeight: '130%',
},
//SemiBold //SemiBold
InSb10120: { InSb10120: {
fontFamily: 'Inter, sans-serif', fontFamily: 'Inter, sans-serif',

View File

@ -9,8 +9,10 @@ export interface IUserData {
username?: string; username?: string;
name?: string; name?: string;
avatar?: string; avatar?: string;
points?: string points?: string;
energy?: string; energy?: string;
referralStorage?: string;
maxStorage: number;
} }
export const ME_REQUEST = 'ME_REQUEST'; export const ME_REQUEST = 'ME_REQUEST';
@ -53,9 +55,15 @@ export const meRequestAsync = (): ThunkAction<void, RootState, unknown, Action<s
const firstName = getState().userTg.firstName; const firstName = getState().userTg.firstName;
const secondName = getState().userTg.lastName; const secondName = getState().userTg.lastName;
const token = getState().token; const token = getState().token;
const URL = getState().url; const Url = getState().url;
const URLClick = getState().urlClick; const URLClick = getState().urlClick;
const referral = getState().referral; //const referral = getState().referral;
let referral = '';
const currentUrl = new URL(window.location.href);
const referredBy = currentUrl.searchParams.get("referred_by");
if (referredBy) {
referral = referredBy;
}
const firstClick = (token: string) => { const firstClick = (token: string) => {
axios.post(`${URLClick}/api/v1/click/`, axios.post(`${URLClick}/api/v1/click/`,
@ -77,9 +85,9 @@ export const meRequestAsync = (): ThunkAction<void, RootState, unknown, Action<s
dispatch(meRequest()); dispatch(meRequest());
let urlUser = ''; let urlUser = '';
if (referral.length != 0) { if (referral.length != 0) {
urlUser = `${URL}/api/v1/users/${tgId}?referred_by=${referral}`; urlUser = `${Url}/api/v1/users/${tgId}?referred_by=${referral}`;
} else { } else {
urlUser = `${URL}/api/v1/users/${tgId}/`; urlUser = `${Url}/api/v1/users/${tgId}/`;
} }
axios.get(urlUser, { axios.get(urlUser, {
headers: { headers: {
@ -132,7 +140,9 @@ export const meRequestAsync = (): ThunkAction<void, RootState, unknown, Action<s
avatar: user.avatar, avatar: user.avatar,
energy: energy.toString(), //energy energy: energy.toString(), //energy
points: user.points, points: user.points,
name: `${firstName} ${secondName}` name: `${firstName} ${secondName}`,
referralStorage: user.referral_storage,
maxStorage: Number(user.max_storage)
}; };
dispatch(meRequestSuccess(userData)); dispatch(meRequestSuccess(userData));
}).catch((err) => { }).catch((err) => {
@ -152,8 +162,8 @@ export const meRequestAsync = (): ThunkAction<void, RootState, unknown, Action<s
} }
}) })
} }
/*if (tgId && URL && !meData.username) { /*if (tgId && Url && !meData.username) {
axios.get(`${URL}/api/v1/users/get-token/123456`, { axios.get(`${Url}/api/internal/users/get-token/123456`, {
headers: { headers: {
"Content-type": "application/json" "Content-type": "application/json"
} }
@ -165,9 +175,9 @@ export const meRequestAsync = (): ThunkAction<void, RootState, unknown, Action<s
dispatch(meRequest()); dispatch(meRequest());
let urlUser = ''; let urlUser = '';
if (referral.length != 0) { if (referral.length != 0) {
urlUser = `${URL}/api/v1/users/${tgId}?referred_by=${referral}`; urlUser = `${Url}/api/v1/users/${tgId}?referred_by=${referral}`;
} else { } else {
urlUser = `${URL}/api/v1/users/${tgId}/`; urlUser = `${Url}/api/v1/users/${tgId}/`;
} }
axios.get(urlUser, { axios.get(urlUser, {
headers: { headers: {
@ -178,7 +188,6 @@ export const meRequestAsync = (): ThunkAction<void, RootState, unknown, Action<s
).then((resp) => { ).then((resp) => {
const user = resp.data; const user = resp.data;
let avatar = user.avatar; let avatar = user.avatar;
avatar = null;
if (!avatar) { if (!avatar) {
avatar = ''; avatar = '';
} }
@ -221,7 +230,9 @@ export const meRequestAsync = (): ThunkAction<void, RootState, unknown, Action<s
avatar: avatar, avatar: avatar,
energy: energy.toString(), //user.energy energy: energy.toString(), //user.energy
points: user.points, points: user.points,
name: `${firstName} ${secondName}` name: `${firstName} ${secondName}`,
referralStorage: '200', //user.referral_storage
maxStorage: Number(user.max_storage)
}; };
dispatch(meRequestSuccess(userData)); dispatch(meRequestSuccess(userData));
}).catch((err) => { }).catch((err) => {
@ -249,11 +260,48 @@ export const meRequestAsync = (): ThunkAction<void, RootState, unknown, Action<s
} }
export const updateCoinsRequestAsync = (coins: number, energy: number): ThunkAction<void, RootState, unknown, Action<string>> => (dispatch, getState) => { export const updateEnergyRequestAsync = (energy: number): ThunkAction<void, RootState, unknown, Action<string>> => (dispatch, getState) => {
const meData = getState().me.data; const meData = getState().me.data;
let newData = meData; let newData = meData;
newData.points = coins.toString();
newData.energy = energy.toString(); newData.energy = energy.toString();
dispatch(meRequestSuccess(newData)); dispatch(meRequestSuccess(newData));
} }
export const updatePointsRequestAsync = (): ThunkAction<void, RootState, unknown, Action<string>> => (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<void, RootState, unknown, Action<string>> => (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));
}

View File

@ -15,7 +15,7 @@ export type RootState = {
styleIndex: number, styleIndex: number,
me: MeState, me: MeState,
referral: string, referral: string,
mult: number mult: number,
}; };
//'http://127.0.0.1:8000' //'http://127.0.0.1:8000'
@ -35,10 +35,12 @@ const initialState: RootState = {
me: { me: {
loading: false, loading: false,
error: '', error: '',
data: {} data: {
maxStorage: 0
}
}, },
referral: '', referral: '',
mult: 1 mult: 1,
}; };
export const RESET_STATE = 'RESET_STATE'; export const RESET_STATE = 'RESET_STATE';

View File

@ -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;
};

View File

@ -7,9 +7,7 @@ export const updateBackground = (page) => {
back.style.background = 'linear-gradient(180deg, #0D0D0D 0%, #222 100%) fixed'; back.style.background = 'linear-gradient(180deg, #0D0D0D 0%, #222 100%) fixed';
} else if (page === 'auction') { } else if (page === 'auction') {
back.style.background = '#0D0D0D'; back.style.background = '#0D0D0D';
} else if (page === 'referral') { } else {
back.style.background = 'linear-gradient(167deg, #000 8.46%, #474747 96.84%) fixed';
} else if (page === 'rating') {
back.style.background = 'linear-gradient(167deg, #000 8.46%, #474747 96.84%) fixed' back.style.background = 'linear-gradient(167deg, #000 8.46%, #474747 96.84%) fixed'
} }
} else if (selectedStyle === 1) { } else if (selectedStyle === 1) {