Merge pull request #1 from MauMauStudios/meow_to_mau
Basic (and First!) Mau Front-End
BIN
src/assets/cards/back.png
Normal file
|
After Width: | Height: | Size: 195 KiB |
BIN
src/assets/cards/clubs_ace.png
Normal file
|
After Width: | Height: | Size: 9.9 KiB |
BIN
src/assets/cards/clubs_eight.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
src/assets/cards/clubs_five.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/cards/clubs_four.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
src/assets/cards/clubs_jack.png
Normal file
|
After Width: | Height: | Size: 130 KiB |
BIN
src/assets/cards/clubs_king.png
Normal file
|
After Width: | Height: | Size: 123 KiB |
BIN
src/assets/cards/clubs_nine.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
src/assets/cards/clubs_queen.png
Normal file
|
After Width: | Height: | Size: 137 KiB |
BIN
src/assets/cards/clubs_seven.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
src/assets/cards/clubs_six.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/cards/clubs_ten.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
src/assets/cards/clubs_three.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/cards/clubs_two.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
src/assets/cards/diamonds_ace.png
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
BIN
src/assets/cards/diamonds_eight.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/cards/diamonds_five.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
src/assets/cards/diamonds_four.png
Normal file
|
After Width: | Height: | Size: 9.4 KiB |
BIN
src/assets/cards/diamonds_jack.png
Normal file
|
After Width: | Height: | Size: 123 KiB |
BIN
src/assets/cards/diamonds_king.png
Normal file
|
After Width: | Height: | Size: 130 KiB |
BIN
src/assets/cards/diamonds_nine.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/cards/diamonds_queen.png
Normal file
|
After Width: | Height: | Size: 124 KiB |
BIN
src/assets/cards/diamonds_seven.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
src/assets/cards/diamonds_six.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
src/assets/cards/diamonds_ten.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
src/assets/cards/diamonds_three.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
src/assets/cards/diamonds_two.png
Normal file
|
After Width: | Height: | Size: 9.8 KiB |
BIN
src/assets/cards/hearts_ace.png
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
BIN
src/assets/cards/hearts_eight.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
src/assets/cards/hearts_five.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
src/assets/cards/hearts_four.png
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
src/assets/cards/hearts_jack.png
Normal file
|
After Width: | Height: | Size: 134 KiB |
BIN
src/assets/cards/hearts_king.png
Normal file
|
After Width: | Height: | Size: 136 KiB |
BIN
src/assets/cards/hearts_nine.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
src/assets/cards/hearts_queen.png
Normal file
|
After Width: | Height: | Size: 138 KiB |
BIN
src/assets/cards/hearts_seven.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
src/assets/cards/hearts_six.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
src/assets/cards/hearts_ten.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
src/assets/cards/hearts_three.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
src/assets/cards/hearts_two.png
Normal file
|
After Width: | Height: | Size: 9.9 KiB |
BIN
src/assets/cards/joker_black.png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
src/assets/cards/joker_red.png
Normal file
|
After Width: | Height: | Size: 96 KiB |
BIN
src/assets/cards/spades_ace.png
Normal file
|
After Width: | Height: | Size: 9.9 KiB |
BIN
src/assets/cards/spades_eight.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
src/assets/cards/spades_five.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/cards/spades_four.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
src/assets/cards/spades_jack.png
Normal file
|
After Width: | Height: | Size: 124 KiB |
BIN
src/assets/cards/spades_king.png
Normal file
|
After Width: | Height: | Size: 127 KiB |
BIN
src/assets/cards/spades_nine.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
src/assets/cards/spades_queen.png
Normal file
|
After Width: | Height: | Size: 138 KiB |
BIN
src/assets/cards/spades_seven.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
src/assets/cards/spades_six.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/cards/spades_ten.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
src/assets/cards/spades_three.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
src/assets/cards/spades_two.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
32
src/layout/components/Card.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import React, {FunctionComponent} from "react";
|
||||
|
||||
interface Props {
|
||||
cardString: string;
|
||||
handleClick?: (cardString: string) => void;
|
||||
isHidden?: boolean;
|
||||
isClickable?: boolean;
|
||||
}
|
||||
|
||||
const Card: FunctionComponent<Props> = ({cardString, handleClick, isHidden, isClickable}) => {
|
||||
const cardType = cardString.split(' ')[0].toLowerCase();
|
||||
const cardValue = cardString.split(' ')[1].toLowerCase();
|
||||
|
||||
const cardSource = isHidden ?
|
||||
require(`../../assets/cards/back.png`) :
|
||||
require(`../../assets/cards/${cardType}_${cardValue}.png`);
|
||||
const cardName = isHidden ? 'back' : `${cardType} ${cardValue}`;
|
||||
|
||||
const handleCardClick = () => {
|
||||
if (handleClick) {
|
||||
handleClick(cardString);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`card ${isClickable && 'card-clickable'}`}>
|
||||
<img className="card__texture" src={cardSource} alt={cardName} onClick={handleCardClick}/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Card;
|
||||
28
src/layout/components/Hand.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import React, {FunctionComponent} from 'react';
|
||||
import Card from "./Card";
|
||||
|
||||
interface Props {
|
||||
hand: string[];
|
||||
actionOnClick: (cardString: string) => void;
|
||||
isHidden?: boolean;
|
||||
}
|
||||
|
||||
const Hand: FunctionComponent<Props> = ({hand, actionOnClick, isHidden}) => {
|
||||
|
||||
const isMyHand = !isHidden;
|
||||
|
||||
return (
|
||||
<div className="hand">
|
||||
{
|
||||
hand.map((card, index) => {
|
||||
return (
|
||||
<Card key={index} cardString={card} handleClick={actionOnClick} isHidden={!isMyHand}
|
||||
isClickable={isMyHand}/>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Hand;
|
||||
@@ -3,6 +3,16 @@ import React from "react";
|
||||
import {useParams} from "react-router";
|
||||
import {GHButton} from "../components/Button";
|
||||
import useTitle from "../../utils/TitleHook";
|
||||
import Card from "../components/Card";
|
||||
import Hand from "../components/Hand";
|
||||
|
||||
interface GameState {
|
||||
PlayerName: string;
|
||||
Hand: string[];
|
||||
CurrentCard: string;
|
||||
CurrentPlayer: string;
|
||||
Players: string[];
|
||||
}
|
||||
|
||||
const Room = () => {
|
||||
|
||||
@@ -12,47 +22,40 @@ const Room = () => {
|
||||
|
||||
const WS_URL = `ws://${process.env.REACT_APP_API_URL}/room/${roomId}`;
|
||||
|
||||
const [message, setMessage] = React.useState<string>('');
|
||||
const [messages, setMessages] = React.useState<string[]>([]);
|
||||
const [gameState, setGameState] = React.useState<GameState>({PlayerName: '', Hand: [], CurrentCard: '', CurrentPlayer: '', Players: []});
|
||||
|
||||
const websocket = useWebSocket(WS_URL, {
|
||||
onOpen: () => {
|
||||
console.log('WebSocket connection established.');
|
||||
},
|
||||
onMessage: (event) => {
|
||||
setMessages([...messages, event.data]);
|
||||
const data = JSON.parse(event.data);
|
||||
setGameState(data);
|
||||
}
|
||||
});
|
||||
|
||||
const handleSend = () => {
|
||||
websocket.sendMessage(message);
|
||||
setMessage('');
|
||||
}
|
||||
|
||||
const handleMessageChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setMessage(event.target.value);
|
||||
}
|
||||
|
||||
const handleLeaveRoom = () => {
|
||||
window.location.href = '/';
|
||||
}
|
||||
|
||||
const handleCardSend = (card: string) => {
|
||||
const formattedCard = JSON.stringify({CardType: card.split(' ')[0], CardValue: card.split(' ')[1]});
|
||||
websocket.sendMessage(formattedCard);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>Room {roomId}</h1>
|
||||
<GHButton onClick={handleLeaveRoom}>Leave Room</GHButton>
|
||||
<form onSubmit={(event) => {
|
||||
event.preventDefault();
|
||||
handleSend();
|
||||
}}>
|
||||
<input type="text" name="message" placeholder="Send a message" value={message}
|
||||
onChange={handleMessageChange}/>
|
||||
<span onClick={handleSend}>Send</span>
|
||||
</form>
|
||||
{
|
||||
gameState.CurrentCard &&
|
||||
<Card cardString={gameState.CurrentCard}/>
|
||||
}
|
||||
<Hand hand={gameState.Hand} actionOnClick={handleCardSend}/>
|
||||
<ul>
|
||||
{
|
||||
messages.map((message, index) => {
|
||||
return <li key={index}>{message}</li>
|
||||
gameState.Players.map((player, index) => {
|
||||
return <li key={index} style={{fontWeight: player === gameState.CurrentPlayer ? 'bold' : 'normal'}}>{player} {player === gameState.PlayerName && '(You)'}</li>
|
||||
})
|
||||
}
|
||||
</ul>
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
@import "button";
|
||||
@import "button";
|
||||
@import "card";
|
||||
@import "hand";
|
||||
14
src/styles/layout/components/card.scss
Normal file
@@ -0,0 +1,14 @@
|
||||
.card {
|
||||
width: 100px;
|
||||
min-width: 100px;
|
||||
|
||||
&-clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&__texture {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
9
src/styles/layout/components/hand.scss
Normal file
@@ -0,0 +1,9 @@
|
||||
.hand {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
//justify-content: center;
|
||||
flex-flow: nowrap !important;
|
||||
overflow-x: scroll;
|
||||
padding: 0.5rem;
|
||||
gap: 0.5rem;
|
||||
}
|
||||