Skip to content

Commit

Permalink
refactor: make deck edit slice a "draft"
Browse files Browse the repository at this point in the history
  • Loading branch information
fspoettel committed Jun 20, 2024
1 parent 2e72aba commit 54d81bd
Show file tree
Hide file tree
Showing 46 changed files with 761 additions and 897 deletions.
56 changes: 25 additions & 31 deletions src/app.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Suspense, lazy, useEffect } from "react";
import { Route, Router, Switch, useLocation } from "wouter";
import { useBrowserLocation } from "wouter/use-browser-location";

import { CardModalProvider } from "./components/card-modal/card-modal-context";
import { ErrorBoundary } from "./components/error-boundary";
import { Loader } from "./components/ui/loader";
import { ToastProvider } from "./components/ui/toast";
Expand All @@ -13,8 +13,6 @@ import {
queryDataVersion,
queryMetadata,
} from "./store/services/queries";
import { useBrowserLocationWithConfirmation } from "./utils/use-location-with-confirm";
import { useSyncActiveDeckId } from "./utils/use-sync-active-deck-id";

const Browse = lazy(() => import("./pages/browse/browse"));
const DeckEdit = lazy(() => import("./pages/deck-edit/deck-edit"));
Expand All @@ -41,41 +39,37 @@ function App() {

return (
<ErrorBoundary>
<CardModalProvider>
<ToastProvider>
<Loader
message="Initializing card database..."
show={storeHydrated && !storeInitialized}
/>
<Suspense fallback={<Loader delay={200} show />}>
{storeInitialized && (
<Router hook={useBrowserLocationWithConfirmation}>
<Switch>
<Route component={Browse} path="/" />
<Route component={CardView} path="/card/:code" />
<Route component={ChooseInvestigator} path="/deck/create" />
<Route component={DeckCreate} path="/deck/create/:code" />
<Route component={DeckView} path="/deck/view/:id" />
<Route component={DeckEdit} path="/deck/edit/:id" />
<Route component={Settings} path="/settings" />
<Route component={About} path="/about" />
<Route component={Error404} path="*" />
</Switch>
<RouteReset />
</Router>
)}
</Suspense>
</ToastProvider>
</CardModalProvider>
<ToastProvider>
<Loader
message="Initializing card database..."
show={storeHydrated && !storeInitialized}
/>
<Suspense fallback={<Loader delay={200} show />}>
{storeInitialized && (
<Router hook={useBrowserLocation}>
<Switch>
<Route component={Browse} path="/" />
<Route component={CardView} path="/card/:code" />
<Route component={ChooseInvestigator} path="/deck/create" />
<Route component={DeckCreate} path="/deck/create/:code" />
<Route component={DeckView} path="/deck/view/:id" />
<Route component={DeckEdit} path="/deck/edit/:id" />
<Route component={Settings} path="/settings" />
<Route component={About} path="/about" />
<Route component={Error404} path="*" />
</Switch>
<RouteReset />
</Router>
)}
</Suspense>
</ToastProvider>
</ErrorBoundary>
);
}

