Add ModalProvider

This commit is contained in:
thesn10
2026-07-02 22:25:25 +02:00
parent d0fce88dbd
commit 9eadca17cd

112
app/src/state/modals.tsx Normal file
View File

@@ -0,0 +1,112 @@
import type { JSX, PropsWithChildren } from "react";
import { createContext, useCallback, useContext, useMemo, useRef, useState } from "react";
import { useWallet, type WalletName } from "@/state/wallet";
export type CheckoutStep = "review" | "pending" | "success";
interface ModalContextValue {
isWalletSheetOpen: boolean;
isCheckoutSheetOpen: boolean;
checkoutListingId: number | null;
checkoutStep: CheckoutStep;
requestBuy: (listingId: number) => void;
openWalletConnect: () => void;
connectWallet: (wallet: WalletName) => void;
closeWalletSheet: () => void;
closeCheckoutSheet: () => void;
confirmOrder: () => void;
}
const ModalContext = createContext<ModalContextValue | null>(null);
export function ModalProvider({ children }: PropsWithChildren): JSX.Element {
const { connected, connect } = useWallet();
const [isWalletSheetOpen, setWalletSheetOpen] = useState(false);
const [isCheckoutSheetOpen, setCheckoutSheetOpen] = useState(false);
const [checkoutListingId, setCheckoutListingId] = useState<number | null>(null);
const [checkoutStep, setCheckoutStep] = useState<CheckoutStep>("review");
const pendingListingId = useRef<number | null>(null);
const requestBuy = useCallback(
(listingId: number) => {
if (connected) {
setCheckoutListingId(listingId);
setCheckoutStep("review");
setCheckoutSheetOpen(true);
} else {
pendingListingId.current = listingId;
setWalletSheetOpen(true);
}
},
[connected],
);
const openWalletConnect = useCallback(() => {
pendingListingId.current = null;
setWalletSheetOpen(true);
}, []);
const connectWallet = useCallback(
(wallet: WalletName) => {
connect(wallet);
setWalletSheetOpen(false);
const listingId = pendingListingId.current;
pendingListingId.current = null;
if (listingId !== null) {
setCheckoutListingId(listingId);
setCheckoutStep("review");
setCheckoutSheetOpen(true);
}
},
[connect],
);
const closeWalletSheet = useCallback(() => {
setWalletSheetOpen(false);
pendingListingId.current = null;
}, []);
const closeCheckoutSheet = useCallback(() => {
setCheckoutSheetOpen(false);
}, []);
const confirmOrder = useCallback(() => {
setCheckoutStep("pending");
setTimeout(() => setCheckoutStep("success"), 2200);
}, []);
const value = useMemo<ModalContextValue>(
() => ({
isWalletSheetOpen,
isCheckoutSheetOpen,
checkoutListingId,
checkoutStep,
requestBuy,
openWalletConnect,
connectWallet,
closeWalletSheet,
closeCheckoutSheet,
confirmOrder,
}),
[
isWalletSheetOpen,
isCheckoutSheetOpen,
checkoutListingId,
checkoutStep,
requestBuy,
openWalletConnect,
connectWallet,
closeWalletSheet,
closeCheckoutSheet,
confirmOrder,
],
);
return <ModalContext.Provider value={value}>{children}</ModalContext.Provider>;
}
export function useModals(): ModalContextValue {
const ctx = useContext(ModalContext);
if (!ctx) throw new Error("useModals must be used within a ModalProvider");
return ctx;
}