Skip to content

Commit

Permalink
UI improvements, added allowance modal to create, still need to add i…
Browse files Browse the repository at this point in the history
…t to like button
  • Loading branch information
luloxi committed Dec 14, 2024
1 parent a5047df commit 63f16b9
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 24 deletions.
16 changes: 10 additions & 6 deletions packages/foundry/contracts/PunkSociety.sol
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,9 @@ contract PunkSociety is Ownable {
postIdToUser[postId] = msg.sender;
userPosts[msg.sender].push(postId);

mockUSDC.transferFrom(msg.sender, owner(), 3 * 1e6);
bool sent = mockUSDC.transferFrom(msg.sender, owner(), 3 * 1e6);
require(sent, "Failed to send USDC to the post owner");

punkPosts.mint(_tokenURI);
// payable(owner()).transfer(3 ether);

Expand Down Expand Up @@ -148,13 +150,15 @@ contract PunkSociety is Ownable {
address postOwner = postIdToUser[_postID];
require(postOwner != address(0), "Post owner does not exist");

userToPostLikes[msg.sender][_postID] = true;
postToLikes[_postID]++;

// Transfer 1 USDC to the post owner
bool sent = mockUSDC.transferFrom(msg.sender, postOwner, 1 * 1e6);
require(sent, "Failed to send USDC to the post owner");
// (bool sent,) = postOwner.call{ value: 1 ether }("");
// require(sent, "Failed to send USDC to the post owner");

userToPostLikes[msg.sender][_postID] = true;
postToLikes[_postID]++;

emit PostLiked(_postID, msg.sender, block.timestamp);
}

Expand Down Expand Up @@ -182,9 +186,9 @@ contract PunkSociety is Ownable {

function commentOnPost(uint256 _postID, string memory _text) public {
_requirePostExists(_postID);
// set max length at 250 characters
// set max length at 140 characters
require(
bytes(_text).length <= 250, "Comment must be less than 250 characters"
bytes(_text).length <= 140, "Comment must be 140 characters or less"
);
uint256 commentIndex = postToComments[_postID].length;
postToComments[_postID].push(Comment(msg.sender, _text, commentIndex));
Expand Down
111 changes: 101 additions & 10 deletions packages/nextjs/app/create/_components/MintingButtons.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { useState } from "react";
// import { parseEther } from "viem";
import { useEffect, useState } from "react";
import Image from "next/image";
import { useAccount } from "wagmi";
import { useScaffoldWriteContract } from "~~/hooks/scaffold-eth";
// import { parseEther } from "viem";
import Modal from "~~/components/punk-society/Modal";
import { InputBase } from "~~/components/scaffold-eth";
import { useDeployedContractInfo, useScaffoldReadContract, useScaffoldWriteContract } from "~~/hooks/scaffold-eth";
import { uploadToPinata } from "~~/utils/pinata-upload";
import { notification } from "~~/utils/scaffold-eth";

Expand All @@ -16,10 +19,72 @@ interface MintingFormProps {
}

export const MintingButtons: React.FC<MintingFormProps> = ({ yourJSON, resetForm, onPostCreated }) => {
const [showModal, setShowModal] = useState(false);
const [loading, setLoading] = useState(false);
const [allowanceAmount, setAllowanceAmount] = useState<number>();

const { address: connectedAddress } = useAccount();
const { writeContractAsync } = useScaffoldWriteContract("PunkSociety");
const { writeContractAsync: USDCwriteContractAsync } = useScaffoldWriteContract("MockUSDC");

const [loading, setLoading] = useState(false);
const { data: punkSocietyContractData } = useDeployedContractInfo("PunkSociety");

const { data: allowance } = useScaffoldReadContract({
contractName: "MockUSDC",
functionName: "allowance",
args: [connectedAddress, punkSocietyContractData?.address],
watch: true,
});

const { data: balanceOf } = useScaffoldReadContract({
contractName: "MockUSDC",
functionName: "balanceOf",
args: [connectedAddress],
watch: true,
});

const formattedUsdcBalance = balanceOf ? (Number(balanceOf.toString()) / 1e6).toFixed(2) : "0.00";

useEffect(() => {
if (allowance && parseInt(allowance.toString()) < 3000000) {
setShowModal(true);
}
}, [allowance]);

const handleCloseModal = () => {
setShowModal(false);
};

const handleAllowanceChange = async () => {
if (!connectedAddress) {
notification.error("Please connect your wallet");
return;
}

// setLoading(true);

try {
// const ipfsPath = await uploadToIPFS();

const contractResponse = await USDCwriteContractAsync({
functionName: "approve",
args: [punkSocietyContractData?.address, allowanceAmount ? BigInt(allowanceAmount * 1e6) : BigInt(0)],
// value: parseEther("3"),
});

if (contractResponse) {
notification.success("Allowance increased successfully!");
}
// resetForm();
// onPostCreated();
} catch (error) {
console.error("Error increasing allowance:", error);
notification.error("Increasing allowance failed, please try again.");
} finally {
setShowModal(false);
// setLoading(false);
}
};

const uploadToIPFS = async () => {
// const notificationId = notification.loading("Uploading to Pinata...");
Expand Down Expand Up @@ -70,12 +135,38 @@ export const MintingButtons: React.FC<MintingFormProps> = ({ yourJSON, resetForm
};

return (
<div className="flex flex-col justify-center items-center mt-6 gap-3">
<div className="flex items-center">
<button className="cool-button" disabled={loading} onClick={handleCreatePost}>
Create Post
</button>
<>
<div className="flex flex-col justify-center items-center mt-6 gap-3">
<div className="flex items-center">
{/* <span>{allowance?.toString()}</span> */}
<button className="cool-button" disabled={loading} onClick={handleCreatePost}>
Create Post
</button>
</div>
</div>
</div>
{showModal && (
<Modal isOpen={showModal} onClose={handleCloseModal}>
<div className="flex flex-col items-center gap-3">
<h2 className="mt-2 text-xl font-bold">Insufficient USDC Allowance!</h2>
<span className="text-red-600">Please increase your USDC allowance to use the platform.</span>
<span className="flex flex-row items-center justify-center gap-2">
Current Balance:{" "}
<span className="flex items-center justify-center gap-1 text-lg text-blue-600 font-bold">
<Image src="/usdc-logo.png" alt="USDC" width={20} height={20} className="inline-block" />
{formattedUsdcBalance}
</span>
</span>
<InputBase placeholder="USDC value here (3.00)" value={allowanceAmount} onChange={setAllowanceAmount} />
<div className="flex items-center mb-2">
<button className="cool-button" disabled={loading} onClick={handleAllowanceChange}>
Increase allowance
</button>
</div>
{/* <button onClick={handleCloseModal}>Close</button> */}
{/* Add your logic to increase the allowance here */}
</div>
</Modal>
)}
</>
);
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useRef, useState } from "react";
import Link from "next/link";
import { PunkBalance } from "../PunkBalance";
// import { PunkBalance } from "../PunkBalance";
import { NetworkOptions } from "./NetworkOptions";
// import { FundButton, getOnrampBuyUrl } from "@coinbase/onchainkit/fund";
import { getAddress } from "viem";
Expand Down Expand Up @@ -82,7 +82,7 @@ export const AddressInfoDropdown = ({ address }: AddressInfoDropdownProps) => {
>
<NetworkOptions hidden={!selectingNetwork} />

<PunkBalance address={connectedAddress} />
{/* <PunkBalance address={connectedAddress} /> */}
<li className={selectingNetwork ? "hidden" : ""}>
<Link className="p-0 flex items-center justify-center" href={`/profile/${connectedAddress}`} passHref>
<div className="btn-sm w-full !rounded-xl flex items-center justify-start gap-2 py-3 text-white bg-orange-600 hover:bg-orange-500 active:bg-orange-500">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import React, { useState } from "react";
import { Balance } from "./Balance";
import Image from "next/image";
// import { Balance } from "./Balance";
import { QRCodeSVG } from "qrcode.react";
import { CopyToClipboard } from "react-copy-to-clipboard";
import { Address as AddressType } from "viem";
import { useAccount } from "wagmi";
import { useScaffoldReadContract } from "~~/hooks/scaffold-eth";
import { notification } from "~~/utils/scaffold-eth";

type AddressQRCodeModalProps = {
Expand All @@ -13,6 +16,17 @@ type AddressQRCodeModalProps = {
export const AddressQRCodeModal = ({ address, modalId }: AddressQRCodeModalProps) => {
const [copied, setCopied] = useState(false);

const { address: connectedAddress } = useAccount();

const { data: usdcBalance } = useScaffoldReadContract({
contractName: "MockUSDC",
functionName: "balanceOf",
args: [connectedAddress],
watch: true,
});

const formattedUsdcBalance = usdcBalance ? (Number(usdcBalance.toString()) / 1e6).toFixed(2) : "0.00";

const handleCopy = () => {
setCopied(true);
notification.success("Address copied to clipboard");
Expand All @@ -26,20 +40,30 @@ export const AddressQRCodeModal = ({ address, modalId }: AddressQRCodeModalProps
<label htmlFor={`${modalId}`} className="modal cursor-pointer">
<label className="modal-box relative">
<div className="flex flex-col justify-center items-center text-center">
<h2 className="text-xl font-bold ">Your Address</h2>
<div className="flex flex-row justify-center items-center px-2 mb-4 rounded-lg bg-yellow-500 text-black">
<span className="font-bold">Balance: </span>
<Balance address={address} />
</div>
<h2 className="text-xl font-bold ">Receive USDC to this address</h2>

<div className="bg-white p-4 rounded-lg shadow-lg mb-4">
<QRCodeSVG value={address} size={256} />
</div>
<div className="break-words whitespace-pre-wrap text-center w-full">{address}</div>

<CopyToClipboard text={address} onCopy={handleCopy}>
<button className="btn btn-primary text-white border-0 bg-green-600 hover:bg-green-500 active:bg-green-500 mt-4">
{copied ? "Copied!" : "Copy Address"}
</button>
</CopyToClipboard>

<div className="flex flex-row justify-around gap-3 items-center mt-4">
<div className="flex flex-row justify-center items-center px-2 gap-2 rounded-lg bg-yellow-500 text-black text-xl">
<span className="font-bold">Balance: </span>
{/* <Balance address={address} /> */}{" "}
<span className="hidden lg:flex items-center justify-center gap-1 text-blue-600 font-bold">
<Image src="/usdc-logo.png" alt="USDC" width={20} height={20} className="inline-block" />
{formattedUsdcBalance}
</span>
</div>
<div> </div>
</div>
<label
htmlFor={`${modalId}`}
className="btn text-xl rounded-full text-white bg-red-600 border-0 hover:bg-red-500 btn-ghost btn-sm btn-circle absolute right-3 top-3"
Expand Down

0 comments on commit 63f16b9

Please sign in to comment.