Skip to content

Commit

Permalink
Merge pull request #24 from DoughFin/feature/df-101-debug-budget-disp…
Browse files Browse the repository at this point in the history
…lay-for-render

Feature/df 101 debug budget display for render
  • Loading branch information
shawndcarpenter authored Feb 24, 2024
2 parents f3c335e + 904a680 commit 7a15da9
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 134 deletions.
2 changes: 1 addition & 1 deletion src/components/AddExpense/AddExpense.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const AddExpense = ({ totalExpenses, setTotalExpenses, setTransactions }) => {
const [open, setOpen] = useState(false);
const [vendor, setVendor] = useState("");
const [category, setCategory] = useState("");
const [amount, setAmount] = useState(0);
const [amount, setAmount] = useState("");
const [date, setDate] = useState("");
// Bilbo's UID
const userId = 3
Expand Down
20 changes: 20 additions & 0 deletions src/components/Budget/Budget.css
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,17 @@
background: rgba(2, 177, 90, 0.15);
}

.budget-details-flex-neg {
display: flex;
width: 80px;
padding: 2px 0px;
justify-content: center;
align-items: center;
gap: 10px;
border-radius: 20px;
background: rgba(177, 2, 2, 0.15);
}

.budget-details-amount {
margin: 0px;
color: #02B15A;
Expand All @@ -132,6 +143,15 @@
line-height: normal;
}

.budget-details-amount-neg {
margin: 0px;
color: #da1717;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: normal;
}

