upd click request

This commit is contained in:
Arseniy Sitnikov 2024-12-12 18:42:33 +03:00
parent 86d3e9bbf4
commit 9e9fcc5f94
5 changed files with 101 additions and 38 deletions

BIN
frontend/src/.DS_Store vendored

Binary file not shown.

View File

@ -5,7 +5,7 @@ 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 { updateEnergyRequestAsync } from '../../../store/me/actions'; import { IUserData, 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';
@ -15,10 +15,11 @@ interface IClickerBtn {
coins: number, coins: number,
setCoins(a: number): void, setCoins(a: number): void,
energy: number, energy: number,
setMult(a: number): void setMult(a: number): void,
setEnergy(a: number): void
} }
export function ClickerBtn({ setCoins, energy, setMult, coins }: IClickerBtn) { export function ClickerBtn({ setCoins, energy, setMult, coins, setEnergy }: 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);
@ -29,14 +30,12 @@ export function ClickerBtn({ setCoins, energy, setMult, coins }: IClickerBtn) {
const [close, setClose] = useState(true); const [close, setClose] = useState(true);
const [gradient, setGradient] = useState(getGradient()); const [gradient, setGradient] = useState(getGradient());
let styleIndex = useAppSelector<number>(state => state.styleIndex); let styleIndex = useAppSelector<number>(state => state.styleIndex);
const [initEnergy, setEnergy] = useState(energy);
//const maxEnergy = Number(localStorage.getItem('eg'));
const [maxEnergy, setMaxEnergy] = useState(500); const [maxEnergy, setMaxEnergy] = useState(500);
const [closeError, setCloseError] = useState(true);
const [error, setError] = useState(false);
const [animClose, setAnimClose] = useState(false);
const dispatch = useDispatch(); const dispatch = useDispatch();
const [loading, setLoading] = useState(false);
useEffect(() => {
setFill((maxEnergy - energy) / maxEnergy * 100);
}, [energy]);
useEffect(() => { useEffect(() => {
const savedEnergy = sessionStorage.getItem('eg'); const savedEnergy = sessionStorage.getItem('eg');
@ -44,28 +43,40 @@ export function ClickerBtn({ setCoins, energy, setMult, coins }: IClickerBtn) {
const encodeEnergy = atob(savedEnergy); const encodeEnergy = atob(savedEnergy);
setMaxEnergy(Number(encodeEnergy)); setMaxEnergy(Number(encodeEnergy));
} }
setFill((maxEnergy - initEnergy) / maxEnergy * 100); setFill((maxEnergy - energy) / maxEnergy * 100);
}, []); }, []);
useEffect(() => {
if (initEnergy === 0 || fill === 100) {
setCloseError(true);
}
}, [initEnergy, fill]);
useEffect(() => { useEffect(() => {
setGradient(getGradient()) setGradient(getGradient())
}, [styleIndex]); }, [styleIndex]);
const btnClick = () => { const btnClick = () => {
if (!(initEnergy === 0)) { if (energy != 0) {
sendClick(); const newEnergy = energy - 1;
const newFill = (maxEnergy - newEnergy) / maxEnergy * 100;
const newCoins = coins + 1;
dispatch<any>(updateEnergyRequestAsync(newEnergy));
setCoins(newCoins);
setEnergy(newEnergy)
setFill(newFill);
if (newFill < 100) {
setSize(220);
const timer = setTimeout(() => {
setSize(240);
clearTimeout(timer);
}, 100);
} else {
setClose(false);
}
//sendClick();
} else { } else {
setClose(false); setClose(false);
} }
}; };
const sendClick = () => { /*const sendClick = () => {
if (token && !loading) { if (token && !loading) {
setLoading(true); setLoading(true);
axios.post(`${urlClick}/api/v1/click/`, axios.post(`${urlClick}/api/v1/click/`,
@ -120,7 +131,7 @@ export function ClickerBtn({ setCoins, energy, setMult, coins }: IClickerBtn) {
console.log(err); console.log(err);
}) })
} }
}; };*/
const hotCards = [ const hotCards = [
@ -144,8 +155,7 @@ export function ClickerBtn({ setCoins, energy, setMult, coins }: 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>
{!loading && <div className={`${styles.ringSmall} ${fill === 100 && styles.borderNone}`} style={{ backgroundImage: `url(${img})`, backgroundSize: `${size}px` }} onClick={btnClick}></div>} <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>
@ -155,9 +165,6 @@ export function ClickerBtn({ setCoins, energy, setMult, coins }: IClickerBtn) {
{!close && <ModalWindow setCloseAnimOut={setClose} removeBtn={true} setClose={setClose} modalBlock={ {!close && <ModalWindow setCloseAnimOut={setClose} removeBtn={true} setClose={setClose} modalBlock={
<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={
<DevPopup setClose={setAnimClose} title='Возникла ошибка' text='Мы пока не можем принимать клики, но скоро всё починим.'/>
} />}
</div> </div>
); );
} }

View File

@ -4,8 +4,11 @@ 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 { useDispatch } from 'react-redux';
import { updatePointsRequestAsync } from '../../../store/me/actions'; import { meRequest, meRequestError, updateEnergyRequestAsync, updatePointsRequestAsync } from '../../../store/me/actions';
import { checkIOS } from '../../../utils/checkMobile'; import { checkIOS } from '../../../utils/checkMobile';
import axios from 'axios';
import { useAppSelector } from '../../hooks/useAppSelector';
import { saveMult } from '../../../store/mult';
interface IPointsZoom { interface IPointsZoom {
points: number, points: number,
@ -13,27 +16,64 @@ interface IPointsZoom {
className ?: string, className ?: string,
closePointsAnim: boolean, closePointsAnim: boolean,
setClosePointsAnim(a: boolean): void, setClosePointsAnim(a: boolean): void,
setCoins(a:number):void setCoins(a:number):void,
setCloseError(a: boolean): void,
setEnergy(a: number): void,
setMult(a: number): void,
} }
export function PointsZoom({ points, setClose, setCoins, className, closePointsAnim, setClosePointsAnim }: IPointsZoom) { export function PointsZoom({ points, setMult, setClose, setCoins, className, closePointsAnim, setClosePointsAnim, setCloseError, setEnergy }: IPointsZoom) {
const [open, setOpen] = useState(true); const [open, setOpen] = useState(true);
const node = document.querySelector('#modal_root'); const node = document.querySelector('#modal_root');
const urlClick = useAppSelector<string>(state => state.urlClick);
const token = useAppSelector<string>(state => state.token);
const [sizeHand, setSizeHand] = useState(30);
const energy = Number(useAppSelector<string | undefined>(state=>state.me.data.energy));
if (!node) return null; if (!node) return null;
const dispatch = useDispatch(); const dispatch = useDispatch();
const sendClicks = () => {
const initPoints = points;
dispatch(meRequest());
axios.post(`${urlClick}/api/v1/batch-click/`,
{
count: initPoints
},
{
headers: {
"Authorization": `TelegramToken ${token}`
}
}
).then(resp => {
const data = resp.data;
const click = Number(data.click.value);
const encodeMult = btoa(click.toString());
sessionStorage.setItem('mt', encodeMult);
setMult(Number(click.toFixed(2)));
const energy = Number(data.energy);
dispatch<any>(saveMult(Number(click.toFixed(2))));
dispatch<any>(updateEnergyRequestAsync(energy));
dispatch<any>(updatePointsRequestAsync());
}).catch(err => {
console.log(err);
setCloseError(false);
const returnEnergy = energy + initPoints;
setEnergy(returnEnergy);
dispatch<any>(updateEnergyRequestAsync(returnEnergy));
dispatch(meRequestError(String(err)));
})
};
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()); sendClicks();
const timer = setTimeout(() => { const timer = setTimeout(() => {
setClosePointsAnim(false); setClosePointsAnim(false);
setClose(true); setClose(true);
@ -43,12 +83,21 @@ export function PointsZoom({ points, setClose, setCoins, className, closePointsA
} }
}, [closePointsAnim]); }, [closePointsAnim]);
useEffect(() => {
setSizeHand(25);
const timer = setTimeout(() => {
setSizeHand(30);
}, 100);
return () => clearTimeout(timer);
}, [points]);
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 : ''} ${checkIOS() && styles.ios}`}> <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/point.png')`, width: `${sizeHand}px`, height: `${sizeHand}px` }}></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

@ -15,6 +15,7 @@
left: 10px; left: 10px;
z-index: 50; z-index: 50;
width: calc(100% - 20px); width: calc(100% - 20px);
height: 50px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
@ -29,8 +30,6 @@
} }
.icon { .icon {
width: 40px;
height: 40px;
background-position: center; background-position: center;
background-size: contain; background-size: contain;
background-repeat: no-repeat; background-repeat: no-repeat;

View File

@ -9,6 +9,8 @@ import { StyleElements } from '../../Clicker/StyleElements';
import { PointsZoom } from '../../Clicker/PointsZoom'; import { PointsZoom } from '../../Clicker/PointsZoom';
import { useWindowSize } from 'usehooks-ts'; import { useWindowSize } from 'usehooks-ts';
import { useAppSelector } from '../../hooks/useAppSelector'; import { useAppSelector } from '../../hooks/useAppSelector';
import { ModalWindow } from '../../ModalWindow';
import { DevPopup } from '../../Elements/DevPopup';
interface IClickerPageInterface { interface IClickerPageInterface {
name: string, name: string,
@ -25,7 +27,10 @@ export function ClickerPage({ name, points, img, energy }: IClickerPageInterface
const [closePointsAnim, setClosePointsAnim] = useState(false); const [closePointsAnim, setClosePointsAnim] = useState(false);
const { width, height } = useWindowSize(); const { width, height } = useWindowSize();
const savedMult = useAppSelector<number>(state => state.mult); const savedMult = useAppSelector<number>(state => state.mult);
const [closeError, setCloseError] = useState(true);
const [animClose, setAnimClose] = useState(false);
const [initEnergy, setInitEnergy] = useState(energy);
useEffect(() => { useEffect(() => {
setMult(savedMult); setMult(savedMult);
}, [savedMult]); }, [savedMult]);
@ -49,18 +54,21 @@ 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 setCoins={setCoins} points={coins} setClosePointsAnim={setClosePointsAnim} setClose={setClosePoints} className={styles.pointsAnim} closePointsAnim={closePointsAnim}/>} {!closePoints && <PointsZoom setMult={setMult} setEnergy={setInitEnergy} setCloseError={setCloseError} setCoins={setCoins} points={coins} setClosePointsAnim={setClosePointsAnim} setClose={setClosePoints} className={styles.pointsAnim} closePointsAnim={closePointsAnim}/>}
<Profile name={name} 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>
<div className={styles.clicker} style={{height: `${height > 670 && 'calc(100vh - 355px)'}`}}> <div className={styles.clicker} style={{height: `${height > 670 && 'calc(100vh - 355px)'}`}}>
<ClickerBtn coins={coins} setCoins={setCoins} energy={energy} setMult={setMult}/> <ClickerBtn setEnergy={setInitEnergy} coins={coins} setCoins={setCoins} energy={initEnergy} setMult={setMult}/>
</div> </div>
<ClickerFooter /> <ClickerFooter />
{styleIndex != 0 && <div> {styleIndex != 0 && <div>
<StyleElements styleIndex={styleIndex}/> <StyleElements styleIndex={styleIndex}/>
</div>} </div>}
{!closeError && <ModalWindow removeBtn={true} setCloseAnimOut={setAnimClose} closeAnimOut={animClose} setClose={setCloseError} modalBlock={
<DevPopup setClose={setAnimClose} title='Возникла ошибка' text='Мы пока не можем принимать клики, но скоро всё починим.' />
} />}
</div> </div>
); );
} }