-
-
Save Ernesto-tha-great/4fdbe33cefdd51c3dad5ca3895f12037 to your computer and use it in GitHub Desktop.
Pages
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | |
); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | |
); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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