136 lines
4.1 KiB
TypeScript
136 lines
4.1 KiB
TypeScript
import clsx from "clsx";
|
|
import { FC, HTMLAttributes, MouseEvent } from "react";
|
|
|
|
import {
|
|
characterActions,
|
|
Item,
|
|
ItemPlan,
|
|
ItemPlanUtils,
|
|
ItemUtils,
|
|
} from "@dndbeyond/character-rules-engine";
|
|
|
|
import { Button } from "~/components/Button";
|
|
import { useSidebar } from "~/contexts/Sidebar";
|
|
import { useCharacterEngine } from "~/hooks/useCharacterEngine";
|
|
import { useDispatch } from "~/hooks/useDispatch";
|
|
import { PaneIdentifierUtils } from "~/tools/js/Shared/utils";
|
|
import ItemPreview from "~/tools/js/smartComponents/ItemPreview";
|
|
|
|
import { PaneComponentEnum } from "../Sidebar/types";
|
|
import styles from "./styles.module.css";
|
|
|
|
export interface MagicItemPlansProps extends HTMLAttributes<HTMLDivElement> {}
|
|
|
|
export const MagicItemPlans: FC<MagicItemPlansProps> = ({
|
|
className,
|
|
...props
|
|
}) => {
|
|
const { characterTheme, itemPlans, maxReplicatedItemsCount } =
|
|
useCharacterEngine();
|
|
const {
|
|
pane: { paneHistoryStart },
|
|
} = useSidebar();
|
|
const dispatch = useDispatch();
|
|
|
|
const itemPlanWithMappingsCount = itemPlans.filter((plan) =>
|
|
ItemPlanUtils.getItem(plan)
|
|
).length;
|
|
|
|
const atMax =
|
|
maxReplicatedItemsCount !== null &&
|
|
itemPlanWithMappingsCount >= maxReplicatedItemsCount;
|
|
|
|
const handleItemPlansManagePaneShow = (
|
|
e: MouseEvent<HTMLButtonElement>
|
|
): void => {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
paneHistoryStart(PaneComponentEnum.ITEM_PLANS_MANAGE);
|
|
};
|
|
|
|
const handleItemClick = (item: Item): void => {
|
|
const inventoryMappingId = ItemUtils.getMappingId(item);
|
|
|
|
if (inventoryMappingId) {
|
|
paneHistoryStart(
|
|
PaneComponentEnum.ITEM_DETAIL,
|
|
PaneIdentifierUtils.generateItem(inventoryMappingId)
|
|
);
|
|
}
|
|
};
|
|
|
|
const handleReplicateItem = (itemPlan: ItemPlan): void => {
|
|
const itemDefinitionKey = ItemPlanUtils.getItemDefinitionKey(itemPlan);
|
|
const itemPlanOriginDefinitionKey =
|
|
ItemPlanUtils.getOriginDefinitionKey(itemPlan);
|
|
|
|
if (itemDefinitionKey) {
|
|
dispatch(
|
|
characterActions.itemPlanInventoryMappingCreate(
|
|
itemDefinitionKey,
|
|
1,
|
|
itemPlanOriginDefinitionKey
|
|
)
|
|
);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className={clsx([styles.magicItemPlans, className])} {...props}>
|
|
{itemPlans.length > 0 ? (
|
|
itemPlans.map((plan) => {
|
|
const planOriginDefinitionKey =
|
|
ItemPlanUtils.getOriginDefinitionKey(plan);
|
|
const planName = ItemPlanUtils.getItemName(plan);
|
|
const itemDefinitionKey = ItemPlanUtils.getItemDefinitionKey(plan);
|
|
const item = ItemPlanUtils.getItem(plan);
|
|
const planDescription = ItemPlanUtils.getDescription(plan);
|
|
|
|
return itemDefinitionKey ? (
|
|
<div className={styles.itemPlan} key={planOriginDefinitionKey}>
|
|
<div className={styles.planHeader}>
|
|
<p className={styles.planName}>{planName}</p>
|
|
<p className={styles.description}>{planDescription}</p>
|
|
</div>
|
|
<div className={styles.itemContent}>
|
|
{item ? (
|
|
<div className={styles.itemPreview}>
|
|
<ItemPreview
|
|
theme={characterTheme}
|
|
item={item}
|
|
onClick={() => handleItemClick(item)}
|
|
/>
|
|
</div>
|
|
) : (
|
|
<Button
|
|
className={styles.replicateButton}
|
|
themed
|
|
size="xx-small"
|
|
onClick={() => handleReplicateItem(plan)}
|
|
disabled={atMax}
|
|
>
|
|
{atMax ? "At Max Replicated Items" : "Replicate Item"}
|
|
</Button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
) : null;
|
|
})
|
|
) : (
|
|
<div className={styles.empty}>
|
|
No Magic Item plans have been selected for this character
|
|
<Button
|
|
className={styles.emptyButton}
|
|
themed
|
|
size="x-small"
|
|
onClick={handleItemPlansManagePaneShow}
|
|
>
|
|
Add Magic Item Plans
|
|
</Button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|