Skip to content

Commit

Permalink
Update notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
hiep-immutable committed Sep 12, 2024
1 parent 4dbe573 commit af63d75
Show file tree
Hide file tree
Showing 18 changed files with 156 additions and 31 deletions.
2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
},
"devDependencies": {
"@emotion/react": "^11.13.3",
"@rive-app/react-canvas-lite": "^4.13.8",
"@rive-app/react-canvas-lite": "^4.13.10",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
Expand Down
2 changes: 1 addition & 1 deletion client/src/app/components/Inventory/Inventory.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useCollectionItemsQuery } from "@/app/hooks/useQuery";
import { Collection, nftToName } from "@/app/types";
import { usePassportProvider } from "@/context";
import { usePassportProvider } from "@/app/context";
import { Box, Card, Grid, Heading } from "@biom3/react";

export default function Inventory({ collection }: { collection: Collection }) {
Expand Down
8 changes: 5 additions & 3 deletions client/src/app/components/Layout/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import SideMenu from "../SideMenu/SideMenu";

export default function Layout({ children }: Readonly<{ children: React.ReactNode }>) {
return (
<Box sx={{
height: "100%",
}}>
<Box
sx={{
height: "100%",
}}
>
<Box
sx={{
d: "flex",
Expand Down
62 changes: 45 additions & 17 deletions client/src/app/components/Recipes/RecipeBox.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Box, Heading, Button, Icon, MenuItem, Stack } from "@biom3/react";
import { Box, Heading, Button, Icon, MenuItem, Stack, Modal, LoadingOverlay } from "@biom3/react";
import { Collection, nftToName, Recipe } from "@/app/types";
import { useSubmitCraft, useCraftTx, useApprovalQuery, useSetApprovalAllTx } from "@/app/hooks";
import { usePassportProvider } from "@/context";
import { usePassportProvider, useMessageProvider } from "@/app/context";
import { useState } from "react";

export default function RecipeBox({
recipe,
Expand All @@ -14,24 +15,43 @@ export default function RecipeBox({
const { submitCraft } = useSubmitCraft();
const { sendCraftTx } = useCraftTx();
const { getIsApprovedForAll } = useApprovalQuery();
const { setApprovalForAll, error: setApprovalErr } = useSetApprovalAllTx();
const { setApprovalForAll } = useSetApprovalAllTx();
const [isLoading, setIsLoading] = useState(false);
const { addMessage } = useMessageProvider();

const execute = async (recipe: Recipe) => {
const res = await submitCraft(recipe.id);
const isApproved = await getIsApprovedForAll({ collection, operator: res.multicallerAddress });
if (!isApproved) {
await setApprovalForAll({ collection, operator: res.multicallerAddress });
try {
setIsLoading(true);
const res = await submitCraft(recipe.id);
const isApproved = await getIsApprovedForAll({
collection,
operator: res.multicallerAddress,
});
if (!isApproved) {
await setApprovalForAll({ collection, operator: res.multicallerAddress });
}
await sendCraftTx({
multicallerAddress: res.multicallerAddress,
executeArgs: {
multicallSigner: res.multicallSigner,
reference: res.reference,
calls: res.calls,
deadline: BigInt(res.deadline),
signature: res.signature,
},
});
addMessage({
status: "success",
message: "Crafting transaction sent!",
});
} catch (e: any) {
addMessage({
status: "fatal",
message: "Transaction failed! View console for more details.",
});
} finally {
setIsLoading(false);
}
await sendCraftTx({
multicallerAddress: res.multicallerAddress,
executeArgs: {
multicallSigner: res.multicallSigner,
reference: res.reference,
calls: res.calls,
deadline: BigInt(res.deadline),
signature: res.signature,
},
});
};

return (
Expand Down Expand Up @@ -102,6 +122,14 @@ export default function RecipeBox({
>
Execute
</Button>
<LoadingOverlay visible={isLoading}>
<LoadingOverlay.Content>
<LoadingOverlay.Content.LoopingText
text={["Sending crafting transaction", recipe.name]}
textDuration={1000}
/>
</LoadingOverlay.Content>
</LoadingOverlay>
</Box>
);
}
22 changes: 22 additions & 0 deletions client/src/app/components/SideMenu/Banners.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from "react";
import { Banner, Stack } from "@biom3/react";
import { useMessageProvider } from "@/app/context";

export default function Banners() {
const { messages, removeMessage } = useMessageProvider();

return (
<>
{messages ? (
<Stack gap="base.spacing.x2">
{messages.map((message, index) => (
<Banner key={index} variant={message.status}>
<Banner.Caption>{message.message}</Banner.Caption>
<Banner.RightButton onClick={() => removeMessage(index)}>Close</Banner.RightButton>
</Banner>
))}
</Stack>
) : null}
</>
);
}
11 changes: 8 additions & 3 deletions client/src/app/components/SideMenu/SideMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { usePassportProvider } from "@/context";
import { usePassportProvider } from "@/app/context";
import { Box, Logo, Heading, Button, EllipsizedText } from "@biom3/react";
import Banners from "./Banners";

export default function SideMenu() {
const { userInfo, triggerLogin, passportState, walletAddress } = usePassportProvider();
Expand All @@ -8,7 +9,7 @@ export default function SideMenu() {
<Box
sx={{
w: "100%",
maxw: "300px",
maxw: "350px",
h: "100%",
top: [null, null, "0px"],
pos: "sticky",
Expand All @@ -32,11 +33,12 @@ export default function SideMenu() {
display: "flex",
alignItems: "center",
flexDirection: "column",
gap: "base.spacing.x4",
}}
>
<Logo logo="ImmutableHorizontalLockup" sx={{ maxh: "base.spacing.x10" }} />
<Heading size="small">Crafting</Heading>
<Box sx={{ marginTop: "base.spacing.x8" }}>
<Box>
{!passportState.authenticated && (
<Button onClick={triggerLogin}>
<Button.Logo logo="PassportSymbolOutlined" />
Expand All @@ -50,6 +52,9 @@ export default function SideMenu() {
</>
)}
</Box>
<Box sx={{ w: "100%" }}>
<Banners />
</Box>
</Box>
</Box>
);
Expand Down
File renamed without changes.
42 changes: 42 additions & 0 deletions client/src/app/context/MessageProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { createContext, useContext } from "react";
import { Message } from "../types";
import React from "react";

const MessageContext = createContext<{
messages: Message[];
removeMessage: (index: number) => void;
addMessage: (message: Message) => void;
}>({
messages: [],
removeMessage: () => {},
addMessage: () => {},
});

export function MessageProvider({ children }: { children: React.ReactNode }) {
const [messages, setMessages] = React.useState<Message[]>([]);

const removeMessage = (index: number) => {
const newMessages = [...messages];
newMessages.splice(index, 1);
setMessages(newMessages);
};

const addMessage = (message: Message) => {
setMessages([...messages, message]);
};

return (
<MessageContext.Provider value={{ messages, removeMessage, addMessage }}>
{children}
</MessageContext.Provider>
);
}

export function useMessageProvider() {
const { messages, removeMessage, addMessage } = useContext(MessageContext);
return {
messages,
removeMessage,
addMessage,
};
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export { useImmutableProvider, ImmutableProvider } from "./ImmutableProvider";
export { usePassportProvider, PassportProvider } from "./PassportProvider";
export { useWagmiProvider, WagmiProvider } from "./WagmiProvider";
export { useViemProvider, ViemProvider } from "./ViemProvider";
export { useMessageProvider, MessageProvider } from "./MessageProvider";
2 changes: 1 addition & 1 deletion client/src/app/hooks/useCraft.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useConnect, useWriteContract } from "wagmi";
import { GuardedMulticaller2Abi, ImmutableERC1155Abi, ImmutableERC721Abi } from "@imtbl/contracts";
import { Address, Collection, CraftResult } from "../types";
import { usePassportProvider, useViemProvider } from "@/context";
import { usePassportProvider, useViemProvider } from "@/app/context";

type Call = {
target: `0x${string}`;
Expand Down
2 changes: 1 addition & 1 deletion client/src/app/hooks/useQuery.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useQuery } from "@tanstack/react-query";
import { Address, Collection, NFT, Recipe } from "../types";
import { useImmutableProvider, usePassportProvider, useViemProvider, useWagmiProvider } from "@/context";
import { useImmutableProvider, usePassportProvider, useViemProvider, useWagmiProvider } from "@/app/context";
import { getContract } from "viem";
import { immutableErc1155Abi } from "@imtbl/contracts/dist/abi/generated";

Expand Down
12 changes: 10 additions & 2 deletions client/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
"use client";
import { BiomeCombinedProviders } from "@biom3/react";
import { onDarkBase } from "@biom3/design-tokens";
import { ImmutableProvider, PassportProvider, WagmiProvider, ViemProvider } from "../context";
import {
ImmutableProvider,
PassportProvider,
WagmiProvider,
ViemProvider,
MessageProvider,
} from "./context";
import "./globals.css";
import Layout from "./components/Layout/Layout";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
Expand All @@ -22,7 +28,9 @@ export default function RootLayout({
<ImmutableProvider>
<PassportProvider>
<BiomeCombinedProviders skipFontLoad theme={{ base: onDarkBase }}>
<Layout>{children}</Layout>
<MessageProvider>
<Layout>{children}</Layout>
</MessageProvider>
</BiomeCombinedProviders>
</PassportProvider>
</ImmutableProvider>
Expand Down
2 changes: 1 addition & 1 deletion client/src/app/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { Heading } from "@biom3/react";
import { useEffect } from "react";

import { usePassportProvider } from "@/context";
import { usePassportProvider } from "@/app/context";

export default function Login() {
const { loginCallback, userInfo } = usePassportProvider();
Expand Down
5 changes: 5 additions & 0 deletions client/src/app/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,8 @@ export type Address = `0x${string}`
export type Collection = {
address: Address;
}

export type Message = {
status: 'success' | 'fatal';
message: string;
}
14 changes: 13 additions & 1 deletion client/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1894,7 +1894,19 @@
resolved "https://registry.yarnpkg.com/@rive-app/canvas-lite/-/canvas-lite-2.20.0.tgz#2ff253e0c59560ca03a75551721368adb39af5ac"
integrity sha512-tvZokI/oZh1PLyMn4v7YQXlKz8MkrHQuoQ6upVcNwOxWxXnfwL5zeE/fguUEbPYZ22d1oKQ7pO5Imr5fjk8KjQ==

"@rive-app/react-canvas-lite@^4.13.8", "@rive-app/react-canvas-lite@^4.9.0":
"@rive-app/[email protected]":
version "2.20.2"
resolved "https://registry.yarnpkg.com/@rive-app/canvas-lite/-/canvas-lite-2.20.2.tgz#e9b2c63b16476129bbdbd2410c4c46ddb14a5256"
integrity sha512-Eqy9D1qFI7jOESFtLJMDOiiRUSGOMeERsVVJC33xkQXySxaJ9sgvLUzN6RPdgwFlOjEmOhy5QWyQ/8B6r1xJ+w==

"@rive-app/react-canvas-lite@^4.13.10":
version "4.13.10"
resolved "https://registry.yarnpkg.com/@rive-app/react-canvas-lite/-/react-canvas-lite-4.13.10.tgz#6d8f4b07ea8ef828bbdb7431197be58fa0104c0e"
integrity sha512-JXbBfRimZUtlAtr5tXM22CmMYwnqNjqEEH7bfnJ3VgS6FUHv+Lw1BeoMPdam4vRMm1guuZu8HsvQn91U08fr5g==
dependencies:
"@rive-app/canvas-lite" "2.20.2"

"@rive-app/react-canvas-lite@^4.9.0":
version "4.13.8"
resolved "https://registry.yarnpkg.com/@rive-app/react-canvas-lite/-/react-canvas-lite-4.13.8.tgz#e6665207dac1c665c79fd130cfd9bbbb955d1968"
integrity sha512-0InycO7Eon03++Z4HfkqTOFLU2fIcw2GUZFz5k6GPjIeF3bhBIG9jfULcFVLpac94Ce/VuVfsq38+9qoq9HWUA==
Expand Down

0 comments on commit af63d75

Please sign in to comment.