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 + + + )} + + )} ); }