nsaroiu's picture
Deploy 41a05c7
08b6c63 verified
Raw History Blame Contribute Delete
1.96 kB
import { useState } from 'react'
import type { CardSummary } from '../api'
import { findTypedCard } from '../lib/search'
import { CardSearch } from './CardSearch'
interface Props {
/** The commanders' combined color identity, e.g. "BG" ("" = colorless):
* suggestions stay within it. */
colors: string
disabled: boolean
/** Adds the card and returns what to tell the user. */
onAdd: (card: CardSummary) => string
}
// Search for a card and put it in the deck by hand. Suggestions only include
// cards the deck can legally hold (and basic lands).
export function AddCard({ colors, disabled, onAdd }: Props) {
const [query, setQuery] = useState('')
const [message, setMessage] = useState<string | null>(null)
const [adding, setAdding] = useState(false)
const add = (card: CardSummary) => {
setMessage(onAdd(card))
setQuery('')
}
// Same rule as the ban list: the typed text must name exactly one card.
const addTyped = async () => {
if (!query.trim() || disabled) return
setAdding(true)
setMessage(null)
const found = await findTypedCard(query, { colors, basics: true })
setAdding(false)
if ('card' in found) add(found.card)
else setMessage(found.message)
}
return (
<div className="add-card">
<div className="add-card-row">
<CardSearch
label="Add a card"
value={query}
onChange={(v) => {
setQuery(v)
setMessage(null)
}}
onSelect={(card) => !disabled && add(card)}
onEnter={addTyped}
colors={colors}
basics
placeholder="Search cards in your commander's colors"
/>
<button type="button" className="btn btn-secondary" onClick={addTyped} disabled={disabled || adding || !query.trim()}>
Add
</button>
</div>
<p className="hint add-card-message" role="status">
{message ?? ''}
</p>
</div>
)
}