-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add task react-clase-2 #20
base: master
Are you sure you want to change the base?
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
.board { | ||
position: relative; | ||
width: 100%; | ||
height: 100%; | ||
display: grid; | ||
grid-template-columns: repeat(4, 1fr); | ||
grid-template-rows: repeat(4, 1fr); | ||
grid-gap: 10px; | ||
perspective: 1000px; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import React from 'react'; | ||
import Card from './Card'; | ||
import background from '../assets/shenlong.jpg'; | ||
import './Board.css'; | ||
|
||
const Board = ({cards, handleCard, flipped, animating }) => { | ||
const boardStyle = { | ||
backgroundImage: 'url(' + background + ')', | ||
backgroundSize: '100% 100%' | ||
}; | ||
|
||
return( | ||
<section className='board' style={boardStyle} > | ||
{ | ||
cards.map((card, i) => ( | ||
<Card | ||
onClick={handleCard} | ||
flipped={flipped[i]} | ||
animating={animating} | ||
key={`${card.name}-${i}`} | ||
alt={card.name} | ||
src={card.img} | ||
id={i} | ||
/> | ||
)) | ||
} | ||
</section> | ||
) | ||
} | ||
|
||
export default Board; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
.cards { | ||
position: relative; | ||
background-color: ghostwhite; | ||
border-radius: 5px; | ||
aspect-ratio: 1 / 1; | ||
transform: scale(1); | ||
transform-style: preserve-3d; | ||
transition: transform .5s; | ||
cursor: pointer; | ||
z-index: 0; | ||
object-fit: contain; | ||
} | ||
|
||
.cards:active { | ||
transform: scale(.97); | ||
transition: transform .2s; | ||
} | ||
|
||
.cards.flip { | ||
transform: rotateY(180deg); | ||
} | ||
|
||
.cards.find { | ||
opacity: 0; | ||
} | ||
|
||
#front, | ||
#back{ | ||
display: block; | ||
position: absolute; | ||
width: 100%; | ||
height: 100%; | ||
background-clip: content-box; | ||
border-radius: 5px; | ||
backface-visibility: hidden; | ||
} | ||
|
||
#back { | ||
transform: rotateY(180deg); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import React from 'react'; | ||
import front from '../assets/fondo.jpg'; | ||
import './Card.css'; | ||
|
||
const Card = ({src, alt, id, flipped, onClick, animating}) => { | ||
return( | ||
<div | ||
className={'cards ' + (flipped ? 'flip' : '')} | ||
key={id} | ||
id={id} | ||
> | ||
<img src={front} alt={alt} id="front" onClick={() => (!animating && onClick(id, alt))}/> | ||
<img src={src} alt={alt} id="back" /> | ||
</div> | ||
) | ||
} | ||
|
||
export default Card; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import cell from '../assets/cell.png'; | ||
import gohan from '../assets/gohan.png'; | ||
import goku from '../assets/goku.png'; | ||
import gotenks from '../assets/gotenks.png'; | ||
import majinboo from '../assets/majinboo.png'; | ||
import piccolo from '../assets/piccolo.png'; | ||
import saibaman from '../assets/saibaman.png'; | ||
import vegeta from '../assets/vegeta.png'; | ||
|
||
const cardArray = [ | ||
{ | ||
name: 'cell', | ||
img: cell, | ||
}, | ||
{ | ||
name: 'gohan', | ||
img: gohan, | ||
}, | ||
{ | ||
name: 'goku', | ||
img: goku, | ||
}, | ||
{ | ||
name: 'gotenks', | ||
img: gotenks, | ||
}, | ||
{ | ||
name: 'majinboo', | ||
img: majinboo, | ||
}, | ||
{ | ||
name: 'piccolo', | ||
img: piccolo, | ||
}, | ||
{ | ||
name: 'saibaman', | ||
img: saibaman, | ||
}, | ||
{ | ||
name: 'vegeta', | ||
img: vegeta, | ||
} | ||
]; | ||
|
||
export default cardArray; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import React, { useState } from 'react'; | ||
import cardArray from '../constants/initial-cards'; | ||
|
||
const createInitialCards = () => { | ||
let allCards = cardArray.concat(cardArray); | ||
let newCards = allCards.sort(() => 0.5 - Math.random()); | ||
return newCards; | ||
} | ||
|
||
const useMemotestGame = () => { | ||
const [cards, setCards] = useState(createInitialCards); | ||
const [isFlipped, setIsFlipped] = useState([false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]); | ||
const [currentPairs, setCurrentPairs] = useState([]); | ||
const [previousID, setPreviousID] = useState(null); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. El previousID me hace ruido, creo que es innecesario. Entiendo que lo necesitás para dar vuelta las dos cartas después, pero siento que eso mismo lo deberías poder hacer con
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. El previousID es más para el CSS así aplico las transformaciones al dar vuelta la carta. Ahora corrijo como decís para que me quede más prolijo. |
||
const [animating, setAnimating] = useState(false); | ||
const [wonPairs, setWonPairs] = useState(0); | ||
const gameEnded = wonPairs > 7; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. esto debería ser |
||
|
||
const handleCard = (id, alt) => { | ||
let newIsPair = [...currentPairs, alt]; | ||
setCurrentPairs(newIsPair); | ||
|
||
let newIsFlipped = [...isFlipped]; | ||
newIsFlipped.splice(id, 1, true); | ||
setIsFlipped(newIsFlipped); | ||
|
||
if(previousID === null) { | ||
setPreviousID(id); | ||
} | ||
|
||
if(newIsPair.length === 2) { | ||
if(newIsPair[0] === newIsPair[1]) { | ||
setWonPairs(wonPairs + 1); | ||
setCurrentPairs([]); | ||
setPreviousID(null); | ||
} else { | ||
setAnimating(true); | ||
setTimeout(() => { | ||
setCurrentPairs([]); | ||
newIsFlipped.splice(id, 1, false); | ||
newIsFlipped.splice(previousID, 1, false); | ||
setIsFlipped(newIsFlipped); | ||
setPreviousID(null); | ||
setAnimating(false); | ||
}, 750); | ||
} | ||
} | ||
} | ||
|
||
const restart = () => { | ||
console.log('restart') | ||
setCards(createInitialCards); | ||
setCurrentPairs([]); | ||
setIsFlipped([false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]); | ||
setWonPairs(0); | ||
setPreviousID(null); | ||
setAnimating(false); | ||
} | ||
|
||
return { cards, handleCard, isFlipped, gameEnded, animating, restart}; | ||
} | ||
|
||
export default useMemotestGame; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import React, { useState, useEffect, useRef } from 'react'; | ||
|
||
const useTimer = gameEnded => { | ||
const [minutes, setMinutes] = useState(0); | ||
const [seconds, setSeconds] = useState(0); | ||
|
||
useInterval(() => { | ||
setSeconds(seconds + 1); | ||
|
||
if(seconds === 59) { | ||
setSeconds(0); | ||
setMinutes(minutes + 1); | ||
} | ||
}, !gameEnded ? 1000 : null); | ||
|
||
return { minutes, seconds }; | ||
} | ||
|
||
function useInterval(callback, delay) { | ||
const savedCallback = useRef(); | ||
|
||
useEffect(() => { | ||
savedCallback.current = callback; | ||
}, [callback]); | ||
|
||
useEffect(() => { | ||
function tick() { | ||
savedCallback.current(); | ||
} | ||
|
||
if (delay !== null) { | ||
let id = setInterval(tick, delay); | ||
return () => clearInterval(id); | ||
} | ||
}, [delay]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no declares un hook por dentro de otro, declaralo por fuera del useTimer There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Este código lo copié y pegué del blog que me mandaste, lo cambio igual? Simplemente lo adapté al memotest There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sí, pero en general no tenés que declarar hooks adentro de otros hooks, solamente movelo afuera del otro hook |
||
} | ||
|
||
export default useTimer; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import React from 'react'; | ||
|
||
const Timer = ({ minutes, seconds, gameEnded }) => { | ||
return( | ||
<section className={gameEnded ? 'hidden' : ''}> | ||
<p id="timer"> | ||
Tiempo de juego: <span className="game-score"> | ||
{' '}{minutes < 10 ? `0${minutes}` : minutes}:{seconds < 10 ? `0${seconds}` : seconds} | ||
</span> | ||
</p> | ||
</section> | ||
) | ||
} | ||
|
||
export default Timer; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
.winner-score { | ||
position: relative; | ||
opacity: 0; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
font-size: 40px; | ||
flex-direction: column; | ||
margin-borttom: 250px; | ||
} | ||
|
||
.winner-score:not(.winner-score--hidden) { | ||
transition: opacity ease-in-out 0.7s; | ||
} | ||
|
||
.winner-score--hidden { | ||
opacity: 1; | ||
pointer-events: none; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import React from 'react'; | ||
import FancyButton from '../../small/FancyButton'; | ||
import './WinnerScore.css'; | ||
|
||
const WinnerScore = ({ show, result, restart = () => {} }) => { | ||
return ( | ||
<div className={'winner-score ' + (show ? 'winner-score--hidden': '')}> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. creo que esto hace lo opuesto de lo que querés: si There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lo del botón no lo pude hacer funcionar 😂 Ahora veo el problema, ojalá ahora si funcione |
||
<span className="winner-score-text"> | ||
Has completado el juego en {result} | ||
</span> | ||
<FancyButton onClick={restart}>¿Jugar de nuevo?</FancyButton> | ||
</div> | ||
); | ||
}; | ||
|
||
export default WinnerScore; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
.memotest-app { | ||
position: relative; | ||
text-align: center; | ||
width: 90%; | ||
} | ||
|
||
.memotest { | ||
position: relative; | ||
width: 350px; | ||
height: 350px; | ||
border: 4px solid ghostwhite; | ||
margin: auto; | ||
display: flex; | ||
} | ||
|
||
#timer { | ||
font-size: 24px; | ||
} | ||
|
||
.hidden { | ||
display: none; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
si ya estás guardando las cartas en un state, podés pasar el state de isFlipped acá mismo (así no lo tenés que armar a mano con un tamaño predeterminado). también podés agregar las keys que habíamos dicho para el render (
vegeta-0
,vegeta-1
, etc.)podés hacer todo eso con un .map() antes de devolverlo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Si las keys puse nombre[i] porque no se me ocurrió deducir el vegeta-0 y vegeta-1. IsFlipped lo paso como array o pensaba asignarlo cómo objeto { isFlipped: false }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
claro, asignarlo al objeto es lo que decía