diff --git a/packages/shell/rsbuild.config.ts b/packages/shell/rsbuild.config.ts index a1b9340..f412462 100644 --- a/packages/shell/rsbuild.config.ts +++ b/packages/shell/rsbuild.config.ts @@ -82,7 +82,7 @@ export default defineConfig({ catalog: `catalog@${process.env.MFE_URL_CATALOG}/remoteEntry.js`, order: `order@${process.env.MFE_URL_ORDER}/remoteEntry.js`, profile: `profile@${process.env.MFE_URL_PROFILE}/remoteEntry.js`, - marketing: `marketing@https://marketing-mfe.bitovi-sandbox.com/remoteEntry.js`, + marketing: `marketing@${process.env.MFE_URL_MARKETING}/remoteEntry.js`, workshop: `workshop@${process.env.MFE_URL_WORKSHOP}/workshop.js`, }, shared: { diff --git a/packages/shell/src/scenes/Login/Login.tsx b/packages/shell/src/scenes/Login/Login.tsx index 18900dc..7b314a7 100644 --- a/packages/shell/src/scenes/Login/Login.tsx +++ b/packages/shell/src/scenes/Login/Login.tsx @@ -18,15 +18,15 @@ const LoginScene: LoginScene = () => { const navigate = useNavigate(); + const handleLoginSuccess = () => { + setIsLoggedIn(true); + navigate("/shop"); + }; + return ( }> }> - { - setIsLoggedIn(true); - navigate("/shop"); - }} - /> + ); diff --git a/packages/workshop/src/scenes/Exercises/Exercises.tsx b/packages/workshop/src/scenes/Exercises/Exercises.tsx index c778719..73f1da7 100644 --- a/packages/workshop/src/scenes/Exercises/Exercises.tsx +++ b/packages/workshop/src/scenes/Exercises/Exercises.tsx @@ -9,6 +9,8 @@ import FaultTolerance from "./components/FaultTolerance"; import AddingMoreMicroFrontends from "./components/AddingMoreMicroFrontends"; import type { WorkshopScene } from "shared/workshop"; +import SettingUpRoutes from "./components/SettingUpRoutes"; +import CheckoutFlow from "./components/CheckoutFlow"; const Workshop: WorkshopScene = () => { return ( @@ -19,6 +21,8 @@ const Workshop: WorkshopScene = () => { } /> } /> } /> + } /> + } /> ); diff --git a/packages/workshop/src/scenes/Exercises/components/CheckoutFlow/CheckoutFlow.tsx b/packages/workshop/src/scenes/Exercises/components/CheckoutFlow/CheckoutFlow.tsx new file mode 100644 index 0000000..47810e8 --- /dev/null +++ b/packages/workshop/src/scenes/Exercises/components/CheckoutFlow/CheckoutFlow.tsx @@ -0,0 +1,123 @@ +import { Anchor, Code, Grid, Image, List, Text, Title } from "@mantine/core"; + +import ExerciseLayout from "../../shared/components/ExerciseLayout"; + +import shipping from "./assets/shipping.png"; +import payment from "./assets/payment.png"; + +const readLogin = `import { readLocalStorageValue } from "@mantine/hooks"; + +// ... + +const isLoggedIn = readLocalStorageValue({ key: "logged-in" });`; + +const setLogin = `const [, setIsLoggedIn] = useLocalStorage({ + key: "logged-in", + defaultValue: false, + }); + + const handleLoginSuccess = () => { + setIsLoggedIn(true); + }; +}`; + +const CheckoutFlow = () => { + return ( + + + We have a catalog but no way to purchase any of our items, so it's high + time we addressed that. The application needs two parts. + + + User authentication + The checkout flow + + + User Authentication + + + Users should only be able to view the shop when authenticated. To + achieve this, we must implement an authentication check before allowing + access to the shop. Users who are not authenticated should be redirected + to the login page. You can use the following code to check if a user is + authenticated + + + {readLogin} + + + The login micro-frontend (MFE) should be loaded at the{" "} + /login route, ensuring it handles user authentication and + redirects authenticated users back to the shop. + + + The login MFE (profile/login) accepts an{" "} + onLoginSuccess prop. In the component that loads the login + MFE, you can add the following code to handle the authentication portion + of the requirements. However, you will need to add the redirection + logic; here's a{" "} + + hint. + + + + {setLogin} + + + The Checkout Flow + + + We need to implement a checkout flow to enable users to purchase items + from the catalog. This will involve consuming and updating the checkout + MFE (profile/checkout). The checkout flow can be described + as follows. + + + + The user visits/navigates to /order, where they are shown + their order summary and a form to input their shipping information. + + + After entering their shipping information and pressing “continue”, the + user is moved on to order/checkout where they are still + able to view their order summary but the form is now a payment form. + + + + + + + + + + + + Inside the checkout scene, a lot of the infrastructure is already in + place. To achieve this flow, you'll need to: + + + + Update the shell application to load and defer the /order{" "} + route to the + order/checkout MFE. + + + Update the Checkout component in{" "} + src/scenes/Checkout/Checkout.tsx file to handle the + layout and subroutes. + + + Update the Layout component in + src/scenes/Checkout/components/Layout/Layout.tsx to + render the proper view for the app. + + + + ); +}; + +export default CheckoutFlow; diff --git a/packages/workshop/src/scenes/Exercises/components/CheckoutFlow/assets/payment.png b/packages/workshop/src/scenes/Exercises/components/CheckoutFlow/assets/payment.png new file mode 100644 index 0000000..880ce5e Binary files /dev/null and b/packages/workshop/src/scenes/Exercises/components/CheckoutFlow/assets/payment.png differ diff --git a/packages/workshop/src/scenes/Exercises/components/CheckoutFlow/assets/shipping.png b/packages/workshop/src/scenes/Exercises/components/CheckoutFlow/assets/shipping.png new file mode 100644 index 0000000..dd13f78 Binary files /dev/null and b/packages/workshop/src/scenes/Exercises/components/CheckoutFlow/assets/shipping.png differ diff --git a/packages/workshop/src/scenes/Exercises/components/CheckoutFlow/index.ts b/packages/workshop/src/scenes/Exercises/components/CheckoutFlow/index.ts new file mode 100644 index 0000000..f18f7df --- /dev/null +++ b/packages/workshop/src/scenes/Exercises/components/CheckoutFlow/index.ts @@ -0,0 +1 @@ +export { default } from "./CheckoutFlow"; diff --git a/packages/workshop/src/scenes/Exercises/components/Layout/components/hooks/useExercises/exercises.tsx b/packages/workshop/src/scenes/Exercises/components/Layout/components/hooks/useExercises/exercises.tsx index 3ab8fa8..2cd1976 100644 --- a/packages/workshop/src/scenes/Exercises/components/Layout/components/hooks/useExercises/exercises.tsx +++ b/packages/workshop/src/scenes/Exercises/components/Layout/components/hooks/useExercises/exercises.tsx @@ -42,19 +42,24 @@ export const exercises: ExerciseData[] = [ to: "exercise-4", }, { - title: "Individual and Shared Routes", + title: "Setting Up Routes", subTitle: "Most apps (ours included) need routing", to: "exercise-5", }, + { + title: "Checkout Flow", + subTitle: "Our users will need a way to purchase items", + to: "exercise-6", + }, { title: "Pub-Sub and Micro-Frontends", subTitle: "Add MFE to MFE communication with pub-sub", - to: "exercise-6", + to: "exercise-7", }, { title: "The URL for Communication", subTitle: "The URL can also be used to communicate data across MFEs", - to: "exercise-7", + to: "exercise-8", }, { title: "Completed", diff --git a/packages/workshop/src/scenes/Exercises/components/SettingUpRoutes/SettingUpRoutes.tsx b/packages/workshop/src/scenes/Exercises/components/SettingUpRoutes/SettingUpRoutes.tsx new file mode 100644 index 0000000..33af61a --- /dev/null +++ b/packages/workshop/src/scenes/Exercises/components/SettingUpRoutes/SettingUpRoutes.tsx @@ -0,0 +1,52 @@ +import { Code, List, Text, Title } from "@mantine/core"; +import ExerciseLayout from "../../shared/components/ExerciseLayout"; + +const SettingUpRoutes = () => { + return ( + + + We have several pages left to set up for our application. Let's take a + moment to wire up the following MFEs with their respective routes. Each + MFE should maintain the site's layout. + + + + marketing/about at /about + + + marketing/contact at /contact + + + profile/account at /account + + + + Once added, you should be able to navigate to each page using the + header. The account page can be reached by clicking on the user icon. + + + + Viewing Catalog Items + + + Currently, there is no way to view the details of the items in the + catalog list. Let's fix that. Create a dynamic segment under the{" "} + /shop + route so that shop/item/1 and shop/item/2{" "} + render the catalog/item MFE. + + + After setting up the routes, update the CatalogItem{" "} + component in + catalog/src/scene/CatalogItem to use the dynamic path + segment instead of the currently hard-coded id variable. + + + ); +}; + +export default SettingUpRoutes; diff --git a/packages/workshop/src/scenes/Exercises/components/SettingUpRoutes/index.ts b/packages/workshop/src/scenes/Exercises/components/SettingUpRoutes/index.ts new file mode 100644 index 0000000..789a24b --- /dev/null +++ b/packages/workshop/src/scenes/Exercises/components/SettingUpRoutes/index.ts @@ -0,0 +1 @@ +export { default } from "./SettingUpRoutes";