Passed
Push — master ( 570acf...bff261 )
by Guangyu
08:10 queued 12s
created

myems-web/src/components/MyEMS/Space/SpaceCarbon.js   A

Complexity

Total Complexity 29
Complexity/F 0

Size

Lines of Code 745
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 29
eloc 652
dl 0
loc 745
rs 9.948
c 0
b 0
f 0
mnd 29
bc 29
fnc 0
bpm 0
cpm 0
noi 0
1
import React, { Fragment, useEffect, useState } from 'react';
2
import {
3
  Breadcrumb,
4
  BreadcrumbItem,
5
  Row,
6
  Col,
7
  Card,
8
  CardBody,
9
  Button,
10
  ButtonGroup,
11
  Form,
12
  FormGroup,
13
  Input,
14
  Label,
15
  CustomInput,
16
  Spinner
17
} from 'reactstrap';
18
import CountUp from 'react-countup';
19
import moment from 'moment';
20
import loadable from '@loadable/component';
21
import Cascader from 'rc-cascader';
22
import CardSummary from '../common/CardSummary';
23
import LineChart from '../common/LineChart';
24
import SharePie from '../common/SharePie';
25
import { getCookieValue, createCookie } from '../../../helpers/utils';
26
import withRedirect from '../../../hoc/withRedirect';
27
import { withTranslation } from 'react-i18next';
28
import { toast } from 'react-toastify';
29
import ButtonIcon from '../../common/ButtonIcon';
30
import { APIBaseURL } from '../../../config';
31
import uuid from 'uuid/v1';
32
import { periodTypeOptions } from '../common/PeriodTypeOptions';
33
import { comparisonTypeOptions } from '../common/ComparisonTypeOptions';
34
import { DateRangePicker } from 'rsuite';
35
import { endOfDay} from 'date-fns';
36
37
const ChildSpacesTable = loadable(() => import('../common/ChildSpacesTable'));
38
const DetailedDataTable = loadable(() => import('../common/DetailedDataTable'));
39
40
const SpaceCarbon = ({ setRedirect, setRedirectUrl, t }) => {
41
  let current_moment = moment();
42
  useEffect(() => {
43
    let is_logged_in = getCookieValue('is_logged_in');
44
    let user_name = getCookieValue('user_name');
45
    let user_display_name = getCookieValue('user_display_name');
46
    let user_uuid = getCookieValue('user_uuid');
47
    let token = getCookieValue('token');
48
    if (is_logged_in === null || !is_logged_in) {
49
      setRedirectUrl(`/authentication/basic/login`);
50
      setRedirect(true);
51
    } else {
52
      //update expires time of cookies
53
      createCookie('is_logged_in', true, 1000 * 60 * 60 * 8);
54
      createCookie('user_name', user_name, 1000 * 60 * 60 * 8);
55
      createCookie('user_display_name', user_display_name, 1000 * 60 * 60 * 8);
56
      createCookie('user_uuid', user_uuid, 1000 * 60 * 60 * 8);
57
      createCookie('token', token, 1000 * 60 * 60 * 8);
58
    }
59
  });
60
  // State
61
  // Query Parameters
62
  const [selectedSpaceName, setSelectedSpaceName] = useState(undefined);
63
  const [selectedSpaceID, setSelectedSpaceID] = useState(undefined);
64
  const [comparisonType, setComparisonType] = useState('month-on-month');
65
  const [periodType, setPeriodType] = useState('daily');
66
  const [cascaderOptions, setCascaderOptions] = useState(undefined);
67
  const [basePeriodDateRange, setBasePeriodDateRange] = useState([current_moment.clone().subtract(1, 'months').startOf('month').toDate(), current_moment.clone().subtract(1, 'months').toDate()]);
68
  const [basePeriodDateRangePickerDisabled, setBasePeriodDateRangePickerDisabled] = useState(true);
69
  const [reportingPeriodDateRange, setReportingPeriodDateRange] = useState([current_moment.clone().startOf('month').toDate(), current_moment.toDate()]);
70
  const dateRangePickerLocale = {
71
    sunday: t('sunday'),
72
    monday: t('monday'),
73
    tuesday: t('tuesday'),
74
    wednesday: t('wednesday'),
75
    thursday: t('thursday'),
76
    friday: t('friday'),
77
    saturday: t('saturday'),
78
    ok: t('ok'),
79
    today: t('today'),
80
    yesterday: t('yesterday'),
81
    hours: t('hours'),
82
    minutes: t('minutes'),
83
    seconds: t('seconds'),
84
    last7Days: t('last7Days')
85
  };
86
  const dateRangePickerStyle = { display: 'block', zIndex: 10};
87
  
88
  // buttons
89
  const [submitButtonDisabled, setSubmitButtonDisabled] = useState(true);
90
  const [spinnerHidden, setSpinnerHidden] = useState(true);
91
  const [exportButtonHidden, setExportButtonHidden] = useState(true);
92
  
93
  //Results
94
  const [timeOfUseShareData, setTimeOfUseShareData] = useState([]);
95
  const [carbonShareData, setCarbonShareData] = useState([]);
96
97
  const [cardSummaryList, setCardSummaryList] = useState([]);
98
  const [spaceLineChartLabels, setSpaceLineChartLabels] = useState([]);
99
  const [spaceLineChartData, setSpaceLineChartData] = useState({});
100
  const [spaceLineChartOptions, setSpaceLineChartOptions] = useState([]);
101
  const [childSpaceProportionList, setChildSpaceProportionList] = useState([]);
102
  const [childSpaceSubtotalShareData, setChildSpaceSubtotalShareData] = useState([]);
103
104
  const [parameterLineChartLabels, setParameterLineChartLabels] = useState([]);
105
  const [parameterLineChartData, setParameterLineChartData] = useState({});
106
  const [parameterLineChartOptions, setParameterLineChartOptions] = useState([]);
107
  
108
  const [detailedDataTableData, setDetailedDataTableData] = useState([]);
109
  const [detailedDataTableColumns, setDetailedDataTableColumns] = useState([{dataField: 'startdatetime', text: t('Datetime'), sort: true}]);
110
  
111
  const [childSpacesTableData, setChildSpacesTableData] = useState([]);
112
  const [childSpacesTableColumns, setChildSpacesTableColumns] = useState([{dataField: 'name', text: t('Child Spaces'), sort: true }]);
113
  const [excelBytesBase64, setExcelBytesBase64] = useState(undefined);
114
115
  useEffect(() => {
116
    let isResponseOK = false;
117
    fetch(APIBaseURL + '/spaces/tree', {
118
      method: 'GET',
119
      headers: {
120
        "Content-type": "application/json",
121
        "User-UUID": getCookieValue('user_uuid'),
122
        "Token": getCookieValue('token')
123
      },
124
      body: null,
125
126
    }).then(response => {
127
      console.log(response);
128
      if (response.ok) {
129
        isResponseOK = true;
130
        // enable submit button
131
        setSubmitButtonDisabled(false);
132
      }
133
      return response.json();
134
    }).then(json => {
135
      console.log(json);
136
      if (isResponseOK) {
137
        // rename keys 
138
        json = JSON.parse(JSON.stringify([json]).split('"id":').join('"value":').split('"name":').join('"label":'));
139
        setCascaderOptions(json);
140
        setSelectedSpaceName([json[0]].map(o => o.label));
141
        setSelectedSpaceID([json[0]].map(o => o.value));
142
      } else {
143
        toast.error(json.description);
144
      }
145
    }).catch(err => {
146
      console.log(err);
147
    });
148
149
  }, []);
150
151
  const labelClasses = 'ls text-uppercase text-600 font-weight-semi-bold mb-0';
152
153
  let onSpaceCascaderChange = (value, selectedOptions) => {
154
    console.log(value, selectedOptions);
155
    setSelectedSpaceName(selectedOptions.map(o => o.label).join('/'));
156
    setSelectedSpaceID(value[value.length - 1]);
157
  }
158
159
160
  let onComparisonTypeChange = ({ target }) => {
161
    console.log(target.value);
162
    setComparisonType(target.value);
163
    if (target.value === 'year-over-year') {
164
      setBasePeriodDateRangePickerDisabled(true);
165
      setBasePeriodDateRange([moment(reportingPeriodDateRange[0]).subtract(1, 'years').toDate(),
166
        moment(reportingPeriodDateRange[1]).subtract(1, 'years').toDate()]);
167
    } else if (target.value === 'month-on-month') {
168
      setBasePeriodDateRangePickerDisabled(true);
169
      setBasePeriodDateRange([moment(reportingPeriodDateRange[0]).subtract(1, 'months').toDate(),
170
        moment(reportingPeriodDateRange[1]).subtract(1, 'months').toDate()]);
171
    } else if (target.value === 'free-comparison') {
172
      setBasePeriodDateRangePickerDisabled(false);
173
    } else if (target.value === 'none-comparison') {
174
      setBasePeriodDateRange([null, null]);
175
      setBasePeriodDateRangePickerDisabled(true);
176
    }
177
  };
178
179
  // Callback fired when value changed
180
  let onBasePeriodChange = (DateRange) => {
181
    if(DateRange == null) {
182
      setBasePeriodDateRange([null, null]);
183
    } else {
184
      if (moment(DateRange[1]).format('HH:mm:ss') == '00:00:00') {
185
        // if the user did not change time value, set the default time to the end of day
186
        DateRange[1] = endOfDay(DateRange[1]);
187
      }
188
      setBasePeriodDateRange([DateRange[0], DateRange[1]]);
189
    }
190
  };
191
192
  // Callback fired when value changed
193
  let onReportingPeriodChange = (DateRange) => {
194
    if(DateRange == null) {
195
      setReportingPeriodDateRange([null, null]);
196
    } else {
197
      if (moment(DateRange[1]).format('HH:mm:ss') == '00:00:00') {
198
        // if the user did not change time value, set the default time to the end of day
199
        DateRange[1] = endOfDay(DateRange[1]);
200
      }
201
      setReportingPeriodDateRange([DateRange[0], DateRange[1]]);
202
      if (comparisonType === 'year-over-year') {
203
        setBasePeriodDateRange([moment(DateRange[0]).clone().subtract(1, 'years').toDate(), moment(DateRange[1]).clone().subtract(1, 'years').toDate()]);
204
      } else if (comparisonType === 'month-on-month') {
205
        setBasePeriodDateRange([moment(DateRange[0]).clone().subtract(1, 'months').toDate(), moment(DateRange[1]).clone().subtract(1, 'months').toDate()]);
206
      }
207
    }
208
  };
209
210
  // Callback fired when value clean
211
  let onBasePeriodClean = event => {
212
    setBasePeriodDateRange([null, null]);
213
  };
214
215
  // Callback fired when value clean
216
  let onReportingPeriodClean = event => {
217
    setReportingPeriodDateRange([null, null]);
218
  };
219
220
  // Handler
221
  const handleSubmit = e => {
222
    e.preventDefault();
223
    console.log('handleSubmit');
224
    console.log(selectedSpaceID);
225
    console.log(comparisonType);
226
    console.log(periodType);
227
    console.log(basePeriodDateRange[0] != null ? moment(basePeriodDateRange[0]).format('YYYY-MM-DDTHH:mm:ss') : null)
228
    console.log(basePeriodDateRange[1] != null ? moment(basePeriodDateRange[1]).format('YYYY-MM-DDTHH:mm:ss') : null)
229
    console.log(moment(reportingPeriodDateRange[0]).format('YYYY-MM-DDTHH:mm:ss'))
230
    console.log(moment(reportingPeriodDateRange[1]).format('YYYY-MM-DDTHH:mm:ss'));
231
    
232
    // disable submit button
233
    setSubmitButtonDisabled(true);
234
    // show spinner
235
    setSpinnerHidden(false);
236
    // hide export button
237
    setExportButtonHidden(true)
238
239
    // Reinitialize tables
240
    setDetailedDataTableData([]);
241
    setChildSpacesTableData([]);
242
243
    let isResponseOK = false;
244
    fetch(APIBaseURL + '/reports/spacecarbon?' +
245
      'spaceid=' + selectedSpaceID +
246
      '&periodtype=' + periodType +
247
      '&baseperiodstartdatetime=' + (basePeriodDateRange[0] != null ? moment(basePeriodDateRange[0]).format('YYYY-MM-DDTHH:mm:ss') : '') +
248
      '&baseperiodenddatetime=' + (basePeriodDateRange[1] != null ? moment(basePeriodDateRange[1]).format('YYYY-MM-DDTHH:mm:ss') : '') +
249
      '&reportingperiodstartdatetime=' + moment(reportingPeriodDateRange[0]).format('YYYY-MM-DDTHH:mm:ss') +
250
      '&reportingperiodenddatetime=' + moment(reportingPeriodDateRange[1]).format('YYYY-MM-DDTHH:mm:ss'), {
251
      method: 'GET',
252
      headers: {
253
        "Content-type": "application/json",
254
        "User-UUID": getCookieValue('user_uuid'),
255
        "Token": getCookieValue('token')
256
      },
257
      body: null,
258
259
    }).then(response => {
260
      if (response.ok) {
261
        isResponseOK = true;
262
      }
263
      return response.json();
264
    }).then(json => {
265
      if (isResponseOK) {
266
        console.log(json)
267
268
        let cardSummaryList = []
269
        json['reporting_period']['names'].forEach((currentValue, index) => {
270
          let cardSummaryItem = {}
271
          cardSummaryItem['name'] = json['reporting_period']['names'][index];
272
          cardSummaryItem['unit'] = json['reporting_period']['units'][index];
273
          cardSummaryItem['subtotal'] = json['reporting_period']['subtotals'][index];
274
          cardSummaryItem['increment_rate'] = parseFloat(json['reporting_period']['increment_rates'][index] * 100).toFixed(2) + "%";
275
          cardSummaryItem['subtotal_per_unit_area'] = json['reporting_period']['subtotals_per_unit_area'][index];
276
          cardSummaryList.push(cardSummaryItem);
277
        });
278
        let cardSummaryItem = {}
279
        cardSummaryItem['name'] = t('Total');
280
        cardSummaryItem['unit'] = json['reporting_period']['total_unit'];
281
        cardSummaryItem['subtotal'] = json['reporting_period']['total'];
282
        cardSummaryItem['increment_rate'] = parseFloat(json['reporting_period']['total_increment_rate'] * 100).toFixed(2) + "%";
283
        cardSummaryItem['subtotal_per_unit_area'] = json['reporting_period']['total_per_unit_area'];
284
        cardSummaryList.push(cardSummaryItem);
285
        setCardSummaryList(cardSummaryList);
286
287
        let timeOfUseArray = [];
288
        json['reporting_period']['energy_category_ids'].forEach((currentValue, index) => {
289
          if(currentValue === 1) {
290
            // energy_category_id 1 electricity
291
            let timeOfUseItem = {}
292
            timeOfUseItem['id'] = 1;
293
            timeOfUseItem['name'] =  t('Top-Peak');
294
            timeOfUseItem['value'] = json['reporting_period']['toppeaks'][index];
295
            timeOfUseItem['color'] = "#"+((1<<24)*Math.random()|0).toString(16);
296
            timeOfUseArray.push(timeOfUseItem);
297
            
298
            timeOfUseItem = {}
299
            timeOfUseItem['id'] = 2;
300
            timeOfUseItem['name'] =  t('On-Peak');
301
            timeOfUseItem['value'] = json['reporting_period']['onpeaks'][index];
302
            timeOfUseItem['color'] = "#"+((1<<24)*Math.random()|0).toString(16);
303
            timeOfUseArray.push(timeOfUseItem);
304
305
            timeOfUseItem = {}
306
            timeOfUseItem['id'] = 3;
307
            timeOfUseItem['name'] =  t('Mid-Peak');
308
            timeOfUseItem['value'] = json['reporting_period']['midpeaks'][index];
309
            timeOfUseItem['color'] = "#"+((1<<24)*Math.random()|0).toString(16);
310
            timeOfUseArray.push(timeOfUseItem);
311
312
            timeOfUseItem = {}
313
            timeOfUseItem['id'] = 4;
314
            timeOfUseItem['name'] =  t('Off-Peak');
315
            timeOfUseItem['value'] = json['reporting_period']['offpeaks'][index];
316
            timeOfUseItem['color'] = "#"+((1<<24)*Math.random()|0).toString(16);
317
            timeOfUseArray.push(timeOfUseItem);
318
          }
319
        });
320
        setTimeOfUseShareData(timeOfUseArray);
321
322
        let carbonDataArray = [];
323
        json['reporting_period']['names'].forEach((currentValue, index) => {
324
          let carbonDataItem = {}
325
          carbonDataItem['id'] = index;
326
          carbonDataItem['name'] = currentValue;
327
          carbonDataItem['value'] = json['reporting_period']['subtotals'][index];
328
          carbonDataItem['color'] = "#"+((1<<24)*Math.random()|0).toString(16);
329
          carbonDataArray.push(carbonDataItem);
330
        });
331
        setCarbonShareData(carbonDataArray);
332
333
        let childSpaceProportionArray = [];
334
        json['child_space']['energy_category_names'].forEach((currentValue, energyCategoryIndex) => {
335
          if (json['child_space']['child_space_names_array'][energyCategoryIndex].length > 0) {
336
            let childSpaceProportionItem = {}
337
            childSpaceProportionItem['data'] = []
338
            json['child_space']['child_space_names_array'][energyCategoryIndex].forEach((currentSpaceName, spaceIndex) => {
339
              let childSpaceProportionItemDataItem = {}
340
              childSpaceProportionItemDataItem['id'] = spaceIndex;
341
              childSpaceProportionItemDataItem['name'] = currentSpaceName;
342
              childSpaceProportionItemDataItem['value'] = json['child_space']['subtotals_array'][energyCategoryIndex][spaceIndex];
343
              childSpaceProportionItemDataItem['color'] = "#"+((1<<24)*Math.random()|0).toString(16);
344
              childSpaceProportionItem['data'].push(childSpaceProportionItemDataItem);
345
            });
346
347
            childSpaceProportionItem['name'] = json['child_space']['energy_category_names'][energyCategoryIndex];
348
            childSpaceProportionItem['unit'] = json['child_space']['units'][energyCategoryIndex];
349
            childSpaceProportionArray.push(childSpaceProportionItem);
350
          };
351
        });
352
        setChildSpaceProportionList(childSpaceProportionArray);
353
354
        let childSpaceSubtotalShareDataArray = [];
355
        if (json['child_space']['child_space_names_array'].length > 0) {
356
          json['child_space']['child_space_names_array'][0].forEach((currentSpaceName, spaceIndex) => {
357
            let subtotal = 0.0;
358
            json['child_space']['energy_category_names'].forEach((currentValue, energyCategoryIndex) => {
359
              subtotal += json['child_space']['subtotals_array'][energyCategoryIndex][spaceIndex];
360
            });
361
            let childSpaceSubtotalDataItem = {};
362
            childSpaceSubtotalDataItem['id'] = spaceIndex;
363
            childSpaceSubtotalDataItem['name'] = currentSpaceName;
364
            childSpaceSubtotalDataItem['value'] = subtotal;
365
            childSpaceSubtotalDataItem['color'] = "#"+((1<<24)*Math.random()|0).toString(16);
366
           childSpaceSubtotalShareDataArray.push(childSpaceSubtotalDataItem);
367
          });
368
        };
369
        setChildSpaceSubtotalShareData(childSpaceSubtotalShareDataArray);
370
371
        let timestamps = {}
372
        json['reporting_period']['timestamps'].forEach((currentValue, index) => {
373
          timestamps['a' + index] = currentValue;
374
        });
375
        setSpaceLineChartLabels(timestamps);
376
377
        let values = {}
378
        json['reporting_period']['values'].forEach((currentValue, index) => {
379
          values['a' + index] = currentValue;
380
        });
381
        setSpaceLineChartData(values);
382
        
383
        let names = Array();
384
        json['reporting_period']['names'].forEach((currentValue, index) => {
385
          let unit = json['reporting_period']['units'][index];
386
          names.push({ 'value': 'a' + index, 'label': currentValue + ' (' + unit + ')'});
387
        });
388
        setSpaceLineChartOptions(names);
389
390
        timestamps = {}
391
        json['parameters']['timestamps'].forEach((currentValue, index) => {
392
          timestamps['a' + index] = currentValue;
393
        });
394
        setParameterLineChartLabels(timestamps);
395
396
        values = {}
397
        json['parameters']['values'].forEach((currentValue, index) => {
398
          values['a' + index] = currentValue;
399
        });
400
        setParameterLineChartData(values);
401
      
402
        names = Array();
403
        json['parameters']['names'].forEach((currentValue, index) => {
404
          if (currentValue.startsWith('TARIFF-')) {
405
            currentValue = t('Tariff') + currentValue.replace('TARIFF-', '-');
406
          }
407
          
408
          names.push({ 'value': 'a' + index, 'label': currentValue });
409
        });
410
        setParameterLineChartOptions(names);
411
412
        let detailed_value_list = [];
413
        if (json['reporting_period']['timestamps'].length > 0) {
414
          json['reporting_period']['timestamps'][0].forEach((currentTimestamp, timestampIndex) => {
415
            let detailed_value = {};
416
            detailed_value['id'] = timestampIndex;
417
            detailed_value['startdatetime'] = currentTimestamp;
418
            let total_current_timstamp = 0.0;
419
            json['reporting_period']['values'].forEach((currentValue, energyCategoryIndex) => {
420
              detailed_value['a' + energyCategoryIndex] = json['reporting_period']['values'][energyCategoryIndex][timestampIndex];
421
              total_current_timstamp += json['reporting_period']['values'][energyCategoryIndex][timestampIndex];
422
            });
423
            detailed_value['total'] = total_current_timstamp;
424
            detailed_value_list.push(detailed_value);
425
          });
426
        };
427
428
        let detailed_value = {};
429
        detailed_value['id'] = detailed_value_list.length;
430
        detailed_value['startdatetime'] = t('Subtotal');
431
        let total_of_subtotals = 0.0;
432
        json['reporting_period']['subtotals'].forEach((currentValue, index) => {
433
            detailed_value['a' + index] = currentValue;
434
            total_of_subtotals += currentValue
435
          });
436
        detailed_value['total'] = total_of_subtotals;
437
        detailed_value_list.push(detailed_value);
438
        setDetailedDataTableData(detailed_value_list);
439
        
440
        let detailed_column_list = [];
441
        detailed_column_list.push({
442
          dataField: 'startdatetime',
443
          text: t('Datetime'),
444
          sort: true
445
        });
446
        json['reporting_period']['names'].forEach((currentValue, index) => {
447
          let unit = json['reporting_period']['units'][index];
448
          detailed_column_list.push({
449
            dataField: 'a' + index,
450
            text: currentValue + ' (' + unit + ')',
451
            sort: true,
452
            formatter: function (decimalValue) {
453
              if (typeof decimalValue === 'number') {
454
                return decimalValue.toFixed(2);
455
              } else {
456
                return null;
457
              }
458
            }
459
          });
460
        });
461
        detailed_column_list.push({
462
          dataField: 'total',
463
          text: t('Total') + ' (' + json['reporting_period']['total_unit'] + ')',
464
          sort: true,
465
          formatter: function (decimalValue) {
466
            if (typeof decimalValue === 'number') {
467
              return decimalValue.toFixed(2);
468
            } else {
469
              return null;
470
            }
471
          }
472
        });
473
        setDetailedDataTableColumns(detailed_column_list);
474
475
        let child_space_value_list = [];
476
        if (json['child_space']['child_space_names_array'].length > 0) {
477
          json['child_space']['child_space_names_array'][0].forEach((currentSpaceName, spaceIndex) => {
478
            let child_space_value = {};
479
            child_space_value['id'] = spaceIndex;
480
            child_space_value['name'] = currentSpaceName;
481
            let total = 0.0;
482
            json['child_space']['energy_category_names'].forEach((currentValue, energyCategoryIndex) => {
483
              child_space_value['a' + energyCategoryIndex] = json['child_space']['subtotals_array'][energyCategoryIndex][spaceIndex];
484
              total += json['child_space']['subtotals_array'][energyCategoryIndex][spaceIndex]
485
            });
486
            child_space_value['total'] = total;
487
            child_space_value_list.push(child_space_value);
488
          });
489
        };
490
491
        setChildSpacesTableData(child_space_value_list);
492
493
        let child_space_column_list = [];
494
        child_space_column_list.push({
495
          dataField: 'name',
496
          text: t('Child Spaces'),
497
          sort: true
498
        });
499
        json['child_space']['energy_category_names'].forEach((currentValue, index) => {
500
          let unit = json['child_space']['units'][index];
501
          child_space_column_list.push({
502
            dataField: 'a' + index,
503
            text: currentValue + ' (' + unit + ')',
504
            sort: true,
505
            formatter: function (decimalValue) {
506
              if (typeof decimalValue === 'number') {
507
                return decimalValue.toFixed(2);
508
              } else {
509
                return null;
510
              }
511
            }
512
          });
513
        });
514
        child_space_column_list.push({
515
          dataField: 'total',
516
          text: t('Total') + ' (' + json['child_space']['total_unit'] + ')',
517
          sort: true,
518
          formatter: function (decimalValue) {
519
            if (typeof decimalValue === 'number') {
520
              return decimalValue.toFixed(2);
521
            } else {
522
              return null;
523
            }
524
          }
525
        });
526
527
        setChildSpacesTableColumns(child_space_column_list);
528
        
529
        setExcelBytesBase64(json['excel_bytes_base64']);
530
531
        // enable submit button
532
        setSubmitButtonDisabled(false);
533
        // hide spinner
534
        setSpinnerHidden(true);
535
        // show export button
536
        setExportButtonHidden(false) 
537
538
      } else {
539
        toast.error(json.description)
540
      }
541
    }).catch(err => {
542
      console.log(err);
543
    });
544
  };
545
546
  const handleExport = e => {
547
    e.preventDefault();
548
    const mimeType='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
549
    const fileName = 'spacecarbon.xlsx'
550
    var fileUrl = "data:" + mimeType + ";base64," + excelBytesBase64;
551
    fetch(fileUrl)
552
        .then(response => response.blob())
553
        .then(blob => {
554
            var link = window.document.createElement("a");
555
            link.href = window.URL.createObjectURL(blob, { type: mimeType });
556
            link.download = fileName;
557
            document.body.appendChild(link);
558
            link.click();
559
            document.body.removeChild(link);
560
        });
561
  };
562
  
563
564
  return (
565
    <Fragment>
566
      <div>
567
        <Breadcrumb>
568
          <BreadcrumbItem>{t('Space Data')}</BreadcrumbItem><BreadcrumbItem active>{t('Carbon')}</BreadcrumbItem>
569
        </Breadcrumb>
570
      </div>
571
      <Card className="bg-light mb-3">
572
        <CardBody className="p-3">
573
          <Form onSubmit={handleSubmit}>
574
            <Row form>
575
              <Col xs={6} sm={3}>
576
                <FormGroup className="form-group">
577
                  <Label className={labelClasses} for="space">
578
                    {t('Space')}
579
                  </Label>
580
                  <br />
581
                  <Cascader options={cascaderOptions}
582
                    onChange={onSpaceCascaderChange}
583
                    changeOnSelect
584
                    expandTrigger="hover">
585
                    <Input value={selectedSpaceName || ''} readOnly />
586
                  </Cascader>
587
                </FormGroup>
588
              </Col>
589
              <Col xs="auto">
590
                <FormGroup>
591
                  <Label className={labelClasses} for="comparisonType">
592
                    {t('Comparison Types')}
593
                  </Label>
594
                  <CustomInput type="select" id="comparisonType" name="comparisonType"
595
                    defaultValue="month-on-month"
596
                    onChange={onComparisonTypeChange}
597
                  >
598
                    {comparisonTypeOptions.map((comparisonType, index) => (
599
                      <option value={comparisonType.value} key={comparisonType.value} >
600
                        {t(comparisonType.label)}
601
                      </option>
602
                    ))}
603
                  </CustomInput>
604
                </FormGroup>
605
              </Col>
606
              <Col xs="auto">
607
                <FormGroup>
608
                  <Label className={labelClasses} for="periodType">
609
                    {t('Period Types')}
610
                  </Label>
611
                  <CustomInput type="select" id="periodType" name="periodType" defaultValue="daily" onChange={({ target }) => setPeriodType(target.value)}
612
                  >
613
                    {periodTypeOptions.map((periodType, index) => (
614
                      <option value={periodType.value} key={periodType.value} >
615
                        {t(periodType.label)}
616
                      </option>
617
                    ))}
618
                  </CustomInput>
619
                </FormGroup>
620
              </Col>
621
              <Col xs={6} sm={3}>
622
                <FormGroup className="form-group">
623
                  <Label className={labelClasses} for="basePeriodDateRangePicker">{t('Base Period')}{t('(Optional)')}</Label>
624
                  <DateRangePicker 
625
                    id='basePeriodDateRangePicker'
626
                    readOnly={basePeriodDateRangePickerDisabled}
627
                    format="yyyy-MM-dd HH:mm:ss"
628
                    value={basePeriodDateRange}
629
                    onChange={onBasePeriodChange}
630
                    size="md"
631
                    style={dateRangePickerStyle}
632
                    onClean={onBasePeriodClean}
633
                    locale={dateRangePickerLocale}
634
                    placeholder={t("Select Date Range")}
635
                   />
636
                </FormGroup>
637
              </Col>
638
              <Col xs={6} sm={3}>
639
                <FormGroup className="form-group">
640
                  <Label className={labelClasses} for="reportingPeriodDateRangePicker">{t('Reporting Period')}</Label>
641
                  <br/>
642
                  <DateRangePicker
643
                    id='reportingPeriodDateRangePicker'
644
                    format="yyyy-MM-dd HH:mm:ss"
645
                    value={reportingPeriodDateRange}
646
                    onChange={onReportingPeriodChange}
647
                    size="md"
648
                    style={dateRangePickerStyle}
649
                    onClean={onReportingPeriodClean}
650
                    locale={dateRangePickerLocale}
651
                    placeholder={t("Select Date Range")}
652
                  />
653
                </FormGroup>
654
              </Col>
655
              <Col xs="auto">
656
                <FormGroup>
657
                  <br></br>
658
                  <ButtonGroup id="submit">
659
                    <Button color="success" disabled={submitButtonDisabled} >{t('Submit')}</Button>
660
                  </ButtonGroup>
661
                </FormGroup>
662
              </Col>
663
              <Col xs="auto">
664
                <FormGroup>
665
                  <br></br>
666
                  <Spinner color="primary" hidden={spinnerHidden}  />
667
                </FormGroup>
668
              </Col>
669
              <Col xs="auto">
670
                  <br></br>
671
                  <ButtonIcon icon="external-link-alt" transform="shrink-3 down-2" color="falcon-default" 
672
                  hidden={exportButtonHidden}
673
                  onClick={handleExport} >
674
                    {t('Export')}
675
                  </ButtonIcon>
676
              </Col>
677
            </Row>
678
          </Form>
679
        </CardBody>
680
      </Card>
681
      <div className="card-deck">
682
        {cardSummaryList.map(cardSummaryItem => (
683
          <CardSummary key={cardSummaryItem['name']}
684
            rate={cardSummaryItem['increment_rate']}
685
            title={t('Reporting Period Carbon Dioxide Emissions CATEGORY UNIT', { 'CATEGORY': cardSummaryItem['name'], 'UNIT': '(' + cardSummaryItem['unit'] + ')' })}
686
            color="success" 
687
            footnote={t('Per Unit Area')} 
688
            footvalue={cardSummaryItem['subtotal_per_unit_area']}
689
            footunit={"(" + cardSummaryItem['unit'] + "/M²)"} >
690
            {cardSummaryItem['subtotal'] && <CountUp end={cardSummaryItem['subtotal']} duration={2} prefix="" separator="," decimal="." decimals={2} />}
691
          </CardSummary>
692
        ))}
693
      </div>
694
      <Row noGutters>
695
        <Col className="mb-3 pr-lg-2 mb-3">
696
          <SharePie data={timeOfUseShareData} title={t('Electricity Carbon Dioxide Emissions by Time-Of-Use')} />
697
        </Col>
698
        <Col className="mb-3 pr-lg-2 mb-3">
699
          <SharePie data={carbonShareData} title={t('Carbon Dioxide Emissions by Energy Category')} />
700
        </Col>
701
        {childSpaceProportionList.map(childSpaceProportionItem => (
702
          <Col className="mb-3 pr-lg-2 mb-3" key={uuid()}>
703
            <SharePie
704
              data={childSpaceProportionItem['data']}
705
              title={t('Child Space Proportion CATEGORY UNIT',
706
                      {'CATEGORY': childSpaceProportionItem['name'],
707
                       'UNIT': '(' + childSpaceProportionItem['unit'] + ')'
708
                      })}
709
            />
710
          </Col>
711
        ))}
712
        <Col className="mb-3 pr-lg-2 mb-3">
713
          <SharePie
714
            data={childSpaceSubtotalShareData}
715
            title={t('Child Space Total Proportion')}
716
          />
717
        </Col>
718
719
      </Row>
720
      <LineChart reportingTitle={t('Reporting Period Carbon Dioxide Emissions CATEGORY VALUE UNIT', { 'CATEGORY': null, 'VALUE': null, 'UNIT': null })}
721
         baseTitle=''
722
        labels={spaceLineChartLabels}
723
        data={spaceLineChartData}
724
        options={spaceLineChartOptions}>
725
      </LineChart>
726
727
      <LineChart reportingTitle={t('Related Parameters')}
728
        baseTitle=''
729
        labels={parameterLineChartLabels}
730
        data={parameterLineChartData}
731
        options={parameterLineChartOptions}>
732
      </LineChart>
733
734
      <DetailedDataTable data={detailedDataTableData} title={t('Detailed Data')} columns={detailedDataTableColumns} pagesize={50} >
735
      </DetailedDataTable>
736
      <br />
737
      <ChildSpacesTable data={childSpacesTableData} title={t('Child Spaces Data')} columns={childSpacesTableColumns}>
738
      </ChildSpacesTable>
739
740
    </Fragment>
741
  );
742
};
743
744
export default withTranslation()(withRedirect(SpaceCarbon));
745