auctions and bugs fixed about top imgs
This commit is contained in:
parent
07915ca426
commit
6ae11e83d6
BIN
frontend/src/.DS_Store
vendored
BIN
frontend/src/.DS_Store
vendored
Binary file not shown.
BIN
frontend/src/shared/.DS_Store
vendored
Normal file
BIN
frontend/src/shared/.DS_Store
vendored
Normal file
Binary file not shown.
|
@ -2,8 +2,6 @@ import React, { useState } from 'react';
|
|||
import styles from './auctioncard.module.css';
|
||||
import { ETextStyles } from '../../texts';
|
||||
import { PointsBlock } from '../../Elements/PointsBlock';
|
||||
import { PersonIcon } from '../../Elements/PersonIcon';
|
||||
import { UsersIcons } from '../../Elements/UsersIcons';
|
||||
import { Button } from '../../Button';
|
||||
import { EIcons } from '../../Icons';
|
||||
import { Timer } from '../Timer';
|
||||
|
@ -12,19 +10,23 @@ import { Slider } from '../../Elements/Slider';
|
|||
import { ModalWindow } from '../../ModalWindow';
|
||||
import { AuctionPopup } from '../AuctionPopup';
|
||||
import { ResultAuctionPopup } from '../ResultAuctionPopup';
|
||||
import { DevPopup } from '../../Elements/DevPopup';
|
||||
import { useAppSelector } from '../../hooks/useAppSelector';
|
||||
|
||||
interface IAuctionCard {
|
||||
auctionId: string,
|
||||
name: string,
|
||||
imgs: Array<string>,
|
||||
minBet: string,
|
||||
users: number,
|
||||
prevBet: string,
|
||||
myBetInit: string,
|
||||
time: number,
|
||||
isLead: boolean
|
||||
isLead: boolean,
|
||||
commission: number,
|
||||
className ?: string
|
||||
}
|
||||
|
||||
export function AuctionCard({ name, imgs, users, prevBet, myBetInit, time, isLead }: IAuctionCard) {
|
||||
export function AuctionCard({ name, imgs, users, prevBet, myBetInit, time, isLead, commission, auctionId, className }: IAuctionCard) {
|
||||
const [myBet, setBet] = useState(Number(myBetInit));
|
||||
const [myNewBet, setMyNewBet] = useState(0);
|
||||
const [initPrevBet, setPrevBet] = useState(prevBet);
|
||||
|
@ -33,9 +35,10 @@ export function AuctionCard({ name, imgs, users, prevBet, myBetInit, time, isLea
|
|||
const [closeAnim, setCloseAnim] = useState(false);
|
||||
const [closeresultPopup, setCloseResultPopup] = useState(true);
|
||||
const styleIndex = Number(localStorage.getItem('selectedStyle'));
|
||||
const [closeErrorBet, setCloseErrorBet] = useState(true);
|
||||
|
||||
return (
|
||||
<div className={`${styles.container} ${styleIndex===0 ? styles.darkContainer : styles.opacityContainer}`}>
|
||||
<div className={`${styles.container} ${className} ${styleIndex===0 ? styles.darkContainer : styles.opacityContainer}`}>
|
||||
<Slider className={styles.slider} imgs={imgs}/>
|
||||
<h2 style={ETextStyles.InBd18120} className={styles.title}>{name}</h2>
|
||||
<h3 style={ETextStyles.RwSb16120} className={styles.title2}>Подробности аукциона</h3>
|
||||
|
@ -44,13 +47,13 @@ export function AuctionCard({ name, imgs, users, prevBet, myBetInit, time, isLea
|
|||
<PointsBlock points={initPrevBet} sizeIcon={20}/>
|
||||
</div>
|
||||
<div className={`${styles.card} ${styles.cardFlex} ${styles.card2}`}>
|
||||
<p style={ETextStyles.RwRg14100}>{users === 0 ? 'Ты единственный участник' : 'Участники аукциона'}</p>
|
||||
{users === 0 ? <PersonIcon /> : <div className={styles.usersBlock}><UsersIcons/> {users > 3 && <div className={styles.userCount} style={ETextStyles.InSb10120}>{users-3}</div>}</div>}
|
||||
<p style={ETextStyles.RwRg14100}>Количество победителей</p>
|
||||
<div className={styles.winnersNumber}>{users}</div>
|
||||
</div>
|
||||
<div className={`${styles.card} ${initLead && styles.leadCard}`}>
|
||||
<div className={styles.cardTop}>
|
||||
<div className={styles.cardLeft} style={ETextStyles.RwSb14120}>{!initLead ? 'Успей сделать ставку! До конца осталось:'
|
||||
: <p><span>Ты в числе победителей! </span>Но все может поменяться</p>}</div>
|
||||
<div className={styles.cardLeft} style={ETextStyles.RwSb14120}>{initLead ? <p><span>Ты в числе победителей! </span>Но все может поменяться</p>
|
||||
: <p>{myBet > 0 ? 'Вашу ставку перебили, повысьте ее, чтобы сохранить лидерство' : 'Успей сделать ставку! До конца осталось:' }</p> }</div>
|
||||
<Timer initTime={time}/>
|
||||
</div>
|
||||
<Button onClick={() => setClose(false)} text={myBet === 0 ? 'Сделать первую ставку' : <div className={styles.newBtn}>
|
||||
|
@ -63,11 +66,14 @@ export function AuctionCard({ name, imgs, users, prevBet, myBetInit, time, isLea
|
|||
icon={EIcons.UpPriceIcon}/>
|
||||
</div>
|
||||
{!closeWindow && <ModalWindow closeAnimOut={closeAnim} setCloseAnimOut={setCloseAnim} setClose={setClose} removeBtn={true} modalBlock={
|
||||
<AuctionPopup setLead={setLead} setClose={setCloseAnim} img={imgs[0]} name={name} prevBet={initPrevBet} prevUserImg={''} setBet={setMyNewBet} setCloseResultPopup={setCloseResultPopup}/>
|
||||
<AuctionPopup myBet={myBet} setCloseErrorBet={setCloseErrorBet} auctionId={auctionId} commission={commission} setLead={setLead} setClose={setCloseAnim} img={imgs[0]} name={name} prevBet={initPrevBet} prevUserImg={''} setBet={setMyNewBet} setCloseResultPopup={setCloseResultPopup}/>
|
||||
} />}
|
||||
{!closeresultPopup && <ModalWindow closeAnimOut={closeAnim} setCloseAnimOut={setCloseAnim} setClose={setCloseResultPopup} removeBtn={true} modalBlock={
|
||||
{!closeresultPopup && closeErrorBet && <ModalWindow closeAnimOut={closeAnim} setCloseAnimOut={setCloseAnim} setClose={setCloseResultPopup} removeBtn={true} modalBlock={
|
||||
<ResultAuctionPopup prevBet={initPrevBet} prevMyBet={myBet} newBet={myNewBet} setBet={setBet} setClose={setCloseAnim} setCloseBetWindow={setClose} setPrevBet={setPrevBet}/>
|
||||
} />}
|
||||
{!closeErrorBet && <ModalWindow closeAnimOut={closeAnim} setCloseAnimOut={setCloseAnim} setClose={setCloseErrorBet} removeBtn={true} modalBlock={
|
||||
<DevPopup setClose={setCloseAnim} title='Возникла ошибка' text='Не получилось сделать ставку. Но мы скоро всё починим.' />
|
||||
} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -114,3 +114,13 @@
|
|||
border-radius: 15px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.winnersNumber {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 27px;
|
||||
height: 27px;
|
||||
border-radius: 50%;
|
||||
background-color: var(--grey34);
|
||||
}
|
|
@ -4,6 +4,7 @@ import { useNavigate } from 'react-router-dom';
|
|||
import { ETextStyles } from '../../texts';
|
||||
import { ProductCard } from '../ProductCard';
|
||||
import { Button } from '../../Button';
|
||||
import { generateRandomString } from '../../../utils/generateRandom';
|
||||
|
||||
interface IProduct {
|
||||
name: string,
|
||||
|
@ -28,7 +29,7 @@ export function AuctionLosePopup({ items, setClose }: IAuctionLosePopup) {
|
|||
<h3 className={styles.title2} style={ETextStyles.RwSb18120}>Аукционы, в которых нужно увеличить ставку:</h3>
|
||||
<div className={styles.cards}>
|
||||
{items.map(item => {
|
||||
return <ProductCard name={item.name} img={item.img} bet={item.bet} />
|
||||
return <ProductCard key={ generateRandomString() } name={item.name} img={item.img} bet={item.bet} />
|
||||
})}
|
||||
</div>
|
||||
<Button text='Увеличить ставку' onClick={() => { navigate('/auction'); setClose(true) }} />
|
||||
|
|
|
@ -1,39 +1,50 @@
|
|||
import React, { useState } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import styles from './auctionmainpopups.module.css';
|
||||
import { ModalWindow } from '../../ModalWindow';
|
||||
import { AuctionWinPopup } from '../AuctionWinPopup';
|
||||
import { AuctionTopPopup } from '../AuctionTopPopup';
|
||||
import { AuctionLosePopup } from '../AuctionLosePopup';
|
||||
import { useAppSelector } from '../../hooks/useAppSelector';
|
||||
import { IAuctionItem } from '../../../store/me/actions';
|
||||
|
||||
export function AuctionMainPopups() {
|
||||
const [closeWin, setCloseWin] = useState(true);
|
||||
const [closeTop, setCloseTop] = useState(true);
|
||||
const [closeLose, setCloseLose] = useState(true);
|
||||
const [closeAnim, setCloseAnim] = useState(false);
|
||||
const topAuctions = useAppSelector<Array<IAuctionItem> | undefined>(state=>state.me.data.topAuctions);
|
||||
const loseAuctions = useAppSelector<Array<IAuctionItem> | undefined>(state => state.me.data.loseAuctions);
|
||||
|
||||
const items = [
|
||||
{
|
||||
name: 'iPhone 15 Pro Max',
|
||||
img: '',
|
||||
bet: '788'
|
||||
},
|
||||
{
|
||||
name: 'iPhone 13 Pro',
|
||||
img: '',
|
||||
bet: '200'
|
||||
useEffect(() => {
|
||||
const show = sessionStorage.getItem('shT');
|
||||
if (show === 't' && closeTop) {
|
||||
if (topAuctions && topAuctions.length != 0) {
|
||||
sessionStorage.setItem('shT', 'f');
|
||||
setCloseTop(false);
|
||||
}
|
||||
];
|
||||
}
|
||||
}, [topAuctions]);
|
||||
|
||||
useEffect(() => {
|
||||
const show = sessionStorage.getItem('shL');
|
||||
if (show === 't' && closeLose) {
|
||||
if (loseAuctions && loseAuctions.length != 0) {
|
||||
sessionStorage.setItem('shL', 'f');
|
||||
setCloseLose(false);
|
||||
}
|
||||
}
|
||||
}, [loseAuctions]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{!closeWin && <ModalWindow closeAnimOut={closeAnim} setCloseAnimOut={setCloseAnim} setClose={setCloseWin} removeBtn={true} modalBlock={
|
||||
<AuctionWinPopup name='iPhone 15 Pro Max ' img='' setClose={setCloseAnim}/>
|
||||
} />}
|
||||
{!closeTop && <ModalWindow closeAnimOut={closeAnim} setCloseAnimOut={setCloseAnim} setClose={setCloseTop} removeBtn={true} modalBlock={
|
||||
<AuctionTopPopup items={items} setClose={setCloseAnim}/>
|
||||
{!closeTop && topAuctions != undefined && <ModalWindow closeAnimOut={closeAnim} setCloseAnimOut={setCloseAnim} setClose={setCloseTop} removeBtn={true} modalBlock={
|
||||
<AuctionTopPopup items={topAuctions} setClose={setCloseAnim}/>
|
||||
} />}
|
||||
{!closeLose && <ModalWindow closeAnimOut={closeAnim} setCloseAnimOut={setCloseAnim} setClose={setCloseLose} removeBtn={true} modalBlock={
|
||||
<AuctionLosePopup items={items} setClose={setCloseAnim} />
|
||||
{!closeLose && loseAuctions != undefined && <ModalWindow closeAnimOut={closeAnim} setCloseAnimOut={setCloseAnim} setClose={setCloseLose} removeBtn={true} modalBlock={
|
||||
<AuctionLosePopup items={loseAuctions} setClose={setCloseAnim} />
|
||||
} />}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
import React, { useState } from 'react';
|
||||
import styles from './auctionpopup.module.css';
|
||||
import { ETextStyles } from '../../texts';
|
||||
import { PersonIcon } from '../../Elements/PersonIcon';
|
||||
import { PointsBlock } from '../../Elements/PointsBlock';
|
||||
import { Button } from '../../Button';
|
||||
import { EIcons } from '../../Icons';
|
||||
import { declension } from '../../../utils/declension';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { ProductCard } from '../ProductCard';
|
||||
import { useAppSelector } from '../../hooks/useAppSelector';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import axios from 'axios';
|
||||
import { updatePointsRequestAsync } from '../../../store/me/actions';
|
||||
import { updateAuction } from '../../../store/auction/actions';
|
||||
|
||||
interface IAuctionPopup {
|
||||
auctionId: string,
|
||||
setClose(a: boolean): void,
|
||||
setLead(a: boolean): void,
|
||||
img: string,
|
||||
|
@ -17,16 +21,23 @@ interface IAuctionPopup {
|
|||
prevBet: string,
|
||||
prevUserImg: string,
|
||||
setBet(a: number): void,
|
||||
setCloseResultPopup(a: boolean): void
|
||||
setCloseResultPopup(a: boolean): void,
|
||||
commission: number,
|
||||
setCloseErrorBet(a: boolean): void,
|
||||
myBet: number
|
||||
}
|
||||
|
||||
export function AuctionPopup({ setClose, img, name, prevBet, prevUserImg, setBet, setLead, setCloseResultPopup }: IAuctionPopup) {
|
||||
export function AuctionPopup({ setClose, setCloseErrorBet, auctionId, img, name, prevBet, prevUserImg, setBet, setLead, setCloseResultPopup, commission, myBet }: IAuctionPopup) {
|
||||
const [value, setValue] = useState<string>('');
|
||||
const [disabled, setDis] = useState(true);
|
||||
const [autoBet, setAutoBet] = useState(false);
|
||||
const navigate = useNavigate();
|
||||
const percent = 5;
|
||||
const userPoints = 1000;
|
||||
const [percent, setPercent] = useState(commission);
|
||||
const userPoints = Number(useAppSelector<string | undefined>(state=>state.me.data.points));
|
||||
const URL = useAppSelector<string>(state=>state.url);
|
||||
const token = useAppSelector<string>(state => state.token);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
|
||||
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
let newValue = event.target.value;
|
||||
|
@ -41,28 +52,43 @@ export function AuctionPopup({ setClose, img, name, prevBet, prevUserImg, setBet
|
|||
}
|
||||
|
||||
const newBet = () => {
|
||||
setBet(Math.floor((1 + percent / 100) * Number(value)));
|
||||
const bet = Number(value);
|
||||
setClose(true);
|
||||
setLead(true);
|
||||
|
||||
if (token) {
|
||||
axios.post(`${URL}/api/v1/auction/auction/${auctionId}/place-bet/?value=${bet}`, {},
|
||||
{
|
||||
headers: {
|
||||
"Authorization": `TelegramToken ${token}`
|
||||
}
|
||||
}
|
||||
).then(resp => {
|
||||
const data = resp.data;
|
||||
dispatch<any>(updatePointsRequestAsync());
|
||||
dispatch<any>(updateAuction(auctionId));
|
||||
setBet(bet);
|
||||
setLead(true);
|
||||
const timer = setInterval(() => {
|
||||
setCloseResultPopup(false);
|
||||
clearTimeout(timer);
|
||||
}, 400);
|
||||
|
||||
}).catch(err => {
|
||||
setCloseErrorBet(false);
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2 className={styles.title} style={ETextStyles.RwSb24100}>Сделать ставку</h2>
|
||||
<ProductCard name={name} img={img} bet={prevBet} personImg={prevUserImg} className={styles.card} />
|
||||
{!autoBet ? <Button onClick={() => { setAutoBet(true), setValue((Number(prevBet) + 5).toString()), setDis(false) }} text='Сразу перебить ставку' className={styles.btnFirst} icon={<div className={styles.icon} style={{ backgroundImage: "url('assets/Rocket.png')" }}></div>} /> :
|
||||
{!autoBet ? <Button onClick={() => { setAutoBet(true), setValue(Number(Number((1 + percent / 100) * Number(prevBet)).toFixed(2)).toString()), setDis(false) }} text='Сразу перебить ставку' className={styles.btnFirst} icon={<div className={styles.icon} style={{ backgroundImage: "url('assets/Rocket.png')" }}></div>} /> :
|
||||
<button style={ETextStyles.InBd14120} className={styles.btnCancel} onClick={() => setClose(true)}>Не перебивать</button>
|
||||
}
|
||||
<p className={styles.descr} style={ETextStyles.RwRg10140}>Наши алгоритмы автоматически рассчитают стоимость, чтобы ваша ставка стала самой высокой</p>
|
||||
<h3 className={styles.title2} style={ETextStyles.InSb14120}>{!autoBet ? 'Ввести свою цену' : 'Цена, чтобы перебить ставку'}</h3>
|
||||
<input style={ETextStyles.InSb14120} className={styles.input} value={value} type="text" onChange={handleChange} inputMode="numeric" />
|
||||
{(Math.floor((1 + percent / 100) * Number(value)) < userPoints) ? ((Number(value) < Number(prevBet) && value.length > 0) ?
|
||||
{(Number(Number((1 + percent / 100) * Number(value))) - myBet < userPoints) ? ((Number(value) < Number(prevBet) && value.length > 0) ?
|
||||
<button className={styles.btnForbidden}>
|
||||
<p style={ETextStyles.InBd14120}>Ставка должна быть больше</p>
|
||||
<p style={ETextStyles.InRg12140} className={styles.textForbidden}>Нельзя сделать ставку меньше предыдущей</p>
|
||||
|
@ -70,7 +96,7 @@ export function AuctionPopup({ setClose, img, name, prevBet, prevUserImg, setBet
|
|||
: <Button onClick={() => newBet()} disabled={disabled} text={disabled ? 'Перебить ставку' : <div className={styles.newBtn}>
|
||||
<p>Перебить ставку</p>
|
||||
<div className={styles.btnText}>
|
||||
<p style={ETextStyles.InRg12140}>{`${declension(value, 'коин', 'коина', 'коинов', true)} + ${percent}% = ${declension(Math.floor((1 + percent / 100) * Number(value)), 'коин', 'коина', 'коинов', true)}`}</p>
|
||||
<p style={ETextStyles.InRg12140}>{`${declension(value, 'коин', 'коина', 'коинов', true)} + ${percent}% = ${declension(Number(Number((1 + percent / 100) * Number(value)).toFixed(2)), 'коин', 'коина', 'коинов', true)}`}</p>
|
||||
<div className={styles.icon} style={{ backgroundImage: "url('assets/btnIcon.png')" }}></div>
|
||||
</div>
|
||||
</div>}
|
||||
|
|
|
@ -4,6 +4,7 @@ import { ETextStyles } from '../../texts';
|
|||
import { ProductCard } from '../ProductCard';
|
||||
import { Button } from '../../Button';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { generateRandomString } from '../../../utils/generateRandom';
|
||||
|
||||
interface IProduct {
|
||||
name: string,
|
||||
|
@ -20,7 +21,7 @@ export function AuctionTopPopup({ items, setClose }: IAuctionTopPopup) {
|
|||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='top'>
|
||||
<div className={styles.iconBlock}>
|
||||
<div className={styles.icon} style={{ backgroundImage: "url('assets/Fire.png')" }}></div>
|
||||
</div>
|
||||
|
@ -29,7 +30,7 @@ export function AuctionTopPopup({ items, setClose }: IAuctionTopPopup) {
|
|||
<h3 className={styles.title2} style={ETextStyles.RwSb18120}>Аукционы, в которых вы лидируете:</h3>
|
||||
<div className={styles.cards}>
|
||||
{items.map(item => {
|
||||
return <ProductCard name={item.name} img={item.img} bet={item.bet} />
|
||||
return <ProductCard key={ generateRandomString() } name={item.name} img={item.img} bet={item.bet} />
|
||||
})}
|
||||
</div>
|
||||
<Button text='Продолжить кликать' onClick={() => { navigate('/'); setClose(true)}}/>
|
||||
|
|
|
@ -18,12 +18,17 @@ interface IResultAuctionPopup {
|
|||
export function ResultAuctionPopup({ prevBet, prevMyBet, newBet, setBet, setClose, setCloseBetWindow, setPrevBet }: IResultAuctionPopup) {
|
||||
const [diff, setDiff] = useState(0);
|
||||
const [prevBetOld, setPrevBetOld] = useState(prevBet);
|
||||
const [prevMyOldBet, setPrevMyOld] = useState(prevMyBet);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
setDiff(newBet - prevMyBet);
|
||||
if (prevMyOldBet > 0) {
|
||||
setDiff(newBet - prevMyOldBet);
|
||||
} else {
|
||||
setDiff(newBet - Number(prevBetOld));
|
||||
}
|
||||
setBet(newBet);
|
||||
setPrevBet(newBet.toString())
|
||||
setPrevBet(newBet.toString());
|
||||
}, []);
|
||||
|
||||
const onClick = () => {
|
||||
|
@ -40,7 +45,7 @@ export function ResultAuctionPopup({ prevBet, prevMyBet, newBet, setBet, setClos
|
|||
<div className={styles.icon} style={{backgroundImage: 'url("assets/Money.png")'}}></div>
|
||||
</div>
|
||||
<div className={styles.text} style={ETextStyles.InSb24100}>
|
||||
Вы <span>увеличили</span> ставку <span>{`на ${diff}`}</span> {declension(diff, 'коин', 'коина', 'коинов')}
|
||||
Вы <span>{prevMyOldBet > 0 ? 'увеличили' : 'перебили'}</span> ставку <span>{`на ${diff.toFixed(2)}`}</span> {declension(diff.toFixed(2), 'коин', 'коина', 'коинов')}
|
||||
</div>
|
||||
<div className={styles.cards}>
|
||||
<div className={styles.card}>
|
||||
|
|
|
@ -40,7 +40,7 @@ export function Timer({initTime}: ITimer) {
|
|||
</div>
|
||||
<div className={styles.dot}></div>
|
||||
<div className={styles.block}>
|
||||
<p className={styles.value} style={ETextStyles.InSb14120}>{min}</p>
|
||||
<p className={styles.value} style={ETextStyles.InSb14120}>{min.toString().length === 1 ? `0${min}` : min}</p>
|
||||
<p className={styles.text} style={ETextStyles.RwRg12120}>мин</p>
|
||||
</div>
|
||||
<div className={styles.dot}></div>
|
||||
|
|
|
@ -17,10 +17,11 @@ interface IClickerBtn {
|
|||
clickTime: number,
|
||||
sameCoords: boolean,
|
||||
setSameCoords(a: boolean): void,
|
||||
closeAutoClick: boolean
|
||||
closeAutoClick: boolean,
|
||||
setSameInterval(a: boolean): void,
|
||||
}
|
||||
|
||||
export function ClickerBtn({ setCoins, closeAutoClick, energy, setMult, coins, setEnergy, setClickTime, clickTime, setSameCoords }: IClickerBtn) {
|
||||
export function ClickerBtn({ setCoins, setSameInterval, closeAutoClick, energy, setMult, coins, setEnergy, setClickTime, clickTime, setSameCoords }: IClickerBtn) {
|
||||
const [fill, setFill] = useState(0);
|
||||
const [size, setSize] = useState(240);
|
||||
const circumference = 2 * Math.PI * 125;
|
||||
|
@ -33,6 +34,7 @@ export function ClickerBtn({ setCoins, closeAutoClick, energy, setMult, coins, s
|
|||
const dispatch = useDispatch();
|
||||
const [prevClickTime, setPrevClickTime] = useState(0);
|
||||
const [prevCoords, setPrevCoords] = useState(0);
|
||||
const [clickInterval, setClickInterval] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
if(!closeAutoClick) {
|
||||
|
@ -78,9 +80,17 @@ export function ClickerBtn({ setCoins, closeAutoClick, energy, setMult, coins, s
|
|||
setPrevCoords(coords);
|
||||
|
||||
const currentTime = Date.now();
|
||||
const clickInterval = currentTime - prevClickTime;
|
||||
const clickIntervalInit = currentTime - prevClickTime;
|
||||
if (clickInterval != 0) {
|
||||
if (clickInterval === clickIntervalInit) {
|
||||
setSameInterval(true)
|
||||
} else {
|
||||
setSameInterval(false)
|
||||
}
|
||||
}
|
||||
|
||||
if(prevClickTime != 0) {
|
||||
setClickTime(clickTime + clickInterval);
|
||||
setClickTime(clickTime + clickIntervalInit);
|
||||
}
|
||||
setPrevClickTime(currentTime);
|
||||
|
||||
|
@ -136,7 +146,7 @@ export function ClickerBtn({ setCoins, closeAutoClick, energy, setMult, coins, s
|
|||
{gradient}
|
||||
</defs>
|
||||
</svg>
|
||||
{!close && !closeAutoClick && <ModalWindow setCloseAnimOut={setClose} removeBtn={true} setClose={setClose} modalBlock={
|
||||
{!close && closeAutoClick && <ModalWindow setCloseAnimOut={setClose} removeBtn={true} setClose={setClose} modalBlock={
|
||||
<ClickerPopup title='Кнопка перегрелась' cards={hotCards} setClose={setClose} isBtn={true}/>
|
||||
} />}
|
||||
</div>
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
import React, { useState } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import styles from './clickerfooter.module.css';
|
||||
import { ClickerBtnFooter } from '../ClickerBtnFooter';
|
||||
import { EIcons, Icon } from '../../Icons';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { isWhiteList } from '../../../utils/isWhiteList';
|
||||
|
||||
export function ClickerFooter() {
|
||||
const navigate = useNavigate();
|
||||
const isDev = true;
|
||||
const [isDev, setIsDev] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
setIsDev(!isWhiteList());
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
|
|
|
@ -26,9 +26,11 @@ interface IPointsZoom {
|
|||
setCloseAutoClick(a: boolean): void,
|
||||
sameCoords: boolean,
|
||||
setSameCoords(a: boolean): void,
|
||||
setSameInterval(a: boolean): void,
|
||||
sameInterval: boolean,
|
||||
}
|
||||
|
||||
export function PointsZoom({ points, sameCoords, setSameCoords, setCloseAutoClick, setMult, setClose, setCoins, className, closePointsAnim, setClosePointsAnim, setCloseError, setEnergy, clickTime, setClickTime }: IPointsZoom) {
|
||||
export function PointsZoom({ points, sameInterval, setSameInterval, sameCoords, setSameCoords, setCloseAutoClick, setMult, setClose, setCoins, className, closePointsAnim, setClosePointsAnim, setCloseError, setEnergy, clickTime, setClickTime }: IPointsZoom) {
|
||||
const [open, setOpen] = useState(true);
|
||||
const node = document.querySelector('#modal_root');
|
||||
const urlClick = useAppSelector<string>(state => state.urlClick);
|
||||
|
@ -36,6 +38,7 @@ export function PointsZoom({ points, sameCoords, setSameCoords, setCloseAutoClic
|
|||
const [sizeHand, setSizeHand] = useState(30);
|
||||
const energy = Number(useAppSelector<string | undefined>(state => state.me.data.energy));
|
||||
const userData = useAppSelector<IUserData>(state => state.me.data);
|
||||
const URL = useAppSelector<string>(state => state.url);
|
||||
if (!node) return null;
|
||||
const dispatch = useDispatch();
|
||||
|
||||
|
@ -43,6 +46,7 @@ export function PointsZoom({ points, sameCoords, setSameCoords, setCloseAutoClic
|
|||
const initPoints = points;
|
||||
const clickTimeInit = clickTime;
|
||||
let initSameCoords = sameCoords;
|
||||
let initSameInterval = sameInterval;
|
||||
let avtTime = 500;
|
||||
if (points > 1) {
|
||||
avtTime = clickTimeInit / (initPoints - 1);
|
||||
|
@ -51,9 +55,20 @@ export function PointsZoom({ points, sameCoords, setSameCoords, setCloseAutoClic
|
|||
setClickTime(0);
|
||||
setSameCoords(false);
|
||||
|
||||
if (avtTime < 100 && initSameCoords && points > 40) {
|
||||
if ((avtTime < 100 && initSameCoords) || (initSameInterval) && initPoints > 20) {
|
||||
|
||||
/*axios.post(`${URL}/api/v1/users/warn/`, {}, {
|
||||
headers: {
|
||||
"Authorization": `TelegramToken ${token}`
|
||||
}
|
||||
}).then(resp => {
|
||||
console.log(resp);
|
||||
}).catch(err => {
|
||||
//console.log(err)
|
||||
})*/
|
||||
sendAutoClickData(userData.tgId, points, avtTime);
|
||||
setCloseAutoClick(false);
|
||||
setSameInterval(false);
|
||||
const returnEnergy = energy + initPoints;
|
||||
setEnergy(returnEnergy);
|
||||
dispatch<any>(updateEnergyRequestAsync(returnEnergy));
|
||||
|
|
|
@ -66,6 +66,8 @@ export function SectionsBlock({ mult }: ISectionsBlock) {
|
|||
},
|
||||
];
|
||||
|
||||
//<UsersIcons imgs={topImgs} size={16}/>
|
||||
|
||||
return (
|
||||
<div className={styles.sectionContainer}>
|
||||
<div className={styles.leftContainer}>
|
||||
|
@ -75,7 +77,6 @@ export function SectionsBlock({ mult }: ISectionsBlock) {
|
|||
<span className={styles.rank1}>#</span>
|
||||
<span>{isDev ? '?' : (userRank ? formatNumber(userRank) : '?')}</span>
|
||||
</div>
|
||||
<UsersIcons imgs={topImgs} size={16}/>
|
||||
</div>}
|
||||
</CardSection>
|
||||
<CardSection title='Множитель' onClick={() => { setClose(false) }}>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React from 'react';
|
||||
import styles from './usersicons.module.css';
|
||||
import { PersonIcon } from '../PersonIcon';
|
||||
import { EIcons, Icon } from '../../Icons';
|
||||
|
||||
interface IUsersIcons {
|
||||
size?: number,
|
||||
|
@ -11,9 +12,15 @@ interface IUsersIcons {
|
|||
export function UsersIcons({ size = 25, imgs = [], className = '' }: IUsersIcons) {
|
||||
return (
|
||||
<div className={`${styles.users} ${className}`} style={{height: `${size}px`, width: `${size*2.5}px`}}>
|
||||
<PersonIcon className={`${styles.userIcon} ${styles.userIcon1}`} size={size} img={imgs[0] ? imgs[0] : ''}/>
|
||||
<PersonIcon className={`${styles.userIcon} ${styles.userIcon2}`} size={size} left={size / 1.4} img={imgs[1] ? imgs[1] : ''} />
|
||||
<PersonIcon className={`${styles.userIcon} ${styles.userIcon3}`} size={size} left={2 * size / 1.4} img={imgs[2] ? imgs[2] : ''} />
|
||||
<div className={`${styles.userIcon} ${styles.userIcon1}`}>
|
||||
<Icon icon={EIcons.MedalFirst}/>
|
||||
</div>
|
||||
<div className={`${styles.userIcon} ${styles.userIcon2}`}>
|
||||
<Icon icon={EIcons.MedalSecond} />
|
||||
</div>
|
||||
<div className={`${styles.userIcon} ${styles.userIcon3}`}>
|
||||
<Icon icon={EIcons.MedalThird} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -3,11 +3,14 @@
|
|||
}
|
||||
|
||||
.userIcon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
border-radius: 50%;
|
||||
background-color: var(--grey6C);
|
||||
border: 1px solid var(--grey12);
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.userIcon1 {
|
||||
|
@ -17,8 +20,10 @@
|
|||
|
||||
.userIcon2 {
|
||||
z-index: 2;
|
||||
left: 14px;
|
||||
}
|
||||
|
||||
.userIcon3 {
|
||||
z-index: 1;
|
||||
left: 28px;
|
||||
}
|
|
@ -10,9 +10,10 @@ interface IModalWindow {
|
|||
removeBtn ?: boolean,
|
||||
closeAnimOut?: boolean,
|
||||
setCloseAnimOut(a: boolean): void,
|
||||
isReload?: boolean,
|
||||
}
|
||||
|
||||
export function ModalWindow({ modalBlock, setClose, removeBtn, closeAnimOut, setCloseAnimOut }: IModalWindow) {
|
||||
export function ModalWindow({ modalBlock, setClose, removeBtn, closeAnimOut, setCloseAnimOut, isReload=false }: IModalWindow) {
|
||||
const node = document.querySelector('#modal_root');
|
||||
const [closeAnim, setCloseAnim] = useState(false);
|
||||
const html = document.querySelector('html');
|
||||
|
@ -34,6 +35,9 @@ export function ModalWindow({ modalBlock, setClose, removeBtn, closeAnimOut, set
|
|||
const timer = setTimeout(() => {
|
||||
setClose(true);
|
||||
clearTimeout(timer);
|
||||
if(isReload) {
|
||||
window.location.reload();
|
||||
}
|
||||
}, 400);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,39 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import styles from './auctionpage.module.css';
|
||||
import { ETextStyles } from '../../texts';
|
||||
import { AuctionCard } from '../../Auction/AuctionCard';
|
||||
import { useAuctionData } from '../../hooks/useAuctionData';
|
||||
import { Spinner } from '../../Elements/Spinner';
|
||||
import { ErrorPage } from '../ErrorPage';
|
||||
|
||||
export function AuctionPage() {
|
||||
const imgs = ['https://cdn.dribbble.com/userupload/11863775/file/original-6009708366fadd352f61fbaf0db5acee.png?resize=1200x853',
|
||||
'https://cdn.dribbble.com/userupload/10040892/file/original-850d482568c1f1c870b7066113903bd2.png?resize=1200x900',
|
||||
'https://cdn.dribbble.com/users/9735273/screenshots/19338580/media/6657322ea7990bd504427ed1b171be3d.png?resize=1200x900']
|
||||
const { dataAuction, loadingAuction, errorAuction } = useAuctionData();
|
||||
const [auctionBlock, setAuctionBlock] = useState( <div></div> );
|
||||
|
||||
useEffect(() => {
|
||||
if(dataAuction.length != 0) {
|
||||
const newBlock = dataAuction.map(item => {
|
||||
if (item.productName && item.productCover && item.initialCost && item.time && item.winnersNumber && item.commission && item.id && item.isLead != undefined && item.myBet != undefined)
|
||||
return <AuctionCard className={styles.card} auctionId={item.id} key={`${item.id}${JSON.stringify(dataAuction)}`} name={item.productName} imgs={[item.productCover]} users={item.winnersNumber} prevBet={item.initialCost} myBetInit={item.myBet} time={item.time} isLead={item.isLead} commission={item.commission}/>
|
||||
});
|
||||
|
||||
//@ts-ignore
|
||||
setAuctionBlock(newBlock);
|
||||
}
|
||||
}, [dataAuction]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{loadingAuction && <div className={styles.spinnerContainer}><Spinner color='#FFFFFF' size='40px' thickness='6px' className={styles.spinner} /></div>}
|
||||
{!loadingAuction && <div>
|
||||
{errorAuction ? <ErrorPage fullScreen={true} title='Возникла ошибка загрузки аукционов' text='Перезагрузите страницу или попробуйте позже' detail={errorAuction} /> :
|
||||
<div>
|
||||
<h1 className={styles.title} style={ETextStyles.RwSb26100}> <span>Соревнуйся за товары</span> на аукционе!</h1>
|
||||
<AuctionCard name='iPhone 15 Pro Max, 256gb, Natural Titanium' imgs={imgs} minBet='200' users={23} prevBet='290' myBetInit='0' time={86400} isLead={false}/>
|
||||
{auctionBlock}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -5,3 +5,15 @@
|
|||
.title span {
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.spinnerContainer {
|
||||
display: flex;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.card {
|
||||
margin-bottom: 24px;
|
||||
}
|
|
@ -11,6 +11,8 @@ import { useWindowSize } from 'usehooks-ts';
|
|||
import { useAppSelector } from '../../hooks/useAppSelector';
|
||||
import { ModalWindow } from '../../ModalWindow';
|
||||
import { DevPopup } from '../../Elements/DevPopup';
|
||||
import { AuctionMainPopups } from '../../Auction/AuctionMainPopups';
|
||||
import { useAuctionData } from '../../hooks/useAuctionData';
|
||||
|
||||
interface IClickerPageInterface {
|
||||
name: string,
|
||||
|
@ -33,6 +35,17 @@ export function ClickerPage({ name, points, img, energy }: IClickerPageInterface
|
|||
const [clickTime, setClickTime] = useState(0);
|
||||
const [closeAutoClick, setCloseAutoClick] = useState(true);
|
||||
const [sameCoords, setSameCoords] = useState(false);
|
||||
const [sameInterval, setSameInterval] = useState(false);
|
||||
useAuctionData();
|
||||
|
||||
useEffect(() => {
|
||||
const html = document.querySelector('html');
|
||||
|
||||
if(html) {
|
||||
html.style.overflow = 'scroll';
|
||||
}
|
||||
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setMult(savedMult);
|
||||
|
@ -57,13 +70,13 @@ export function ClickerPage({ name, points, img, energy }: IClickerPageInterface
|
|||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.records}>
|
||||
{!closePoints && <PointsZoom sameCoords={sameCoords} setSameCoords={setSameCoords} setCloseAutoClick={setCloseAutoClick} setClickTime={setClickTime} clickTime={clickTime} setMult={setMult} setEnergy={setInitEnergy} setCloseError={setCloseError} setCoins={setCoins} points={coins} setClosePointsAnim={setClosePointsAnim} setClose={setClosePoints} className={styles.pointsAnim} closePointsAnim={closePointsAnim}/>}
|
||||
{!closePoints && <PointsZoom sameInterval={sameInterval} setSameInterval={setSameInterval} sameCoords={sameCoords} setSameCoords={setSameCoords} setCloseAutoClick={setCloseAutoClick} setClickTime={setClickTime} clickTime={clickTime} 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}/>
|
||||
<h1 style={ETextStyles.RwSb24100} className={styles.title}>Мои рекорды</h1>
|
||||
<SectionsBlock mult={mult}/>
|
||||
</div>
|
||||
<div className={styles.clicker} style={{height: `${height > 670 && 'calc(100vh - 355px)'}`}}>
|
||||
<ClickerBtn closeAutoClick={closeAutoClick} sameCoords={sameCoords} setSameCoords={setSameCoords} clickTime={clickTime} setClickTime={setClickTime} setEnergy={setInitEnergy} coins={coins} setCoins={setCoins} energy={initEnergy} setMult={setMult}/>
|
||||
<ClickerBtn setSameInterval={setSameInterval} closeAutoClick={closeAutoClick} sameCoords={sameCoords} setSameCoords={setSameCoords} clickTime={clickTime} setClickTime={setClickTime} setEnergy={setInitEnergy} coins={coins} setCoins={setCoins} energy={initEnergy} setMult={setMult}/>
|
||||
</div>
|
||||
<ClickerFooter />
|
||||
{styleIndex != 0 && <div>
|
||||
|
@ -75,6 +88,7 @@ export function ClickerPage({ name, points, img, energy }: IClickerPageInterface
|
|||
{!closeAutoClick && <ModalWindow removeBtn={true} setCloseAnimOut={setAnimClose} closeAnimOut={animClose} setClose={setCloseAutoClick} modalBlock={
|
||||
<DevPopup setClose={setAnimClose} title='Кажется, вы используете автокликер...' text='Ваши клики не отправлены. Давайте играть честно.' img='assets/police.gif'/>
|
||||
} />}
|
||||
<AuctionMainPopups/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
18
frontend/src/shared/hooks/useAuctionData.ts
Normal file
18
frontend/src/shared/hooks/useAuctionData.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import { useDispatch } from 'react-redux';
|
||||
import { useEffect } from 'react';
|
||||
import { useAppSelector } from './useAppSelector';
|
||||
import { IAuction, auctionRequestAsync } from '../../store/auction/actions';
|
||||
|
||||
export function useAuctionData() {
|
||||
const dataAuction = useAppSelector<Array<IAuction>>(state => state.auction.data);
|
||||
const loadingAuction = useAppSelector<boolean>(state => state.auction.loading);
|
||||
const errorAuction = useAppSelector<String>(state => state.auction.error);
|
||||
const token = useAppSelector<string>(state => state.token);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch<any>(auctionRequestAsync());
|
||||
}, [token]);
|
||||
|
||||
return { dataAuction, loadingAuction, errorAuction };
|
||||
}
|
245
frontend/src/store/auction/actions.ts
Normal file
245
frontend/src/store/auction/actions.ts
Normal file
|
@ -0,0 +1,245 @@
|
|||
import { Action, ActionCreator } from "redux";
|
||||
import { ThunkAction } from "redux-thunk";
|
||||
import { RootState } from "../reducer";
|
||||
import axios from "axios";
|
||||
import { updateMyAuctions } from "../me/actions";
|
||||
|
||||
export interface IAuction {
|
||||
id?: string,
|
||||
commission?: number,
|
||||
time?: number,
|
||||
initialCost?: string,
|
||||
productId?: string,
|
||||
productCover?: string,
|
||||
productName?: string,
|
||||
winnersNumber?: number,
|
||||
isLead?: boolean,
|
||||
myBet?: string,
|
||||
}
|
||||
|
||||
export const AUCTION_REQUEST = 'AUCTION_REQUEST';
|
||||
|
||||
export type AuctionRequestAction = {
|
||||
type: typeof AUCTION_REQUEST
|
||||
};
|
||||
|
||||
export const auctionRequest: ActionCreator<AuctionRequestAction> = () => ({
|
||||
type: AUCTION_REQUEST,
|
||||
});
|
||||
|
||||
export const AUCTION_REQUEST_SUCCESS = 'AUCTION_REQUEST_SUCCESS';
|
||||
|
||||
export type AuctionRequestSuccessAction = {
|
||||
type: typeof AUCTION_REQUEST_SUCCESS;
|
||||
data: Array<IAuction>;
|
||||
};
|
||||
|
||||
export const auctionRequestSuccess: ActionCreator<AuctionRequestSuccessAction> = (data: Array<IAuction>) => ({
|
||||
type: AUCTION_REQUEST_SUCCESS,
|
||||
data
|
||||
});
|
||||
|
||||
export const AUCTION_REQUEST_ERROR = 'AUCTION_REQUEST_ERROR';
|
||||
|
||||
export type AuctionRequestErrorAction = {
|
||||
type: typeof AUCTION_REQUEST_ERROR;
|
||||
error: String;
|
||||
};
|
||||
|
||||
export const auctionRequestError: ActionCreator<AuctionRequestErrorAction> = (error: String) => ({
|
||||
type: AUCTION_REQUEST_ERROR,
|
||||
error
|
||||
});
|
||||
|
||||
export const auctionRequestAsync = (): ThunkAction<void, RootState, unknown, Action<string>> => (dispatch, getState) => {
|
||||
const URL = getState().url;
|
||||
const token = getState().token;
|
||||
const userTg = getState().userTg.id;
|
||||
|
||||
if (token) {
|
||||
axios.get(`${URL}/api/v1/auction/auction?is_active=true`,
|
||||
{
|
||||
headers: {
|
||||
"Authorization": `TelegramToken ${token}`
|
||||
}
|
||||
}
|
||||
).then(resp => {
|
||||
const data = resp.data.results;
|
||||
|
||||
axios.get(`${URL}/api/v1/auction/bet?order_by=-value&is_winning=true`,
|
||||
{
|
||||
headers: {
|
||||
"Authorization": `TelegramToken ${token}`
|
||||
}
|
||||
}
|
||||
).then(resp2 => {
|
||||
const dataBet = resp2.data.results;
|
||||
const auctionResults: Array<IAuction> = [];
|
||||
|
||||
axios.get(`${URL}/api/v1/auction/bet?user=${userTg}&order_by=-value`,
|
||||
{
|
||||
headers: {
|
||||
"Authorization": `TelegramToken ${token}`
|
||||
}
|
||||
}
|
||||
).then(resp3 => {
|
||||
const userData = resp3.data.results;
|
||||
const topAuctions = [];
|
||||
const loseAuctions = [];
|
||||
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const nowDate = new Date();
|
||||
const endDate = new Date(data[i].end_time);
|
||||
const time = Math.ceil(Math.abs(endDate.getTime() - nowDate.getTime()) / 1000);
|
||||
let maxBet = Number(data[i].initial_cost);
|
||||
let isLead = false;
|
||||
let myBet = 0;
|
||||
|
||||
if (dataBet.length != 0) {
|
||||
for (let k = 0; k < dataBet.length; k++) {
|
||||
if (dataBet[k].auction === data[i].id) {
|
||||
if (Number(dataBet[k].value) > maxBet) {
|
||||
maxBet = Number(dataBet[k].value);
|
||||
}
|
||||
|
||||
if (Number(dataBet[k].user.tg_id) === Number(userTg)) {
|
||||
|
||||
isLead = true;
|
||||
|
||||
const topItem = {
|
||||
name: data[i].product.name,
|
||||
img: data[i].product.cover,
|
||||
bet: dataBet[k].value
|
||||
}
|
||||
|
||||
topAuctions.push(topItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (userData.length != 0) {
|
||||
for (let z = 0; z < userData.length; z++) {
|
||||
if (userData[z].auction === data[i].id) {
|
||||
if (Number(userData[z].value) > myBet) {
|
||||
myBet = Number(userData[z].value);
|
||||
|
||||
if(!isLead) {
|
||||
const loseItem = {
|
||||
name: data[i].product.name,
|
||||
img: data[i].product.cover,
|
||||
bet: userData[z].value
|
||||
}
|
||||
|
||||
loseAuctions.push(loseItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const item = {
|
||||
id: data[i].id,
|
||||
initialCost: maxBet.toString(),
|
||||
commission: Number(data[i].commission) * 100,
|
||||
time: time,
|
||||
winnersNumber: data[i].quantity,
|
||||
productId: data[i].product.id,
|
||||
productName: data[i].product.name,
|
||||
productCover: data[i].product.cover,
|
||||
isLead: isLead,
|
||||
myBet: myBet.toString()
|
||||
};
|
||||
|
||||
auctionResults.push(item);
|
||||
}
|
||||
|
||||
dispatch(updateMyAuctions(topAuctions, 'top'));
|
||||
dispatch(updateMyAuctions(loseAuctions, 'lose'));
|
||||
|
||||
dispatch(auctionRequestSuccess(auctionResults));
|
||||
})
|
||||
|
||||
}).catch(err => {
|
||||
console.log(err);
|
||||
if (err.response.data.detail) {
|
||||
dispatch(auctionRequestError(String(err.response.data.detail)));
|
||||
} else {
|
||||
dispatch(auctionRequestError(String(err)));
|
||||
}
|
||||
})
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
if (err.response.data.detail) {
|
||||
dispatch(auctionRequestError(String(err.response.data.detail)));
|
||||
} else {
|
||||
dispatch(auctionRequestError(String(err)));
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export const updateAuction = (id: string): ThunkAction<void, RootState, unknown, Action<string>> => (dispatch, getState) => {
|
||||
const auctionData = getState().auction.data;
|
||||
const URL = getState().url;
|
||||
const token = getState().token;
|
||||
const userTg = getState().userTg.id;
|
||||
let newData = auctionData;
|
||||
|
||||
axios.get(`${URL}/api/v1/auction/bet?order_by=-value&is_winning=true&auction=${id}`,
|
||||
{
|
||||
headers: {
|
||||
"Authorization": `TelegramToken ${token}`
|
||||
}
|
||||
}
|
||||
).then(resp => {
|
||||
const dataBet = resp.data.results;
|
||||
let maxBet = 0;
|
||||
let isLead = false;
|
||||
|
||||
if (dataBet.length != 0) {
|
||||
for (let i = 0; i < dataBet.length; i++) {
|
||||
if (Number(dataBet[i].value) > maxBet) {
|
||||
maxBet = Number(dataBet[i].value);
|
||||
}
|
||||
|
||||
if (Number(dataBet[i].user.tg_id) === Number(userTg)) {
|
||||
isLead = true;
|
||||
newData[i].isLead = isLead;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
axios.get(`${URL}/api/v1/auction/bet?auction=${id}&user=${userTg}&order_by=-value`,
|
||||
{
|
||||
headers: {
|
||||
"Authorization": `TelegramToken ${token}`
|
||||
}
|
||||
}
|
||||
).then(resp2 => {
|
||||
const data = resp2.data.results;
|
||||
let myBet = 0;
|
||||
|
||||
if (data.length != 0) {
|
||||
myBet = Number(dataBet[0].value);
|
||||
}
|
||||
|
||||
//обновляем данные
|
||||
for (let i = 0; i < newData.length; i++) {
|
||||
if (newData[i].id === id) {
|
||||
if (myBet != 0) {
|
||||
newData[i].myBet = myBet.toString();
|
||||
}
|
||||
|
||||
if (maxBet != 0) {
|
||||
newData[i].initialCost = maxBet.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
dispatch(auctionRequestSuccess(newData));
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
36
frontend/src/store/auction/reducer.ts
Normal file
36
frontend/src/store/auction/reducer.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
import { Reducer } from 'react';
|
||||
import { AUCTION_REQUEST, AUCTION_REQUEST_ERROR, AUCTION_REQUEST_SUCCESS, AuctionRequestAction, AuctionRequestErrorAction, AuctionRequestSuccessAction, IAuction } from './actions';
|
||||
|
||||
export type AuctionState = {
|
||||
loading: boolean,
|
||||
error: String,
|
||||
data: Array<IAuction>
|
||||
}
|
||||
|
||||
type AuctionAction = AuctionRequestAction | AuctionRequestSuccessAction | AuctionRequestErrorAction;
|
||||
|
||||
export const auctionReducer: Reducer<AuctionState, AuctionAction> = (state, action) => {
|
||||
switch (action.type) {
|
||||
case AUCTION_REQUEST:
|
||||
return {
|
||||
...state,
|
||||
loading: true,
|
||||
error: ''
|
||||
};
|
||||
case AUCTION_REQUEST_ERROR:
|
||||
return {
|
||||
...state,
|
||||
error: action.error,
|
||||
loading: false,
|
||||
};
|
||||
case AUCTION_REQUEST_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
data: action.data,
|
||||
loading: false,
|
||||
error: ''
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
|
@ -5,6 +5,12 @@ import axios from "axios";
|
|||
import { saveMult } from "../mult";
|
||||
import { saveToken } from "../token";
|
||||
|
||||
export interface IAuctionItem {
|
||||
name: string,
|
||||
img: string,
|
||||
bet: string
|
||||
}
|
||||
|
||||
export interface IUserData {
|
||||
tgId?: number;
|
||||
username?: string;
|
||||
|
@ -14,7 +20,9 @@ export interface IUserData {
|
|||
energy?: string;
|
||||
referralStorage?: string;
|
||||
maxStorage: number;
|
||||
rank ?: number
|
||||
rank ?: number,
|
||||
loseAuctions?: Array<IAuctionItem>,
|
||||
topAuctions?: Array<IAuctionItem>,
|
||||
}
|
||||
|
||||
export const ME_REQUEST = 'ME_REQUEST';
|
||||
|
@ -117,6 +125,8 @@ export const meRequestAsync = (): ThunkAction<void, RootState, unknown, Action<s
|
|||
const savedToken = sessionStorage.getItem('tk');
|
||||
if (savedToken) {
|
||||
if (savedToken != encodeToken) {
|
||||
sessionStorage.setItem('shT', 't');
|
||||
sessionStorage.setItem('shL', 't');
|
||||
sessionStorage.setItem('tk', encodeToken);
|
||||
firstClick(token);
|
||||
const energyCode = btoa(energy.toString());
|
||||
|
@ -170,7 +180,7 @@ export const meRequestAsync = (): ThunkAction<void, RootState, unknown, Action<s
|
|||
})
|
||||
}
|
||||
/*if (tgId && Url && !meData.username) {
|
||||
axios.get(`${Url}/api/internal/users/get-token/123456`, {
|
||||
axios.get(`${Url}/api/internal/users/get-token/${tgId}`, {
|
||||
headers: {
|
||||
"Content-type": "application/json"
|
||||
}
|
||||
|
@ -211,6 +221,8 @@ export const meRequestAsync = (): ThunkAction<void, RootState, unknown, Action<s
|
|||
const savedToken = sessionStorage.getItem('tk');
|
||||
if (savedToken) {
|
||||
if (savedToken != encodeToken) {
|
||||
sessionStorage.setItem('shT', 't');
|
||||
sessionStorage.setItem('shL', 't');
|
||||
sessionStorage.setItem('tk', encodeToken);
|
||||
firstClick(token);
|
||||
const energyCode = btoa(energy.toString());
|
||||
|
@ -295,6 +307,7 @@ export const updatePointsRequestAsync = (): ThunkAction<void, RootState, unknown
|
|||
const newData = meData;
|
||||
newData.points = points;
|
||||
dispatch(meRequestSuccess(newData));
|
||||
dispatch(loadNewRank());
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
dispatch(meRequestError(String(err)));
|
||||
|
@ -320,3 +333,43 @@ export const updateRank = (rank: number): ThunkAction<void, RootState, unknown,
|
|||
newData.rank = rank;
|
||||
dispatch(meRequestSuccess(newData));
|
||||
}
|
||||
|
||||
export const loadNewRank = (): ThunkAction<void, RootState, unknown, Action<string>> => (dispatch, getState) => {
|
||||
const token = getState().token;
|
||||
const URL = getState().url;
|
||||
const userTg = getState().userTg.id;
|
||||
|
||||
if(token) {
|
||||
axios.get(`${URL}/api/v1/users/rank/neighbours?limit=1`,
|
||||
{
|
||||
headers: {
|
||||
"Authorization": `TelegramToken ${token}`
|
||||
}
|
||||
}
|
||||
).then(resp => {
|
||||
const data = resp.data;
|
||||
if(data.length != 0) {
|
||||
|
||||
for(let i = 0; i<data.length; i++) {
|
||||
if (Number(data[i].tg_id) === Number(userTg)) {
|
||||
dispatch<any>(updateRank(Number(data[i].rank)))
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export const updateMyAuctions = (data: Array<IAuctionItem>, type: string): ThunkAction<void, RootState, unknown, Action<string>> => (dispatch, getState) => {
|
||||
const meData = getState().me.data;
|
||||
let newData = meData;
|
||||
|
||||
if(type === 'top') {
|
||||
newData.topAuctions = data;
|
||||
} else {
|
||||
newData.loseAuctions = data;
|
||||
}
|
||||
|
||||
dispatch(meRequestSuccess(newData));
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ import { RankState, friendsReducer } from './friends/reducer';
|
|||
import { FRIENDS_REQUEST, FRIENDS_REQUEST_ERROR, FRIENDS_REQUEST_SUCCESS } from './friends/actions';
|
||||
import { RANK_REQUEST, RANK_REQUEST_ERROR, RANK_REQUEST_SUCCESS } from './rank/actions';
|
||||
import { rankReducer } from './rank/reducer';
|
||||
import { AuctionState, auctionReducer } from './auction/reducer';
|
||||
import { AUCTION_REQUEST, AUCTION_REQUEST_ERROR, AUCTION_REQUEST_SUCCESS } from './auction/actions';
|
||||
|
||||
export type RootState = {
|
||||
url: string,
|
||||
|
@ -22,6 +24,7 @@ export type RootState = {
|
|||
mult: number,
|
||||
friends: RankState,
|
||||
rank: RankState,
|
||||
auction: AuctionState
|
||||
};
|
||||
|
||||
//'http://127.0.0.1:8000'
|
||||
|
@ -55,6 +58,11 @@ const initialState: RootState = {
|
|||
error: '',
|
||||
data: []
|
||||
},
|
||||
auction: {
|
||||
loading: false,
|
||||
error: '',
|
||||
data: []
|
||||
},
|
||||
referral: '',
|
||||
mult: 1,
|
||||
};
|
||||
|
@ -108,6 +116,13 @@ export const rootReducer: Reducer<RootState> = (state = initialState, action) =>
|
|||
...state,
|
||||
rank: rankReducer(state.rank, action)
|
||||
};
|
||||
case AUCTION_REQUEST:
|
||||
case AUCTION_REQUEST_SUCCESS:
|
||||
case AUCTION_REQUEST_ERROR:
|
||||
return {
|
||||
...state,
|
||||
auction: auctionReducer(state.auction, action)
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ export const isWhiteList = () => {
|
|||
//123456,
|
||||
const whiteList = [
|
||||
342495217, 6374536117, 322861155, 5219438370, 193428034, 402449803,
|
||||
406350282
|
||||
406350282, 1083462027
|
||||
];
|
||||
|
||||
const userId = Number(getTgUserId());
|
||||
|
|
Loading…
Reference in New Issue
Block a user