+ `
+}
+
+function notification(_text) {
+ document.querySelector(".alert").style.display = "block"
+ document.querySelector("#notification").textContent = _text
+}
+
+function notificationOff() {
+ document.querySelector(".alert").style.display = "none"
+}
+
+window.addEventListener("load", async () => {
+ notification("⌛ Loading...")
+ await connectCeloWallet()
+ await getBalance()
+ await getProducts()
+ notificationOff()
+});
+
+document
+ .querySelector("#newProductBtn")
+ .addEventListener("click", async (e) => {
+ const params = [
+ document.getElementById("newProductName").value,
+ document.getElementById("newImgUrl").value,
+ document.getElementById("newProductDescription").value,
+ document.getElementById("newLocation").value,
+ new BigNumber(document.getElementById("newPrice").value)
+ .shiftedBy(ERC20_DECIMALS)
+ .toString()
+ ]
+ notification(`⌛ Adding "${params[0]}"...`)
+ try {
+ const result = await contract.methods
+ .writeProduct(...params)
+ .send({ from: kit.defaultAccount })
+ } catch (error) {
+ notification(`⚠️ ${error}.`)
+ }
+ notification(`🎉 You successfully added "${params[0]}".`)
+ getProducts()
+ })
+
+document.querySelector("#marketplace").addEventListener("click", async (e) => {
+ if (e.target.className.includes("buyBtn")) {
+ const index = e.target.id
+ notification("⌛ Waiting for payment approval...")
+ try {
+ await approve(products[index].price)
+ } catch (error) {
+ notification(`⚠️ ${error}.`)
+ }
+ notification(`⌛ Awaiting payment for "${products[index].name}"...`)
+ try {
+ const result = await contract.methods
+ .buyProduct(index)
+ .send({ from: kit.defaultAccount })
+ notification(`🎉 You successfully bought "${products[index].name}".`)
+ getProducts()
+ getBalance()
+ } catch (error) {
+ notification(`⚠️ ${error}.`)
+ }
+ }
+ if (e.target.className.includes("delBtn")) {
+ const index = e.target.id
+ notification(`⌛ Waiting confirm delete..."${products[index].name}"...`)
+ try {
+ const result = await contract.methods
+ .deleteProduct(index)
+ .send({ from: kit.defaultAccount })
+ notification(`🎉 You successfully delete "${products[index].name}".`)
+ getProducts()
+ getBalance()
+ } catch (error) {
+ notification(`⚠️ ${error}.`)
+ }
+ }
+})
+
+document
+ .querySelector("#editProductBtn")
+ .addEventListener("click", async (e) => {
+ const index = document.getElementById('editProductBtn').getAttribute('data-index')
+ const name = document.getElementById("editProductName").value
+ const imageUrl = document.getElementById("editImgUrl").value
+ const description = document.getElementById("editProductDescription").value
+ const location = document.getElementById("editLocation").value
+ const price = new BigNumber(document.getElementById("editPrice").value)
+ .shiftedBy(ERC20_DECIMALS)
+ .toString()
+ notification(`⌛ Edit "${name}"...`)
+ try {
+ const result = await contract.methods
+ .editProduct(index, name, imageUrl, description, location, price)
+ .send({ from: kit.defaultAccount })
+ } catch (error) {
+ notification(`⚠️ ${error}.`)
+ }
+ notification(`🎉 You successfully edit "${name}".`)
+ getProducts()
+ })
+
+document.getElementById('editModal').addEventListener('show.bs.modal', (e) => {
+ document.getElementById('editProductName').value = e.relatedTarget.dataset.name
+ document.getElementById('editImgUrl').value = e.relatedTarget.dataset.image
+ document.getElementById('editProductDescription').value = e.relatedTarget.dataset.description
+ document.getElementById('editLocation').value = e.relatedTarget.dataset.location
+ document.getElementById('editPrice').value = e.relatedTarget.dataset.price
+ document.getElementById('editProductBtn').setAttribute('data-index', e.relatedTarget.dataset.index)
+});
\ No newline at end of file
diff --git a/content/celo101_chapter_4.md b/content/celo101_chapter_4.md
new file mode 100644
index 0000000..47bb7b7
--- /dev/null
+++ b/content/celo101_chapter_4.md
@@ -0,0 +1,312 @@
+In previous chapters, you learn how to read, write, buy product in marketplace. But this is a marketplace where buyer and seller exchange goods, the buyer need to edit their product such as price, name, description, etc ... And if they dont want to sell this product, they may need to delete it right ? In this section, you will learn how to create edit & delete function into smart contract and implement it to frontend
+
+## 4.1 Edit function
+
+Open a `marketplace.sol` contract you already write in chapter 2.
+Create a function to let user edit a new value to their current product. Name it `editProduct`. You have to specific the type of parameters of the function.
+You need an index as a parameter to specific which product will edit. And, you also need to add _name, _image, _description, and _location. They are all a string stored in memory and the price is an uint.
+
+The function use public method so that everyone can edit. But one thing important, only owner of product can edit their own product not everyone, so use `require` function to ensure that ([Learn more about error handling](https://docs.soliditylang.org/en/latest/control-structures.html#error-handling-assert-require-revert-and-exceptions)).
+
+This method prevent others user try to edit your product, it will display error message. Otherwise smartcontract excute edit function.
+
+```solidity
+ function editProduct(uint _index,
+ string memory _name,
+ string memory _image,
+ string memory _description,
+ string memory _location,
+ uint _price
+ ) public {
+ require(products[_index].owner == msg.sender, "You can not edit this product.");
+ products[_index].name = _name;
+ products[_index].image = _image;
+ products[_index].description = _description;
+ products[_index].location = _location;
+ products[_index].price = _price;
+ }
+```
+
+You're done with edit function.
+
+## 4.2 Delete funtion
+
+Next create a function to let user delete their product. Name it `deleteProduct`. You only need to pass an index as a parameter to specific which product will delete. ([Learn more about delete function](https://docs.soliditylang.org/en/v0.8.2/types.html?highlight=delete#delete)).
+
+* Notes if you use `delete products`, it will reset all members inside, so in this case `delete products[_index]` will delete the value store at _index.
+
+Like edit function, delete function use public method and use `require` function to ensure only owner of product can delete it not everyone.
+
+```solidity
+ function deleteProduct(uint _index) public {
+ require(products[_index].owner == msg.sender, "You can not delete this product.");
+ delete products[_index];
+ }
+```
+
+You're done with delete function.
+
+## 4.3 Implement to frontend
+
+You will need to redeploy the marketplace.sol into celo blockchain and replace it with the new one you deploy. (You can watch it in in chapter 2).
+```
+ const MPContractAddress = "0x564b27A5499fa3fcd4B763Ae4120282fa0eF6De2"
+```
+I already deploy it here:
+https://alfajores-blockscout.celo-testnet.org/address/0x564b27A5499fa3fcd4B763Ae4120282fa0eF6De2/transactions
+
+In order to interact with your smart contract that is deployed in bytecode, you need an interface, you need to copy the new ABI (Application Binary Interface) and save it into `marketplace.abi.json` file of the contracts folder in your project.
+
+In this scenario, you continue use bootstrap and old code from chapter 3.
+First open `index.html`, below add new product modal, you need to edit a modal that opens up when the user clicks on the Edit product button. This code is pretty long.
+
+```html
+
+
+
+
+
+
Edit Product
+
+
+
+
+
+
+
+
+
+
+
+```
+### Display edit & delete button
+
+Open the main.js file inside the src folder of your project. In function ```productTemplate```, create a variable ```configProduct```, this variable is the HTML of button edit & delete. It has condition to check only of owner product will display these button
+
+```html
+ let configProduct = ""
+ if (kit.defaultAccount === _product.owner) {
+ configProduct = `
+
+
+ `
+ }
+```
+
+And modify the return ```productTemplate``` HTML
+
+```html
+return `
+
+ `
+```
+
+### Hide deleted products
+
+Go to function `renderProducts` and add
+
+```javascript
+ if (_product.owner == "0x0000000000000000000000000000000000000000") return
+```
+
+When use function `delete` in smartcontract, it will set to 0, you need a condition to check if owner is valid so it won't display the deleted product. The complete code will be like this:
+
+```javascript
+function renderProducts() {
+ document.getElementById("marketplace").innerHTML = ""
+ products.forEach((_product) => {
+ const newDiv = document.createElement("div")
+ newDiv.className = "col-md-4"
+ if (_product.owner == "0x0000000000000000000000000000000000000000") return
+ newDiv.innerHTML = productTemplate(_product)
+ document.getElementById("marketplace").appendChild(newDiv)
+ })
+}
+```
+
+### Call function editProduct
+
+To interact with ```editProduct``` function you should open a modal edit box and adapt a edit button event. Move to button of file main.js, and add event listen when user click on edit button to open modal box.
+
+```javascript
+document.getElementById('editModal').addEventListener('show.bs.modal', (e) => {
+ document.getElementById('editProductName').value = e.relatedTarget.dataset.name
+ document.getElementById('editImgUrl').value = e.relatedTarget.dataset.image
+ document.getElementById('editProductDescription').value = e.relatedTarget.dataset.description
+ document.getElementById('editLocation').value = e.relatedTarget.dataset.location
+ document.getElementById('editPrice').value = e.relatedTarget.dataset.price
+ document.getElementById('editProductBtn').setAttribute('data-index', e.relatedTarget.dataset.index)
+});
+```
+
+When edit modal is display, user modify product and click submit button to interact with `editProduct` function, you should receive the product name and show them a notification about what is happening.
+
+```javascript
+document
+ .querySelector("#editProductBtn")
+ .addEventListener("click", async (e) => {
+ const index = document.getElementById('editProductBtn').getAttribute('data-index')
+ const name = document.getElementById("editProductName").value
+ const imageUrl = document.getElementById("editImgUrl").value
+ const description = document.getElementById("editProductDescription").value
+ const location = document.getElementById("editLocation").value
+ const price = new BigNumber(document.getElementById("editPrice").value)
+ .shiftedBy(ERC20_DECIMALS)
+ .toString()
+ notification(`⌛ Edit "${name}"...`)
+ try {
+ const result = await contract.methods
+ .editProduct(index, name, imageUrl, description, location, price)
+ .send({ from: kit.defaultAccount })
+ } catch (error) {
+ notification(`⚠️ ${error}.`)
+ }
+ notification(`🎉 You successfully edit "${name}".`)
+ getProducts()
+ })
+```
+
+### Call function deleteProduct
+
+Move to ```document.querySelector("#marketplace")``` add event delete, if user click on delete button, call to `deleteProduct` function. Then send them a notification and render the products again,
+
+```javascript
+ if (e.target.className.includes("delBtn")) {
+ const index = e.target.id
+ notification(`⌛ Waiting confirm delete..."${products[index].name}"...`)
+ try {
+ const result = await contract.methods
+ .deleteProduct(index)
+ .send({ from: kit.defaultAccount })
+ notification(`🎉 You successfully delete "${products[index].name}".`)
+ getProducts()
+ getBalance()
+ } catch (error) {
+ notification(`⚠️ ${error}.`)
+ }
+ }
+```
+
+Finally, you should display all notifications. If there is no error, call your getProducts function again to show the updated products in your DApp, and yourgetBalance function to show the updated balance after the user bought the product.
+
+