diff --git a/.gitignore b/.gitignore
index 4d29575..61ef65f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,3 +21,5 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
+bun.lock
+bun.lockb
diff --git a/package.json b/package.json
index 89282b5..49490c5 100644
--- a/package.json
+++ b/package.json
@@ -7,8 +7,14 @@
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^13.5.0",
+ "bootstrap": "^5.3.7",
+ "chart.js": "^4.5.0",
+ "faker": "^6.6.6",
"react": "^19.1.0",
+ "react-bootstrap": "^2.10.10",
+ "react-chartjs-2": "^5.3.0",
"react-dom": "^19.1.0",
+ "react-router-dom": "^7.7.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
diff --git a/src/App.css b/src/App.css
deleted file mode 100644
index 74b5e05..0000000
--- a/src/App.css
+++ /dev/null
@@ -1,38 +0,0 @@
-.App {
- text-align: center;
-}
-
-.App-logo {
- height: 40vmin;
- pointer-events: none;
-}
-
-@media (prefers-reduced-motion: no-preference) {
- .App-logo {
- animation: App-logo-spin infinite 20s linear;
- }
-}
-
-.App-header {
- background-color: #282c34;
- min-height: 100vh;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- font-size: calc(10px + 2vmin);
- color: white;
-}
-
-.App-link {
- color: #61dafb;
-}
-
-@keyframes App-logo-spin {
- from {
- transform: rotate(0deg);
- }
- to {
- transform: rotate(360deg);
- }
-}
diff --git a/src/App.js b/src/App.js
deleted file mode 100644
index 3784575..0000000
--- a/src/App.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import logo from './logo.svg';
-import './App.css';
-
-function App() {
- return (
-
- );
-}
-
-export default App;
diff --git a/src/App.jsx b/src/App.jsx
new file mode 100644
index 0000000..d1b9bc5
--- /dev/null
+++ b/src/App.jsx
@@ -0,0 +1,38 @@
+import "./css/App.css";
+import NavigationBar from "./components/NavigationBar/NavigationBar";
+import { useTheme } from "./contexts/ThemeContext";
+import { useEffect } from "react";
+import Transactions from "./pages/Transactions";
+import Home from "./pages/Home";
+import {
+ BrowserRouter as Router,
+ Routes,
+ Route,
+ Navigate,
+} from "react-router-dom";
+// import { Container } from "react-bootstrap";
+import NotFound from "./pages/NotFound";
+
+function App() {
+ const { theme } = useTheme();
+
+ useEffect(() => {
+ document.body.setAttribute("data-bs-theme", theme);
+ }, [theme]);
+
+ return (
+
+
+ <>
+
+ } />
+ } />
+ } />
+ } />
+
+ >
+
+ );
+}
+
+export default App;
diff --git a/src/components/AppointmentDashboard/AppointmentDashboard.jsx b/src/components/AppointmentDashboard/AppointmentDashboard.jsx
new file mode 100644
index 0000000..e68052a
--- /dev/null
+++ b/src/components/AppointmentDashboard/AppointmentDashboard.jsx
@@ -0,0 +1,167 @@
+import { Card, Accordion, ProgressBar } from "react-bootstrap";
+
+const AppointmentDashboard = ({ ...props }) => {
+ return (
+ <>
+
+
+
+ Appointment
+
+
+
+
+
+
+
+
+ Cash loan
+
+
+ 21531,00 ₽
+
+
+
+
+
+
+
+
+
+
+
+ Cash loan
+
+
+ 21531,00 ₽
+
+
+
+
+
+
+
+
+
+
+
+ Cash loan
+
+
+ 21531,00 ₽
+
+
+
+
+
+
+
+
+
+ {/*
+
+
+
+
+ -63.00 ₽
+
+
+ Transport
+
+
+ Note
+
+
+
+
+
*/}
+
+
+ >
+ );
+};
+export default AppointmentDashboard;
diff --git a/src/components/BalanceBlock/BalanceBlock.jsx b/src/components/BalanceBlock/BalanceBlock.jsx
new file mode 100644
index 0000000..d1b4907
--- /dev/null
+++ b/src/components/BalanceBlock/BalanceBlock.jsx
@@ -0,0 +1,26 @@
+import React from "react";
+import { Card } from "react-bootstrap";
+import AddOperationModal from "../../modals/AddOperationModal/AddOperationModal";
+
+const BalanceBlock = ({ balance }) => {
+ return (
+
+
+
+
+ Balance
+
+
+ 40 407,17 ₽
+
+
+
+
+
+ );
+};
+
+export default BalanceBlock;
diff --git a/src/components/FinancialDashboard/FinancialDashboard.jsx b/src/components/FinancialDashboard/FinancialDashboard.jsx
new file mode 100644
index 0000000..e0a4f86
--- /dev/null
+++ b/src/components/FinancialDashboard/FinancialDashboard.jsx
@@ -0,0 +1,121 @@
+import React from "react";
+import { Card, Col } from "react-bootstrap";
+import { Bar } from "react-chartjs-2";
+import {
+ Chart as ChartJS,
+ CategoryScale,
+ LinearScale,
+ BarElement,
+ Tooltip,
+} from "chart.js";
+// import { useTheme } from "../../contexts/ThemeContext";
+import styles from "./FinancialDashboard.module.css";
+
+ChartJS.register(CategoryScale, LinearScale, BarElement, Tooltip);
+
+const FinancialDashboard = ({
+ chartData,
+ chartOptions,
+ maxValue,
+ LeftCardData,
+ RightCardData,
+}) => {
+ // const { theme } = useTheme();
+ // const [incomedata, setIncomeData] = useState(income);
+ // const [expensesdata, setExpensesData] = useState(expenses);
+
+ return (
+
+ {/* Карточка с диаграммой */}
+
+
+
+
+
+
+
+
+
+
+ {LeftCardData.value.toLocaleString("ru-RU", {
+ minimumFractionDigits: 2,
+ })}{" "}
+ ₽
+
+
+
+
+ {LeftCardData.label}
+
+
+
+
+
+
+
+
+
+
+
+ {RightCardData.value.toLocaleString("ru-RU", {
+ minimumFractionDigits: 2,
+ })}{" "}
+ ₽
+
+
+
+
+ {RightCardData.label}
+
+
+
+
+
+
+ {/* Контейнер для диаграммы */}
+
+
+
+
+
+
+ );
+};
+
+export default FinancialDashboard;
diff --git a/src/components/FinancialDashboard/FinancialDashboard.module.css b/src/components/FinancialDashboard/FinancialDashboard.module.css
new file mode 100644
index 0000000..fbb56d9
--- /dev/null
+++ b/src/components/FinancialDashboard/FinancialDashboard.module.css
@@ -0,0 +1,13 @@
+.chartContainer {
+ margin: 0;
+ height: 200px;
+ width: auto;
+ position: relative;
+ margin-bottom: 0;
+}
+
+@media (max-width: 768px) {
+ .chartContainer {
+ height: 100px;
+ }
+}
diff --git a/src/components/NavigationBar/NavigationBar.jsx b/src/components/NavigationBar/NavigationBar.jsx
new file mode 100644
index 0000000..1fa9177
--- /dev/null
+++ b/src/components/NavigationBar/NavigationBar.jsx
@@ -0,0 +1,18 @@
+import React from "react";
+import Navbar from "react-bootstrap/Navbar";
+import SettingsModal from "../../modals/SettingsModal/SettingsModal";
+
+const NavigationBar = () => {
+ return (
+
+ Wallet
+
+
+ );
+};
+
+export default NavigationBar;
diff --git a/src/components/NavigationBar/NavigationBar.module.css b/src/components/NavigationBar/NavigationBar.module.css
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/ThemeToggle.jsx b/src/components/ThemeToggle.jsx
new file mode 100644
index 0000000..449ad07
--- /dev/null
+++ b/src/components/ThemeToggle.jsx
@@ -0,0 +1,25 @@
+import React from "react";
+import { Form, Row, Col } from "react-bootstrap";
+import { useTheme } from "../contexts/ThemeContext";
+
+const ThemeToggle = () => {
+ const { theme, toggleTheme } = useTheme();
+
+ return (
+ <>
+
+ Dark Mode
+
+
+
+
+ >
+ );
+};
+
+export default ThemeToggle;
diff --git a/src/contexts/ThemeContext.js b/src/contexts/ThemeContext.js
new file mode 100644
index 0000000..71ba751
--- /dev/null
+++ b/src/contexts/ThemeContext.js
@@ -0,0 +1,35 @@
+import React, { createContext, useState, useEffect, useContext } from "react";
+
+const ThemeContext = createContext();
+
+export const ThemeProvider = ({ children }) => {
+ const [theme, setTheme] = useState(() => {
+ if (typeof window !== "undefined") {
+ const savedTheme = localStorage.getItem("theme");
+ const systemPreferDark = window.matchMedia(
+ "(prefers-color-scheme: dark)",
+ ).matches;
+ return savedTheme || (systemPreferDark ? "dark" : "light");
+ }
+ return "light";
+ });
+
+ useEffect(() => {
+ if (typeof window !== "undefined") {
+ document.body.setAttribute("data-bs-theme", theme);
+ localStorage.setItem("theme", theme);
+ }
+ }, [theme]);
+
+ const toggleTheme = () => {
+ setTheme((prev) => (prev === "light" ? "dark" : "light"));
+ };
+
+ return (
+
+ {children}
+
+ );
+};
+
+export const useTheme = () => useContext(ThemeContext);
diff --git a/src/css/App.css b/src/css/App.css
new file mode 100644
index 0000000..5c79a4d
--- /dev/null
+++ b/src/css/App.css
@@ -0,0 +1,36 @@
+/* src/App.css */
+body[data-bs-theme="dark"] {
+ background-color: #121212;
+ color: #f8f9fa;
+ .modal-content {
+ background-color: #121212 !important;
+ }
+ .nav-link.active {
+ background-color: #121212 !important;
+ }
+}
+
+body[data-bs-theme="light"] {
+ background-color: #f8f9fa;
+ color: #212529;
+}
+
+.progress {
+ border-radius: 20px;
+}
+
+.progress-bar {
+ border-radius: 20px;
+}
+
+.accordion-button {
+ padding: 10px !important;
+}
+
+.accordion-body {
+ padding: 0 10px !important;
+}
+
+hr {
+ margin: 0 !important;
+}
diff --git a/src/css/index.css b/src/css/index.css
new file mode 100644
index 0000000..4363b68
--- /dev/null
+++ b/src/css/index.css
@@ -0,0 +1,19 @@
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family:
+ -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
+ "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
+ sans-serif;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+code {
+ font-family:
+ source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
+}
diff --git a/src/index.css b/src/index.css
deleted file mode 100644
index ec2585e..0000000
--- a/src/index.css
+++ /dev/null
@@ -1,13 +0,0 @@
-body {
- margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
- sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-
-code {
- font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
- monospace;
-}
diff --git a/src/index.js b/src/index.js
index d563c0f..059eed5 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,14 +1,25 @@
-import React from 'react';
-import ReactDOM from 'react-dom/client';
-import './index.css';
-import App from './App';
-import reportWebVitals from './reportWebVitals';
+import React from "react";
+import ReactDOM from "react-dom/client";
+import "./css/index.css";
+import App from "./App";
+import reportWebVitals from "./reportWebVitals";
+import "bootstrap/dist/css/bootstrap.min.css";
+import { ThemeProvider } from "./contexts/ThemeContext";
-const root = ReactDOM.createRoot(document.getElementById('root'));
+const savedTheme =
+ localStorage.getItem("theme") ||
+ (window.matchMedia("(prefers-color-scheme: dark)").matches
+ ? "dark"
+ : "light");
+document.body.setAttribute("data-bs-theme", savedTheme);
+
+const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
-
-
+
+
+
+ ,
);
// If you want to start measuring performance in your app, pass a function
diff --git a/src/logo.svg b/src/logo.svg
deleted file mode 100644
index 9dfc1c0..0000000
--- a/src/logo.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/src/modals/AddOperationModal/AddOperationModal.jsx b/src/modals/AddOperationModal/AddOperationModal.jsx
new file mode 100644
index 0000000..fb6bdf7
--- /dev/null
+++ b/src/modals/AddOperationModal/AddOperationModal.jsx
@@ -0,0 +1,194 @@
+import { useState } from "react";
+import { useTheme } from "../../contexts/ThemeContext";
+import {
+ ListGroup,
+ Modal,
+ Button,
+ Card,
+ Form,
+ Row,
+ Col,
+} from "react-bootstrap";
+// import styles from "./HistoryModal.module.css";
+
+const AddOperationModal = ({ variant }) => {
+ const { theme } = useTheme();
+ const [show, setShow] = useState(false);
+ const handleClose = () => setShow(false);
+ const handleShow = () => setShow(true);
+ const [isIncome, setIsIncome] = useState(false);
+ const [isExpense, setIsExpense] = useState(true);
+ const [isNoteVisible, setIsNoteVisible] = useState(false);
+ const [amount, setAmount] = useState();
+ return (
+ <>
+ {variant ? (
+
+ ) : (
+
+ )}
+
+
+
+ Add operation
+
+
+
+
+
+ Amount
+
+
+ setAmount(e.target.value)}
+ />
+
+
+
+
+
+
+
+
+
+ Appointment
+
+
+
+
+
+
+ ADDITIONAL
+
+
+
+
+ Date
+
+
+
+
+
+
+
+ Tag
+
+
+
+
+
+
+
+
+ Note
+
+ setIsNoteVisible(!isNoteVisible)}
+ />
+
+
+
+
+
+
+
+
+
+ Repeat payment
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
+export default AddOperationModal;
diff --git a/src/modals/AnalyticsModal/AnalyticsModal.jsx b/src/modals/AnalyticsModal/AnalyticsModal.jsx
new file mode 100644
index 0000000..f93193d
--- /dev/null
+++ b/src/modals/AnalyticsModal/AnalyticsModal.jsx
@@ -0,0 +1,185 @@
+import { useState } from "react";
+import { useTheme } from "../../contexts/ThemeContext";
+import { Tabs, Tab, Modal, Button } from "react-bootstrap";
+import FinancialDashboard from "../../components/FinancialDashboard/FinancialDashboard";
+import AppointmentDashboard from "../../components/AppointmentDashboard/AppointmentDashboard";
+import styles from "./AnalyticsModal.module.css";
+
+const AnalyticsModal = () => {
+ const { theme } = useTheme();
+ const [show, setShow] = useState(false);
+ const handleClose = () => setShow(false);
+ const handleShow = () => setShow(true);
+
+ // const income = 40407.17;
+ const expenses = 39985.23;
+
+ const monthdata = [
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 141, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 2, 29, 30, 31,
+ ];
+
+ const monthMaxValue = Math.max(...monthdata);
+
+ const MonthChartData = {
+ labels: [
+ "1",
+ "2",
+ "3",
+ "4",
+ "5",
+ "6",
+ "7",
+ "8",
+ "9",
+ "10",
+ "11",
+ "12",
+ "13",
+ "14",
+ "15",
+ "16",
+ "17",
+ "18",
+ "19",
+ "20",
+ "21",
+ "22",
+ "23",
+ "24",
+ "25",
+ "26",
+ "27",
+ "28",
+ "29",
+ "30",
+ "31",
+ ],
+ datasets: [
+ {
+ data: monthdata,
+ backgroundColor: "#3576C3",
+ categoryPercentage: 0.5,
+ borderRadius: 3,
+ responsive: true,
+ },
+ ],
+ };
+
+ const MonthLeftCardData = {
+ label: "Total for the period",
+ value: expenses,
+ };
+
+ const MonthRightCardData = {
+ label: "Daily average",
+ value: expenses / monthdata.length,
+ };
+
+ const MonthChartOptions = {
+ responsive: true,
+ maintainAspectRatio: false,
+ scales: {
+ y: {
+ display: false,
+ beginAtZero: true,
+ max: monthMaxValue * 1.1,
+ },
+ x: {
+ grid: {
+ display: false,
+ drawBorder: false,
+ },
+ ticks: {
+ color: "#6b7280",
+ font: {
+ size: 12,
+ weight: "500",
+ },
+ },
+ },
+ },
+ plugins: {
+ legend: {
+ display: false,
+ },
+ tooltip: {
+ // enabled: true,
+ callbacks: {
+ // title: function (context) {
+ // // Customize the tooltip title
+ // return `${context[0].label}`;
+ // },
+ label: function (context) {
+ // Customize the tooltip label
+ let label = context.dataset.label || "";
+ if (label) {
+ label += ": ";
+ }
+ if (context.parsed.y !== null) {
+ label += `${context.parsed.y} ₽`;
+ }
+ return label;
+ },
+ },
+ },
+ },
+ };
+ return (
+ <>
+
+
+
+
+
+ Analytics
+
+
+
+
+
+
+
+
+
+ July 2025
+
+
+ Period: month
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
+export default AnalyticsModal;
diff --git a/src/modals/AnalyticsModal/AnalyticsModal.module.css b/src/modals/AnalyticsModal/AnalyticsModal.module.css
new file mode 100644
index 0000000..8626f1c
--- /dev/null
+++ b/src/modals/AnalyticsModal/AnalyticsModal.module.css
@@ -0,0 +1,11 @@
+.scrollableContent {
+ height: calc(100vh - 220px);
+ bottom: 0;
+ overflow-y: auto;
+}
+
+@media (max-width: 768px) {
+ .scrollableContent {
+ height: calc(100vh - 280px);
+ }
+}
diff --git a/src/modals/HistoryModal/HistoryModal.jsx b/src/modals/HistoryModal/HistoryModal.jsx
new file mode 100644
index 0000000..29ef4de
--- /dev/null
+++ b/src/modals/HistoryModal/HistoryModal.jsx
@@ -0,0 +1,652 @@
+import { useState } from "react";
+import { useTheme } from "../../contexts/ThemeContext";
+import { ListGroup, Tabs, Tab, Modal, Button } from "react-bootstrap";
+import styles from "./HistoryModal.module.css";
+import AddOperationModal from "../AddOperationModal/AddOperationModal";
+
+const HistoryModal = () => {
+ const { theme } = useTheme();
+ const [show, setShow] = useState(false);
+ const handleClose = () => setShow(false);
+ const handleShow = () => setShow(true);
+ return (
+ <>
+
+
+
+
+
+ History
+
+ {/* */}
+
+
+
+
+
+
+
+
+ 25 Jul 2025
+
+
+
+ Income: 0,00 ₽
+
+
+ Expense: 0,00 ₽
+
+
+
+
+
+
+
+
+
+
+ -63.00 ₽
+
+
+ Transport
+
+
+ Note
+
+
+
+
+
+
+
+
+
+
+ 18000 ₽
+
+
+ Transport
+
+
+ Note
+
+
+
+
+
+
+
+
+
+
+ -63.00 ₽
+
+
+ Transport
+
+
+ Note
+
+
+
+
+
+
+
+
+
+ 25 Jul 2025
+
+
+
+ Income: 0,00 ₽
+
+
+ Expense: 0,00 ₽
+
+
+
+
+
+
+
+
+
+
+ -63.00 ₽
+
+
+ Transport
+
+
+ Note
+
+
+
+
+
+
+
+
+
+
+ 18000 ₽
+
+
+ Transport
+
+
+ Note
+
+
+
+
+
+
+
+
+
+
+ -63.00 ₽
+
+
+ Transport
+
+
+ Note
+
+
+
+
+
+
+
+
+
+ 25 Jul 2025
+
+
+
+ Income: 0,00 ₽
+
+
+ Expense: 0,00 ₽
+
+
+
+
+
+
+
+
+
+
+ -63.00 ₽
+
+
+ Transport
+
+
+ Note
+
+
+
+
+
+
+
+
+
+
+ 18000 ₽
+
+
+ Transport
+
+
+ Note
+
+
+
+
+
+
+
+
+
+
+ -63.00 ₽
+
+
+ Transport
+
+
+ Note
+
+
+
+
+
+
+
+
+
+ 25 Jul 2025
+
+
+
+ Income: 0,00 ₽
+
+
+ Expense: 0,00 ₽
+
+
+
+
+
+
+
+
+
+
+ -63.00 ₽
+
+
+ Transport
+
+
+ Note
+
+
+
+
+
+
+
+
+
+
+ 18000 ₽
+
+
+ Transport
+
+
+ Note
+
+
+
+
+
+
+
+
+
+
+ -63.00 ₽
+
+
+ Transport
+
+
+ Note
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
+export default HistoryModal;
diff --git a/src/modals/HistoryModal/HistoryModal.module.css b/src/modals/HistoryModal/HistoryModal.module.css
new file mode 100644
index 0000000..4e8181a
--- /dev/null
+++ b/src/modals/HistoryModal/HistoryModal.module.css
@@ -0,0 +1,10 @@
+.scrollableContent {
+ height: calc(100vh - 220px);
+ overflow-y: auto;
+}
+
+@media (max-width: 768px) {
+ .scrollableContent {
+ height: calc(100vh - 240px);
+ }
+}
diff --git a/src/modals/SettingsModal/SettingsModal.jsx b/src/modals/SettingsModal/SettingsModal.jsx
new file mode 100644
index 0000000..d2ae274
--- /dev/null
+++ b/src/modals/SettingsModal/SettingsModal.jsx
@@ -0,0 +1,52 @@
+import { useState } from "react";
+import { useTheme } from "../../contexts/ThemeContext";
+import { ListGroup, Modal, Button } from "react-bootstrap";
+import ThemeToggle from "../../components/ThemeToggle";
+
+const SettingsModal = () => {
+ const { theme } = useTheme();
+ const [show, setShow] = useState(false);
+ const handleClose = () => setShow(false);
+ const handleShow = () => setShow(true);
+ return (
+ <>
+
+
+
+
+
+ Settings
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
+export default SettingsModal;
diff --git a/src/modals/SettingsModal/SettingsModal.module.css b/src/modals/SettingsModal/SettingsModal.module.css
new file mode 100644
index 0000000..4e8181a
--- /dev/null
+++ b/src/modals/SettingsModal/SettingsModal.module.css
@@ -0,0 +1,10 @@
+.scrollableContent {
+ height: calc(100vh - 220px);
+ overflow-y: auto;
+}
+
+@media (max-width: 768px) {
+ .scrollableContent {
+ height: calc(100vh - 240px);
+ }
+}
diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx
new file mode 100644
index 0000000..2104fe6
--- /dev/null
+++ b/src/pages/Home.jsx
@@ -0,0 +1,110 @@
+import FinancialDashboard from "../components/FinancialDashboard/FinancialDashboard";
+import { Row, Col } from "react-bootstrap";
+import HistoryModal from "../modals/HistoryModal/HistoryModal";
+import AnalyticsModal from "../modals/AnalyticsModal/AnalyticsModal";
+import BalanceBlock from "../components/BalanceBlock/BalanceBlock";
+
+const Home = () => {
+ const weeklyData = [63, 63, 63, 63, 63, 63, 63];
+ const weeklyData1 = [20, 80, 50, 100, 1800, 60, 90];
+ const weeklyMaxValue = Math.max(...weeklyData, ...weeklyData1);
+ const chartData = {
+ labels: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
+ datasets: [
+ {
+ data: weeklyData,
+ backgroundColor: "#3576C3",
+ categoryPercentage: 0.5,
+ borderRadius: 3,
+ responsive: true,
+ },
+ {
+ data: weeklyData1,
+ backgroundColor: "#38393F",
+ categoryPercentage: 0.5,
+ borderRadius: 3,
+ responsive: true,
+ },
+ ],
+ };
+ const chartOptions = {
+ responsive: true,
+ maintainAspectRatio: false,
+ scales: {
+ y: {
+ display: false,
+ beginAtZero: true,
+ max: weeklyMaxValue * 1.1,
+ },
+ x: {
+ grid: {
+ display: false,
+ drawBorder: false,
+ },
+ ticks: {
+ color: "#6b7280",
+ font: {
+ size: 12,
+ weight: "500",
+ },
+ },
+ },
+ },
+ plugins: {
+ legend: {
+ display: false,
+ },
+ tooltip: {
+ callbacks: {
+ label: function (context) {
+ let label = context.dataset.label || "";
+ if (label) {
+ label += ": ";
+ }
+ if (context.parsed.y !== null) {
+ label +=
+ `${weeklyData[context.dataIndex]}₽ ` +
+ `${weeklyData1[context.dataIndex]}₽`;
+ }
+ return label;
+ },
+ },
+ },
+ },
+ };
+ const income = 40407.17;
+ const expenses = 39985.23;
+
+ const LeftCardData = {
+ label: "Monthly Icome",
+ value: income,
+ };
+
+ const RightCardData = {
+ label: "Monthly Expenses",
+ value: expenses,
+ };
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
+
+export default Home;
diff --git a/src/pages/NotFound.jsx b/src/pages/NotFound.jsx
new file mode 100644
index 0000000..140525c
--- /dev/null
+++ b/src/pages/NotFound.jsx
@@ -0,0 +1,14 @@
+import { Alert, Button } from "react-bootstrap";
+import { Link } from "react-router-dom";
+
+const NotFound = () => (
+
+ 404 - Page Not Found
+ The page you're looking for doesn't exist.
+
+
+);
+
+export default NotFound;
diff --git a/src/pages/Transactions.jsx b/src/pages/Transactions.jsx
new file mode 100644
index 0000000..c1ad67d
--- /dev/null
+++ b/src/pages/Transactions.jsx
@@ -0,0 +1,9 @@
+const Transactions = () => {
+ return (
+ <>
+ Welcome to transactions
+ >
+ );
+};
+
+export default Transactions;