Water Quality Monitoring
Monitor water quality parameters in real-time with threshold-based alerts, visual range indicators, and 7-day trend analysis across multiple units and locations.
Overview
The Water Quality Monitoring feature tracks multiple water quality parameters (pH, TDS, Turbidity, Temperature, etc.) with configurable min/max thresholds, visual sliders showing current values, and line graphs displaying 7-day trends.
Location: libs/monitoring/src/pages/quality/
Route: /monitoring/quality/:categoryId
Permission Required: WATER_MONITORING
Key Features
1. Multi-Parameter Monitoring
Track multiple quality parameters simultaneously per unit:
Common Parameters:
- pH - Acidity/Alkalinity level
- TDS - Total Dissolved Solids (ppm)
- Turbidity - Water cloudiness (NTU)
- Temperature - Water temperature (°C)
- Conductivity - Electrical conductivity (µS/cm)
- DO - Dissolved Oxygen (mg/L)
- COD - Chemical Oxygen Demand (mg/L)
- BOD - Biological Oxygen Demand (mg/L)
2. Threshold-Based Alerts
Each parameter has configurable threshold ranges:
unit.meta = {
params: ['pH', 'TDS', 'Turbidity'],
paramsEnabled: ['pH', 'TDS'], // Only enabled params are displayed
min: {
pH: 0,
TDS: 0,
Turbidity: 0
},
max: {
pH: 14,
TDS: 1000,
Turbidity: 100
},
lowThreshold: {
pH: 6.5,
TDS: 100,
Turbidity: 5
},
highThreshold: {
pH: 8.5,
TDS: 500,
Turbidity: 10
}
};
Color Coding:
- Green - Within acceptable range (between low and high thresholds)
- Red - Outside acceptable range (below low or above high threshold)
3. Visual Range Slider
Interactive slider visualization showing:
- Min Value - Absolute minimum
- Low Threshold - Lower acceptable limit
- Current Value - Current reading (as black vertical line)
- High Threshold - Upper acceptable limit
- Max Value - Absolute maximum
Color Gradient:
- Red zone: Min → Low Threshold
- Green zone: Low Threshold → High Threshold
- Red zone: High Threshold → Max
4. 7-Day Trend Graph
Line chart showing parameter trends over the past 7 days:
Features:
- Reference lines for min, max, low threshold, high threshold
- Color-coded dots:
- Green - Values within acceptable range
- Red - Values outside acceptable range
- Hover tooltip showing exact value and date
- X-axis: Daily labels (DD MMM format)
- Y-axis: Parameter value range
5. Online/Offline Status
Each unit displays:
- Online: Green "Online" badge
- Offline: Last update timestamp and reduced opacity
Architecture
Data Flow
QualityPage Component
↓
QualityScreenDataProvider (Context)
↓
MonitoringStore.getCategoryData()
↓
MonitoringController.getCategoryData()
↓
MonitoringDataSource.getCategoryData()
↓
API Client → Backend
↓
Update Context State
↓
Re-render Quality Components
Key Components
1. QualityScreenDataProvider
- Purpose: State management for quality monitoring
- Location:
libs/monitoring/src/dataProvider/QualityScreenDataProvider.jsx - State Variables:
qualityData- Quality parameter data with units and graphsparams- Query parameters (date, category, type)
Example Context Value:
{
qualityData: {
data: {
subCategories: [
{
displayName: 'Inlet Water',
units: [
{
unitId: 'UNIT_1',
displayName: 'Inlet Point 1',
online: true,
value1: { pH: 7.2, TDS: 350, Turbidity: 5 },
lastUpdatedAt: '25/02/2026 10:30 AM',
meta: {
params: ['pH', 'TDS', 'Turbidity'],
paramsEnabled: ['pH', 'TDS'],
min: { pH: 0, TDS: 0, Turbidity: 0 },
max: { pH: 14, TDS: 1000, Turbidity: 100 },
lowThreshold: { pH: 6.5, TDS: 100, Turbidity: 5 },
highThreshold: { pH: 8.5, TDS: 500, Turbidity: 10 }
},
graph1: [
{ x: '19/02/2026', y: { pH: 7.1, TDS: 340 } },
{ x: '20/02/2026', y: { pH: 7.3, TDS: 360 } },
// ... 7 days of data
]
}
]
}
]
}
},
setParams: (params) => {}
}
2. QualityPage
- Purpose: Main quality monitoring page
- Location:
libs/monitoring/src/pages/quality/QualityPage.jsx - Features:
- Displays all subcategories and units
- Renders parameter sliders and trend graphs
- Shows online/offline status
3. BuildUnitsView
- Purpose: Render individual unit quality panels
- Features:
- Unit name and online status
- Category heading (Parameter, Range, 7 Days Trend)
- Parameter rows with slider + graph
4. CustomTooltip
- Purpose: Graph tooltip for trend line chart
- Shows: Parameter value with unit on hover
5. CustomizedDot
- Purpose: Custom dots for line chart
- Logic:
- Green dot if value within thresholds
- Red dot if value outside thresholds
- No dot if value is null/undefined
API Integration
Get Category Data
GET /categoryData
Params: {
category: 'QUALITY_CATEGORY',
type: 'HOUR',
date1: '25/02/2026'
}
Response: {
siUnit: {
pH: '',
TDS: 'ppm',
Turbidity: 'NTU',
Temperature: '°C'
},
subCategories: [
{
id: 'SUB_CAT_1',
displayName: 'Inlet Water',
units: [
{
unitId: 'UNIT_1',
displayName: 'Inlet Point 1',
online: true,
value1: {
pH: 7.2,
TDS: 350,
Turbidity: 5,
Temperature: 25
},
lastUpdatedAt: '25/02/2026 10:30 AM',
meta: {
params: ['pH', 'TDS', 'Turbidity', 'Temperature'],
paramsEnabled: ['pH', 'TDS', 'Turbidity'],
min: { pH: 0, TDS: 0, Turbidity: 0, Temperature: 0 },
max: { pH: 14, TDS: 1000, Turbidity: 100, Temperature: 50 },
lowThreshold: { pH: 6.5, TDS: 100, Turbidity: 5, Temperature: 10 },
highThreshold: { pH: 8.5, TDS: 500, Turbidity: 10, Temperature: 35 }
},
graph1: [
{ x: '19/02/2026', y: { pH: 7.1, TDS: 340, Turbidity: 5 } },
{ x: '20/02/2026', y: { pH: 7.3, TDS: 360, Turbidity: 6 } },
{ x: '21/02/2026', y: { pH: 7.0, TDS: 330, Turbidity: 5 } },
{ x: '22/02/2026', y: { pH: 7.2, TDS: 350, Turbidity: 7 } },
{ x: '23/02/2026', y: { pH: 7.4, TDS: 370, Turbidity: 6 } },
{ x: '24/02/2026', y: { pH: 7.1, TDS: 345, Turbidity: 5 } },
{ x: '25/02/2026', y: { pH: 7.2, TDS: 350, Turbidity: 5 } }
]
}
]
}
]
}
Usage Examples
1. Initialize Quality Monitoring
import { QualityScreenDataProvider } from '@aquagen-mf-webapp/monitoring';
function QualityApp() {
const { categoryId } = useParams();
return (
<QualityScreenDataProvider categoryId={categoryId}>
<QualityContent />
</QualityScreenDataProvider>
);
}
2. Access Quality Data
import { useContext } from 'react';
import { QualityDataContext } from '@aquagen-mf-webapp/monitoring';
function QualityWidget() {
const qualityStore = useContext(QualityDataContext);
const { qualityData } = qualityStore;
return (
<div>
{qualityData?.data?.subCategories?.map(category => (
<div key={category.id}>
<h3>{category.displayName}</h3>
{category.units.map(unit => (
<div key={unit.unitId}>
<h4>{unit.displayName}</h4>
<p>pH: {unit.value1?.pH}</p>
<p>TDS: {unit.value1?.TDS} ppm</p>
<p>Status: {unit.online ? 'Online' : 'Offline'}</p>
</div>
))}
</div>
))}
</div>
);
}
3. Check Parameter Thresholds
function checkParameterStatus(unit, param) {
const value = unit.value1?.[param];
const lowThreshold = unit.meta.lowThreshold[param];
const highThreshold = unit.meta.highThreshold[param];
if (!value) return 'NO_DATA';
if (value < lowThreshold || value > highThreshold) {
return 'OUT_OF_RANGE'; // Red
}
return 'NORMAL'; // Green
}
// Usage
const status = checkParameterStatus(unit, 'pH');
const color = status === 'NORMAL' ? 'green' : 'red';
4. Filter Enabled Parameters
function getEnabledParameters(unit) {
// Use paramsEnabled if available, otherwise use params
const enabledParams = unit.meta.paramsEnabled ?? unit.meta.params;
return enabledParams.map(param => ({
name: param,
currentValue: unit.value1?.[param],
min: unit.meta.min[param],
max: unit.meta.max[param],
lowThreshold: unit.meta.lowThreshold[param],
highThreshold: unit.meta.highThreshold[param],
siUnit: categoryData.siUnit?.[param]
}));
}
Slider Visualization Logic
Color Gradient Calculation
// Calculate percentage positions for color zones
const total = max - min;
const minPV = lowThreshold - min;
const minP = (minPV / total) * 100; // Red zone end %
const maxPV = highThreshold - min;
const maxP = (maxPV / total) * 100; // Green zone end %
// Create gradient
const gradient = `linear-gradient(to right,
red 0%,
red ${minP}%,
green ${minP}%,
green ${maxP}%,
red ${maxP}%,
red 100%
)`;
Marks Configuration
const marks = [
{ value: min, label: min },
{ value: lowThreshold, label: lowThreshold },
{ value: highThreshold, label: highThreshold },
{ value: max, label: max }
];
Graph Visualization
Line Chart with Reference Lines
<LineChart data={labels}>
<YAxis min={min} max={max} hide domain={[min, max]} />
<XAxis dataKey="label" />
<Tooltip content={<CustomTooltip siUnit={siUnit} />} />
{/* Reference Lines */}
<ReferenceLine y={min} stroke="#B0B0B0" strokeWidth={1} />
<ReferenceLine y={lowThreshold} stroke="#CBCBCB" strokeWidth={1} strokeDasharray="3 3" />
<ReferenceLine y={highThreshold} stroke="#CBCBCB" strokeWidth={1} strokeDasharray="3 3" />
<ReferenceLine y={max} stroke="#CBCBCB" strokeWidth={1} strokeDasharray="3 3" />
{/* Data Line */}
<Line
type="monotone"
dataKey="value"
stroke="black"
dot={<CustomizedDot />}
/>
</LineChart>
Custom Dot Component
const CustomizedDot = (props) => {
const { cx, cy, value } = props;
if (!value) return <span></span>; // No data
const isOutOfRange = value < lowThreshold || value > highThreshold;
const color = isOutOfRange ? 'red' : 'green';
return (
<svg x={cx - 5} y={cy - 5} width={8} height={10} fill={color} viewBox="0 0 1024 1024">
<circle cx="512" cy="512" r="450" />
</svg>
);
};
Auto-Refresh
Quality data auto-refreshes at configured intervals:
useEffect(() => {
init(); // Initial load
const interval = setInterval(() => {
init(); // Background refresh
}, constants.refreshDuration);
return () => clearInterval(interval);
}, []);
Default Refresh Interval: Configured in constants.refreshDuration (typically 30-60 seconds)
Responsive Layout
The quality monitoring page adapts to different screen sizes:
Desktop (lg+):
- Three-column layout: Parameter | Range Slider | 7-Day Graph
- Category heading visible
- Horizontal dividers between sections
Mobile (xs-md):
- Stacked vertical layout
- Horizontal dividers between sections
- Last update timestamp moved to bottom
Best Practices
1. Use Enabled Parameters
Always check paramsEnabled before rendering:
const enabledParams = unit.meta.paramsEnabled ?? unit.meta.params;
2. Handle Null Values
Check for null/undefined values in graphs:
const labels = unit.graph1.map(g => ({
label: DateFormatter.customFormatter(g.x, 'DD/MM/YYYY', 'DD MMM'),
value: g.y?.[param]?.toFixed(2) ?? 0,
showTooltip: g.y?.[param] !== undefined && g.y?.[param] !== null
}));
3. Color Code for Quick Status
Use consistent color coding:
- Green = Normal/Good
- Red = Alert/Out of Range
- Grey = Offline/No Data
4. Show Unit Information
Always display SI units for parameters:
`${value} ${categoryData.siUnit?.[param] || ''}`
Troubleshooting
Parameters Not Showing
Cause: Parameter not in paramsEnabled array
Solution: Check backend configuration or use params as fallback
const enabledParams = unit.meta.paramsEnabled ?? unit.meta.params;
Graph Not Rendering
Cause: Missing or null values in graph1 data
Solution: Filter out null values and set showTooltip: false
showTooltip: g.y?.[param] !== undefined && g.y?.[param] !== null
Thresholds Not Matching Colors
Cause: Gradient calculation error Solution: Verify min, max, lowThreshold, highThreshold are numeric and in correct order
Analytics Integration
Quality monitoring tracks page views:
import { AnalyticsService } from '@aquagen-mf-webapp/shared/services';
import { AnalyticEvents } from '@aquagen-mf-webapp/shared/enums';
useEffect(() => {
AnalyticsService.sendEvent(AnalyticEvents.PAGE_VIEW, {}, true);
}, []);
Related Documentation
- Water Flow Monitoring - Flow consumption tracking
- Routes - Quality monitoring route configuration
- Permissions - Access control for quality monitoring
- API & Services - API client integration
Last Updated: February 2026
Module Location: libs/monitoring/src/pages/quality/