From d9b6a593be91821e8432aea29f24546cbe49b469 Mon Sep 17 00:00:00 2001 From: ppsahu Date: Fri, 7 Mar 2025 22:09:20 -0800 Subject: [PATCH 001/236] created a new component material summary for phase 2 --- .../MaterialSummary/MaterialSummary.jsx | 364 ++++++++++++++++++ src/routes.js | 2 + 2 files changed, 366 insertions(+) create mode 100644 src/components/MaterialSummary/MaterialSummary.jsx diff --git a/src/components/MaterialSummary/MaterialSummary.jsx b/src/components/MaterialSummary/MaterialSummary.jsx new file mode 100644 index 0000000000..3694bf71ca --- /dev/null +++ b/src/components/MaterialSummary/MaterialSummary.jsx @@ -0,0 +1,364 @@ +"use client" + +import { useState, useEffect } from "react" +import { Chart as ChartJS, ArcElement, Tooltip, Legend } from "chart.js" +import { Pie } from "react-chartjs-2" + +// Register ChartJS components +ChartJS.register(ArcElement, Tooltip, Legend) + +// Mock data for projects and materials +const mockProjects = [ + { id: 1, name: "Office Building" }, + { id: 2, name: "Residential Complex" }, + { id: 3, name: "Shopping Mall" }, + { id: 4, name: "Highway Bridge" }, +] + +const materialTypes = [ + { id: 1, name: "All Materials" }, + { id: 2, name: "Wood" }, + { id: 3, name: "Concrete" }, + { id: 4, name: "Steel" }, +] + +// Mock data for material usage +const mockMaterialData = { + 1: { + // Office Building + all: { + available: 50, + used: 30, + wasted: 20, + lastWeekUsed: 25, + }, + wood: { + available: 20, + used: 15, + wasted: 5, + lastWeekUsed: 12, + }, + concrete: { + available: 15, + used: 10, + wasted: 5, + lastWeekUsed: 8, + }, + steel: { + available: 15, + used: 5, + wasted: 10, + lastWeekUsed: 5, + }, + }, + 2: { + // Residential Complex + all: { + available: 60, + used: 40, + wasted: 10, + lastWeekUsed: 30, + }, + wood: { + available: 25, + used: 20, + wasted: 5, + lastWeekUsed: 15, + }, + concrete: { + available: 20, + used: 15, + wasted: 2, + lastWeekUsed: 10, + }, + steel: { + available: 15, + used: 5, + wasted: 3, + lastWeekUsed: 5, + }, + }, + 3: { + // Shopping Mall + all: { + available: 70, + used: 45, + wasted: 15, + lastWeekUsed: 35, + }, + wood: { + available: 15, + used: 10, + wasted: 5, + lastWeekUsed: 8, + }, + concrete: { + available: 30, + used: 25, + wasted: 5, + lastWeekUsed: 20, + }, + steel: { + available: 25, + used: 10, + wasted: 5, + lastWeekUsed: 7, + }, + }, + 4: { + // Highway Bridge + all: { + available: 80, + used: 60, + wasted: 10, + lastWeekUsed: 50, + }, + wood: { + available: 10, + used: 5, + wasted: 2, + lastWeekUsed: 4, + }, + concrete: { + available: 40, + used: 35, + wasted: 5, + lastWeekUsed: 30, + }, + steel: { + available: 30, + used: 20, + wasted: 3, + lastWeekUsed: 16, + }, + }, +} + +// Chart colors - more distinct and vibrant +const chartColors = { + available: "#4BC0C0", // Teal + used: "#FF6384", // Pink + wasted: "#FFCE56", // Yellow +} + +export default function MaterialUsageDashboard() { + const [selectedProject, setSelectedProject] = useState(1) + const [selectedMaterial, setSelectedMaterial] = useState("all") + const [showIncreaseOnly, setShowIncreaseOnly] = useState(false) + const [chartData, setChartData] = useState(null) + const [loading, setLoading] = useState(false) + const [increasePercentage, setIncreasePercentage] = useState(0) + + // Update chart data when filters change + useEffect(() => { + setLoading(true) + + // Simulate API call delay + setTimeout(() => { + updateChartData() + setLoading(false) + }, 800) + }, [selectedProject, selectedMaterial, showIncreaseOnly]) + + const updateChartData = () => { + const projectData = mockMaterialData[selectedProject] + const materialData = projectData[selectedMaterial] + + // Calculate increase percentage + const increase = ((materialData.used - materialData.lastWeekUsed) / materialData.lastWeekUsed) * 100 + setIncreasePercentage(increase) + + // If "Increase Over Last Week" is selected and there's no increase, return empty data + if (showIncreaseOnly && increase <= 0) { + setChartData({ + labels: ["No increased usage"], + datasets: [ + { + data: [1], + backgroundColor: ["#e2e8f0"], + borderWidth: 0, + }, + ], + }) + return + } + + // Calculate total for percentages + const total = materialData.available + materialData.used + materialData.wasted + + // Generate more detailed colors based on material type + let colorPalette = [chartColors.available, chartColors.used, chartColors.wasted] + + // Add material-specific color variations + if (selectedMaterial === "wood") { + colorPalette = ["#36A2EB", "#9966FF", "#FF9F40"] // Blue, Purple, Orange + } else if (selectedMaterial === "concrete") { + colorPalette = ["#4BC0C0", "#FF6384", "#FFCE56"] // Teal, Pink, Yellow + } else if (selectedMaterial === "steel") { + colorPalette = ["#7ED2FA", "#FF8A80", "#A5D6A7"] // Light Blue, Light Red, Light Green + } + + // Prepare chart data + setChartData({ + labels: [ + `Available Materials: ${Math.round((materialData.available / total) * 100)}%`, + `Used Materials: ${Math.round((materialData.used / total) * 100)}%`, + `Wasted Materials: ${Math.round((materialData.wasted / total) * 100)}%`, + ], + datasets: [ + { + data: [materialData.available, materialData.used, materialData.wasted], + backgroundColor: colorPalette, + borderWidth: 1, + borderColor: "#ffffff", + }, + ], + }) + } + + return ( +
+

