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";