Repository: dcapal/dcapal (language: rust)

Issue:
Add demo portfolios
- Mr. RIP
- All Seasons Portfolio
- 60/40


Discussion / hints:

Fix patch:
diff --git a/dcapal-frontend/demo/dcapal-60-40.json b/dcapal-frontend/demo/dcapal-60-40.json
new file mode 100644
index 00000000..8eef4493
--- /dev/null
+++ b/dcapal-frontend/demo/dcapal-60-40.json
@@ -0,0 +1,27 @@
+{
+  "quoteCcy": "eur",
+  "assets": [
+    {
+      "symbol": "VWCE.MI",
+      "name": "Vanguard FTSE All-World UCITS ETF",
+      "baseCcy": "eur",
+      "provider": "YF",
+      "price": 92.69000244140625,
+      "qty": 54,
+      "amount": 5005.2601318359375,
+      "weight": 50.01399448644559,
+      "targetWeight": 60
+    },
+    {
+      "symbol": "AGGH.MI",
+      "name": "iShares Core Global Aggregate Bond UCITS ETF",
+      "baseCcy": "eur",
+      "provider": "YF",
+      "price": 4.640500068664551,
+      "qty": 1078,
+      "amount": 5002.459074020386,
+      "weight": 49.98600551355442,
+      "targetWeight": 40
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dcapal-frontend/demo/dcapal-all-seasons.json b/dcapal-frontend/demo/dcapal-all-seasons.json
new file mode 100644
index 00000000..8fe796d1
--- /dev/null
+++ b/dcapal-frontend/demo/dcapal-all-seasons.json
@@ -0,0 +1,60 @@
+{
+  "quoteCcy": "eur",
+  "assets": [
+    {
+      "symbol": "VWCE.MI",
+      "name": "Vanguard FTSE All-World UCITS ETF",
+      "baseCcy": "eur",
+      "provider": "YF",
+      "price": 92.69000244140625,
+      "qty": 22,
+      "amount": 2039.1800537109375,
+      "weight": 20.16928173647701,
+      "targetWeight": 30
+    },
+    {
+      "symbol": "AGGH.MI",
+      "name": "iShares Core Global Aggregate Bond UCITS ETF",
+      "baseCcy": "eur",
+      "provider": "YF",
+      "price": 4.640500068664551,
+      "qty": 431,
+      "amount": 2000.0555295944214,
+      "weight": 19.782305830021098,
+      "targetWeight": 40
+    },
+    {
+      "symbol": "IBGX.MI",
+      "name": "iShares € Govt Bond 3-5yr UCITS ETF",
+      "baseCcy": "eur",
+      "provider": "YF",
+      "price": 158.44000244140625,
+      "qty": 13,
+      "amount": 2059.7200317382812,
+      "weight": 20.37244015936401,
+      "targetWeight": 15
+    },
+    {
+      "symbol": "SGLD.MI",
+      "name": "Invesco Physical Gold ETC",
+      "baseCcy": "eur",
+      "provider": "YF",
+      "price": 177.1699981689453,
+      "qty": 11,
+      "amount": 1948.8699798583984,
+      "weight": 19.276035787028295,
+      "targetWeight": 7.5
+    },
+    {
+      "symbol": "CMOD.MI",
+      "name": "Invesco Bloomberg Commodity UCITS ETF",
+      "baseCcy": "eur",
+      "provider": "YF",
+      "price": 20.625,
+      "qty": 100,
+      "amount": 2062.5,
+      "weight": 20.39993648710958,
+      "targetWeight": 7.5
+    }
+  ]
+}
\ No newline at end of file
diff --git a/dcapal-frontend/src/app/config.js b/dcapal-frontend/src/app/config.js
index fdc526a8..2f832984 100644
--- a/dcapal-frontend/src/app/config.js
+++ b/dcapal-frontend/src/app/config.js
@@ -8,4 +8,6 @@ export const IMAGEKIT_URL = "https://ik.imagekit.io/dcapal";
 
 export const MEDIA_SMALL = "only screen and (min-width: 521px)";
 
+export const DEMO_PF_60_40 = "60-40";
+export const DEMO_PF_ALL_SEASONS = "all-seasons";
 export const DEMO_PF_MR_RIP = "mr-rip";
diff --git a/dcapal-frontend/src/components/core/inputNumber.js b/dcapal-frontend/src/components/core/inputNumber.js
index d5aee1be..4025cefa 100644
--- a/dcapal-frontend/src/components/core/inputNumber.js
+++ b/dcapal-frontend/src/components/core/inputNumber.js
@@ -42,7 +42,6 @@ export const InputNumber = ({
       newValue = newValue.substr(1);
     }
 
-    newValue = newValue.replace(/,/g, "");
     if (newValue === "") {
       newValue = null;
     } else if (type === InputNumberType.DECIMAL) {
diff --git a/dcapal-frontend/src/routes/demoPage.js b/dcapal-frontend/src/routes/demoPage.js
index 6be0d0ef..d0e67537 100644
--- a/dcapal-frontend/src/routes/demoPage.js
+++ b/dcapal-frontend/src/routes/demoPage.js
@@ -8,16 +8,30 @@ import { Footer } from "../components/core/footer";
 import { clearPortfolio } from "../components/allocationFlow/portfolioStep/portfolioSlice";
 import { setAllocationFlowStep, setPfolioFile, Step } from "../app/appSlice";
 
-import { DEMO_PF_MR_RIP } from "../app/config";
+import {
+  DEMO_PF_60_40,
+  DEMO_PF_ALL_SEASONS,
+  DEMO_PF_MR_RIP,
+} from "../app/config";
+import PF_60_40 from "../../demo/dcapal-60-40.json";
+import PF_ALL_SEASONS from "../../demo/dcapal-all-seasons.json";
 import PF_MR_RIP from "../../demo/dcapal-mrrip.json";
 
+const demoPortfolios = {
+  [DEMO_PF_60_40]: JSON.stringify(PF_60_40),
+  [DEMO_PF_ALL_SEASONS]: JSON.stringify(PF_ALL_SEASONS),
+  [DEMO_PF_MR_RIP]: JSON.stringify(PF_MR_RIP),
+};
+
 const getPfolioFile = (path) => {
   const demoId = path
     .split("/")
     .filter((e) => e !== "")
     .pop();
 
-  if (demoId === DEMO_PF_MR_RIP) return JSON.stringify(PF_MR_RIP);
+  if (demoId in demoPortfolios) {
+    return demoPortfolios[demoId];
+  }
 
   return "";
 };
diff --git a/dcapal-frontend/src/routes/router.js b/dcapal-frontend/src/routes/router.js
index 8ad8175c..c268de6a 100644
--- a/dcapal-frontend/src/routes/router.js
+++ b/dcapal-frontend/src/routes/router.js
@@ -3,7 +3,7 @@ import { useDispatch, useSelector } from "react-redux";
 import { useLocation, useRoutes } from "react-router-dom";
 import { App } from "../app";
 import { setAllocationFlowStep, Step } from "../app/appSlice";
-import { DEMO_PF_MR_RIP } from "../app/config";
+
 import AboutPage from "./aboutPage";
 import DemoPage from "./demoPage";
 import ErrorPage from "./errorPage";
@@ -11,6 +11,12 @@ import NotFoundPage from "./notFoundPage";
 import { Root } from "./root";
 import UnderConstructionPage from "./underConstruction";
 
+import {
+  DEMO_PF_60_40,
+  DEMO_PF_ALL_SEASONS,
+  DEMO_PF_MR_RIP,
+} from "../app/config";
+
 export const Router = () => {
   const step = useSelector((state) => state.app.allocationFlowStep);
 
@@ -23,7 +29,7 @@ export const Router = () => {
     }
   }, [location]);
 
-  const routes = useRoutes([
+  let routesConfig = [
     {
       path: "*",
       element: <NotFoundPage />,
@@ -48,12 +54,18 @@ export const Router = () => {
       element: <UnderConstructionPage title="Docs" />,
       errorElement: <ErrorPage />,
     },
-    {
-      path: `demo/${DEMO_PF_MR_RIP}`,
+  ];
+
+  const demoRoutes = [DEMO_PF_60_40, DEMO_PF_ALL_SEASONS, DEMO_PF_MR_RIP];
+  for (const route of demoRoutes) {
+    routesConfig.push({
+      path: `demo/${route}`,
       element: <DemoPage />,
       errorElement: <ErrorPage />,
-    },
-  ]);
+    });
+  }
+
+  const routes = useRoutes(routesConfig);
 
   return routes;
 };


Test patch: