diff --git a/package-lock.json b/package-lock.json
index d0c16e8..c373f08 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -37,6 +37,7 @@
"react-toastify": "^10.0.6",
"redux": "^5.0.1",
"redux-persist": "^6.0.0",
+ "reselect": "^5.1.1",
"web-vitals": "^2.1.3",
"yup": "^1.4.0"
}
diff --git a/package.json b/package.json
index af58f9a..8bf39e6 100644
--- a/package.json
+++ b/package.json
@@ -33,6 +33,7 @@
"react-toastify": "^10.0.6",
"redux": "^5.0.1",
"redux-persist": "^6.0.0",
+ "reselect": "^5.1.1",
"web-vitals": "^2.1.3",
"yup": "^1.4.0"
},
diff --git a/src/Pages/Home/Home.jsx b/src/Pages/Home/Home.jsx
index 6363932..15eb9a5 100644
--- a/src/Pages/Home/Home.jsx
+++ b/src/Pages/Home/Home.jsx
@@ -22,6 +22,7 @@ const Home = () => {
const data = useSelector(selectAllTransactions);
useEffect(() => {
+ console.log('Data:', data);
dispatch(fetchTransactions());
}, [dispatch]);
diff --git a/src/components/StatisticsDashboard/StatisticsDashboard.jsx b/src/components/StatisticsDashboard/StatisticsDashboard.jsx
index 74f0a09..d5d0a1f 100644
--- a/src/components/StatisticsDashboard/StatisticsDashboard.jsx
+++ b/src/components/StatisticsDashboard/StatisticsDashboard.jsx
@@ -1,9 +1,12 @@
-import React, { useState } from 'react';
+import React, { useEffect } from 'react';
+import { useDispatch } from 'react-redux';
import CustomDropdown from '../CustomDropdown/CustomDropdown';
+import { getTransactionsSummaryByPeriod } from '../../redux/Statistics/operations';
const StatisticsDashboard = () => {
- const [selectedMonth, setSelectedMonth] = useState(11);
- const [selectedYear, setSelectedYear] = useState(2024);
+ const dispatch = useDispatch();
+ const [selectedMonth, setSelectedMonth] = React.useState(11);
+ const [selectedYear, setSelectedYear] = React.useState(2024);
const months = [
{ value: 1, label: 'January' },
@@ -28,6 +31,15 @@ const StatisticsDashboard = () => {
{ value: 2024, label: '2024' },
];
+ useEffect(() => {
+ dispatch(
+ getTransactionsSummaryByPeriod({
+ month: selectedMonth,
+ year: selectedYear,
+ })
+ );
+ }, [dispatch, selectedMonth, selectedYear]);
+
return (
{
selectedValue={selectedYear}
onSelect={setSelectedYear}
/>
+ {/* Poți folosi transactionsSummary aici sau în StatisticsTable */}
);
};
diff --git a/src/components/StatisticsTable/StatisticsTable.jsx b/src/components/StatisticsTable/StatisticsTable.jsx
index f1c919d..010cdc0 100644
--- a/src/components/StatisticsTable/StatisticsTable.jsx
+++ b/src/components/StatisticsTable/StatisticsTable.jsx
@@ -1,31 +1,87 @@
import React from 'react';
+import { useSelector } from 'react-redux';
+import { useEffect } from 'react';
+// import { selectTransactionsSummary } from '../../redux/selectors/transactionsSelector';
+import { selectTransactionsByCategory } from '../../redux/selectors/transactionsSelector';
+// import { getTransactionsSummaryByPeriod } from '../../redux/Statistics/operations';
import styles from './StatisticsTable.module.css';
const StatisticsTable = () => {
+ // const totalTransactionsAmount = useSelector(selectTransactionsSummary);
+ const transactionsByCategory = useSelector(selectTransactionsByCategory);
+
+ useEffect(() => {
+ console.log('Sume pe categorii:', transactionsByCategory);
+ }, [transactionsByCategory]);
+
const expenses = [
- { label: 'Main expenses', amount: 8700.00, color: '#fed057'},
- { label: 'Products', amount: 3800.74, color: '#ffd8d0'},
- { label: 'Car', amount: 1500.00, color: '#FFADAD' },
- { label: 'Self care', amount: 800.00, color: '#D0A8FF' },
- { label: 'Child care', amount: 2208.50, color: '#8F9BFF' },
- { label: 'Household products', amount: 300.00, color: '#6E7FFF' },
- { label: 'Education', amount: 3400.00, color: '#65E2FF' },
- { label: 'Leisure', amount: 1230.00, color: '#47D5A4' },
- { label: 'Other expenses', amount: 610.00, color: '#28B491' },
+ {
+ label: 'Main expenses',
+ amount: transactionsByCategory['Main expenses'] || 0,
+ color: '#fed057',
+ },
+ {
+ label: 'Products',
+ amount: transactionsByCategory['Products'] || 0,
+ color: '#ffd8d0',
+ },
+ {
+ label: 'Car',
+ amount: transactionsByCategory['Car'] || 0,
+ color: '#FFADAD',
+ },
+ {
+ label: 'Self care',
+ amount: transactionsByCategory['Self care'] || 0,
+ color: '#D0A8FF',
+ },
+ {
+ label: 'Child care',
+ amount: transactionsByCategory['Child care'] || 0,
+ color: '#8F9BFF',
+ },
+ {
+ label: 'Household products',
+ amount: transactionsByCategory['Household products'] || 0,
+ color: '#6E7FFF',
+ },
+ {
+ label: 'Education',
+ amount: transactionsByCategory['Education'] || 0,
+ color: '#65E2FF',
+ },
+ {
+ label: 'Leisure',
+ amount: transactionsByCategory['Leisure'] || 0,
+ color: '#47D5A4',
+ },
+ {
+ label: 'Other expenses',
+ amount: transactionsByCategory['Other expenses'] || 0,
+ color: '#28B491',
+ },
];
- // ce este mai sus este doar pentru proba, trebuie modificat cu ce se introduce in modal
-
- const totalExpenses = expenses.reduce((sum, expense) => sum + expense.amount, 0).toFixed(2);
- const income = 27350.00;
+ const totalExpenses = expenses
+ .reduce((sum, expense) => sum + expense.amount, 0)
+ .toFixed(2);
+ const income = 27350.0;
return (
{expenses.map((expense, index) => (
-
+
{expense.label}
- {expense.amount.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+
+ {expense.amount.toLocaleString('en-US', {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}
+
))}
@@ -35,7 +91,12 @@ const StatisticsTable = () => {
Income:
- {income.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
+
+ {income.toLocaleString('en-US', {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}
+
diff --git a/src/components/TransactionsDesktop/TransactionsDesktop.jsx b/src/components/TransactionsDesktop/TransactionsDesktop.jsx
index ede941e..326c7f8 100644
--- a/src/components/TransactionsDesktop/TransactionsDesktop.jsx
+++ b/src/components/TransactionsDesktop/TransactionsDesktop.jsx
@@ -3,26 +3,20 @@ import TransactionsDesktopRow from '../../components/TransactionsDesktopRow/Tran
import styles from './TransactionsDesktop.module.css';
const TransactionsDesktop = ({ data, openDeleteModal, openEditModal }) => {
- // Definim funcția de comparație pentru sortare:
const compareTransactions = (a, b) => {
const dateComparison =
new Date(a.transactionDate) - new Date(b.transactionDate);
- // Verificăm dacă tranzacțiile au aceeași dată:
if (dateComparison === 0) {
- // Dacă tranzacția A este de tip "Income", o afișăm înaintea celei de tip "Expense":
if (a.type === 'INCOME' && b.type !== 'INCOME') {
return -1;
}
- // Dacă tranzacția B este de tip "Income", o afișăm înaintea celei de tip "Expense":
if (a.type !== 'INCOME' && b.type === 'INCOME') {
return 1;
}
}
- // Returnăm rezultatul comparării datelor:
return dateComparison;
};
- // Sortăm datele utilizând funcția de comparație definită mai sus:
const sortedData = [...data].sort(compareTransactions);
return (
diff --git a/src/index.js b/src/index.js
index 3273f03..e3ded25 100644
--- a/src/index.js
+++ b/src/index.js
@@ -8,10 +8,12 @@ import './index.css';
const container = document.getElementById('root');
const root = createRoot(container);
+const basename =
+ process.env.NODE_ENV === 'production' ? '//team1_MoneyGuard' : '/';
root.render(
-
+
diff --git a/src/redux/operations/authOperations.js b/src/redux/operations/authOperations.js
index 0c8985d..28dda8f 100644
--- a/src/redux/operations/authOperations.js
+++ b/src/redux/operations/authOperations.js
@@ -55,7 +55,7 @@ export const getUserInfo = createAsyncThunk(
async (_, thunkAPI) => {
try {
const response = await axios.get(`${BASE_URL}/users/current`);
-
+ console.log('User Info:', response.data);
return response.data;
} catch (error) {
console.log(error);
diff --git a/src/redux/operations/transactionsOperations.js b/src/redux/operations/transactionsOperations.js
index 6630f28..e3e75c2 100644
--- a/src/redux/operations/transactionsOperations.js
+++ b/src/redux/operations/transactionsOperations.js
@@ -84,7 +84,26 @@ export const deleteTransaction = createAsyncThunk(
export const fetchCategories = createAsyncThunk(
'categories/fetch',
async () => {
- const response = await axios.get('/api/categories'); // pt api, inca nu e implementat!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ const response = await axios.get('/api/categories');
return response.data;
}
);
+
+// Fetch Transaction Categories
+export const fetchTransactionCategories = createAsyncThunk(
+ 'transactions/fetchCategories',
+ async (_, { rejectWithValue }) => {
+ const token = localStorage.getItem('token');
+ try {
+ const response = await axios.get(`${BASE_URL}/transaction-categories`, {
+ headers: {
+ Authorization: `Bearer ${token}`,
+ },
+ });
+ return response.data;
+ } catch (error) {
+ toast.error('Failed to load transaction categories');
+ return rejectWithValue(error.response?.data || error.message);
+ }
+ }
+);
diff --git a/src/redux/selectors/transactionsSelector.js b/src/redux/selectors/transactionsSelector.js
index 0558b60..5282f31 100644
--- a/src/redux/selectors/transactionsSelector.js
+++ b/src/redux/selectors/transactionsSelector.js
@@ -1,3 +1,5 @@
+import { createSelector } from 'reselect';
+
const selectAllTransactions = state => state.transactions.items;
const selectTotalBalance = state => state.transactions.totalBalance;
const selectError = state => state.transactions.error;
@@ -7,10 +9,36 @@ const selectTrasactionIdForDelete = state =>
const selectTransactionForUpdate = state =>
state.transactions.transactionForUpdate;
+const selectTransactionsSummary = state => {
+ const transactions = state.transactions.items;
+ const totalAmount = transactions.reduce(
+ (sum, transaction) => sum + transaction.amount,
+ 0
+ );
+
+ return totalAmount;
+};
+
+const selectTransactionsByCategory = createSelector(
+ state => state.transactions.items,
+ transactions => {
+ console.log('Tranzacții primite în selector:', transactions);
+ return transactions.reduce((acc, transaction) => {
+ const { category, amount } = transaction;
+ if (category) {
+ acc[category] = (acc[category] || 0) + amount;
+ }
+ return acc;
+ }, {});
+ }
+);
+
export {
selectAllTransactions,
selectTotalBalance,
selectError,
selectTransactionForUpdate,
selectTrasactionIdForDelete,
+ selectTransactionsSummary,
+ selectTransactionsByCategory,
};