Skip to content

Commit

Permalink
Merge branch 'styling-app'
Browse files Browse the repository at this point in the history
  • Loading branch information
bfullam committed Apr 21, 2024
2 parents 2d87b08 + 48dbcd0 commit a1cf2cb
Show file tree
Hide file tree
Showing 7,743 changed files with 4,832 additions and 180 deletions.
The diff you're trying to view is too large. We only load the first 3000 changed files.
124 changes: 87 additions & 37 deletions packages/nextjs/app/debug/_components/portfolio/bundlCard.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
"use client";

// @ts-ignore
import React, { ChangeEvent, useEffect, useState } from "react";
import Image from "next/image";
import Jazzicon, { jsNumberForAddress } from "react-jazzicon";
import { formatEther, parseEther } from "viem";
import { useScaffoldContractWrite } from "~~/hooks/scaffold-eth";
import { useScaffoldContractRead } from "~~/hooks/scaffold-eth";
Expand All @@ -20,22 +23,53 @@ export const BundlCard = ({ tokenId }: BundlCardProps) => {
const [isModalOpen, setIsModalOpen] = useState(false);
const [fundAmount, setFundAmount] = useState("");

const bagNames = ["Alpha", "Beta", "Gamma", "Delta", "Epsilon", "Zeta", "Eta", "Theta", "Iota", "Kappa"];

const openModal = () => setIsModalOpen(true);
const closeModal = () => setIsModalOpen(false);

const handleFundInput = (e: ChangeEvent<HTMLInputElement>) => setFundAmount(e.target.value);

// UTILS

const formatAddress = (address: string | null) => {
// @ts-ignore
/* const formatAddress = (address: string | null) => {
if (!address) return "No Address";
const first = address.slice(0, 6); // First 6 characters
const last = address.slice(-4); // Last 4 characters
return `${first}...${last}`; // Concatenated with ellipsis
};
}; */

// @ts-ignore
const balanceInDecimals = (balance: bigint) => {
return formatEther(balance);
return Number(formatEther(balance));
};

// Function to generate a random Ethereum address
const generateRandomAddress = () => {
const characters = "0123456789abcdef";
let address = "0x";
for (let i = 0; i < 40; i++) {
address += characters[Math.floor(Math.random() * characters.length)];
}
return address;
};

// Render Jazzicon directly where needed
const renderTokenImage = (token: any) => {
if (!token || !token.symbol) return null;
const imagePath = `/cryptocurrency-icons/128/color/${token.symbol.toLowerCase()}.png`;

try {
console.log("path: ", imagePath);
return <Image src={imagePath} width={50} height={50} alt={token.symbol} />;
} catch (error) {
console.log("Image not found, error:", error);
// Generate a random Ethereum address
const address = generateRandomAddress();
// Generate a Jazzicon using the random address
// @ts-ignore
return <Jazzicon diameter={25} seed={jsNumberForAddress(address)} />;
}
};

// This function fetches token prices from the API, ID is the token ID
Expand Down Expand Up @@ -69,6 +103,7 @@ export const BundlCard = ({ tokenId }: BundlCardProps) => {
args: [BigInt(tokenId)],
});

// @ts-ignore
const { data: getAllocationBalances } = useScaffoldContractRead({
contractName: "BundlrNft",
functionName: "getAllocationBalances",
Expand Down Expand Up @@ -112,41 +147,50 @@ export const BundlCard = ({ tokenId }: BundlCardProps) => {

return (
<>
<div className="bg-gray-200 px-20 py-10 rounded-md">
<div className="font-semibold">Name</div>
<div>Id: {tokenId}</div>
<div className="bg-[#dddcd9] bg-opacity-40 px-12 py-10 rounded-md">
<div className="text-lg font-semibold">{bagNames[Number(tokenId) - 1]}</div>
<div className="pt-5">
{getAllocations?.map((allocation, index) => (
<div className="pb-2" key={index}>
<div>Symbol: {allocation.symbol}</div>
<div>Address: {formatAddress(allocation.token)}</div>
<div>Weight: {allocation?.percentage}</div>
<div>
Balance:{" "}
{getAllocationBalances?.[index]?.balance
? balanceInDecimals(getAllocationBalances[index].balance)
: "No balance available"}
{getAllocations?.map((allocation, index) => {
console.log("allo:", allocation);
// Calculate the index of the next bag name
return (
<div key={index}>
<div className="pb-2">
<div className="flex flex-row justify-between">
<div className="flex flex-row space-x-2">
{renderTokenImage(allocation)}
<div className="font-medium">{allocation?.symbol}</div>
<div>
{getAllocationBalances?.[index]?.balance
? balanceInDecimals(getAllocationBalances[index].balance)
: "No balance available"}
</div>
</div>
<div className="font-medium">{allocation?.percentage}%</div>
</div>
</div>
</div>
{/* <div>
USD Values: {usdBalances[index] !== undefined ? `$${usdBalances[index]?.toFixed(2)} USD` : "Loading..."}
</div> */}
</div>
))}
);
})}
</div>
<div>
{isModalOpen && (
<div className="fixed inset-0 bg-black bg-opacity-10 flex justify-center items-center z-30">
<div className="bg-white p-5 rounded-lg">
<h2 className="text-lg">Enter the amount to fund</h2>
<h2 className="text-lg font-semibold">Funding amount</h2>
<h2 className="text-md w-[20rem]">
Specify the ETH amount you wish to invest, and we will automatically exchange it to rebalance your
portfolio according to predetermined token weights.
</h2>
<input
type="text"
value={fundAmount}
onChange={handleFundInput}
className="border border-gray-300 rounded-md p-2 mt-2"
className="border border-gray-300 rounded-md p-2 mt-2 w-full"
/>
<div className="flex flex-row justify-between mt-4">
<button
className="bg-gray-800 hover:bg-green-700 text-white font-bold py-2 px-6 rounded"
className="flex-grow bg-gray-800 hover:bg-gray-900 text-white font-bold py-2 px-6 rounded mr-2" // Added flex-grow class
onClick={() => {
fundNftWithEth();
setIsModalOpen(false);
Expand All @@ -155,7 +199,7 @@ export const BundlCard = ({ tokenId }: BundlCardProps) => {
Fund
</button>
<button
className="bg-red-400 hover:bg-red-700 text-white font-bold py-2 px-6 rounded"
className="flex-grow bg-red-300 hover:bg-red-700 text-white font-bold py-2 px-6 rounded ml-2" // Added flex-grow class
onClick={closeModal}
>
Cancel
Expand All @@ -164,18 +208,24 @@ export const BundlCard = ({ tokenId }: BundlCardProps) => {
</div>
</div>
)}
<div className="flex flex-row space-x-5">
<div
className="bg-gray-800 hover:bg-gray-400 text-white font-bold py-2 px-4 rounded mt-5 cursor-pointer"
onClick={openModal}
>
Fund
<div className="font-semibold pt-4">Total Volume Locked (TVL)</div>
<div className="font-medium text-gray-800">{Math.floor(Math.random() * 10000) + 1}$</div>
<div className="flex flex-row space-x-5 mt-4">
<div className="flex-grow">
<div
className="w-full bg-gray-200 border border-gray-500 hover:bg-gray-50 text-gray-700 font-bold py-2 px-8 rounded cursor-pointer"
onClick={openModal}
>
Fund
</div>
</div>
<div
className="bg-gray-800 hover:bg-gray-400 text-white font-bold py-2 px-4 rounded mt-5"
onClick={() => unbundleNftAssets()}
>
Liquidate
<div className="flex-grow">
<div
className="w-full bg-gray-200 border border-gray-500 hover:bg-gray-50 text-gray-700 font-bold py-2 px-4 rounded"
onClick={() => unbundleNftAssets()}
>
Liquidate
</div>
</div>
</div>
</div>
Expand Down
145 changes: 100 additions & 45 deletions packages/nextjs/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
"use client";

import { useState } from "react";
import { useEffect, useRef, useState } from "react";
import Image from "next/image";
import { BundlCard } from "./debug/_components/portfolio/bundlCard";
import { ApolloClient, InMemoryCache, gql } from "@apollo/client";
import type { NextPage } from "next";
import Jazzicon, { jsNumberForAddress } from "react-jazzicon";
import { useAccount, useChainId } from "wagmi";
import { useScaffoldContractRead, useScaffoldContractWrite } from "~~/hooks/scaffold-eth";

const Home: NextPage = () => {
const { address: connectedAddress } = useAccount();
const modalRef = useRef<HTMLDivElement>(null);

// READ FUNCTIONS
const { data: tokenlist } = useScaffoldContractRead({
Expand Down Expand Up @@ -153,19 +156,51 @@ const Home: NextPage = () => {
const symbol = tokenObject ? tokenObject.symbol : "";

return (
<div key={index} className="mt-4">
<label className="mr-2">{symbol} Percentage:</label>
<div key={index} className="mt-4 flex items-center">
<label className="mr-2 text-md font-semibold flex-shrink-0" style={{ width: "100px" }}>
{symbol}
</label>
<input
type="number"
value={input.percentage || ""}
onChange={e => handlePercentageChange(e, index)}
className="border px-2 py-1 rounded"
className="border px-2 py-1 rounded w-full"
style={{ maxWidth: "calc(100% - 100px)" }} // Adjust based on the width of the label
/>
</div>
);
});
};

// Function to generate a random Ethereum address
const generateRandomAddress = () => {
const characters = "0123456789abcdef";
let address = "0x";
for (let i = 0; i < 40; i++) {
address += characters[Math.floor(Math.random() * characters.length)];
}
return address;
};

// Render Jazzicon directly where needed
const renderTokenImage = (token: any) => {
console.log("token", token);
const imagePath = `/cryptocurrency-icons/svg/color/${token.symbol.toLowerCase()}.svg`;

try {
require(imagePath);
console.log("path: ", imagePath);
return <Image src={imagePath} width={50} height={50} alt={token.symbol} />;
} catch (error) {
console.log("Image not found, error:", error);
// Generate a random Ethereum address
const address = generateRandomAddress();
// Generate a Jazzicon using the random address
// @ts-ignore
return <Jazzicon diameter={25} seed={jsNumberForAddress(address)} />;
}
};

const handlePercentageChange = (e: React.ChangeEvent<HTMLInputElement>, index: number) => {
const newPercentage = parseInt(e.target.value);
if (!isNaN(newPercentage) || e.target.value === "") {
Expand All @@ -182,6 +217,25 @@ const Home: NextPage = () => {
}
}
};

// EFFECTS

useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
console.log("modalRef", modalRef.current);
if (modalRef.current && !modalRef.current.contains(event.target as Node)) {
console.log("detected");
closeModal(); // Close the modal if clicked outside
}
};

document.addEventListener("mousedown", handleClickOutside);

return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [modalRef, closeModal]);

// WRITE FUNCTIONS
const {
writeAsync: mintNFT,
Expand All @@ -200,49 +254,50 @@ const Home: NextPage = () => {
<>
<div className="flex items-center flex-col flex-grow pt-10">
<div>
<div className="flex flex-row justify-between items-center">
<div className="text-4xl font-bold">Portfolio</div>
{isModalOpen && (
<div className="fixed inset-0 bg-black bg-opacity-10 flex justify-center items-center z-30">
<div className="bg-white p-5 rounded-lg max-h-96 overflow-y-auto max-w-md w-full mx-auto">
<h2 className="text-lg font-semibold">Select Tokens</h2>
<div className="max-h-[11rem] overflow-y-auto">
{Object.values(pairingTokens).length > 0 ? (
Object.values(pairingTokens)
.sort((a: any, b: any) => a.symbol.localeCompare(b.symbol))
.map((token: any, index: number) => (
<div
key={index}
onClick={() => handleTokenSelect(token.symbol, token.id, token.pools[0].feeTier)}
>
<label>{token.symbol}</label>
</div>
))
) : (
<div>Loading...</div>
)}
</div>
{renderInputFields()}
<div className="flex flex-row justify-between mt-4">
<button
className="bg-gray-800 hover:bg-green-700 text-white font-bold py-2 px-6 rounded"
onClick={() => {
mintNFT(); // Pass selected tokens to mint function
setIsModalOpen(false);
}}
>
Create
</button>
<button
className="bg-red-400 hover:bg-red-700 text-white font-bold py-2 px-6 rounded"
onClick={closeModal}
>
Cancel
</button>
</div>
{isModalOpen && (
<div className="fixed inset-0 bg-black bg-opacity-10 flex justify-center items-center z-30">
<div ref={modalRef} className="bg-white p-5 rounded-lg max-h-96 overflow-y-auto max-w-md w-full mx-auto">
<h2 className="text-lg font-semibold">Select Tokens</h2>
<h3 className="text-md pb-6">Tailor your bag to suit your preferences.</h3>
<div className="max-h-[11rem] overflow-y-auto">
{Object.values(pairingTokens).length > 0 ? (
Object.values(pairingTokens).map((token: any, index: number) => (
<div
key={index}
onClick={() => handleTokenSelect(token.symbol, token.id, token.pools[0].feeTier)}
>
<div className="flex flex-row space-x-4">
<div>{renderTokenImage(token)}</div>
<div>{token.symbol}</div>
</div>
</div>
))
) : (
<div>Loading...</div>
)}
</div>
<div className="text-md pt-7 font-semibold">Select Weight</div>
<div className="text-md pt-2">
You provide funds, and we diversify your investment based on your chosen weight distribution.
</div>
{renderInputFields()}
<div className="flex flex-row justify-between mt-5">
<button
className="bg-gray-800 hover:bg-gray-900 text-white font-bold py-2 px-6 rounded w-full"
onClick={() => {
mintNFT(); // Pass selected tokens to mint function
setIsModalOpen(false);
}}
>
Create
</button>
</div>
</div>
)}
</div>
)}
<div className={`flex flex-row space-x-[64.5rem] items-center mb-4`}>
<div className="text-4xl font-bold">Portfolio</div>

<div>
<button
className="bg-gray-800 hover:bg-gray-500 text-white font-bold py-2 px-4 rounded mt-5"
Expand Down
Loading

0 comments on commit a1cf2cb

Please sign in to comment.