diff --git a/ui/package-lock.json b/ui/package-lock.json
index 25d4050..2ee7479 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -19,7 +19,8 @@
},
"../pkg": {
"name": "word_grid",
- "version": "0.1.0"
+ "version": "0.1.0",
+ "license": "AGPL-3"
},
"node_modules/@babel/code-frame": {
"version": "7.22.5",
diff --git a/ui/src/Modal.tsx b/ui/src/Modal.tsx
index 041a13e..d043788 100644
--- a/ui/src/Modal.tsx
+++ b/ui/src/Modal.tsx
@@ -2,7 +2,7 @@ import {useEffect, useRef} from "react";
export function Modal(props: {
isOpen: boolean;
- setClosed: () => void;
+ setOpen: (isOpen: boolean) => void;
children: any;
}){
@@ -27,7 +27,7 @@ export function Modal(props: {
// we manually trigger a close anyway because the children can get updated before the dialog gets closed otherwise
// @ts-ignore
ref.current.close();
- props.setClosed();
+ props.setOpen(false);
}}>✕
diff --git a/ui/src/elements.tsx b/ui/src/elements.tsx
index e34672c..1db9dd2 100644
--- a/ui/src/elements.tsx
+++ b/ui/src/elements.tsx
@@ -1,6 +1,8 @@
import * as React from "react";
import {GameWasm, Letter as LetterData, MyResult, PlayedTile, PlayerAndScore, Tray, WordResult} from "word_grid";
import {ChangeEvent, JSX, useEffect, useMemo, useReducer, useRef, useState} from "react";
+import {Modal} from "./Modal";
+import {addNTimes} from "./utils";
export interface Settings {
trayLength: number;
@@ -181,8 +183,6 @@ export function Game(props: {wasm: GameWasm, settings: Settings}) {
}
const [playerLetters, trayDispatch] = useReducer(movePlayableLetters, []);
-
-
const [logInfo, logDispatch] = useReducer(addLogInfo, []);
const [turnCount, setTurnCount] = useState
(1);
@@ -202,6 +202,7 @@ export function Game(props: {wasm: GameWasm, settings: Settings}) {
const logDivRef = useRef(null);
+ const [isTileExchangeOpen, setIsTileExchangeOpen] = useState(false);
useEffect(() => {
// Effect is to keep the log window scrolled down
@@ -214,6 +215,7 @@ export function Game(props: {wasm: GameWasm, settings: Settings}) {
return <>
+
@@ -273,6 +275,7 @@ export function Game(props: {wasm: GameWasm, settings: Settings}) {
}}>{confirmedScorePoints > -1 ? `Score ${confirmedScorePoints} points ✅` : "Check"}
+
>;
@@ -465,4 +468,115 @@ function Scores(props: {playerScores: Array
}){
return
{elements}
-}
\ No newline at end of file
+}
+
+function TileExchangeModal(props: {playerLetters: PlayableLetterData[], isOpen: boolean, setOpen: (isOpen: boolean) => void}) {
+
+ function clearExchangeTiles() {
+ const array: boolean[] = [];
+ addNTimes(array, false, props.playerLetters.length);
+ return array;
+ }
+
+ const [tilesToExchange, setTilesToExchange] = useState(clearExchangeTiles);
+
+ let tilesExchangedSelected = 0;
+ for (let i of tilesToExchange) {
+ if(i) {
+ tilesExchangedSelected++;
+ }
+ }
+
+ return {
+ setTilesToExchange(clearExchangeTiles());
+ props.setOpen(isOpen);
+ }}>
+
+
+ Click on each tile you'd like to exchange. You currently have {tilesExchangedSelected} tiles selected.
+
+
+
+
+
+
+
+
+
+
+
+
+ ;
+
+}
+
+function TilesExchangedTray(props: {
+ tray: Array,
+ trayLength: number,
+ selectedArray: Array,
+ setSelectedArray: (x: Array) => void,
+}){
+
+ const divContent = [];
+ for(let i = 0; i {
+ props.selectedArray[i] = !props.selectedArray[i];
+ props.setSelectedArray(props.selectedArray.slice());
+ }
+
+ if(tileData != null){
+ divContent.push(
+
+ );
+ } else{
+ divContent.push();
+ }
+ }
+
+ return
+ {divContent}
+
;
+
+}
+
+function DummyExchangeTile(props: {
+ letter: LetterData,
+ isSelected: boolean,
+ onClick: () => void,
+}){
+
+ let textClassName = "text";
+ if(props.letter.is_blank) {
+ textClassName += " prev-blank";
+ }
+
+ let letterClassName = "letter";
+ if(props.isSelected){
+ letterClassName += ' selected-tile';
+ }
+
+
+ return
+
{props.letter.text}
+
{props.letter.points}
+
;
+}
diff --git a/ui/src/style.less b/ui/src/style.less
index a205905..b5d837f 100644
--- a/ui/src/style.less
+++ b/ui/src/style.less
@@ -188,4 +188,31 @@ dialog {
}
}
+ .tile-exchange-dialog {
+
+ .selection-buttons {
+ display: flex;
+ justify-content: space-around;
+
+ button {
+ width: 40%;
+ }
+ }
+
+ .finish-buttons {
+ .selection-buttons();
+ }
+
+ .tray-container {
+ display: flex;
+ justify-content: center;
+ margin: 20px;
+ }
+
+ .selected-tile {
+ bottom: 10px;
+ }
+
+ }
+
}
\ No newline at end of file
diff --git a/ui/src/utils.ts b/ui/src/utils.ts
new file mode 100644
index 0000000..bc070f3
--- /dev/null
+++ b/ui/src/utils.ts
@@ -0,0 +1,6 @@
+
+export function addNTimes(array: T[], toAdd: T, times: number) {
+ for (let i=0; i