Skip to content

Commit

Permalink
feat: affiliate ui
Browse files Browse the repository at this point in the history
  • Loading branch information
painiteleo authored and painiteleo committed Jul 8, 2024
1 parent aff59b3 commit 3dc347c
Show file tree
Hide file tree
Showing 10 changed files with 232 additions and 0 deletions.
Binary file modified bun.lockb
Binary file not shown.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
"remixicon": "^4",
"sharp": "^0",
"tailwindcss-animate": "^1.0.7",
"usehooks-ts": "^3.1.0",
"viem": "^2",
"wagmi": "^2.5.7",
"zod": "^3.22.4"
Expand Down
13 changes: 13 additions & 0 deletions src/app/(site)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { type NextPage } from "next";

interface Props {
children: React.ReactNode;
}

export const metadata = {
title: "Stable Yield For Stablecoins",
};

const AppLayout: NextPage<Props> = ({ children }) => children;

export default AppLayout;
5 changes: 5 additions & 0 deletions src/app/app/[tab]/AppTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { AppPreMining } from "@/components/app/pre-mining/AppPreMining";
import { SessionProvider } from "next-auth/react";
import { AppStaking } from "@/components/app/staking/AppStaking";
import Link from "next/link";
import { AppAffiliate } from "@/components/app/affiliate/AppAffiliate";