function RouteReset() {
const [pathname] = useLocation();

useSyncActiveDeckId();

useEffect(() => {
if (window.location.hash) {
// HACK: this enables hash-based deep links to work when a route is loaded async.
Expand Down
26 changes: 14 additions & 12 deletions src/components/card-list/card-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import { CenterLayout } from "@/layouts/center-layout";
import { useStore } from "@/store";
import type { ListState } from "@/store/selectors/card-list";
import { selectListCards } from "@/store/selectors/card-list";
import { selectCardQuantities } from "@/store/selectors/decks";
import { selectActiveListSearch } from "@/store/selectors/lists";
import type { Card } from "@/store/services/queries.types";
import type { Id, Slots } from "@/store/slices/data.types";
import { range } from "@/utils/range";
import { useDeckId } from "@/utils/use-deck-id";

import css from "./card-list.module.css";

Expand All @@ -22,28 +23,32 @@ import { CardListNav } from "./card-list-nav";
import { CardSearch } from "./card-search";

type Props = {
canEdit?: boolean;
onOpenModal?: (code: string) => void;
deckId?: Id;
onChangeCardQuantity?: (code: string, quantity: number) => void;
quantities?: Slots;
renderListCardAction?: (card: Card) => React.ReactNode;
renderListCardExtra?: (card: Card) => React.ReactNode;
slotLeft?: React.ReactNode;
slotRight?: React.ReactNode;
targetDeck?: "slots" | "extraSlots" | "both";
};

export function CardList({
canEdit,
onOpenModal,
onChangeCardQuantity,
quantities,
renderListCardAction,
renderListCardExtra,
slotLeft,
slotRight,
targetDeck,
}: Props) {
const modalContext = useCardModalContext();
const deckIdCtx = useDeckId();

const data = useStore(selectListCards);
const data = useStore((state) =>
selectListCards(state, deckIdCtx.deckId, deckIdCtx.canEdit, targetDeck),
);

const updateCardQuantity = useStore((state) => state.updateCardQuantity);
const quantities = useStore(selectCardQuantities);
const search = useStore(selectActiveListSearch);
const metadata = useStore((state) => state.metadata);

Expand Down Expand Up @@ -196,10 +201,7 @@ export function CardList({
disableKeyboard
isActive={index === currentTop}
key={data.cards[index].code}
onChangeCardQuantity={
canEdit ? updateCardQuantity : undefined
}
onOpenModal={onOpenModal}
onChangeCardQuantity={onChangeCardQuantity}
quantities={quantities}
renderAction={renderListCardAction}
renderExtra={renderListCardExtra}
Expand Down
2 changes: 0 additions & 2 deletions src/components/card-modal/card-modal-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import { CardModal } from "./card-modal";

type CardModalContextConfig = {
code: string;
deckId?: string | number;
canEdit?: boolean;
};

type CardModalContextState =
Expand Down
27 changes: 18 additions & 9 deletions src/components/card-modal/card-modal-quantities.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { useCallback, useEffect, useRef } from "react";

import { useStore } from "@/store";
import type { DisplayDeck } from "@/store/lib/deck-grouping";
import { selectShowIgnoreDeckLimitSlots } from "@/store/selectors/decks";
import { selectShowIgnoreDeckLimitSlotsById } from "@/store/selectors/deck-view";
import type { Card } from "@/store/services/queries.types";
import type { Slot } from "@/store/slices/deck-view.types";
import type { Slot } from "@/store/slices/deck-edits.types";

import css from "./card-modal.module.css";

Expand Down Expand Up @@ -42,17 +42,23 @@ export function CardModalQuantities({
if (!canEdit) return;

function onKeyDown(evt: KeyboardEvent) {
if (evt.metaKey) return;
if (evt.metaKey || !deck?.id) return;

if (evt.key === "ArrowRight") {
evt.preventDefault();
updateCardQuantity(card.code, 1, "slots");
updateCardQuantity(deck.id, card.code, 1, "slots");
} else if (evt.key === "ArrowLeft") {
evt.preventDefault();
updateCardQuantity(card.code, -1, "slots");
updateCardQuantity(deck.id, card.code, -1, "slots");
} else if (Number.parseInt(evt.key) >= 0) {
evt.preventDefault();
updateCardQuantity(card.code, Number.parseInt(evt.key), "slots", "set");
updateCardQuantity(
deck.id,
card.code,
Number.parseInt(evt.key),
"slots",
"set",
);
onClickBackground?.();
}
}
Expand All @@ -61,7 +67,7 @@ export function CardModalQuantities({
return () => {
window.removeEventListener("keydown", onKeyDown);
};
}, [canEdit, card.code, updateCardQuantity, onClickBackground]);
}, [canEdit, card.code, updateCardQuantity, onClickBackground, deck?.id]);

const quantities = deck?.slots;
const sideSlotQuantities = deck?.sideSlots;
Expand All @@ -70,11 +76,14 @@ export function CardModalQuantities({
const ignoreDeckLimitQuantities = deck?.ignoreDeckLimitSlots;

const onChangeQuantity = (quantity: number, slot: Slot) => {
updateCardQuantity(card.code, quantity, slot);
if (!deck?.id) return;
updateCardQuantity(deck.id, card.code, quantity, slot);
};

const showIgnoreDeckLimitSlots = useStore((state) =>
selectShowIgnoreDeckLimitSlots(state, card),
deck
? selectShowIgnoreDeckLimitSlotsById(state, deck.id, false, card)
: false,
);

const code = card.code;
Expand Down
32 changes: 10 additions & 22 deletions src/components/card-modal/card-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import {
} from "@/store/lib/resolve-card";
import { selectCardWithRelations } from "@/store/selectors/card-view";
import { selectActiveDeckById } from "@/store/selectors/deck-view";
import { selectActiveDeck } from "@/store/selectors/decks";
import { formatRelationTitle } from "@/utils/formatting";
import { useDeckId } from "@/utils/use-deck-id";
import { useMedia } from "@/utils/use-media";

import css from "./card-modal.module.css";
Expand All @@ -22,41 +22,30 @@ import { CustomizationsEditor } from "../customizations/customizations-editor";
import { Button } from "../ui/button";
import { useDialogContext } from "../ui/dialog.hooks";
import { Modal } from "../ui/modal";
import { useCardModalContext } from "./card-modal-context";
import { CardModalQuantities } from "./card-modal-quantities";

type Props = {
code: string;
deckId?: string;
canEdit?: boolean;
};

export function CardModal({ canEdit, code, deckId }: Props) {
export function CardModal({ code }: Props) {
const deckIdCtx = useDeckId();
const deckId = deckIdCtx.deckId;
const canEdit = deckIdCtx.canEdit;

const modalContext = useDialogContext();
const cardModalContext = useCardModalContext();

const onCloseModal = useCallback(() => {
modalContext?.setOpen(false);
}, [modalContext]);

const onOpenModal = useCallback(
(code: string) => {
cardModalContext?.setOpen({ canEdit, code, deckId });
},
[canEdit, deckId, cardModalContext],
);

// FIXME: Remove this hack when we have refactored the deck edit state.
// we need the active deck here to get contents of bondedSlots.
const activeDeck = useStore((state) =>
deckId
? canEdit
? selectActiveDeck(state)
: selectActiveDeckById(state, deckId)
: undefined,
deckId ? selectActiveDeckById(state, deckId, canEdit) : undefined,
);

const cardWithRelations = useStore((state) =>
selectCardWithRelations(state, code, true),
selectCardWithRelations(state, code, true, deckId, canEdit),
);

const showQuantities =
Expand All @@ -78,9 +67,9 @@ export function CardModal({ canEdit, code, deckId }: Props) {
{cardWithRelations.card.customization_options ? (
activeDeck ? (
<CustomizationsEditor
activeDeck={activeDeck}
canEdit={canEdit}
card={cardWithRelations.card}
deck={activeDeck}
/>
) : (
<Customizations card={cardWithRelations.card} />
Expand All @@ -93,7 +82,6 @@ export function CardModal({ canEdit, code, deckId }: Props) {
const cards = Array.isArray(value) ? value : [value];
return (
<CardSet
onOpenModal={onOpenModal}
key={key}
set={{
title: formatRelationTitle(key),
Expand Down
11 changes: 10 additions & 1 deletion src/components/card-tooltip.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useStore } from "@/store";
import { selectCardWithRelations } from "@/store/selectors/card-view";
import { useDeckId } from "@/utils/use-deck-id";

import css from "./card-tooltip.module.css";

Expand All @@ -10,8 +11,16 @@ type Props = {
};

export function CardTooltip({ code }: Props) {
const deckIdCtx = useDeckId();

const resolvedCard = useStore((state) =>
selectCardWithRelations(state, code, false),
selectCardWithRelations(
state,
code,
false,
deckIdCtx?.deckId,
deckIdCtx?.canEdit,
),
);

if (!resolvedCard) return null;
Expand Down
9 changes: 1 addition & 8 deletions src/components/cardset.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,11 @@ import { Checkbox } from "./ui/checkbox";

type Props = {
onChangeCardQuantity?: (code: string, quantity: number) => void;
onOpenModal?: (code: string) => void;
onSelect?: (id: string) => void;
set: CardSetType;
};

export function CardSet({
onChangeCardQuantity,
onOpenModal,
onSelect,
set,
}: Props) {
export function CardSet({ onChangeCardQuantity, onSelect, set }: Props) {
const canCheckOwnership = useStore(selectCanCheckOwnership);
const cardOwnedCount = useStore(selectCardOwnedCount);

Expand Down Expand Up @@ -55,7 +49,6 @@ export function CardSet({
onChangeCardQuantity={
set.canSetQuantity ? onChangeCardQuantity : undefined
}
onOpenModal={onOpenModal}
owned={cardOwnedCount(card)}
quantities={
set.quantities
Expand Down
2 changes: 1 addition & 1 deletion src/components/customizations/customization-option.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type {
Card,
CustomizationOption as CustomizationOptionType,
} from "@/store/services/queries.types";
import type { CustomizationEdit } from "@/store/slices/deck-view.types";
import type { CustomizationEdit } from "@/store/slices/deck-edits.types";
import { parseCustomizationTextHtml } from "@/utils/card-utils";
import { range } from "@/utils/range";

Expand Down
Loading

0 comments on commit 54d81bd

Please sign in to comment.