mirror of
https://github.com/felipefg/doom-arena.git
synced 2026-05-05 03:00:25 -04:00
Home page displaying active contest
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
"react-icons": "^4",
|
||||
"react-jazzicon": "^1",
|
||||
"react-use-downloader": "^1.2.4",
|
||||
"swr": "^2",
|
||||
"urql": "^4",
|
||||
"viem": "^1",
|
||||
"wagmi": "^1"
|
||||
|
||||
@@ -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}
|
||||
/>
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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>
|
||||
),
|
||||
|
||||
41
frontend/src/components/DifficultyLevelPicker.tsx
Normal file
41
frontend/src/components/DifficultyLevelPicker.tsx
Normal 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>
|
||||
),
|
||||
}))}
|
||||
/>
|
||||
);
|
||||
};
|
||||
56
frontend/src/hooks/inspect.ts
Normal file
56
frontend/src/hooks/inspect.ts
Normal 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 };
|
||||
};
|
||||
20
frontend/src/model/index.ts
Normal file
20
frontend/src/model/index.ts
Normal 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[];
|
||||
}
|
||||
Reference in New Issue
Block a user