interface Props {
defaultTab: string;
Expand Down Expand Up @@ -72,6 +73,7 @@ const _AppTabs: FC = () => {
Pre-Mining
</TabsTrigger>
<TabsTrigger value="dashboard">Dashboard</TabsTrigger>
<TabsTrigger value="affiliate">Affiliate Program</TabsTrigger>
</TabsList>
<div className="[&_>_*]:animate-fadeAndMoveIn [&_>_*]:[animation-duration:300ms] sm:px-5 max-w-[100vw]">
<SessionProvider>
Expand All @@ -90,6 +92,9 @@ const _AppTabs: FC = () => {
<TabsContent value="dashboard">
<AppDashboard />
</TabsContent>
<TabsContent value="affiliate">
<AppAffiliate />
</TabsContent>
</SessionProvider>
</div>
</Tabs>
Expand Down
1 change: 1 addition & 0 deletions src/app/app/[tab]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export async function generateMetadata({ params }: Props): Promise<Metadata> {
"get-usdc": "Get USDC",
// "pre-mining": "Pre-Mining",
staking: "Staking",
affiliate: "Affiliate Program",
}[params.tab];

const description = {
Expand Down
99 changes: 99 additions & 0 deletions src/components/app/affiliate/AppAffiliate.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { Button, Card, Input } from "@/components/ui";
import { createAffiliateCode, RequestParams } from "@/services/api/createAffiliateCode";
import { FC, useEffect, useRef, useState } from "react";
import { twMerge } from "tailwind-merge";
import { useCopyToClipboard } from "usehooks-ts";
import { getAddress } from "viem";

export const AppAffiliate: FC = () => {
const [walletAddress, setWalletAddress] = useState<string>("");
const [isLoading, setIsLoading] = useState<boolean>(false);
const [copiedText, copy] = useCopyToClipboard();
const [affiliateUrl, setAffiliateUrl] = useState<string>("https://ledgity.finance/example");

const handleCopy = (text: string) => {
copy(text)
.then(() => {
console.log("Copied!", { text });
})
.catch((error) => {
console.error("Failed to copy!", error);
});
};

const sendAffiliateRequest = async () => {
if (walletAddress?.length) {
setIsLoading(true);
const requestParams: RequestParams = {
walletAddress: getAddress(walletAddress),
};
const data = await createAffiliateCode(requestParams);
console.log("data: ", data);
setIsLoading(false);
}
};

return (
<div className="lg:w-[1080px] flex flex-col items-center justify-center w-full h-full text-slate-700 gap-y-4">
<span className="text-2xl lg:text-5xl font-extrabold text-nowrap leading-loose">
Affiliate Program
</span>
<div className="lg:w-[600px] text-center w-full">
Simply invite your friends with your referral link and{" "}
<p className="text-primary font-bold inline-block">earn up to 50% </p>
Ledgity's commission from the referral. It's as easy as that!
</div>
<div className="w-full grid grid-cols-12 gap-5 content-center place-content-center">
<Card
circleIntensity={0.07}
defaultGradient={true}
className="w-full flex flex-col items-center col-span-12 xl:col-span-6 gap-2 p-8"
>
<div className="">Paste your wallet to participate in the affiliate program!</div>
<div className="flex justify-start w-full gap-x-2">
<Input
placeholder="Input Wallet Address"
value={walletAddress}
onChange={(e) => (setWalletAddress ? setWalletAddress(e.target.value) : null)}
disableDefaultCss={true}
className="bg-gray-300 w-full p-1 rounded-lg text-sm"
/>
<Button
size="tiny"
onClick={sendAffiliateRequest}
disabled={isLoading}
className="px-4"
>
Confirm
{isLoading && (
<i className="text-xl text-gray-300 font-bold ri-loader-4-fill animate-spin"></i>
)}
</Button>
</div>
</Card>
<Card
circleIntensity={0.07}
defaultGradient={true}
className="w-full flex flex-col items-center col-span-12 xl:col-span-6 gap-2 p-8"
>
<div className="text-center">
Copy your referral link and share it to earn up to 50% of Ledgity's commission and help
your friends get stable yield.
</div>
<div className="relative flex bg-gray-300 w-full rounded-lg">
<i
className="ri-link rounded-full px-1 text-2xl font-bold absolute z-20 h-8 top-1/2 transform -translate-y-1/2 left-3 bg-none hover:cursor-pointer hover:bg-gray-100"
onClick={() => handleCopy(affiliateUrl)}
></i>
<input
type="text"
value={affiliateUrl}
readOnly
className="w-full bg-transparent text-gray-400 focus:ring relative rounded text-sm border-none outline-none focus:outline-none pl-12 pr-3 py-2"
/>
</div>
</Card>
</div>
</div>
);
};
1 change: 1 addition & 0 deletions src/constants/constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const AFFILIATE_URL = "http://localhost:9010";
32 changes: 32 additions & 0 deletions src/contexts/MainContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { FC, createContext, useState } from "react";

interface IMainContext {
referralCode: string | null;
changeReferalCode: (slug: string | null) => void;
}

export const MainContext = createContext<IMainContext | undefined>(undefined);

interface Props {
children?: React.ReactNode;
defaultTab: string;
}

export const MainContextProvider: FC<Props> = ({ children }) => {
const [referralCode, setReferralCode] = useState<string | null>(null);

const changeReferalCode = (slug: string | null) => {
setReferralCode(slug);
};

return (
<MainContext.Provider
value={{
referralCode,
changeReferalCode,
}}
>
{children}
</MainContext.Provider>
);
};
9 changes: 9 additions & 0 deletions src/hooks/useMainContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { useContext } from "react";
import { MainContext } from "@/contexts";

export const useMainContext = () => {
const context = useContext(MainContext);
if (context === undefined)
throw new Error("useMainContext() must be used within a <MainContext>");
return context;
};
71 changes: 71 additions & 0 deletions src/services/api/createAffiliateCode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { AFFILIATE_URL } from "@/constants/constant";
import { env } from "../../../env.mjs";

import { Address } from "viem";

export interface RequestParams {
walletAddress: Address;
}

export interface QuotoV2Response {
deprecated: string;
inTokens: string[];
outTokens: string[];
inAmounts: string[];
outAmounts: string[];
gasEstimate: number;
dataGasEstimate: number;
gweiPerGas: number;
gasEstimateValue: number;
inValues: number[];
outValues: number[];
netOutValue: number;
priceImpact: number;
percentDiff: number;
partnerFeePercent: number;
pathId: string | null;
pathViz: object;
pathVizImage: string;
blockNumber: number;
}

export const createAffiliateCode = (params: RequestParams) => {
const option = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(params),
};
console.log("AFFILIATE_URL: ", AFFILIATE_URL);
return fetch(AFFILIATE_URL + "/affiliate/create", option)
.then(async (res) => {
// if (!res.ok) throw new Error();
if (!res.ok) console.log("failed: ", res);
const data: any = await res.json();
console.log("data: ", data);
// return {
// deprecated: data.deprecated,
// inTokens: data.inTokens,
// outTokens: data.outTokens,
// inAmounts: data.inAmounts,
// outAmounts: data.outAmounts,
// gasEstimate: data.gasEstimate,
// dataGasEstimate: data.dataGasEstimate,
// gweiPerGas: data.gweiPerGas,
// gasEstimateValue: data.gasEstimateValue,
// inValues: data.inValues,
// outValues: data.outValues,
// netOutValue: data.netOutValue,
// priceImpact: data.priceImpact,
// percentDiff: data.percentDiff,
// partnerFeePercent: data.partnerFeePercent,
// pathId: data.pathId,
// pathViz: data.pathViz,
// pathVizImage: data.pathVizImage,
// blockNumber: data.blockNumber,
// };
})
.catch((error) => {
console.log(error);
return undefined;
});
};

0 comments on commit 3dc347c

Please sign in to comment.