diff --git a/code/Software/Frontend/package-lock.json b/code/Software/Frontend/package-lock.json index acd00ee..56baf38 100644 --- a/code/Software/Frontend/package-lock.json +++ b/code/Software/Frontend/package-lock.json @@ -14,8 +14,10 @@ "axios": "^1.6.3", "bootstrap": "^5.3.2", "bootstrap-icons": "^1.11.2", + "chart.js": "^4.4.1", "mqtt": "^5.3.4", "react": "^18.2.0", + "react-chartjs-2": "^5.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.21.1" }, @@ -939,6 +941,11 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@kurkle/color": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", + "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1691,6 +1698,17 @@ "node": ">=4" } }, + "node_modules/chart.js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.1.tgz", + "integrity": "sha512-C74QN1bxwV1v2PEujhmKjOZ7iUM4w6BWs23Md/6aOZZSlwMzeCIDGuZay++rBgChYru7/+QFeoQW0fQoP534Dg==", + "dependencies": { + "@kurkle/color": "^0.3.0" + }, + "engines": { + "pnpm": ">=7" + } + }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -3791,6 +3809,15 @@ "node": ">=0.10.0" } }, + "node_modules/react-chartjs-2": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.2.0.tgz", + "integrity": "sha512-98iN5aguJyVSxp5U3CblRLH67J8gkfyGNbiK3c+l1QI/G4irHMPQw44aEPmjVag+YKTyQ260NcF82GTQ3bdscA==", + "peerDependencies": { + "chart.js": "^4.1.1", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-dom": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", diff --git a/code/Software/Frontend/package.json b/code/Software/Frontend/package.json index d0c98a3..8736fac 100644 --- a/code/Software/Frontend/package.json +++ b/code/Software/Frontend/package.json @@ -16,8 +16,10 @@ "axios": "^1.6.3", "bootstrap": "^5.3.2", "bootstrap-icons": "^1.11.2", + "chart.js": "^4.4.1", "mqtt": "^5.3.4", "react": "^18.2.0", + "react-chartjs-2": "^5.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.21.1" }, diff --git a/code/Software/Frontend/src/AdminDashboard/Dashboard/Dashboard.jsx b/code/Software/Frontend/src/AdminDashboard/Dashboard/Dashboard.jsx index 1c06407..904a25d 100644 --- a/code/Software/Frontend/src/AdminDashboard/Dashboard/Dashboard.jsx +++ b/code/Software/Frontend/src/AdminDashboard/Dashboard/Dashboard.jsx @@ -57,7 +57,7 @@ const Dashboard = () => { const fetchProductQuantities = async () => { try { - const response = await axios.get("http://localhost:5555/itemPurchased/quantity"); + const response = await axios.get("http://localhost:5555/itemPurchased/quantity/t"); const data = response.data; console.log(data); @@ -95,7 +95,7 @@ const Dashboard = () => {

LKR {totalSaleToday}

Total Sales -

{percentageChange}% from yesterday

+

{percentageChange.toFixed(0)}% from yesterday

@@ -108,7 +108,7 @@ const Dashboard = () => {

{billCountToday}

Total Bills -

{percentageChangeBills}% from yesterday

+

{percentageChangeBills.toFixed(0)}% from yesterday

diff --git a/code/Software/Frontend/src/AdminDashboard/Invoices.jsx b/code/Software/Frontend/src/AdminDashboard/Invoices.jsx index 6d02ba1..fd01e53 100644 --- a/code/Software/Frontend/src/AdminDashboard/Invoices.jsx +++ b/code/Software/Frontend/src/AdminDashboard/Invoices.jsx @@ -152,7 +152,7 @@ function Invoices() { name="totalAmount" value={updateFormData[invoice._id]?.totalAmount || ""} onChange={(e) => handleUpdateInputChange(e, invoice._id)} - style={{ width: '70px' }} + style={{ width: '70px',height:'27px',borderRadius:'1px'}} /> @@ -165,7 +165,7 @@ function Invoices() { name="discountApplied" value={updateFormData[invoice._id]?.discountApplied || ""} onChange={(e) => handleUpdateInputChange(e, invoice._id)} - style={{ width: '90px'}} + style={{ width: '90px',height:'27px',borderRadius:'1px'}} /> {invoice.paymentMethod} @@ -176,7 +176,7 @@ function Invoices() { name="paymentMethod" value={updateFormData[invoice._id]?.paymentMethod || ""} onChange={(e) => handleUpdateInputChange(e, invoice._id)} - style={{ width: '100px' }} + style={{ width: '100px' ,height:'27px',borderRadius:'1px'}} /> diff --git a/code/Software/Frontend/src/AdminDashboard/Sales.jsx b/code/Software/Frontend/src/AdminDashboard/Sales.jsx index 3de05d1..ab485be 100644 --- a/code/Software/Frontend/src/AdminDashboard/Sales.jsx +++ b/code/Software/Frontend/src/AdminDashboard/Sales.jsx @@ -1,11 +1,89 @@ -import React from "react"; +import React, { useState, useEffect, useRef } from 'react'; +import axios from 'axios'; +//import { Line } from 'react-chartjs-2'; +import Chart from 'chart.js/auto'; -function Sales(){ - return( -
-
Sales details here...
-
- ) -} -export default Sales; \ No newline at end of file +const Sales = () => { + const [data, setData] = useState([]); + const [labels, setLabels] = useState([]); + const chartRef = useRef(null); + + useEffect(() => { + const fetchData = async () => { + try { + const today = new Date(); + const lastTenDays = Array.from({ length: 10 }, (_, i) => { + const day = new Date(today); + day.setDate(today.getDate() - i+1); + return day.toISOString().split('T')[0]; + }); + + const fetchDataPromises = lastTenDays.map(async (day) => { + const response = await axios.get(`http://localhost:5555/bill/billCountPerDay/${day}`); + return response.data.billCountSelectedDay; + + }); + + const fetchedData = await Promise.all(fetchDataPromises); + + setData(fetchedData.reverse()); + setLabels(lastTenDays.reverse()); + } catch (error) { + console.error('Error fetching data:', error.message); + } + }; + + fetchData(); + }, []); + + useEffect(() => { + const renderChart = () => { + if (chartRef.current) { + const chartInstance = chartRef.current.chartInstance; + if (chartInstance) { + chartInstance.destroy(); + } + + chartRef.current.chartInstance = new Chart(chartRef.current.getContext('2d'), { + type: 'line', + data: { + labels: labels, + datasets: [ + { + label: 'Bill Issued Per Day (customer count)', + data: data, + fill: false, + borderColor: 'rgba(75,192,192,1)', + }, + ], + }, + options: { + scales: { + x: { + type: 'category', + labels: labels, + }, + y: { + beginAtZero: true, + min: 0, + }, + }, + }, + }); + } + }; + + renderChart(); + }, [data, labels]); + + return ( +
+

Sales Data Variation


+ +
+ ); +}; + +export default Sales; + diff --git a/code/Software/Server/controllers/billController.js b/code/Software/Server/controllers/billController.js index 13266aa..96e0392 100644 --- a/code/Software/Server/controllers/billController.js +++ b/code/Software/Server/controllers/billController.js @@ -172,4 +172,28 @@ export async function getBillsToday(request, response) { } return ((currentValue - previousValue) / Math.abs(previousValue)) * 100; - } \ No newline at end of file + } + export async function getBillCountPerdate(request, response) { + try { + const { day } = request.params; + + // Parse the day parameter to a Date object + const selectedDay = new Date(day); + selectedDay.setHours(0, 0, 0, 0); // Set hours, minutes, seconds, and milliseconds to 0 + + // Get bills created on the selected day + const billsOnSelectedDay = await Bill.find({ + createdAt: { $gte: selectedDay, $lt: new Date(selectedDay.getTime() + 24 * 60 * 60 * 1000) }, + }); + + // Calculate the bill count for the selected day + const billCountSelectedDay = billsOnSelectedDay.length; + + response.status(200).json({ billCountSelectedDay }); + } catch (error) { + console.error(error.message); + response.status(500).json({ error: 'An error occurred while fetching the bill count for the selected day.' }); + } + } + + \ No newline at end of file diff --git a/code/Software/Server/controllers/itemPurchasedController.js b/code/Software/Server/controllers/itemPurchasedController.js index 6df84ed..07a00d0 100644 --- a/code/Software/Server/controllers/itemPurchasedController.js +++ b/code/Software/Server/controllers/itemPurchasedController.js @@ -214,29 +214,26 @@ export async function deleteItemsPurchasedById(request, response) { } export const getTotalProductQuantities = async () => { - try { - // Get the current date - const today = moment().startOf('day'); - - // Use Mongoose aggregation to sum the total quantities - const result = await ItemPurchased.aggregate([ - { - $match: { - createdAt: { $gte: today.toDate() }, - }, - }, - { - $group: { - _id: null, - totalQuantity: { $sum: "$quantity" }, - }, - }, - ]); - - return result.length > 0 ? result[0].totalQuantity : 0; - } catch (error) { - console.error("Error fetching total product sold:", error); - throw error; - } - }; - \ No newline at end of file + try { + + const today = new Date(); + today.setHours(0, 0, 0, 0); + + // Get items purchased today + const itemsPurchased = await ItemPurchased.find({ + createdAt: { $gte: today }, + }); + + // Calculate the total quantity by summing the quantity field + const totalQuantity = itemsPurchased.reduce( + (total, item) => total + item.quantity, + 0 + ); + + return totalQuantity; + } catch (error) { + + console.error("Error fetching total product sold:", error); + throw error; + } +}; diff --git a/code/Software/Server/routes/billRoute.js b/code/Software/Server/routes/billRoute.js index bc5a4ed..15aebbd 100644 --- a/code/Software/Server/routes/billRoute.js +++ b/code/Software/Server/routes/billRoute.js @@ -6,7 +6,8 @@ import { saveNewBill, updateBill, deleteBillById, - getBillsToday + getBillsToday, + getBillCountPerdate } from "../controllers/billController.js"; const router = express.Router(); @@ -14,6 +15,7 @@ const router = express.Router(); // Route for get bills today router.get("/today", getBillsToday); +router.get("/billCountPerDay/:day",getBillCountPerdate) // Route for get all bills router.get("/", getAllBills); diff --git a/code/Software/Server/routes/itemPurchasedRoute.js b/code/Software/Server/routes/itemPurchasedRoute.js index 4155eeb..681c22a 100644 --- a/code/Software/Server/routes/itemPurchasedRoute.js +++ b/code/Software/Server/routes/itemPurchasedRoute.js @@ -20,7 +20,8 @@ router.use(cors()); // Route for get total sale today router.get("/saletoday", getProductsSoldToday); -router.get("/quantity", getTotalProductQuantities); +// Route for get total product quantities in today +router.get("/quantity/t", getTotalProductQuantities); // Route for get all purchased item router.get("/", getAllItemsPurchased);