Skip to content

feat(frontend): pnk-token-page #29

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

Merged
merged 4 commits into from
Jan 3, 2025
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
2 changes: 2 additions & 0 deletions frontend/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
STRAPI_TOKEN=
STRAPI_URL=
1 change: 1 addition & 0 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ yarn-debug.log*
yarn-error.log*

# local env files
.env
.env*.local

# vercel
Expand Down
47 changes: 47 additions & 0 deletions frontend/src/components/CtaCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import Image from "next/image";

import Divider from "./Divider";
import ExternalLink from "./ExternalLink";

export interface ICtaCard {
icon: {
url: string;
};
title: string;
description: string;
arrowLink: {
text: string;
link: {
url: string;
};
};
}

const CtaCard: React.FC<ICtaCard> = ({
icon,
title,
description,
arrowLink,
}) => {
return (
<div className="flex flex-col items-start border border-stroke rounded-2xl p-6">
<Image
width={90}
height={90}
src={icon.url}
className="object-contain mb-4"
alt="Icon"
/>
<h2 className="text-xl text-primary-text font-medium mb-6">{title}</h2>
<p className="text-lg text-secondary-text mb-6">{description}</p>
<Divider />
<ExternalLink
text={arrowLink.text}
url={arrowLink.link.url}
className="mt-6 mb-4"
/>
</div>
);
};

export default CtaCard;
4 changes: 4 additions & 0 deletions frontend/src/components/Divider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const Divider: React.FC = () => (
<div className="w-full border border-stroke"></div>
);
export default Divider;
32 changes: 32 additions & 0 deletions frontend/src/components/ExternalLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React, { HTMLAttributes } from "react";

import Image from "next/image";
import Link from "next/link";

import LinkArrow from "@/assets/svgs/icons/link-arrow.svg";

interface IExternalLink {
text: string;
url: string;
className?: HTMLAttributes<HTMLDivElement>["className"]
}
const ExternalLink: React.FC<IExternalLink> = ({ text, url, className }) => {
return (
<Link
href={url}
target="_blank"
rel="noopener noreferrer"
className={`flex gap-4 items-center hover:brightness-[1.2] ${className}`}
>
<span className="text-lg text-primary-blue text-center">{text}</span>
<Image
src={LinkArrow}
width="24"
height="24"
alt="Arrow link image"
className="inline"
/>
</Link>
);
};
export default ExternalLink;
5 changes: 2 additions & 3 deletions frontend/src/components/Navbar/AppsDropdownContent/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ import Image from "next/image";
import clsx from "clsx";
import { Solution } from "@/queries/navbar";
import Link from "next/link"
import { hoverEffect } from "@/styles";


const hoverEffect = clsx(
"hover:scale-[1.01] transform transition duration-100"
);
const cardBaseStyle = clsx(
"bg-background-2 rounded-2xl border border-stroke text-wrap",
"p-4 flex gap-4 h-full lg:items-start"
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/Navbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ const Navbar: React.FC<INavbar> = ({ navbarData }) => {
isScrolled ? "bg-background-2" : "bg-transparent"
)}
style={{
paddingLeft: responsiveSize(24, 256, 1024, 1920),
paddingRight: responsiveSize(24, 256, 1024, 1920),
paddingLeft: responsiveSize(24, 128, 1024, 1920),
paddingRight: responsiveSize(24, 128, 1024, 1920),
}}
>
<Link href="/" className="flex items-center">
Expand Down
33 changes: 33 additions & 0 deletions frontend/src/components/PNKToken/BuySection/Exchanges.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Exchange } from "@/queries/pnk-token/token-buy";
import { hoverEffect } from "@/styles";
import Image from "next/image";
import Link from "next/link";

interface IExchanges {
exchanges: Exchange[];
}

const Exchanges: React.FC<IExchanges> = ({ exchanges }) => {
return (
<div className="w-full flex flex-wrap justify-center gap-6 md:gap-16 lg:gap-20 mb-8 md:mb-0">
{exchanges.map((exchange) => (
<Link
href={exchange.url}
target="_blank"
rel="noopener noreferrer"
key={exchange.name}
>
<Image
width={64}
height={64}
src={exchange.icon.url}
alt={exchange.name}
className={hoverEffect}
/>
</Link>
))}
</div>
);
};

export default Exchanges;
25 changes: 25 additions & 0 deletions frontend/src/components/PNKToken/BuySection/FeaturedExchange.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import Image from "next/image";
import Link from "next/link";

import { Exchange } from "@/queries/pnk-token/token-buy";
import clsx from "clsx";
import { hoverEffect } from "@/styles";

interface IFeaturedExchange {
exchange: Exchange;
}
const FeaturedExchange: React.FC<IFeaturedExchange> = ({ exchange }) => {
return (
<Link href={exchange.url} target="_blank" rel="noopener noreferrer">
<div className={clsx("h-40 flex flex-col gap-5 items-center justify-center border border-stroke rounded-2xl px-2 ", hoverEffect)}>
<div className="relative h-16 w-60">
<Image src={exchange.icon.url} alt={exchange.name} fill />
</div>

<p className="text-secondary-text">{exchange.name}</p>
</div>
</Link>
);
};

export default FeaturedExchange;
26 changes: 26 additions & 0 deletions frontend/src/components/PNKToken/BuySection/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Exchanges from "./Exchanges";
import FeaturedExchange from "./FeaturedExchange";

