From df661089e52566815c634612b36ac52e9a8f89cc Mon Sep 17 00:00:00 2001 From: Ayo Ayco Date: Mon, 22 Jan 2024 23:15:28 +0100 Subject: [PATCH] feat: orchestrator usage across MFs (#1) --- app-cart/src/Cart.jsx | 139 ++++++++++++++++++++++++--------------- app-heading/src/App.jsx | 8 ++- app-products/src/App.jsx | 3 +- utils/index.js | 1 + utils/orchestrator.mjs | 18 ++++- 5 files changed, 112 insertions(+), 57 deletions(-) diff --git a/app-cart/src/Cart.jsx b/app-cart/src/Cart.jsx index 3951afb..c1610ae 100644 --- a/app-cart/src/Cart.jsx +++ b/app-cart/src/Cart.jsx @@ -1,71 +1,102 @@ // @ts-check -// import { broadcast } from 'utils/orchestrator' -import React, { useState } from "react"; -const Cart = () => { - const [products, setProducts] = useState([ - { - name: "Shoe A", - description: "It is a good shoe", - price: 100, - count: 2, - }, - { - name: "Shoe B", - description: "It is a comfortable shoe", - price: 120, - count: 7, - }, - ]); +import { broadcast, listen } from "utils"; +import React, { Component } from "react"; - // listen to add-to-cart messages - // if item is already in cart, increment count +class Cart extends Component { + constructor(props) { + super(props); + this.state = { + products: [ + { + name: "Shoe A", + description: "It is a good shoe", + price: 100, + count: 2, + }, + { + name: "Shoe B", + description: "It is a comfortable shoe", + price: 120, + count: 7, + }, + ], + }; + } - const getTotal = () => { + getTotalItems = () => { + const { products } = this.state; + return products.reduce((acc, product) => { + return acc + product.count; + }, 0); + }; + + getTotalPrice = () => { + const { products } = this.state; return products.reduce((acc, product) => { return acc + product.price * product.count; }, 0); }; - const decreaseCount = (index) => { - // if in cart, decrease count - const updatedProducts = [...products]; - if (updatedProducts[index].count > 1) { - updatedProducts[index].count--; + addProduct = (product) => { + const { products } = this.state; + const index = products.findIndex((p) => p.name === product.name); + if (index > -1) { + const updatedProducts = [...products]; + updatedProducts[index].count++; + this.setState({ products: updatedProducts }); } else { - updatedProducts.splice(index, 1); + this.setState({ products: [...products, { ...product, count: 1 }] }); } - setProducts(updatedProducts); }; - const increaseCount = (index) => { - // if in cart, increase count - const updatedProducts = [...products]; - updatedProducts[index].count++; - setProducts(updatedProducts); + removeProduct = (product) => { + const { products } = this.state; + const index = products.findIndex((p) => p.name === product.name); + if (index > -1) { + const updatedProducts = [...products]; + updatedProducts[index].count--; + this.setState({ products: updatedProducts }); + } }; - return ( -
-

🛒 Cart

- + componentDidMount() { + broadcast("update-count", this.getTotalItems()); + listen("add-product", this.addProduct); + } - Total: - ${getTotal()} -
- ); -}; + componentDidUpdate(prevProps, prevState) { + const { products } = this.state; + if (prevState.products !== products) { + broadcast("update-count", this.getTotalItems()); + } + } + + render() { + const { products } = this.state; + + return ( +
+

🛒 Cart

+ + + Total: + ${this.getTotalPrice()} +
+ ); + } +} export default Cart; diff --git a/app-heading/src/App.jsx b/app-heading/src/App.jsx index d5922d8..e0d34c3 100644 --- a/app-heading/src/App.jsx +++ b/app-heading/src/App.jsx @@ -1,4 +1,5 @@ -import React from "react"; +import { listen } from "utils"; +import React, { useEffect } from "react"; import "./App.css"; const App = (props) => { @@ -6,6 +7,11 @@ const App = (props) => { const [count, setCount] = React.useState(0); // listen to add-to-cart messages + useEffect(() => + listen("update-count", (count) => { + setCount(count); + }) + ); return (
diff --git a/app-products/src/App.jsx b/app-products/src/App.jsx index 6ae3222..7d4a067 100644 --- a/app-products/src/App.jsx +++ b/app-products/src/App.jsx @@ -1,3 +1,4 @@ +import { broadcast } from "utils"; import styles from "./App.module.css"; function App() { @@ -25,8 +26,8 @@ function App() { ]; const addToCart = (product) => { - console.log(">>> add to cart", product); // broadcast add product to cart + broadcast("add-product", product); }; return ( diff --git a/utils/index.js b/utils/index.js index e69de29..f3fb4e4 100644 --- a/utils/index.js +++ b/utils/index.js @@ -0,0 +1 @@ +export { broadcast, listen } from "./orchestrator.mjs"; diff --git a/utils/orchestrator.mjs b/utils/orchestrator.mjs index 2c27412..7856c19 100644 --- a/utils/orchestrator.mjs +++ b/utils/orchestrator.mjs @@ -1,3 +1,19 @@ // implement messaging system between MF's +const listeners = {}; + // - broadcast message -// - listen to message & attach callback \ No newline at end of file +export function broadcast(action, data) { + window.parent.postMessage({ action, data }); + console.log("broadcast", { action, data }); +} + +// - listen to message & attach callback +export function listen(action, callback) { + window.parent.addEventListener("message", (event) => { + const { data } = event; + + if (data.action === action) { + callback(data.data); + } + }); +}