Skip to content

Commit

Permalink
feat: add frontend design
Browse files Browse the repository at this point in the history
  • Loading branch information
irisdv committed May 24, 2024
1 parent d7120e1 commit 4334bab
Show file tree
Hide file tree
Showing 54 changed files with 9,701 additions and 2,091 deletions.
18 changes: 18 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Unit Tests

on:
push:
branches:
- main
pull_request:
branches: [main]

jobs:
Jest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Run Tests
run: |
npm install --legacy-peer-deps
npm test
44 changes: 44 additions & 0 deletions app/components/button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"use client";

import React, { FunctionComponent } from "react";
import styles from "../styles/components/button.module.css";
import { CircularProgress } from "@mui/material";

type ButtonProps = {
onClick: () => void;
children: string;
icon?: React.ReactNode;
width?: number;
loading?: boolean;
};

const Button: FunctionComponent<ButtonProps> = ({
children,
onClick,
icon,
width = 0,
loading = false,
}) => {
return (
<div
className={styles.svgBorder}
onClick={onClick}
style={{ width: `${width ? width + "px" : "auto"} ` }}
>
<div className={styles.btnContainer}>
{loading || icon ? (
<div className={styles.btnIcon}>
{loading ? (
<CircularProgress size={24} sx={{ color: "#4C6449" }} />
) : (
icon
)}
</div>
) : null}
<div className={styles.btnText}>{children}</div>
</div>
</div>
);
};

export default Button;
42 changes: 42 additions & 0 deletions app/components/countdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"use client";

import React, { FunctionComponent, useEffect, useState } from "react";
import styles from "../styles/components/countdown.module.css";
import { formatTime } from "@/utils/stringService";

type CountdownProps = {};

const Countdown: FunctionComponent<CountdownProps> = ({}) => {
const [timeRemaining, setTimeRemaining] = useState(120); // in seconds
const formattedTime = formatTime(timeRemaining);
const [minutes, seconds] = formattedTime.split(":");

useEffect(() => {
const timer = setInterval(() => {
setTimeRemaining((prevTime) => (prevTime > 0 ? prevTime - 1 : 0));
}, 1000);

// Cleanup interval on component unmount
return () => clearInterval(timer);
}, []);

return (
<>
<div className={styles.countdownWrapper}>
<div className={styles.countdown}>{minutes[0]}</div>
</div>
<div className={styles.countdownWrapper}>
<div className={styles.countdown}>{minutes[1]}</div>
</div>
<div>:</div>
<div className={styles.countdownWrapper}>
<div className={styles.countdown}>{seconds[0]}</div>
</div>
<div className={styles.countdownWrapper}>
<div className={styles.countdown}>{seconds[1]}</div>
</div>
</>
);
};

export default Countdown;
23 changes: 23 additions & 0 deletions app/components/ethButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"use client";

import React, { FunctionComponent } from "react";
import styles from "../styles/components/ethButton.module.css";

type EthButtonProps = {
onClick: () => void;
};

const EthButton: FunctionComponent<EthButtonProps> = ({ onClick }) => {
return (
<div className={styles.base} onClick={onClick}>
<div className={styles.innerCircle}>
<div className={styles.content}>
<img src="/visuals/ethereumIcon.svg" alt="ethereum icon" />
<p>PRESS</p>
</div>
</div>
</div>
);
};

export default EthButton;
39 changes: 39 additions & 0 deletions app/components/modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from "react";
import styles from "../styles/components/modal.module.css";
import { FunctionComponent, ReactNode } from "react";
import { Modal } from "@mui/material";

type ModalMessageProps = {
title: string;
message: ReactNode;
closeModal: () => void;
open: boolean;
};

const ModalMessage: FunctionComponent<ModalMessageProps> = ({
title,
message,
closeModal,
open,
}) => {
return (
<Modal
disableAutoFocus
open={open}
onClose={closeModal}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<div className={styles.menu_wrapper}>
<div className={styles.menu}>
<p className={styles.menu_title}>{title}</p>
{message}
<div onClick={closeModal} className={styles.menu_close}>
Close
</div>
</div>
</div>
</Modal>
);
};
export default ModalMessage;
108 changes: 108 additions & 0 deletions app/components/starknetConnect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
"use client";

import React, { FunctionComponent } from "react";
import { Modal, useMediaQuery } from "@mui/material";
import { Connector } from "starknetkit";
import styles from "../styles/components/walletConnect.module.css";
import {
getConnectorDiscovery,
getConnectorIcon,
getConnectorName,
sortConnectors,
} from "@/utils/starknetConnectorsWrapper";
import Button from "./button";

