State in redux changes but it's not updating in the component - reactjs

My redux store updates perfectly
after sorting
before sorting
But the props in my component don't update even when the store has updated and so the child components still show the old values. I'm sorting my channels according to the timestamp. The sorting function updates the redux store but it still renders the non-sorted data.
the output it should be sorted but it remains the same(unsorted)
This is my component code
export const RoomItem = (props) => {
const [roomLiveStatus, setRoomLiveStatus] = useState(false);
const compareTimestamp = (t1 = 0, t2 = 0) => {
return (t1.lastMessage && t2.lastMessage) && t2.lastMessage.timestamp - t1.lastMessage.timestamp
}
const getRoomData = () => {
const { roomData, workspace } = props;
const { workspaceId } = workspace
const workspaceIdLowerCase = workspaceId.toLowerCase()
const { roomId } = roomData;
const roomIdLowerCase = roomId.toLowerCase()
firebase
.firestore()
.collection(`sessions/${workspaceIdLowerCase}/rooms`)
.doc(`${roomIdLowerCase}`)
.onSnapshot(doc => {
if (doc.exists) {
// console.log("LIVE Sessions doc: ", doc.data())
const { currentSession } = doc.data()
if (currentSession !== "") {
setRoomLiveStatus(true)
} else {
setRoomLiveStatus(false)
}
}
})
}
useEffect(() => {
getRoomData();
},[])
useEffect(() => {
// do something
getRoomData();
// console.log(props,"props of roomitem")
},[props.sortType])
const strip = (value) => {
const { user, content } = value
let name = user.name;
let firstName = name.trim().split(" ")[0]
if (value.type === 0) {
if ( (firstName.length + content.length) > 32 ) {
let completeContent = `${firstName}: ${content}`
return `${completeContent.slice(0, 32)}...`
} else {
return `${firstName}: ${content}`
}
} else if (value.type === 1) {
return <span>{firstName}: <FontAwesomeIcon icon={faCalendarAlt} className="text-theme" /> Schedule</span>
} else if (value.type === 2) {
return (
<span>{firstName}: <FontAwesomeIcon icon={faClipboard} className="text-theme" />Files</span>
);
} else if (value.type === 3) {
return <span>{firstName}: <FontAwesomeIcon icon={faPoll} className="text-theme" /> Poll</span>
} else if (value.type === 4) {
return <span>{firstName}: <FontAwesomeIcon icon={faTasks} className="text-theme" /> Quiz</span>
} else if (value.type === 6) {
if ( (firstName.length + content.length) > 32) {
let len = 32 - firstName.length;
return <span>{firstName}: <FontAwesomeIcon icon={faImage} /> {content.length > len ? content.slice(0, len) + '…' : content}</span>
} else {
return <span>{firstName}: <FontAwesomeIcon icon={faImage} /> Photo</span>
}
} else if (value.type === 7) {
if ( (firstName.length + content.length) > 32) {
let len = 32 - firstName.length;
return <span>{firstName}: <FileIcon message={value} /> {content.length > len ? content.slice(0, len) + '…' : content}</span>
} else {
return <span>{firstName}: <FileIcon message={value} /> {value.metaData && value.metaData.name}</span>
}
} else if (value.type === 8) {
return <span>{content.length > 36 ? `${content.slice(0, 36)}...` : content}</span>
} else if (value.type === 9) {
return <span>{content.length > 36 ? `${content.slice(0, 36)}...` : content}</span>
} else {
return value.type
}
}
const {
key,
currentChannel,
workspaceData,
workspace,
setCurrentChannel,
setCurrentWorkspace,
setParticipants,
resetData
} = props;
const roomData = props.roomData;
const { roomId } = roomData;
return(
<li
className={currentChannel && (roomData.roomId === currentChannel.roomId)
? "active rounded-lg py-1 m-1 bg-card-theme shadow-sm text-theme"
: "rounded-lg py-1 m-1 bg-card-theme shadow-sm text-theme"}
key={key}
onClick={() => {
setCurrentChannel({ ...roomData, roomId })
setCurrentWorkspace({ ...workspaceData, ...workspace })
setParticipants(workspace.workspaceId, roomId)
resetData()
// setLeftPanel(!this.props.displayLeftPanel);
}}
name={roomData.roomName}
active={currentChannel && (roomData.roomId === currentChannel.roomId)}
>
<div className="d-flex align-items-center p-2 w-100">
<div className={roomLiveStatus ? "liveroom" : ""}>
<img
className={roomLiveStatus ? "mr-2 rounded-circle profile-image" : "mr-2 rounded-circle"}
src={roomData.roomPic}
style={{ height: 45, width: 45 }} />
</div>
<div className="flex-grow-1">
<div className="d-flex align-items-center">
{(roomData.roomType === 1)
&& <FontAwesomeIcon
icon={faLock}
className="text-success mr-2"
size="xs" />}
<p className="mb-0 text-theme">{roomData.roomName}</p>
</div>
{roomData.lastMessage
&& <small className="text-theme text-theme-lighter">
<span>{strip(roomData.lastMessage)}</span>
</small>}
</div>
<div className="text-right align-self-start">
{/* <FontAwesomeIcon
icon={faThumbtack}
style={isPinned ? { fontSize: 12, transform: "rotate(45deg)" } : { fontSize: 12 }}
className={isPinned ? "text-theme" : "text-secondary"} /> */}
<p
className="mb-0 text-theme small text-theme-lighter"
style={{ whiteSpace: "nowrap" }}
>
{roomData.lastMessage
&& timeFromNow(roomData.lastMessage.timestamp)}
</p>
{/* Messages Notification */}
{/* <span className="text-white bg-primary smaller font-weight-bold" style={{ whiteSpace: "nowrap", borderRadius: "2px", padding: "3px 3px 3px 3px" }}>
99+</span> */}
</div>
</div>
</li>
)
}
const WorkspaceListElement = (props) => {
const [workspaceData, setWorkspaceData] = useState({});
const [loadingWorkspaceData, setLoadingWorkspaceData] = useState(true);
const [roomsDataArray, setRoomsDataArray] = useState([]);
const [sortingCount, setSortingCount] = useState(0);
const getWorkspaceData = async () => {
const { workspace } = props;
let docRef = await firebase.firestore().collection(`workspaces`).doc(`${workspace.workspaceId}`)
let workspace_data = await docRef.get()
.then(function (doc) {
if (doc.exists) {
// console.log("Document data workspace:", doc.data());
const workspaceData = doc.data()
return workspaceData;
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
})
.catch(function (error) {
console.log("Error getting document:", error);
})
setWorkspaceData(workspace_data);
setLoadingWorkspaceData(false);
}
const getAllRoomsData = () => {
const { workspace, roomsVisible, setChannels } = props
let roomsArray = []
let roomsDataPromises = []
let roomsDataArray = []
getWorkspaceData()
roomsArray = workspace[roomsVisible] && Object.values(workspace[roomsVisible]).map((room, key) => (
room.roomId
))
// console.log(`roomsArray ${JSON.stringify(roomsArray)}`)
roomsDataPromises = roomsArray.map((roomId, key) => firebase.firestore().collection(`workspaces/${workspace.workspaceId}/rooms`).doc(`${roomId}`).get())
Promise.all(roomsDataPromises).then(values => {
roomsDataArray = values.map(value => {
return { ...value.data(), roomId: value.id }
})
setChannels(roomsDataArray)
})
}
const {
workspace,
_handleAddRoom,
_handleOpenWorkspaceDetails,
roomsVisible,
currentChannel,
allChannels,
searchTerm,
sortType
} = props;
const regex = new RegExp(searchTerm, "gi");
useEffect(() => {
getAllRoomsData()
},[])
useEffect(() => {
getAllRoomsData()
},[props.roomsVisible, props.workspace[props.roomsVisible]])
useEffect(() => {
getWorkspaceData()
},[props.workspace])
useEffect(() => {
console.log('sorttype changed')
switchSort(allChannels, sortType)
setSortingCount((prev) => prev + 1)
},[sortType])
const compareTimestamp = (t1 = null, t2 = null) => {
if (t1 && t2) {return t2.timestamp - t1.timestamp}
if (t1 && t2 == null) {return -1}
if (t2 && t1 == null) {return 1}
return 0
}
const compareTimestampLodashLatestFirst = (allChannels) => {
const sorted = _.orderBy(allChannels, (channel) => {
})
props.setChannels(sorted);
return (sorted);
}
const compareAlphabetLodashAtoZ = (allChannels) => {
const sorted = _.sortBy(allChannels, (channel) => channel.roomName)
// console.log('atoz')
props.setChannels(sorted)
return (sorted);
}
const compareAlphabetLodashZtoA = (allChannels) => {
const sorted = _.sortBy(allChannels, (channel) => channel.roomName)
// console.log('ztoa')
props.setChannels(sorted.reverse())
return (sorted.reverse());
}
const switchSort = (allChannels, sortType) => {
// console.log(allChannels,"allChannels")
switch (sortType) {
case 0:
return compareTimestampLodashLatestFirst(allChannels)
case 1:
return compareAlphabetLodashAtoZ(allChannels)
case 2:
return compareAlphabetLodashZtoA(allChannels)
case 3:
return compareTimestampLodashLatestFirst(allChannels)
default:
return compareTimestampLodashLatestFirst(allChannels)
}
}
// console.log(allChannels,"before return")
return(
<>
{
searchTerm && searchTerm.length > 0
? allChannels
&& allChannels
.filter(item => {
return item.roomName.match(regex) || (item.lastMessage && item.lastMessage.content && item.lastMessage.content.match(regex))
})
.sort((a, b) => switchSort(a, b, sortType))
.map((room, key) => (
<RoomItem
roomData={room}
key={key}
index={key}
currentChannel={currentChannel}
workspace={workspace}
workspaceData={workspaceData}
allChannels={allChannels}
{...props}
/>
))
: allChannels &&
allChannels.map((room, key) => {
return(
<RoomItem
roomData={room}
key={room.roomName + key}
index={key}
currentChannel={currentChannel}
workspace={workspace}
workspaceData={workspaceData}
{...props}
/>
)
})
}
</>
)
}
const mapStateToProps = state => ({
roomsVisible: state.workspace.roomsVisible,
currentChannel: state.channel.currentChannel,
allChannels: state.channel.allChannels,
platform: state.channel.platform
})
export default connect(mapStateToProps, {
setChannels,
setCurrentChannel,
setCurrentWorkspace,
setParticipants,
resetData
})(WorkspaceListElement);
Edit: I fixed it by using lodash cloneDeep. If anyone is stuck in a similar situation refer to this react-redux update item in array doesn't re-render

Related

Getting a value from input using onChange before it moves to the next input

I have created a Wordle game, I am trying to get the values from the inputs by line. Despite many attempts, a value is received only after I enter the next letter in the next input and an alert message pops up according to the new letter from the beginning of the next line appears.
import React, { ChangeEvent, useEffect,useRef, useState } from "react";
interface Props {
word: string;
numberOfLines: number;
numberOfInputs: number;
}
const Wordle = ({ word, numberOfLines, numberOfInputs }: Props) => {
const [inputs, setInputs] = useState<string[][]>(
Array(numberOfLines)
.fill(null)
.map(() => Array(numberOfInputs).fill(""))
);
const fullWord = useRef("");
const [currentRow, setCurrentRow] = useState(0);
const [currentCol, setCurrentCol] = useState(0);
const [color, setColor] = useState<string[][]>(
Array(numberOfLines)
.fill(null)
.map(() => Array(numberOfInputs).fill("white"))
);
const handleChange = (
e: ChangeEvent<HTMLInputElement>,
row: number,
col: number
) => {
const updatedInputs = inputs.map((inputRow, i) => {
if (i === row) {
return inputRow.map((input, j) => (j === col ? e.target.value : input));
}
return inputRow;
});
setInputs(updatedInputs);
if (col === numberOfInputs - 1) {
setCurrentRow(row + 1);
setCurrentCol(0);
} else {
setCurrentRow(row);
setCurrentCol(col+1);
}
const updatedColor = color.map((colorRow, i) => {
if (i === row) {
return colorRow.map((color, j) => {
if (j === col) {
if (word.includes(e.target.value)) {
if (word[j] === e.target.value) {
return "green";
}
return "brown";
}
return "white";
}
return color;
});
}
return colorRow;
});
setColor(updatedColor);
if(fullWord.current.length < word.length)
{fullWord.current = fullWord.current + e.target.value;
document
.getElementsByTagName("input")[row * numberOfInputs + col + 1].focus();
}
else if (fullWord.current.length === word.length) {
if (fullWord.current == word) {
alert("Success!");
fullWord.current="";
document
.getElementsByTagName("input")[row * numberOfInputs + col].focus();
} else {
fullWord.current="";
alert("Fail!");
}
}
}
return (
<div>
{inputs.map((inputRow, i) => (
<div key={i} className="word">
{inputRow.map((input, j) => (
<input
key={j}
type="text"
value={input}
maxLength={1}
onChange={(e) => handleChange(e, i, j)}
style={{ backgroundColor: color[i][j] }}
/>
))}
</div>
))}
{/* <Keyboard onClick={handleClick} /> */}
</div>
);
};
export default Wordle;
I want to get the value before the focus moves to the next input.
Thanks

function is being called but I dont know why

can someone tell me why in the world the drawCard() function runs 4 times as it should and then 52 more times the deck is 52 items long it must be related
but this
const initCard = ()=>{return deck.map((card,index)=>{return index<4 && drawCard(index%2===0?'player':'dealer')})}
so I don't know why does it happen
here is the full component
import Box from '#mui/material/Box';
import { useEffect, useRef, useState } from 'react';
import Card from '../components/Card'
import {styles} from '../visuals/Styles'
import { drawCardAnimation } from '../visuals/Animations'
function Gamepage() {
const [deck, setDeck] = useState([]);
/*let dealerHand=[];
let playerHand=[];*/
const [dealerHand, setDealerHand] = useState([]);
const [playerHand, setPlayerHand] = useState([]);
const [screenState, setScreenState] = useState('placeBet')
const first = useRef(true) //in order to prevent the effect of react strict we use ref to keep alive the first var which tells us if the useEffect hasnt been executed yes
useEffect(()=>
{
if(first.current){
first.current =false;
getDeck();
}
},[]);
const getDeck = async () =>{
const res = await fetch('http://localhost:5000/deck/shuffled');
const data = await res.json();
setDeck(data);
}
const initCard = ()=>{return deck.map((card,index)=>{return index<4 && drawCard(index%2===0?'player':'dealer')})}
const countCards = (hand)=>{
let res=0;
return {"cardsCount":hand.map(({suit,number,imgPath})=>{ return number }).sort((a, b) => b-a).map((value)=>{
if(value ===1 && res+11 <= 21)
res +=11;
else
res+=value;
return res
})[hand.length-1], "isBusted": res<=21 ? false:true};
}
const isBlackJack = (hand)=>{
return hand.length === 2 && countCards(hand).cardsCount === 21
}
const isPlayerWon= ()=>{
isBlackJack(playerHand) && console.log("BLACK JACK !");
return isBlackJack(playerHand) || (!countCards(playerHand).isBusted && countCards(dealerHand).isBusted) || (countCards(playerHand).cardsCount>=countCards(dealerHand).cardsCount && !countCards(playerHand).isBusted)
}
const drawToDealer = ()=>{
while(countCards(dealerHand).cardsCount<17){
drawCard('dealer')}
}
const drawCard = (target) =>
{
console.log("drawn");
let index = dealerHand.length + playerHand.length;
if(deck[index]&& target==='dealer' && !dealerHand.includes(deck[index]))
{
//dealerHand.push(deck[index])
setDealerHand((prev)=>[...prev, deck[index]])
}
else if(deck[index]&& target==='player'&& !playerHand.includes(deck[index]))
{
//playerHand.push(deck[index]);
setPlayerHand((prev)=>[...prev, deck[index]])
}
return deck[index]&&
<Card
key={index}
stl={index===1?styles.firstDealerCard:styles.card}
cardImg={( target==='dealer'&&dealerHand.length===1)?'upsidedownCard':deck[index].imgPath}
animation={drawCardAnimation(target==='dealer'?dealerHand.length-1:playerHand.length-1,target)}/>;
}
return (
<div>
<Box sx={styles.box}>
{/*TODO find out why functions inside onClick does not work
and make the end game prompt on screen
*/}
<Card stl={styles.deck} cardImg={'upsidedownCard'} />
{
(screenState==='placeBet')?
<img src={require('../assets/btnPlaceBet.png')} alt='' style={styles.btnPlaceBet} onClick={()=>setScreenState('gameStart')} />
:initCard()
}
{
screenState==='gameStart' && <img src={require('../assets/btnHit.png')} alt='' style={styles.btnHit} onClick={()=>{ drawCard('player'); console.log(playerHand);}} />
}
{
screenState==='gameStart' && <img src={require('../assets/btnStand.png')} alt='' style={styles.btnStand} onClick={()=>{ setScreenState('dilearsTurn')}} />
}
{
screenState==='gameStart' && <img src={require('../assets/btnDouble.png')} alt='' style={styles.btnDouble} onClick={()=>{ console.log('money is doubled'); drawCard('player'); /*console.log(playerHand);*/;setScreenState('dilearsTurn')}} />
}
{
screenState==='dilearsTurn' && <Card stl={styles.revealedCard} cardImg={dealerHand[0].imgPath} />
}
{
screenState==='dilearsTurn' && drawToDealer()
}
{
screenState==='dilearsTurn' && console.log(dealerHand.length)
}
{
screenState==='dilearsTurn' &&console.log(isPlayerWon() ?
`player wins ${countCards(playerHand).cardsCount} and dealer ${countCards(dealerHand).cardsCount} ${countCards(dealerHand).isBusted ? 'dealer busted':''}`
:
`dealer wins ${countCards(dealerHand).cardsCount} and player ${countCards(playerHand).cardsCount} ${countCards(playerHand).isBusted ? 'player busted':''}`)
}
{screenState==='dilearsTurn' && setTimeout(()=>{
console.log('game ended');
setTimeout(()=>{
setScreenState('placeBet')
},2000);
},3000)}
</Box>
</div>
)
}
export default Gamepage

Keep random numbers consistent after state change in React

I'm making a Nextjs app, and on one page I create an array of numbers that is shuffled using a random number. The problem is that every time the state changes, the component gets rendered so the array gets re-shuffled. I need the original shuffle to stay consistent. Here's the relevant code:
export default function Game() {
const { query } = useRouter();
const [cardsFlipped, setCardsFlipped] = useState(
Array(query.tileNumber).fill(false)
);
let counter = query.tileNumber / 2;
let iconSet = [...Array(counter).keys()];
while (counter > 0) {
const index = Math.floor(Math.random() * iconSet.length);
tiles.push(iconSet.splice(index, 1));
counter--;
}
const tileOrder = tiles.concat(tiles).sort((a, b) => 0.5 - Math.random());
const handleFlip = (index) => {
if (cardsFlipped[index] === false) {
setCardsFlipped((prev) =>
prev.map((el, i) => {
if (i === index) {
return true;
}
return el;
})
);
setTimeout(() => {
setCardsFlipped((prev) =>
prev.map((el, i) => {
if (i === index) {
return false;
}
return el;
})
);
}, query.tileTransition * 1000);
}
};
let cards = tileOrder.map((e, i) => (
<ReactCardFlip
isFlipped={cardsFlipped[i]}
flipDirection="horizontal"
key={"card" + i + "-" + e}
>
<Card
iconSet={2}
index={50}
callback={() => {
handleFlip(i);
}}
/>
<Card iconSet={parseInt(query.icons)} index={e} callback={handleFlip} />
</ReactCardFlip>
));
return (<div>{cards}</div>);
}
I thought of converting it into a class, and having a constructor, but then I get an error that useRouter can't be used in classes.
You just need to wrap your logic in a useEffect, something like this:
export default function Test() {
const { query } = useRouter();
const [cardsFlipped, setCardsFlipped] = useState(
Array(query.tileNumber).fill(false)
);
const [tileOrder, setTileOrder] = useState([]);
useEffect(() => {
let counter = query.tileNumber / 2;
let iconSet = [...Array(counter).keys()];
while (counter > 0) {
const index = Math.floor(Math.random() * iconSet.length);
tiles.push(iconSet.splice(index, 1));
counter--;
}
setTileOrder(tiles.concat(tiles).sort((a, b) => 0.5 - Math.random()));
}, []);
const handleFlip = index => {
if (cardsFlipped[index] === false) {
setCardsFlipped(prev =>
prev.map((el, i) => {
if (i === index) {
return true;
}
return el;
})
);
setTimeout(() => {
setCardsFlipped(prev =>
prev.map((el, i) => {
if (i === index) {
return false;
}
return el;
})
);
}, query.tileTransition * 1000);
}
};
let cards = tileOrder.map((e, i) => (
<ReactCardFlip
isFlipped={cardsFlipped[i]}
flipDirection="horizontal"
key={'card' + i + '-' + e}
>
<Card
iconSet={2}
index={50}
callback={() => {
handleFlip(i);
}}
/>
<Card iconSet={parseInt(query.icons)} index={e} callback={handleFlip} />
</ReactCardFlip>
));
return <div>{cards}</div>;
}

Type error in react when accessing data from an object array

I am trying to access the resolution timestamp variable from regressions_test_summary however I am getting a type error saying cannot read property of 'resolution_map' undefined.
Variable I am trying to access:
Code from function:
export const getRegressionTestStatus = summary => {
if(summary.regression_test_summary.resolution_timestamp === null) return 'Unresolved'
else if(summary.unit_test_fails || summary.unit_test_errors) return 'Failed'
else if(!summary.unit_test_fails && !summary.unit_test_errors) return 'Success'
console.log('from summary', summary);
}
export const getLogIcon = (unitTest, size) => {
if(unitTest.result && typeof(unitTest.result[0]) === 'string') {
return <ErrorIcon className={`LogIcon${size} TestError`} />
}
else {
return <FiberManualRecordIcon
className={`LogIcon${size} ${!unitTest.result ? 'TestNA' : unitTest.result[0] ? 'TestPass' : 'TestFail'}`}
/>
}
}
regressiontestData:
const getIcon = (summary) => {
const status = getRegressionTestStatus(summary)
if(status === 'Unresolved') return <ScheduleIcon style={{color: 'var(--update-bg-color)'}} />
else if(status === 'Failed') return <CloseIcon style={{color: 'var(--reject-fg-color)'}} />
else if(status === 'Success') return <CheckIcon style={{color: 'var(--approve-bg-color)'}} />
console.log('summary', summary);
}
useEffect(() => {
async function onLoadRegressionTests() {
loading.setLoading(true)
const results = await verifiedGet(`get_regression_tests/${(currentPage - 1) * resPerPage}/${resPerPage}`, user.user)
if(results.status === 0) {
setRegressionTestsData(results.data)
setPageNumbers(getPageNumbersList(results.total_count, resPerPage))
} else if(results.status >=20 && results.status <=30) {
snackbar.statusCheck(results)
user.setSessionTokenMatches(false)
} else snackbar.statusCheck(results)
loading.setLoading(false)
}
if(user.f_auth([1, 20])) onLoadRegressionTests()
else setRegressionTestsData('You do not have the authority to view this page.')
}, [currentPage])
const onRegressionTestClick = (id) => props.history.push(`test?id=${id}`)
const onRequestRegressionTestClick = () => props.history.push('/requesttest')
const onPageNumberClick = (pageNum) => {
setCurrentPage(pageNum)
}
I can see the summary is an array. You can not access properties of an element of arrays like this.
When you get the summary, try this:
const getIcon = summary.data.map((item) => {
const status = getRegressionTestStatus(item)
if(status === 'Unresolved') return <ScheduleIcon style={{color: 'var(--update-bg-color)'}} />
else if(status === 'Failed') return <CloseIcon style={{color: 'var(--reject-fg-color)'}} />
else if(status === 'Success') return <CheckIcon style={{color: 'var(--approve-bg-color)'}} />
)}
This will return a new array of Icon you want.

react clearinterval not working for another function

i am working on one of the react project, for that i have used setInterval and clearInterval, it works fine in same function, but when i used clearInterval in another function it is not working, can anyone please help me why it is happening like that ? here i have attached my whole code, can anyone please look my code and help me to resolve this issue ? clearInterval is not working for the onClickStartRound in function
export class GamePlayBlack extends React.Component<Props, State>
{
public interval_counter;
public setTimer = '30:00';
public setSeconds = 30;
constructor(props: Props)
{
super(props);
this.state = {
gameData: GameDataStore.state,
userData: UserDataStore.state,
buttonLoading: false,
gameStarted: false,
updateTimer: this.setTimer,
clearintervaltimer : '',
};
localStorage.setItem('is_called','0');
localStorage.setItem('is_called_show_winner_card','0');
}
public componentDidMount(): void
{
GameDataStore.listen(data => this.setState({
gameData: data
}));
UserDataStore.listen(data => this.setState({
userData: data
}));
}
private onSelect = (winningPlayerGuid: string) =>
{
return GameDataStore.chooseWinner(this.state.userData.playerGuid, winningPlayerGuid);
};
private onClickStartRound = () =>
{
localStorage.setItem('is_started','1');
clearInterval(this.interval_counter);
this.setState({
buttonLoading: true,
gameStarted: true,
});
GameDataStore.startRound(this.state.userData.playerGuid)
.finally(() => this.setState({
buttonLoading: false,
gameStarted: true,
}));
};
private onClickSkipBlack = () =>
{
this.setState({
buttonLoading: true
});
GameDataStore.skipBlack(this.state.userData.playerGuid)
.finally(() => this.setState({
buttonLoading: false
}));
};
private waitforstart = (game_id:any,playerGUID:any,chooserGuid:any) => { //game_id:any,playerGUID:any,chooserGuid:any
console.log("guid");
console.log(this.state.gameData);
console.log(this.state.userData);
let self = this;
window.setInterval(function() {
//alert("sdsd");
return GameDataStore.removePlayer(game_id,playerGUID,chooserGuid);
}.bind(self),30000);
};
private skipPlayer = (game_string_id:any,target_turn:any,chooserGuid:any) => {
return GameDataStore.skipPlayer(game_string_id,target_turn,chooserGuid);
}
public startTimer = () => {
localStorage.setItem('is_called','1');
let timer = this.setSeconds, minutes, seconds;
let _self = this;
this.interval_counter = setInterval(function () {
let is_started = localStorage.getItem('is_started');
if(is_started == "0") {
let chooserGuid = localStorage.getItem('chooserGuid');
let game_string_id = localStorage.getItem('game_id');
let target_turn = localStorage.getItem('target_turn');
let is_called = localStorage.getItem('is_called');
if(typeof timer!==undefined && timer!=null) {
minutes = parseInt(timer/60 as any,10);
seconds = parseInt(timer%60 as any,10);
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
console.log(minutes + ":" + seconds);
_self.setState({
updateTimer: minutes + ":" + seconds
});
if (--timer < 0) {
//localStorage.setItem('is_called','0');
if(is_started == "0") {
_self.skipPlayer(game_string_id,target_turn,chooserGuid);
clearInterval(_self.interval_counter);
return false;
}
}
}
}
}, 1000);
}
public render()
{
const {
gameData,
buttonLoading
} = this.state;
const me = gameData.game?.players?.[this.state.userData.playerGuid];
const defsLoaded = cardDefsLoaded(gameData);
if (!me || !gameData.game || !defsLoaded)
{
return <ContainerProgress />;
} else {
let game_id = gameData.game.id;
let chooserGuid = gameData.game.chooserGuid;
let all_players = gameData.game.players;
let all_player_id = Object.keys(all_players);
//alert(gameData.game.chooserGuid);
let filteredAry = all_player_id.filter(e => e !== this.state.userData.playerGuid);
console.log("guid:"+chooserGuid);
console.log("all players:"+all_player_id);
console.log("new array:"+filteredAry);
let target_item = filteredAry.find((_, i, ar) => Math.random() < 1 / (ar.length - i));
if(typeof target_item !== undefined && target_item!=null) {
localStorage.setItem('target_turn',target_item);
}
}
const {
players,
chooserGuid,
roundCards,
roundStarted,
} = gameData.game;
const roundCardKeys = Object.keys(roundCards ?? {});
const remainingPlayerGuids = Object.keys(players ?? {})
.filter(pg => !(pg in (roundCards ?? {})) && pg !== chooserGuid);
const remainingPlayers = remainingPlayerGuids.map(pg => unescape(players?.[pg]?.nickname));
const revealedIndex = this.state.gameData.game?.revealIndex ?? 0;
const timeToPick = remainingPlayers.length === 0;
const revealMode = timeToPick && revealedIndex < roundCardKeys.length;
const hasWinner = !!gameData.game?.lastWinner;
if(!roundStarted) {
//alert(chooserGuid);
localStorage.setItem('is_started','0');
if(typeof gameData.game.id !== undefined && gameData.game.id!=null) {
localStorage.setItem('game_id',gameData.game.id);
}
if(typeof gameData.game.chooserGuid !== undefined && gameData.game.chooserGuid!=null) {
localStorage.setItem('chooserGuid',gameData.game.chooserGuid);
}
let is_called = localStorage.getItem('is_called');
if(is_called == "0") {
this.startTimer();
}
} else {
localStorage.setItem('is_started','1');
}
return (
<>
<div>
<PlayersRemaining/>
</div>
<Divider style={{margin: "1rem 0"}}/>
{!roundStarted && (
<Typography style={{marginBottom: "1rem", textAlign: "center"}}>
<strong>You are the Card Captain!</strong>
<br/>
Read the card aloud, then click Start The Round. Once everyone plays, you will choose your favorite!<br/>
<span> {this.state.updateTimer}</span> Seconds
</Typography>
)}
{!timeToPick && roundStarted && (
<CardPlayTimeRemaining gameData={gameData}/>
)}
<Grid container spacing={2} style={{justifyContent: "center", marginTop: "1rem"}}>
{(!hasWinner) && (
<Grid item xs={12} sm={6} md={4} lg={3}>
<BlackCard packId={gameData.game?.blackCard.packId}>
{gameData.blackCardDef?.content}
</BlackCard>
</Grid>
)}
<RevealWhites canReveal={true}/>
<ShowWinner/>
</Grid>
{!roundStarted && (
<div style={{marginTop: "1rem", textAlign: "center"}}>
<LoadingButton loading={buttonLoading} color={"secondary"} variant={"outlined"} onClick={this.onClickSkipBlack}>
Skip Card
</LoadingButton>
<LoadingButton loading={buttonLoading} color={"secondary"} variant={"contained"} onClick={this.onClickStartRound} style={{marginLeft: "1rem"}}>
Start the round!
</LoadingButton>
</div>
)}
<PickWinner
canPick={true}
hasWinner={hasWinner}
onPickWinner={this.onSelect}
revealMode={revealMode}
timeToPick={timeToPick}
/>
</>
);
}
}

Resources