diff --git a/src/Routes.tsx b/src/Routes.tsx index d33327c..0e100b3 100644 --- a/src/Routes.tsx +++ b/src/Routes.tsx @@ -1,7 +1,7 @@ import { Route, Routes as ReactRoutes, HashRouter } from 'react-router-dom'; import HomeView from './views/HomeView'; import ExpandableTable from './views/ExpandableTable'; -import getAllGames from './allGames'; +import { getAllGames } from './allGames'; import StringUtils from './utils/StringUtils'; import CreateCustomView from './views/CreateCustomView/CreateCustomView'; diff --git a/src/allGames.ts b/src/allGames.ts index 02b908d..24fb8eb 100644 --- a/src/allGames.ts +++ b/src/allGames.ts @@ -10,7 +10,7 @@ import Wizard from './games/wizard/main'; import Wingspan from './games/wingspan/main'; import ForestShuffle from './games/forest-shuffle/main'; -export default function getAllGames() { +export function getAllGames() { return [ Everdell, Calico, @@ -25,3 +25,14 @@ export default function getAllGames() { ForestShuffle, ]; } + +export function getSortedGames() { + const games = getAllGames(); + games.sort((a, b) => a.definition.title.localeCompare(b.definition.title)); + return games; +} + +export function getSortedGameNames(): string[] { + const games = getSortedGames(); + return games.map((game) => game.definition.title); +} diff --git a/src/components/FavoriteGameSection/FavoriteGameSection.scss b/src/components/FavoriteGameSection/FavoriteGameSection.scss new file mode 100644 index 0000000..f4e38cf --- /dev/null +++ b/src/components/FavoriteGameSection/FavoriteGameSection.scss @@ -0,0 +1,3 @@ +.btn-template { + border: 2px dashed var(--font-color); +} diff --git a/src/components/FavoriteGameSection/FavoriteGameSection.tsx b/src/components/FavoriteGameSection/FavoriteGameSection.tsx new file mode 100644 index 0000000..67758b7 --- /dev/null +++ b/src/components/FavoriteGameSection/FavoriteGameSection.tsx @@ -0,0 +1,77 @@ +import { useState } from 'react'; +import './FavoriteGameSection.scss'; +import { getSortedGameNames } from '../../allGames'; +import LocalStorageService from '../../utils/LocalStorageService'; +import GameButton from '../GameButton/GameButton'; + +/** + * This is a FavoriteGameSection component + * @author cophilot + * @version 1.0.0 + * @created 2024-8-7 + */ +function FavoriteGameSection() { + const [addingMode, setAddingMode] = useState(false); + const [favoriteGames, setFavoriteGamesInternal] = useState( + LocalStorageService.getFavoriteGames() + ); + const games = getSortedGameNames(); + + const setFavoriteGames = (favoriteGames: string[]) => { + setFavoriteGamesInternal(favoriteGames); + LocalStorageService.setFavoriteGames(favoriteGames); + }; + + const templateButtonStyle = { border: '2px dashed var(--font-color)' }; + + const onGameClick = (game: string) => { + if (addingMode) { + if (favoriteGames.includes(game)) { + setFavoriteGames(favoriteGames.filter((g) => g !== game)); + } else { + setFavoriteGames([...favoriteGames, game]); + } + } + }; + + return ( +
+ {addingMode + ? games.map((game) => ( + + )) + : favoriteGames.map((game) => ( + + ))} + setAddingMode(!addingMode)}> +
+ ); +} +export default FavoriteGameSection; + +function getIconClassName(addingMode: boolean, favoriteGames: string[]) { + if (addingMode) { + return 'bi-check-lg'; + } + if (favoriteGames.length === 0) { + return 'bi-plus-circle'; + } + return 'bi-pencil-square'; +} diff --git a/src/components/GameButton/GameButton.scss b/src/components/GameButton/GameButton.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/components/GameButton/GameButton.tsx b/src/components/GameButton/GameButton.tsx new file mode 100644 index 0000000..9c7b019 --- /dev/null +++ b/src/components/GameButton/GameButton.tsx @@ -0,0 +1,43 @@ +import { useNavigate } from 'react-router-dom'; +import './GameButton.scss'; +import StringUtils from '../../utils/StringUtils'; + +interface GameButtonProps { + game: string; + asLink?: boolean; + link?: string; +} + +/** + * This is a GameButton component + * @author cophilot + * @version 1.0.0 + * @created 2024-8-7 + */ +function GameButton({ game, asLink = false, link = '' }: GameButtonProps) { + const navigate = useNavigate(); + + if (asLink) { + return ( +
+ + {game} + +
+ ); + } + return ( + + ); +} +export default GameButton; diff --git a/src/index.scss b/src/index.scss index cb22e12..9c4fdd2 100644 --- a/src/index.scss +++ b/src/index.scss @@ -133,3 +133,9 @@ a { .imp { color: var(--primary-color); } + +.icon { + font-size: 30px; + margin: 10px; + cursor: pointer; +} diff --git a/src/utils/LocalStorageService.ts b/src/utils/LocalStorageService.ts new file mode 100644 index 0000000..fad442c --- /dev/null +++ b/src/utils/LocalStorageService.ts @@ -0,0 +1,20 @@ +export default class LocalStorageService { + private static FAVORITE_GAMES_KEY = 'bsh-favorite-games'; + + static getFavoriteGames() { + const favoriteGames = localStorage.getItem( + LocalStorageService.FAVORITE_GAMES_KEY + ); + if (favoriteGames === null) { + return []; + } + return JSON.parse(favoriteGames); + } + + static setFavoriteGames(favoriteGames: string[]) { + localStorage.setItem( + LocalStorageService.FAVORITE_GAMES_KEY, + JSON.stringify(favoriteGames) + ); + } +} diff --git a/src/views/HomeView.tsx b/src/views/HomeView.tsx index 9daac25..c58367b 100644 --- a/src/views/HomeView.tsx +++ b/src/views/HomeView.tsx @@ -1,11 +1,12 @@ import { useEffect } from 'react'; import StyleUtils from '../api/utils/StyleUtils'; import { useNavigate } from 'react-router-dom'; -import StringUtils from '../utils/StringUtils'; import By from '../components/By'; -import getAllGames from '../allGames'; +import { getSortedGameNames } from '../allGames'; import Logo from '../components/Logo'; import DevMessage from '../components/DevMessage'; +import GameButton from '../components/GameButton/GameButton'; +import FavoriteGameSection from '../components/FavoriteGameSection/FavoriteGameSection'; export default function HomeView() { const navigate = useNavigate(); @@ -14,8 +15,7 @@ export default function HomeView() { document.title = 'BoardScoreHub'; }, []); - const games = getAllGames().map((game) => game.definition.title); - games.sort((a, b) => a.localeCompare(b)); + const games = getSortedGameNames(); return (
@@ -32,10 +32,12 @@ export default function HomeView() { {/* */}
+

Favorites

+

Games

{games.map((game) => ( - + ))}

@@ -50,7 +52,11 @@ export default function HomeView() {

External

- +

Custom

@@ -67,31 +73,3 @@ export default function HomeView() {
); } - -function LinkGameButton({ game }: { game: string }) { - const navigate = useNavigate(); - if (game.includes('$x$')) { - const [name, link] = game.split('$x$'); - return ( -
- - {name} - -
- ); - } - - return ( - - ); -}