Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 16 additions & 14 deletions src/components/common/CardDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const CardDrawer = <TCard extends Card>({
open={open}
onClose={onClose}
sx={{
"--Drawer-verticalSize": "min(571px, 65%)",
"--Drawer-verticalSize": "100%",
}}
>
<ModalClose />
Expand All @@ -66,19 +66,21 @@ const CardDrawer = <TCard extends Card>({
)}
</DialogTitle>
<DialogContent sx={{ m: 1.5 }}>
<CardSelect
sx={{ height: "100%" }}
cards={cards}
cardName={cardName}
onCardNameChange={setCardName}
gameBox={gameBox}
onGameBoxChange={setGameBox}
treeSymbol={treeSymbol}
onTreeSymbolChange={setTreeSymbol}
onSelect={onSelectCard}
canRemove={!!selectedCard}
onRemove={onRemoveCard}
/>
{open && (
<CardSelect
sx={{ height: "100%" }}
cards={cards}
cardName={cardName}
onCardNameChange={setCardName}
gameBox={gameBox}
onGameBoxChange={setGameBox}
treeSymbol={treeSymbol}
onTreeSymbolChange={setTreeSymbol}
onSelect={onSelectCard}
canRemove={!!selectedCard}
onRemove={onRemoveCard}
/>
)}
</DialogContent>
</ResponsiveDrawer>
);
Expand Down
121 changes: 89 additions & 32 deletions src/components/common/CardSelect.tsx
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -108,8 +111,16 @@ const CardSelect = <TCard extends Card>({
}: CardSelectProps<TCard>) => {
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,
);
Expand Down Expand Up @@ -190,6 +201,7 @@ const CardSelect = <TCard extends Card>({
};

const handleSelectCardName = (value: TCard) => {
handleClearSearch();
handleSelect(value.name);
};

Expand All @@ -216,6 +228,17 @@ const CardSelect = <TCard extends Card>({
onGameBoxChange(undefined);
};

const handleClearSearch = () => {
setSearch("");
};

const showSubheaders =
new Set(
cards
.flatMap((c) => c.types)
.filter((t) => !EXPANSION_CARD_TYPES.includes(t)),
).size > 1;

return (
<Stack direction="column" gap={2} justifyContent="space-between" sx={sx}>
<Stack direction="column" gap={1} sx={{ flex: "1 1" }}>
Expand All @@ -239,36 +262,70 @@ const CardSelect = <TCard extends Card>({
</IconButton>
</Stack>
) : (
<List
sx={(theme) => ({
"--List-padding": 0,
"--ListItem-paddingX": 0,
"--ListItem-stickyTop": "-1px",
"--ListItem-stickyBackground": theme.palette.background.surface,
"flex": "1 1",
"overflowY": "auto",
})}
>
{sortedCardTypes.map((type) => (
<ListItem nested key={type}>
{Object.keys(cardNameOptionsByType).length > 1 && (
<ListSubheader sticky>
{intl.formatMessage(CardTypeMessages[type].plural)}
</ListSubheader>
)}
{cardNameOptionsByType[type].map((card) => (
<ListItem key={card.name}>
<CardButton
fullWidth
size="sm"
card={card}
onClick={() => handleSelectCardName(card)}
/>
</ListItem>
))}
</ListItem>
))}
</List>
<Stack direction="column" gap={1}>
<FormattedMessage
id="CardSelect.search.placeholder"
defaultMessage="Search..."
>
{([placeholder]) => (
<Input
autoFocus
fullWidth
startDecorator={<SearchIcon />}
endDecorator={
search.length > 0 && (
<IconButton size="sm" onClick={handleClearSearch}>
<ClearIcon />
</IconButton>
)
}
placeholder={placeholder as string}
onChange={(event) => setSearch(event.target.value)}
value={search}
/>
)}
</FormattedMessage>

{search.length > 0 && cardNameOptions.length === 0 && (
<Typography level="body-sm" sx={{ mt: 0.5 }}>
<FormattedMessage
id="CardSelect.search.noResults"
defaultMessage="No cards found with this name."
/>
</Typography>
)}

<List
sx={(theme) => ({
"--List-padding": 0,
"--ListItem-paddingX": 0,
"--ListItem-stickyTop": "-1px",
"--ListItem-stickyBackground": theme.palette.background.surface,
"flex": "1 1",
"overflowY": "auto",
})}
>
{sortedCardTypes.map((type) => (
<ListItem nested key={type}>
{showSubheaders && (
<ListSubheader sticky>
{intl.formatMessage(CardTypeMessages[type].plural)}
</ListSubheader>
)}
{cardNameOptionsByType[type].map((card) => (
<ListItem key={card.name}>
<CardButton
fullWidth
size="sm"
card={card}
onClick={() => handleSelectCardName(card)}
/>
</ListItem>
))}
</ListItem>
))}
</List>
</Stack>
)}

{canSelectTreeSymbol && (
Expand Down
2 changes: 2 additions & 0 deletions src/translations/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 2 additions & 0 deletions src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 2 additions & 0 deletions src/translations/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 2 additions & 0 deletions src/translations/pt-br.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Loading