``` ~/go/bin/sourcemapper -output ddb -jsurl https://media.dndbeyond.com/character-app/static/js/main.90aa78c5.js ```
94 lines
3.0 KiB
TypeScript
94 lines
3.0 KiB
TypeScript
import React, { useContext } from "react";
|
|
|
|
import { Select } from "@dndbeyond/character-components/es";
|
|
import { FeatList, FormatUtils } from "@dndbeyond/character-rules-engine";
|
|
|
|
import { Accordion } from "~/components/Accordion";
|
|
import { FeatDetail } from "~/subApps/sheet/components/Sidebar/panes/FeatsManagePane/FeatDetail";
|
|
import { CharacterFeaturesManagerContext } from "~/tools/js/Shared/managers/CharacterFeaturesManagerContext";
|
|
|
|
type GrantedFeatProps = {
|
|
featList: FeatList;
|
|
requiredLevel?: number;
|
|
};
|
|
|
|
export const GrantedFeat: React.FC<GrantedFeatProps> = ({
|
|
featList,
|
|
requiredLevel,
|
|
}) => {
|
|
const { characterFeaturesManager } = useContext(
|
|
CharacterFeaturesManagerContext
|
|
);
|
|
|
|
// Only show the Feat List section if there is something to show.
|
|
if (featList.isEmpty()) {
|
|
return null;
|
|
}
|
|
|
|
let featContent: React.ReactNode | undefined;
|
|
let selectBox: React.ReactNode | undefined;
|
|
let infoMessage: React.ReactNode | undefined;
|
|
let hasUnfinishedChoices = featList.hasChoiceToMake();
|
|
let subtitleItems = ["Granted Feat"];
|
|
|
|
// Show a message when the character already has every feat in the feat list from somewhere else.
|
|
if (featList.alreadyHasEveryFeat() && featList.chosenFeatId === null) {
|
|
infoMessage = <p>This feat already exists on your character.</p>;
|
|
} else {
|
|
// Show the feat details if a feat has been chosen from the feat list.
|
|
if (featList.chosenFeatId !== null) {
|
|
const featId = featList.chosenFeatId;
|
|
const featManager = characterFeaturesManager.getFeatById(featId);
|
|
|
|
if (featManager !== null) {
|
|
const needToChooseFeatOptions =
|
|
featManager.getUnfinishedChoices().length > 0;
|
|
hasUnfinishedChoices = hasUnfinishedChoices || needToChooseFeatOptions;
|
|
|
|
featContent = <FeatDetail featManager={featManager} />;
|
|
|
|
if (featManager.isHiddenFeat()) {
|
|
subtitleItems = []; // don't call it a feat if it isn't really a feat.
|
|
}
|
|
|
|
const choiceCount = featManager.getChoices().length;
|
|
if (choiceCount) {
|
|
subtitleItems.push(
|
|
`${choiceCount} Choice${choiceCount !== 1 ? "s" : ""}`
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
// When there is more than one feat in the list, show the select box to choose one.
|
|
if (!featList.isSingleFeat()) {
|
|
selectBox = (
|
|
<Select
|
|
onChangePromise={(...args) => featList.handleChoiceSelected(...args)}
|
|
options={featList.availableChoices}
|
|
value={featList.chosenFeatId !== null ? featList.chosenFeatId : -1}
|
|
clsNames={["description-manage-background-granted-feat-chooser"]}
|
|
/>
|
|
);
|
|
}
|
|
}
|
|
|
|
if (requiredLevel) {
|
|
subtitleItems.push(`${FormatUtils.ordinalize(requiredLevel)} level`);
|
|
}
|
|
|
|
return (
|
|
<Accordion
|
|
summary={featList.definition.name}
|
|
summaryMetaItems={subtitleItems}
|
|
showAlert={hasUnfinishedChoices}
|
|
variant="paper"
|
|
key={featList.definition.id}
|
|
>
|
|
{infoMessage}
|
|
{selectBox}
|
|
{featContent}
|
|
</Accordion>
|
|
);
|
|
};
|