diff --git a/src/components/BMDashboard/WeeklyProjectSummary/ToolStatusDonutChart/ToolStatusDonutChart.jsx b/src/components/BMDashboard/WeeklyProjectSummary/ToolStatusDonutChart/ToolStatusDonutChart.jsx index 484c699aaf..e86293bb02 100644 --- a/src/components/BMDashboard/WeeklyProjectSummary/ToolStatusDonutChart/ToolStatusDonutChart.jsx +++ b/src/components/BMDashboard/WeeklyProjectSummary/ToolStatusDonutChart/ToolStatusDonutChart.jsx @@ -34,7 +34,16 @@ const renderCustomizedLabel = ({ cx, cy, midAngle, outerRadius, percent, width } }; // Custom tooltip component -const CustomTooltip = ({ active, payload, total, hasNoData, toolName, projectName, toolId }) => { +const CustomTooltip = ({ + active, + payload, + total, + hasNoData, + toolName, + projectName, + toolId, + darkMode, +}) => { if (!active || !payload || !payload.length) { return null; } @@ -44,8 +53,8 @@ const CustomTooltip = ({ active, payload, total, hasNoData, toolName, projectNam return (
-
📊 No Tools Match
-
+
+ 📊 No Tools Match +
+
No tools match the selected combination
@@ -66,8 +77,8 @@ const CustomTooltip = ({ active, payload, total, hasNoData, toolName, projectNam return (
-
{toolName}
-
❌ Not used in this project
+
{toolName}
+
+ ❌ Not used in this project +
); } @@ -87,8 +100,8 @@ const CustomTooltip = ({ active, payload, total, hasNoData, toolName, projectNam return (
-
+
{toolName || 'All Tools'}
-
+
Count: {data.value}
-
+
Percentage: {percentage}%
@@ -316,6 +329,7 @@ export default function ToolStatusDonutChart() { hasNoData={hasNoData} toolName={toolName} toolId={toolId} + darkMode={darkMode} /> } cursor={false} diff --git a/src/components/BMDashboard/WeeklyProjectSummary/ToolStatusDonutChart/ToolStatusDonutChart.module.css b/src/components/BMDashboard/WeeklyProjectSummary/ToolStatusDonutChart/ToolStatusDonutChart.module.css index 988ced2c86..e3d41e6631 100644 --- a/src/components/BMDashboard/WeeklyProjectSummary/ToolStatusDonutChart/ToolStatusDonutChart.module.css +++ b/src/components/BMDashboard/WeeklyProjectSummary/ToolStatusDonutChart/ToolStatusDonutChart.module.css @@ -46,6 +46,40 @@ color: var(--donut-text-color); } +.toolDonutWrapper select { + width: 220px; + margin-top: 8px; + padding: 10px 14px; + border: 1px solid #d1d5db; + border-radius: 14px; + background-color: #ffffff; + color: #111827; + font-size: 20px; + line-height: 1.2; + outline: none; +} + +.toolDonutWrapper select:focus { + border-color: #3b82f6; + box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2); +} + +.toolDonutWrapperDark select { + background-color: #253342; + color: #ffffff; + border-color: #3a506b; +} + +.toolDonutWrapperDark select:focus { + border-color: #5b89c2; + box-shadow: 0 0 0 2px rgba(91, 137, 194, 0.25); +} + +.toolDonutWrapperDark select option { + background-color: #253342; + color: #ffffff; +} + .filterValue { font-size: 14px; color: #888; diff --git a/src/components/BMDashboard/WeeklyProjectSummary/Tools/ToolsAvailabilityPage.jsx b/src/components/BMDashboard/WeeklyProjectSummary/Tools/ToolsAvailabilityPage.jsx index 5dd1d9f1d2..da5183ed3a 100644 --- a/src/components/BMDashboard/WeeklyProjectSummary/Tools/ToolsAvailabilityPage.jsx +++ b/src/components/BMDashboard/WeeklyProjectSummary/Tools/ToolsAvailabilityPage.jsx @@ -59,51 +59,6 @@ function ToolsAvailabilityPage() { setEndDate(''); }; - // Apply dark mode styles to document body when in dark mode - useEffect(() => { - if (darkMode) { - document.body.classList.add('dark-mode-body'); - } else { - document.body.classList.remove('dark-mode-body'); - } - - // Add dark mode CSS - if (!document.getElementById('dark-mode-styles')) { - const styleElement = document.createElement('style'); - styleElement.id = 'dark-mode-styles'; - styleElement.innerHTML = ` - .dark-mode-body .tools-availability-page { - background-color: #1e2736 !important; - color: #e0e0e0 !important; - } - .dark-mode-body .tools-availability-content { - background-color: #1e2736 !important; - color: #e0e0e0 !important; - } - .dark-mode-body .recharts-wrapper, - .dark-mode-body .recharts-surface { - background-color: #1e2736 !important; - } - .dark-mode-body .recharts-layer { - background-color: #1e2736 !important; - } - `; - document.head.appendChild(styleElement); - } - - return () => { - // Cleanup - document.body.classList.remove('dark-mode-body'); - }; - }, [darkMode]); - - const darkModeStyles = darkMode - ? { - backgroundColor: '#1e2736', - color: '#e0e0e0', - } - : {}; - // Render project selection based on loading and error states const renderProjectSelection = () => { if (loading) { @@ -130,16 +85,16 @@ function ToolsAvailabilityPage() { ? { control: baseStyles => ({ ...baseStyles, - backgroundColor: '#2c3344', - borderColor: '#364156', + backgroundColor: '#253342', + borderColor: '#3a506b', }), menu: baseStyles => ({ ...baseStyles, - backgroundColor: '#2c3344', + backgroundColor: '#253342', }), option: (baseStyles, state) => ({ ...baseStyles, - backgroundColor: state.isFocused ? '#364156' : '#2c3344', + backgroundColor: state.isFocused ? '#3a506b' : '#253342', color: '#e0e0e0', }), singleValue: baseStyles => ({ @@ -158,11 +113,8 @@ function ToolsAvailabilityPage() { }; return ( -
-
+
+
diff --git a/src/components/BMDashboard/WeeklyProjectSummary/Tools/ToolsAvailabilityPage.module.css b/src/components/BMDashboard/WeeklyProjectSummary/Tools/ToolsAvailabilityPage.module.css index a911dde851..1b9ba8ff2d 100644 --- a/src/components/BMDashboard/WeeklyProjectSummary/Tools/ToolsAvailabilityPage.module.css +++ b/src/components/BMDashboard/WeeklyProjectSummary/Tools/ToolsAvailabilityPage.module.css @@ -1,24 +1,45 @@ .tools-availability-page { + --tools-bg: #ffffff; + --tools-text: #000000; + --tools-card: #fafafa; + --tools-section: #ffffff; + --tools-border: #d1d5db; + --tools-input-bg: #ffffff; + --tools-input-border: #d1d5db; + --tools-select-bg: #ffffff; + --tools-select-hover: #f3f4f6; + padding: 24px; min-height: 100vh; - background-color: var(--bg-color); + background-color: var(--tools-bg); + color: var(--tools-text); + transition: background-color 0.25s ease, color 0.25s ease; } .tools-availability-page.dark-mode { - background-color: var(--dark-bg); + --tools-bg: #1b2a41; + --tools-text: #ffffff; + --tools-card: #2b3e59; + --tools-section: #253342; + --tools-border: #3a506b; + --tools-input-bg: #253342; + --tools-input-border: #3a506b; + --tools-select-bg: #253342; + --tools-select-hover: #3a506b; } .tools-availability-content { max-width: 1200px; margin: 0 auto; padding: 24px; - background-color: var(--card-bg); + background-color: var(--tools-section); border-radius: 8px; - box-shadow: 0 2px 5px var(--card-shadow); + box-shadow: 0 2px 5px var(--card-shadow, rgba(0,0,0,0.1)); } .tools-availability-page.dark-mode .tools-availability-content { - background-color: var(--section-bg); + background-color: var(--tools-section); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4); } /* Filter section styling */ @@ -79,8 +100,8 @@ /* Dark mode date picker styling */ .tools-availability-page.dark-mode .date-picker { - background-color: #2c3344; - border-color: #364156; + background-color: var(--tools-input-bg); + border-color: var(--tools-input-border); color: #e0e0e0; } @@ -90,7 +111,7 @@ } .tools-availability-page.dark-mode .date-picker:hover { - border-color: #4b5563; + border-color: var(--tools-input-border); } /* "to" text styling */ @@ -184,9 +205,9 @@ } .tools-availability-page.dark-mode .select-loading { - background-color: #2c3344; + background-color: var(--tools-input-bg); color: #9ca3af; - border-color: #364156; + border-color: var(--tools-input-border); } .tools-availability-page.dark-mode .select-error { diff --git a/src/components/BMDashboard/WeeklyProjectSummary/Tools/ToolsHorizontalBarChart.jsx b/src/components/BMDashboard/WeeklyProjectSummary/Tools/ToolsHorizontalBarChart.jsx index 57451e1889..b90c703083 100644 --- a/src/components/BMDashboard/WeeklyProjectSummary/Tools/ToolsHorizontalBarChart.jsx +++ b/src/components/BMDashboard/WeeklyProjectSummary/Tools/ToolsHorizontalBarChart.jsx @@ -1,14 +1,12 @@ import { useEffect, useState } from 'react'; +import { useSelector } from 'react-redux'; import Select from 'react-select'; import { BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer, CartesianGrid } from 'recharts'; import axios from 'axios'; import { ENDPOINTS } from '../../../../utils/URL'; import styles from './ToolsHorizontalBarChart.module.css'; -// No mock data - use real backend data only - -// Custom tooltip component -function CustomTooltip({ active, payload, label }) { +function CustomTooltip({ active, payload, label, darkMode }) { if (!active || !payload || !payload.length) { return null; } @@ -16,19 +14,41 @@ function CustomTooltip({ active, payload, label }) { const total = payload.reduce((sum, entry) => sum + (entry.value || 0), 0); return ( -
-

{label}

+
+

+ {label} +

{payload.map((entry, index) => (

{entry.name}: {entry.value}

))} -

Total: {total}

+

+ Total: {total} +

); } -function ToolsHorizontalBarChart({ darkMode }) { +function ToolsHorizontalBarChart({ darkMode: darkModeProp }) { + const reduxDarkMode = useSelector(state => state.theme.darkMode); + const darkMode = typeof darkModeProp === 'boolean' ? darkModeProp : reduxDarkMode; + const [data, setData] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); @@ -36,8 +56,8 @@ function ToolsHorizontalBarChart({ darkMode }) { const [selectedProject, setSelectedProject] = useState(null); const [allTools, setAllTools] = useState([]); const [selectedTools, setSelectedTools] = useState([]); + const [isPreviewHovering, setIsPreviewHovering] = useState(false); - // Date range state for filters const currentDate = new Date(); const startDate12MonthsAgo = new Date(currentDate.getFullYear() - 1, currentDate.getMonth(), 1); const endOfCurrentMonth = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 0); @@ -45,41 +65,41 @@ function ToolsHorizontalBarChart({ darkMode }) { const [startDate, setStartDate] = useState(startDate12MonthsAgo.toISOString().split('T')[0]); const [endDate, setEndDate] = useState(endOfCurrentMonth.toISOString().split('T')[0]); - // Date range logging removed for production - - // Fetch projects list useEffect(() => { const fetchProjects = async () => { try { const projectsResponse = await axios.get(ENDPOINTS.TOOLS_AVAILABILITY_PROJECTS); const projects = projectsResponse.data; - // Projects fetched successfully - if (projects && projects.length > 0) { const projectOptions = projects.map(project => ({ value: project.projectId, - label: project.projectId, // Use project ID as the visible label + label: project.projectId, })); setAllProjects(projectOptions); - - // Auto-select first project for initial display - setSelectedProject(projectOptions[0]); + setSelectedProject(null); + } else { + setAllProjects([]); + setSelectedProject(null); } } catch (err) { setError('Failed to load projects'); + setAllProjects([]); + setSelectedProject(null); + } finally { + setLoading(false); } }; fetchProjects(); }, []); - // Fetch tools data when project or date range changes useEffect(() => { const fetchToolsData = async () => { if (!selectedProject?.value) { setData([]); setAllTools([]); + setError(null); setLoading(false); return; } @@ -90,12 +110,10 @@ function ToolsHorizontalBarChart({ darkMode }) { const projectId = selectedProject.value; - // 1. Fetch unfiltered dataset (for fallback + full tool list) const toolsResponseNoFilter = await axios.get( ENDPOINTS.TOOLS_AVAILABILITY_BY_PROJECT(projectId), ); - // 2. Fetch filtered dataset const toolsResponse = await axios.get( ENDPOINTS.TOOLS_AVAILABILITY_BY_PROJECT(projectId, startDate, endDate), ); @@ -103,16 +121,14 @@ function ToolsHorizontalBarChart({ darkMode }) { const toolsDataFiltered = toolsResponse.data; const toolsDataUnfiltered = toolsResponseNoFilter.data; - // Use filtered data if available; otherwise fallback to unfiltered const toolsData = toolsDataFiltered && toolsDataFiltered.length > 0 ? toolsDataFiltered : toolsDataUnfiltered; - // Extract unique tool names for dropdown if (toolsDataUnfiltered?.length > 0) { const uniqueTools = [...new Set(toolsDataUnfiltered.map(item => item.toolName))] - .filter(Boolean) // remove null/undefined + .filter(Boolean) .map(tool => ({ label: tool, value: tool, @@ -123,14 +139,12 @@ function ToolsHorizontalBarChart({ darkMode }) { setAllTools([]); } - // If tool filters active → apply them let filteredForChart = toolsData; if (selectedTools.length > 0) { const selectedNames = selectedTools.map(t => t.value); filteredForChart = toolsData.filter(item => selectedNames.includes(item.toolName)); } - // ✅ Format chart data if (filteredForChart.length > 0) { const formattedData = filteredForChart.map(item => ({ name: item.toolName || 'Unknown Tool', @@ -138,13 +152,11 @@ function ToolsHorizontalBarChart({ darkMode }) { needsReplacement: item.needsReplacement || 0, yetToReceive: item.yetToReceive || 0, })); - setData(formattedData); } else { setData([]); } } catch (err) { - console.error(err); setError('Failed to load tools data'); setData([]); setAllTools([]); @@ -156,7 +168,6 @@ function ToolsHorizontalBarChart({ darkMode }) { fetchToolsData(); }, [selectedProject, startDate, endDate, selectedTools]); - // Filter handlers const handleToolChange = selectedOption => setSelectedTools(selectedOption || []); const handleProjectChange = selectedOption => { @@ -172,59 +183,47 @@ function ToolsHorizontalBarChart({ darkMode }) { }; const handleClearDates = () => { - const currentDate = new Date(); - const startDate12MonthsAgo = new Date(currentDate.getFullYear() - 1, currentDate.getMonth(), 1); - const endOfCurrentMonth = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 0); - setStartDate(startDate12MonthsAgo.toISOString().split('T')[0]); - setEndDate(endOfCurrentMonth.toISOString().split('T')[0]); + const now = new Date(); + const start = new Date(now.getFullYear() - 1, now.getMonth(), 1); + const end = new Date(now.getFullYear(), now.getMonth() + 1, 0); + setStartDate(start.toISOString().split('T')[0]); + setEndDate(end.toISOString().split('T')[0]); + setSelectedProject(null); }; - if (loading) { - return ( -
-

Tools by Availability

-
Loading...
-
- ); - } - - if (error && data.length === 0) { - return ( -
-

Tools by Availability

-
{error}
-
- ); - } - const darkSelectStyles = { control: base => ({ ...base, - backgroundColor: '#2c3344', - borderColor: '#364156', + backgroundColor: '#253342', + borderColor: '#3a506b', minHeight: '32px', fontSize: '12px', }), menu: base => ({ ...base, - backgroundColor: '#2c3344', + backgroundColor: '#253342', fontSize: '12px', }), option: (base, state) => ({ ...base, - backgroundColor: state.isFocused ? '#364156' : '#2c3344', + backgroundColor: state.isFocused ? '#3a506b' : '#253342', color: '#e0e0e0', fontSize: '12px', }), multiValue: base => ({ ...base, - backgroundColor: '#364156', + backgroundColor: '#3a506b', }), multiValueLabel: base => ({ ...base, color: '#e0e0e0', fontSize: '12px', }), + singleValue: base => ({ + ...base, + color: '#e0e0e0', + fontSize: '12px', + }), placeholder: base => ({ ...base, color: '#aaaaaa', @@ -254,6 +253,10 @@ function ToolsHorizontalBarChart({ darkMode }) { ...base, fontSize: '12px', }), + singleValue: base => ({ + ...base, + fontSize: '12px', + }), placeholder: base => ({ ...base, fontSize: '12px', @@ -268,7 +271,6 @@ function ToolsHorizontalBarChart({ darkMode }) { >

Tools by Availability

- {/* Filters Section */}