From 138d13de805da7e524efe28f72867c2c5a380f19 Mon Sep 17 00:00:00 2001 From: cophilot Date: Sat, 14 Sep 2024 18:21:00 +0200 Subject: [PATCH] added extension --- src/api/BoardScoreTable/BoardScoreTable.tsx | 183 ++++++++++-------- .../ExtensionButtons/ExtensionButtons.scss | 0 src/api/ExtensionButtons/ExtensionButtons.tsx | 78 ++++++++ src/api/utils/GameStorage.ts | 20 ++ src/games/wingspan/assets/bird.png | Bin 6845 -> 6845 bytes src/games/wingspan/assets/bonus.png | Bin 13320 -> 13320 bytes src/games/wingspan/assets/eggs.png | Bin 5074 -> 5074 bytes src/games/wingspan/assets/nectar.png | Bin 0 -> 12806 bytes src/games/wingspan/assets/resources.png | Bin 6738 -> 6738 bytes src/games/wingspan/assets/round-goals.png | Bin 5936 -> 5936 bytes src/games/wingspan/assets/tucked-card.png | Bin 9831 -> 9831 bytes src/games/wingspan/definition.ts | 19 ++ 12 files changed, 219 insertions(+), 81 deletions(-) create mode 100644 src/api/ExtensionButtons/ExtensionButtons.scss create mode 100644 src/api/ExtensionButtons/ExtensionButtons.tsx create mode 100644 src/games/wingspan/assets/nectar.png diff --git a/src/api/BoardScoreTable/BoardScoreTable.tsx b/src/api/BoardScoreTable/BoardScoreTable.tsx index d03eca2..bf2aba4 100644 --- a/src/api/BoardScoreTable/BoardScoreTable.tsx +++ b/src/api/BoardScoreTable/BoardScoreTable.tsx @@ -3,6 +3,7 @@ import { useEffect, useState } from 'react'; import './BoardScoreTable.scss'; import GameStorage from '../utils/GameStorage'; import { getFunctionForWinMode, WinMode } from '../types/WinMode'; +import ExtensionButtons from '../ExtensionButtons/ExtensionButtons'; interface BoardScoreTableProps { definition: any; @@ -24,9 +25,8 @@ function BoardScoreTable({ onCellChange, }: BoardScoreTableProps) { const playerSizes = Array.from(Array(playerSize).keys()); - const rows = definition.rows || []; + const [rows, setRows] = useState(definition.rows || []); const tableStyle = parseTableStyle(definition); - const [tableMatrix, setTableMatrix] = useState( GameStorage.getGameMatrix( definition.title, @@ -106,87 +106,108 @@ function BoardScoreTable({ }; return ( - - - - - {playerSizes.map((index) => ( - - ))} - - - - {rows.map( - (row: any, index: number) => - (rounds === -1 || index < rounds) && ( - <> - {gameSettings.showHelp && row.icon && ( + <> + { + const extRows = extensionDefinition.rows || []; + extRows.forEach((row: any) => { + row.__extName = extensionName; + }); + setRows([...rows, ...extRows]); + }} + onExtensionOff={(extensionName) => { + setRows( + rows.filter( + (row: any) => row.__extName !== extensionName + ) + ); + }} + /> +
- { - const newPlayerNames = playerNames.slice(); - newPlayerNames[index] = - e.target.value.toUpperCase(); - setPlayerNames(newPlayerNames); - GameStorage.setPlayerNames( - definition.title, - newPlayerNames - ); - }} - /> -
+ + + + {playerSizes.map((index) => ( + + ))} + + + + {rows.map( + (row: any, index: number) => + (rounds === -1 || index < rounds) && ( + <> + {gameSettings.showHelp && row.icon && ( + + + + )} - + key={index} + style={getStyleFromRow( + row, + definition, + index + )}> + + {playerSizes.map((playerIndex) => ( + + ))} - )} - - - {playerSizes.map((playerIndex) => ( - - ))} - - - ) - )} - - - {totalRow.map((value, playerIndex) => ( - - ))} - - -
+ { + const newPlayerNames = + playerNames.slice(); + newPlayerNames[index] = + e.target.value.toUpperCase(); + setPlayerNames(newPlayerNames); + GameStorage.setPlayerNames( + definition.title, + newPlayerNames + ); + }} + /> +
+ {row.name} + + {row.description + ? ' - ' + + row.description + : ''} + +
- {row.name} - - {row.description - ? ' - ' + row.description - : ''} - -
- {isNaN(value) ? 0 : value} -
+ + ) + )} + + + {totalRow.map((value, playerIndex) => ( + + {isNaN(value) ? 0 : value} + + ))} + + + + ); } export default BoardScoreTable; diff --git a/src/api/ExtensionButtons/ExtensionButtons.scss b/src/api/ExtensionButtons/ExtensionButtons.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/api/ExtensionButtons/ExtensionButtons.tsx b/src/api/ExtensionButtons/ExtensionButtons.tsx new file mode 100644 index 0000000..c5e7338 --- /dev/null +++ b/src/api/ExtensionButtons/ExtensionButtons.tsx @@ -0,0 +1,78 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { useEffect, useState } from 'react'; +import './ExtensionButtons.scss'; +import GameStorage from '../utils/GameStorage'; + +interface ExtensionButtonsProps { + definition: any; + onExtensionOn?: (extensionName: string, extensionDefinition: any) => void; + onExtensionOff?: (extensionName: string) => void; +} + +/** + * This is a ExtensionButtons component + * @author cophilot + * @version 1.0.0 + * @created 2024-7-21 + */ +function ExtensionButtons({ + definition, + onExtensionOn, + onExtensionOff, +}: ExtensionButtonsProps) { + const extensionsDefinition = definition.extensions || {}; + const extensionsNames = Object.keys(extensionsDefinition); + + const [selectedExtensions, setSelectedExtensions] = useState( + GameStorage.getSelectedExtension(definition.title, []) + ); + + const handleExtensionClick = (extensionName: string) => { + let newSelectedExtensions = [...selectedExtensions]; + if (selectedExtensions.includes(extensionName)) { + newSelectedExtensions = selectedExtensions.filter( + (name) => name !== extensionName + ); + onExtensionOff?.(extensionName); + } else { + newSelectedExtensions.push(extensionName); + onExtensionOn?.(extensionName, extensionsDefinition[extensionName]); + } + + GameStorage.setSelectedExtension( + definition.title, + newSelectedExtensions + ); + setSelectedExtensions(newSelectedExtensions); + }; + + useEffect(() => { + GameStorage.getSelectedExtension(definition.title, []).forEach( + (extensionName: string) => { + onExtensionOn?.( + extensionName, + extensionsDefinition[extensionName] + ); + } + ); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return ( +
+ {extensionsNames.length > 0 &&

Extensions

} + {extensionsNames.map((name) => ( + + ))} +
+ ); +} +export default ExtensionButtons; diff --git a/src/api/utils/GameStorage.ts b/src/api/utils/GameStorage.ts index eda43fa..8a9931e 100644 --- a/src/api/utils/GameStorage.ts +++ b/src/api/utils/GameStorage.ts @@ -52,6 +52,26 @@ export default class GameStorage { ); } + static getSelectedExtension(gameTitle: string, fallback: string[] = []) { + const selectedExtension = localStorage.getItem( + GameStorage.getStorageKeyFromTitle(gameTitle, 'selected-extension') + ); + if (selectedExtension === null) { + return fallback; + } + return JSON.parse(selectedExtension); + } + + static setSelectedExtension( + gameTitle: string, + selectedExtension: string[] + ) { + localStorage.setItem( + GameStorage.getStorageKeyFromTitle(gameTitle, 'selected-extension'), + JSON.stringify(selectedExtension) + ); + } + static getGameMatrix(gameTitle: string, fallback: number[][] = []) { const matrix = localStorage.getItem( GameStorage.getStorageKeyFromTitle(gameTitle, 'matrix') diff --git a/src/games/wingspan/assets/bird.png b/src/games/wingspan/assets/bird.png index 24fa5846e7b897fc6be6422026dee842f923a83e..89f613e1fe70df14001d5e9a712147083944e30a 100644 GIT binary patch delta 68 zcmdmMy4Q3<=d#Wzp$PyQ+!fLQ diff --git a/src/games/wingspan/assets/bonus.png b/src/games/wingspan/assets/bonus.png index e4223538607c684e38389a128b3a6e228cfd4808..0c911c702015afedf88e51f1ef90165eea93b616 100644 GIT binary patch delta 68 zcmeCk=*XDR$H~bjz{q4^e^p@PbX8-16JskQGi?I{D+7b&l36N~Pa7*qBZ*yexio_T O2s~Z=T-G@yGywpR3lk#% delta 68 zcmeCk=*XDR$H^`sq%GC@@3GRx>8i&32Bua;j-@w$$z*O77z{F3ZX#*206R246 Sv6Yn!K;Y@>=d#Wzp$PyXN)=`R diff --git a/src/games/wingspan/assets/nectar.png b/src/games/wingspan/assets/nectar.png new file mode 100644 index 0000000000000000000000000000000000000000..f0d3c22ce6492d31a563f8c767880a8cf4c79adb GIT binary patch literal 12806 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 Q{R#k+l8_g#5j70{A64=B>Hq)$ literal 0 HcmV?d00001 diff --git a/src/games/wingspan/assets/resources.png b/src/games/wingspan/assets/resources.png index db9061a53bccd86f08214cd46ddb6183cad07803..79e27132d7ee60e899ccea7cc215f3138ed66441 100644 GIT binary patch delta 68 zcmca)a>-;uA15cD03(xu{Z)aD)AJ?yO^mIK%(V>+tPBho^Aaaa7L`(xMiMJ9zNy0i N1fH&bF6*2UngD@A5$FH_ delta 68 zcmca)a>-;uA1Awnkhb)vpO?36oSrYqZ(wR=V5DteU}a#iW{X$gTe~DWM4fEl(BG diff --git a/src/games/wingspan/assets/round-goals.png b/src/games/wingspan/assets/round-goals.png index f93af060858cb17377278d9d4b81cdf6ed48bc3b..af5dc821e458fce7a64b8815f8fb0896d71c6a84 100644 GIT binary patch delta 68 zcmdm>w?S`0A15cD03(xu{Z)aD(|yJGO^mIK%(V>+tPBho^Aaaa{w$^>jU-lJd{c)3 O2s~Z=T-G@yGywpAk`he- delta 68 zcmdm>w?S`0A1Awnkhb)vpO?36obD^eZ(w3&YNBmmU}a#C;U@Kd@@Fw6X`q;iDMYOJ S*vd)+tPBho^Aaaa)>2cFMiMJ9zNy0i N1fH&bF6*2UngF8u5`+K% delta 68 zcmaFv^W0}bA1Awnkhb)vpO?36oZh0!Z(w0%V4`hcU76