Skip to content
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

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30,825 changes: 30,825 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

Binary file added src/components/memotest/assets/cell.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/components/memotest/assets/fondo.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/components/memotest/assets/gohan.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/components/memotest/assets/goku.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/components/memotest/assets/gotenks.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/components/memotest/assets/majinboo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/components/memotest/assets/piccolo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/components/memotest/assets/saibaman.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/components/memotest/assets/shenlong.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/components/memotest/assets/vegeta.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions src/components/memotest/board/Board.css
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;
}
31 changes: 31 additions & 0 deletions src/components/memotest/board/Board.js
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;
40 changes: 40 additions & 0 deletions src/components/memotest/board/Card.css
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);
}
18 changes: 18 additions & 0 deletions src/components/memotest/board/Card.js
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;
45 changes: 45 additions & 0 deletions src/components/memotest/constants/initial-cards.js
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;
63 changes: 63 additions & 0 deletions src/components/memotest/customHooks/useMemotestGame.js
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;
}
Copy link
Collaborator

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

Copy link
Author

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 }

Copy link
Collaborator

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


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);
Copy link
Collaborator

Choose a reason for hiding this comment

The 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 currentPairs si lo modificás para que en vez de tener solo las strings alt, tengan la id también, onda:

setCurrentPairs([...currentPairs, { alt, id }]) 

Copy link
Author

Choose a reason for hiding this comment

The 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;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

esto debería ser wonPairs > (cards.length / 2), así podés agregar cartas nuevas sin tener que modificar nada acá


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;
38 changes: 38 additions & 0 deletions src/components/memotest/customHooks/useTimer.js
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]);
Copy link
Collaborator

Choose a reason for hiding this comment

The 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

Copy link
Author

Choose a reason for hiding this comment

The 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

Copy link
Collaborator

Choose a reason for hiding this comment

The 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;
15 changes: 15 additions & 0 deletions src/components/memotest/score/Timer.js
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;
19 changes: 19 additions & 0 deletions src/components/memotest/score/WinnerScore.css
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;
}
16 changes: 16 additions & 0 deletions src/components/memotest/score/WinnerScore.js
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': '')}>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

creo que esto hace lo opuesto de lo que querés: si show es true, pone la clase winner-score--hidden.
Fijate que cuando ganás no podés apretar el botón porque tiene el pointer-events: none; puesto

Copy link
Author

Choose a reason for hiding this comment

The 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;
5 changes: 5 additions & 0 deletions src/components/pages/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import FocusableInput from './FocusableInput';
import UglyClass from './UglyClass';
import FancyButton from '../small/FancyButton';
import TicTacToe from './TicTacToe';
import Memotest from './Memotest';

const pages = {
home: {
Expand Down Expand Up @@ -38,6 +39,10 @@ const pages = {
name: 'Tic Tac Toe',
component: TicTacToe,
},
memotest: {
name: 'Memotest',
component: Memotest,
}
};

function App() {
Expand Down
22 changes: 22 additions & 0 deletions src/components/pages/Memotest.css
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;
}
Loading