Skip to content

Commit d15af18

Browse files
authored
Prettify UI (#8)
* begin refactoring to a ltotery card state * update lott state card * update and include play button * begin updating the damn monoliuth website intop components. fuck my life * update --------- Co-authored-by: James <11054922+entrancedjames@users.noreply.github.com>
1 parent 771722c commit d15af18

File tree

17 files changed

+384
-356
lines changed

17 files changed

+384
-356
lines changed

‎CHANGELOG.md‎

Lines changed: 0 additions & 128 deletions
This file was deleted.

‎codegen/CwLotto.types.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export type Timestamp = Uint64;
7878
export type Uint64 = string;
7979
export interface LotteryStateResponse {
8080
lotto_state: LotteryState;
81+
total_tickets: number;
8182
}
8283
export interface TicketResponse {
8384
tickets?: number | null;

‎components/forms/buy-tickets.tsx‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import {Coin, Config} from "../../codegen/CwLotto.types";
2+
import {Button, Form} from "semantic-ui-react";
3+
import {ChangeEvent, useState} from "react";
4+
import {CwLottoClient} from "../../codegen/CwLotto.client";
5+
6+
interface BuyTicketsProps {
7+
cwLottoClient: CwLottoClient,
8+
config: Config,
9+
}
10+
11+
export const BuyTicketsForm: React.FC<BuyTicketsProps> = ({cwLottoClient, config}: {
12+
cwLottoClient: CwLottoClient,
13+
config: Config
14+
}) => {
15+
const [inputValue, setInputValue] = useState<string | ReadonlyArray<string> | number | undefined>(undefined);
16+
const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {
17+
setInputValue(Number(event.target.value));
18+
};
19+
20+
const handleButtonClick = async () => {
21+
let parsedInputValue = Number(inputValue);
22+
let totalCost = Number(inputValue) * Number(config.ticket_unit_cost.amount);
23+
let fee: Coin = {amount: totalCost.toString(), denom: config.ticket_unit_cost.denom};
24+
await cwLottoClient.buyTicket({numTickets: parsedInputValue}, "auto", undefined, [fee]);
25+
};
26+
27+
return <><Form>
28+
<Form.Input
29+
type="number"
30+
label="Number of Tickets"
31+
placeholder="Enter a number"
32+
value={inputValue}
33+
onChange={handleInputChange}
34+
/>
35+
<Button onClick={handleButtonClick} type='submit'>Buy</Button>
36+
</Form>
37+
</>
38+
}

‎components/forms/claim-button.tsx‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import {useEffect, useState} from "react";
2+
import {CwLottoClient} from "../../codegen/CwLotto.client";
3+
import {Button} from "semantic-ui-react";
4+
import {useChain} from "@cosmos-kit/react";
5+
import {chainName} from "../../config";
6+
7+
interface ClaimButtonProps {
8+
contractAddr: string
9+
}
10+
11+
export const ClaimButton: React.FC<ClaimButtonProps> = ({contractAddr}) => {
12+
const {address, getSigningCosmWasmClient, getRestEndpoint, getRpcEndpoint, chain} = useChain(chainName);
13+
const [signingClient, setSigningClient] = useState<CwLottoClient | null>(null);
14+
// only is rendered during component claimed. ok so this page will be responsible for generating
15+
// the assumption before initiating this component is that the state is in closed
16+
useEffect(() => {
17+
if (!address) {
18+
return
19+
}
20+
getSigningCosmWasmClient()
21+
.then(signingCWClient => {
22+
if (!signingCWClient || !address) {
23+
console.error("cosmwasmClient undefined or address undefined.");
24+
return;
25+
}
26+
setSigningClient(new CwLottoClient(signingCWClient, address, contractAddr));
27+
});
28+
}, [address, contractAddr, getSigningCosmWasmClient]);
29+
30+
const handleButtonClick = async () => {
31+
await signingClient?.claimTokens("auto", undefined, []);
32+
};
33+
34+
return (<>
35+
<Button onClick={handleButtonClick}>Claim your winnings!</Button>
36+
</>);
37+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import {useEffect, useState} from "react";
2+
3+
export interface CountdownCardProps {
4+
finalDate: Date
5+
}
6+
7+
interface TimeLeft {
8+
days: number;
9+
hours: number;
10+
minutes: number;
11+
seconds: number;
12+
}
13+
14+
export const CountdownCard: React.FC<CountdownCardProps> = ({finalDate}) => {
15+
const calculateTimeLeft = () => {
16+
const difference = finalDate.getTime() - new Date().getTime();
17+
18+
if (difference <= 0) {
19+
return {
20+
days: 0,
21+
hours: 0,
22+
minutes: 0,
23+
seconds: 0,
24+
} as TimeLeft;
25+
}
26+
27+
const days = Math.floor(difference / (1000 * 60 * 60 * 24));
28+
const hours = Math.floor((difference / (1000 * 60 * 60)) % 24);
29+
const minutes = Math.floor((difference / 1000 / 60) % 60);
30+
const seconds = Math.floor((difference / 1000) % 60);
31+
32+
return {
33+
days,
34+
hours,
35+
minutes,
36+
seconds,
37+
} as TimeLeft;
38+
};
39+
40+
const [timeLeft, setTimeLeft] = useState(calculateTimeLeft());
41+
42+
useEffect(() => {
43+
const timer = setTimeout(() => {
44+
setTimeLeft(calculateTimeLeft());
45+
}, 1000);
46+
return () => clearTimeout(timer);
47+
}, [calculateTimeLeft, timeLeft]);
48+
49+
return (
50+
<div>
51+
<p>
52+
{timeLeft.days} days {timeLeft.hours} hours {timeLeft.minutes} minutes {timeLeft.seconds} seconds left
53+
</p>
54+
</div>
55+
);
56+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import {Button, Header} from "semantic-ui-react";
2+
import {Config, LotteryState} from "../../codegen/CwLotto.types";
3+
import React from "react";
4+
import {CountdownCard} from "./countdown-card";
5+
6+
export interface LotteryStateCardProps {
7+
lotteryState: LotteryState,
8+
lotteryConfig: Config,
9+
showPlayButton: boolean
10+
}
11+
12+
export const LotteryStateCard: React.FC<LotteryStateCardProps> = ({lotteryState, lotteryConfig, showPlayButton}) => {
13+
return (<>
14+
<Header as='h3' style={{fontSize: '2em'}}>
15+
{
16+
"OPEN" in lotteryState ? (
17+
<>Lottery is Open</>
18+
) : "CHOOSING" in lotteryState ? (
19+
<>Waiting for lottery to be executed</>
20+
) : "CLOSED" in lotteryState ? (
21+
<>Lottery has finished</>
22+
) : <>Unknown lottery state reached</>
23+
}
24+
</Header>
25+
{
26+
"OPEN" in lotteryState && "at_time" in lotteryState.OPEN.expiration &&
27+
<CountdownCard finalDate={new Date(Number(lotteryState.OPEN.expiration.at_time) / 1e6)}/>
28+
}
29+
Cost per Ticket: {lotteryConfig.ticket_unit_cost.amount}{lotteryConfig.ticket_unit_cost.denom}
30+
<p>
31+
{
32+
"OPEN" in lotteryState ? (
33+
<>Lottery is open state.</>
34+
) : "CHOOSING" in lotteryState ? (
35+
<>The lottery is waiting to be executed on the chain.</>
36+
) : "CLOSED" in lotteryState ? (
37+
<>Lottery has completed. Winner is: {lotteryState.CLOSED.winner} and {lotteryState.CLOSED.claimed ? (<>has been claimed</>) : (<>has not been claimed</>)}</>
38+
) : <>Unknown lottery state reached</>
39+
}
40+
</p>
41+
{ showPlayButton && <> {
42+
"OPEN" in LotteryStateCard ? (
43+
<Button>Play</Button>
44+
): <Button>View</Button> // Default is view
45+
}</>}
46+
</>
47+
)
48+
}

‎components/react/ticket-card.tsx‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import {Icon, Segment} from "semantic-ui-react";
2+
3+
export interface TicketCardProps {
4+
numTickets: number | undefined | null
5+
}
6+
7+
export const TicketCard: React.FC<TicketCardProps> = ({numTickets}) => {
8+
return (
9+
<Segment>
10+
{numTickets ? (
11+
<p><Icon name='ticket' /> Ticket count is {numTickets}</p>
12+
) : (<p>No tickets bought yet</p>
13+
)}
14+
</Segment>
15+
)
16+
}

‎config/defaults.ts‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,6 @@ import { AssetList, Asset } from '@chain-registry/types';
44
export const chainName = 'junotestnet';
55
export const STAKINGDENOM = 'ujunox';
66

7-
export const FREEDOM_LIST: string[] = [
8-
'juno1law3szlnn4snqe6gylgt3h7r003e549fjs9sl9tf6zh3w480e33shlqrlp',
9-
'juno1w4lgq9mvlvtldf0q9thqtaq986tuhy3j7jneq68lc4xhecvaa9aq8mzqhc',
10-
];
11-
127
export const chainassets: AssetList = assets.find(
138
(chain) => chain.chain_name === chainName
149
) as AssetList;

‎config/lottery.ts‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export const FREEDOM_LIST: string[] = [
2+
'juno1law3szlnn4snqe6gylgt3h7r003e549fjs9sl9tf6zh3w480e33shlqrlp',
3+
'juno1w4lgq9mvlvtldf0q9thqtaq986tuhy3j7jneq68lc4xhecvaa9aq8mzqhc',
4+
];
5+
6+
export const PRIMARY_RUNNING_LOTTERY = FREEDOM_LIST[0];

‎hooks/use-cw-lotto-state.ts‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ export function useCwLottoState(contractAddress: string) {
1111
chain: chainInfo,
1212
getCosmWasmClient,
1313
} = useChain(chainName);
14-
1514
const [queryClient, setQueryClient] = useState<CwLottoQueryClient | null>(null);
1615

1716
useEffect(() => {
@@ -28,10 +27,7 @@ export function useCwLottoState(contractAddress: string) {
2827

2928
useEffect(() => {
3029
if (queryClient && address) {
31-
queryClient.lotteryState().then((lotteryStateResp => {
32-
let y = lotteryStateResp.lotto_state;
33-
setState(y);
34-
}))
30+
queryClient.lotteryState().then(lotteryStateResp => setState(lotteryStateResp.lotto_state))
3531
}
3632
}, [queryClient, address]);
3733

0 commit comments

Comments
 (0)