Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Completed advanced mode in OpenCommitmentActionPanel #37

Merged
merged 4 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"scripts": {
"dev": "next dev",
"build": "next build",
"build:dev": "__NEXT_TEST_MODE=1 next build",
"start": "next start",
"lint": "next lint"
},
Expand Down
82 changes: 59 additions & 23 deletions apps/web/src/app/game/[gameId]/OpenCommitmentActionPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
"use client";

// 3rd-parties components
import { type FormEvent, useCallback, useState } from "react";
import { type FormEvent, useCallback, useState, useRef, useEffect } from "react";
import { useAccount, useWriteContract } from "wagmi";
import {
Button,
FormControl,
FormLabel,
FormErrorMessage,
HStack,
Input,
InputGroup,
InputLeftAddon,
Switch,
VStack,
} from "@chakra-ui/react";
import { useLocalStorage } from "@uidotdev/usehooks";
Expand All @@ -30,7 +33,7 @@ export default function OpenCommitmentActionPanel({
game: GameView;
hasOpened: boolean;
}) {
const advancedMode = false;
const [advancedMode, setAdvancedMode] = useState<boolean>(false);
const { address: userAccount } = useAccount();
const contractCfg = useGameContractConfig();
const { writeContractAsync, isPending } = useWriteContract();
Expand All @@ -41,6 +44,10 @@ export default function OpenCommitmentActionPanel({
);
const [openingError, setOpeningError] = useState<string>("");
const sleepAndGotoURL = useSleepAndGotoURL();
// For setting the initial value of the two form inputs
const subRef = useRef<HTMLInputElement>(null);
const nullRef = useRef<HTMLInputElement>(null);
const [refSet, setRefSet] = useState<boolean>(false);

const openCommitment = useCallback(
async (ev: FormEvent) => {
Expand All @@ -49,8 +56,8 @@ export default function OpenCommitmentActionPanel({
const formValues = Object.fromEntries(formData.entries());
const { submission, nullifier } = formValues;

if (typeof submission === "undefined" || typeof nullifier === "undefined") {
return setOpeningError("Please enter a value for submission & nullifier");
if (!submission || !nullifier) {
return setOpeningError("Please enter a value for submission and nullifier.");
}

const fullProof = await generateFullProof(
Expand All @@ -71,35 +78,64 @@ export default function OpenCommitmentActionPanel({
[gameId, contractCfg, setLog, sleepAndGotoURL, writeContractAsync]
);

useEffect(() => {
!refSet && subRef.current && (subRef.current.value = subNull.submission.toString());
!refSet && nullRef.current && (nullRef.current.value = subNull.nullifier);
setRefSet(true);
}, [subNull, refSet]);

return hasOpened ? (
<Button variant="outline" colorScheme="yellow" isDisabled={true}>
Waiting for other players to open...
</Button>
) : (
<form onSubmit={openCommitment}>
<VStack spacing={3} border="1px" borderColor="gray.200" borderRadius="8" p={4}>
<VStack w="300px" spacing={3} border="1px" borderColor="gray.200" borderRadius="8" p={4}>
<FormControl isInvalid={!!openingError}>
<FormLabel>Open Commitment</FormLabel>

<InputGroup display={advancedMode ? "block" : "none"}>
<InputLeftAddon>Commitment</InputLeftAddon>
<Input
id="submission"
name="submission"
type={advancedMode ? "number" : "hidden"}
value={subNull?.["submission"]}
/>
</InputGroup>
<VStack spacing={3} alignItems="stretch">
{/* Advanced mode toggle */}
<HStack justify="space-between" align="center">
<FormLabel htmlFor="form-advanced-mode" mb="0">
Advanced Mode
</FormLabel>
<Switch
id="form-advanced-mode"
onChange={(e) => {
setAdvancedMode(e.target.checked);
setOpeningError("");
}}
/>
</HStack>

<InputGroup size="sm" display={advancedMode ? "flex" : "none"}>
<InputLeftAddon color="blue.800" fontWeight="medium">
Commitment
</InputLeftAddon>
<Input
ref={subRef}
id="submission"
name="submission"
type={advancedMode ? "number" : "hidden"}
onChange={() => setOpeningError("")}
/>
</InputGroup>

<InputGroup display={advancedMode ? "block" : "none"}>
<InputLeftAddon>Nullifier</InputLeftAddon>
<Input
id="nullifier"
name="nullifier"
type={advancedMode ? "number" : "hidden"}
value={subNull?.["nullifier"]}
/>
</InputGroup>
<InputGroup size="sm" display={advancedMode ? "flex" : "none"}>
<InputLeftAddon color="blue.800" fontWeight="medium">
Nullifier
</InputLeftAddon>
<Input
ref={nullRef}
id="nullifier"
name="nullifier"
type={advancedMode ? "number" : "hidden"}
onChange={() => () => setOpeningError("")}
/>
</InputGroup>
</VStack>
<FormErrorMessage>{openingError}</FormErrorMessage>
</FormControl>
<Button colorScheme="yellow" type="submit" isLoading={isPending}>
Open Commitment
Expand Down
72 changes: 38 additions & 34 deletions apps/web/src/components/PageContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,44 @@ import { projectInfo } from "@/config";
import { useLogContext } from "@/context/LogContext";
import { Web3Connect } from "@/components";

export default function PageContainer({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
const { log } = useLogContext();
const { walletInfo } = useWalletInfo();

return (
<VStack spacing={0} align="stretch" height="100vh">
<Header />
<VStack flex="1" spacing={0} alignItems="center" align="stretch" height="90vh">
<Box flex="1" alignItems="center">
{walletInfo ? <>{children}</> : <PromptForWalletConnect />}
</Box>
{log && (
<Box
position="fixed"
bottom="10"
left="0"
right="0"
borderTopWidth="1px"
borderTopColor="text.600"
backgroundColor="darkBlueBg"
color="white"
p={2}
textAlign="center"
>
{log.endsWith("...") && <Spinner color="primary.400" />}
<Text>{log}</Text>
</Box>
)}
</VStack>
<Footer />
</VStack>
);
}

function PromptForWalletConnect() {
return (
<VStack align="center" justify="center" height="80vh">
Expand Down Expand Up @@ -83,37 +121,3 @@ function Header() {
</HStack>
);
}

export default function PageContainer({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
const { log } = useLogContext();
const { walletInfo } = useWalletInfo();

return (
<VStack spacing={0} align="stretch" height="100vh">
<Header />
<Box flex="1" alignItems="center">
{walletInfo ? <>{children}</> : <PromptForWalletConnect />}
{log && (
<HStack
flexBasis="56px"
borderTopWidth="1px"
borderTopColor="text.600"
backgroundColor="darkBlueBg"
align="center"
justify="center"
spacing="4"
p="4"
>
{log.endsWith("...") && <Spinner color="primary.400" />}
<Text>{log}</Text>
</HStack>
)}
</Box>
<Footer />
</VStack>
);
}