type StarknetWalletConnectProps = {
closeModal: () => void;
open: boolean;
connectors: Connector[];
connectWallet: (connector: Connector) => void;
};

const StarknetWalletConnect: FunctionComponent<StarknetWalletConnectProps> = ({
closeModal,
open,
connectors,
connectWallet,
}) => {
const connect = (connector: Connector) => {
connectWallet(connector);
closeModal();
};
const isMobile = useMediaQuery("(max-width: 768px)");

const filterConnectors = (connectors: Connector[]) => {
if (!isMobile) return connectors;
return connectors.filter((connector) => connector.id !== "argentMobile");
};

const getWalletName = (connectorId: string, isAvailable: boolean): string => {
return `${!isAvailable ? "Install " : ""}${
connectorId === "argentX" && isMobile
? "Argent"
: getConnectorName(connectorId)
}`;
};

return (
<Modal
disableAutoFocus
open={open}
onClose={closeModal}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
componentsProps={{
backdrop: {
sx: {
backdropFilter: "blur(4px)",
backgroundColor: "rgba(0, 0, 0, 0.5)",
},
},
}}
>
<div className={styles.menu_wrapper}>
<div className={styles.menu}>
<div className={styles.modalContent}>
<div className={styles.modalTitle}>
Connect <span>to</span>
</div>
{sortConnectors(filterConnectors(connectors)).map(
(connector: Connector) => {
const isAvailable = connector.available();
return (
<div
key={connector.id}
className={styles.wallet}
onClick={
isAvailable
? () => connect(connector)
: () => window.open(getConnectorDiscovery(connector.id))
}
>
<Button
onClick={() => console.log("Open connect wallet modal")}
icon={
<img
src={getConnectorIcon(connector.id)}
className={styles.walletIcon}
/>
}
width={300}
>
{getWalletName(connector.id, isAvailable)}
</Button>
</div>
);
}
)}
<div onClick={closeModal} className={styles.menu_close}>
Close
</div>
</div>
</div>
</div>
</Modal>
);
};

export default StarknetWalletConnect;
31 changes: 31 additions & 0 deletions app/components/stats.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"use client";

import React, { FunctionComponent } from "react";
import styles from "../styles/components/stats.module.css";

type StatsProps = {};

const Stats: FunctionComponent<StatsProps> = ({}) => {
const clickNumber: number = 0;
const timeClicked: number = 0;
const totalParticipants = 126702;

return (
<div className={styles.statsSections}>
<div className={styles.statsSection}>
<p>Click number</p>
<p>{clickNumber !== 0 ? clickNumber.toLocaleString("en-US") : "--"}</p>
</div>
<div className={styles.statsSection}>
<p>Time clicked</p>
<p>{timeClicked !== 0 ? timeClicked.toLocaleString("en-US") : "--"}</p>
</div>
<div className={styles.statsSection}>
<p>Total participants</p>
<p>{totalParticipants.toLocaleString("en-US")}</p>
</div>
</div>
);
};

export default Stats;
33 changes: 0 additions & 33 deletions app/globals.css

This file was deleted.

38 changes: 32 additions & 6 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,36 @@
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";

const inter = Inter({ subsets: ["latin"] });
import "./styles/globals.css";
import { Providers } from "./provider";

// todo: update with right text
export const metadata: Metadata = {
title: "Create Next App",
title: "The ETH button",
description: "Generated by create next app",
metadataBase: new URL(process.env.NEXT_PUBLIC_APP_LINK as string),
// openGraph: {
// title: "The ETH button",
// description: "Generated by create next app",
// url: process.env.NEXT_PUBLIC_APP_LINK,
// siteName: "The ETH button",
// images: [
// {
// url: "/visuals/twitterImage.webp",
// width: 680,
// height: 680,
// },
// ],
// locale: "en_US",
// type: "website",
// },
// icons: {
// icon: "/icons/theethbutton.svg",
// },
// twitter: {
// card: "summary_large_image",
// title: "The ETH button",
// description: "Generated by create next app",
// images: ["/visuals/twitterImage.webp"],
// },
};

export default function RootLayout({
Expand All @@ -16,7 +40,9 @@ export default function RootLayout({
}>) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
<body className="mainContainer">
<Providers>{children}</Providers>
</body>
</html>
);
}
Loading

0 comments on commit 4334bab

Please sign in to comment.