.budget-categories-container {
display: flex;
flex-direction: column;
Expand Down
278 changes: 146 additions & 132 deletions src/components/Budget/Budget.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,149 +10,163 @@ import { useGetBudgetsByParams } from "../apollo-client/queries/getBudgetsByPara
import { useGetBudgetCategories } from "../apollo-client/queries/getBudgetCategories";

const Budget = () => {
const email = "[email protected]";
const { loading: loadingCategories, error: errorCategories, budgetCategoriesData } = useGetBudgetCategories(email);
console.log("Fetched budgetCategoriesData:", budgetCategoriesData);
const categories = loadingCategories || errorCategories ? [] : budgetCategoriesData || [];
const titleize = (sentence) => {
return sentence
.toLowerCase()
.split(' ')
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ');
};

const [category, setCategory] = useState();
const [month, setMonth] = useState(getCurrentMonth());
const { loading, error, budgetsData } = useGetBudgetsByParams(month, category, email);
// debugger;
if (error) {
console.error("Error fetching data:", error);
}
console.log("Fetched budgetData:", budgetsData);
const pctRemaining = Math.round(budgetsData?.budgets[0]?.pctRemaining) || 'Loading...';
const amount = budgetsData?.budgets[0]?.amount || 'Loading...';
const amountRemaining = Math.round(budgetsData?.budgets[0]?.amountRemaining) || 'Loading...';
const email = "[email protected]";
const { loading: loadingCategories, error: errorCategories, budgetCategoriesData } = useGetBudgetCategories(email);
console.log("Fetched budgetCategoriesData:", budgetCategoriesData);
const categories = loadingCategories || errorCategories ? [] : budgetCategoriesData || [];

// State to manage dropdown visibility
const [isDropdownVisible, setIsDropdownVisible] = useState(false);
const [dropDownStyle, setDropdownStyle] = useState({}); // State to hold modal's dynamic style
// references
const dropdownRef = useRef(null); // Ref for the dropdown icon to position the modal
const modalRef = useRef(null); // Add a ref for the modal
const [category, setCategory] = useState();
const [month, setMonth] = useState(getCurrentMonth());
const { loading, error, budgetsData } = useGetBudgetsByParams(month, category, email);
// debugger;
if (error) {
console.error("Error fetching data:", error);
}
console.log("Fetched budgetData:", budgetsData);
const pctRemaining = Math.round(budgetsData?.budgets[0]?.pctRemaining) < 0 ? 0 : Math.round(budgetsData?.budgets[0]?.pctRemaining) || 'Loading...';
const amount = budgetsData?.budgets[0]?.amount || 'Loading...';
const amountRemaining = Math.round(budgetsData?.budgets[0]?.amountRemaining) || 'Loading...';

// Handler functions for updating state
const handleCategoryChange = (selectedCategory) => {
setCategory(selectedCategory);
setIsDropdownVisible(false); // Hide the modal
};
// Handler to toggle dropdown visibility
const toggleDropdownVisibility = () => {
setIsDropdownVisible(!isDropdownVisible);
// State to manage dropdown visibility
const [isDropdownVisible, setIsDropdownVisible] = useState(false);
const [dropDownStyle, setDropdownStyle] = useState({}); // State to hold modal's dynamic style
// references
const dropdownRef = useRef(null); // Ref for the dropdown icon to position the modal
const modalRef = useRef(null); // Add a ref for the modal

if (dropdownRef.current) {
const { bottom, right } = dropdownRef.current.getBoundingClientRect();
const rightOffset = window.innerWidth - right; // Calculate the right offset from the viewport
// Handler functions for updating state
const handleCategoryChange = (selectedCategory) => {
setCategory(selectedCategory);
setIsDropdownVisible(false); // Hide the modal
};
// Handler to toggle dropdown visibility
const toggleDropdownVisibility = () => {
setIsDropdownVisible(!isDropdownVisible);

setDropdownStyle({
position: 'absolute',
top: `${bottom}px`,
right: `${rightOffset}px`,
// Adjustments might be needed based on actual layout and styling
});
}
};
const handleMonthChange = (event) => {
setMonth(event.target.value);
};
// Utility function to get current month, implementation depends on your needs
function getCurrentMonth() {
const date = new Date();
const year = date.getFullYear(); // Get current year
let month = date.getMonth() + 1; // Get current month (0-11, hence +1)
month = month < 10 ? `0${month}` : month; // Ensure month is in two digits
return `${year}-${month}`; // Concatenate to get "YYYY-MM" format
}
if (dropdownRef.current) {
const { bottom, right } = dropdownRef.current.getBoundingClientRect();
const rightOffset = window.innerWidth - right; // Calculate the right offset from the viewport

useEffect(() => {
if (categories.length > 0) {
setCategory(categories[0]);
}
}, [categories]);
setDropdownStyle({
position: 'absolute',
top: `${bottom}px`,
right: `${rightOffset}px`,
// Adjustments might be needed based on actual layout and styling
});
}
};
const handleMonthChange = (event) => {
setMonth(event.target.value);
};
// Utility function to get current month, implementation depends on your needs
function getCurrentMonth() {
const date = new Date();
const year = date.getFullYear(); // Get current year
let month = date.getMonth() + 1; // Get current month (0-11, hence +1)
month = month < 10 ? `0${month}` : month; // Ensure month is in two digits
return `${year}-${month}`; // Concatenate to get "YYYY-MM" format
}

useEffect(() => {
const handleClickOutside = (event) => {
if (modalRef.current && !modalRef.current.contains(event.target) &&
dropdownRef.current && !dropdownRef.current.contains(event.target)) {
setIsDropdownVisible(false);
}
};
useEffect(() => {
if (categories.length > 0) {
setCategory(categories[0]);
}
}, [categories]);

document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, []); // This effect does not depend on `categories`
useEffect(() => {
const handleClickOutside = (event) => {
if (modalRef.current && !modalRef.current.contains(event.target) &&
dropdownRef.current && !dropdownRef.current.contains(event.target)) {
setIsDropdownVisible(false);
}
};

return (
<aside className='budget'>
<header className='budget-header'>
<h2>{category}</h2>
<div ref={dropdownRef} onClick={toggleDropdownVisibility}>
<img className='budget-dropdown-button' src={DropDownIcon} alt='dropdown icon' />
</div>
{/* Conditionally render select dropdown */}
{isDropdownVisible && (
<div ref={modalRef} className="select-modal" style={dropDownStyle}>
{/* Dynamically generated modal content with options */}
{categories.length > 0 ? (
categories.map((category, index) => (
<div key={index} onClick={() => handleCategoryChange(category)}>{category}</div>
))
) : (
<div>No categories found.</div> // Or handle the empty state differently
)}
</div>
)}
</header>
<summary className='budget-pie-chart'>
<BasicPie
data={[
{ id: 0, value: (100 - pctRemaining) },
{ id: 1, value: pctRemaining },
]}
/>
</summary>
<section className='budget-percentage-breakdown'>
<div className='percentage-container'>
<div className='percentage-description'>
<img src={EllipsePurple} alt='purple ellipse'/>
<p>Budget Remaining</p>
</div>
<p className='percentage'>{pctRemaining}%</p>
document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, []); // This effect does not depend on `categories`

return (
<aside className='budget'>
<header className='budget-header'>
<h2>{category && titleize(category)}</h2>
<div ref={dropdownRef} onClick={toggleDropdownVisibility}>
<img className='budget-dropdown-button' src={DropDownIcon} alt='dropdown icon' />
</div>
{/* Conditionally render select dropdown */}
{isDropdownVisible && (
<div ref={modalRef} className="select-modal" style={dropDownStyle}>
{/* Dynamically generated modal content with options */}
{categories.length > 0 ? (
categories.map((category, index) => (
<div key={index} onClick={() => handleCategoryChange(category)}>{titleize(category)}</div>
))
) : (
<div>No categories found.</div> // Or handle the empty state differently
)}
</div>
<div className='percentage-container'>
<div className='percentage-description'>
<img src={EllipseBlue} alt='purple ellipse' />
<p>Budget Used</p>
)}
</header>
<summary className='budget-pie-chart'>
<BasicPie
data={[
{ id: 0, value: (100 - pctRemaining), color: '#64CFF6' },
{ id: 1, value: pctRemaining < 0 ? 0 : pctRemaining, color: '#6359E9'},
]}
/>
</summary>
<section className='budget-percentage-breakdown'>
<div className='percentage-container'>
<div className='percentage-description'>
<img src={EllipsePurple} alt='purple ellipse'/>
<p>Budget Remaining</p>
</div>
<p className='percentage'>{pctRemaining}%</p>
</div>
<p className='percentage'>{100 - pctRemaining}%</p>
<div className='percentage-container'>
<div className='percentage-description'>
<img src={EllipseBlue} alt='purple ellipse' />
<p>Budget Used</p>
</div>
</section>
<section className='budget-details-container'>
<div className='budget-details'>
<h3 className='budget-details-h3'>Budgeted Amount</h3>
<div className='budget-details-flex'>
<p className='budget-details-amount'>${amount}</p>
</div>
<p className='percentage'>{100 - pctRemaining}%</p>
</div>
</section>
<section className='budget-details-container'>
<div className='budget-details'>
<h3 className='budget-details-h3'>Budgeted Amount</h3>
<div className='budget-details-flex'>
<p className='budget-details-amount'>${(amount / 100).toFixed(2)}</p>
</div>
<div className='budget-details'>
<h3 className='budget-details-h3'>Remaining Budget</h3>
<div className='budget-details-flex'>
<p className='budget-details-amount'>${amountRemaining}</p>
</div>
<div className='budget-details'>
<h3 className='budget-details-h3'>Remaining Budget</h3>
{(amountRemaining / 100).toFixed(2) < 0 ? (
<div className='budget-details-flex-neg'>
<p className='budget-details-amount-neg'>-${Math.abs(amountRemaining / 100).toFixed(2)}</p>
</div>
</div>
</section>
<section className='budget-categories-container'>
<div className='budget-categories'>
<h3 className='budget-categories-h3'>Add New Category</h3>
<img className='budget-categories-add-button' src={PlusIcon} alt='dropdown icon' />
</div>
</section>
</aside>
)
}
export default Budget
) : (
<div className='budget-details-flex'>
<p className='budget-details-amount'>${(amountRemaining / 100).toFixed(2)}</p>
</div>
)}
</div>
</section>
<section className='budget-categories-container'>
<div className='budget-categories'>
<h3 className='budget-categories-h3'>Add New Category</h3>
<img className='budget-categories-add-button' src={PlusIcon} alt='dropdown icon' />
</div>
</section>
</aside>
)
}
export default Budget
2 changes: 1 addition & 1 deletion src/components/TransactionsTable/TransactionsTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const TransactionsTable = ({ transactions }) => {
<input
className="searchbar-text"
type="text"
placeholder="Search..."
placeholder="Search"
/>
<button className="searchbar-button"></button>
</div>
Expand Down

0 comments on commit 7a15da9

Please sign in to comment.