diff --git a/back-end/routes/addEventMemberRoute.js b/back-end/routes/addEventMemberRoute.js
index ec2b702..718c364 100644
--- a/back-end/routes/addEventMemberRoute.js
+++ b/back-end/routes/addEventMemberRoute.js
@@ -4,30 +4,7 @@ const { User } = require("../models/User.js");
const { Event } = require("../models/Event.js");
const { body, validationResult } = require("express-validator");
-// Hardcoded user data to simulate a database
-
-/*
-let friendData = [{
- "id":"507f1f77bcf86cd799439011",
- "name":"Gaby Coupar",
- "avatar":"https://robohash.org/temporererumomnis.png?size=50x50\u0026set=set1",
- "phone":"435-715-2899",
- "email":"gcoupar0@rakuten.co.jp"
- }, {
- "id": "507f1f77bcf86cd799439012",
- "name": "Andy Gaber",
- "avatar": "https://robohash.org/quaeetcorrupti.png?size=50x50&set=set1",
- "phone":"425-712-2309",
- "email":"gmember0@rakuten.co.jp"
- }]
-
-// Endpoint to get user data after search
-router.get('/friend', (req, res) => {
- res.json(friendData);
-});
-*/
-
-router.get("/friendsList/:userId", async (req, res) => {
+router.get('/friendsList/:userId', async (req, res) => {
try {
//fetch all data
const userId = req.params.userId;
@@ -47,66 +24,4 @@ router.get("/friendsList/:userId", async (req, res) => {
}
});
-/*
-router.get('/friends/:userId', async (req, res) => {
- try {
- const userId = req.params.userId;
- console.log('Fetching user with ID:', userId);
-
- const user = await User.findById(userId).populate('friends');
- console.log('User:', user);
-
- if (!user) {
- console.log('User not found');
- return res.status(404).json({ message: 'User not found' });
- }
-
- res.json(user.friends);
- } catch (error) {
- console.error('Error:', error);
- res.status(500).json({ message: 'Server error', error: error.message });
- }
-});
-
-
-router.post('/events/:eventId/participants', async (req, res) => {
- try {
- const { eventId } = req.params;
- const { memberId } = req.body;
-
- // Find the event and add the new member
- const event = await Event.findById(eventId);
- const user = await User.findById(userId)
-
- if (!event) {
- return res.status(404).json({ message: 'Event not found' });
- }
- if(!user){
- return res.status(404).json({ message: 'User not found'})
- }
-
- // Check if member is already in the participants list
- if (event.participants.includes(memberId)) {
- return res.status(400).json({ message: 'Member already in the event' });
- }
-
- // Validate if the memberId is in the user's friend list
- const isFriend = user.friends.some(friend => friend._id.toString() === memberId);
-
- if (!isFriend) {
- return res.status(400).json({ message: 'Member is not in the user\'s friend list' });
- }
-
- // Add the member to the participants list
- event.participants.push(memberId);
- await event.save();
-
- res.json({message: 'Member added successfully', event});
- } catch (error) {
- console.error(error);
- res.status(500).json({ message: 'Server error' });
- }
-});
-*/
-
module.exports = router;
diff --git a/back-end/test/expenseStatusRoute.test.js b/back-end/test/expenseStatusRoute.test.js
new file mode 100644
index 0000000..e69de29
diff --git a/front-end/src/components/Event.js b/front-end/src/components/Event.js
index b1dc6ad..9c7da6d 100644
--- a/front-end/src/components/Event.js
+++ b/front-end/src/components/Event.js
@@ -52,27 +52,35 @@ const Event = (props) => {
const isParticipant = expense.splitDetails.find(
(detail) => detail.user === userId
);
- //let settlement;
let userBalance = 0;
-
- if (isParticipant) {
- if (expense.paidBy === userId) {
+
+ if (expense.paidBy === userId) {
+ // Check if the currentUser is involved in the split
+ if (isParticipant) {
expense.splitDetails.forEach((split) => {
if (!split.settlement.status) {
userBalance += split.settlement.amount;
}
});
} else {
- //user is not the one who paid, find what the user owe to the person who paid
- const user = expense.splitDetails.find(
- (split) => split.user === userId
- );
- if (user) {
- userBalance = user.settlement.status ? 0 : -user.settlement.amount;
- }
+ let totalSettledAmount = 0;
+ expense.splitDetails.forEach((split) => {
+ if (split && split.settlement && split.settlement.status) {
+ totalSettledAmount += split.settlement.amount;
+ }
+ });
+ userBalance = (expense.totalAmount ? expense.totalAmount : 0) - totalSettledAmount;
+ }
+ } else if (isParticipant) {
+ // If currentUser is not the one who paid, but is involved in the split
+ const user = expense.splitDetails.find(
+ (split) => split.user === userId
+ );
+ if (user) {
+ userBalance = user.settlement.status ? 0 : -user.settlement.amount;
}
} else {
- // User is not a participant, create a settlement object with amount 0
+ // User is neither the payer nor a participant in the split
userBalance = 0;
}
@@ -180,12 +188,10 @@ const Event = (props) => {
{item.expense.name}
-
- {item.settlement.toFixed(2) === "0.00" ? (
-
Settled
- ) : (
- `$${item.settlement.toFixed(2)}`
- )}
+
+ {item.settlement.toFixed(2) === "0.00" ?
+ Settled :
+ `$${item.settlement.toFixed(2)}`}
))}
diff --git a/front-end/src/components/Events.jsx b/front-end/src/components/Events.jsx
index b85f844..7cb7d59 100644
--- a/front-end/src/components/Events.jsx
+++ b/front-end/src/components/Events.jsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react";
-import "../styles/Events.css";
+import '../styles/Events.css';
import Navbar from "./Navbar";
import { Link } from "react-router-dom";
import axios from "axios";
@@ -7,212 +7,181 @@ import AddEvent from "./AddEvent";
import { jwtDecode } from "jwt-decode";
function Events({ isDarkMode }) {
- const [eventData, setEventData] = useState([]);
- const [addEvent, setaddEvent] = useState(false);
- const [settlements, setSettlements] = useState([]);
- const [amountOwed, setAmountOwed] = useState(0);
- const [amountOwedBy, setAmountOwedBy] = useState(0);
- const [searchTerm, setSearchTerm] = useState("");
- //const[showFilter, setShowFilter] = useState(false);
- //const[selectedFilter, setSelectedFilter] = useState('all');
- //const[filteredEvents, setFilteredEvents] = useState([]);
-
- function reformatDate(dateStr) {
- const months = [
- "Jan",
- "Feb",
- "Mar",
- "Apr",
- "May",
- "Jun",
- "Jul",
- "Aug",
- "Sep",
- "Oct",
- "Nov",
- "Dec",
- ];
- const date = new Date(dateStr);
-
- const monthName = months[date.getMonth()];
- const day = date.getDate();
- const year = date.getFullYear();
-
- return `${monthName} ${day} ${year}`;
- }
-
- // Toggle the 'body-dark-mode' class on the body element
- useEffect(() => {
- if (isDarkMode) {
- document.body.classList.add("body-dark-mode");
- } else {
- document.body.classList.remove("body-dark-mode");
+ const[eventData, setEventData] = useState([])
+ const[addEvent, setaddEvent] = useState(false)
+ const [settlements, setSettlements] = useState([]);
+ const [amountOwed, setAmountOwed] = useState(0);
+ const [amountOwedBy, setAmountOwedBy] = useState(0);
+ const [searchTerm, setSearchTerm] = useState("");
+ //const[showFilter, setShowFilter] = useState(false);
+ //const[selectedFilter, setSelectedFilter] = useState('all');
+ //const[filteredEvents, setFilteredEvents] = useState([]);
+
+ function reformatDate(dateStr) {
+ const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
+ const date = new Date(dateStr);
+
+ const monthName = months[date.getMonth()];
+ const day = date.getDate();
+ const year = date.getFullYear();
+
+ return `${monthName} ${day} ${year}`;
}
- // Clean up function to remove the class when the component unmounts or when dark mode is turned off
- return () => {
- document.body.classList.remove("body-dark-mode");
- };
- }, [isDarkMode]);
-
- const token = localStorage.getItem("token");
- const decode = jwtDecode(token);
-
- useEffect(() => {
- //fetch mock data about a user's events list
- async function dataFetch() {
- try {
- if (!decode.id) {
- console.error("No current user found in local storage.");
- return;
+ // Toggle the 'body-dark-mode' class on the body element
+ useEffect(() => {
+ if (isDarkMode) {
+ document.body.classList.add('body-dark-mode');
} else {
- console.log(decode.id);
+ document.body.classList.remove('body-dark-mode');
+ }
+
+ // Clean up function to remove the class when the component unmounts or when dark mode is turned off
+ return () => {
+ document.body.classList.remove('body-dark-mode');
+ };
+ }, [isDarkMode]);
+
+ const token = localStorage.getItem("token");
+ const decode = jwtDecode(token);
+
+ useEffect(()=>{
+ //fetch mock data about a user's events list
+ async function dataFetch(){
+ try{
+ if (!decode.id) {
+ console.error("No current user found in local storage.");
+ return;
+ } else {
+ console.log(decode.id);
+ }
+ //requesting data from the mock API endpoint
+ const response = await axios.get(`${process.env.REACT_APP_BACKEND}/events/for/${decode.id}`);
+ console.log(response)
+ //return the data
+ setEventData(response.data)
+
+ }catch(error){
+ console.error("There was an error fetching the data:", error);
+ }
}
- //requesting data from the mock API endpoint
- const response = await axios.get(
- `${process.env.REACT_APP_BACKEND}/events/for/${decode.id}`
- );
- console.log(response);
- //return the data
- setEventData(response.data);
- } catch (error) {
- console.error("There was an error fetching the data:", error);
- }
+ dataFetch();
+ },[]);
+
+ useEffect(() => {
+ console.log(decode.id)
+ const fetchSettlements = async () => {
+ try {
+ const response = await axios.get(`${process.env.REACT_APP_BACKEND}/settlement/from/${decode.id}`);
+ console.log("Settlements:", response.data);
+ setSettlements(response.data);
+ // Process and use the fetched settlements here
+ } catch (error) {
+ console.error("Error fetching settlements:", error.response);
+ }
+ };
+
+ fetchSettlements();
+
+ }, []);
+
+ function calculateAmounts(expenses, currentUserId) {
+ let amountOwed = 0; // Amount the current user owes to others
+ let amountOwedBy = 0; // Amount owed to the current user by others
+
+ expenses.forEach(expense => {
+ if (expense.settleTo._id !== currentUserId && !expense.status) {
+ // If the current user is not the one who paid and the status is false (unsettled)
+ amountOwed += expense.amount;
+ }
+ if (expense.settleTo._id === currentUserId && !expense.status) {
+ // If the current user is the one who paid and the status is false (unsettled)
+ amountOwedBy += expense.amount;
+ }
+ });
+
+ return { amountOwed, amountOwedBy };
}
- dataFetch();
- }, []);
-
- useEffect(() => {
- console.log(decode.id);
- const fetchSettlements = async () => {
- try {
- const response = await axios.get(
- `${process.env.REACT_APP_BACKEND}/settlement/from/${decode.id}`
- );
- console.log("Settlements:", response.data);
- setSettlements(response.data);
- // Process and use the fetched settlements here
- } catch (error) {
- console.error("Error fetching settlements:", error.response);
- }
- };
-
- fetchSettlements();
- }, []);
-
- function calculateAmounts(expenses, currentUserId) {
- let amountOwed = 0; // Amount the current user owes to others
- let amountOwedBy = 0; // Amount owed to the current user by others
- expenses.forEach((expense) => {
- if (expense.settleTo._id !== currentUserId && !expense.status) {
- // If the current user is not the one who paid and the status is false (unsettled)
- amountOwed += expense.amount;
- }
- if (expense.settleTo._id === currentUserId && !expense.status) {
- // If the current user is the one who paid and the status is false (unsettled)
- amountOwedBy += expense.amount;
- }
- });
-
- return { amountOwed, amountOwedBy };
- }
+ useEffect(() => {
+ if (settlements.length > 0) {
+ const { amountOwed, amountOwedBy } = calculateAmounts(settlements, decode.id);
+ setAmountOwed(amountOwed);
+ setAmountOwedBy(amountOwedBy);
+ // Now you can use amountOwed and amountOwedBy in your component
+ console.log(`Amount Owed: ${amountOwed}, Amount Owed By: ${amountOwedBy}`);
+ }
+ }, [settlements, decode.id]);
- useEffect(() => {
- if (settlements.length > 0) {
- const { amountOwed, amountOwedBy } = calculateAmounts(
- settlements,
- decode.id
- );
- setAmountOwed(amountOwed);
- setAmountOwedBy(amountOwedBy);
- // Now you can use amountOwed and amountOwedBy in your component
- console.log(
- `Amount Owed: ${amountOwed}, Amount Owed By: ${amountOwedBy}`
- );
+ function EventClick(eventId){
+ console.log(`Event ${eventId} was clicked`)
}
- }, [settlements, decode.id]);
-
- function EventClick(eventId) {
- console.log(`Event ${eventId} was clicked`);
- }
- return (
-
-
Events
-
+ return(
+
+
Events
+
+
+
+ < img src={eventData.avatar} alt="User's Avatar" className="Total_Balance_avatar">
+
+
Total Balance
+
+ { (
+
You owe ${Math.abs(amountOwed).toFixed(2)}
+ )}
+ {(
+
You are owed ${amountOwedBy.toFixed(2)}
+ )}
+ {amountOwed === 0 && amountOwedBy === 0 && (
+
All Balances are Settled!
+ )}
+
+
+
-
-
-
-
Total Balance
-
- {
You owe ${Math.abs(amountOwed).toFixed(2)}
}
- {
You are owed ${amountOwedBy.toFixed(2)}
}
- {amountOwed === 0 && amountOwedBy === 0 && (
-
All Balances are Settled!
- )}
-
-
-
+
setSearchTerm(e.target.value)}
+ className="mt-4 search-input"
+ />
+
+
+
+ {eventData.events && eventData.events.length > 0 ? (eventData.events
+ .filter(event => event.name.toLowerCase().includes(searchTerm.toLowerCase()))
+ .map(event => (
+ -
+
+ {reformatDate(event.date)}
+
+
+ {event.name}
+
+
+
+
+
+ ))
+ ) : (
+ Please add your first event!
+ )}
+
+
-
setSearchTerm(e.target.value)}
- className="mt-4 search-input"
- />
-
-
- {eventData.events && eventData.events.length > 0 ? (
- eventData.events
- .filter((event) =>
- event.name.toLowerCase().includes(searchTerm.toLowerCase())
- )
- .map((event) => (
- -
-
{reformatDate(event.date)}
-
- {event.name}
-
-
-
-
-
- ))
- ) : (
-
- Please add your first event!
-
- )}
-
-
+ {addEvent && (
+
{setaddEvent(false); window.location.reload();}} />
+ )}
+
+
- {addEvent && (
- {
- setaddEvent(false);
- window.location.reload();
- }}
- />
- )}
-
-
-
-
-
- );
+
+ )
}
-export default Events;
+export default Events
\ No newline at end of file
diff --git a/front-end/src/components/Expense.jsx b/front-end/src/components/Expense.jsx
index bf93f90..f938309 100644
--- a/front-end/src/components/Expense.jsx
+++ b/front-end/src/components/Expense.jsx
@@ -79,26 +79,33 @@ function Expense({ isDarkMode }) {
(split) => split.user._id === userId
);
- if (!isParticipant) {
- // If not a participant, return an empty array or another appropriate value
- return [];
- }
-
let filteredExpenses = [];
if (expensesData.paidBy._id === userId) {
- filteredExpenses = expensesData.splitDetails
- .filter((split) => split.user._id !== userId)
- .map((split) => ({ ...split, displayName: split.user.username }));
- } else {
- filteredExpenses = expensesData.splitDetails
- .filter(
- (split) => split.user._id === userId && expensesData.paidBy !== userId
- )
- .map((split) => ({
+ if (!isParticipant) {
+ // If currentUser is not a participant, then the amount will be negative (owed by others)
+ filteredExpenses = expensesData.splitDetails.map(split => ({
+ ...split,
+ displayName: split.user.username,
+ amount: -split.settlement.amount
+ }));
+ } else {
+ // If currentUser is also a participant
+ filteredExpenses = expensesData.splitDetails.filter(split => split.user._id !== userId).map(split => ({
...split,
- displayName: expensesData.paidBy.username,
+ displayName: split.user.username,
+ amount: split.settlement.amount
}));
+ }
+ } else if (isParticipant) {
+ // When currentUser is not the one who paid but is a participant
+ filteredExpenses = expensesData.splitDetails.filter(split => split.user._id === userId && expensesData.paidBy !== userId).map(split => ({
+ ...split,
+ displayName: expensesData.paidBy.username,
+ amount: -split.settlement.amount
+ }));
+ }else{
+ filteredExpenses = [];
}
return filteredExpenses;
};
@@ -148,13 +155,7 @@ function Expense({ isDarkMode }) {