Material Usage Dashboard

+ +
+ {/* Filters Section */} +
+
+
+

Filters

+

Select options to filter the chart data

+
+
+ {/* Project Filter */} +
+ + +
+ + {/* Material Type Filter */} +
+ + +
+ + {/* Increase Over Last Week Filter */} +
+ setShowIncreaseOnly(e.target.checked)} + className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" + /> + +
+
+
+ + {/* Increase Counter */} + {increasePercentage !== 0 && ( +
+
+

Usage Trend

+
+
+ 0 ? "bg-green-100 text-green-800" : "bg-red-100 text-red-800" + }`} + > + {increasePercentage > 0 ? "↑" : "↓"} {Math.abs(increasePercentage).toFixed(1)}% + + + {increasePercentage > 0 ? "Increase in material usage" : "Decrease in material usage"} compared to + last week + +
+
+ )} +
+ + {/* Chart Section */} +
+
+
+

+ Material Usage Breakdown + {selectedMaterial !== "all" && + ` - ${selectedMaterial.charAt(0).toUpperCase() + selectedMaterial.slice(1)}`} +

+

{mockProjects.find((p) => p.id === selectedProject)?.name}

+
+
+ {loading ? ( +
+
+

Loading data...

+
+ ) : chartData ? ( +
+ { + const label = context.label || "" + const value = context.raw || 0 + return `${label} (${value} units)` + }, + }, + }, + }, + }} + /> +
+ ) : ( +

No data available

+ )} +
+
+
+
+
+ ) +} + diff --git a/src/routes.js b/src/routes.js index d955da7662..778d2c6d22 100644 --- a/src/routes.js +++ b/src/routes.js @@ -63,6 +63,7 @@ import ActivityList from './components/CommunityPortal/Activities/ActivityList'; import EPProtectedRoute from './components/common/EPDashboard/EPProtectedRoute'; import EPLogin from './components/EductionPortal/Login'; import EPDashboard from './components/EductionPortal'; +import MaterialSummary from './components/MaterialSummary/MaterialSummary' @@ -147,6 +148,7 @@ export default ( )} /> + From 09c059c45005d669dabc354335e53c542ceeb24a Mon Sep 17 00:00:00 2001 From: ppsahu Date: Tue, 1 Apr 2025 13:33:26 -0700 Subject: [PATCH 002/236] refined donut chart UI --- .../MaterialSummary/MaterialSummary.jsx | 379 +++++++++++++++++- 1 file changed, 376 insertions(+), 3 deletions(-) diff --git a/src/components/MaterialSummary/MaterialSummary.jsx b/src/components/MaterialSummary/MaterialSummary.jsx index 3694bf71ca..4220e62079 100644 --- a/src/components/MaterialSummary/MaterialSummary.jsx +++ b/src/components/MaterialSummary/MaterialSummary.jsx @@ -13,13 +13,22 @@ const mockProjects = [ { id: 2, name: "Residential Complex" }, { id: 3, name: "Shopping Mall" }, { id: 4, name: "Highway Bridge" }, + { id: 5, name: "Industrial Warehouse" }, + { id: 6, name: "School Building" }, + { id: 7, name: "Hospital Complex" }, + { id: 8, name: "Sports Stadium" }, ] +// Mock data for material types const materialTypes = [ { id: 1, name: "All Materials" }, { id: 2, name: "Wood" }, { id: 3, name: "Concrete" }, { id: 4, name: "Steel" }, + { id: 5, name: "Aluminum" }, + { id: 6, name: "Glass" }, + { id: 7, name: "Brick" }, + { id: 8, name: "Plastic" }, ] // Mock data for material usage @@ -50,6 +59,30 @@ const mockMaterialData = { wasted: 10, lastWeekUsed: 5, }, + aluminum: { + available: 10, + used: 7, + wasted: 3, + lastWeekUsed: 5, + }, + glass: { + available: 25, + used: 20, + wasted: 5, + lastWeekUsed: 15, + }, + brick: { + available: 5, + used: 3, + wasted: 2, + lastWeekUsed: 2, + }, + plastic: { + available: 12, + used: 8, + wasted: 4, + lastWeekUsed: 6, + }, }, 2: { // Residential Complex @@ -77,6 +110,30 @@ const mockMaterialData = { wasted: 3, lastWeekUsed: 5, }, + aluminum: { + available: 8, + used: 5, + wasted: 2, + lastWeekUsed: 4, + }, + glass: { + available: 18, + used: 15, + wasted: 3, + lastWeekUsed: 12, + }, + brick: { + available: 30, + used: 25, + wasted: 5, + lastWeekUsed: 20, + }, + plastic: { + available: 10, + used: 7, + wasted: 3, + lastWeekUsed: 5, + }, }, 3: { // Shopping Mall @@ -104,6 +161,30 @@ const mockMaterialData = { wasted: 5, lastWeekUsed: 7, }, + aluminum: { + available: 20, + used: 15, + wasted: 5, + lastWeekUsed: 10, + }, + glass: { + available: 35, + used: 30, + wasted: 5, + lastWeekUsed: 25, + }, + brick: { + available: 10, + used: 8, + wasted: 2, + lastWeekUsed: 6, + }, + plastic: { + available: 15, + used: 12, + wasted: 3, + lastWeekUsed: 10, + }, }, 4: { // Highway Bridge @@ -131,6 +212,234 @@ const mockMaterialData = { wasted: 3, lastWeekUsed: 16, }, + aluminum: { + available: 15, + used: 10, + wasted: 2, + lastWeekUsed: 8, + }, + glass: { + available: 5, + used: 3, + wasted: 1, + lastWeekUsed: 2, + }, + brick: { + available: 8, + used: 5, + wasted: 2, + lastWeekUsed: 4, + }, + plastic: { + available: 12, + used: 8, + wasted: 2, + lastWeekUsed: 6, + }, + }, + 5: { + // Industrial Warehouse + all: { + available: 90, + used: 70, + wasted: 15, + lastWeekUsed: 60, + }, + wood: { + available: 15, + used: 10, + wasted: 3, + lastWeekUsed: 8, + }, + concrete: { + available: 45, + used: 40, + wasted: 5, + lastWeekUsed: 35, + }, + steel: { + available: 40, + used: 35, + wasted: 5, + lastWeekUsed: 30, + }, + aluminum: { + available: 25, + used: 20, + wasted: 3, + lastWeekUsed: 15, + }, + glass: { + available: 10, + used: 8, + wasted: 2, + lastWeekUsed: 6, + }, + brick: { + available: 20, + used: 15, + wasted: 3, + lastWeekUsed: 12, + }, + plastic: { + available: 15, + used: 12, + wasted: 2, + lastWeekUsed: 10, + }, + }, + 6: { + // School Building + all: { + available: 65, + used: 50, + wasted: 10, + lastWeekUsed: 45, + }, + wood: { + available: 20, + used: 15, + wasted: 3, + lastWeekUsed: 12, + }, + concrete: { + available: 30, + used: 25, + wasted: 4, + lastWeekUsed: 20, + }, + steel: { + available: 15, + used: 12, + wasted: 2, + lastWeekUsed: 10, + }, + aluminum: { + available: 10, + used: 8, + wasted: 1, + lastWeekUsed: 7, + }, + glass: { + available: 25, + used: 20, + wasted: 3, + lastWeekUsed: 18, + }, + brick: { + available: 30, + used: 25, + wasted: 4, + lastWeekUsed: 22, + }, + plastic: { + available: 15, + used: 12, + wasted: 2, + lastWeekUsed: 10, + }, + }, + 7: { + // Hospital Complex + all: { + available: 85, + used: 70, + wasted: 12, + lastWeekUsed: 65, + }, + wood: { + available: 15, + used: 12, + wasted: 2, + lastWeekUsed: 10, + }, + concrete: { + available: 40, + used: 35, + wasted: 4, + lastWeekUsed: 32, + }, + steel: { + available: 30, + used: 25, + wasted: 3, + lastWeekUsed: 22, + }, + aluminum: { + available: 20, + used: 18, + wasted: 2, + lastWeekUsed: 15, + }, + glass: { + available: 30, + used: 25, + wasted: 3, + lastWeekUsed: 22, + }, + brick: { + available: 25, + used: 20, + wasted: 3, + lastWeekUsed: 18, + }, + plastic: { + available: 25, + used: 22, + wasted: 2, + lastWeekUsed: 20, + }, + }, + 8: { + // Sports Stadium + all: { + available: 100, + used: 85, + wasted: 15, + lastWeekUsed: 80, + }, + wood: { + available: 10, + used: 8, + wasted: 1, + lastWeekUsed: 7, + }, + concrete: { + available: 50, + used: 45, + wasted: 5, + lastWeekUsed: 42, + }, + steel: { + available: 45, + used: 40, + wasted: 4, + lastWeekUsed: 38, + }, + aluminum: { + available: 30, + used: 25, + wasted: 3, + lastWeekUsed: 22, + }, + glass: { + available: 20, + used: 18, + wasted: 2, + lastWeekUsed: 15, + }, + brick: { + available: 15, + used: 12, + wasted: 2, + lastWeekUsed: 10, + }, + plastic: { + available: 20, + used: 18, + wasted: 2, + lastWeekUsed: 15, + }, }, } @@ -160,6 +469,7 @@ export default function MaterialUsageDashboard() { }, 800) }, [selectedProject, selectedMaterial, showIncreaseOnly]) + // Update the updateChartData function to handle the new material types with appropriate colors const updateChartData = () => { const projectData = mockMaterialData[selectedProject] const materialData = projectData[selectedMaterial] @@ -196,6 +506,14 @@ export default function MaterialUsageDashboard() { colorPalette = ["#4BC0C0", "#FF6384", "#FFCE56"] // Teal, Pink, Yellow } else if (selectedMaterial === "steel") { colorPalette = ["#7ED2FA", "#FF8A80", "#A5D6A7"] // Light Blue, Light Red, Light Green + } else if (selectedMaterial === "aluminum") { + colorPalette = ["#B39DDB", "#E57373", "#81C784"] // Light Purple, Light Red, Light Green + } else if (selectedMaterial === "glass") { + colorPalette = ["#90CAF9", "#F48FB1", "#80DEEA"] // Light Blue, Light Pink, Light Cyan + } else if (selectedMaterial === "brick") { + colorPalette = ["#FFAB91", "#CE93D8", "#FFF59D"] // Light Orange, Light Purple, Light Yellow + } else if (selectedMaterial === "plastic") { + colorPalette = ["#80CBC4", "#F06292", "#FFD54F"] // Light Teal, Pink, Amber } // Prepare chart data @@ -216,6 +534,30 @@ export default function MaterialUsageDashboard() { }) } + // Function to add a title in the center of the donut chart + const plugins = [ + { + id: "donutTitle", + beforeDraw: (chart) => { + const width = chart.width + const height = chart.height + const ctx = chart.ctx + + ctx.restore() + const fontSize = (height / 180).toFixed(2) // Smaller font size + ctx.font = `${fontSize}em sans-serif` + ctx.textBaseline = "middle" + + const text = "Materials" + const textX = Math.round((width - ctx.measureText(text).width) / 2) + const textY = height / 2 + + ctx.fillText(text, textX, textY) + ctx.save() + }, + }, + ] + return (

Material Usage Dashboard

@@ -263,6 +605,10 @@ export default function MaterialUsageDashboard() { + + + +
@@ -316,26 +662,29 @@ export default function MaterialUsageDashboard() {

{mockProjects.find((p) => p.id === selectedProject)?.name}

-
+
{loading ? (

Loading data...

) : chartData ? ( -
+
) : (

No data available

)}
+ {/* Material Breakdown List */} + {chartData && !loading && ( +
+

Material Breakdown

+
+ {chartData.datasets[0].data.map((value, index) => { + const label = chartData.labels[index].split(":")[0] + const color = chartData.datasets[0].backgroundColor[index] + return ( +
+
+
+

{label}

+

+ {value} units +

+
+
+ ) + })} +
+
+ )}
From ca80aa9e3bc4707a0f54295708d1dda6eff9d9a8 Mon Sep 17 00:00:00 2001 From: ppsahu Date: Fri, 4 Apr 2025 22:33:04 -0700 Subject: [PATCH 003/236] refined the UI and updated packages --- package-lock.json | 12 +- package.json | 4 +- .../MaterialSummary/MaterialSummary.jsx | 220 +++++++++--------- 3 files changed, 124 insertions(+), 112 deletions(-) diff --git a/package-lock.json b/package-lock.json index f34f51d7aa..67552c3a7b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14650,9 +14650,9 @@ "dev": true }, "chart.js": { - "version": "4.4.7", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.7.tgz", - "integrity": "sha512-pwkcKfdzTMAU/+jNosKhNL2bHtJc/sSmYgVbuGTEDhzkrhmyihmP7vUc/5ZK9WopidMDHNe3Wm7jOd/WhuHWuw==", + "version": "4.4.8", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.8.tgz", + "integrity": "sha512-IkGZlVpXP+83QpMm4uxEiGqSI7jFizwVtF3+n5Pc3k7sMO+tkd0qxh2OzLhenM0K80xtmAONWGBn082EiBQSDA==", "requires": { "@kurkle/color": "^0.3.0" } @@ -29198,9 +29198,9 @@ } }, "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==" + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.3.0.tgz", + "integrity": "sha512-UfZZFnDsERI3c3CZGxzvNJd02SHjaSJ8kgW1djn65H1KK8rehwTjyrRKOG3VTMG8wtHZ5rgAO5oTHtHi9GCCmw==" }, "react-circular-progressbar": { "version": "2.1.0", diff --git a/package.json b/package.json index 4b673f57c4..daded1fa5c 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "axios": "^0.21.2", "axios-mock-adapter": "^1.22.0", "bootstrap": "^4.5.3", - "chart.js": "^4.4.7", + "chart.js": "^4.4.8", "chartjs-plugin-datalabels": "^2.2.0", "classnames": "^2.2.6", "d3": "^7.8.5", @@ -41,7 +41,7 @@ "react-autosuggest": "^10.1.0", "react-beautiful-dnd": "^13.1.1", "react-bootstrap": "^1.0.1", - "react-chartjs-2": "^5.2.0", + "react-chartjs-2": "^5.3.0", "react-circular-progressbar": "^2.1.0", "react-collapsible": "^2.10.0", "react-datepicker": "^3.7.0", diff --git a/src/components/MaterialSummary/MaterialSummary.jsx b/src/components/MaterialSummary/MaterialSummary.jsx index 4220e62079..ca2037aec6 100644 --- a/src/components/MaterialSummary/MaterialSummary.jsx +++ b/src/components/MaterialSummary/MaterialSummary.jsx @@ -1,35 +1,35 @@ -"use client" +'use client'; -import { useState, useEffect } from "react" -import { Chart as ChartJS, ArcElement, Tooltip, Legend } from "chart.js" -import { Pie } from "react-chartjs-2" +import { useState, useEffect } from 'react'; +import { Chart as ChartJS, ArcElement, Tooltip, Legend } from 'chart.js'; +import { Pie } from 'react-chartjs-2'; // Register ChartJS components -ChartJS.register(ArcElement, Tooltip, Legend) +ChartJS.register(ArcElement, Tooltip, Legend); // Mock data for projects and materials const mockProjects = [ - { id: 1, name: "Office Building" }, - { id: 2, name: "Residential Complex" }, - { id: 3, name: "Shopping Mall" }, - { id: 4, name: "Highway Bridge" }, - { id: 5, name: "Industrial Warehouse" }, - { id: 6, name: "School Building" }, - { id: 7, name: "Hospital Complex" }, - { id: 8, name: "Sports Stadium" }, -] + { id: 1, name: 'Office Building' }, + { id: 2, name: 'Residential Complex' }, + { id: 3, name: 'Shopping Mall' }, + { id: 4, name: 'Highway Bridge' }, + { id: 5, name: 'Industrial Warehouse' }, + { id: 6, name: 'School Building' }, + { id: 7, name: 'Hospital Complex' }, + { id: 8, name: 'Sports Stadium' }, +]; // Mock data for material types const materialTypes = [ - { id: 1, name: "All Materials" }, - { id: 2, name: "Wood" }, - { id: 3, name: "Concrete" }, - { id: 4, name: "Steel" }, - { id: 5, name: "Aluminum" }, - { id: 6, name: "Glass" }, - { id: 7, name: "Brick" }, - { id: 8, name: "Plastic" }, -] + { id: 1, name: 'All Materials' }, + { id: 2, name: 'Wood' }, + { id: 3, name: 'Concrete' }, + { id: 4, name: 'Steel' }, + { id: 5, name: 'Aluminum' }, + { id: 6, name: 'Glass' }, + { id: 7, name: 'Brick' }, + { id: 8, name: 'Plastic' }, +]; // Mock data for material usage const mockMaterialData = { @@ -441,79 +441,80 @@ const mockMaterialData = { lastWeekUsed: 15, }, }, -} +}; // Chart colors - more distinct and vibrant const chartColors = { - available: "#4BC0C0", // Teal - used: "#FF6384", // Pink - wasted: "#FFCE56", // Yellow -} + available: '#4BC0C0', // Teal + used: '#FF6384', // Pink + wasted: '#FFCE56', // Yellow +}; export default function MaterialUsageDashboard() { - const [selectedProject, setSelectedProject] = useState(1) - const [selectedMaterial, setSelectedMaterial] = useState("all") - const [showIncreaseOnly, setShowIncreaseOnly] = useState(false) - const [chartData, setChartData] = useState(null) - const [loading, setLoading] = useState(false) - const [increasePercentage, setIncreasePercentage] = useState(0) + const [selectedProject, setSelectedProject] = useState(1); + const [selectedMaterial, setSelectedMaterial] = useState('all'); + const [showIncreaseOnly, setShowIncreaseOnly] = useState(false); + const [chartData, setChartData] = useState(null); + const [loading, setLoading] = useState(false); + const [increasePercentage, setIncreasePercentage] = useState(0); // Update chart data when filters change useEffect(() => { - setLoading(true) + setLoading(true); // Simulate API call delay setTimeout(() => { - updateChartData() - setLoading(false) - }, 800) - }, [selectedProject, selectedMaterial, showIncreaseOnly]) + updateChartData(); + setLoading(false); + }, 800); + }, [selectedProject, selectedMaterial, showIncreaseOnly]); // Update the updateChartData function to handle the new material types with appropriate colors const updateChartData = () => { - const projectData = mockMaterialData[selectedProject] - const materialData = projectData[selectedMaterial] + const projectData = mockMaterialData[selectedProject]; + const materialData = projectData[selectedMaterial]; // Calculate increase percentage - const increase = ((materialData.used - materialData.lastWeekUsed) / materialData.lastWeekUsed) * 100 - setIncreasePercentage(increase) + const increase = + ((materialData.used - materialData.lastWeekUsed) / materialData.lastWeekUsed) * 100; + setIncreasePercentage(increase); // If "Increase Over Last Week" is selected and there's no increase, return empty data if (showIncreaseOnly && increase <= 0) { setChartData({ - labels: ["No increased usage"], + labels: ['No increased usage'], datasets: [ { data: [1], - backgroundColor: ["#e2e8f0"], + backgroundColor: ['#e2e8f0'], borderWidth: 0, }, ], - }) - return + }); + return; } // Calculate total for percentages - const total = materialData.available + materialData.used + materialData.wasted + const total = materialData.available + materialData.used + materialData.wasted; // Generate more detailed colors based on material type - let colorPalette = [chartColors.available, chartColors.used, chartColors.wasted] + let colorPalette = [chartColors.available, chartColors.used, chartColors.wasted]; // Add material-specific color variations - if (selectedMaterial === "wood") { - colorPalette = ["#36A2EB", "#9966FF", "#FF9F40"] // Blue, Purple, Orange - } else if (selectedMaterial === "concrete") { - colorPalette = ["#4BC0C0", "#FF6384", "#FFCE56"] // Teal, Pink, Yellow - } else if (selectedMaterial === "steel") { - colorPalette = ["#7ED2FA", "#FF8A80", "#A5D6A7"] // Light Blue, Light Red, Light Green - } else if (selectedMaterial === "aluminum") { - colorPalette = ["#B39DDB", "#E57373", "#81C784"] // Light Purple, Light Red, Light Green - } else if (selectedMaterial === "glass") { - colorPalette = ["#90CAF9", "#F48FB1", "#80DEEA"] // Light Blue, Light Pink, Light Cyan - } else if (selectedMaterial === "brick") { - colorPalette = ["#FFAB91", "#CE93D8", "#FFF59D"] // Light Orange, Light Purple, Light Yellow - } else if (selectedMaterial === "plastic") { - colorPalette = ["#80CBC4", "#F06292", "#FFD54F"] // Light Teal, Pink, Amber + if (selectedMaterial === 'wood') { + colorPalette = ['#36A2EB', '#9966FF', '#FF9F40']; // Blue, Purple, Orange + } else if (selectedMaterial === 'concrete') { + colorPalette = ['#4BC0C0', '#FF6384', '#FFCE56']; // Teal, Pink, Yellow + } else if (selectedMaterial === 'steel') { + colorPalette = ['#7ED2FA', '#FF8A80', '#A5D6A7']; // Light Blue, Light Red, Light Green + } else if (selectedMaterial === 'aluminum') { + colorPalette = ['#B39DDB', '#E57373', '#81C784']; // Light Purple, Light Red, Light Green + } else if (selectedMaterial === 'glass') { + colorPalette = ['#90CAF9', '#F48FB1', '#80DEEA']; // Light Blue, Light Pink, Light Cyan + } else if (selectedMaterial === 'brick') { + colorPalette = ['#FFAB91', '#CE93D8', '#FFF59D']; // Light Orange, Light Purple, Light Yellow + } else if (selectedMaterial === 'plastic') { + colorPalette = ['#80CBC4', '#F06292', '#FFD54F']; // Light Teal, Pink, Amber } // Prepare chart data @@ -528,35 +529,35 @@ export default function MaterialUsageDashboard() { data: [materialData.available, materialData.used, materialData.wasted], backgroundColor: colorPalette, borderWidth: 1, - borderColor: "#ffffff", + borderColor: '#ffffff', }, ], - }) - } + }); + }; // Function to add a title in the center of the donut chart const plugins = [ { - id: "donutTitle", - beforeDraw: (chart) => { - const width = chart.width - const height = chart.height - const ctx = chart.ctx + id: 'donutTitle', + beforeDraw: chart => { + const width = chart.width; + const height = chart.height; + const ctx = chart.ctx; - ctx.restore() - const fontSize = (height / 180).toFixed(2) // Smaller font size - ctx.font = `${fontSize}em sans-serif` - ctx.textBaseline = "middle" + ctx.restore(); + const fontSize = (height / 180).toFixed(2); // Smaller font size + ctx.font = `${fontSize}em sans-serif`; + ctx.textBaseline = 'middle'; - const text = "Materials" - const textX = Math.round((width - ctx.measureText(text).width) / 2) - const textY = height / 2 + const text = 'Materials'; + const textX = Math.round((width - ctx.measureText(text).width) / 2); + const textY = height / 2; - ctx.fillText(text, textX, textY) - ctx.save() + ctx.fillText(text, textX, textY); + ctx.save(); }, }, - ] + ]; return (
@@ -580,9 +581,9 @@ export default function MaterialUsageDashboard() { id="project" className="w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" value={selectedProject} - onChange={(e) => setSelectedProject(Number.parseInt(e.target.value))} + onChange={e => setSelectedProject(Number.parseInt(e.target.value))} > - {mockProjects.map((project) => ( + {mockProjects.map(project => ( @@ -599,7 +600,7 @@ export default function MaterialUsageDashboard() { id="material" className="w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" value={selectedMaterial} - onChange={(e) => setSelectedMaterial(e.target.value)} + onChange={e => setSelectedMaterial(e.target.value)} > @@ -618,7 +619,7 @@ export default function MaterialUsageDashboard() { type="checkbox" id="increase" checked={showIncreaseOnly} - onChange={(e) => setShowIncreaseOnly(e.target.checked)} + onChange={e => setShowIncreaseOnly(e.target.checked)} className="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" />
@@ -657,10 +662,12 @@ export default function MaterialUsageDashboard() {

Material Usage Breakdown - {selectedMaterial !== "all" && + {selectedMaterial !== 'all' && ` - ${selectedMaterial.charAt(0).toUpperCase() + selectedMaterial.slice(1)}`}

-

{mockProjects.find((p) => p.id === selectedProject)?.name}

+

+ {mockProjects.find(p => p.id === selectedProject)?.name} +

{loading ? ( @@ -675,10 +682,10 @@ export default function MaterialUsageDashboard() { options={{ responsive: true, maintainAspectRatio: true, - cutout: "50%", + cutout: '50%', plugins: { legend: { - position: "bottom", + position: 'bottom', labels: { padding: 10, font: { @@ -689,10 +696,10 @@ export default function MaterialUsageDashboard() { }, tooltip: { callbacks: { - label: (context) => { - const label = context.label || "" - const value = context.raw || 0 - return `${label} (${value} units)` + label: context => { + const label = context.label || ''; + const value = context.raw || 0; + return `${label} (${value} units)`; }, }, }, @@ -711,11 +718,17 @@ export default function MaterialUsageDashboard() {

Material Breakdown

{chartData.datasets[0].data.map((value, index) => { - const label = chartData.labels[index].split(":")[0] - const color = chartData.datasets[0].backgroundColor[index] + const label = chartData.labels[index].split(':')[0]; + const color = chartData.datasets[0].backgroundColor[index]; return ( -
-
+
+

{label}

@@ -723,7 +736,7 @@ export default function MaterialUsageDashboard() {

- ) + ); })}
@@ -732,6 +745,5 @@ export default function MaterialUsageDashboard() {
- ) + ); } - From 7ebc612cff19f78b8f7a3a06cbb0c0713227fb82 Mon Sep 17 00:00:00 2001 From: ppsahu Date: Fri, 11 Apr 2025 22:45:25 -0700 Subject: [PATCH 004/236] fixed lint issues --- .../MaterialSummary/MaterialSummary.jsx | 49 +++++++------------ 1 file changed, 17 insertions(+), 32 deletions(-) diff --git a/src/components/MaterialSummary/MaterialSummary.jsx b/src/components/MaterialSummary/MaterialSummary.jsx index ca2037aec6..0ea545d3de 100644 --- a/src/components/MaterialSummary/MaterialSummary.jsx +++ b/src/components/MaterialSummary/MaterialSummary.jsx @@ -19,18 +19,6 @@ const mockProjects = [ { id: 8, name: 'Sports Stadium' }, ]; -// Mock data for material types -const materialTypes = [ - { id: 1, name: 'All Materials' }, - { id: 2, name: 'Wood' }, - { id: 3, name: 'Concrete' }, - { id: 4, name: 'Steel' }, - { id: 5, name: 'Aluminum' }, - { id: 6, name: 'Glass' }, - { id: 7, name: 'Brick' }, - { id: 8, name: 'Plastic' }, -]; - // Mock data for material usage const mockMaterialData = { 1: { @@ -458,17 +446,6 @@ export default function MaterialUsageDashboard() { const [loading, setLoading] = useState(false); const [increasePercentage, setIncreasePercentage] = useState(0); - // Update chart data when filters change - useEffect(() => { - setLoading(true); - - // Simulate API call delay - setTimeout(() => { - updateChartData(); - setLoading(false); - }, 800); - }, [selectedProject, selectedMaterial, showIncreaseOnly]); - // Update the updateChartData function to handle the new material types with appropriate colors const updateChartData = () => { const projectData = mockMaterialData[selectedProject]; @@ -535,14 +512,25 @@ export default function MaterialUsageDashboard() { }); }; + // Update chart data when filters change + useEffect(() => { + setLoading(true); + + // Simulate API call delay + setTimeout(() => { + updateChartData(); + setLoading(false); + }, 800); + }, [selectedProject, selectedMaterial, showIncreaseOnly]); + // Function to add a title in the center of the donut chart const plugins = [ { id: 'donutTitle', beforeDraw: chart => { - const width = chart.width; - const height = chart.height; - const ctx = chart.ctx; + const { width } = chart; + const { height } = chart; + const { ctx } = chart; ctx.restore(); const fontSize = (height / 180).toFixed(2); // Smaller font size @@ -581,7 +569,7 @@ export default function MaterialUsageDashboard() { id="project" className="w-full p-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" value={selectedProject} - onChange={e => setSelectedProject(Number.parseInt(e.target.value))} + onChange={e => setSelectedProject(Number(e.target.value))} > {mockProjects.map(project => (