From 7f3a20f913be5d9ac0f06f4219efa11f7fda4a67 Mon Sep 17 00:00:00 2001 From: predrag jandric Date: Wed, 2 Oct 2024 23:08:57 +0200 Subject: [PATCH 1/5] will FIX: responsive issues in GroupMembers.jsx and GroupChart.jsx when there are a lot of members. elements would previously overflow outside of parent container and not be aligned. this is now fixed --- expense-splitter/TODO.md | 8 +++-- .../src/components/Groups/GroupChart.jsx | 27 +++++++++------- .../src/components/Groups/GroupMembers.jsx | 32 +++++++++++-------- 3 files changed, 39 insertions(+), 28 deletions(-) diff --git a/expense-splitter/TODO.md b/expense-splitter/TODO.md index 1f43f77..9d86c7a 100644 --- a/expense-splitter/TODO.md +++ b/expense-splitter/TODO.md @@ -1,7 +1,9 @@ -some reminder for myself (Predrag) +some reminders for myself (Predrag) - try to extract modal logic into a custom hook -- simplify GroupMembers.jsx by making members automatically wrap inside container so that you can remove "view all" btn - replace icons in Total budget/Total expense/Remaining budget cards to be empty not filled, and replace the bugged shopping cart icon with something else + +MINOR + - see with Fari to make array of colors that look nice and are the same theme, like sand colors or something. this is for the chart colors on groups page -- inside GroupMembers.jsx make it so that member cards will wrap automatically and the container expands downwards automatically. for some reason, this is not the case right now by default. member cards should not overflow outside the container +- inside GroupMembers.jsx make a bg change on hover, add a little nice rounded corners also diff --git a/expense-splitter/src/components/Groups/GroupChart.jsx b/expense-splitter/src/components/Groups/GroupChart.jsx index 7672d50..b73c7f3 100644 --- a/expense-splitter/src/components/Groups/GroupChart.jsx +++ b/expense-splitter/src/components/Groups/GroupChart.jsx @@ -13,7 +13,7 @@ const renderCustomizedLabel = ({ outerRadius, percent, }) => { - const radius = innerRadius + (outerRadius - innerRadius) * 0.5; + const radius = innerRadius + (outerRadius - innerRadius) * 0.6; const x = cx + radius * Math.cos(-midAngle * (Math.PI / 180)); const y = cy + radius * Math.sin(-midAngle * (Math.PI / 180)); @@ -25,7 +25,7 @@ const renderCustomizedLabel = ({ fill="#FFFFFF" textAnchor="middle" dominantBaseline="central" - className="text-sm font-bold text-secondary" + className="text-md font-bold text-secondary" > {(percent * 100).toFixed(0)}% @@ -49,21 +49,23 @@ function GroupChart({ groupId }) { })); return ( -
+

Budget Split

- + */}
- + {/* chart size */} + {/* Custom legend */} -
+ {/* bg-white removed */} +
{data.map((entry, index) => ( -
+

Members

- + */}
-
+ {/* note to self, add bg-red-500 to line under to better checking for aligments */} +
{/* map method */} + {group.members.map((member) => ( -
+
))} - - -
+
{isModalOpen && (
Date: Thu, 3 Oct 2024 22:33:46 +0200 Subject: [PATCH 2/5] will ADD: fully functional search bar on homepage that filters groups by name and displays only those groups that match the letters in the search bar input field --- expense-splitter/TODO.md | 1 + expense-splitter/src/components/Layout.jsx | 9 ++- expense-splitter/src/components/SearchBar.jsx | 27 ++++++++ expense-splitter/src/features/groupsSlice.js | 24 +++---- expense-splitter/src/pages/Home.jsx | 69 +++++++++++++++---- 5 files changed, 98 insertions(+), 32 deletions(-) create mode 100644 expense-splitter/src/components/SearchBar.jsx diff --git a/expense-splitter/TODO.md b/expense-splitter/TODO.md index eb5b704..7720d32 100644 --- a/expense-splitter/TODO.md +++ b/expense-splitter/TODO.md @@ -7,4 +7,5 @@ MINOR - check whether DarkModeToggle.jsx toggle functionality can be written in more declarative way - [IN PROGRESS] see with Fari to make array of colors that look nice and are the same theme, like sand colors or something. this is for the chart colors on groups page +- [IN PROGRESS] color pallete for dark mode - inside GroupMembers.jsx make a bg change on hover diff --git a/expense-splitter/src/components/Layout.jsx b/expense-splitter/src/components/Layout.jsx index 5282d21..00478a9 100644 --- a/expense-splitter/src/components/Layout.jsx +++ b/expense-splitter/src/components/Layout.jsx @@ -1,20 +1,19 @@ import { Outlet } from "react-router-dom"; + // components import Sidebar from "./Sidebar"; // import Header from "./Header"; function Layout() { return ( -
+
- {/* */} +
- {/*
*/} -
-
+
); } diff --git a/expense-splitter/src/components/SearchBar.jsx b/expense-splitter/src/components/SearchBar.jsx new file mode 100644 index 0000000..8bb7f37 --- /dev/null +++ b/expense-splitter/src/components/SearchBar.jsx @@ -0,0 +1,27 @@ +import { IoIosSearch } from "react-icons/io"; +import { useState } from "react"; + +function SearchBar({ onSearch }) { + const [searchQuery, setSearchQuery] = useState(""); + + const handleSearch = (e) => { + const value = e.target.value; + setSearchQuery(value); + onSearch(value); // Call the parent handler to filter groups + }; + + return ( +
+ + +
+ ); +} + +export default SearchBar; diff --git a/expense-splitter/src/features/groupsSlice.js b/expense-splitter/src/features/groupsSlice.js index 7e0e3bf..85326f0 100644 --- a/expense-splitter/src/features/groupsSlice.js +++ b/expense-splitter/src/features/groupsSlice.js @@ -21,18 +21,18 @@ const initialState = { { id: 1, name: "Mark", contribution: 0 }, { id: 2, name: "Jason", contribution: 0 }, { id: 3, name: "Conan", contribution: 0 }, - { id: 1, name: "Mark", contribution: 0 }, - { id: 2, name: "Jason", contribution: 0 }, - { id: 3, name: "Conan", contribution: 0 }, - { id: 1, name: "Mark", contribution: 0 }, - { id: 2, name: "Jason", contribution: 0 }, - { id: 3, name: "Conan", contribution: 0 }, - { id: 1, name: "Mark", contribution: 0 }, - { id: 2, name: "Jason", contribution: 0 }, - { id: 3, name: "Conan", contribution: 0 }, - { id: 1, name: "Mark", contribution: 0 }, - { id: 2, name: "Jason", contribution: 0 }, - { id: 3, name: "Conan", contribution: 0 }, + { id: 4, name: "Mark", contribution: 0 }, + { id: 5, name: "Jason", contribution: 0 }, + { id: 6, name: "Conan", contribution: 0 }, + { id: 7, name: "Mark", contribution: 0 }, + { id: 8, name: "Jason", contribution: 0 }, + { id: 9, name: "Conan", contribution: 0 }, + { id: 10, name: "Mark", contribution: 0 }, + { id: 11, name: "Jason", contribution: 0 }, + { id: 12, name: "Conan", contribution: 0 }, + { id: 13, name: "Mark", contribution: 0 }, + { id: 14, name: "Jason", contribution: 0 }, + { id: 15, name: "Conan", contribution: 0 }, ], }, ], diff --git a/expense-splitter/src/pages/Home.jsx b/expense-splitter/src/pages/Home.jsx index 3c0bb0d..87cba6c 100644 --- a/expense-splitter/src/pages/Home.jsx +++ b/expense-splitter/src/pages/Home.jsx @@ -2,10 +2,23 @@ import { useDispatch, useSelector } from "react-redux"; import { useEffect, useState } from "react"; import HomeIndividualGroup from "../components/Home/HomeIndividualGroup"; import { addGroup } from "../features/groupsSlice"; +import SearchBar from "../components/SearchBar"; function Home() { const groups = useSelector((state) => state.groups.groups); + // search bar functionality + const [filteredGroups, setFilteredGroups] = useState(groups); + + const handleSearch = (query) => { + const lowerCaseQuery = query.toLowerCase(); + setFilteredGroups( + groups.filter((group) => + group.name.toLowerCase().includes(lowerCaseQuery) + ) + ); + }; + const [isModalOpen, setIsModalOpen] = useState(false); const dispatch = useDispatch(); @@ -61,15 +74,26 @@ function Home() { } }; + useEffect(() => { + setFilteredGroups(groups); + }, [groups]); + return (
-
-

Welcome to SplitSmart!

-

Tracks expenses, calculates costs, and settles debts with friends 😊

-
+
+
+

+ Welcome to SplitSmart! +

+

+ Tracks expenses, calculates costs, and settles debts with friends + 😊 +

+
+ +
-
- {groups.map((group) => ( - - ))} + {filteredGroups.length > 0 ? ( + filteredGroups.map((group) => ( + + )) + ) : ( +

No groups found

+ )} {isModalOpen && (
-

Add New Group

+

+ Add New Group +

{/* add actual icon for close btn */}
diff --git a/expense-splitter/src/features/localStorageUtils.js b/expense-splitter/src/features/localStorageUtils.js new file mode 100644 index 0000000..5e2df79 --- /dev/null +++ b/expense-splitter/src/features/localStorageUtils.js @@ -0,0 +1,24 @@ +// localStorageUtils.js + +export const loadState = () => { + try { + const serializedState = localStorage.getItem("appState"); + if (serializedState === null) { + return undefined; // Let reducers initialize the app state + } + return JSON.parse(serializedState); // Parse the state + } catch (err) { + console.error("Error loading state:", err); + return undefined; + } + }; + + export const saveState = (state) => { + try { + const serializedState = JSON.stringify(state); + localStorage.setItem("appState", serializedState); + } catch (err) { + console.error("Error saving state:", err); + } + }; + \ No newline at end of file diff --git a/expense-splitter/src/store.js b/expense-splitter/src/store.js index 8cb4d8b..2a5c828 100644 --- a/expense-splitter/src/store.js +++ b/expense-splitter/src/store.js @@ -1,12 +1,23 @@ import { configureStore } from "@reduxjs/toolkit"; import groupsReducer from "./features/groupsSlice"; +import { loadState, saveState } from "./features/localStorageUtils"; + +const preloadedState = loadState() export const store = configureStore({ reducer: { groups: groupsReducer, - } + }, + preloadedState, }) +store.subscribe(() => { + saveState(store.getState()); + }); + +// run in the browser console to clear the local storage or just remove manually in the local storage tab in dev tools +// localStorage.removeItem("appState"); + // if interested about this, you can read more here. // https://redux-toolkit.js.org/tutorials/quick-start // still left to do: create state slice inside features folder From e33958b2e4009dda26137a7ad54e957757b41fef Mon Sep 17 00:00:00 2001 From: predrag jandric Date: Thu, 3 Oct 2024 23:04:49 +0200 Subject: [PATCH 4/5] will REFACTOR: some code around add btn inside GroupMembers.jsx but the styling still has work to be done, it is inconsistent --- .../src/components/Groups/GroupMembers.jsx | 12 ++++++------ expense-splitter/src/store.js | 7 +++---- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/expense-splitter/src/components/Groups/GroupMembers.jsx b/expense-splitter/src/components/Groups/GroupMembers.jsx index d0763af..79989b4 100644 --- a/expense-splitter/src/components/Groups/GroupMembers.jsx +++ b/expense-splitter/src/components/Groups/GroupMembers.jsx @@ -1,4 +1,3 @@ -import { MdGroups } from "react-icons/md"; import GroupsEachMember from "./GroupsEachMember"; import { useParams } from "react-router-dom"; import { useSelector, useDispatch } from "react-redux"; @@ -89,15 +88,16 @@ function GroupMembers() { {/* note to self, add bg-red-500 to line under to better checking for aligments */}
- {/* map method */} + +
+

Add

+
{group.members.map((member) => (
{ saveState(store.getState()); }); -// run in the browser console to clear the local storage or just remove manually in the local storage tab in dev tools -// localStorage.removeItem("appState"); +// uncomment line below and reload page 2x for testing purposes or run in the browser console to clear the local storage or just remove manually in the local storage tab in dev tools + localStorage.removeItem("appState"); // if interested about this, you can read more here. // https://redux-toolkit.js.org/tutorials/quick-start -// still left to do: create state slice inside features folder -// and then add that slice reducers to the store + From c67e1531e9c580a3bbee027eccc378958d884f80 Mon Sep 17 00:00:00 2001 From: predrag jandric Date: Fri, 4 Oct 2024 16:05:25 +0200 Subject: [PATCH 5/5] will ADD: a list of tasks to do divided between developer team members which is the result of a meeting between Predrag (Peter) and Cash (Mandla) --- expense-splitter/TODO.md | 24 +++++++++++++++---- .../src/components/DarkModeToggle.jsx | 14 +++++------ .../src/components/Groups/GroupMembers.jsx | 6 ++--- expense-splitter/src/features/groupsSlice.js | 12 +--------- 4 files changed, 31 insertions(+), 25 deletions(-) diff --git a/expense-splitter/TODO.md b/expense-splitter/TODO.md index 7720d32..aa1ee46 100644 --- a/expense-splitter/TODO.md +++ b/expense-splitter/TODO.md @@ -1,11 +1,27 @@ some reminders for myself (Predrag) -- try to extract modal logic into a custom hook -- replace icons in Total budget/Total expense/Remaining budget cards to be empty not filled, and replace the bugged shopping cart icon with something else - MINOR - check whether DarkModeToggle.jsx toggle functionality can be written in more declarative way - [IN PROGRESS] see with Fari to make array of colors that look nice and are the same theme, like sand colors or something. this is for the chart colors on groups page - [IN PROGRESS] color pallete for dark mode -- inside GroupMembers.jsx make a bg change on hover + +CASH MEETING + +- AGREEMENT TO DELAY FOR NOW UNTIL ALL PREVIOUS TASKS ARE DONE discuss purpose of table inside group details and how to handle adding an expense +- CASH [STEP TO BE DONE?] discuss implementing groups in the sidebar as well and the ability to add new groups from the sidebar [SHOW IMAGE] +- [STEP TO BE DONE?] implement editing groups total budget and expense from groups details page +- CASH [STEP TO BE DONE?] fix styling and align everything well in GroupMembers.jsx +- CASH [STEP TO BE DONE?] inside GroupMembers.jsx members section where you can add and remove members, make a bg change on hover and replace minus for removing members with x and make bg of x more red and do hover too +- PREDRAG [STEP TO BE DONE?] try to extract modal logic into a custom hook +- PREDRAG [STEP TO BE DONE?] replace icons in Total budget/Total expense/Remaining budget cards to be empty not filled, and replace the bugged shopping cart icon with something else +- PREDRAG [STEP TO BE DONE?] refactor the modal in GroupMembers.jsx and all logic related to "member number". it should be contribution, what % of it. +- PREDRAG [STEP TO BE DONE?] add number of dollars that is percentage inside chart +- CASH [STEP TO BE DONE?] implement editable description component both for individual group and individual friend +- CASH [STEP TO BE DONE?] complete the layout on all pages +- PREDRAG [STEP TO BE DONE?] when there are no members in a group, the Budget Split component is bugged, fix it. ad text that says "there are no members for chart to display" +- CASH [STEP TO BE DONE?] create styling for a btn for theme toggling and put it in place instead of "need help" btn +- CASH [STEP TO BE DONE?] make logo clickable, it should take user to homepage +- AGREEMENT TO REMOVE discuss removing "montly" and "view all" btns in groups details page +- AGREEMENT TO REMOVE [IMAGE] discuss displayed list of friends on the homepage +- AGREEMENT TO DISCUSS FURTHER WITH THE REST OF THE TEAM discuss friends details page, NEEDS BIG CHANGES diff --git a/expense-splitter/src/components/DarkModeToggle.jsx b/expense-splitter/src/components/DarkModeToggle.jsx index 96e3163..92987c6 100644 --- a/expense-splitter/src/components/DarkModeToggle.jsx +++ b/expense-splitter/src/components/DarkModeToggle.jsx @@ -1,28 +1,28 @@ -import { useEffect, useState } from 'react'; +import { useEffect, useState } from "react"; function DarkModeToggle() { const [darkMode, setDarkMode] = useState(false); useEffect(() => { // Check local storage for the theme on initial render - const isDarkMode = localStorage.getItem('theme') === 'dark'; + const isDarkMode = localStorage.getItem("theme") === "dark"; setDarkMode(isDarkMode); - document.documentElement.classList.toggle('dark', isDarkMode); + document.documentElement.classList.toggle("dark", isDarkMode); }, []); const toggleDarkMode = () => { const newDarkMode = !darkMode; setDarkMode(newDarkMode); - document.documentElement.classList.toggle('dark', newDarkMode); - localStorage.setItem('theme', newDarkMode ? 'dark' : 'light'); + document.documentElement.classList.toggle("dark", newDarkMode); + localStorage.setItem("theme", newDarkMode ? "dark" : "light"); }; return ( ); } diff --git a/expense-splitter/src/components/Groups/GroupMembers.jsx b/expense-splitter/src/components/Groups/GroupMembers.jsx index 79989b4..7dd64c4 100644 --- a/expense-splitter/src/components/Groups/GroupMembers.jsx +++ b/expense-splitter/src/components/Groups/GroupMembers.jsx @@ -102,9 +102,9 @@ function GroupMembers() {
- +