Passed
Push — master ( ae2710...d99a30 )
by
unknown
10:28
created

myems-web/src/components/MyEMS/Microgrid/MicrogridDetails.js   F

Complexity

Total Complexity 86
Complexity/F 0

Size

Lines of Code 1438
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 86
eloc 1237
mnd 86
bc 86
fnc 0
dl 0
loc 1438
rs 0.8
bpm 0
cpm 0
noi 0
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like myems-web/src/components/MyEMS/Microgrid/MicrogridDetails.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
import React, { Fragment, useState, useEffect, useContext } from 'react';
2
import { Card, CardBody, Col, Row, Table, Nav, NavItem, NavLink, TabContent, TabPane, Button, Form, FormGroup, Input, CustomInput, Spinner } from 'reactstrap';
3
import Cascader from 'rc-cascader';
4
import MultipleLineChart from '../common/MultipleLineChart';
5
import SectionLineChart from '../common/SectionLineChart';
6
import { getCookieValue, createCookie, checkEmpty } from '../../../helpers/utils';
7
import withRedirect from '../../../hoc/withRedirect';
8
import { withTranslation } from 'react-i18next';
9
import { toast } from 'react-toastify';
10
import { v4 as uuid } from 'uuid';
11
import { APIBaseURL, settings } from '../../../config';
12
import useInterval from '../../../hooks/useInterval';
13
import { useLocation } from 'react-router-dom';
14
import DetailsTable from './DetailsTable';
15
import { isIterableArray } from '../../../helpers/utils';
16
import classNames from 'classnames';
17
import AppContext from '../../../context/Context';
18
import blankPage from '../../../assets/img/generic/blank-page.png';
19
20
const MicrogridDetails = ({ setRedirect, setRedirectUrl, t }) => {
21
  const location = useLocation();
22
  const microgridUUID = location.search.split('=')[1];
23
  const { currency } = useContext(AppContext);
24
25
  useEffect(() => {
26
    let is_logged_in = getCookieValue('is_logged_in');
27
    let user_name = getCookieValue('user_name');
28
    let user_display_name = getCookieValue('user_display_name');
29
    let user_uuid = getCookieValue('user_uuid');
30
    let token = getCookieValue('token');
31
    if (checkEmpty(is_logged_in) || checkEmpty(token) || checkEmpty(user_uuid) || !is_logged_in) {
32
      setRedirectUrl(`/authentication/basic/login`);
33
      setRedirect(true);
34
    } else {
35
      //update expires time of cookies
36
      createCookie('is_logged_in', true, settings.cookieExpireTime);
37
      createCookie('user_name', user_name, settings.cookieExpireTime);
38
      createCookie('user_display_name', user_display_name, settings.cookieExpireTime);
39
      createCookie('user_uuid', user_uuid, settings.cookieExpireTime);
40
      createCookie('token', token, settings.cookieExpireTime);
41
    }
42
  });
43
44
  useEffect(() => {
45
    let timer = setInterval(() => {
46
      let is_logged_in = getCookieValue('is_logged_in');
47
      if (is_logged_in === null || !is_logged_in) {
48
        setRedirectUrl(`/authentication/basic/login`);
49
        setRedirect(true);
50
      }
51
    }, 1000);
52
    return () => clearInterval(timer);
53
  }, [setRedirect, setRedirectUrl]);
54
55
  const [activeTabLeft, setActiveTabLeft] = useState('1');
56
  const toggleTabLeft = tab => {
57
    if (activeTabLeft !== tab) setActiveTabLeft(tab);
58
  };
59
60
  const [activeTabRight, setActiveTabRight] = useState('1');
61
  const toggleTabRight = tab => {
62
    if (activeTabRight !== tab) setActiveTabRight(tab);
63
  };
64
65
  const [activeTabBottom, setActiveTabBottom] = useState('1');
66
  const toggleTabBottom = tab => {
67
    if (activeTabBottom !== tab) setActiveTabBottom(tab);
68
  };
69
70
  // Fullscreen state
71
  const [isFullscreen, setIsFullscreen] = useState(false);
72
  const toggleFullscreen = () => {
73
    setIsFullscreen(!isFullscreen);
74
  };
75
76
  // Bottom section pinned to top state
77
  const [isBottomSectionPinned, setIsBottomSectionPinned] = useState(false);
78
  const toggleBottomSectionPin = () => {
79
    setIsBottomSectionPinned(!isBottomSectionPinned);
80
  };
81
82
  // Check if current tab has data
83
  const hasTabData = () => {
84
    switch (activeTabBottom) {
85
      case '1':
86
        return parameterLineChartLabels && Object.keys(parameterLineChartLabels).length > 0 &&
87
               parameterLineChartData && Object.keys(parameterLineChartData).length > 0;
88
      case '2':
89
        return scheduleXaxisData && scheduleXaxisData.length > 0 &&
90
               scheduleSeriesData && scheduleSeriesData.length > 0;
91
      case '3':
92
        return true; // Table always has structure
93
      case '4':
94
        return isIterableArray(PCSDetailsList) && PCSDetailsList.length > 0;
95
      case '5':
96
        return isIterableArray(BMSDetailsList) && BMSDetailsList.length > 0;
97
      case '6':
98
        return isIterableArray(PVDetailsList) && PVDetailsList.length > 0;
99
      case '7':
100
        return isIterableArray(EVChargerDetailsList) && EVChargerDetailsList.length > 0;
101
      case '8':
102
        return isIterableArray(GeneratorDetailsList) && GeneratorDetailsList.length > 0;
103
      case '9':
104
        return isIterableArray(GridDetailsList) && GridDetailsList.length > 0;
105
      case '10':
106
        return isIterableArray(LoadDetailsList) && LoadDetailsList.length > 0;
107
      case '11':
108
        return isIterableArray(HeatpumpDetailsList) && HeatpumpDetailsList.length > 0;
109
      default:
110
        return false;
111
    }
112
  };
113
114
  // State for space selection
115
  const [selectedSpaceName, setSelectedSpaceName] = useState(undefined);
116
  const [microgridList, setMicrogridList] = useState([]);
117
  const [filteredMicrogridList, setFilteredMicrogridList] = useState([]);
118
  const [selectedMicrogrid, setSelectedMicrogrid] = useState(undefined);
119
  const [cascaderOptions, setCascaderOptions] = useState(undefined);
120
  const [spaceCascaderHidden, setSpaceCascaderHidden] = useState(false);
121
  const [spinnerHidden, setSpinnerHidden] = useState(true);
122
  const [resultDataHidden, setResultDataHidden] = useState(true);
123
124
  //Results
125
126
  const [microgridID, setMicrogridID] = useState();
127
  const [microgridName, setMicrogridName] = useState();
128
  const [microgridSerialNumber, setMicrogridSerialNumber] = useState();
129
  const [microgridAddress, setMicrogridAddress] = useState();
130
  const [microgridPostalCode, setMicrogridPostalCode] = useState();
131
  const [microgridRatedCapacity, setMicrogridRatedCapacity] = useState();
132
  const [microgridRatedPower, setMicrogridRatedPower] = useState();
133
  const [microgridLatitude, setMicrogridLatitude] = useState();
134
  const [microgridLongitude, setMicrogridLongitude] = useState();
135
  const [microgridSVG, setMicrogridSVG] = useState();
136
137
  const [todayChargeEnergyValue, setTodayChargeEnergyValue] = useState();
138
  const [todayDischargeEnergyValue, setTodayDischargeEnergyValue] = useState();
139
  const [totalChargeEnergyValue, setTotalChargeEnergyValue] = useState();
140
  const [totalDischargeEnergyValue, setTotalDischargeEnergyValue] = useState();
141
  const [totalEfficiency, setTotalEfficiency] = useState();
142
143
  const [todayChargeRevenueValue, setTodayChargeRevenueValue] = useState();
144
  const [todayDischargeRevenueValue, setTodayDischargeRevenueValue] = useState();
145
  const [totalChargeRevenueValue, setTotalChargeRevenueValue] = useState();
146
  const [totalDischargeRevenueValue, setTotalDischargeRevenueValue] = useState();
147
148
  const [todayChargeCarbonValue, setTodayChargeCarbonValue] = useState();
149
  const [todayDischargeCarbonValue, setTodayDischargeCarbonValue] = useState();
150
  const [totalChargeCarbonValue, setTotalChargeCarbonValue] = useState();
151
  const [totalDischargeCarbonValue, setTotalDischargeCarbonValue] = useState();
152
153
  const [scheduleXaxisData, setScheduleXaxisData] = useState();
154
  const [scheduleSeriesName, setScheduleSeriesName] = useState();
155
  const [scheduleSeriesData, setScheduleSeriesData] = useState();
156
  const [scheduleMarkAreaData, setScheduleMarkAreaData] = useState();
157
158
  const [parameterLineChartLabels, setParameterLineChartLabels] = useState([]);
159
  const [parameterLineChartData, setParameterLineChartData] = useState({});
160
  const [parameterLineChartOptions, setParameterLineChartOptions] = useState([]);
161
162
  const [BMSDetailsList, setBMSDetailsList] = useState([]);
163
  const [EVChargerDetailsList, setEVChargerDetailsList] = useState([]);
164
  const [PCSDetailsList, setPCSDetailsList] = useState([]);
165
  const [PVDetailsList, setPVDetailsList] = useState([]);
166
  const [GeneratorDetailsList, setGeneratorDetailsList] = useState([]);
167
  const [GridDetailsList, setGridDetailsList] = useState([]);
168
  const [LoadDetailsList, setLoadDetailsList] = useState([]);
169
  const [HeatpumpDetailsList, setHeatpumpDetailsList] = useState([]);
170
171
  useEffect(() => {
172
    if (microgridUUID === null || !microgridUUID) {
173
      // No UUID, show space selector
174
      let isResponseOK = false;
175
      setSpaceCascaderHidden(false);
176
      fetch(APIBaseURL + '/spaces/tree', {
177
        method: 'GET',
178
        headers: {
179
          'Content-type': 'application/json',
180
          'User-UUID': getCookieValue('user_uuid'),
181
          Token: getCookieValue('token')
182
        },
183
        body: null
184
      })
185
        .then(response => {
186
          if (response.ok) {
187
            isResponseOK = true;
188
          }
189
          return response.json();
190
        })
191
        .then(json => {
192
          if (isResponseOK) {
193
            // rename keys
194
            json = JSON.parse(
195
              JSON.stringify([json])
196
                .split('"id":')
197
                .join('"value":')
198
                .split('"name":')
199
                .join('"label":')
200
            );
201
            setCascaderOptions(json);
202
            setSelectedSpaceName([json[0]].map(o => o.label));
203
            let selectedSpaceID = [json[0]].map(o => o.value);
204
            // get Microgrids by root Space ID
205
            let isResponseOK = false;
206
            fetch(APIBaseURL + '/spaces/' + selectedSpaceID + '/microgrids', {
207
              method: 'GET',
208
              headers: {
209
                'Content-type': 'application/json',
210
                'User-UUID': getCookieValue('user_uuid'),
211
                Token: getCookieValue('token')
212
              },
213
              body: null
214
            })
215
              .then(response => {
216
                if (response.ok) {
217
                  isResponseOK = true;
218
                }
219
                return response.json();
220
              })
221
              .then(json => {
222
                if (isResponseOK) {
223
                  json = JSON.parse(
224
                    JSON.stringify([json])
225
                      .split('"id":')
226
                      .join('"value":')
227
                      .split('"name":')
228
                      .join('"label":')
229
                  );
230
                  setMicrogridList(json[0]);
231
                  setFilteredMicrogridList(json[0]);
232
                  if (json[0].length > 0) {
233
                    // select the first microgrid
234
                    let microgridID = json[0][0].value;
235
                    setSelectedMicrogrid(microgridID);
236
                    // automatically submit with the first microgrid
237
                    loadData(APIBaseURL + '/reports/microgriddetails?id=' + microgridID);
238
                  } else {
239
                    setSelectedMicrogrid(undefined);
240
                    setResultDataHidden(true);
241
                  }
242
                } else {
243
                  toast.error(t(json.description));
244
                }
245
              })
246
              .catch(err => {
247
                console.log(err);
248
              });
249
            // end of get Microgrids by root Space ID
250
          } else {
251
            toast.error(t(json.description));
252
          }
253
        })
254
        .catch(err => {
255
          console.log(err);
256
        });
257
    } else {
258
      setSpaceCascaderHidden(true);
259
      loadData(APIBaseURL + '/reports/microgriddetails?uuid=' + microgridUUID);
260
    }
261
  }, [microgridUUID]);
262
263
  const loadData = url => {
264
    // show spinner
265
    setSpinnerHidden(false);
266
    // hide result data
267
    setResultDataHidden(true);
268
269
    let isResponseOK = false;
270
    fetch(url, {
271
      method: 'GET',
272
      headers: {
273
        'Content-type': 'application/json',
274
        'User-UUID': getCookieValue('user_uuid'),
275
        Token: getCookieValue('token')
276
      },
277
      body: null
278
    })
279
      .then(response => {
280
        if (response.ok) {
281
          isResponseOK = true;
282
        }
283
        return response.json();
284
      })
285
      .then(json => {
286
        if (isResponseOK) {
287
          if (microgridUUID !== null && microgridUUID) {
288
            setFilteredMicrogridList([
289
              { id: json['microgrid']['id'], label: json['microgrid']['name'] }
290
            ]);
291
            setSelectedMicrogrid(json['microgrid']['id']);
292
          }
293
          console.log(json);
294
          setMicrogridID(json['microgrid']['id']);
295
          setMicrogridName(json['microgrid']['name']);
296
          setMicrogridSerialNumber(json['microgrid']['serial_number']);
297
          setMicrogridAddress(json['microgrid']['address']);
298
          setMicrogridPostalCode(json['microgrid']['postal_code']);
299
          setMicrogridRatedCapacity(json['microgrid']['rated_capacity']);
300
          setMicrogridRatedPower(json['microgrid']['rated_power']);
301
          setMicrogridLatitude(json['microgrid']['latitude']);
302
          setMicrogridLongitude(json['microgrid']['longitude']);
303
          setMicrogridSVG({ __html: json['microgrid']['svg'] });
304
305
          setTodayChargeEnergyValue(json['energy_indicators']['today_charge_energy_value']);
306
          setTodayDischargeEnergyValue(json['energy_indicators']['today_discharge_energy_value']);
307
          setTotalChargeEnergyValue(json['energy_indicators']['total_charge_energy_value']);
308
          setTotalDischargeEnergyValue(json['energy_indicators']['total_discharge_energy_value']);
309
310
          if (json['energy_indicators']['total_charge_energy_value'] > 0) {
311
            setTotalEfficiency(
312
              (
313
                (100 * json['energy_indicators']['total_discharge_energy_value']) /
314
                json['energy_indicators']['total_charge_energy_value']
315
              ).toFixed(2)
316
            );
317
          } else {
318
            setTotalEfficiency(0);
319
          }
320
321
          setTodayChargeRevenueValue(json['revenue_indicators']['today_charge_revenue_value']);
322
          setTodayDischargeRevenueValue(json['revenue_indicators']['today_discharge_revenue_value']);
323
          setTotalChargeRevenueValue(json['revenue_indicators']['total_charge_revenue_value']);
324
          setTotalDischargeRevenueValue(json['revenue_indicators']['total_discharge_revenue_value']);
325
326
          setTodayChargeCarbonValue(json['carbon_indicators']['today_charge_carbon_value']);
327
          setTodayDischargeCarbonValue(json['carbon_indicators']['today_discharge_carbon_value']);
328
          setTotalChargeCarbonValue(json['carbon_indicators']['total_charge_carbon_value']);
329
          setTotalDischargeCarbonValue(json['carbon_indicators']['total_discharge_carbon_value']);
330
331
          setScheduleXaxisData([
332
            '00:00:00',
333
            '00:30:00',
334
            '01:00:00',
335
            '01:30:00',
336
            '02:00:00',
337
            '02:30:00',
338
            '03:00:00',
339
            '03:30:00',
340
            '04:00:00',
341
            '04:30:00',
342
            '05:00:00',
343
            '05:30:00',
344
            '06:00:00',
345
            '06:30:00',
346
            '07:00:00',
347
            '07:30:00',
348
            '08:00:00',
349
            '08:30:00',
350
            '09:00:00',
351
            '09:30:00',
352
            '10:00:00',
353
            '10:30:00',
354
            '11:00:00',
355
            '11:30:00',
356
            '12:00:00',
357
            '12:30:00',
358
            '13:00:00',
359
            '13:30:00',
360
            '14:00:00',
361
            '14:30:00',
362
            '15:00:00',
363
            '15:30:00',
364
            '16:00:00',
365
            '16:30:00',
366
            '17:00:00',
367
            '17:30:00',
368
            '18:00:00',
369
            '18:30:00',
370
            '19:00:00',
371
            '19:30:00',
372
            '20:00:00',
373
            '20:30:00',
374
            '21:00:00',
375
            '21:30:00',
376
            '22:00:00',
377
            '22:30:00',
378
            '23:00:00',
379
            '23:30:00',
380
            '23:59:59'
381
          ]);
382
          setScheduleSeriesName('Power');
383
          setScheduleSeriesData(json['schedule']['series_data']);
384
          let schedule_mark_area_data = [];
385
          json['schedule']['schedule_list'].forEach((schedule_item, index) => {
386
            schedule_mark_area_data.push([
387
              { name: t(schedule_item['peak_type']), xAxis: schedule_item['start_time_of_day'] },
388
              { xAxis: schedule_item['end_time_of_day'] }
389
            ]);
390
          });
391
          setScheduleMarkAreaData(schedule_mark_area_data);
392
393
          let timestamps = {};
394
          json['parameters']['timestamps'].forEach((currentValue, index) => {
395
            timestamps['a' + index] = currentValue;
396
          });
397
          setParameterLineChartLabels(timestamps);
398
399
          let values = {};
400
          json['parameters']['values'].forEach((currentValue, index) => {
401
            values['a' + index] = currentValue;
402
          });
403
          setParameterLineChartData(values);
404
405
          let names = [];
406
          json['parameters']['names'].forEach((currentValue, index) => {
407
            names.push({ value: 'a' + index, label: currentValue });
408
          });
409
          setParameterLineChartOptions(names);
410
          // hide spinner
411
          setSpinnerHidden(true);
412
          // show result data
413
          setResultDataHidden(false);
414
        } else {
415
          toast.error(t(json.description));
416
          // hide spinner
417
          setSpinnerHidden(true);
418
        }
419
      })
420
      .catch(err => {
421
        console.log(err);
422
        // hide spinner
423
        setSpinnerHidden(true);
424
      });
425
  };
426
427
  const onSpaceCascaderChange = (value, selectedOptions) => {
428
    setSelectedSpaceName(selectedOptions.map(o => o.label).join('/'));
429
    let selectedSpaceID = value[value.length - 1];
430
    let isResponseOK = false;
431
    fetch(APIBaseURL + '/spaces/' + selectedSpaceID + '/microgrids', {
432
      method: 'GET',
433
      headers: {
434
        'Content-type': 'application/json',
435
        'User-UUID': getCookieValue('user_uuid'),
436
        Token: getCookieValue('token')
437
      },
438
      body: null
439
    })
440
      .then(response => {
441
        if (response.ok) {
442
          isResponseOK = true;
443
        }
444
        return response.json();
445
      })
446
      .then(json => {
447
        if (isResponseOK) {
448
          json = JSON.parse(
449
            JSON.stringify([json])
450
              .split('"id":')
451
              .join('"value":')
452
              .split('"name":')
453
              .join('"label":')
454
          );
455
          setMicrogridList(json[0]);
456
          setFilteredMicrogridList(json[0]);
457
          if (json[0].length > 0) {
458
            // select the first microgrid
459
            let microgridID = json[0][0].value;
460
            setSelectedMicrogrid(microgridID);
461
            // automatically submit with the first microgrid
462
            loadData(APIBaseURL + '/reports/microgriddetails?id=' + microgridID);
463
          } else {
464
            setSelectedMicrogrid(undefined);
465
            setResultDataHidden(true);
466
          }
467
        } else {
468
          toast.error(t(json.description));
469
        }
470
      })
471
      .catch(err => {
472
        console.log(err);
473
      });
474
  };
475
476
  const onMicrogridChange = event => {
477
    let microgridID = event.target.value;
478
    setSelectedMicrogrid(microgridID);
479
    loadData(APIBaseURL + '/reports/microgriddetails?id=' + microgridID);
480
  };
481
482
  const labelClasses = 'ls text-uppercase text-600 font-weight-semi-bold mb-0';
483
484
  const refreshSVGData = () => {
485
    let isResponseOK = false;
486
    fetch(APIBaseURL + '/reports/pointrealtime', {
487
      method: 'GET',
488
      headers: {
489
        'Content-type': 'application/json',
490
        'User-UUID': getCookieValue('user_uuid'),
491
        Token: getCookieValue('token')
492
      },
493
      body: null
494
    })
495
      .then(response => {
496
        if (response.ok) {
497
          isResponseOK = true;
498
        }
499
        return response.json();
500
      })
501
      .then(json => {
502
        if (isResponseOK) {
503
          console.log(json);
504
          json.forEach(currentPoint => {
505
            let textElement = document.getElementById('PT' + currentPoint['point_id']);
506
            if (textElement) {
507
              textElement.textContent = parseFloat(currentPoint['value']).toFixed(2);
508
            }
509
            let circleElement = document.getElementById('CIRCLE' + currentPoint['point_id']);
510
            if (circleElement) {
511
              if (currentPoint['value'] > 0) {
512
                circleElement.className.baseVal = 'flow';
513
              } else if (currentPoint['value'] < 0) {
514
                circleElement.className.baseVal = 'flow-reverse';
515
              } else {
516
                circleElement.className.baseVal = '';
517
              }
518
            }
519
          });
520
        }
521
      })
522
      .catch(err => {
523
        console.log(err);
524
      });
525
  };
526
527
  useInterval(() => {
528
    refreshSVGData();
529
  }, 1000 * 10);
530
531
  // BMS
532
  const fetchBMSDetails = () => {
533
    let url = APIBaseURL + '/reports/microgriddetails/' + microgridID + '/bms';
534
    let isResponseOK = false;
535
    fetch(url, {
536
      method: 'GET',
537
      headers: {
538
        'Content-type': 'application/json',
539
        'User-UUID': getCookieValue('user_uuid'),
540
        Token: getCookieValue('token')
541
      },
542
      body: null
543
    })
544
      .then(response => {
545
        if (response.ok) {
546
          isResponseOK = true;
547
        }
548
        return response.json();
549
      })
550
      .then(json => {
551
        if (isResponseOK) {
552
          setBMSDetailsList(json);
553
        } else {
554
          toast.error(t(json.description));
555
        }
556
      })
557
      .catch(err => {
558
        console.log(err);
559
      });
560
  };
561
  // EVCharger
562
  const fetchEVChargerDetails = () => {
563
    let url = APIBaseURL + '/reports/microgriddetails/' + microgridID + '/evcharger';
564
    let isResponseOK = false;
565
    fetch(url, {
566
      method: 'GET',
567
      headers: {
568
        'Content-type': 'application/json',
569
        'User-UUID': getCookieValue('user_uuid'),
570
        Token: getCookieValue('token')
571
      },
572
      body: null
573
    })
574
      .then(response => {
575
        if (response.ok) {
576
          isResponseOK = true;
577
        }
578
        return response.json();
579
      })
580
      .then(json => {
581
        if (isResponseOK) {
582
          setEVChargerDetailsList(json);
583
        } else {
584
          toast.error(t(json.description));
585
        }
586
      })
587
      .catch(err => {
588
        console.log(err);
589
      });
590
  };
591
592
  // PCS
593
  const fetchPCSDetails = () => {
594
    let url = APIBaseURL + '/reports/microgriddetails/' + microgridID + '/pcs';
595
    let isResponseOK = false;
596
    fetch(url, {
597
      method: 'GET',
598
      headers: {
599
        'Content-type': 'application/json',
600
        'User-UUID': getCookieValue('user_uuid'),
601
        Token: getCookieValue('token')
602
      },
603
      body: null
604
    })
605
      .then(response => {
606
        if (response.ok) {
607
          isResponseOK = true;
608
        }
609
        return response.json();
610
      })
611
      .then(json => {
612
        if (isResponseOK) {
613
          setPCSDetailsList(json);
614
        } else {
615
          toast.error(t(json.description));
616
        }
617
      })
618
      .catch(err => {
619
        console.log(err);
620
      });
621
  };
622
623
  // PV
624
  const fetchPVDetails = () => {
625
    let url = APIBaseURL + '/reports/microgriddetails/' + microgridID + '/pv';
626
    let isResponseOK = false;
627
    fetch(url, {
628
      method: 'GET',
629
      headers: {
630
        'Content-type': 'application/json',
631
        'User-UUID': getCookieValue('user_uuid'),
632
        Token: getCookieValue('token')
633
      },
634
      body: null
635
    })
636
      .then(response => {
637
        if (response.ok) {
638
          isResponseOK = true;
639
        }
640
        return response.json();
641
      })
642
      .then(json => {
643
        if (isResponseOK) {
644
          setPVDetailsList(json);
645
        } else {
646
          toast.error(t(json.description));
647
        }
648
      })
649
      .catch(err => {
650
        console.log(err);
651
      });
652
  };
653
  // Generator
654
  const fetchGeneratorDetails = () => {
655
    let url = APIBaseURL + '/reports/microgriddetails/' + microgridID + '/generator';
656
    let isResponseOK = false;
657
    fetch(url, {
658
      method: 'GET',
659
      headers: {
660
        'Content-type': 'application/json',
661
        'User-UUID': getCookieValue('user_uuid'),
662
        Token: getCookieValue('token')
663
      },
664
      body: null
665
    })
666
      .then(response => {
667
        if (response.ok) {
668
          isResponseOK = true;
669
        }
670
        return response.json();
671
      })
672
      .then(json => {
673
        if (isResponseOK) {
674
          setGeneratorDetailsList(json);
675
        } else {
676
          toast.error(t(json.description));
677
        }
678
      })
679
      .catch(err => {
680
        console.log(err);
681
      });
682
  };
683
  // Grid
684
  const fetchGridDetails = () => {
685
    let url = APIBaseURL + '/reports/microgriddetails/' + microgridID + '/grid';
686
    let isResponseOK = false;
687
    fetch(url, {
688
      method: 'GET',
689
      headers: {
690
        'Content-type': 'application/json',
691
        'User-UUID': getCookieValue('user_uuid'),
692
        Token: getCookieValue('token')
693
      },
694
      body: null
695
    })
696
      .then(response => {
697
        if (response.ok) {
698
          isResponseOK = true;
699
        }
700
        return response.json();
701
      })
702
      .then(json => {
703
        if (isResponseOK) {
704
          setGridDetailsList(json);
705
        } else {
706
          toast.error(t(json.description));
707
        }
708
      })
709
      .catch(err => {
710
        console.log(err);
711
      });
712
  };
713
  // Load
714
  const fetchLoadDetails = () => {
715
    let url = APIBaseURL + '/reports/microgriddetails/' + microgridID + '/load';
716
    let isResponseOK = false;
717
    fetch(url, {
718
      method: 'GET',
719
      headers: {
720
        'Content-type': 'application/json',
721
        'User-UUID': getCookieValue('user_uuid'),
722
        Token: getCookieValue('token')
723
      },
724
      body: null
725
    })
726
      .then(response => {
727
        if (response.ok) {
728
          isResponseOK = true;
729
        }
730
        return response.json();
731
      })
732
      .then(json => {
733
        if (isResponseOK) {
734
          setLoadDetailsList(json);
735
        } else {
736
          toast.error(t(json.description));
737
        }
738
      })
739
      .catch(err => {
740
        console.log(err);
741
      });
742
  };
743
  // Heatpump
744
  const fetchHeatpumpDetails = () => {
745
    let url = APIBaseURL + '/reports/microgriddetails/' + microgridID + '/heatpump';
746
    let isResponseOK = false;
747
    fetch(url, {
748
      method: 'GET',
749
      headers: {
750
        'Content-type': 'application/json',
751
        'User-UUID': getCookieValue('user_uuid'),
752
        Token: getCookieValue('token')
753
      },
754
      body: null
755
    })
756
      .then(response => {
757
        if (response.ok) {
758
          isResponseOK = true;
759
        }
760
        return response.json();
761
      })
762
      .then(json => {
763
        if (isResponseOK) {
764
          setHeatpumpDetailsList(json);
765
        } else {
766
          toast.error(t(json.description));
767
        }
768
      })
769
      .catch(err => {
770
        console.log(err);
771
      });
772
  };
773
774
  return (
775
    <Fragment>
776
      <Form>
777
        <Row form>
778
          <Col xs={6} sm={3} hidden={spaceCascaderHidden}>
779
            <FormGroup className="form-group">
780
              <Cascader options={cascaderOptions} onChange={onSpaceCascaderChange} changeOnSelect expandTrigger="hover">
781
                <Input bsSize="sm" value={selectedSpaceName || ''} readOnly />
782
              </Cascader>
783
            </FormGroup>
784
          </Col>
785
          <Col xs="auto">
786
            <FormGroup>
787
              <Form inline>
788
                <CustomInput
789
                  type="select"
790
                  id="microgridSelect"
791
                  name="microgridSelect"
792
                  bsSize="sm"
793
                  onChange={onMicrogridChange}
794
                  value={selectedMicrogrid || ''}
795
                >
796
                  <option value="">{t('Select Microgrid')}</option>
797
                  {filteredMicrogridList.map((microgrid, index) => (
798
                    <option value={microgrid.value} key={index}>
799
                      {microgrid.label}
800
                    </option>
801
                  ))}
802
                </CustomInput>
803
              </Form>
804
            </FormGroup>
805
          </Col>
806
          <Col xs="auto">
807
            <FormGroup>
808
              <Spinner color="primary" hidden={spinnerHidden} />
809
            </FormGroup>
810
          </Col>
811
        </Row>
812
      </Form>
813
      <div style={{ visibility: resultDataHidden ? 'visible' : 'hidden', display: resultDataHidden ? '' : 'none' }}>
814
        <img className="img-fluid" src={blankPage} alt="" />
815
      </div>
816
      <div style={{ visibility: resultDataHidden ? 'hidden' : 'visible', display: resultDataHidden ? 'none' : '' }}>
817
      <Row noGutters>
818
        <Col lg="3" className="pr-lg-2">
819
          <Nav tabs>
820
            <NavItem className="cursor-pointer">
821
              <NavLink
822
                className={classNames({ active: activeTabLeft === '1' })}
823
                onClick={() => {
824
                  toggleTabLeft('1');
825
                }}
826
              >
827
                <h6>{t('Energy Indicator')}</h6>
828
              </NavLink>
829
            </NavItem>
830
            <NavItem className="cursor-pointer">
831
              <NavLink
832
                className={classNames({ active: activeTabLeft === '2' })}
833
                onClick={() => {
834
                  toggleTabLeft('2');
835
                }}
836
              >
837
                <h6>{t('Revenue Indicator')}</h6>
838
              </NavLink>
839
            </NavItem>
840
            <NavItem className="cursor-pointer">
841
              <NavLink
842
                className={classNames({ active: activeTabLeft === '3' })}
843
                onClick={() => {
844
                  toggleTabLeft('3');
845
                }}
846
              >
847
                <h6>{t('Carbon Indicator')}</h6>
848
              </NavLink>
849
            </NavItem>
850
          </Nav>
851
          <TabContent activeTab={activeTabLeft}>
852
            <TabPane tabId="1">
853
              <Card className="mb-3 fs--1">
854
                <Fragment>
855
                  <CardBody className="pt-0">
856
                    <Table borderless className="fs--1 mb-0">
857
                      <tbody>
858
                        <tr className="border-bottom">
859
                          <th className="pl-0">{t("Today's Charge")}</th>
860
                          <th className="pr-0 text-right">{todayChargeEnergyValue} kWh</th>
861
                        </tr>
862
                        <tr className="border-bottom">
863
                          <th className="pl-0">{t("Today's Discharge")}</th>
864
                          <th className="pr-0 text-right ">{todayDischargeEnergyValue} kWh</th>
865
                        </tr>
866
                        <tr className="border-bottom">
867
                          <th className="pl-0 pb-0">{t('Total Charge')}</th>
868
                          <th className="pr-0 text-right">{totalChargeEnergyValue} kWh</th>
869
                        </tr>
870
                        <tr className="border-bottom">
871
                          <th className="pl-0 pb-0">{t('Total Discharge')}</th>
872
                          <th className="pr-0 text-right">{totalDischargeEnergyValue} kWh</th>
873
                        </tr>
874
                        <tr className="border-bottom">
875
                          <th className="pl-0 pb-0">{t('Total Efficiency')}</th>
876
                          <th className="pr-0 text-right">{totalEfficiency}%</th>
877
                        </tr>
878
                        <tr className="border-bottom">
879
                          <th className="pl-0 pb-0">{t('Discharge Achievement Rate')}</th>
880
                          <th className="pr-0 text-right">
881
                            {((100 * todayDischargeEnergyValue) / microgridRatedCapacity).toFixed(2)}%
882
                          </th>
883
                        </tr>
884
                      </tbody>
885
                    </Table>
886
                  </CardBody>
887
                </Fragment>
888
              </Card>
889
            </TabPane>
890
            <TabPane tabId="2">
891
              <Card className="mb-3 fs--1">
892
                <Fragment>
893
                  <CardBody className="pt-0">
894
                    <Table borderless className="fs--1 mb-0">
895
                      <tbody>
896
                        <tr className="border-bottom">
897
                          <th className="pl-0">{t("Today's Cost")}</th>
898
                          <th className="pr-0 text-right">
899
                            {todayChargeRevenueValue} {currency}
900
                          </th>
901
                        </tr>
902
                        <tr className="border-bottom">
903
                          <th className="pl-0 pb-0">{t("Today's Revenue")}</th>
904
                          <th className="pr-0 text-right">
905
                            {todayDischargeRevenueValue} {currency}
906
                          </th>
907
                        </tr>
908
                        <tr className="border-bottom">
909
                          <th className="pl-0">{t('Total Cost')}</th>
910
                          <th className="pr-0 text-right ">
911
                            {totalChargeRevenueValue} {currency}
912
                          </th>
913
                        </tr>
914
                        <tr className="border-bottom">
915
                          <th className="pl-0 pb-0">{t('Total Revenue')}</th>
916
                          <th className="pr-0 text-right">
917
                            {totalDischargeRevenueValue} {currency}
918
                          </th>
919
                        </tr>
920
                        <tr className="border-bottom">
921
                          <th className="pl-0 pb-0">{t("Today's Profit")}</th>
922
                          <th className="pr-0 text-right">
923
                            {(todayDischargeRevenueValue - todayChargeRevenueValue).toFixed(2)} {currency}
924
                          </th>
925
                        </tr>
926
                        <tr className="border-bottom">
927
                          <th className="pl-0 pb-0">{t('Total Profit')}</th>
928
                          <th className="pr-0 text-right">
929
                            {(totalDischargeRevenueValue - totalChargeRevenueValue).toFixed(2)} {currency}
930
                          </th>
931
                        </tr>
932
                      </tbody>
933
                    </Table>
934
                  </CardBody>
935
                </Fragment>
936
              </Card>
937
            </TabPane>
938
            <TabPane tabId="3">
939
              <Card className="mb-3 fs--1">
940
                <Fragment>
941
                  <CardBody className="pt-0">
942
                    <Table borderless className="fs--1 mb-0">
943
                      <tbody>
944
                        <tr className="border-bottom">
945
                          <th className="pl-0">{t("Today's Emission")} </th>
946
                          <th className="pr-0 text-right">{todayChargeCarbonValue} kgCO2</th>
947
                        </tr>
948
                        <tr className="border-bottom">
949
                          <th className="pl-0 pb-0">{t("Today's Reduction")}</th>
950
                          <th className="pr-0 text-right">{todayDischargeCarbonValue} kgCO2</th>
951
                        </tr>
952
                        <tr className="border-bottom">
953
                          <th className="pl-0">{t('Total Emission')}</th>
954
                          <th className="pr-0 text-right ">{totalChargeCarbonValue} kgCO2</th>
955
                        </tr>
956
                        <tr className="border-bottom">
957
                          <th className="pl-0 pb-0">{t('Total Reduction')}</th>
958
                          <th className="pr-0 text-right">{totalDischargeCarbonValue} kgCO2</th>
959
                        </tr>
960
                        <tr className="border-bottom">
961
                          <th className="pl-0 pb-0">{t("Today's Net Reduction")}</th>
962
                          <th className="pr-0 text-right">
963
                            {(todayDischargeCarbonValue - todayChargeCarbonValue).toFixed(2)} kgCO2
964
                          </th>
965
                        </tr>
966
                        <tr className="border-bottom">
967
                          <th className="pl-0 pb-0">{t('Total Net Reduction')}</th>
968
                          <th className="pr-0 text-right">
969
                            {(totalDischargeCarbonValue - totalChargeCarbonValue).toFixed(2)} kgCO2
970
                          </th>
971
                        </tr>
972
                      </tbody>
973
                    </Table>
974
                  </CardBody>
975
                </Fragment>
976
              </Card>
977
            </TabPane>
978
          </TabContent>
979
        </Col>
980
        <Col lg="6" className="pr-lg-2" key={uuid()}>
981
          <div
982
            style={{
983
              position: isFullscreen ? 'fixed' : 'relative',
984
              top: isFullscreen ? 0 : 'auto',
985
              left: isFullscreen ? 0 : 'auto',
986
              width: isFullscreen ? '100vw' : '100%',
987
              height: isFullscreen ? '100vh' : 'auto',
988
              backgroundColor: isFullscreen ? '#fff' : 'transparent',
989
              zIndex: isFullscreen ? 9999 : 'auto',
990
              display: isFullscreen ? 'flex' : 'block',
991
              alignItems: isFullscreen ? 'center' : 'flex-start',
992
              justifyContent: isFullscreen ? 'center' : 'flex-start',
993
              overflow: isFullscreen ? 'auto' : 'visible',
994
              padding: isFullscreen ? '20px' : '0'
995
            }}
996
          >
997
            <Button
998
              color="secondary"
999
              size="sm"
1000
              onClick={toggleFullscreen}
1001
              style={{
1002
                position: 'absolute',
1003
                top: isFullscreen ? '20px' : '10px',
1004
                right: isFullscreen ? '20px' : '10px',
1005
                zIndex: isFullscreen ? 10000 : 10,
1006
                opacity: 0.8,
1007
                minWidth: '32px',
1008
                padding: '4px 8px'
1009
              }}
1010
              title={isFullscreen ? '退出全屏' : '全屏显示'}
1011
            >
1012
              {isFullscreen ? '✕' : '⛶'}
1013
            </Button>
1014
            <div
1015
              style={{
1016
                width: isFullscreen ? '100%' : '100%',
1017
                height: isFullscreen ? '100%' : 'auto',
1018
                display: isFullscreen ? 'flex' : 'block',
1019
                alignItems: isFullscreen ? 'center' : 'flex-start',
1020
                justifyContent: isFullscreen ? 'center' : 'flex-start',
1021
                maxWidth: isFullscreen ? '100%' : '100%',
1022
                maxHeight: isFullscreen ? '100%' : 'none',
1023
                overflow: isFullscreen ? 'auto' : 'visible'
1024
              }}
1025
              dangerouslySetInnerHTML={microgridSVG}
1026
            />
1027
          </div>
1028
        </Col>
1029
        <Col lg="3" className="pr-lg-2">
1030
          <Nav tabs>
1031
            <NavItem className="cursor-pointer">
1032
              <NavLink
1033
                className={classNames({ active: activeTabRight === '1' })}
1034
                onClick={() => {
1035
                  toggleTabRight('1');
1036
                }}
1037
              >
1038
                <h6>{t('Device Status')}</h6>
1039
              </NavLink>
1040
            </NavItem>
1041
            <NavItem className="cursor-pointer">
1042
              <NavLink
1043
                className={classNames({ active: activeTabRight === '2' })}
1044
                onClick={() => {
1045
                  toggleTabRight('2');
1046
                }}
1047
              >
1048
                <h6>{t('Basic Information')}</h6>
1049
              </NavLink>
1050
            </NavItem>
1051
          </Nav>
1052
          <TabContent activeTab={activeTabRight}>
1053
            <TabPane tabId="1">
1054
              <Card className="mb-3 fs--1">
1055
                <Fragment>
1056
                  <CardBody className="pt-0">
1057
                    <Table borderless className="fs--1 mb-0">
1058
                      <tbody>
1059
                        <tr className="border-bottom">
1060
                          <th className="pl-0 pb-0">网关</th>
1061
                          <th className="pr-0 text-right">在线</th>
1062
                        </tr>
1063
                        <tr className="border-bottom">
1064
                          <th className="pl-0">储能</th>
1065
                          <th className="pr-0 text-right">运行</th>
1066
                        </tr>
1067
                        <tr className="border-bottom">
1068
                          <th className="pl-0">负载</th>
1069
                          <th className="pr-0 text-right ">运行</th>
1070
                        </tr>
1071
                        <tr className="border-bottom">
1072
                          <th className="pl-0 pb-0">光伏</th>
1073
                          <th className="pr-0 text-right">运行</th>
1074
                        </tr>
1075
                        <tr className="border-bottom">
1076
                          <th className="pl-0 pb-0">充电桩</th>
1077
                          <th className="pr-0 text-right">运行</th>
1078
                        </tr>
1079
                        <tr className="border-bottom">
1080
                          <th className="pl-0 pb-0">电网表</th>
1081
                          <th className="pr-0 text-right">运行</th>
1082
                        </tr>
1083
                      </tbody>
1084
                    </Table>
1085
                  </CardBody>
1086
                </Fragment>
1087
              </Card>
1088
            </TabPane>
1089
            <TabPane tabId="2">
1090
              <Card className="mb-3 fs--1">
1091
                <Fragment>
1092
                  <CardBody className="pt-0">
1093
                    <Table borderless className="fs--1 mb-0">
1094
                      <tbody>
1095
                        <tr className="border-bottom">
1096
                          <th className="pl-0">{t('Name')}</th>
1097
                          <th className="pr-0 text-right">{microgridName}</th>
1098
                        </tr>
1099
                        <tr className="border-bottom">
1100
                          <th className="pl-0">{t('Address')}</th>
1101
                          <th className="pr-0 text-right ">{microgridAddress}</th>
1102
                        </tr>
1103
                        <tr className="border-bottom">
1104
                          <th className="pl-0 pb-0">{t('Postal Code')}</th>
1105
                          <th className="pr-0 text-right">{microgridPostalCode}</th>
1106
                        </tr>
1107
                        <tr className="border-bottom">
1108
                          <th className="pl-0 pb-0">{t('Rated Capacity')} </th>
1109
                          <th className="pr-0 text-right">{microgridRatedCapacity} kWh</th>
1110
                        </tr>
1111
                        <tr className="border-bottom">
1112
                          <th className="pl-0 pb-0">{t('Rated Power')} </th>
1113
                          <th className="pr-0 text-right">{microgridRatedPower} kW</th>
1114
                        </tr>
1115
                      </tbody>
1116
                    </Table>
1117
                  </CardBody>
1118
                </Fragment>
1119
              </Card>
1120
            </TabPane>
1121
          </TabContent>
1122
        </Col>
1123
      </Row>
1124
      </div>
1125
1126
      {/* Overlay to cover content when bottom section is pinned and has no data */}
1127
      {isBottomSectionPinned && !hasTabData() && !resultDataHidden && (
1128
        <div
1129
          style={{
1130
            position: 'fixed',
1131
            top: '60px',
1132
            left: '250px',
1133
            width: 'calc(100% - 250px)',
1134
            height: 'calc(100vh - 60px)',
1135
            backgroundColor: '#fff',
1136
            zIndex: 9997,
1137
            pointerEvents: 'none'
1138
          }}
1139
        />
1140
      )}
1141
1142
      <div
1143
        style={{ visibility: resultDataHidden ? 'hidden' : 'visible', display: resultDataHidden ? 'none' : '' }}
1144
      >
1145
      <div
1146
        style={{
1147
          position: isBottomSectionPinned ? 'fixed' : 'relative',
1148
          top: isBottomSectionPinned ? '60px' : 'auto',
1149
          left: isBottomSectionPinned ? '250px' : 'auto',
1150
          width: isBottomSectionPinned ? 'calc(100% - 250px)' : 'auto',
1151
          backgroundColor: isBottomSectionPinned ? '#fff' : 'transparent',
1152
          zIndex: isBottomSectionPinned ? 9998 : 'auto',
1153
          padding: isBottomSectionPinned ? '10px 15px' : '0',
1154
          paddingTop: isBottomSectionPinned ? '10px' : '40px',
1155
          boxShadow: isBottomSectionPinned ? '0 2px 8px rgba(0,0,0,0.1)' : 'none',
1156
          marginTop: isBottomSectionPinned ? '0' : 'auto'
1157
        }}
1158
      >
1159
        {!isFullscreen && (
1160
          <Button
1161
            color="secondary"
1162
            size="sm"
1163
            onClick={toggleBottomSectionPin}
1164
            style={{
1165
              position: 'absolute',
1166
              top: isBottomSectionPinned ? '10px' : '5px',
1167
              right: '10px',
1168
              zIndex: 9999,
1169
              opacity: 0.8,
1170
              minWidth: '32px',
1171
              padding: '4px 8px'
1172
            }}
1173
            title={isBottomSectionPinned ? '恢复原位置' : '提升到顶部'}
1174
          >
1175
            {isBottomSectionPinned ? '↓' : '↑'}
1176
          </Button>
1177
        )}
1178
        <Nav tabs>
1179
        <NavItem className="cursor-pointer">
1180
          <NavLink
1181
            className={classNames({ active: activeTabBottom === '1' })}
1182
            onClick={() => {
1183
              toggleTabBottom('1');
1184
            }}
1185
          >
1186
            <h6>{t('Operating Characteristic Curve')}</h6>
1187
          </NavLink>
1188
        </NavItem>
1189
        <NavItem className="cursor-pointer">
1190
          <NavLink
1191
            className={classNames({ active: activeTabBottom === '2' })}
1192
            onClick={() => {
1193
              toggleTabBottom('2');
1194
            }}
1195
          >
1196
            <h6>{t('Strategy Management')}</h6>
1197
          </NavLink>
1198
        </NavItem>
1199
        <NavItem className="cursor-pointer">
1200
          <NavLink
1201
            className={classNames({ active: activeTabBottom === '3' })}
1202
            onClick={() => {
1203
              toggleTabBottom('3');
1204
            }}
1205
          >
1206
            <h6>{t('Fault Alarms')}</h6>
1207
          </NavLink>
1208
        </NavItem>
1209
1210
        <NavItem className="cursor-pointer">
1211
          <NavLink
1212
            className={classNames({ active: activeTabBottom === '4' })}
1213
            onClick={() => {
1214
              toggleTabBottom('4');
1215
              fetchPCSDetails();
1216
            }}
1217
          >
1218
            <h6>{t('PCS')}</h6>
1219
          </NavLink>
1220
        </NavItem>
1221
1222
        <NavItem className="cursor-pointer">
1223
          <NavLink
1224
            className={classNames({ active: activeTabBottom === '5' })}
1225
            onClick={() => {
1226
              toggleTabBottom('5');
1227
              fetchBMSDetails();
1228
            }}
1229
          >
1230
            <h6>{t('BMS')}</h6>
1231
          </NavLink>
1232
        </NavItem>
1233
1234
        <NavItem className="cursor-pointer">
1235
          <NavLink
1236
            className={classNames({ active: activeTabBottom === '6' })}
1237
            onClick={() => {
1238
              toggleTabBottom('6');
1239
              fetchPVDetails();
1240
            }}
1241
          >
1242
            <h6>{t('Photovoltaic')}</h6>
1243
          </NavLink>
1244
        </NavItem>
1245
1246
        <NavItem className="cursor-pointer">
1247
          <NavLink
1248
            className={classNames({ active: activeTabBottom === '7' })}
1249
            onClick={() => {
1250
              toggleTabBottom('7');
1251
              fetchEVChargerDetails();
1252
            }}
1253
          >
1254
            <h6>{t('EV Charger')}</h6>
1255
          </NavLink>
1256
        </NavItem>
1257
1258
        <NavItem className="cursor-pointer">
1259
          <NavLink
1260
            className={classNames({ active: activeTabBottom === '8' })}
1261
            onClick={() => {
1262
              toggleTabBottom('8');
1263
              fetchGeneratorDetails();
1264
            }}
1265
          >
1266
            <h6>{t('Generator')}</h6>
1267
          </NavLink>
1268
        </NavItem>
1269
1270
        <NavItem className="cursor-pointer">
1271
          <NavLink
1272
            className={classNames({ active: activeTabBottom === '9' })}
1273
            onClick={() => {
1274
              toggleTabBottom('9');
1275
              fetchGridDetails();
1276
            }}
1277
          >
1278
            <h6>{t('Grid Meter')}</h6>
1279
          </NavLink>
1280
        </NavItem>
1281
1282
        <NavItem className="cursor-pointer">
1283
          <NavLink
1284
            className={classNames({ active: activeTabBottom === '10' })}
1285
            onClick={() => {
1286
              toggleTabBottom('10');
1287
              fetchLoadDetails();
1288
            }}
1289
          >
1290
            <h6>{t('Load Meter')}</h6>
1291
          </NavLink>
1292
        </NavItem>
1293
1294
        <NavItem className="cursor-pointer">
1295
          <NavLink
1296
            className={classNames({ active: activeTabBottom === '11' })}
1297
            onClick={() => {
1298
              toggleTabBottom('11');
1299
              fetchHeatpumpDetails();
1300
            }}
1301
          >
1302
            <h6>{t('Heat Pump')}</h6>
1303
          </NavLink>
1304
        </NavItem>
1305
      </Nav>
1306
      <div
1307
        style={{
1308
          maxHeight: isBottomSectionPinned ? 'calc(100vh - 200px)' : '600px',
1309
          overflowY: 'auto',
1310
          overflowX: 'hidden'
1311
        }}
1312
      >
1313
        <TabContent activeTab={activeTabBottom}>
1314
          <TabPane tabId="1">
1315
            <MultipleLineChart
1316
              reportingTitle=""
1317
              baseTitle=""
1318
              labels={parameterLineChartLabels}
1319
              data={parameterLineChartData}
1320
              options={parameterLineChartOptions}
1321
            />
1322
          </TabPane>
1323
        <TabPane tabId="2">
1324
          <Card className="mb-3 fs--1">
1325
            <CardBody className="bg-light">
1326
              <SectionLineChart
1327
                xaxisData={scheduleXaxisData}
1328
                seriesName={scheduleSeriesName}
1329
                seriesData={scheduleSeriesData}
1330
                markAreaData={scheduleMarkAreaData}
1331
              />
1332
            </CardBody>
1333
          </Card>
1334
        </TabPane>
1335
        <TabPane tabId="3">
1336
          <Card className="mb-3 fs--1">
1337
            <CardBody className="bg-light">
1338
              <Table striped className="border-bottom">
1339
                <thead>
1340
                  <tr>
1341
                    <th>#</th>
1342
                    <th>{t('Subject')}</th>
1343
                    <th>{t('Datetime')}</th>
1344
                    <th>{t('Start Datetime')}</th>
1345
                    <th>{t('End Datetime')}</th>
1346
                    <th>{t('Content')}</th>
1347
                    <th>{t('Status')}</th>
1348
                    <th>{t('Update Datetime')}</th>
1349
                  </tr>
1350
                </thead>
1351
                <tbody>
1352
                  <tr>
1353
                    <th scope="row">1</th>
1354
                    <td />
1355
                    <td />
1356
                    <td />
1357
                    <td />
1358
                    <td />
1359
                    <td />
1360
                    <td />
1361
                  </tr>
1362
                  <tr>
1363
                    <th scope="row">2</th>
1364
                    <td />
1365
                    <td />
1366
                    <td />
1367
                    <td />
1368
                    <td />
1369
                    <td />
1370
                    <td />
1371
                  </tr>
1372
                  <tr>
1373
                    <th scope="row">3</th>
1374
                    <td />
1375
                    <td />
1376
                    <td />
1377
                    <td />
1378
                    <td />
1379
                    <td />
1380
                    <td />
1381
                  </tr>
1382
                  <tr>
1383
                    <th scope="row">4</th>
1384
                    <td />
1385
                    <td />
1386
                    <td />
1387
                    <td />
1388
                    <td />
1389
                    <td />
1390
                    <td />
1391
                  </tr>
1392
                </tbody>
1393
              </Table>
1394
            </CardBody>
1395
          </Card>
1396
        </TabPane>
1397
        <TabPane tabId="4">
1398
          {isIterableArray(PCSDetailsList) &&
1399
            PCSDetailsList.map(({ id, ...rest }) => <DetailsTable key={id} id={id} {...rest} />)}
1400
        </TabPane>
1401
        <TabPane tabId="5">
1402
          {isIterableArray(BMSDetailsList) &&
1403
            BMSDetailsList.map(({ id, ...rest }) => <DetailsTable key={id} id={id} {...rest} />)}
1404
        </TabPane>
1405
        <TabPane tabId="6">
1406
          {isIterableArray(PVDetailsList) &&
1407
            PVDetailsList.map(({ id, ...rest }) => <DetailsTable key={id} id={id} {...rest} />)}
1408
        </TabPane>
1409
        <TabPane tabId="7">
1410
          {isIterableArray(EVChargerDetailsList) &&
1411
            EVChargerDetailsList.map(({ id, ...rest }) => <DetailsTable key={id} id={id} {...rest} />)}
1412
        </TabPane>
1413
        <TabPane tabId="8">
1414
          {isIterableArray(GeneratorDetailsList) &&
1415
            GeneratorDetailsList.map(({ id, ...rest }) => <DetailsTable key={id} id={id} {...rest} />)}
1416
        </TabPane>
1417
        <TabPane tabId="9">
1418
          {isIterableArray(GeneratorDetailsList) &&
1419
            GeneratorDetailsList.map(({ id, ...rest }) => <DetailsTable key={id} id={id} {...rest} />)}
1420
        </TabPane>
1421
        <TabPane tabId="10">
1422
          {isIterableArray(GeneratorDetailsList) &&
1423
            GeneratorDetailsList.map(({ id, ...rest }) => <DetailsTable key={id} id={id} {...rest} />)}
1424
        </TabPane>
1425
        <TabPane tabId="11">
1426
          {isIterableArray(GeneratorDetailsList) &&
1427
            GeneratorDetailsList.map(({ id, ...rest }) => <DetailsTable key={id} id={id} {...rest} />)}
1428
        </TabPane>
1429
      </TabContent>
1430
      </div>
1431
      </div>
1432
      </div>
1433
    </Fragment>
1434
  );
1435
};
1436
1437
export default withTranslation()(withRedirect(MicrogridDetails));
1438