Created
September 18, 2020 01:51
-
-
Save rodkeys/e22a228447919f8e73528bef0df1de99 to your computer and use it in GitHub Desktop.
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, { Component } from "react"; | |
import "./App.css"; | |
import Box from "3box"; | |
import { BrowserRouter as Router, Switch, Route } from "react-router-dom"; | |
import "bootstrap/dist/css/bootstrap.min.css"; | |
import Nav from "./components/Nav"; | |
import { BounceLoader } from "react-spinners"; | |
// import ChatBox from "3box-chatbox-react"; | |
import MyStore from "./pages/MyStore"; | |
import Home from "./pages/Home"; | |
import Cart from "./pages/Cart"; | |
import AddListing from "./pages/AddListing"; | |
import Profile from "./pages/Profile"; | |
import Orders from "./pages/Orders"; | |
import Inbox from "./pages/Inbox"; | |
import Thread from "./pages/Thread"; | |
import { SPACE_NAME } from "./Constants"; | |
// 3Box identity | |
const getThreeBox = async (address) => { | |
const profile = await Box.getProfile(address); | |
return profile; | |
}; | |
export default class App extends Component { | |
// Changes to true if Metamask isn't detected, or there's a problem | |
state = { | |
needToAWeb3Browser: false, | |
}; | |
/** | |
* getAddressFromMetaMask => fetch the user's Ethereum account | |
* * Function isn't limited to MetaMask; works for all Web3 enabled browswers | |
*/ | |
async getAddressFromMetaMask() { | |
if (typeof window.ethereum == "undefined") { | |
this.setState({ needToAWeb3Browser: true }); | |
} else { | |
window.ethereum.autoRefreshOnNetworkChange = false; //silences warning about no autofresh on network change | |
const accounts = await window.ethereum.enable(); | |
this.setState({ accounts }); | |
} | |
} | |
/** | |
* componentDidMount | |
* * Take care how many times this function is called | |
* * We're loading the user's listing, not all the listings from the marketplace | |
* * The user is the moderator of their own store | |
*/ | |
async componentDidMount() { | |
// Set the background color (need to move this out of here) | |
document.body.style.backgroundColor = "#ffffff"; | |
// Fetch the user's ethereum account | |
await this.getAddressFromMetaMask(); | |
// Get 3Box profile of the ethereum account | |
if (this.state.accounts) { | |
const threeBoxProfile = await getThreeBox(this.state.accounts[0]); | |
this.setState({ threeBoxProfile }); | |
} | |
const userMod = this.state.accounts[0]; | |
this.setState({ userMod }); | |
const admin = "0xf54d276a029a49458e71167ebc25d1cca235ee6f"; | |
this.setState({ admin }); | |
// Open the 3Box object of the user's account | |
const box = await Box.openBox(this.state.accounts[0], window.ethereum); | |
await box.syncDone; | |
this.setState({ box }); | |
// Open the demo marketplace 'space' of the user | |
const space = await this.state.box.openSpace(SPACE_NAME); | |
this.setState({ space }); | |
// Create and fetch the listings thread of the user's store | |
const thread = await space.joinThread("listing_list", { | |
firstModerator: userMod, | |
members: true, | |
}); | |
this.setState({ thread }, () => this.getListingsThread()); | |
// Create a public inbox for the user | |
const inboxThread = await space.joinThread("inboxTestnet", { | |
firstModerator: userMod, | |
members: false, | |
ghost: false, | |
confidential: false, | |
}); | |
this.setState({ inboxThread }, () => this.getInboxThread()); | |
// Create and fetch the listings in the shopping cart | |
const shoppingCart = await space.joinThread("demo-shoppingCart-public", { | |
firstModerator: userMod, | |
members: true, | |
ghost: false, | |
confidential: false, | |
}); | |
this.setState({ shoppingCart }, () => this.getShoppingCartThread()); | |
// Create and fetch the orders | |
const orders = await space.joinThread("demo-orders-public", { | |
firstModerator: userMod, | |
members: true, | |
ghost: false, | |
confidential: false, | |
}); | |
this.setState({ orders }, () => this.getOrdersThread()); | |
// Create and fetch the testnet receipts | |
const testnetReceipts = await space.joinThread( | |
"demo-testnet-receipts-public", | |
{ | |
firstModerator: userMod, | |
members: true, | |
ghost: false, | |
confidential: false, | |
} | |
); | |
this.setState({ testnetReceipts }, () => this.getTestnetReceipts()); | |
// Join global chat | |
const globalChat = await space.joinThread("globalListChat"); | |
this.setState({ globalChat }); | |
// Fetch the listings in the thread of the global marketplace | |
const globalThread = await space.joinThreadByAddress( | |
"/orbitdb/zdpuAosv7kRPN49quPCwVr5p531SwjycjdxQeEbM9Y3SiNBp9/3box.thread.demo-marketplace.globalList" | |
); | |
this.setState({ globalThread }, () => this.getGlobalListingsThread()); | |
// TEST: remove later | |
/* const submarketThread = await space.joinThread("bbb", { | |
firstModerator: "0xf54D276a029a49458E71167EBc25D1cCa235ee6f", | |
members: false, | |
}); | |
this.setState({ submarketThread }, () => this.getSubmarketThread()); */ | |
} | |
/** | |
* getListingsThread => Fetch the listings in a user's store | |
*/ | |
async getListingsThread() { | |
if (!this.state.thread) { | |
console.error("listings thread not in react state"); | |
return; | |
} | |
// Fetch the listings and add them to state | |
const posts = await this.state.thread.getPosts(); | |
this.setState({ posts }); | |
// Update the state when new listings are added | |
await this.state.thread.onUpdate(async () => { | |
const posts = await this.state.thread.getPosts(); | |
this.setState({ posts }); | |
}); | |
} | |
/** | |
* getInboxThread => Fetch the messages in a user's inbox | |
*/ | |
async getInboxThread() { | |
if (!this.state.inboxThread) { | |
console.error("messages in inbox thread not in react state"); | |
return; | |
} | |
// Save the thread address | |
const inboxThreadAddress = this.state.inboxThread.address; | |
this.setState({ inboxThreadAddress }); | |
// Fetch the messages and add them to state | |
const inboxMessages = await this.state.inboxThread.getPosts(); | |
this.setState({ inboxMessages }); | |
// Update the state when new messages are added | |
await this.state.inboxThread.onUpdate(async () => { | |
const inboxMessages = await this.state.inboxThread.getPosts(); | |
this.setState({ inboxMessages }); | |
}); | |
} | |
/** | |
* getGlobalListingsThread => Fetch the listings from the global marketplace | |
*/ | |
async getGlobalListingsThread() { | |
if (!this.state.globalThread) { | |
console.error("global listings thread not in react state"); | |
return; | |
} | |
// Fetch the listings and add them to state | |
const globalPosts = await this.state.globalThread.getPosts(); | |
this.setState({ globalPosts }); | |
// Update the state when new listings are added | |
await this.state.globalThread.onUpdate(async () => { | |
const globalPosts = await this.state.globalThread.getPosts(); | |
this.setState({ globalPosts }); | |
}); | |
} | |
/** | |
* getShoppingCartThread => Fetch the cart items in a user's store | |
*/ | |
async getShoppingCartThread() { | |
if (!this.state.shoppingCart) { | |
console.error("shoppingCart thread not in react state"); | |
return; | |
} | |
// Fetch the cart items and add them to state | |
const cartItems = await this.state.shoppingCart.getPosts(); | |
this.setState({ cartItems }); | |
// Update the shopping cart when new items are added | |
await this.state.shoppingCart.onUpdate(async () => { | |
const cartItems = await this.state.shoppingCart.getPosts(); | |
this.setState({ cartItems }); | |
}); | |
// Fetch the order price and add it to state | |
const prices = this.state.cartItems.map((x) => | |
parseFloat(x.message.message.price) | |
); | |
const orderPrice = prices.reduce((a, b) => a + b, 0).toFixed(2); | |
this.setState({ orderPrice }); | |
} | |
/** | |
* getOrdersThread => Fetch orders for a user | |
*/ | |
async getOrdersThread() { | |
if (!this.state.orders) { | |
console.error("orders thread not in react state"); | |
return; | |
} | |
// Fetch the cart items and add them to state | |
const orderItems = await this.state.orders.getPosts(); | |
this.setState({ orderItems }); | |
// Update the shopping cart when new items are added | |
await this.state.orders.onUpdate(async () => { | |
const orderItems = await this.state.orders.getPosts(); | |
this.setState({ orderItems }); | |
}); | |
} | |
/** | |
* getTestnetReceiptsThread => Fetch receipts from testnet | |
*/ | |
async getTestnetReceipts() { | |
if (!this.state.testnetReceipts) { | |
console.error("testnet receipts thread not in react state"); | |
return; | |
} | |
// Fetch the cart items and add them to state | |
const testnetReceiptItems = await this.state.testnetReceipts.getPosts(); | |
this.setState({ testnetReceiptItems }); | |
// Update the shopping cart when new items are added | |
await this.state.testnetReceipts.onUpdate(async () => { | |
const testnetReceiptItems = await this.state.testnetReceipts.getPosts(); | |
this.setState({ testnetReceiptItems }); | |
}); | |
} | |
async joinSubmarket() { | |
// Fetch the listings in the thread of the global marketplace | |
const space = this.state.space; | |
const submarketThread = await space.joinThread("bbb", { | |
firstModerator: "0xf54D276a029a49458E71167EBc25D1cCa235ee6f", | |
members: false, | |
}); | |
this.setState({ submarketThread }, () => this.getSubmarketThread()); | |
} | |
async getSubmarketThread() { | |
if (!this.state.submarketThread) { | |
console.error("global listings thread not in react state"); | |
return; | |
} | |
// Fetch the listings and add them to state | |
const submarketPosts = await this.state.submarketThread.getPosts(); | |
this.setState({ submarketPosts }); | |
// Update the state when new listings are added | |
await this.state.submarketThread.onUpdate(async () => { | |
const submarketPosts = await this.state.submarketThread.getPosts(); | |
this.setState({ submarketPosts }); | |
}); | |
} | |
render() { | |
if (this.state.needToAWeb3Browser) { | |
return <h1>Please install metamask</h1>; //! Need something nice here | |
} | |
return ( | |
<Router> | |
<div> | |
<Nav | |
cartItems={this.state.cartItems} | |
inboxMessages={this.state.inboxMessages} | |
style={{ background: "#ffffff" }} | |
/> | |
<Switch> | |
<Route path="/profile"> | |
{this.state.space && ( | |
<Profile | |
box={this.state.box} | |
space={this.state.space} | |
accounts={this.state.accounts} | |
threeBoxProfile={this.state.threeBoxProfile} | |
/> | |
)} | |
{!this.state.space && ( | |
<div style={{ width: "60px", margin: "auto" }}> | |
<BounceLoader color={"blue"} /> | |
</div> | |
)} | |
</Route> | |
<Route path="/add-listing"> | |
{this.state.accounts && ( | |
<AddListing | |
accounts={this.state.accounts} | |
thread={this.state.thread} | |
globalThread={this.state.globalThread} | |
box={this.state.box} | |
space={this.state.space} | |
threadMembers={this.state.threadMembers} | |
posts={this.state.posts} | |
globalPosts={this.state.globalPosts} | |
threeBoxProfile={this.state.threeBoxProfile} | |
getListingsThread={this.getListingsThread.bind(this)} | |
getGlobalListingsThread={this.getGlobalListingsThread.bind( | |
this | |
)} | |
inboxThreadAddress={this.state.inboxThreadAddress} | |
getSubmarketThread={this.getSubmarketThread.bind(this)} | |
submarketThread={this.state.submarketThread} | |
submarketPosts={this.state.submarketPosts} | |
/> | |
)} | |
{!this.state.accounts && <h1>Login with metamask</h1>} | |
</Route> | |
<Route path="/my-store"> | |
<MyStore | |
thread={this.state.thread} | |
posts={this.state.posts} | |
globalThread={this.state.globalThread} | |
globalPosts={this.state.globalPosts} | |
space={this.state.space} | |
box={this.state.box} | |
getGlobalListingsThread={this.getGlobalListingsThread.bind( | |
this | |
)} | |
getListingsThread={this.getListingsThread.bind(this)} | |
usersAddress={ | |
this.state.accounts ? this.state.accounts[0] : null | |
} | |
/> | |
</Route> | |
<Route path="/cart"> | |
<Cart | |
space={this.state.space} | |
box={this.state.box} | |
cartItems={this.state.cartItems} | |
shoppingCart={this.state.shoppingCart} | |
getShoppingCartThread={this.getShoppingCartThread.bind(this)} | |
usersAddress={ | |
this.state.accounts ? this.state.accounts[0] : null | |
} | |
orderPrice={this.state.orderPrice} | |
orders={this.state.orders} | |
orderItems={this.state.orderItems} | |
getOrdersThread={this.getOrdersThread.bind(this)} | |
userMod={this.state.userMod} | |
/> | |
</Route> | |
<Route path="/orders"> | |
<Orders | |
space={this.state.space} | |
box={this.state.box} | |
getTestnetReceipts={this.getTestnetReceipts.bind(this)} | |
testnetReceipts={this.state.testnetReceipts} | |
testnetReceiptItems={this.state.testnetReceiptItems} | |
usersAddress={ | |
this.state.accounts ? this.state.accounts[0] : null | |
} | |
/> | |
</Route> | |
<Route path="/inbox"> | |
<Inbox | |
space={this.state.space} | |
box={this.state.box} | |
inboxThread={this.state.inboxThread} | |
inboxMessages={this.state.inboxMessages} | |
getInboxThread={this.getInboxThread.bind(this)} | |
usersAddress={ | |
this.state.accounts ? this.state.accounts[0] : null | |
} | |
/> | |
</Route> | |
<Route exact path="/s/:threadId"> | |
<Thread | |
thread={this.state.thread} | |
posts={this.state.posts} | |
globalThread={this.state.globalThread} | |
globalPosts={this.state.globalPosts} | |
space={this.state.space} | |
box={this.state.box} | |
getGlobalListingsThread={this.getGlobalListingsThread.bind( | |
this | |
)} | |
getListingsThread={this.getListingsThread.bind(this)} | |
usersAddress={ | |
this.state.accounts ? this.state.accounts[0] : null | |
} | |
joinSubmarket={this.joinSubmarket.bind(this)} | |
getSubmarketThread={this.getSubmarketThread.bind(this)} | |
submarketThread={this.state.submarketThread} | |
submarketPosts={this.state.submarketPosts} | |
/> | |
</Route> | |
<Route path="/"> | |
<Home | |
globalThread={this.state.globalThread} | |
globalPosts={this.state.globalPosts} | |
space={this.state.space} | |
box={this.state.box} | |
getGlobalListingsThread={this.getGlobalListingsThread.bind( | |
this | |
)} | |
cartItems={this.state.cartItems} | |
shoppingCart={this.state.shoppingCart} | |
getShoppingCartThread={this.getShoppingCartThread.bind(this)} | |
usersAddress={ | |
this.state.accounts ? this.state.accounts[0] : null | |
} | |
admin={this.state.admin} | |
testnetReceipts={this.state.testnetReceipts} | |
testnetReceiptItems={this.state.testnetReceiptItems} | |
getTestnetReceipts={this.getTestnetReceipts.bind(this)} | |
inboxThread={this.state.inboxThread} | |
inboxMessages={this.state.inboxMessages} | |
getInboxThread={this.getInboxThread.bind(this)} | |
/> | |
</Route> | |
</Switch> | |
</div> | |
{/* <div className="userscontainer"> | |
{this.state.space && ( | |
<ChatBox | |
// required | |
spaceName={SPACE_NAME} | |
threadName="globalListChat" | |
// Required props for context A) & B) | |
box={this.state.box} | |
currentUserAddr={ | |
this.state.accounts ? this.state.accounts[0] : null | |
} | |
// optional | |
mute={false} | |
popupChat | |
showEmoji | |
colorTheme="#181F21" | |
currentUser3BoxProfile={this.state.threeBoxProfile} | |
agentProfile={{ | |
chatName: "Spendit chat", | |
}} | |
openOnMount={false} | |
/> | |
)} | |
</div> */} | |
</Router> | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment