diff --git a/src/components/common/CardDrawer.tsx b/src/components/common/CardDrawer.tsx index 51178b12..2598c64d 100644 --- a/src/components/common/CardDrawer.tsx +++ b/src/components/common/CardDrawer.tsx @@ -47,7 +47,7 @@ const CardDrawer = ({ open={open} onClose={onClose} sx={{ - "--Drawer-verticalSize": "min(571px, 65%)", + "--Drawer-verticalSize": "100%", }} > @@ -66,19 +66,21 @@ const CardDrawer = ({ )} - + {open && ( + + )} ); diff --git a/src/components/common/CardSelect.tsx b/src/components/common/CardSelect.tsx index 146005f8..1ae404b3 100644 --- a/src/components/common/CardSelect.tsx +++ b/src/components/common/CardSelect.tsx @@ -1,11 +1,14 @@ import * as _ from "lodash-es"; -import { useEffect } from "react"; +import { useEffect, useState } from "react"; import { FormattedMessage, useIntl } from "react-intl"; +import ClearIcon from "@mui/icons-material/Clear"; import EditIcon from "@mui/icons-material/Edit"; +import SearchIcon from "@mui/icons-material/Search"; import { Button, IconButton, + Input, List, ListItem, ListSubheader, @@ -108,8 +111,16 @@ const CardSelect = ({ }: CardSelectProps) => { const intl = useIntl(); + const [search, setSearch] = useState(""); + + const matchingCards = cards.filter((card) => + getLocalizedCardName(intl, card.name) + ?.toLowerCase() + ?.includes(search.toLowerCase()), + ); + const cardNameOptions = getOptions( - cards, + matchingCards, (c) => c.name, (n) => getLocalizedCardName(intl, n) ?? n, ); @@ -190,6 +201,7 @@ const CardSelect = ({ }; const handleSelectCardName = (value: TCard) => { + handleClearSearch(); handleSelect(value.name); }; @@ -216,6 +228,17 @@ const CardSelect = ({ onGameBoxChange(undefined); }; + const handleClearSearch = () => { + setSearch(""); + }; + + const showSubheaders = + new Set( + cards + .flatMap((c) => c.types) + .filter((t) => !EXPANSION_CARD_TYPES.includes(t)), + ).size > 1; + return ( @@ -239,36 +262,70 @@ const CardSelect = ({ ) : ( - ({ - "--List-padding": 0, - "--ListItem-paddingX": 0, - "--ListItem-stickyTop": "-1px", - "--ListItem-stickyBackground": theme.palette.background.surface, - "flex": "1 1", - "overflowY": "auto", - })} - > - {sortedCardTypes.map((type) => ( - - {Object.keys(cardNameOptionsByType).length > 1 && ( - - {intl.formatMessage(CardTypeMessages[type].plural)} - - )} - {cardNameOptionsByType[type].map((card) => ( - - handleSelectCardName(card)} - /> - - ))} - - ))} - + + + {([placeholder]) => ( + } + endDecorator={ + search.length > 0 && ( + + + + ) + } + placeholder={placeholder as string} + onChange={(event) => setSearch(event.target.value)} + value={search} + /> + )} + + + {search.length > 0 && cardNameOptions.length === 0 && ( + + + + )} + + ({ + "--List-padding": 0, + "--ListItem-paddingX": 0, + "--ListItem-stickyTop": "-1px", + "--ListItem-stickyBackground": theme.palette.background.surface, + "flex": "1 1", + "overflowY": "auto", + })} + > + {sortedCardTypes.map((type) => ( + + {showSubheaders && ( + + {intl.formatMessage(CardTypeMessages[type].plural)} + + )} + {cardNameOptionsByType[type].map((card) => ( + + handleSelectCardName(card)} + /> + + ))} + + ))} + + )} {canSelectTreeSymbol && ( diff --git a/src/translations/de.json b/src/translations/de.json index 6199b591..c4e8fcee 100644 --- a/src/translations/de.json +++ b/src/translations/de.json @@ -161,6 +161,8 @@ "CardSelect.header.expansion": "Erweiterung", "CardSelect.header.treeSymbol": "Baumsymbol", "CardSelect.remove": "Karte entfernen", + "CardSelect.search.noResults": "Keine Karten mit diesem Namen gefunden.", + "CardSelect.search.placeholder": "Suche...", "CardTypes.Alps.plural": "Alpen", "CardTypes.Alps.singular": "Alpen", "CardTypes.Amphibian.plural": "Amphibien", diff --git a/src/translations/en.json b/src/translations/en.json index 036ee3aa..c298bcc5 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -161,6 +161,8 @@ "CardSelect.header.expansion": "Expansion", "CardSelect.header.treeSymbol": "Tree symbol", "CardSelect.remove": "Remove card", + "CardSelect.search.noResults": "No cards found with this name.", + "CardSelect.search.placeholder": "Search...", "CardTypes.Alps.plural": "Alps", "CardTypes.Alps.singular": "Alps", "CardTypes.Amphibian.plural": "Amphibians", diff --git a/src/translations/nl.json b/src/translations/nl.json index 4b0630ef..c453af18 100644 --- a/src/translations/nl.json +++ b/src/translations/nl.json @@ -161,6 +161,8 @@ "CardSelect.header.expansion": "Uitbreiding", "CardSelect.header.treeSymbol": "Boom Symbool", "CardSelect.remove": "Kaart verwijderen", + "CardSelect.search.noResults": "Geen kaarten gevonden met deze naam.", + "CardSelect.search.placeholder": "Zoeken...", "CardTypes.Alps.plural": "Alpen", "CardTypes.Alps.singular": "Alp", "CardTypes.Amphibian.plural": "Amfibieën", diff --git a/src/translations/pt-br.json b/src/translations/pt-br.json index b32f4ad8..38b853c9 100644 --- a/src/translations/pt-br.json +++ b/src/translations/pt-br.json @@ -161,6 +161,8 @@ "CardSelect.header.expansion": "Expansão", "CardSelect.header.treeSymbol": "Símbolo de árvore", "CardSelect.remove": "Remover carta", + "CardSelect.search.noResults": "Nenhuma carta encontrada com esse nome.", + "CardSelect.search.placeholder": "Pesquisar...", "CardTypes.Alps.plural": "Alpes", "CardTypes.Alps.singular": "Alpes", "CardTypes.Amphibian.plural": "Anfíbios",