feat: migrate compare store

This commit is contained in:
TrèsAbhi committed 2024-07-09 19:53:50 -05:00
1 parent f423f8f797
commit 8b70aa12e4
8 files changed
+115 -92

No files matched your search

@@ -4,7 +4,7 @@ import Link from 'next/link';
import { use, useState } from 'react'; import { use, useState } from 'react';
import { provisionDefinitions } from '../../../../core/blitzkit/provisionDefinitions'; import { provisionDefinitions } from '../../../../core/blitzkit/provisionDefinitions';
import { tankToCompareMember } from '../../../../core/blitzkit/tankToCompareMember'; import { tankToCompareMember } from '../../../../core/blitzkit/tankToCompareMember';
import { mutateCompareTemporary } from '../../../../stores/compare'; import * as CompareEphemeral from '../../../../stores/compareEphemeral';
import { TankSearch } from '../../tankopedia/components/TankSearch'; import { TankSearch } from '../../tankopedia/components/TankSearch';
interface TankControlProps { interface TankControlProps {
@@ -15,13 +15,14 @@ interface TankControlProps {
export function TankControl({ index, id }: TankControlProps) { export function TankControl({ index, id }: TankControlProps) {
const awaitedProvisionDefinitions = use(provisionDefinitions); const awaitedProvisionDefinitions = use(provisionDefinitions);
const [switchTankDialogOpen, setSwitchTankDialogOpen] = useState(false); const [switchTankDialogOpen, setSwitchTankDialogOpen] = useState(false);
const mutateCompareEphemeral = CompareEphemeral.useMutation();
return ( return (
<Flex gap="3" justify="center" style={{ width: '100%' }}> <Flex gap="3" justify="center" style={{ width: '100%' }}>
<IconButton <IconButton
variant="ghost" variant="ghost"
onClick={() => { onClick={() => {
mutateCompareTemporary((draft) => { mutateCompareEphemeral((draft) => {
draft.members.splice(index, 1); draft.members.splice(index, 1);
draft.sorting = undefined; draft.sorting = undefined;
}); });
@@ -51,7 +52,7 @@ export function TankControl({ index, id }: TankControlProps) {
<TankSearch <TankSearch
compact compact
onSelect={(tank) => { onSelect={(tank) => {
mutateCompareTemporary((draft) => { mutateCompareEphemeral((draft) => {
draft.members[index] = tankToCompareMember( draft.members[index] = tankToCompareMember(
tank, tank,
awaitedProvisionDefinitions, awaitedProvisionDefinitions,
+17
View File
@@ -0,0 +1,17 @@
import { ReactNode } from 'react';
import * as CompareEphemeral from '../../../stores/compareEphemeral';
import * as ComparePersistent from '../../../stores/comparePersistent';
import * as TankFilters from '../../../stores/tankFilters';
import * as TankopediaSort from '../../../stores/tankopediaSort';
export default function Layout({ children }: { children: ReactNode }) {
return (
<TankopediaSort.Provider>
<TankFilters.Provider>
<ComparePersistent.Provider>
<CompareEphemeral.Provider>{children}</CompareEphemeral.Provider>
</ComparePersistent.Provider>
</TankFilters.Provider>
</TankopediaSort.Provider>
);
}
+39 -36
View File
@@ -50,13 +50,8 @@ import { tankIcon } from '../../../core/blitzkit/tankIcon';
import { tankToCompareMember } from '../../../core/blitzkit/tankToCompareMember'; import { tankToCompareMember } from '../../../core/blitzkit/tankToCompareMember';
import { BlitzkitButtonWatermark } from '../../../icons/BlitzkitButtonWatermark'; import { BlitzkitButtonWatermark } from '../../../icons/BlitzkitButtonWatermark';
import { theme } from '../../../stitches.config'; import { theme } from '../../../stitches.config';
import { import * as CompareEphemeral from '../../../stores/compareEphemeral';
DeltaMode, import * as ComparePersistent from '../../../stores/comparePersistent';
mutateComparePersistent,
mutateCompareTemporary,
useComparePersistent,
useCompareTemporary,
} from '../../../stores/compare';
import { EquipmentMatrix } from '../../../stores/duel'; import { EquipmentMatrix } from '../../../stores/duel';
import { permanentSkills } from '../tankopedia/[id]/components/Characteristics/components/Skills/constants'; import { permanentSkills } from '../tankopedia/[id]/components/Characteristics/components/Skills/constants';
import { TankSearch } from '../tankopedia/components/TankSearch'; import { TankSearch } from '../tankopedia/components/TankSearch';
@@ -71,14 +66,16 @@ export default function Page() {
const awaitedSkillDefinitions = use(skillDefinitions); const awaitedSkillDefinitions = use(skillDefinitions);
const awaitedConsumableDefinitions = use(consumableDefinitions); const awaitedConsumableDefinitions = use(consumableDefinitions);
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const members = useCompareTemporary((state) => state.members); const members = CompareEphemeral.use((state) => state.members);
const [addTankDialogOpen, setAddTankDialogOpen] = useState(false); const [addTankDialogOpen, setAddTankDialogOpen] = useState(false);
const sorting = useCompareTemporary((state) => state.sorting); const sorting = CompareEphemeral.use((state) => state.sorting);
const awaitedModelDefinitions = use(modelDefinitions); const awaitedModelDefinitions = use(modelDefinitions);
const awaitedEquipmentDefinitions = use(equipmentDefinitions); const awaitedEquipmentDefinitions = use(equipmentDefinitions);
const awaitedProvisionDefinitions = use(provisionDefinitions); const awaitedProvisionDefinitions = use(provisionDefinitions);
const deltaMode = useComparePersistent((state) => state.deltaMode); const deltaMode = ComparePersistent.use((state) => state.deltaMode);
const crewSkills = useCompareTemporary((state) => state.crewSkills); const crewSkills = CompareEphemeral.use((state) => state.crewSkills);
const mutateCompareEphemeral = CompareEphemeral.useMutation();
const mutateComparePersistent = ComparePersistent.useMutation();
const haveReactive = members.some((member) => const haveReactive = members.some((member) =>
member.consumables.includes(33), member.consumables.includes(33),
); );
@@ -151,7 +148,7 @@ export default function Page() {
const tanksParam = searchParams.get('tanks'); const tanksParam = searchParams.get('tanks');
if (tanksParam) { if (tanksParam) {
mutateCompareTemporary((draft) => { mutateCompareEphemeral((draft) => {
draft.members = tanksParam draft.members = tanksParam
.split(',') .split(',')
.map(Number) .map(Number)
@@ -165,7 +162,7 @@ export default function Page() {
} }
if (Object.keys(crewSkills).length === 0) { if (Object.keys(crewSkills).length === 0) {
mutateCompareTemporary((draft) => { mutateCompareEphemeral((draft) => {
draft.crewSkills = createDefaultSkills(awaitedSkillDefinitions); draft.crewSkills = createDefaultSkills(awaitedSkillDefinitions);
}); });
} }
@@ -210,7 +207,7 @@ export default function Page() {
color={sorting?.by === name ? undefined : 'gray'} color={sorting?.by === name ? undefined : 'gray'}
variant="ghost" variant="ghost"
onClick={() => { onClick={() => {
mutateCompareTemporary((draft) => { mutateCompareEphemeral((draft) => {
draft.members.sort((memberA, memberB) => { draft.members.sort((memberA, memberB) => {
const indexA = draft.members.indexOf(memberA); const indexA = draft.members.indexOf(memberA);
const indexB = draft.members.indexOf(memberB); const indexB = draft.members.indexOf(memberB);
@@ -413,7 +410,7 @@ export default function Page() {
if (dropIndex === -1) return; if (dropIndex === -1) return;
mutateCompareTemporary((draft) => { mutateCompareEphemeral((draft) => {
const fromIndex = index; const fromIndex = index;
const toIndex = dropIndex > index ? dropIndex - 1 : dropIndex; const toIndex = dropIndex > index ? dropIndex - 1 : dropIndex;
@@ -558,7 +555,7 @@ export default function Page() {
<TankSearch <TankSearch
compact compact
onSelect={(tank) => { onSelect={(tank) => {
mutateCompareTemporary((draft) => { mutateCompareEphemeral((draft) => {
draft.members.push( draft.members.push(
tankToCompareMember( tankToCompareMember(
tank, tank,
@@ -570,7 +567,7 @@ export default function Page() {
setAddTankDialogOpen(false); setAddTankDialogOpen(false);
}} }}
onSelectAll={(tanks) => { onSelectAll={(tanks) => {
mutateCompareTemporary((draft) => { mutateCompareEphemeral((draft) => {
draft.members.push( draft.members.push(
...tanks.map((tank) => ...tanks.map((tank) =>
tankToCompareMember( tankToCompareMember(
@@ -593,7 +590,7 @@ export default function Page() {
variant="soft" variant="soft"
color="red" color="red"
onClick={() => { onClick={() => {
mutateCompareTemporary((draft) => { mutateCompareEphemeral((draft) => {
draft.members = []; draft.members = [];
draft.sorting = undefined; draft.sorting = undefined;
}); });
@@ -606,17 +603,23 @@ export default function Page() {
value={deltaMode} value={deltaMode}
onValueChange={(value) => { onValueChange={(value) => {
mutateComparePersistent((draft) => { mutateComparePersistent((draft) => {
draft.deltaMode = value as DeltaMode; draft.deltaMode = value as ComparePersistent.DeltaMode;
}); });
}} }}
> >
<SegmentedControl.Item value={'none' satisfies DeltaMode}> <SegmentedControl.Item
value={'none' satisfies ComparePersistent.DeltaMode}
>
No deltas No deltas
</SegmentedControl.Item> </SegmentedControl.Item>
<SegmentedControl.Item value={'percentage' satisfies DeltaMode}> <SegmentedControl.Item
value={'percentage' satisfies ComparePersistent.DeltaMode}
>
Percentage Percentage
</SegmentedControl.Item> </SegmentedControl.Item>
<SegmentedControl.Item value={'absolute' satisfies DeltaMode}> <SegmentedControl.Item
value={'absolute' satisfies ComparePersistent.DeltaMode}
>
Absolute Absolute
</SegmentedControl.Item> </SegmentedControl.Item>
</SegmentedControl.Root> </SegmentedControl.Root>
@@ -716,7 +719,7 @@ export default function Page() {
<CrewSkillManager <CrewSkillManager
skillLevels={crewSkills} skillLevels={crewSkills}
onChange={(skills) => { onChange={(skills) => {
mutateCompareTemporary((draft) => { mutateCompareEphemeral((draft) => {
draft.crewSkills = skills; draft.crewSkills = skills;
}); });
}} }}
@@ -726,7 +729,7 @@ export default function Page() {
<Button <Button
variant="ghost" variant="ghost"
onClick={() => { onClick={() => {
mutateCompareTemporary((draft) => { mutateCompareEphemeral((draft) => {
Object.keys(draft.crewSkills).forEach( Object.keys(draft.crewSkills).forEach(
(skill) => { (skill) => {
draft.crewSkills[skill] = 0; draft.crewSkills[skill] = 0;
@@ -740,7 +743,7 @@ export default function Page() {
<Button <Button
variant="ghost" variant="ghost"
onClick={() => { onClick={() => {
mutateCompareTemporary((draft) => { mutateCompareEphemeral((draft) => {
Object.keys(draft.crewSkills).forEach( Object.keys(draft.crewSkills).forEach(
(skill) => { (skill) => {
draft.crewSkills[skill] = 7; draft.crewSkills[skill] = 7;
@@ -836,7 +839,7 @@ export default function Page() {
engine={engine} engine={engine}
track={track} track={track}
onChange={(modules) => { onChange={(modules) => {
mutateCompareTemporary((draft) => { mutateCompareEphemeral((draft) => {
draft.members[index] = { draft.members[index] = {
...draft.members[index], ...draft.members[index],
...modules, ...modules,
@@ -849,7 +852,7 @@ export default function Page() {
<Button <Button
variant="ghost" variant="ghost"
onClick={() => { onClick={() => {
mutateCompareTemporary((draft) => { mutateCompareEphemeral((draft) => {
const member = draft.members[index]; const member = draft.members[index];
member.turret = member.tank.turrets[0]; member.turret = member.tank.turrets[0];
@@ -865,7 +868,7 @@ export default function Page() {
<Button <Button
variant="ghost" variant="ghost"
onClick={() => { onClick={() => {
mutateCompareTemporary((draft) => { mutateCompareEphemeral((draft) => {
const member = draft.members[index]; const member = draft.members[index];
member.turret = member.turret =
@@ -952,7 +955,7 @@ export default function Page() {
tank.provisions === provisions.length tank.provisions === provisions.length
} }
onChange={(provisions) => { onChange={(provisions) => {
mutateCompareTemporary((draft) => { mutateCompareEphemeral((draft) => {
draft.members[index].provisions = draft.members[index].provisions =
provisions; provisions;
}); });
@@ -963,7 +966,7 @@ export default function Page() {
<Button <Button
variant="ghost" variant="ghost"
onClick={() => { onClick={() => {
mutateCompareTemporary((draft) => { mutateCompareEphemeral((draft) => {
draft.members[index].provisions = []; draft.members[index].provisions = [];
}); });
}} }}
@@ -1036,7 +1039,7 @@ export default function Page() {
matrix={equipmentMatrix} matrix={equipmentMatrix}
preset={equipmentPreset} preset={equipmentPreset}
onChange={(matrix) => { onChange={(matrix) => {
mutateCompareTemporary((draft) => { mutateCompareEphemeral((draft) => {
draft.members[index].equipmentMatrix = draft.members[index].equipmentMatrix =
matrix; matrix;
draft.sorting = undefined; draft.sorting = undefined;
@@ -1049,7 +1052,7 @@ export default function Page() {
variant="ghost" variant="ghost"
color="red" color="red"
onClick={() => { onClick={() => {
mutateCompareTemporary((draft) => { mutateCompareEphemeral((draft) => {
draft.members[index].equipmentMatrix = draft.members[index].equipmentMatrix =
times(3, () => times(3, () =>
times(3, () => 0), times(3, () => 0),
@@ -1063,7 +1066,7 @@ export default function Page() {
<Button <Button
variant="ghost" variant="ghost"
onClick={() => { onClick={() => {
mutateCompareTemporary((draft) => { mutateCompareEphemeral((draft) => {
draft.members.forEach((member) => { draft.members.forEach((member) => {
member.equipmentMatrix = member.equipmentMatrix =
draft.members[ draft.members[
@@ -1141,7 +1144,7 @@ export default function Page() {
consumables={consumablesList} consumables={consumablesList}
selected={consumables} selected={consumables}
onChange={(consumables) => { onChange={(consumables) => {
mutateCompareTemporary((draft) => { mutateCompareEphemeral((draft) => {
draft.members[index].consumables = draft.members[index].consumables =
consumables; consumables;
}); });
@@ -1155,7 +1158,7 @@ export default function Page() {
<Button <Button
variant="ghost" variant="ghost"
onClick={() => { onClick={() => {
mutateCompareTemporary((draft) => { mutateCompareEphemeral((draft) => {
draft.members[index].consumables = []; draft.members[index].consumables = [];
}); });
}} }}
@@ -1209,7 +1212,7 @@ export default function Page() {
marginLeft: shellIndex === 0 ? 0 : -1, marginLeft: shellIndex === 0 ? 0 : -1,
}} }}
onClick={() => { onClick={() => {
mutateCompareTemporary((draft) => { mutateCompareEphemeral((draft) => {
draft.members[index].shell = thisShell; draft.members[index].shell = thisShell;
}); });
}} }}
+1 -1
View File
@@ -1,5 +1,5 @@
import { uniqueId } from 'lodash'; import { uniqueId } from 'lodash';
import { CompareMember } from '../../stores/compare'; import { CompareMember } from '../../stores/compareEphemeral';
import { ProvisionDefinitions } from './provisionDefinitions'; import { ProvisionDefinitions } from './provisionDefinitions';
import { TankDefinition } from './tankDefinitions'; import { TankDefinition } from './tankDefinitions';
import { tankToDuelMember } from './tankToDuelMember'; import { tankToDuelMember } from './tankToDuelMember';
-52
View File
@@ -1,52 +0,0 @@
import { produce } from 'immer';
import { merge } from 'lodash';
import { create } from 'zustand';
import { persist, subscribeWithSelector } from 'zustand/middleware';
import { DuelMember } from './duel';
export interface CompareMember extends DuelMember {
key: string;
}
export interface CompareTemporary {
crewSkills: Record<string, number>;
members: CompareMember[];
sorting?: {
direction: 'ascending' | 'descending';
by: string;
};
}
export type DeltaMode = 'none' | 'percentage' | 'absolute';
export interface ComparePersistent {
deltaMode: DeltaMode;
}
export const useCompareTemporary = create<CompareTemporary>()(() => ({
crewSkills: {},
members: [],
}));
export const useComparePersistent = create<ComparePersistent>()(
persist(
subscribeWithSelector<ComparePersistent>(() => ({
deltaMode: 'none',
})),
{
name: 'compare',
merge: (a, b) => merge(b, a),
},
),
);
export function mutateCompareTemporary(
recipe: (draft: CompareTemporary) => void,
) {
useCompareTemporary.setState(produce(recipe));
}
export function mutateComparePersistent(
recipe: (draft: ComparePersistent) => void,
) {
useComparePersistent.setState(produce(recipe));
}
+26
View File
@@ -0,0 +1,26 @@
'use client';
import { create } from 'zustand';
import { createNextSafeStore } from '../core/zustand/createNextSafeStore';
import { DuelMember } from './duel';
export interface CompareMember extends DuelMember {
key: string;
}
export interface CompareEphemeral {
crewSkills: Record<string, number>;
members: CompareMember[];
sorting?: {
direction: 'ascending' | 'descending';
by: string;
};
}
export const { Provider, use, useMutation, useStore } = createNextSafeStore(
() =>
create<CompareEphemeral>()(() => ({
crewSkills: {},
members: [],
})),
);
+26
View File
@@ -0,0 +1,26 @@
'use client';
import { merge } from 'lodash';
import { create } from 'zustand';
import { persist, subscribeWithSelector } from 'zustand/middleware';
import { createNextSafeStore } from '../core/zustand/createNextSafeStore';
export type DeltaMode = 'none' | 'percentage' | 'absolute';
export interface ComparePersistent {
deltaMode: DeltaMode;
}
export const { Provider, use, useMutation, useStore } = createNextSafeStore(
() =>
create<ComparePersistent>()(
persist(
subscribeWithSelector<ComparePersistent>(() => ({
deltaMode: 'none',
})),
{
name: 'compare',
merge: (a, b) => merge(b, a),
},
),
),
);
+2
View File
@@ -1,3 +1,5 @@
'use client';
import { merge } from 'lodash'; import { merge } from 'lodash';
import { create } from 'zustand'; import { create } from 'zustand';
import { persist } from 'zustand/middleware'; import { persist } from 'zustand/middleware';