Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: enabled viewing historical finance data #3658

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
126 changes: 109 additions & 17 deletions components/FinancialSummary/BarChartComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
'use client';

import React, { useEffect, useState } from 'react';
import { Bar, BarChart, CartesianGrid, Legend, Tooltip, YAxis } from 'recharts';

import type { ExpenseItem, ExpensesLinkItem } from '@/types/FinancialSummary/BarChartComponent';
import { loadYearData } from '@/utils/loadYearData';

import ExpensesData from '../../config/finance/json-data/Expenses.json';
import ExpensesLinkData from '../../config/finance/json-data/ExpensesLink.json';
Expand All @@ -13,35 +16,107 @@ import ExpensesCard from './ExpensesCard';
* @description BarChartComponent component displays a bar chart for expense analysis.
*/
export default function BarChartComponent() {
const [mounted, setMounted] = useState(false);
// Setting up state variables using useState hook
const [selectedCategory, setSelectedCategory] = useState<string>('All Categories');
const [selectedMonth, setSelectedMonth] = useState<string>('All Months');
const [selectedYear, setSelectedYear] = useState<string>('2024');
const [windowWidth, setWindowWidth] = useState<number>(0);
const [currentData, setCurrentData] = useState<{
expensesData: { [key: string]: ExpenseItem[] };
expensesLinkData: ExpensesLinkItem[];
}>({
expensesData: ExpensesData, // Use JSON data as initial value
expensesLinkData: ExpensesLinkData
});

// Extracting unique categories and months from the data
const categories: string[] = getUniqueCategories();
const months: string[] = Object.keys(ExpensesData);
const years: string[] = ['2023', '2024']; // Add more years as needed

// Effect hook to handle mounting state
useEffect(() => {
setMounted(true);
}, []);

// Effect hook to update windowWidth state on resize
useEffect(() => {
const handleResize = () => {
setWindowWidth(window.innerWidth);
};

// Initial setup and event listener
handleResize();
window.addEventListener('resize', handleResize);

// Cleanup function to remove event listener
return () => {
window.removeEventListener('resize', handleResize);
};
if (typeof window !== 'undefined') {
const handleResize = () => {
setWindowWidth(window.innerWidth);
};

handleResize();
window.addEventListener('resize', handleResize);

return () => {
window.removeEventListener('resize', handleResize);
};
}
}, []);

// Filtering data based on selected month and category
const filteredData: ExpenseItem[] = Object.entries(ExpensesData).flatMap(([month, entries]) =>
// Effect to load year-specific data when year changes
useEffect(() => {
if (selectedYear === 'All Years') {
const allYearsData: { [key: string]: ExpenseItem[] } = {};
const allLinksData: ExpensesLinkItem[] = [...ExpensesLinkData];

// Start with the default JSON data
Object.keys(ExpensesData).forEach((month) => {
allYearsData[month] = [...ExpensesData[month as keyof typeof ExpensesData]];
});

// Add data from each year
years.forEach((year) => {
const { expensesData, expensesLinkData } = loadYearData(year);

if (Object.keys(expensesData).length > 0) {
// Combine expenses for each month
Object.keys(expensesData).forEach((month) => {
if (!allYearsData[month]) {
allYearsData[month] = [];
}
allYearsData[month].push(...expensesData[month]);
});

// Merge unique links
expensesLinkData.forEach((link: ExpensesLinkItem) => {
if (!allLinksData.some((l) => l.category === link.category)) {
allLinksData.push(link);
}
});
}
});

setCurrentData({
expensesData: allYearsData,
expensesLinkData: allLinksData
});
} else {
// Otherwise load year-specific data
const { expensesData, expensesLinkData } = loadYearData(selectedYear);

if (Object.keys(expensesData).length === 0) {
// If no year-specific data found, fallback to JSON data
setCurrentData({
expensesData: ExpensesData,
expensesLinkData: ExpensesLinkData
});
} else {
setCurrentData({ expensesData, expensesLinkData });
}
}
}, [selectedYear]);

// Modify months to use current year's data
const months: string[] = Object.keys(currentData.expensesData);

// Filtering data based on selected month, year, and category
const filteredData: ExpenseItem[] = Object.entries(currentData.expensesData).flatMap(([month, entries]) =>
selectedMonth === 'All Months' || selectedMonth === month
? entries.filter((entry) => selectedCategory === 'All Categories' || entry.Category === selectedCategory)
? entries.filter(
(entry: ExpenseItem) => selectedCategory === 'All Categories' || entry.Category === selectedCategory
)
: []
);

Expand All @@ -68,6 +143,11 @@ export default function BarChartComponent() {
const barWidth: number | undefined = windowWidth && windowWidth < 900 ? undefined : 800;
const barHeight: number | undefined = windowWidth && windowWidth < 900 ? undefined : 400;

// Don't render anything until component is mounted
if (!mounted) {
return null;
}

return (
<div className='mt-8 flex items-center justify-center sm:px-6 lg:px-8'>
<div className='w-full px-4 text-center lg:w-2/3'>
Expand Down Expand Up @@ -107,6 +187,18 @@ export default function BarChartComponent() {
</option>
))}
</select>
<select
className='m-1 w-full rounded-md border border-gray-600 bg-white p-2 text-xs font-semibold text-violet sm:w-auto md:w-48'
value={selectedYear}
onChange={(e) => setSelectedYear(e.target.value)}
>
<option value='All Years'>All Years</option>
{years.map((year) => (
<option key={year} value={year}>
{year}
</option>
))}
</select>
</div>
</div>
</div>
Expand All @@ -122,7 +214,7 @@ export default function BarChartComponent() {
fill='#7B5DD3FF'
onClick={(data) => {
const category = data.payload.Category;
const matchedLinkObject: ExpensesLinkItem | undefined = ExpensesLinkData.find(
const matchedLinkObject: ExpensesLinkItem | undefined = currentData.expensesLinkData.find(
(obj) => obj.category === category
);

Expand Down
194 changes: 194 additions & 0 deletions config/finance/2023/Expenses.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
{
"January": [
{
"Category": "Ambassador Program",
"Amount": "68.95"
},
{
"Category": "Google Season of Docs 2022",
"Amount": "35.62"
},
{
"Category": "Google Season of Docs 2022",
"Amount": "1666.67"
},
{
"Category": "AsyncAPI Mentorship 2022",
"Amount": "1500"
},
{
"Category": "AsyncAPI Mentorship 2022",
"Amount": "1500"
},
{
"Category": "AsyncAPI Mentorship 2022",
"Amount": "1500"
}
],
"February": [
{
"Category": "Community Manager",
"Amount": "1000.39"
},
{
"Category": "AsyncAPI Mentorship 2022",
"Amount": "1500"
}
],
"March": [
{
"Category": "Community Manager",
"Amount": "2000.39"
},
{
"Category": "AsyncAPI Mentorship 2022",
"Amount": "1500"
},
{
"Category": "AsyncAPI Mentorship 2022",
"Amount": "1500"
}
],
"April": [
{
"Category": "Community Manager",
"Amount": "2000.39"
}
],
"May": [
{
"Category": "Community Manager",
"Amount": "2000.39"
},
{
"Category": "Swag Store",
"Amount": "75.11"
},
{
"Category": "Bounty Program",
"Amount": "400"
}
],
"June": [
{
"Category": "Community Manager",
"Amount": "2000.39"
},
{
"Category": "Bounty Program",
"Amount": "200"
},
{
"Category": "3rd Party Services",
"Amount": "28.31"
},
{
"Category": "Bounty Program",
"Amount": "200"
},
{
"Category": "Bounty Program",
"Amount": "200"
},
{
"Category": "Bounty Program",
"Amount": "200"
}
],
"July": [
{
"Category": "Community Manager",
"Amount": "2000.39"
},
{
"Category": "Bounty Program",
"Amount": "400"
}
],
"August": [
{
"Category": "3rd Party Services",
"Amount": "1093.92"
},
{
"Category": "Swag Store",
"Amount": "15672.02"
},
{
"Category": "Bounty Program",
"Amount": "800.78"
},
{
"Category": "Community Manager",
"Amount": "2000.39"
}
],
"September": [
{
"Category": "Ambassador Program",
"Amount": "139.10"
},
{
"Category": "Community Manager",
"Amount": "2000.39"
}
],
"October": [
{
"Category": "Mentorship Program 2023",
"Amount": "5277.78"
},
{
"Category": "Community Manager",
"Amount": "2000.39"
},
{
"Category": "AsyncAPI Conf on Tour 2023",
"Amount": "943.07"
},
{
"Category": "Swag Store",
"Amount": "7893.72"
},
{
"Category": "3rd Party Services",
"Amount": "247.04"
}
],
"November": [
{
"Category": "Mentorship Program 2023",
"Amount": "1363.50"
},
{
"Category": "Community Manager",
"Amount": "2000.39"
},
{
"Category": "Swag Store",
"Amount": "873.87"
}
],
"December": [
{
"Category": "Mentorship Program 2023",
"Amount": "675.39"
},
{
"Category": "Community Manager",
"Amount": "2000.39"
},
{
"Category": "AsyncAPI Conf on Tour 2023",
"Amount": "1356.34"
},
{
"Category": "Swag Store",
"Amount": "1415.90"
},
{
"Category": "Bounty Program",
"Amount": "813.10"
}
]
}
Loading
Loading