components#PokemonType TypeScript Examples
The following examples show how to use
components#PokemonType.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: PokemonSlot.tsx From nuzlocke with BSD 3-Clause "New" or "Revised" License | 6 votes |
function PokemonSlot({ pokemon }: PokemonSlotProps): JSX.Element {
return (
<div className={styles.selector} style={{ backgroundColor: `${TYPE_COLOR[pokemon?.type]}50` }}>
<div className={styles.info}>
<div className={styles.image}>
<PkmImage name={pokemon?.text} />
</div>
<span>{pokemon?.text}</span>
</div>
<PokemonType pokemon={pokemon} />
</div>
);
}
Example #2
Source File: DetailSelector.tsx From nuzlocke with BSD 3-Clause "New" or "Revised" License | 4 votes |
function DetailSelector({
children,
details,
handleDetail,
limitGen,
}: DetailSelectorProps): JSX.Element {
const { t } = useTranslation('common');
const [open, setOpen] = useState(false);
const itemSize = useRemtoPx();
const values = useFilter();
const filteredEncounters = details?.filter((p) => {
const foundPokemon = POKEMAP.get(p.id);
return (
foundPokemon?.text.toUpperCase().includes(values.search) &&
(limitGen ? foundPokemon.generation <= limitGen : true) &&
(values.gens.length > 0 ? values.gens.includes(foundPokemon.generation) : true) &&
(values.types.length > 0
? values.types.includes(foundPokemon.type) || values.types.includes(foundPokemon?.dualtype)
: true)
);
});
const handleClick = (detail: PokemonDetail) => {
handleDetail(detail);
values.reset();
setOpen(false);
};
const handleClose = () => {
values.reset();
setOpen(false);
};
const renderRow: React.FC<RowProps> = ({ index, style }) => {
const detail = filteredEncounters[index];
const foundPokemon = POKEMAP.get(detail.id);
return (
<div className={styles.rowContainer} style={style}>
<div
className={styles.row}
data-testid={`poke-${foundPokemon.text}`}
onClick={() => handleClick(detail)}
role="presentation"
style={{ backgroundColor: `${TYPE_COLOR[foundPokemon.type]}50` }}
>
<div className={styles.details}>
<div className={styles.image}>
<PkmImage name={foundPokemon?.text} shiny={detail?.shiny} />
</div>
<b>{foundPokemon.text}</b>
</div>
<PokemonType pokemon={foundPokemon} />
</div>
</div>
);
};
return (
<Modal
closeOnDimmerClick
open={open}
trigger={
<div onClick={() => setOpen(true)} role="presentation">
{children}
</div>
}
>
<Modal.Content className={styles.content} scrolling>
<Filter hideGen={!!limitGen} values={values} />
{/* @ts-ignore */}
<FixedSizeList
height={400}
itemCount={filteredEncounters?.length ?? 0}
itemSize={itemSize}
width="100%"
>
{renderRow}
</FixedSizeList>
</Modal.Content>
<Modal.Actions>
<Button onClick={handleClose}>{t('cancel', { ns: 'common' })}</Button>
</Modal.Actions>
</Modal>
);
}
Example #3
Source File: EncounterSelector.tsx From nuzlocke with BSD 3-Clause "New" or "Revised" License | 4 votes |
function EncounterSelector({
children,
encounters,
handleEncounter,
limitGen,
}: EncounterSelectorProps): JSX.Element {
const { t } = useTranslation('common');
const [open, setOpen] = useState(false);
const itemSize = useRemtoPx();
const values = useFilter();
const filteredEncounters = encounters.filter((p) => {
const foundPokemon = POKEMAP.get(p.pokemon);
return (
foundPokemon?.text.toUpperCase().includes(values.search) &&
(limitGen ? foundPokemon.generation <= limitGen : true) &&
(values.gens.length > 0 ? values.gens.includes(foundPokemon.generation) : true) &&
(values.types.length > 0
? values.types.includes(foundPokemon.type) || values.types.includes(foundPokemon?.dualtype)
: true)
);
});
const handleClick = (encounter: TEncounter) => {
handleEncounter(encounter);
values.reset();
setOpen(false);
};
const handleClose = () => {
values.reset();
setOpen(false);
};
const renderRow: React.FC<RowProps> = ({ index, style }) => {
const encounter = filteredEncounters[index];
const foundPokemon = POKEMAP.get(encounter.pokemon);
return (
<div className={styles.rowContainer} style={style}>
<div
className={styles.row}
data-testid={`poke-${foundPokemon.text}`}
onClick={() => handleClick(encounter)}
role="presentation"
style={{ backgroundColor: `${TYPE_COLOR[foundPokemon.type]}50` }}
>
<div className={styles.details}>
<div className={styles.image}>
<PkmImage name={foundPokemon?.text} />
</div>
<b>{encounter.nickname || foundPokemon.text}</b>
</div>
<PokemonType pokemon={foundPokemon} />
</div>
</div>
);
};
return (
<Modal
closeOnDimmerClick
open={open}
trigger={
<div onClick={() => setOpen(true)} role="presentation">
{children}
</div>
}
>
<Modal.Content className={styles.content} scrolling>
<Filter hideGen={!!limitGen} values={values} />
{/* @ts-ignore */}
<FixedSizeList
height={400}
itemCount={filteredEncounters.length}
itemSize={itemSize}
width="100%"
>
{renderRow}
</FixedSizeList>
</Modal.Content>
<Modal.Actions>
<Button onClick={handleClose}>{t('cancel', { ns: 'common' })}</Button>
</Modal.Actions>
</Modal>
);
}
Example #4
Source File: PokemonSelector.tsx From nuzlocke with BSD 3-Clause "New" or "Revised" License | 4 votes |
function PokemonSelector({
children,
dupes,
filter = false,
handlePokemon,
limitGen,
suggestions,
tooltip = false,
}: PokemonSelectorProps): JSX.Element {
const { t } = useTranslation('common');
const [open, setOpen] = useState(false);
const values = useFilter();
const itemSize = useRemtoPx();
const toggleShowAllTooltip = useStore(useCallback((state) => state.toggleShowAllTooltip, []));
const filteredPokemon = useMemo(() => {
let filtered = POKEMON.filter(
(p) =>
(typeof filter === 'boolean' ? true : filter.includes(p.value)) &&
p.text.toUpperCase().includes(values.search) &&
(limitGen ? p.generation <= limitGen : true) &&
(values.gens.length > 0 ? values.gens.includes(p.generation) : true) &&
(values.types.length > 0
? values.types.includes(p.type) || values.types.includes(p?.dualtype)
: true)
);
if (suggestions) {
filtered = filtered.sort(
(a, b) =>
Number(suggestions.includes(b.type) || suggestions.includes(b.dualtype)) -
Number(suggestions.includes(a.type) || suggestions.includes(a.dualtype))
);
}
return filtered;
}, [filter, suggestions, limitGen, values]);
const handleClick = (pokemonId: number) => {
handlePokemon(pokemonId);
values.reset();
setOpen(false);
};
const onKeyPress = (e: React.KeyboardEvent<HTMLDivElement>) => {
if (e.key === 'Enter' || e.key === ' ') setOpen(true);
};
const handleClose = () => {
values.reset();
setOpen(false);
};
const renderRow: React.FC<RowProps> = ({ index, style }) => {
const pokemon = filteredPokemon[index];
const dupe = pokemon?.evolve
? pokemon.evolve.some((evoId) => dupes?.includes(evoId))
: dupes?.includes(pokemon?.value);
return (
<div className={styles.rowContainer} style={style}>
<div
className={`${styles.row} ${dupe ? styles.dupe : ''}`}
data-testid={`poke-${pokemon.text}`}
onClick={() => handleClick(pokemon.value)}
role="presentation"
style={{ backgroundColor: `${TYPE_COLOR[pokemon.type]}50` }}
>
{suggestions &&
!dupe &&
(suggestions.includes(pokemon.type) || suggestions.includes(pokemon.dualtype)) && (
<div className={styles.suggestion}>
<Icon name="star" />
<span>{t('suggested')}</span>
</div>
)}
{dupe && (
<span className={styles.suggestion} title={t('dupe_description')}>
DUPE
</span>
)}
<div className={styles.details}>
<div className={styles.image}>
<PkmImage name={pokemon?.text} />
</div>
<b>{pokemon.text}</b>
</div>
<PokemonType pokemon={pokemon} />
</div>
</div>
);
};
return (
<Modal
closeOnDimmerClick
open={open}
trigger={
<div
data-testid="pokemon-selector"
onClick={() => setOpen(true)}
onKeyPress={onKeyPress}
role="button"
tabIndex={0}
>
{children}
</div>
}
>
<Modal.Content className={styles.content} scrolling>
<Filter hideGen={!!limitGen} values={values} />
{tooltip && (
<aside className={styles.callout}>
<Icon name="lightbulb outline" />
<p>{t('show_all_tooltip')}</p>
<Button data-testid="remove-tooltip" type="button" icon onClick={toggleShowAllTooltip}>
<Icon className={styles.icon} name="close" />
</Button>
</aside>
)}
{/* @ts-ignore */}
<FixedSizeList
height={400}
itemCount={filteredPokemon.length}
itemSize={itemSize}
width="100%"
>
{renderRow}
</FixedSizeList>
</Modal.Content>
<Modal.Actions>
<Button onClick={handleClose}>{t('cancel')}</Button>
</Modal.Actions>
</Modal>
);
}
Example #5
Source File: BadgeDetail.tsx From nuzlocke with BSD 3-Clause "New" or "Revised" License | 4 votes |
function BadgeDetail({ selectedDetail }: BadgeDetailProps): JSX.Element {
const { t } = useTranslation('badges');
const [view, setView] = useState(0);
const selectedGame = useStore(useCallback((state) => state.selectedGame, []));
const darkMode = useStore(useCallback((state) => state.darkMode, []));
const isSplit = !PHYS_SPEC_SPLIT.includes(selectedGame?.value);
const colors = darkMode ? D_STAT_COLOR : STAT_COLOR;
const getContent = () => {
if (!!selectedDetail?.rematch && view === 1) {
return selectedDetail.rematch;
}
return selectedDetail?.content;
};
return (
<>
<div className={styles.title}>{selectedDetail?.name}</div>
{selectedDetail?.type === 'REMATCH' && (
<div className={styles.rematch}>
<Radio
checked={view === 0}
label={t('original')}
onChange={(e: React.FormEvent<HTMLInputElement>, data: CheckboxProps) =>
setView(data.value as number)
}
value={0}
/>
<Radio
checked={view === 1}
label={t('rematch')}
onChange={(e: React.FormEvent<HTMLInputElement>, data: CheckboxProps) =>
setView(data.value as number)
}
value={1}
/>
</div>
)}
<div className={styles.gymPokemon}>
{getContent()?.map((pokemon, ind) => {
const poke = POKEMAP.get(pokemon.id);
let stats = undefined;
try {
stats = new Pokemon(GAME_GENERATION[selectedGame?.value], getSmogonName(poke.text), {
level: pokemon?.level,
});
} catch {
// do nothing
}
return (
<div
className={styles.pokemon}
key={`pokemon-${pokemon.id}-${ind + 1}`}
style={{ border: `2px solid ${TYPE_COLOR[poke?.type]}` }}
>
<div className={styles.pokemonHeader}>
<div className={styles.pokemonName}>
{selectedDetail?.type === 'TRIAL' && ind === 0 && (
<span className={styles.totem}>TOTEM</span>
)}
{selectedDetail?.type === 'DYNAMAX' &&
ind === (selectedDetail?.content?.length ?? 0) - 1 && (
<span className={styles.totem}>DYNAMAX</span>
)}
<div className={styles.pokemonImage}>
<PkmImage name={poke?.text} />
</div>
<span>{poke?.text}</span>
<span>Lv. {pokemon?.level}</span>
</div>
<div className={styles.pokemonDetails}>
<PokemonType pokemon={poke} />
{!!pokemon?.ability && (
<div className={styles.pokemonLabel}>
<span>{t('ability')}:</span>
<span className={styles.value}>{pokemon?.ability}</span>
</div>
)}
{!!pokemon?.item && (
<div className={styles.pokemonLabel}>
<span>{t('item')}:</span>
<div className={styles.item}>
<span className={styles.value}>{pokemon?.item}</span>
<div className="pkitem-wrapper">
<div className={`pkitem pkitem-${getSmogonItemName(pokemon?.item)}`} />
</div>
</div>
</div>
)}
</div>
</div>
<div className={styles.extendedDetails}>
{stats?.stats && (
<div className={styles.stats}>
{Object.entries(stats.stats).map(([key, value]) => (
<React.Fragment key={`${key}-${value}`}>
<span className={styles.statLabel}>{t(key)}:</span>
<span style={{ color: colors[key][0] }}>{value}</span>
<div
className={styles.statBar}
style={{
width: `${(value / 450) * 100}%`,
backgroundColor: colors[key][0],
border: `1px solid ${colors[key][1]}`,
}}
/>
</React.Fragment>
))}
</div>
)}
<Moves moves={pokemon?.moves} showStatus={isSplit} />
</div>
</div>
);
})}
</div>
</>
);
}
Example #6
Source File: Member.tsx From nuzlocke with BSD 3-Clause "New" or "Revised" License | 4 votes |
function Member({ index, pokemonDetail }: MemberProps): JSX.Element {
const { t } = useTranslation('builder');
const pokemon = POKEMAP.get(pokemonDetail.id);
const changeTeamMember = useStore(useCallback((state) => state.changeTeamMember, []));
const deleteTeamMember = useStore(useCallback((state) => state.deleteTeamMember, []));
const darkMode = useStore(useCallback((state) => state.darkMode, []));
const [expanded, setExpanded] = useState(false);
return (
<>
<div
className={styles.member}
data-testid={`team-poke-${pokemon.text}`}
style={{ backgroundColor: `${TYPE_COLOR[pokemon.type]}50` }}
>
<div className={styles.info}>
<div className={styles.pokemonImage}>
<PkmImage name={pokemon?.text} />
</div>
<b>{pokemon.text}</b>
</div>
<div className={styles.other}>
<PokemonType pokemon={pokemon} />
<Icon
className={styles.arrow}
style={{ transform: expanded ? 'rotate(90deg)' : undefined }}
name="angle right"
onClick={() => setExpanded((prevState) => !prevState)}
/>
</div>
</div>
<div className={`${styles.details} ${expanded ? styles.open : ''}`}>
<div>
<Dropdown
aria-label="nature-selector"
basic
className={`${dropdownStyles.dropdown} ${styles.nature}`}
data-testid={`team-nature-${pokemon?.text}`}
inline
lazyLoad
onChange={(e, data) =>
changeTeamMember(index, { ...pokemonDetail, nature: data.value as unknown as string })
}
options={NATURES}
placeholder={t('select_nature', { ns: 'calculator' })}
search
selection
value={pokemonDetail.nature ?? ''}
/>
<Natures />
</div>
<Dropdown
aria-label="ability"
basic
className={dropdownStyles.dropdown}
data-testid={`team-ability-${pokemon?.text}`}
inline
lazyLoad
onChange={(e, data) =>
changeTeamMember(index, { ...pokemonDetail, ability: data.value as string })
}
options={[...new Set(ABILITIES[8])].map((smogonAbility) => {
return { text: smogonAbility, value: smogonAbility };
})}
placeholder={t('select_ability', { ns: 'calculator' })}
search
selection
value={pokemonDetail.ability ?? ''}
/>
<ItemSelector
dataTestId={`team-item-${pokemon?.text}`}
item={pokemonDetail.item}
onChange={(newItem) => changeTeamMember(index, { ...pokemonDetail, item: newItem })}
/>
<MoveSelector
currentMoveId={pokemonDetail?.moves?.length > 0 ? pokemonDetail.moves[0] : null}
handleMove={(moveId: number) =>
changeTeamMember(index, {
...pokemonDetail,
moves: [
moveId,
pokemonDetail.moves[1],
pokemonDetail.moves[2],
pokemonDetail.moves[3],
],
})
}
/>
<MoveSelector
currentMoveId={pokemonDetail?.moves?.length > 1 ? pokemonDetail.moves[1] : null}
handleMove={(moveId: number) =>
changeTeamMember(index, {
...pokemonDetail,
moves: [
pokemonDetail.moves[0],
moveId,
pokemonDetail.moves[2],
pokemonDetail.moves[3],
],
})
}
/>
<MoveSelector
currentMoveId={pokemonDetail?.moves?.length > 2 ? pokemonDetail.moves[2] : null}
handleMove={(moveId: number) =>
changeTeamMember(index, {
...pokemonDetail,
moves: [
pokemonDetail.moves[0],
pokemonDetail.moves[1],
moveId,
pokemonDetail.moves[3],
],
})
}
/>
<MoveSelector
currentMoveId={pokemonDetail?.moves?.length > 3 ? pokemonDetail.moves[3] : null}
handleMove={(moveId: number) =>
changeTeamMember(index, {
...pokemonDetail,
moves: [
pokemonDetail.moves[0],
pokemonDetail.moves[1],
pokemonDetail.moves[2],
moveId,
],
})
}
/>
<Button
className={styles.delete}
color="red"
data-testid={`delete-team-${index}`}
inverted={darkMode}
onClick={() => deleteTeamMember(index)}
>
{t('delete')}
<Icon className="icon close" />
</Button>
</div>
</>
);
}
Example #7
Source File: Detail.tsx From nuzlocke with BSD 3-Clause "New" or "Revised" License | 4 votes |
function Detail({ encounter }: DetailProps): JSX.Element {
const { t } = useTranslation('tracker');
const darkMode = useStore(useCallback((state) => state.darkMode, []));
const changeDetails = useStore(useCallback((state) => state.changeDetails, []));
const exportTeamMember = useStore(useCallback((state) => state.exportTeamMember, []));
const exportToGame = useStore(useCallback((state) => state.exportToGame, []));
const selectedGame = useStore(useCallback((state) => state.selectedGame, []));
const gamesList = useStore(useCallback((state) => state.gamesList, []));
const soulink = useStore(useCallback((state) => state.soulink, []));
const isNatureAbilityGen = useStore(selectNAGeneration);
const isItemGenderGen = useStore(selectItemGeneration);
const foundPokemon = POKEMAP.get(encounter.pokemon);
const [show, setShow] = useState(false);
const [level, setLevel] = useState(encounter?.details?.level);
const [metLevel, setMetLevel] = useState(encounter?.details?.metLevel);
const [gender, setGender] = useState(encounter?.details?.gender);
const [ability, setAbility] = useState(encounter?.details?.ability);
const [nature, setNature] = useState(encounter?.details?.nature);
const [item, setItem] = useState(encounter?.details?.item);
const [faint, setFaint] = useState(encounter?.details?.faint);
const [moveOne, setMoveOne] = useState(encounter?.details?.moves[0]);
const [moveTwo, setMoveTwo] = useState(encounter?.details?.moves[1]);
const [moveThree, setMoveThree] = useState(encounter?.details?.moves[2]);
const [moveFour, setMoveFour] = useState(encounter?.details?.moves[3]);
const [shiny, setShiny] = useState(encounter?.details?.shiny);
const [ivhp, setIvhp] = useState(encounter?.details?.ivhp);
const [ivatk, setIvatk] = useState(encounter?.details?.ivatk);
const [ivdef, setIvdef] = useState(encounter?.details?.ivdef);
const [ivspatk, setIvspatk] = useState(encounter?.details?.ivspatk);
const [ivspeed, setIvspeed] = useState(encounter?.details?.ivspeed);
const [ivspdef, setIvspdef] = useState(encounter?.details?.ivspdef);
const [evhp, setEvhp] = useState(encounter?.details?.evhp);
const [evatk, setEvatk] = useState(encounter?.details?.evatk);
const [evdef, setEvdef] = useState(encounter?.details?.evdef);
const [evspatk, setEvspatk] = useState(encounter?.details?.evspatk);
const [evspeed, setEvspeed] = useState(encounter?.details?.evspeed);
const [evspdef, setEvspdef] = useState(encounter?.details?.evspdef);
const [soulLink, setSoulLink] = useState(encounter?.details?.soulink);
const limitGen = GAME_GENERATION[selectedGame?.value] || undefined;
const foundSoulLink = POKEMAP.get(soulLink);
const handleClose = () => {
setShow(false);
setLevel(encounter?.details?.level);
setMetLevel(encounter?.details?.metLevel);
setGender(encounter?.details?.gender);
setAbility(encounter?.details?.ability);
setNature(encounter?.details?.nature);
setItem(encounter?.details?.item);
setFaint(encounter?.details?.faint);
setMoveOne(encounter?.details?.moves[0]);
setMoveTwo(encounter?.details?.moves[1]);
setMoveThree(encounter?.details?.moves[2]);
setMoveFour(encounter?.details?.moves[3]);
setShiny(encounter?.details?.shiny);
setSoulLink(encounter?.details?.soulink);
};
const handleSave = () => {
changeDetails(
encounter.id,
level,
metLevel,
gender,
ability,
nature,
item,
faint,
moveOne,
moveTwo,
moveThree,
moveFour,
shiny,
ivhp,
ivatk,
ivdef,
ivspatk,
ivspdef,
ivspeed,
evhp,
evatk,
evdef,
evspatk,
evspdef,
evspeed,
soulLink
);
setShow(false);
};
const handleExport = () => {
exportTeamMember({
ability,
id: encounter.pokemon,
level,
item,
nature,
moves: [moveOne, moveTwo, moveThree, moveFour],
});
toast.success(t('pokemon_export'));
};
const handleGameExport = (game: string) => {
if (game !== selectedGame?.value) {
exportToGame(encounter, game, `From ${selectedGame?.text} - ${new Date().toLocaleString()}`);
handleClose();
toast.success(t('pokemon_export'));
}
};
const handleDeleteSoulLink = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
e.preventDefault();
e.stopPropagation();
setSoulLink(null);
};
return (
<Modal
open={show}
trigger={
<Button
aria-label="edit encounter"
basic
compact
data-testid={`edit-encounter-${encounter.id}`}
icon
inverted={darkMode}
onClick={() => setShow(true)}
type="button"
>
<Icon name="pencil" />
</Button>
}
>
<Modal.Content className={styles.content} scrolling>
<div className={styles.header}>
<div className={styles.headerLeft}>
<div className={styles.image}>
<PkmImage name={foundPokemon?.text} shiny={shiny} />
</div>
<span className={styles.name}>{foundPokemon.text}</span>
</div>
<PokemonType pokemon={foundPokemon} />
</div>
{soulink && (
<div className={styles.soulink}>
<span>Soul Link Pokémon:</span>
<PokemonSelector handlePokemon={(pokemonId) => setSoulLink(pokemonId)}>
{soulLink ? (
<div className={styles.selector} data-testid={`soullink-${encounter.id}`}>
<div className={styles.image}>
<PkmImage name={foundSoulLink.text} />
</div>
<span className={styles.soulLinkName}>{foundSoulLink.text}</span>
<Button
aria-label="delete-soullink"
className={styles.deleteSoullink}
data-testid={`delete-soullink-${encounter.id}`}
icon
onClick={handleDeleteSoulLink}
style={{ boxShadow: 'none' }}
>
<Icon name="trash" />
</Button>
</div>
) : (
<div className={styles.selector} data-testid={`soullink-${encounter.id}`}>
<span
data-testid={`soullink-empty-${encounter.id}`}
className={styles.placeholder}
>
Pokémon...
</span>
</div>
)}
</PokemonSelector>
</div>
)}
<details open>
<summary data-testid="detail-summary">{t('details', { ns: 'badges' })}</summary>
<div className={styles.expandable}>
<Input
className={styles.input}
data-testid="level"
maxLength={3}
label={t('level', { ns: 'rules' })}
onChange={(e, data) => setLevel(Number(data.value))}
value={Number.isNaN(level) ? '' : level}
/>
<Input
className={styles.input}
data-testid="metlevel"
label={t('met_level')}
maxLength={3}
onChange={(e, data) => setMetLevel(Number(data.value))}
value={Number.isNaN(metLevel) ? '' : metLevel}
/>
{isItemGenderGen && (
<Dropdown
aria-label="gender-selector"
className={dropdownStyles.dropdown}
clearable
data-testid="gender"
inline
lazyLoad
onChange={(e, data) => setGender(data.value as unknown as Gender)}
options={GENDERS}
placeholder={t('gender', { ns: 'calculator' })}
selection
value={gender ?? ''}
/>
)}
{isNatureAbilityGen && (
<div className={styles.natureContainer}>
<Dropdown
aria-label="nature-selector"
className={dropdownStyles.dropdown}
clearable
data-testid="nature"
inline
lazyLoad
onChange={(e, data) => setNature(data.value as unknown as string)}
options={NATURES}
placeholder={t('select_nature', { ns: 'calculator' })}
search
selection
value={nature ?? ''}
/>
<Natures />
</div>
)}
{isNatureAbilityGen && (
<div className={styles.natureContainer}>
<Dropdown
aria-label="ability"
className={dropdownStyles.dropdown}
clearable
data-testid="ability"
inline
lazyLoad
onChange={(e, data) => setAbility(data.value as unknown as string)}
options={[...new Set(ABILITIES[8])].map((smogonAbility) => {
return { text: smogonAbility, value: smogonAbility };
})}
placeholder={t('select_ability', { ns: 'calculator' })}
search
selection
value={ability ?? ''}
/>
<Abilities text={ability ?? ''} />
</div>
)}
{isItemGenderGen && (
<ItemSelector item={item} onChange={(newItem) => setItem(newItem)} />
)}
<Checkbox
checked={shiny}
className={styles.checkbox}
data-testid="shiny"
label="Shiny"
onChange={(e, data) => setShiny(data.checked)}
/>
</div>
</details>
<details className={styles.expandable}>
<summary data-testid="move-summary">Moves</summary>
<div className={styles.expandable}>
<div data-testid="move-1">
<span>Move 1:</span>
<MoveSelector
currentMoveId={moveOne}
handleMove={(moveId: number) => setMoveOne(moveId)}
limitGen={limitGen}
/>
</div>
<div data-testid="move-2">
<span>Move 2:</span>
<MoveSelector
currentMoveId={moveTwo}
handleMove={(moveId: number) => setMoveTwo(moveId)}
limitGen={limitGen}
/>
</div>
<div data-testid="move-3">
<span>Move 3:</span>
<MoveSelector
currentMoveId={moveThree}
handleMove={(moveId: number) => setMoveThree(moveId)}
limitGen={limitGen}
/>
</div>
<div data-testid="move-4">
<span>Move 4:</span>
<MoveSelector
currentMoveId={moveFour}
handleMove={(moveId: number) => setMoveFour(moveId)}
limitGen={limitGen}
/>
</div>
</div>
</details>
<details
className={styles.expandable}
style={{ display: limitGen > 2 ? undefined : 'none' }}
>
<summary data-testid="stats-summary">Stats</summary>
<div className={styles.expandable}>
HP:
<fieldset className={styles.fieldset}>
<RangeSelector
name="ivhp"
value={ivhp ?? 0}
onChange={(newValue: number) => setIvhp(newValue)}
/>
<RangeSelector
name="evhp"
value={evhp ?? 0}
onChange={(newValue: number) => setEvhp(newValue)}
/>
</fieldset>
ATK:
<fieldset className={styles.fieldset}>
<RangeSelector
name="ivatk"
value={ivatk ?? 0}
onChange={(newValue: number) => setIvatk(newValue)}
/>
<RangeSelector
name="evatk"
value={evatk ?? 0}
onChange={(newValue: number) => setEvatk(newValue)}
/>
</fieldset>
DEF:
<fieldset className={styles.fieldset}>
<RangeSelector
name="ivdef"
value={ivdef ?? 0}
onChange={(newValue: number) => setIvdef(newValue)}
/>
<RangeSelector
name="evdef"
value={evdef ?? 0}
onChange={(newValue: number) => setEvdef(newValue)}
/>
</fieldset>
SPATK:
<fieldset className={styles.fieldset}>
<RangeSelector
name="ivspatk"
value={ivspatk ?? 0}
onChange={(newValue: number) => setIvspatk(newValue)}
/>
<RangeSelector
name="evspatk"
value={evspatk ?? 0}
onChange={(newValue: number) => setEvspatk(newValue)}
/>
</fieldset>
SPDEF:
<fieldset className={styles.fieldset}>
<RangeSelector
name="ivspdef"
value={ivspdef ?? 0}
onChange={(newValue: number) => setIvspdef(newValue)}
/>
<RangeSelector
name="evspdef"
value={evspdef ?? 0}
onChange={(newValue: number) => setEvspdef(newValue)}
/>
</fieldset>
SPEED:
<fieldset className={styles.fieldset}>
<RangeSelector
name="ivspeed"
value={ivspeed ?? 0}
onChange={(newValue: number) => setIvspeed(newValue)}
/>
<RangeSelector
name="evspeed"
value={evspeed ?? 0}
onChange={(newValue: number) => setEvspeed(newValue)}
/>
</fieldset>
</div>
</details>
{encounter?.status?.value === 2 && (
<label>
<div>{t('cause_of_fainting')}:</div>
<textarea
className={styles.textarea}
data-testid="cause of fainting"
maxLength={250}
onChange={(e) => setFaint(e.target.value)}
rows={5}
value={faint}
/>
</label>
)}
</Modal.Content>
<Modal.Actions>
<Button onClick={handleClose}>{t('cancel', { ns: 'common' })}</Button>
<Button onClick={handleExport}>{t('export_to_builder')}</Button>
<Dropdown
button
data-testid="export-to-game"
onChange={(e, data) => handleGameExport(data.value as string)}
options={gamesList}
text={t('export_to_game')}
value={selectedGame?.value}
/>
<Button onClick={handleSave} primary>
{t('save', { ns: 'common' })}
</Button>
</Modal.Actions>
</Modal>
);
}