Leadership Dashboard
Executive-level dashboard for leadership and management to monitor multiple sites/industries with KPI tracking, status categorization, time-based analysis, and quick site navigation. Designed for high-level oversight across all managed facilities.
Overview
The Leadership Dashboard provides a bird's-eye view of all sites/industries under management. Executives can quickly assess performance across multiple facilities, identify high-priority issues, pin important sites for quick access, and drill down into specific site details. The dashboard automatically categorizes sites by status (Safe, High, Pinned) with configurable time periods (Day, Month, Year).
Location: libs/leadership/
Route: /leadership
Permission Required: LEADERSHIP (Executive/Management only)
Key Features
1. Multi-Site Overview Table
Accordion-Based Organization:
- Sites grouped by status category (PINNED, HIGH, SAFE)
- Color-coded indicators for quick visual assessment
- Collapsible sections with count badges
- Sticky header and first column for easy navigation
Status Categories:
PINNED Sites
- Color: No color indicator
- Purpose: User-pinned sites for quick access
- Badge: Shows count of pinned sites
- Behavior: Sites manually pinned by executive
SAFE Sites
- Color: Green (#05dca4)
- Purpose: Sites operating within normal parameters
- Badge: Green background with site count
- Behavior: Automatically categorized by backend based on thresholds
HIGH Priority Sites
- Color: Red (#F84848)
- Purpose: Sites requiring attention (threshold violations, alerts)
- Badge: Red background with site count
- Behavior: Automatically categorized by backend based on alerts/thresholds
2. Time Period Selection
Three Time Views:
Day View (Hourly)
- Type:
HOUR - Display Name: "Day"
- Date Picker: Single date picker
- Table Header Prefix: "Total"
- Use Case: Today's hourly data for all sites
Month View (Daily Average)
- Type:
DATE - Display Name: "Month"
- Date Picker: Month picker
- Table Header Prefix: "Daily Avg."
- Use Case: Monthly overview with daily averages
Year View (Monthly Average)
- Type:
MONTH - Display Name: "Year"
- Date Picker: Year picker
- Table Header Prefix: "Daily Avg."
- Use Case: Annual overview with monthly averages
Toggle Buttons:
LeadershipHelper.i.leadershipDateType = {
HOUR: {
id: 'HOUR',
displayName: 'Day',
datePickerType: null,
tableHeaderPrefix: 'Total'
},
DATE: {
id: 'DATE',
displayName: 'Month',
datePickerType: 'month',
tableHeaderPrefix: 'Daily Avg.'
},
MONTH: {
id: 'MONTH',
displayName: 'Year',
datePickerType: 'year',
tableHeaderPrefix: 'Daily Avg.'
}
};
3. Site Management Actions
Pin/Unpin Sites:
- Click pin icon to mark important sites
- Pinned sites appear in "PINNED" accordion
- Retains original status color indicator in pinned view
- Tooltip shows "Already Pinned" for pinned sites in other sections
Redirect to Site:
- External link icon opens site in new tab
- Automatic login to selected industry/site
- Opens in new tab with
noopener,noreferrerfor security - Popup permission warning if browser blocks new tab
4. Dynamic KPI Table
Responsive Table Structure:
- Sticky First Column: Site/Industry name always visible
- Sticky Action Column: Pin and redirect buttons always visible (desktop)
- Horizontal Scroll: For wide data tables
- Dynamic Headers: Backend-controlled column headers
- HTML Content Support: Cells can render formatted HTML
Table Features:
- Border-separated cells for clarity
- Responsive column widths based on content
- Minimum width calculation for site names (8px per character)
- Color-coded status indicators
- Last updated timestamp with refresh button
Architecture
Data Flow
User Opens Leadership Dashboard
↓
LeadershipDataProvider Initializes
↓
LeadershipController.getLeadershipListData({ date1, type })
↓
API Client → GET /executiveData
↓
Backend returns:
- headers: { col1: "Site Name", col2: "Consumption", ... }
- rows: [{ columns: {...}, meta: {...} }]
- maxLengthName: 25
↓
Update LeadershipDataContext
↓
Process rows into status categories (PINNED, SAFE, HIGH)
↓
Render Accordions with Tables
↓
User Actions (Pin/Redirect)
↓
API Client → PUT /executivePinIndustry or GET /executiveIndustryLogin
↓
Update UI
Key Components
1. LeadershipDataProvider
- Purpose: Global state management for leadership dashboard
- Location:
libs/leadership/src/store/LeadershipStore.js - State Variables:
leadershipData- All site data with headers and rowsisLoading- Initial data loading stateparams- Query parameters (date1, type)fullScreenLoader- Full-screen loader for actionslastUpdatedTime- Time of last data refresh
Context Value:
{
leadershipData: {
headers: {
col1: "Site Name",
col2: "Total Consumption",
col3: "Water Balance",
col4: "Alerts"
},
rows: [
{
columns: {
col1: "Site A",
col2: "1,234 kL",
col3: "85%",
col4: "2"
},
meta: {
industryId: "IND_123",
status: "SAFE",
isPinned: false
}
}
],
modifiedRows: {
PINNED: [...],
SAFE: [...],
HIGH: [...]
},
maxLengthName: 25
},
isLoading: false,
params: { date1: '25/02/2026', type: 'HOUR' },
fullScreenLoader: false,
lastUpdatedTime: '10:30 AM',
setParams: (params) => {},
getLoginData: (params) => {},
pinIndustry: (params) => {},
getExecutiveListData: () => {}
}
2. LeadershipDashboardPage
- Purpose: Main leadership dashboard container
- Location:
libs/leadership/src/LeadershipDashboardPage.jsx - Features:
- Fixed header with industry name and site count
- Context provider wrapper
- Bug report integration
- SSO notification reminder
- Executive navbar
3. LeaderShipFixedBar
- Purpose: Fixed header showing industry name and site count
- Display:
{Industry Name} - Total Sites {count} - Dynamic Count: Updates based on filtered data
4. LeadershipHeader
- Purpose: Date selector and refresh controls
- Location:
libs/leadership/src/components/LeadershipHeader.jsx - Features:
- Time period toggle buttons (Day/Month/Year)
- Date picker (changes based on selected period)
- Last updated timestamp
- Refresh button
- Analytics tracking
5. LeadershipListView
- Purpose: Main content area with status accordions
- Location:
libs/leadership/src/components/LeadershipListView.jsx - Features:
- Loading state with custom loader
- Data not found fallback
- Status-based accordion rendering
- Backdrop loader for actions
- Popup permission handling
6. LeadershipAccordian
- Purpose: Individual status section (PINNED, SAFE, HIGH)
- Features:
- Collapsible section with expand/collapse
- Color-coded status badge
- Site count indicator
- Responsive table with sticky columns
- Pin and redirect actions
7. ExecutiveNavbar
- Purpose: Special navbar for leadership view
- Location:
libs/components/src/appNavBar/ExecutiveNavbar.jsx - Features: Executive-specific navigation options
API Integration
Get Leadership List Data
GET /executiveData
Params: {
date1: '25/02/2026',
type: 'HOUR' // or 'DATE', 'MONTH'
}
Response: {
headers: {
col1: "Site Name",
col2: "Total Consumption (kL)",
col3: "Water Balance (%)",
col4: "Alerts",
col5: "Quality Score"
},
rows: [
{
columns: {
col1: "Manufacturing Plant A",
col2: "1,234.5",
col3: "<span style='color: green'>85%</span>",
col4: "2",
col5: "Good"
},
meta: {
industryId: "IND_123",
status: "SAFE",
isPinned: false
}
},
{
columns: {
col1: "Office Campus B",
col2: "567.8",
col3: "<span style='color: red'>45%</span>",
col4: "7",
col5: "Critical"
},
meta: {
industryId: "IND_456",
status: "HIGH",
isPinned: true
}
}
],
maxLengthName: 25
}
Response Processing: Backend returns raw rows, frontend groups by status:
modifiedRows = {
PINNED: rows.filter(r => r.meta.isPinned),
SAFE: rows.filter(r => r.meta.status === 'SAFE' && !r.meta.isPinned),
HIGH: rows.filter(r => r.meta.status === 'HIGH' && !r.meta.isPinned)
};
Pin/Unpin Industry
PUT /executivePinIndustry
Request Body: {
industryId: 'IND_123',
isPinned: true // or false
}
Response: {
status: 200,
message: 'Industry pinned successfully'
}
Frontend Logic:
const pinIndustry = (industryId, isPinned) => {
const pinParams = {
industryId: industryId,
isPinned: !isPinned // Toggle pin state
};
leaderStore.pinIndustry(pinParams);
// Automatically refreshes data after update
};
Industry Login (Redirect)
GET /executiveIndustryLogin
Params: {
industryId: 'IND_123'
}
Response: {
status: 200,
token: 'jwt_token_for_industry_123',
redirectUrl: 'https://app.aquagen.com'
}
Frontend Logic:
const redirectToIndustry = async (industryId) => {
// Get login credentials for industry
await leaderStore.getLoginData({ industryId });
// Track analytics
AnalyticsService.sendEvent(AnalyticEvents.LEADERSHIP_REDIRECT, {
industryId
});
// Open in new tab
const baseUrl = `${window.location.protocol}//${window.location.host}`;
const newTab = window.open(baseUrl, '_blank', 'noopener,noreferrer');
// Check if popup was blocked
if (!newTab || newTab.closed || typeof newTab.closed === 'undefined') {
setShowPermissionPopup(true);
}
};
Usage Examples
1. Initialize Leadership Dashboard
import LeadershipDashboardPage from '@aquagen-mf-webapp/leadership';
function LeadershipRoute() {
return <LeadershipDashboardPage />;
}
2. Access Leadership Context
import { useContext } from 'react';
import { LeadershipDataContext } from '@aquagen-mf-webapp/leadership/store/LeadershipStore';
function CustomLeadershipWidget() {
const leaderStore = useContext(LeadershipDataContext);
const totalSites = leaderStore.leadershipData?.rows?.length || 0;
const safeSites = leaderStore.leadershipData?.modifiedRows?.SAFE?.length || 0;
const highPrioritySites = leaderStore.leadershipData?.modifiedRows?.HIGH?.length || 0;
return (
<div>
<h3>Total Sites: {totalSites}</h3>
<p>Safe: {safeSites}</p>
<p>High Priority: {highPrioritySites}</p>
</div>
);
}
3. Change Time Period
const handlePeriodChange = (newType) => {
let newDate = moment();
// Adjust date based on type
if (newType === LeadershipHelper.i.leadershipDateType.DATE.id) {
newDate = newDate.startOf('month');
}
if (newType === LeadershipHelper.i.leadershipDateType.MONTH.id) {
newDate = newDate.startOf('year');
}
leaderStore.setParams({
type: newType,
date1: DateFormatter.formatter(newDate)
});
};
// Usage
<ToggleButton
value={LeadershipHelper.i.leadershipDateType.HOUR.id}
onClick={() => handlePeriodChange(LeadershipHelper.i.leadershipDateType.HOUR.id)}
>
Day
</ToggleButton>
4. Pin/Unpin Site
const handlePinToggle = (industryId, currentPinState) => {
leaderStore.pinIndustry({
industryId: industryId,
isPinned: !currentPinState
});
// Data automatically refreshes after pin update
};
// Render pin button
<IconButton onClick={() => handlePinToggle(site.meta.industryId, site.meta.isPinned)}>
{site.meta.isPinned ? (
<Icon icon={'bi:pin-fill'} style={{ color: 'black' }} />
) : (
<Icon icon={'bi:pin'} />
)}
</IconButton>
5. Redirect to Site
const handleSiteRedirect = async (industryId) => {
try {
// Get login data
await leaderStore.getLoginData({ industryId });
// Track event
AnalyticsService.sendEvent(AnalyticEvents.LEADERSHIP_REDIRECT, {
industryId
});
// Open site in new tab
const baseUrl = `${window.location.protocol}//${window.location.host}`;
window.open(baseUrl, '_blank', 'noopener,noreferrer');
} catch (error) {
console.error('Redirect failed', error);
}
};
6. Refresh Data
const handleRefresh = () => {
// Track analytics
AnalyticsService.sendEvent(AnalyticEvents.LEADERSHIP_REFRESH_CLICK);
// Show full-screen loader
leaderStore.setFullScreenLoader(true);
// Refresh with current date
leaderStore.setParams({
...leaderStore.params,
date1: moment().format('DD/MM/YYYY')
});
};
// Render refresh button
<ButtonBase onClick={handleRefresh}>
<RefreshRoundedIcon />
</ButtonBase>
Status Configuration
LeadershipHelper.i.leadershipListSatusEnum = {
PINNED: 'PINNED',
HIGH: 'HIGH',
SAFE: 'SAFE'
};
LeadershipHelper.i.leadershipListSatusColor = {
PINNED: null, // No color indicator
SAFE: '#05dca4', // Green
HIGH: '#F84848' // Red
};
// Get status array in order
LeadershipHelper.i.leadershipStatusArray
// Returns: ['PINNED', 'HIGH', 'SAFE']
Responsive Design
Desktop (md+)
- Full-width table with horizontal scroll
- Sticky first column (site name)
- Sticky last column (actions)
- All accordion sections visible
Mobile (xs-sm)
- Full-width horizontal scroll
- Sticky first column only
- Action column scrolls with table
- Minimum column widths: 200px
- Touch-friendly accordions
Responsive Column Width:
minWidth: {
xs: '200px',
sm: !headingIndex && leaderStore.leadershipData?.maxLengthName
? `${leaderStore.leadershipData?.maxLengthName * 8}px`
: 'fit-content'
}
Best Practices
1. Handle Loading States
const { isLoading, fullScreenLoader } = useContext(LeadershipDataContext);
if (isLoading) {
return <CustomLoader />;
}
// Show backdrop loader for actions
<BackdropLoader isLoading={fullScreenLoader} />
2. Handle Empty Data
if (!leaderStore.leadershipData && !leaderStore.isLoading) {
return (
<GenericInfo
lottieData={assets.lotties.dataNotFound}
subTitle="Data Not Found"
/>
);
}
3. Prevent Popup Blockers
const newTab = window.open(baseUrl, '_blank', 'noopener,noreferrer');
// Check if popup was blocked
if (!newTab || newTab.closed || typeof newTab.closed === 'undefined') {
setShowPermissionPopup(true);
}
// Show popup permission helper
<PopupPermission
open={showPermissionPopup}
handleClose={() => setShowPermissionPopup(false)}
/>
4. Track Analytics Events
// Date type change
AnalyticsService.sendEvent(
AnalyticEvents.LEADERSHIP_DATE_TYPE_CHANGE,
{ type: 'HOUR', date1: '25/02/2026' }
);
// Date change
AnalyticsService.sendEvent(
AnalyticEvents.LEADERSHIP_DATE_CHANGE,
{ type: 'DATE', date1: '01/02/2026' }
);
// Site redirect
AnalyticsService.sendEvent(
AnalyticEvents.LEADERSHIP_REDIRECT,
{ industryId: 'IND_123' }
);
// Refresh click
AnalyticsService.sendEvent(AnalyticEvents.LEADERSHIP_REFRESH_CLICK);
5. HTML Content Security
Table cells support HTML rendering:
<div dangerouslySetInnerHTML={{
__html: row.columns[headerId] ? row.columns[headerId] : '-'
}} />
Ensure backend sanitizes HTML to prevent XSS attacks.
Troubleshooting
Sites Not Categorized Correctly
Cause: Backend not returning proper status in meta
Solution: Verify API response includes meta.status
rows: [
{
columns: {...},
meta: {
status: 'SAFE', // Must be 'SAFE', 'HIGH', or 'PINNED'
isPinned: false
}
}
]
Pin Not Working
Cause: API error or missing industryId Solution: Check console and verify PUT request
const pinIndustry = async (params) => {
const response = await LeadershipController.pinIndustry(params);
if (response.status !== 200) {
console.log('Unable to Pin Industry');
}
getExecutiveListData(); // Refresh data
};
Redirect Opens Multiple Tabs
Cause: Double-click or rapid clicks Solution: Disable button during loading
const [redirecting, setRedirecting] = useState(false);
const redirectToIndustry = async (industryId) => {
if (redirecting) return;
setRedirecting(true);
await leaderStore.getLoginData({ industryId });
window.open(baseUrl, '_blank', 'noopener,noreferrer');
setRedirecting(false);
};
Date Picker Not Changing
Cause: Date not formatted correctly based on type Solution: Use handleDateChangeBasedonType helper
const handleDateChangeBasedonType = (dateType, newValue) => {
let newDate = newValue || moment();
if (dateType === LeadershipHelper.i.leadershipDateType.DATE.id) {
newDate = newDate.startOf('month'); // Month view starts at month beginning
}
if (dateType === LeadershipHelper.i.leadershipDateType.MONTH.id) {
newDate = newDate.startOf('year'); // Year view starts at year beginning
}
return DateFormatter.formatter(newDate);
};
Integration with Other Features
Executive Navbar
- Custom navbar for leadership view
- Replaces standard app navigation
- Provides executive-specific menu options
- Auto-integrated via LeadershipDataProvider
SSO Notification Reminder
- Reminds executives to enable SSO if not configured
- Shows only for super users/admins
- Dismissible notification
Bug Report
- Bug reporting widget available in leadership view
- Allows executives to report issues directly
- Includes screenshot and context capture
Analytics Tracking
Events Tracked:
// Page view
AnalyticEvents.PAGE_VIEW
// Date type change (Day/Month/Year)
AnalyticEvents.LEADERSHIP_DATE_TYPE_CHANGE
// Date change
AnalyticEvents.LEADERSHIP_DATE_CHANGE
// Refresh button click
AnalyticEvents.LEADERSHIP_REFRESH_CLICK
// Site redirect
AnalyticEvents.LEADERSHIP_REDIRECT
Related Documentation
- Dashboard - Regular user dashboard
- Routes - Leadership route configuration
- Permissions - LEADERSHIP permission required
- API & Services - API integration details
Last Updated: February 2026
Module Location: libs/leadership/