Files
wow-gear-finder/src/lib/state.ts

88 lines
1.9 KiB
TypeScript

import type { EquipedItem, Item, ItemId, Quality } from "./types";
export type State = {
equipedItems: EquipedItem[];
bisList: ItemId[];
};
export const emptyState: State = {
equipedItems: [],
bisList: [],
};
export type Action =
| {
action: "equipItem";
item: Item;
}
| {
action: "unequipItem";
item: Item;
}
| {
action: "changeQuality";
itemId: ItemId;
quality: Quality;
};
export const reducer = (state: State, action: Action): State => {
switch (action.action) {
case "equipItem":
return {
...state,
equipedItems: [
...state.equipedItems,
{
id: action.item.id,
quality: "champion", // Default quality, can be changed later
},
],
};
case "unequipItem":
return {
...state,
equipedItems: state.equipedItems.filter(
(item) => item.id !== action.item.id,
),
};
case "changeQuality":
return {
...state,
equipedItems: state.equipedItems.map((item) => {
if (item.id === action.itemId) {
return {
id: item.id,
quality: action.quality,
};
}
return item;
}),
};
}
};
export type LoadingAction<S> = {
action: "loadState";
state: S;
};
function isLoadingAction<A, S>(
action: A | LoadingAction<S>,
): action is LoadingAction<S> {
return (action as LoadingAction<S>).action === "loadState";
}
export const withLoadingAction =
<S, A>(reducer: (state: S, action: A) => S) =>
(state: S | "loading", action: A | LoadingAction<S>): S | "loading" => {
if (state !== "loading" && !isLoadingAction(action)) {
return reducer(state, action);
}
if (state === "loading" && isLoadingAction(action)) {
return action.state;
}
return state;
};