diff --git a/src/app/tools/compare/page.tsx b/src/app/tools/compare/page.tsx
index 54127de0d..ace0e03a2 100644
--- a/src/app/tools/compare/page.tsx
+++ b/src/app/tools/compare/page.tsx
@@ -4,6 +4,7 @@ import {
CaretLeftIcon,
CaretRightIcon,
CaretSortIcon,
+ ComponentPlaceholderIcon,
GroupIcon,
PlusIcon,
TrashIcon,
@@ -22,11 +23,14 @@ import {
import { times } from 'lodash';
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
import { use, useCallback, useEffect, useMemo, useState } from 'react';
+import { ConsumablesManager } from '../../../components/ConsumablesManager';
import { EquipmentManager } from '../../../components/EquipmentManager';
import PageWrapper from '../../../components/PageWrapper';
import { ProvisionsManager } from '../../../components/ProvisionsManager';
import { asset } from '../../../core/blitzkrieg/asset';
import { availableProvisions } from '../../../core/blitzkrieg/availableProvisions';
+import { checkConsumableProvisionInclusivity } from '../../../core/blitzkrieg/checkConsumableProvisionInclusivity';
+import { consumableDefinitions } from '../../../core/blitzkrieg/consumableDefinitions';
import { equipmentDefinitions } from '../../../core/blitzkrieg/equipmentDefinitions';
import { modelDefinitions } from '../../../core/blitzkrieg/modelDefinitions';
import { provisionDefinitions } from '../../../core/blitzkrieg/provisionDefinitions';
@@ -52,6 +56,7 @@ export default function Page() {
const router = useRouter();
const awaitedTankDefinitions = use(tankDefinitions);
const awaitedSkillDefinitions = use(skillDefinitions);
+ const awaitedConsumableDefinitions = use(consumableDefinitions);
const searchParams = useSearchParams();
const members = useCompareTemporary((state) => state.members);
const [addTankDialogOpen, setAddTankDialogOpen] = useState(false);
@@ -442,7 +447,17 @@ export default function Page() {
{members.map(
- ({ equipmentMatrix, tank, key, provisions, gun }, index) => {
+ (
+ {
+ equipmentMatrix,
+ tank,
+ key,
+ provisions,
+ gun,
+ consumables,
+ },
+ index,
+ ) => {
const equipmentPreset =
awaitedEquipmentDefinitions.presets[tank.equipment];
const provisionsList = availableProvisions(
@@ -450,6 +465,15 @@ export default function Page() {
gun,
awaitedProvisionDefinitions,
);
+ const consumablesList = Object.values(
+ awaitedConsumableDefinitions,
+ ).filter((consumable) =>
+ checkConsumableProvisionInclusivity(
+ consumable,
+ tank,
+ gun,
+ ),
+ );
return (
@@ -462,6 +486,84 @@ export default function Page() {
height: '100%',
}}
>
+
+
+
+
+
+
+ provision.id,
+ )}
+ selected={provisions}
+ disabled={tank.provisions === provisions.length}
+ onChange={(provisions) => {
+ mutateCompareTemporary((draft) => {
+ draft.members[index].provisions =
+ provisions;
+ });
+ }}
+ />
+
+
+
+
+
+
+
- provision.id,
- )}
- selected={provisions}
- disabled={tank.provisions === provisions.length}
- onChange={(provisions) => {
+ {
mutateCompareTemporary((draft) => {
- draft.members[index].provisions =
- provisions;
+ draft.members[index].consumables =
+ consumables;
});
}}
+ disabled={
+ tank.consumables === consumables.length
+ }
/>
@@ -631,7 +735,7 @@ export default function Page() {
variant="ghost"
onClick={() => {
mutateCompareTemporary((draft) => {
- draft.members[index].provisions = [];
+ draft.members[index].consumables = [];
});
}}
>
diff --git a/src/app/tools/tankopedia/[id]/components/Characteristics/components/Consumables.tsx b/src/app/tools/tankopedia/[id]/components/Characteristics/components/Consumables.tsx
index d5b3c45c8..57bc4b7bc 100644
--- a/src/app/tools/tankopedia/[id]/components/Characteristics/components/Consumables.tsx
+++ b/src/app/tools/tankopedia/[id]/components/Characteristics/components/Consumables.tsx
@@ -8,7 +8,7 @@ import {
Text,
} from '@radix-ui/themes';
import { use } from 'react';
-import { ConsumableButton } from '../../../../../../../components/ModuleButtons/ConsumableButton';
+import { ConsumablesManager } from '../../../../../../../components/ConsumablesManager';
import { checkConsumableProvisionInclusivity } from '../../../../../../../core/blitzkrieg/checkConsumableProvisionInclusivity';
import { consumableDefinitions } from '../../../../../../../core/blitzkrieg/consumableDefinitions';
import { useEquipment } from '../../../../../../../hooks/useEquipment';
@@ -68,48 +68,20 @@ export function Consumables() {
-
- {consumablesList.map((consumable, index) => {
- const selected = consumables.includes(consumable.id);
-
- return (
- {
- mutateDuel((draft) => {
- if (selected) {
- draft.protagonist!.consumables =
- draft.protagonist!.consumables.filter(
- (id) => id !== consumable.id,
- );
- } else {
- draft.protagonist!.consumables.push(consumable.id);
- }
- });
- }}
- />
- );
- })}
-
+ {
+ mutateDuel((draft) => {
+ draft.protagonist!.consumables = consumables;
+ });
+ }}
+ />
);
}
diff --git a/src/components/ConsumablesManager.tsx b/src/components/ConsumablesManager.tsx
new file mode 100644
index 000000000..296e4d3fe
--- /dev/null
+++ b/src/components/ConsumablesManager.tsx
@@ -0,0 +1,73 @@
+import { Flex } from '@radix-ui/themes';
+import { ConsumableEntry } from '../core/blitzkrieg/consumableDefinitions';
+import { ConsumableButton } from './ModuleButtons/ConsumableButton';
+
+interface ConsumablesManagerProps {
+ consumables: ConsumableEntry[];
+ selected: number[];
+ onChange?: (consumables: number[]) => void;
+ disabled?: boolean;
+ timers?: boolean;
+ hasHighEndConsumables?: boolean;
+ hasConsumableDeliverySystem?: boolean;
+ cooldownBooster?: number;
+}
+
+export function ConsumablesManager({
+ consumables,
+ selected,
+ onChange,
+ disabled,
+ timers,
+ hasConsumableDeliverySystem,
+ cooldownBooster,
+ hasHighEndConsumables,
+}: ConsumablesManagerProps) {
+ return (
+
+ {consumables.map((consumable, index) => {
+ const isSelected = selected.some((id) => id === consumable.id);
+
+ return (
+ {
+ if (!onChange) return;
+
+ const draft = [...selected];
+
+ if (draft.some((id) => id === consumable.id)) {
+ draft.splice(draft.indexOf(consumable.id), 1);
+ } else {
+ draft.push(consumable.id);
+ }
+
+ onChange(draft);
+ }}
+ />
+ );
+ })}
+
+ );
+}
diff --git a/src/components/ModuleButtons/ConsumableButton.tsx b/src/components/ModuleButtons/ConsumableButton.tsx
index 3658fa0e1..8513ffc58 100644
--- a/src/components/ModuleButtons/ConsumableButton.tsx
+++ b/src/components/ModuleButtons/ConsumableButton.tsx
@@ -8,7 +8,7 @@ import { TankComponentButtonProps } from './TankComponentButton';
interface ConsumableButtonProps extends TankComponentButtonProps {
consumable: number;
duration?: number;
- cooldown: number;
+ cooldown?: number;
}
export function ConsumableButton({
@@ -17,7 +17,7 @@ export function ConsumableButton({
duration,
...props
}: ConsumableButtonProps) {
- const cooldownDelta = useDelta(cooldown);
+ const cooldownDelta = useDelta(cooldown ?? 0);
const durationDelta = useDelta(duration ?? 0);
return (
@@ -25,38 +25,42 @@ export function ConsumableButton({
icon={asset(`icons/consumables/${consumable}.webp`)}
{...props}
>
-
- {duration && (
- 0
- ? 'tomato'
- : undefined
- }
- >
-
-
- {Math.round(duration)}s
-
-
- )}
- 0
- ? 'tomato'
- : undefined
- }
- >
-
-
- {Math.round(cooldown)}s
-
-
-
+ {(cooldown || duration) && (
+
+ {duration && (
+ 0
+ ? 'tomato'
+ : undefined
+ }
+ >
+
+
+ {Math.round(duration)}s
+
+
+ )}
+ {cooldown && (
+ 0
+ ? 'tomato'
+ : undefined
+ }
+ >
+
+
+ {Math.round(cooldown)}s
+
+
+ )}
+
+ )}
);
}