Home page displaying active contest

This commit is contained in:
Danilo Tuler
2023-09-23 17:15:48 -04:00
parent 3dafe8a682
commit 9589bee0df
8 changed files with 182 additions and 24 deletions

View File

@@ -1,3 +1,4 @@
NEXT_PUBLIC_GRAPHQL_URL=http://127.0.0.1:8080/graphql
NEXT_PUBLIC_INSPECT_URL=http://127.0.0.1:8080/inspect
NEXT_PUBLIC_TOKEN_ADDRESS=0xae7f61eCf06C65405560166b259C54031428A9C4
NEXT_PUBLIC_DAPP_ADDRESS=0x70ac08179605AF2D9e75782b8DEcDD3c22aA4D0C

View File

@@ -29,6 +29,7 @@
"react-icons": "^4",
"react-jazzicon": "^1",
"react-use-downloader": "^1.2.4",
"swr": "^2",
"urql": "^4",
"viem": "^1",
"wagmi": "^1"

View File

@@ -22,7 +22,7 @@ import {
useErc20PortalDepositErc20Tokens,
usePrepareErc20PortalDepositErc20Tokens,
} from "../../hooks/contracts";
import { DifficultyLevel } from "../../components/DifficultyLevel";
import { DifficultyLevelPicker } from "../../components/DifficultyLevelPicker";
import { GameLevel } from "../../components/GameLevel";
const parseIfNeeded = (setter: (v: number) => void) => {
@@ -159,7 +159,7 @@ const CreateGame: FC = () => {
onChange={parseIfNeeded(setSubmissionTime)}
description="Amount of time players will have to submit their gameplay"
/>
<DifficultyLevel
<DifficultyLevelPicker
onChange={setDifficulty}
value={difficulty}
/>

View File

@@ -1,26 +1,70 @@
"use client";
import React, { FC } from "react";
import { Button, Center, Stack } from "@mantine/core";
import { Button, Center, Stack, Text, Title } from "@mantine/core";
import Image from "next/image";
import Link from "next/link";
import { useInspect } from "../hooks/inspect";
import { Contest } from "../model";
import { DifficultyLevel } from "../components/DifficultyLevel";
import { formatUnits, Hex, hexToBigInt } from "viem";
const Home: FC = () => {
const {
report: contest,
error,
data,
} = useInspect<Contest>(`/active_contest`);
const c = {
contest_id: 1,
name: "Contest",
host: "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92261",
ticket_price: "0x8ac7230489e80000",
level: 1,
difficulty: 3,
play_time: 3600,
submission_time: 3600,
creation_timestamp: 1695505002,
state: "finalized",
players: [
{
wallet: "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",
score: 123,
reward: null,
},
{
wallet: "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92267",
score: null,
reward: null,
},
],
prize_pool: "0x32d26d12e980b600000",
};
return (
<Center>
<Stack align="center">
<Image
src="/img/logo.png"
width={960}
height={570}
alt="banner"
/>
<Link href="/create">
<Button>Create Game</Button>
</Link>
<Link href="/play">
<Button>Play Game</Button>
</Link>
{!c && (
<>
<Image
src="/img/logo.png"
width={960}
height={570}
alt="banner"
/>
<Link href="/create">
<Button size="lg">Create Contest</Button>
</Link>
</>
)}
<Title>{c.name}</Title>
<Text>Hosted by {c.host}</Text>
<DifficultyLevel value={c.difficulty} />
<Text size="sm">
{formatUnits(hexToBigInt(c.ticket_price as Hex), 18)} APE to
signup
</Text>
<Button size="lg">Play Now</Button>
</Stack>
</Center>
);

View File

@@ -1,4 +1,4 @@
import { Image, SegmentedControl, Stack, Text } from "@mantine/core";
import { Image, Overlay, SegmentedControl, Stack, Text } from "@mantine/core";
import { FC } from "react";
export const difficultyLevels = [
@@ -9,30 +9,25 @@ export const difficultyLevels = [
];
export type DifficultyLevelProps = {
onChange(value: number): void;
value: number;
};
export const DifficultyLevel: FC<DifficultyLevelProps> = ({
onChange,
value,
}) => {
export const DifficultyLevel: FC<DifficultyLevelProps> = ({ value }) => {
return (
<SegmentedControl
pt={30}
onChange={(value) => onChange(parseInt(value))}
value={value.toString()}
data={difficultyLevels.map((level, index) => ({
value: index.toString(),
label: (
<Stack>
<Text size="sm">{level.label}</Text>
{index != value && <Overlay backgroundOpacity={0.8} />}
<Image
height={171}
width={128}
src={level.image}
alt={level.label}
onMouseEnter={(event) => event.target}
/>
</Stack>
),

View File

@@ -0,0 +1,41 @@
import { Image, Overlay, SegmentedControl, Stack, Text } from "@mantine/core";
import { FC } from "react";
export const difficultyLevels = [
{ label: "I'm Too Young to Die", image: "/img/difficulty1.png" },
{ label: "Hurt Me Plenty", image: "/img/difficulty2.png" },
{ label: "Ultra Violence", image: "/img/difficulty3.png" },
{ label: "Nightmare", image: "/img/difficulty4.png" },
];
export type DifficultyLevelPickerProps = {
onChange(value: number): void;
value: number;
};
export const DifficultyLevelPicker: FC<DifficultyLevelPickerProps> = ({
onChange,
value,
}) => {
return (
<SegmentedControl
pt={30}
onChange={(value) => onChange(parseInt(value))}
value={value.toString()}
data={difficultyLevels.map((level, index) => ({
value: index.toString(),
label: (
<Stack>
<Text size="sm">{level.label}</Text>
<Image
height={171}
width={128}
src={level.image}
alt={level.label}
/>
</Stack>
),
}))}
/>
);
};

View File

@@ -0,0 +1,56 @@
import useSWR, { Key, SWRResponse } from "swr";
import { bytesToString, toBytes } from "viem";
const baseURL = process.env.NEXT_PUBLIC_INSPECT_URL;
export enum InspectStatus {
Accepted = "Accepted",
Rejected = "Rejected",
Exception = "Exception",
MachineHalted = "MachineHalted",
CycleLimitExceeded = "CycleLimitExceeded",
TimeLimitExceeded = "TimeLimitExceeded",
}
export interface InspectReport {
payload: string;
}
export interface InspectMetadata {
active_epoch_index: number;
current_input_index: number;
}
export interface InspectResponse {
status: InspectStatus;
exception_payload: string;
reports: InspectReport[];
metadata: InspectMetadata;
}
type ReportResponse<TReport> = {
report?: TReport;
};
export type UseInspect<TReport> = SWRResponse<InspectResponse> &
ReportResponse<TReport>;
export const useInspect = <TReport>(key: Key): UseInspect<TReport> => {
const swr = useSWR<InspectResponse>(() =>
key ? `${baseURL}${key}` : false
);
const response = swr.data;
let report = undefined;
if (
response &&
response.status == InspectStatus.Accepted &&
response.reports.length > 0
) {
const r = response.reports[0];
const data = bytesToString(toBytes(r.payload));
report = JSON.parse(data) as TReport;
}
return { ...swr, report };
};

View File

@@ -0,0 +1,20 @@
export interface Player {
wallet: string;
score: number;
reward: string;
}
export interface Contest {
contest_id: number;
name: string;
host: string;
ticket_price: string;
prize_pool: string;
level: number;
difficulty: number;
creation_timestamp: number;
play_time: number;
submission_time: number;
state: "ready_to_play" | "gameplay_submission" | "finalized";
players: Player[];
}