diff --git a/src/Pages/CurrencyTab/CurrencyTab.jsx b/src/Pages/CurrencyTab/CurrencyTab.jsx new file mode 100644 index 0000000..95a1081 --- /dev/null +++ b/src/Pages/CurrencyTab/CurrencyTab.jsx @@ -0,0 +1,12 @@ +import Currency from '../../components/Currency/Currency'; +import React from 'react'; +import { useMediaQuery } from 'react-responsive'; + +const CurrencyTab = () => { + const isDesktopOrLaptop = useMediaQuery({ + query: '(min-width: 768px)', + }); + return <>{!isDesktopOrLaptop && }; +}; + +export default CurrencyTab; diff --git a/src/Pages/Home/Home.jsx b/src/Pages/Home/Home.jsx index 1c0e213..99b5004 100644 --- a/src/Pages/Home/Home.jsx +++ b/src/Pages/Home/Home.jsx @@ -1,20 +1,15 @@ -import React, { useEffect } from 'react'; -import { useDispatch } from 'react-redux'; -import { - fetchTransactions, - fetchCategories, -} from '../../redux/operations/transactionsOperations'; +import ButtonAddTransactions from '../../components/ButtonAddTransactions/ButtonAddTransactions'; +import TransactionsList from '../../components/TransactionsList/TransactionsList'; +import React from 'react'; +import styles from './Home.module.css'; const Home = () => { - const dispatch = useDispatch(); - - useEffect(() => { - dispatch(fetchTransactions()); - - dispatch(fetchCategories()); - }, [dispatch]); - - return
{/*aici restul paginii*/}
; + return ( +
+ + +
+ ); }; export default Home; diff --git a/src/Pages/Home/Home.module.css b/src/Pages/Home/Home.module.css index e69de29..be758ba 100644 --- a/src/Pages/Home/Home.module.css +++ b/src/Pages/Home/Home.module.css @@ -0,0 +1,11 @@ +.homeTabContainer { + width: 100%; + margin: 0 auto; + padding: 20px; +} + +@media only screen and (min-width: 768px) { + .homeTabContainer { + padding: 0; + } +} diff --git a/src/components/App/App.jsx b/src/components/App/App.jsx index fe1bb32..b3a767f 100644 --- a/src/components/App/App.jsx +++ b/src/components/App/App.jsx @@ -1,23 +1,20 @@ -// src/App.jsx import React, { useEffect } from 'react'; import { Routes, Route, useNavigate } from 'react-router-dom'; import { useSelector } from 'react-redux'; import LoginPage from 'Pages/LoginPage/LoginPage'; -// import RegisterFormModal from 'components/RegistrationForm/RegistrationForm'; import DashboardPage from 'Pages/DashboardPage/DashboardPage'; import Home from 'Pages/Home/Home'; import Statistics from 'Pages/Statistics/Statistics'; import RegisterPage from 'Pages/RegisterPage/RegisterPage'; +import CurrencyTab from 'Pages/CurrencyTab/CurrencyTab'; const App = () => { - const user = useSelector(state => state.auth.user); // Obține starea autentificării din Redux + const user = useSelector(state => state.auth.user); const navigate = useNavigate(); useEffect(() => { if (user) { navigate('/dashboard'); - } else { - navigate('/login'); } }, [user, navigate]); @@ -29,11 +26,15 @@ const App = () => { path="/dashboard" element={user ? : } /> - } /> + : } /> : } /> + : } + /> } /> ); diff --git a/src/components/ButtonAddTransactions/ButtonAddTransactions.jsx b/src/components/ButtonAddTransactions/ButtonAddTransactions.jsx new file mode 100644 index 0000000..aa3c981 --- /dev/null +++ b/src/components/ButtonAddTransactions/ButtonAddTransactions.jsx @@ -0,0 +1,2 @@ +const ButtonAddTransactions = () => {}; +export default ButtonAddTransactions; diff --git a/src/components/DashboardComponent/DashboardComponent.module.css b/src/components/ButtonAddTransactions/ButtonAddTransactions.modules.css similarity index 100% rename from src/components/DashboardComponent/DashboardComponent.module.css rename to src/components/ButtonAddTransactions/ButtonAddTransactions.modules.css diff --git a/src/components/Chart/Chart.jsx b/src/components/Chart/Chart.jsx new file mode 100644 index 0000000..fbf4813 --- /dev/null +++ b/src/components/Chart/Chart.jsx @@ -0,0 +1,2 @@ +const Chart = () => {}; +export default Chart; diff --git a/src/components/Chart/Chart.modules.css b/src/components/Chart/Chart.modules.css new file mode 100644 index 0000000..e69de29 diff --git a/src/components/DashboardComponent/DashboadComponent.jsx b/src/components/DashboardComponent/DashboadComponent.jsx index e69de29..1332363 100644 --- a/src/components/DashboardComponent/DashboadComponent.jsx +++ b/src/components/DashboardComponent/DashboadComponent.jsx @@ -0,0 +1,71 @@ +import React, { useEffect, useState } from 'react'; +import Select from 'react-select'; +import styles from './DashboardComponent.module.css'; +import { useDispatch } from 'react-redux'; +import { fetchTransactionsSummary } from '../../redux/transactions/operations'; + +const StatisticsDashboard = () => { + const dispatch = useDispatch(); + const [selectedMonth, setSelectedMonth] = useState({ + value: 3, + label: 'March', + }); + const [selectedYear, setSelectedYear] = useState({ + value: 2024, + label: '2024', + }); + + const onMonthChange = month => setSelectedMonth(month); + const onYearClick = year => setSelectedYear(year); + + const optionsYears = [ + { value: 2024, label: '2024' }, + { value: 2023, label: '2023' }, + { value: 2022, label: '2022' }, + { value: 2021, label: '2021' }, + { value: 2019, label: '2019' }, + { value: 2018, label: '2018' }, + { value: 2017, label: '2017' }, + ]; + + const optionsMonth = [ + { value: 1, label: 'January' }, + { value: 2, label: 'February' }, + { value: 3, label: 'March' }, + { value: 4, label: 'April' }, + { value: 5, label: 'May' }, + { value: 6, label: 'June' }, + { value: 7, label: 'July' }, + { value: 8, label: 'August' }, + { value: 9, label: 'September' }, + { value: 10, label: 'October' }, + { value: 11, label: 'November' }, + { value: 12, label: 'December' }, + ]; + + useEffect(() => { + const data = { month: selectedMonth.value, year: selectedYear.value }; + dispatch(fetchTransactionsSummary(data)); + }, [dispatch, selectedMonth, selectedYear]); + + return ( +
+ +
+ ); +}; + +export default StatisticsDashboard; diff --git a/src/components/DashboardComponent/DashboardComponent.modules.css b/src/components/DashboardComponent/DashboardComponent.modules.css new file mode 100644 index 0000000..b4aeafb --- /dev/null +++ b/src/components/DashboardComponent/DashboardComponent.modules.css @@ -0,0 +1,30 @@ +/* DashboardComponent.module.css */ +.mainDiv { + display: flex; + flex-direction: column; + gap: 20px; + padding: 16px 0; + min-width: 280px; + max-width: 280px; + margin: 0 auto; +} + +@media only screen and (min-width: 768px) { + .mainDiv { + flex-direction: row; + gap: 16px; + padding: 20px 0 0 0; + min-width: 192px; + max-width: 192px; + margin: 0; + } +} + +@media only screen and (min-width: 1280px) { + .mainDiv { + margin-top: 60px; + min-width: 213px; + max-width: 213px; + gap: 32px; + } +} diff --git a/src/components/Navigation/Navigation.jsx b/src/components/Navigation/Navigation.jsx index ec7f24b..fa3d713 100644 --- a/src/components/Navigation/Navigation.jsx +++ b/src/components/Navigation/Navigation.jsx @@ -1,3 +1,54 @@ -const Navigation = () => {}; +import React from 'react'; +import { NavLink } from 'react-router-dom'; +import sprite from './sprite.svg'; +import { useMediaQuery } from 'react-responsive'; +import styles from './Navigation.module.css'; + +const Navigation = () => { + const isDesktopOrLaptop = useMediaQuery({ query: '(min-width: 768px)' }); + const isMobile = useMediaQuery({ query: '(max-width: 767px)' }); + + return ( + + ); +}; export default Navigation; diff --git a/src/components/Navigation/Navigation.module.css b/src/components/Navigation/Navigation.module.css index e69de29..bd31039 100644 --- a/src/components/Navigation/Navigation.module.css +++ b/src/components/Navigation/Navigation.module.css @@ -0,0 +1,73 @@ +.navStyledContainer { + padding-top: 40px; + padding-bottom: 28px; +} + +.navList { + display: flex; + flex-direction: row; + gap: 32px; + align-items: center; + justify-content: center; +} + +.styledNavLink { + display: flex; + justify-content: center; + align-items: center; + color: grey; + transition: all 0.3s; +} + +.styledNavLink:hover { + filter: drop-shadow(0px 3px 10px rgba(255, 255, 255, 0.6)); +} + +.styledNavLink div { + border-radius: 6px; + width: 37px; + height: 37px; + overflow: hidden; +} + +.styledNavLink.active { + color: blue; + border-radius: 5px; + transition: all 0.3s; +} + +.styledNavLink.active div { + background: white; + border-radius: 6px; + width: 37px; + height: 37px; + filter: drop-shadow(0px 3px 10px rgba(74, 86, 226, 0.5)); +} + +.styledNavLink svg { + fill: currentColor; +} + +.styledNavText { + color: white; + font-size: 18px; + margin-left: 20px; +} + +@media only screen and (min-width: 768px) { + .navList { + flex-direction: column; + align-items: baseline; + gap: 12px; + } + + .styledNavLink.active { + font-weight: 600; + } + + .styledNavLink div, + .styledNavLink svg { + width: 24px; + height: 24px; + } +} diff --git a/src/components/Navigation/sprite.svg b/src/components/Navigation/sprite.svg new file mode 100644 index 0000000..3b60580 --- /dev/null +++ b/src/components/Navigation/sprite.svg @@ -0,0 +1,82 @@ + \ No newline at end of file diff --git a/src/components/StatisticsDashboard/StatisticsDashboard.jsx b/src/components/StatisticsDashboard/StatisticsDashboard.jsx new file mode 100644 index 0000000..112b5d7 --- /dev/null +++ b/src/components/StatisticsDashboard/StatisticsDashboard.jsx @@ -0,0 +1,2 @@ +const StatisticsDashboard = () => {}; +export default StatisticsDashboard; diff --git a/src/components/StatisticsTable/StatisticsTable.jsx b/src/components/StatisticsTable/StatisticsTable.jsx new file mode 100644 index 0000000..a897fd7 --- /dev/null +++ b/src/components/StatisticsTable/StatisticsTable.jsx @@ -0,0 +1,2 @@ +const StatisticsTable = () => {}; +export default StatisticsTable; diff --git a/src/components/TransactionsList/TransactionsList.jsx b/src/components/TransactionsList/TransactionsList.jsx index 5454bcf..ba134d6 100644 --- a/src/components/TransactionsList/TransactionsList.jsx +++ b/src/components/TransactionsList/TransactionsList.jsx @@ -1,5 +1,4 @@ import React, { useEffect } from 'react'; -import PropTypes from 'prop-types'; import { useDispatch, useSelector } from 'react-redux'; import { fetchTransactions, @@ -15,7 +14,7 @@ import TransactionsItem from '../TransactionsItem/TransactionsItem'; const TransactionsList = () => { const dispatch = useDispatch(); - const transactions = useSelector(selectTransactions); + const transactions = useSelector(selectTransactions) || []; const loading = useSelector(selectLoading); const error = useSelector(selectError); @@ -35,42 +34,23 @@ const TransactionsList = () => { : JSON.stringify(error); return

Error: {errorMessage}

; } - if (transactions.length === 0) return

No transactions found.

; + if (Array.isArray(transactions) && transactions.length === 0) { + return

No transactions found.

; + } return (
- {loading ? ( -

Loading...

- ) : transactions.length ? ( - transactions.map(transaction => ( - - handleDelete(transaction.id, transaction.type, transaction.amount) - } - /> - )) - ) : ( -
No transactions available
- )} + {transactions.map(transaction => ( + + handleDelete(transaction.id, transaction.type, transaction.amount) + } + /> + ))}
); }; -TransactionsList.propTypes = { - transactions: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - date: PropTypes.string.isRequired, - type: PropTypes.oneOf(['income', 'expense']).isRequired, - category: PropTypes.string, - comment: PropTypes.string, - amount: PropTypes.number.isRequired, - }) - ), - loading: PropTypes.bool.isRequired, - error: PropTypes.string, -}; - export default TransactionsList; diff --git a/src/index.css b/src/index.css index 1b4aa5a..68abf88 100644 --- a/src/index.css +++ b/src/index.css @@ -10,11 +10,18 @@ p { margin: 0; } +a { + text-decoration: none; + color: inherit; +} + ul, -ol { +ol, +li { margin: 0; padding: 0; list-style-type: none; + text-decoration: none; } img { @@ -25,9 +32,9 @@ img { body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; + font-family: 'Poppins', -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; } diff --git a/src/index.js b/src/index.js index 56fb9b7..3273f03 100644 --- a/src/index.js +++ b/src/index.js @@ -4,13 +4,14 @@ import { BrowserRouter } from 'react-router-dom'; import { Provider } from 'react-redux'; import App from '../src/components/App/App'; import store from './redux/Store'; +import './index.css'; const container = document.getElementById('root'); const root = createRoot(container); root.render( - + diff --git a/src/styles/fonts.css b/src/styles/fonts.css new file mode 100644 index 0000000..04763a4 --- /dev/null +++ b/src/styles/fonts.css @@ -0,0 +1,23 @@ +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 400; + src: url('./fonts//Poppins-Regular.woff2') format('woff2'), + url('./fonts//Poppins-Regular.woff') format('woff'); +} + +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 500; + src: url('./fonts/Poppins-Medium.woff2') format('woff2'), + url('./fonts/Poppins-Medium.woff') format('woff'); +} + +@font-face { + font-family: 'Poppins'; + font-style: normal; + font-weight: 600; + src: url('./fonts/Poppins-SemiBold.woff2') format('woff2'), + url('./fonts/Poppins-SemiBold.woff') format('woff'); +} diff --git a/src/styles/fonts/Poppins-Medium.woff b/src/styles/fonts/Poppins-Medium.woff new file mode 100644 index 0000000..3fbd4a2 Binary files /dev/null and b/src/styles/fonts/Poppins-Medium.woff differ diff --git a/src/styles/fonts/Poppins-Medium.woff2 b/src/styles/fonts/Poppins-Medium.woff2 new file mode 100644 index 0000000..ceecc77 Binary files /dev/null and b/src/styles/fonts/Poppins-Medium.woff2 differ diff --git a/src/styles/fonts/Poppins-Regular.woff b/src/styles/fonts/Poppins-Regular.woff new file mode 100644 index 0000000..01d94b4 Binary files /dev/null and b/src/styles/fonts/Poppins-Regular.woff differ diff --git a/src/styles/fonts/Poppins-Regular.woff2 b/src/styles/fonts/Poppins-Regular.woff2 new file mode 100644 index 0000000..4aae28c Binary files /dev/null and b/src/styles/fonts/Poppins-Regular.woff2 differ diff --git a/src/styles/fonts/Poppins-SemiBold.woff b/src/styles/fonts/Poppins-SemiBold.woff new file mode 100644 index 0000000..208e285 Binary files /dev/null and b/src/styles/fonts/Poppins-SemiBold.woff differ diff --git a/src/styles/fonts/Poppins-SemiBold.woff2 b/src/styles/fonts/Poppins-SemiBold.woff2 new file mode 100644 index 0000000..990f6f7 Binary files /dev/null and b/src/styles/fonts/Poppins-SemiBold.woff2 differ