diff --git a/src/App.jsx b/src/App.jsx index 36f9c24..6bcb79a 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,19 +1,19 @@ -import { createBrowserRouter, RouterProvider } from "react-router-dom"; -import { ToastContainer } from "react-toastify"; -import "react-toastify/dist/ReactToastify.css"; -import { Main, mainLoader } from "./layouts/Main"; +import { createBrowserRouter, RouterProvider } from 'react-router-dom'; +import { ToastContainer } from 'react-toastify'; +import 'react-toastify/dist/ReactToastify.css'; +import { Main, mainLoader } from './layouts/Main'; -import { deleteBudget } from "./actions/deleteBudget"; +import { deleteBudget } from './actions/deleteBudget'; -import { Dashboard, dashboardAction, dashboardLoader } from "./pages/Dashboard"; -import { BudgetPage, budgetAction, budgetLoader } from "./pages/BudgetPage"; -import { ExpensesPage, expensesAction, expensesLoader } from "./pages/ExpensesPage"; -import { Error } from "./pages/Error"; -import { Stats } from "./pages/Stats"; +import { Dashboard, dashboardAction, dashboardLoader } from './pages/Dashboard'; +import { BudgetPage, budgetAction, budgetLoader } from './pages/BudgetPage'; +import { ExpensesPage, expensesAction, expensesLoader } from './pages/ExpensesPage'; +import { Error } from './pages/Error'; +import { Stats } from './pages/Stats'; const router = createBrowserRouter([ { - path: "/", + path: '/', element:
, loader: mainLoader, errorElement: , @@ -26,20 +26,20 @@ const router = createBrowserRouter([ errorElement: , }, { - path: "budget/:id", + path: 'budget/:id', element: , loader: budgetLoader, action: budgetAction, errorElement: , children: [ { - path: "delete", + path: 'delete', action: deleteBudget, }, ], }, { - path: "expenses", + path: 'expenses', element: , loader: expensesLoader, action: expensesAction, @@ -48,12 +48,12 @@ const router = createBrowserRouter([ ], }, { - path: "/stats", + path: '/stats', element: , errorElement: , }, { - path: "*", + path: '*', element: , }, ]); diff --git a/src/components/utility/DropMenu.jsx b/src/components/utility/DropMenu.jsx index 7797bfe..2ab26a8 100644 --- a/src/components/utility/DropMenu.jsx +++ b/src/components/utility/DropMenu.jsx @@ -1,89 +1,97 @@ -import { Fragment } from "react"; -import { Menu, Transition } from "@headlessui/react"; -import { FaRegUser } from "react-icons/fa6"; -import { toast } from "react-toastify"; -import { deleteItem, getDate } from "../../helpers"; -import * as ExcelJS from "exceljs"; +import { Fragment } from 'react'; +import { Menu, Transition } from '@headlessui/react'; +import { FaRegUser } from 'react-icons/fa6'; +import { toast } from 'react-toastify'; +import { deleteItem, getDate } from '../../helpers'; +import * as ExcelJS from 'exceljs'; function classNames(...classes) { - return classes.filter(Boolean).join(" "); + return classes.filter(Boolean).join(' '); } function logout() { deleteItem({ - key: "userName", + key: 'userName', }); deleteItem({ - key: "income", + key: 'income', }); deleteItem({ - key: "budgets", + key: 'budgets', }); deleteItem({ - key: "expenses", + key: 'expenses', }); - toast.success("You’ve deleted your account!"); + toast.success('You’ve deleted your account!'); + window.location.replace('/'); +} - setTimeout(() => { - return (document.location.href = "/"); - }, 250); +function resetData() { + deleteItem({ + key: 'income', + }); + deleteItem({ + key: 'expenses', + }); + toast.success('Data has been reset!'); + window.location.reload(); } function downloadDataAsJson() { const storedObjects = [ - JSON.parse(localStorage.getItem("userName")), - JSON.parse(localStorage.getItem("income")), - JSON.parse(localStorage.getItem("budgets")), - JSON.parse(localStorage.getItem("expenses")), + JSON.parse(localStorage.getItem('userName')), + JSON.parse(localStorage.getItem('income')), + JSON.parse(localStorage.getItem('budgets')), + JSON.parse(localStorage.getItem('expenses')), ]; if (!storedObjects || !storedObjects.length) { - console.error("No data to download."); - toast.error("Incomplete data in storage. Cannot download file."); + console.error('No data to download.'); + toast.error('Incomplete data in storage. Cannot download file.'); return; } const jsonString = JSON.stringify(storedObjects, null, 2); - const blob = new Blob([jsonString], { type: "application/json" }); + const blob = new Blob([jsonString], { type: 'application/json' }); - const downloadLink = document.createElement("a"); + const downloadLink = document.createElement('a'); downloadLink.href = URL.createObjectURL(blob); - downloadLink.download = "objects.json"; + downloadLink.download = 'objects.json'; document.body.appendChild(downloadLink); downloadLink.click(); document.body.removeChild(downloadLink); - return toast.success("Your data has been downloaded!"); + return toast.success('Your data has been downloaded!'); } function downloadDataAsExcel() { - const username = JSON.parse(localStorage.getItem("userName")); - const income = JSON.parse(localStorage.getItem("income")); - const budgets = JSON.parse(localStorage.getItem("budgets")); - const expenses = JSON.parse(localStorage.getItem("expenses")); + const username = JSON.parse(localStorage.getItem('userName')); + const income = JSON.parse(localStorage.getItem('income')); + const budgets = JSON.parse(localStorage.getItem('budgets')); + const expenses = JSON.parse(localStorage.getItem('expenses')); if (!username || !income || !budgets || !expenses) { - console.error("Incomplete data in local storage. Cannot download Excel file."); - toast.error("Incomplete data in local storage. Cannot download Excel file."); + console.error('Incomplete data in local storage. Cannot download Excel file.'); + toast.error('Incomplete data in local storage. Cannot download Excel file.'); return; } const chartData = [ - ["Type", "Amount"], - ["Budget", budgets.reduce((sum, budget) => sum + budget.amount, 0)], - ["Expense", expenses.reduce((sum, expense) => sum + expense.amount, 0)], + ['Type', 'Amount'], + ['Budget', budgets.reduce((sum, budget) => sum + budget.amount, 0)], + ['Expense', expenses.reduce((sum, expense) => sum + expense.amount, 0)], ]; const workbook = new ExcelJS.Workbook(); const worksheet = workbook.addWorksheet(`${username} - ${getDate()}`); const data = [ - ["User", "Type", "Date", "Name", "Category", "Amount"], + ['User', 'Type', 'Date', 'Name', 'Category', 'Amount'], ...budgets.map((budget) => [ username, - "Budget", + 'Budget', budget.createdAt, budget.name, budget.name, @@ -91,7 +99,7 @@ function downloadDataAsExcel() { ]), ...expenses.map((expense) => [ username, - "Expense", + 'Expense', expense.createdAt, expense.name, expense.budgetName, @@ -104,60 +112,58 @@ function downloadDataAsExcel() { budgets.forEach((budget, index) => { const row = worksheet.getRow(index + 2); row.fill = { - type: "pattern", - pattern: "solid", - fgColor: { argb: "00FF00" }, + type: 'pattern', + pattern: 'solid', + fgColor: { argb: '00FF00' }, }; }); expenses.forEach((expense, index) => { const row = worksheet.getRow(index + 2 + budgets.length); row.fill = { - type: "pattern", - pattern: "solid", - fgColor: { argb: "FF6347" }, + type: 'pattern', + pattern: 'solid', + fgColor: { argb: 'FF6347' }, }; }); workbook.xlsx.writeBuffer().then((buffer) => { const blob = new Blob([buffer], { - type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', }); - const downloadLink = document.createElement("a"); + const downloadLink = document.createElement('a'); downloadLink.href = URL.createObjectURL(blob); - downloadLink.download = "data.xlsx"; + downloadLink.download = 'data.xlsx'; document.body.appendChild(downloadLink); downloadLink.click(); document.body.removeChild(downloadLink); }); - localStorage.setItem("chartData", JSON.stringify(chartData)); + localStorage.setItem('chartData', JSON.stringify(chartData)); } function makeChart() { - const username = JSON.parse(localStorage.getItem("userName")); - const income = JSON.parse(localStorage.getItem("income")); - const budgets = JSON.parse(localStorage.getItem("budgets")); - const expenses = JSON.parse(localStorage.getItem("expenses")); + const username = JSON.parse(localStorage.getItem('userName')); + const income = JSON.parse(localStorage.getItem('income')); + const budgets = JSON.parse(localStorage.getItem('budgets')); + const expenses = JSON.parse(localStorage.getItem('expenses')); if (!username || !income || !budgets || !expenses) { - console.error("Incomplete data in local storage."); - toast.error("Incomplete data (Income, budgets, expenses), cannot make charts yet."); + console.error('Incomplete data in local storage.'); + toast.error('Incomplete data (Income, budgets, expenses), cannot make charts yet.'); return; } const chartData = [ - ["Type", "Amount"], - ["Budget", budgets.reduce((sum, budget) => sum + budget.amount, 0)], - ["Expense", expenses.reduce((sum, expense) => sum + expense.amount, 0)], + ['Type', 'Amount'], + ['Budget', budgets.reduce((sum, budget) => sum + budget.amount, 0)], + ['Expense', expenses.reduce((sum, expense) => sum + expense.amount, 0)], ]; - localStorage.setItem("chartData", JSON.stringify(chartData)); - setTimeout(() => { - return (document.location.href = "/stats"); - }, 500); + localStorage.setItem('chartData', JSON.stringify(chartData)); + window.location.replace('/stats'); } export function DropMenu() { @@ -186,8 +192,8 @@ export function DropMenu() { type='button' onClick={downloadDataAsJson} className={classNames( - active ? "bg-gray-100 text-navy" : "text-gray-700", - "block px-4 py-2 text-sm w-full" + active ? 'bg-gray-100 text-navy' : 'text-gray-700', + 'block px-4 py-2 text-sm w-full' )}> Download Data as JSON @@ -200,8 +206,8 @@ export function DropMenu() { type='button' onClick={downloadDataAsExcel} className={classNames( - active ? "bg-gray-100 text-navy" : "text-gray-700", - "block px-4 py-2 text-sm w-full" + active ? 'bg-gray-100 text-navy' : 'text-gray-700', + 'block px-4 py-2 text-sm w-full' )}> Download Data as excel @@ -214,22 +220,36 @@ export function DropMenu() { type='button' onClick={makeChart} className={classNames( - active ? "bg-gray-100 text-navy" : "text-gray-700", - "block px-4 py-2 text-sm w-full" + active ? 'bg-gray-100 text-navy' : 'text-gray-700', + 'block px-4 py-2 text-sm w-full' )}> Visualize Data )} + + {({ active }) => ( + + )} + + {({ active }) => ( diff --git a/src/pages/Stats.jsx b/src/pages/Stats.jsx index e5e5202..2c7e343 100644 --- a/src/pages/Stats.jsx +++ b/src/pages/Stats.jsx @@ -1,7 +1,9 @@ -import { useEffect, useState } from "react"; -import Chart from "chart.js/auto"; +import { useEffect, useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import Chart from 'chart.js/auto'; export function Stats() { + const navigate = useNavigate(); const [chartData, setChartData] = useState(null); const currentDate = new Date(); @@ -13,37 +15,35 @@ export function Stats() { } function goHome() { - setTimeout(() => { - window.location.href = "/"; - }, 500); + navigate('/'); } useEffect(() => { - const storedChartData = JSON.parse(localStorage.getItem("chartData")); + const storedChartData = JSON.parse(localStorage.getItem('chartData')); if (storedChartData) { setChartData(storedChartData); - console.log("Chart data retrieved from localStorage.", storedChartData); + console.log('Chart data retrieved from localStorage.', storedChartData); } else { - console.error("Chart data not found."); + console.error('Chart data not found.'); } }, []); useEffect(() => { if (chartData) { - const ctx = document.getElementById("myChart"); + const ctx = document.getElementById('myChart'); if (ctx) { new Chart(ctx, { - type: "bar", + type: 'bar', data: { labels: chartData.map((item) => item[0]), datasets: [ { - label: "Amount", + label: 'Amount', data: chartData.map((item) => item[1]), - backgroundColor: ["rgba(75, 192, 192, 0.2)", "rgba(255, 99, 132, 0.2)"], - borderColor: ["rgba(75, 192, 192, 1)", "rgba(255, 99, 132, 1)"], + backgroundColor: ['rgba(75, 192, 192, 0.2)', 'rgba(255, 99, 132, 0.2)'], + borderColor: ['rgba(75, 192, 192, 1)', 'rgba(255, 99, 132, 1)'], borderWidth: 1, }, ], @@ -51,7 +51,7 @@ export function Stats() { options: { scales: { y: { - type: "linear", + type: 'linear', beginAtZero: true, }, }, @@ -65,7 +65,7 @@ export function Stats() {

- Your spending report as of {printDate()} {" "} + Your spending report as of {printDate()} {' '}