import { BuySectionQueryType } from "@/queries/pnk-token/token-buy";

interface IBuySection {
buyData: BuySectionQueryType["pnkTokenPageBuySection"];
}

const BuySection: React.FC<IBuySection> = ({ buyData }) => {
return (
<div className="bg-background-2 py-12 lg:py-24 px-6 lg:px-32">
<h1 className="text-2xl lg:text-3xl text-primary-text font-medium mb-16">
{buyData.header}
</h1>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-12">
{buyData.featuredExchanges.map((exchange) => (
<FeaturedExchange key={exchange.name} {...{ exchange }} />
))}
</div>
<Exchanges exchanges={buyData.exchanges}/>
</div>
);
};

export default BuySection;
32 changes: 32 additions & 0 deletions frontend/src/components/PNKToken/Explorers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { HeroQueryType } from "@/queries/pnk-token/hero";
import Image from "next/image";
import Link from "next/link";

interface IExplorers {
explorers: HeroQueryType["tokenExplorers"];
}

const Explorers: React.FC<IExplorers> = ({ explorers }) => {
return (
<div className="flex flex-wrap gap-6 lg:gap-12">
{explorers.map((explorer) => (
<Link
key={explorer.name}
href={explorer.url}
target="_blank"
rel="noopener noreferrer"
className="block relative h-6 min-w-32 items-start"
>
<Image
src={explorer.icon.url}
fill
alt={explorer.name}
className="!w-min"
/>
</Link>
))}
</div>
);
};

export default Explorers;
44 changes: 44 additions & 0 deletions frontend/src/components/PNKToken/Hero.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from "react";

import Image from "next/image";
import Link from "next/link";

import Button from "@/components/Button";
import { HeroQueryType } from "@/queries/pnk-token/hero";
import Explorers from "./Explorers";

interface IHero {
heroData: HeroQueryType;
}

const Hero: React.FC<IHero> = ({ heroData }) => {
const {header, subtitle, buyButton, background} = heroData.pnkTokenPageHero
return (
<div className="relative pt-52 pb-52 lg:pb-56 px-6 lg:px-32">
<div className="space-y-8">
<h1 className="text-3xl lg:text-4xl font-medium">{header}</h1>
<p className="text-lg">{subtitle}</p>
<div>
<Link
href={buyButton.link.url}
target="_blank"
rel="noopener noreferrer"
>
<Button variant="secondary">
<span>{buyButton.text}</span>
</Button>
</Link>
</div>
<Explorers explorers={heroData.tokenExplorers}/>
</div>
<Image
src={background.url}
alt="Hero Image Background"
fill
className="absolute top-0 left-0 h-full z-[-1] object-cover"
/>
</div>
);
};

export default Hero;
35 changes: 35 additions & 0 deletions frontend/src/components/PNKToken/TokenNeedSection/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import CtaCard from "@/components/CtaCard";
import ExternalLink from "@/components/ExternalLink";
import { TokenNeedSectionQueryType } from "@/queries/pnk-token/token-need";

interface ITokenNeedSection {
tokenNeedData: TokenNeedSectionQueryType["pnkTokenPageNeedSection"];
}

const TokenNeedSection: React.FC<ITokenNeedSection> = ({ tokenNeedData }) => {

return (
<div className="bg-background-1 py-12 lg:py-24 px-6 lg:px-32">
<h1 className="text-2xl lg:text-3xl text-primary-text font-medium mb-8">
{tokenNeedData.header}
</h1>
<p className="text-lg text-secondary-text mb-16">
{tokenNeedData.subtitle}
</p>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
{tokenNeedData.card.map((card) => (
<CtaCard key={card.title} {...card} />
))}
</div>
<div className="w-full items-center">
<ExternalLink
text={tokenNeedData.arrowLink.text}
url={tokenNeedData.arrowLink.link.url}
className="mt-12 flex-wrap justify-center md:justify-start"
/>
</div>
</div>
);
};

export default TokenNeedSection;
23 changes: 23 additions & 0 deletions frontend/src/components/PNKToken/TokenomicsSection/Stat.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { TokenStat } from "@/queries/pnk-token/tokenomics";

const Stat: React.FC<TokenStat & { label: string }> = ({
label,
primaryValue,
secondaryValue,
}) => {
return (
<div className="flex flex-col">
<label className="text-base text-primary-text">{label}</label>
<div className="flex flex-row gap-4">
<h2 className="text-primary-text font-medium text-xl lg:text-2xl">
{primaryValue}
</h2>
<h2 className="text-primary-blue text-xl lg:text-2xl">
{secondaryValue}
</h2>
</div>
</div>
);
};

export default Stat;
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { TokenStatDisplay as ITokenStatDisplay } from "@/queries/pnk-token/tokenomics";

import Image from "next/image";

import Stat from "./Stat";

const TokenStatDisplay: React.FC<ITokenStatDisplay> = ({ icon, stats }) => {
return (
<div className="bg-background-1 md:w-fit flex flex-col gap-8 md:flex-row rounded-2xl md:rounded-full p-6 md:p-4 md:pr-8">
<Image
src={icon.url}
alt="icon"
width={90}
height={90}
className="object-contain"
/>
{stats.map((stat) => (
<Stat
label={stat.key}
primaryValue={stat.primaryValue}
secondaryValue={stat.secondaryValue}
key={stat.key}
/>
))}
</div>
);
};
export default TokenStatDisplay;
Loading