Skip to content

Instantly share code, notes, and snippets.

@Ernesto-tha-great
Last active July 8, 2022 14:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Ernesto-tha-great/4fdbe33cefdd51c3dad5ca3895f12037 to your computer and use it in GitHub Desktop.
Save Ernesto-tha-great/4fdbe33cefdd51c3dad5ca3895f12037 to your computer and use it in GitHub Desktop.
Pages
import React, { useEffect, useState } from "react";
import { useCelo } from "@celo/react-celo";
import { NewsFeed } from "@celo-progressive-dapp-starter/hardhat/types/NewsFeed";
import deployedContracts from "@celo-progressive-dapp-starter/hardhat/deployments/hardhat_contracts.json";
import Link from "next/link";
import FeedList from "../components/FeedList";
import Feed from "../components/Feed";
export default function FeedPage() {
const { network, kit } = useCelo();
const [relatedFeeds, setRelatedFeeds] = useState([]);
// state variable to store the current feed
const [feed, setFeed] = useState<any>([]);
const contractDataS =
deployedContracts[network?.chainId?.toString()]?.[
network?.name?.toLocaleLowerCase()
]?.contracts;
let contractData = contractDataS.NewsFeed;
const contract = contractData
? (new kit.connection.web3.eth.Contract(
contractData.abi,
contractData.address
) as any as NewsFeed)
: null;
// Function to get the feed id from the url
const getUrlValue = () => {
let vars = {};
window.location.href.replace(
/[?&]+([^=&]+)=([^&]*)/gi,
function (m, key, value) {
vars[key] = value;
}
);
return vars;
};
/*
* Get Feed
*/
const getFeed = async () => {
try {
let feedId = getUrlValue()["id"];
const allFeed = await contract.methods.getAllFeeds().call();
const singleFeed: any = allFeed.filter((feed: any) => feed.id === feedId);
// Format feed
const formattedFeed = {
id: singleFeed[0].id,
title: singleFeed[0].title,
description: singleFeed[0].description,
location: singleFeed[0].location,
category: singleFeed[0].category,
coverImageHash: singleFeed[0].coverImageHash,
date: singleFeed[0].date,
author: singleFeed[0].author,
};
setFeed(formattedFeed);
} catch (error) {
console.log(error);
}
};
/*
* Get Related Feeds
*/
const getRelatedFeeds = async () => {
try {
let feedId = getUrlValue()["id"];
// Get all feeds and return feeds and filter only the one in the same category as the feed
const allFeeds = await contract.methods.getAllFeeds().call();
const singleFeed: any = allFeeds.filter(
(feed: any) => feed.id === feedId
);
// Format feed
const formattedSingleFeed = {
id: singleFeed[0].id,
title: singleFeed[0].title,
description: singleFeed[0].description,
location: singleFeed[0].location,
category: singleFeed[0].category,
coverImageHash: singleFeed[0].coverImageHash,
date: singleFeed[0].date,
author: singleFeed[0].author,
};
const relatedFeeds = allFeeds.filter(
(feed: any) => feed.category === formattedSingleFeed.category
);
const formattedFeeds = relatedFeeds.map((feed: any) => {
return {
id: feed.id,
title: feed.title,
description: feed.description,
location: feed.location,
category: feed.category,
coverImageHash: feed.coverImageHash,
author: feed.author,
date: feed.date,
};
});
setRelatedFeeds(formattedFeeds);
} catch (error) {
console.log(error);
}
};
useEffect(() => {
getFeed();
getRelatedFeeds();
}, []);
return (
<div className="w-full bg-gray-200 h-full flex flex-row">
<Link href="/">
<button className="bg-red-600 hover:bg-red-800 text-white w-20 h-20 mt-10 justify-right font-bold px-2 rounded ml-10">
Go Back
</button>
</Link>
<div className="flex-1 flex flex-col">
<div className="flex flex-col m-10 justify-between xl:flex-row">
<div className="lg:w-4/6 w-6/6">{feed && <Feed feed={feed} />}</div>
<div className="w-2/6">
<div className="mt-20">
<h4 className="text-xl font-bold ml-5 mb-3 text-green">
Related Feeds
</h4>
{relatedFeeds.map((f) => {
return (
<Link href={`/feed?id=${f.id}`}>
<FeedList feed={f} horizontal={true} />
</Link>
);
})}
</div>
</div>
</div>
</div>
</div>
);
}
import React, { useState, useEffect } from "react";
import { useCelo } from "@celo/react-celo";
import { NewsFeed } from "@celo-progressive-dapp-starter/hardhat/types/NewsFeed";
import FeedList from "../components/FeedList";
import Link from "next/link";
import { error } from "../utils/response";
import "react-toastify/dist/ReactToastify.css";
export default function HomePage({ contractData }) {
const { kit } = useCelo();
const [loading, setLoading] = useState(false);
const [loadingArray] = useState(15);
// Create a state variable to store the feeds in the blockchain
const [feeds, setFeeds] = useState<any>([]);
const contract = contractData
? (new kit.connection.web3.eth.Contract(
contractData.abi,
contractData.address
) as any as NewsFeed)
: null;
const getFeeds = async () => {
try {
setLoading(true);
const AllFeeds = await contract.methods.getAllFeeds().call();
/*
* We only need title, category, coverImageHash, and author
* pick those out
*/
const formattedFeed = AllFeeds.map((feed: any) => {
return {
id: feed.id,
title: feed.title,
category: feed.category,
coverImageHash: feed.coverImageHash,
author: feed.author,
date: new Date(feed.date * 1000),
};
});
setFeeds(formattedFeed);
setLoading(false);
} catch (err) {
error(`${err.message}`);
}
};
/*
* This runs our function when the page loads.
*/
useEffect(() => {
getFeeds();
}, []);
return (
<div className="w-full flex flex-row">
<div className="flex-1 flex flex-col">
<div className="flex-1 flex flex-row flex-wrap mt-8">
{feeds
?.map((feed, index) => {
return (
<Link href={`/FeedPage?id=${feed.id}`} key={index}>
<div className="w-80 h-80 m-2">
<FeedList feed={feed} />
</div>
</Link>
);
})
.reverse()}
{loading && (
<div className="flex-1 flex flex-row flex-wrap">
{Array(loadingArray)
.fill(0)
.map((_, index) => (
<div key={index} className="w-80">
<Loader />
</div>
))}
</div>
)}
</div>
</div>
</div>
);
}
const Loader = () => {
return (
<div className="flex flex-col m-5 animate-pulse">
<div className="w-full bg-gray-300 dark:bg-borderGray h-40 rounded-lg "></div>
<div className="w-50 mt-3 bg-gray-300 dark:bg-borderGray h-6 rounded-md "></div>
<div className="w-24 bg-gray-300 h-3 dark:bg-borderGray mt-3 rounded-md "></div>
</div>
);
};
import React, { useState, useRef, useEffect } from "react";
import { useCelo } from "@celo/react-celo";
import { NewsFeed } from "@celo-progressive-dapp-starter/hardhat/types/NewsFeed";
import deployedContracts from "@celo-progressive-dapp-starter/hardhat/deployments/hardhat_contracts.json";
import { create } from "ipfs-http-client";
import { BiCloud, BiPlus } from "react-icons/bi";
import { ToastContainer } from "react-toastify";
import { success, error, defaultToast } from "../utils/response";
import { ImportCandidate } from "ipfs-core-types/dist/src/utils";
export default function Upload() {
const { address, connect, kit } = useCelo();
const [title, setTitle] = useState("");
const [description, setDescription] = useState("");
const [category, setCategory] = useState("");
const [location, setLocation] = useState("");
const [coverImage, setCoverImage] = useState<any>("");
const { network } = useCelo();
const contractDataS =
deployedContracts[network?.chainId?.toString()]?.[
network?.name?.toLocaleLowerCase()
]?.contracts;
/*
* Create an IPFS node
*/
const client = create("https://ipfs.infura.io:5001/api/v0");
const coverImageRef = useRef();
let contractData = contractDataS.NewsFeed;
const contract = contractData
? (new kit.connection.web3.eth.Contract(
contractData.abi,
contractData.address
) as any as NewsFeed)
: null;
const handleSubmit = async () => {
if (
title === "" ||
description === "" ||
location === "" ||
coverImage === ""
) {
error("Please, all the fields are required!");
return;
}
uploadCoverImage(coverImage);
};
const uploadCoverImage = async (coverImage: ImportCandidate) => {
defaultToast("Uploading Cover Image...");
try {
const image = await client.add(coverImage);
await saveFeed(image.path);
} catch (err) {
error("Error Uploading Cover Image");
}
};
const saveFeed = async (coverImage: string) => {
defaultToast("Saving Feed...");
console.log(title, description, category, location, coverImage);
try {
const UploadedDate = String(new Date());
console.log("contract", contract);
const gasPriceMinimumContract = await kit.contracts.connection.gasPrice();
await contract.methods
.createFeed(
title,
description,
location,
category,
coverImage,
UploadedDate
)
.send({ from: address, gasPrice: gasPriceMinimumContract });
success("Feed Saved Successfully");
// reset form
setTitle("");
setDescription("");
setCategory("");
setLocation("");
setCoverImage("");
// Redirect to Home Page
window.location.href = "/";
} catch (err) {
console.log(err);
error("Error Saving Feed");
}
};
// Handles redirect to Home Page or previous page
const goBack = () => {
window.history.back();
};
return (
<div className="w-full bg-gray-200 h-screen flex flex-row">
<div className="flex-1 flex flex-col">
<div className="mt-5 mr-10 flex justify-end">
<div className="flex items-center">
<button
className="bg-red dark:text-[#9CA3AF] py-2 px-6 border rounded-lg border-gray-600 mr-6"
onClick={() => {
goBack();
}}
>
{title ? "Discard" : "Back"}
</button>
<button
onClick={() => {
handleSubmit();
}}
className="bg-blue-500 hover:bg-blue-700 text-white py-2 rounded-lg flex px-4 justify-between flex-row items-center"
>
<BiCloud />
<p className="ml-2">Upload</p>
</button>
</div>
</div>
<div className="flex flex-col m-10 mt-5 lg:flex-row lg:justify-center">
<div className="flex lg:w-3/4 flex-col ">
<label className="text-green-600 text-lg font-bold mb-2">
Title
</label>
<input
value={title}
onChange={(e) => setTitle(e.target.value)}
placeholder="Celo launches a $20m connect the world fund."
className="w-[60%] dark:placeholder:text-gray-600 rounded-lg mt-2 h-12 p-2 border border-borderWhiteGray bg-white dark:border-[#444752] focus:outline-none"
/>
<label className="text-green-600 mt-10 text-md font-bold">
Body
</label>
<textarea
value={description}
onChange={(e) => setDescription(e.target.value)}
placeholder="In line with Celo's connect the world initiative, the foundation has set aside $20m to assist CICO ...."
className="w-[60%] dark:placeholder:text-gray-600 rounded-xl mt-2 h-32 p-2 border border-borderWhiteGray bg-white dark:border-[#444752] focus:outline-none"
/>
<div className="flex flex-row mt-10 w-[60%] justify-between">
<div className="flex flex-col w-2/5 ">
<label className="text-green-600 text-md font-bold">
Location
</label>
<input
value={location}
onChange={(e) => setLocation(e.target.value)}
type="text"
placeholder=""
className="rounded-md mt-2 dark:placeholder:text-gray-600 h-12 p-2 border border-borderWhiteGray bg-white dark:border-[#444752] focus:outline-none"
/>
</div>
<div className="flex flex-col w-2/5">
<label className="text-green-600 text-md font-bold">
Category
</label>
<select
value={category}
onChange={(e) => setCategory(e.target.value)}
className=" mt-2 h-12 p-2 dark:border-gray-600 border rounded-xl border-borderWhiteGray bg-white dark:text-[#9CA3AF] focus:outline-none"
>
<option>Music</option>
<option>Sports</option>
<option>Gaming</option>
<option>News</option>
<option>Entertainment</option>
<option>Education</option>
<option>Technology</option>
<option>Travel</option>
</select>
</div>
</div>
<label className="text-green-600 mt-10 text-md font-bold">
Cover Image
</label>
<div
onClick={() => {
coverImageRef.current.click();
}}
className="border-2 w-64 dark:border-gray-600 border-dashed border-border-gray-300 rounded-md mt-2 p-2 h-46 items-center justify-center flex flex-row"
>
{coverImage ? (
<img
onClick={() => {
coverImageRef.current.click();
}}
src={URL.createObjectURL(coverImage)}
alt="coverImage"
className="h-full rounded-md w-full"
/>
) : (
<BiPlus size={60} color="gray" />
)}
</div>
<input
type="file"
className="hidden"
ref={coverImageRef}
onChange={(e) => {
setCoverImage(e.target.files[0]);
}}
/>
</div>
</div>
</div>
<ToastContainer
position="top-center"
autoClose={5000}
hideProgressBar={false}
newestOnTop={false}
closeOnClick
rtl={false}
pauseOnFocusLoss
draggable
pauseOnHover
/>
</div>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment