From 07abcc29d2ff3afed3bd50aaff7d3cb2dcccefff Mon Sep 17 00:00:00 2001 From: Juthatip McDevitt Date: Wed, 3 Apr 2024 15:08:59 -0500 Subject: [PATCH] added dashboard data --- admin_dashboard/client/src/App.js | 5 + .../client/src/components/BreakdownChart.jsx | 124 ++++++++++++++ .../client/src/components/Sidebar.jsx | 18 +- .../client/src/components/StatBox.jsx | 24 +++ .../client/src/pages/breakdown/Breakdown.jsx | 17 ++ .../client/src/pages/dashboard/Dashboard.jsx | 89 +++++++++- .../client/src/pages/monthlyStat/Monthly.jsx | 157 ++++++++++++++++++ admin_dashboard/client/src/state/api.js | 8 +- admin_dashboard/server/controllers/general.js | 26 +++ .../server/controllers/management.js | 12 ++ admin_dashboard/server/models/Stat.js | 2 +- admin_dashboard/server/routes/general.js | 3 +- admin_dashboard/server/routes/management.js | 4 + 13 files changed, 469 insertions(+), 20 deletions(-) create mode 100644 admin_dashboard/client/src/components/BreakdownChart.jsx create mode 100644 admin_dashboard/client/src/components/StatBox.jsx create mode 100644 admin_dashboard/client/src/pages/breakdown/Breakdown.jsx create mode 100644 admin_dashboard/client/src/pages/monthlyStat/Monthly.jsx diff --git a/admin_dashboard/client/src/App.js b/admin_dashboard/client/src/App.js index 37a96b3..5467ad2 100644 --- a/admin_dashboard/client/src/App.js +++ b/admin_dashboard/client/src/App.js @@ -12,6 +12,9 @@ import Transactions from "pages/transactions/Transactions"; import Geography from "pages/geography/Geography"; import Overview from "pages/overview/Overview"; import Daily from "pages/dailyStat/Daily"; +import Monthly from "pages/monthlyStat/Monthly"; +import Breakdown from "pages/breakdown/Breakdown"; + function App() { @@ -35,6 +38,8 @@ function App() { } /> } /> }/> + }/> + }/> diff --git a/admin_dashboard/client/src/components/BreakdownChart.jsx b/admin_dashboard/client/src/components/BreakdownChart.jsx new file mode 100644 index 0000000..0a3f270 --- /dev/null +++ b/admin_dashboard/client/src/components/BreakdownChart.jsx @@ -0,0 +1,124 @@ +import React from 'react' +import { ResponsivePie } from '@nivo/pie' +import { Box, Typography, useTheme } from "@mui/material"; +import { useGetSalesQuery } from 'state/api'; + + + + +const BreakdownChart = ({ isDashboard = false }) => { + const theme = useTheme(); + const {data, isLoading} = useGetSalesQuery(); + if (!data || isLoading) return "Loading..."; + + const colors = [ + theme.palette.secondary[500], + theme.palette.secondary[300], + theme.palette.secondary[300], + theme.palette.secondary[500], + ]; + const formattedData = Object.entries(data.salesByCategory).map( + ([category, sales], i) => ({ + id: category, + label: category, + value: sales, + color: colors[i], + }) + ); + + + return ( + + + + + {!isDashboard && "Total:"} ${data.yearlySalesTotal} + + + + ) +} + +export default BreakdownChart \ No newline at end of file diff --git a/admin_dashboard/client/src/components/Sidebar.jsx b/admin_dashboard/client/src/components/Sidebar.jsx index ead4811..ce4c98e 100644 --- a/admin_dashboard/client/src/components/Sidebar.jsx +++ b/admin_dashboard/client/src/components/Sidebar.jsx @@ -1,7 +1,7 @@ import React from 'react' import { Box, Divider, Drawer, IconButton, List, ListItem, ListItemButton, ListItemIcon, ListItemText, Typography, useTheme } from '@mui/material' import { SettingsOutlined, ChevronLeft, ChevronRightOutlined, HomeOutlined, Groups2Outlined, ReceiptLongOutlined, PublicOutlined, - TodayOutlined, CalendarMonthOutlined, AdminPanelSettingsOutlined, TrendingUpOutlined, PieChartOutlined } from '@mui/icons-material' + TodayOutlined, CalendarMonthOutlined, PieChartOutlined } from '@mui/icons-material' import CategoryOutlinedIcon from '@mui/icons-material/CategoryOutlined'; import PlagiarismOutlinedIcon from '@mui/icons-material/PlagiarismOutlined'; import { useLocation, useNavigate } from 'react-router-dom' @@ -54,18 +54,6 @@ const navItems = [ { text: "Breakdown", icon: - }, - { - text: "Management", - icon: null, - }, - { - text: "Admin", - icon: - }, - { - text: "Performance", - icon: }, ] @@ -95,8 +83,8 @@ const Sidebar = ({user, drawerWidth, sidebarOpen, setSidebarOpen, nonMobile,}) = - - Jtp Dashboard + + Analytics Dashboard {!nonMobile && ( diff --git a/admin_dashboard/client/src/components/StatBox.jsx b/admin_dashboard/client/src/components/StatBox.jsx new file mode 100644 index 0000000..1bc1c11 --- /dev/null +++ b/admin_dashboard/client/src/components/StatBox.jsx @@ -0,0 +1,24 @@ +import React from 'react' +import { Box, Typography, useTheme } from "@mui/material"; +import FlexBetween from "./FlexBetween"; + + +const StatBox = ({ title, value, increase, icon, description }) => { + const theme = useTheme(); + + + return ( + + + {title}{icon} + + {value} + + {increase} + {description} + + + ) +} + +export default StatBox \ No newline at end of file diff --git a/admin_dashboard/client/src/pages/breakdown/Breakdown.jsx b/admin_dashboard/client/src/pages/breakdown/Breakdown.jsx new file mode 100644 index 0000000..6211dc3 --- /dev/null +++ b/admin_dashboard/client/src/pages/breakdown/Breakdown.jsx @@ -0,0 +1,17 @@ +import { Box } from '@mui/material' +import BreakdownChart from 'components/BreakdownChart' +import Header from 'components/Header' +import React from 'react' + +const Breakdown = () => { + return ( + +
+ + + + + ) +} + +export default Breakdown \ No newline at end of file diff --git a/admin_dashboard/client/src/pages/dashboard/Dashboard.jsx b/admin_dashboard/client/src/pages/dashboard/Dashboard.jsx index f493e64..2bd5399 100644 --- a/admin_dashboard/client/src/pages/dashboard/Dashboard.jsx +++ b/admin_dashboard/client/src/pages/dashboard/Dashboard.jsx @@ -1,8 +1,95 @@ +import { Box, Button, Typography, useTheme, useMediaQuery, } from '@mui/material' +import FlexBetween from 'components/FlexBetween' +import Header from 'components/Header' import React from 'react' +import { DownloadOutlined, Email, PointOfSale, PersonAdd, Traffic } from "@mui/icons-material"; +import { DataGrid } from '@mui/x-data-grid'; +import BreakdownChart from 'components/BreakdownChart'; +import OverviewChart from 'components/OverviewChart'; +import { useGetDashboardQuery } from 'state/api'; +import StatBox from 'components/StatBox'; + + + const Dashboard = () => { + const theme = useTheme(); + const isNonMediumScreens = useMediaQuery("(min-width: 1200px)"); + const { data, isLoading } = useGetDashboardQuery(); + console.log(data) + + const columns = [ + { + field: "_id", + headerName: "ID", + flex: 1, + }, + { + field: "userId", + headerName: "User ID", + flex: 1, + }, + { + field: "createdAt", + headerName: "CreatedAt", + flex: 1, + }, + { + field: "products", + headerName: "# of Products", + flex: 0.5, + sortable: false, + renderCell: (params) => params.value.length, + }, + { + field: "cost", + headerName: "Cost", + flex: 1, + renderCell: (params) => `$${Number(params.value).toFixed(2)}`, + }, + ]; + + return ( -
Dashboard
+ + +
+ + + + + div": { gridColumn: isNonMediumScreens ? undefined : "span 12" }}}> + }/> + }/> + + + + }/> + }/> + + + row._id} rows={(data && data.transactions) || []} columns={columns}/> + + + Sales By Category + + + Breakdown of real states and information via category for revenue made for this year and total sales. + + + + ) } diff --git a/admin_dashboard/client/src/pages/monthlyStat/Monthly.jsx b/admin_dashboard/client/src/pages/monthlyStat/Monthly.jsx new file mode 100644 index 0000000..878cd88 --- /dev/null +++ b/admin_dashboard/client/src/pages/monthlyStat/Monthly.jsx @@ -0,0 +1,157 @@ +import { useTheme } from '@emotion/react' +import { Box } from '@mui/material' +import { ResponsiveLine } from '@nivo/line' +import Header from 'components/Header' +import React, { useMemo } from 'react' +import { useGetSalesQuery } from 'state/api' + +const Monthly = () => { + const theme = useTheme(); + const {data} = useGetSalesQuery(); + const [formattedData] = useMemo(() => { + if (!data) return []; + + const {monthlyData} = data; + const totalSalesLine = { + id: "totalSales", + color: theme.palette.secondary.main, + data: [], + }; + const totalUnitsLine = { + id: "totalUnits", + color: theme.palette.secondary[600], + data: [], + }; + Object.values(monthlyData).forEach(({ month, totalSales, totalUnits }) => { + totalSalesLine.data = [ + ...totalSalesLine.data, + { x: month, y: totalSales }, + ]; + totalUnitsLine.data = [ + ...totalUnitsLine.data, + { x: month, y: totalUnits }, + ]; + }); + + const formattedData = [totalSalesLine, totalUnitsLine]; + return [formattedData]; + }, [data]); + + + + return ( + +
+ + {data ? ( + + ) : ( + <>Loading... + )} + + + ) +} + +export default Monthly \ No newline at end of file diff --git a/admin_dashboard/client/src/state/api.js b/admin_dashboard/client/src/state/api.js index 0f9fd12..1c05331 100644 --- a/admin_dashboard/client/src/state/api.js +++ b/admin_dashboard/client/src/state/api.js @@ -3,7 +3,7 @@ import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react" export const api = createApi({ baseQuery: fetchBaseQuery({baseUrl: process.env.REACT_APP_BASE_URL}), reducerPath: "adminApi", - tagTypes: ["User", "Products", "Customers", "Transactions", "Geography", "Sales" ], + tagTypes: ["User", "Products", "Customers", "Transactions", "Geography", "Sales", "Dashboard" ], endpoints: (build) => ({ getUser: build.query({ query: (id) => `general/user/${id}`, @@ -32,8 +32,12 @@ export const api = createApi({ getSales: build.query({ query: () => "sales/sales", providesTags: ["Sales"] + }), + getDashboard: build.query({ + query: () => "general/dashboard", + providesTags: ["Dashboard"] }) }) }) -export const {useGetUserQuery, useGetProductsQuery, useGetCustomersQuery, useGetTransactionsQuery, useGetGeographyQuery, useGetSalesQuery} = api; +export const {useGetUserQuery, useGetProductsQuery, useGetCustomersQuery, useGetTransactionsQuery, useGetGeographyQuery, useGetSalesQuery, useGetDashboardQuery} = api; diff --git a/admin_dashboard/server/controllers/general.js b/admin_dashboard/server/controllers/general.js index de7c435..0bdeb15 100644 --- a/admin_dashboard/server/controllers/general.js +++ b/admin_dashboard/server/controllers/general.js @@ -1,4 +1,6 @@ import User from "../models/User.js"; +import Stat from "../models/Stat.js" +import Transaction from "../models/Transaction.js" export const getUser = async(req, res) => { try { @@ -7,6 +9,30 @@ export const getUser = async(req, res) => { res.status(200).json(user); + } catch (error) { + res.status(404).json({message: error.message}) + } +}; + +export const getDashboardStats = async(req, res) => { + try { + const currerntMonth = "November"; + const currentYear = 2021; + const currenrtDay = "2021-04-15"; + const transactions = await Transaction.find().limit(50).sort({createdOn: -1}); + + const stat = await Stat.find({year: currentYear}); + const {totalCustomers, yearlyTotalSoldUnits, yearlySalesTotal, monthlyData, salesByCategory} = stat[0] + + const thisMonthStats = stat[0].monthlyData.find(({month}) => { + return month === currerntMonth; + }); + const todayStats = stat[0].dailyData.find(({date}) => { + return date === currenrtDay; + }); + + res.status(200).json({totalCustomers, yearlyTotalSoldUnits, yearlySalesTotal, monthlyData, salesByCategory, thisMonthStats, todayStats, transactions}) + } catch (error) { res.status(404).json({message: error.message}) } diff --git a/admin_dashboard/server/controllers/management.js b/admin_dashboard/server/controllers/management.js index e69de29..900f937 100644 --- a/admin_dashboard/server/controllers/management.js +++ b/admin_dashboard/server/controllers/management.js @@ -0,0 +1,12 @@ +import mongoose from "mongoose" +import User from "../models/User.js" + +export const getAdmins = async(req, res) => { + try { + const admins = await User.find({ role: "admin"}).select("-password"); + res.status(200).json(admins); + + } catch (error) { + res.status(404).json({message: error.message}) + } +} \ No newline at end of file diff --git a/admin_dashboard/server/models/Stat.js b/admin_dashboard/server/models/Stat.js index 781c2d2..105a008 100644 --- a/admin_dashboard/server/models/Stat.js +++ b/admin_dashboard/server/models/Stat.js @@ -3,7 +3,7 @@ import mongoose from "mongoose" const StatSchema = new mongoose.Schema( { totalCustomers: Number, - yaerlySalesTotal: Number, + yearlySalesTotal: Number, yearlyTotalSoldUnits: Number, yaer: Number, monthlyData: [ diff --git a/admin_dashboard/server/routes/general.js b/admin_dashboard/server/routes/general.js index d508f96..3c57d6e 100644 --- a/admin_dashboard/server/routes/general.js +++ b/admin_dashboard/server/routes/general.js @@ -1,9 +1,10 @@ import express from "express" -import {getUser} from "../controllers/general.js" +import {getUser, getDashboardStats} from "../controllers/general.js" const router = express.Router(); router.get("/user/:id", getUser); +router.get("/dashboard", getDashboardStats) export default router; \ No newline at end of file diff --git a/admin_dashboard/server/routes/management.js b/admin_dashboard/server/routes/management.js index 4596761..16e45e8 100644 --- a/admin_dashboard/server/routes/management.js +++ b/admin_dashboard/server/routes/management.js @@ -1,5 +1,9 @@ import express from "express" +import {getAdmins} from "../controllers/management.js" + const router = express.Router(); +router.get("/admin", getAdmins); + export default router; \ No newline at end of file