myio-js-library 0.1.541 → 0.1.544

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -620,13 +620,14 @@ formatWaterVolumeM3(null); // "-"
620
620
 
621
621
  ##### `formatTankHeadFromCm(valueCm: number, locale?: string): string`
622
622
 
623
- Formats tank head from centimeters to meters of water column (m.c.a.).
623
+ Formats tank head from centimeters to meters of water column (M.C.A).
624
624
 
625
625
  ```javascript
626
626
  import { formatTankHeadFromCm } from 'myio-js-library';
627
627
 
628
- formatTankHeadFromCm(178); // "1,78 m.c.a."
629
- formatTankHeadFromCm(250); // "2,50 m.c.a."
628
+ formatTankHeadFromCm(178); // "1,78 M.C.A"
629
+ formatTankHeadFromCm(250); // "2,50 M.C.A"
630
+ formatTankHeadFromCm(1220.7); // "12,21 M.C.A"
630
631
  formatTankHeadFromCm(null); // "-"
631
632
  ```
632
633
 
package/dist/index.cjs CHANGED
@@ -891,7 +891,7 @@ module.exports = __toCommonJS(src_exports);
891
891
  // package.json
892
892
  var package_default = {
893
893
  name: "myio-js-library",
894
- version: "0.1.541",
894
+ version: "0.1.544",
895
895
  description: "A clean, standalone JS SDK for MYIO projects",
896
896
  license: "MIT",
897
897
  repository: "github:gh-myio/myio-js-library",
@@ -1095,7 +1095,7 @@ function formatTankHeadFromCm(valueCm, locale = "pt-BR") {
1095
1095
  minimumFractionDigits: 2,
1096
1096
  maximumFractionDigits: 2
1097
1097
  });
1098
- return `${formattedValue} m.c.a.`;
1098
+ return `${formattedValue} M.C.A`;
1099
1099
  }
1100
1100
  function calcDeltaPercent(prev, current) {
1101
1101
  if (prev === null || prev === void 0 || isNaN(prev) || current === null || current === void 0 || isNaN(current)) {
@@ -18790,7 +18790,14 @@ function renderCardComponentV5({
18790
18790
  };
18791
18791
  const isEnergyDevice2 = (deviceType2) => isEnergyDeviceType(deviceType2);
18792
18792
  const isTemperatureDevice2 = (deviceType2) => isTemperatureDeviceType(deviceType2);
18793
+ const isTankDevice2 = deviceType === "TANK" || deviceType === "CAIXA_DAGUA";
18794
+ const percentageForDisplay = isTankDevice2 ? (waterPercentage || 0) * 100 : perc;
18795
+ const tankLevelCm = isTankDevice2 ? Number(waterLevel ?? val) : null;
18796
+ const _pctDecimals = resolvePercentDecimals(percentDecimals);
18793
18797
  const formatCardValue = (value, deviceType2) => {
18798
+ if (isTankDevice2) {
18799
+ return `${percentageForDisplay.toFixed(_pctDecimals).replace(".", ",")}%`;
18800
+ }
18794
18801
  const numValue = Number(value) || 0;
18795
18802
  const category = getDeviceCategory(deviceType2);
18796
18803
  if (isEnergyDevice2(deviceType2)) {
@@ -19078,11 +19085,8 @@ function renderCardComponentV5({
19078
19085
  }
19079
19086
  return getStaticDeviceImage(nameType);
19080
19087
  };
19081
- const isTankDevice2 = deviceType === "TANK" || deviceType === "CAIXA_DAGUA";
19082
19088
  const isTermostatoDevice = deviceType?.toUpperCase() === "TERMOSTATO";
19083
19089
  const isEnergyDeviceFlag = isEnergyDevice2(deviceType);
19084
- const percentageForDisplay = isTankDevice2 ? (waterPercentage || 0) * 100 : perc;
19085
- const _pctDecimals = resolvePercentDecimals(percentDecimals);
19086
19090
  const calculateTempStatus2 = () => {
19087
19091
  if (temperatureStatus) return temperatureStatus;
19088
19092
  const currentTemp = Number(val) || 0;
@@ -19161,7 +19165,7 @@ function renderCardComponentV5({
19161
19165
  <span class="consumption-value">${formatCardValue(cardEntity.lastValue, deviceType)}</span>
19162
19166
  </div>
19163
19167
  </div>
19164
- ${!isTermostatoDevice ? `<span class="device-percentage-badge percentage-tooltip-trigger" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important; cursor: help;">${percentageForDisplay.toFixed(_pctDecimals).replace(".", ",")}%</span>` : tempDeviationPercent ? `<span class="device-percentage-badge temp-deviation-badge temp-comparison-tooltip-trigger" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important; color: ${tempDeviationPercent.isAbove ? "#ef4444" : tempDeviationPercent.isBelow ? "#3b82f6" : "#6b7280"}; font-weight: 600; cursor: help;">${tempDeviationPercent.sign}${tempDeviationPercent.value.toFixed(1)}%</span>` : ""}
19168
+ ${isTankDevice2 ? `<span class="device-percentage-badge device-tank-level-badge" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important;">${formatTankHeadFromCm(tankLevelCm)}</span>` : !isTermostatoDevice ? `<span class="device-percentage-badge percentage-tooltip-trigger" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important; cursor: help;">${percentageForDisplay.toFixed(_pctDecimals).replace(".", ",")}%</span>` : tempDeviationPercent ? `<span class="device-percentage-badge temp-deviation-badge temp-comparison-tooltip-trigger" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important; color: ${tempDeviationPercent.isAbove ? "#ef4444" : tempDeviationPercent.isBelow ? "#3b82f6" : "#6b7280"}; font-weight: 600; cursor: help;">${tempDeviationPercent.sign}${tempDeviationPercent.value.toFixed(1)}%</span>` : ""}
19165
19169
  </div>
19166
19170
  </div>
19167
19171
  </div>
@@ -26607,6 +26611,9 @@ function getLocaleConfig(includeTime = false) {
26607
26611
  firstDay: 1
26608
26612
  };
26609
26613
  }
26614
+ function buildMaxSpan(maxRangeDays) {
26615
+ return { days: maxRangeDays, milliseconds: -1 };
26616
+ }
26610
26617
  var CDNLoader = class {
26611
26618
  static jQueryInstance = null;
26612
26619
  static loadingPromise = null;
@@ -26769,7 +26776,7 @@ function createDateRangePicker($2, input, opts) {
26769
26776
  autoUpdateInput: true,
26770
26777
  linkedCalendars: true,
26771
26778
  showCustomRangeLabel: true,
26772
- maxSpan: { days: maxRangeDays },
26779
+ maxSpan: buildMaxSpan(maxRangeDays),
26773
26780
  maxDate: moment().endOf("day"),
26774
26781
  startDate,
26775
26782
  endDate,
@@ -35359,7 +35366,8 @@ var DeviceReportModal = class {
35359
35366
  this.dateRangePicker = await attach(input, {
35360
35367
  presetStart,
35361
35368
  presetEnd,
35362
- maxRangeDays: 31,
35369
+ // Ciclo de rateio (dia D → dia D do mês seguinte) tem até 32 dias corridos (ex.: 15/08→15/09)
35370
+ maxRangeDays: 32,
35363
35371
  includeTime: this.granularity === "1h",
35364
35372
  timePrecision: "minute",
35365
35373
  parentEl: this.modal.element,
@@ -35369,8 +35377,23 @@ var DeviceReportModal = class {
35369
35377
  }
35370
35378
  });
35371
35379
  } catch (error) {
35372
- console.warn("DateRangePicker initialization failed, using fallback:", error);
35373
- }
35380
+ console.warn("DateRangePicker initialization failed:", error);
35381
+ }
35382
+ }
35383
+ // Janela da consulta. No 1d a API recebe dias inteiros — os MESMOS dias que viram
35384
+ // linhas no zero-fill (rangeDaysInclusive): início 00:00:00 e fim 23:59:59. Um fim à
35385
+ // meia-noite (ex.: 15/09T00:00:00, exclusivo na API) não vira mais um dia "0,00" que
35386
+ // nem foi consultado. No 1h vale a hora escolhida.
35387
+ // Contrato do getDates(): hora LOCAL + offset (YYYY-MM-DDTHH:mm:ss±HH:MM) — os 10
35388
+ // primeiros caracteres são o dia exibido e os 6 últimos, o offset.
35389
+ resolveQueryWindow(range) {
35390
+ if (this.granularity === "1h" || !range.startISO || !range.endISO) return range;
35391
+ const day = (iso) => iso.slice(0, 10);
35392
+ const offset = (iso) => iso.slice(-6);
35393
+ return {
35394
+ startISO: `${day(range.startISO)}T00:00:00${offset(range.startISO)}`,
35395
+ endISO: `${day(range.endISO)}T23:59:59${offset(range.endISO)}`
35396
+ };
35374
35397
  }
35375
35398
  async loadData() {
35376
35399
  if (this.isLoading) return;
@@ -35390,7 +35413,7 @@ var DeviceReportModal = class {
35390
35413
  if (xlsBtn) xlsBtn.disabled = true;
35391
35414
  spinner.style.display = "inline-block";
35392
35415
  try {
35393
- const { startISO, endISO } = this.dateRangePicker.getDates();
35416
+ const { startISO, endISO } = this.resolveQueryWindow(this.dateRangePicker.getDates());
35394
35417
  this.exportPeriod = { startISO, endISO };
35395
35418
  if (!startISO || !endISO) {
35396
35419
  this.showError("Selecione um per\xEDodo v\xE1lido");
@@ -37953,7 +37976,8 @@ var AllReportModal = class {
37953
37976
  this.dateRangePicker = await attach(dateRangeInput, {
37954
37977
  presetStart: this.getDefaultStartDate(),
37955
37978
  presetEnd: this.getDefaultEndDate(),
37956
- maxRangeDays: 31,
37979
+ // Ciclo de rateio (dia D → dia D do mês seguinte) tem até 32 dias corridos (ex.: 15/08→15/09)
37980
+ maxRangeDays: 32,
37957
37981
  parentEl: this.modal.element,
37958
37982
  onApply: ({ startISO, endISO }) => {
37959
37983
  this.hideError();
@@ -37961,7 +37985,7 @@ var AllReportModal = class {
37961
37985
  }
37962
37986
  });
37963
37987
  } catch (error) {
37964
- this.debugLog("DateRangePicker initialization failed, using fallback:", error);
37988
+ this.debugLog("DateRangePicker initialization failed:", error);
37965
37989
  }
37966
37990
  }
37967
37991
  async loadData() {
package/dist/index.d.cts CHANGED
@@ -59,10 +59,10 @@ declare function formatWater$1(value: number): string;
59
59
  */
60
60
  declare function formatWaterVolumeM3(value: number, locale?: string): string;
61
61
  /**
62
- * Formats tank head from centimeters to meters of water column (m.c.a.)
62
+ * Formats tank head from centimeters to meters of water column (M.C.A)
63
63
  * @param valueCm - The tank head value in centimeters
64
64
  * @param locale - The locale to use for formatting (defaults to 'pt-BR')
65
- * @returns Formatted tank head string in m.c.a. unit
65
+ * @returns Formatted tank head string in M.C.A unit (e.g. "12,21 M.C.A")
66
66
  */
67
67
  declare function formatTankHeadFromCm(valueCm: number, locale?: string): string;
68
68
  /**
package/dist/index.d.ts CHANGED
@@ -59,10 +59,10 @@ declare function formatWater$1(value: number): string;
59
59
  */
60
60
  declare function formatWaterVolumeM3(value: number, locale?: string): string;
61
61
  /**
62
- * Formats tank head from centimeters to meters of water column (m.c.a.)
62
+ * Formats tank head from centimeters to meters of water column (M.C.A)
63
63
  * @param valueCm - The tank head value in centimeters
64
64
  * @param locale - The locale to use for formatting (defaults to 'pt-BR')
65
- * @returns Formatted tank head string in m.c.a. unit
65
+ * @returns Formatted tank head string in M.C.A unit (e.g. "12,21 M.C.A")
66
66
  */
67
67
  declare function formatTankHeadFromCm(valueCm: number, locale?: string): string;
68
68
  /**
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  // package.json
11
11
  var package_default = {
12
12
  name: "myio-js-library",
13
- version: "0.1.541",
13
+ version: "0.1.544",
14
14
  description: "A clean, standalone JS SDK for MYIO projects",
15
15
  license: "MIT",
16
16
  repository: "github:gh-myio/myio-js-library",
@@ -214,7 +214,7 @@ function formatTankHeadFromCm(valueCm, locale = "pt-BR") {
214
214
  minimumFractionDigits: 2,
215
215
  maximumFractionDigits: 2
216
216
  });
217
- return `${formattedValue} m.c.a.`;
217
+ return `${formattedValue} M.C.A`;
218
218
  }
219
219
  function calcDeltaPercent(prev, current) {
220
220
  if (prev === null || prev === void 0 || isNaN(prev) || current === null || current === void 0 || isNaN(current)) {
@@ -17184,7 +17184,14 @@ function renderCardComponentV5({
17184
17184
  };
17185
17185
  const isEnergyDevice2 = (deviceType2) => isEnergyDeviceType(deviceType2);
17186
17186
  const isTemperatureDevice2 = (deviceType2) => isTemperatureDeviceType(deviceType2);
17187
+ const isTankDevice2 = deviceType === "TANK" || deviceType === "CAIXA_DAGUA";
17188
+ const percentageForDisplay = isTankDevice2 ? (waterPercentage || 0) * 100 : perc;
17189
+ const tankLevelCm = isTankDevice2 ? Number(waterLevel ?? val) : null;
17190
+ const _pctDecimals = resolvePercentDecimals(percentDecimals);
17187
17191
  const formatCardValue = (value, deviceType2) => {
17192
+ if (isTankDevice2) {
17193
+ return `${percentageForDisplay.toFixed(_pctDecimals).replace(".", ",")}%`;
17194
+ }
17188
17195
  const numValue = Number(value) || 0;
17189
17196
  const category = getDeviceCategory(deviceType2);
17190
17197
  if (isEnergyDevice2(deviceType2)) {
@@ -17472,11 +17479,8 @@ function renderCardComponentV5({
17472
17479
  }
17473
17480
  return getStaticDeviceImage(nameType);
17474
17481
  };
17475
- const isTankDevice2 = deviceType === "TANK" || deviceType === "CAIXA_DAGUA";
17476
17482
  const isTermostatoDevice = deviceType?.toUpperCase() === "TERMOSTATO";
17477
17483
  const isEnergyDeviceFlag = isEnergyDevice2(deviceType);
17478
- const percentageForDisplay = isTankDevice2 ? (waterPercentage || 0) * 100 : perc;
17479
- const _pctDecimals = resolvePercentDecimals(percentDecimals);
17480
17484
  const calculateTempStatus2 = () => {
17481
17485
  if (temperatureStatus) return temperatureStatus;
17482
17486
  const currentTemp = Number(val) || 0;
@@ -17555,7 +17559,7 @@ function renderCardComponentV5({
17555
17559
  <span class="consumption-value">${formatCardValue(cardEntity.lastValue, deviceType)}</span>
17556
17560
  </div>
17557
17561
  </div>
17558
- ${!isTermostatoDevice ? `<span class="device-percentage-badge percentage-tooltip-trigger" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important; cursor: help;">${percentageForDisplay.toFixed(_pctDecimals).replace(".", ",")}%</span>` : tempDeviationPercent ? `<span class="device-percentage-badge temp-deviation-badge temp-comparison-tooltip-trigger" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important; color: ${tempDeviationPercent.isAbove ? "#ef4444" : tempDeviationPercent.isBelow ? "#3b82f6" : "#6b7280"}; font-weight: 600; cursor: help;">${tempDeviationPercent.sign}${tempDeviationPercent.value.toFixed(1)}%</span>` : ""}
17562
+ ${isTankDevice2 ? `<span class="device-percentage-badge device-tank-level-badge" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important;">${formatTankHeadFromCm(tankLevelCm)}</span>` : !isTermostatoDevice ? `<span class="device-percentage-badge percentage-tooltip-trigger" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important; cursor: help;">${percentageForDisplay.toFixed(_pctDecimals).replace(".", ",")}%</span>` : tempDeviationPercent ? `<span class="device-percentage-badge temp-deviation-badge temp-comparison-tooltip-trigger" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important; color: ${tempDeviationPercent.isAbove ? "#ef4444" : tempDeviationPercent.isBelow ? "#3b82f6" : "#6b7280"}; font-weight: 600; cursor: help;">${tempDeviationPercent.sign}${tempDeviationPercent.value.toFixed(1)}%</span>` : ""}
17559
17563
  </div>
17560
17564
  </div>
17561
17565
  </div>
@@ -25001,6 +25005,9 @@ function getLocaleConfig(includeTime = false) {
25001
25005
  firstDay: 1
25002
25006
  };
25003
25007
  }
25008
+ function buildMaxSpan(maxRangeDays) {
25009
+ return { days: maxRangeDays, milliseconds: -1 };
25010
+ }
25004
25011
  var CDNLoader = class {
25005
25012
  static jQueryInstance = null;
25006
25013
  static loadingPromise = null;
@@ -25163,7 +25170,7 @@ function createDateRangePicker($2, input, opts) {
25163
25170
  autoUpdateInput: true,
25164
25171
  linkedCalendars: true,
25165
25172
  showCustomRangeLabel: true,
25166
- maxSpan: { days: maxRangeDays },
25173
+ maxSpan: buildMaxSpan(maxRangeDays),
25167
25174
  maxDate: moment().endOf("day"),
25168
25175
  startDate,
25169
25176
  endDate,
@@ -33753,7 +33760,8 @@ var DeviceReportModal = class {
33753
33760
  this.dateRangePicker = await attach(input, {
33754
33761
  presetStart,
33755
33762
  presetEnd,
33756
- maxRangeDays: 31,
33763
+ // Ciclo de rateio (dia D → dia D do mês seguinte) tem até 32 dias corridos (ex.: 15/08→15/09)
33764
+ maxRangeDays: 32,
33757
33765
  includeTime: this.granularity === "1h",
33758
33766
  timePrecision: "minute",
33759
33767
  parentEl: this.modal.element,
@@ -33763,8 +33771,23 @@ var DeviceReportModal = class {
33763
33771
  }
33764
33772
  });
33765
33773
  } catch (error) {
33766
- console.warn("DateRangePicker initialization failed, using fallback:", error);
33767
- }
33774
+ console.warn("DateRangePicker initialization failed:", error);
33775
+ }
33776
+ }
33777
+ // Janela da consulta. No 1d a API recebe dias inteiros — os MESMOS dias que viram
33778
+ // linhas no zero-fill (rangeDaysInclusive): início 00:00:00 e fim 23:59:59. Um fim à
33779
+ // meia-noite (ex.: 15/09T00:00:00, exclusivo na API) não vira mais um dia "0,00" que
33780
+ // nem foi consultado. No 1h vale a hora escolhida.
33781
+ // Contrato do getDates(): hora LOCAL + offset (YYYY-MM-DDTHH:mm:ss±HH:MM) — os 10
33782
+ // primeiros caracteres são o dia exibido e os 6 últimos, o offset.
33783
+ resolveQueryWindow(range) {
33784
+ if (this.granularity === "1h" || !range.startISO || !range.endISO) return range;
33785
+ const day = (iso) => iso.slice(0, 10);
33786
+ const offset = (iso) => iso.slice(-6);
33787
+ return {
33788
+ startISO: `${day(range.startISO)}T00:00:00${offset(range.startISO)}`,
33789
+ endISO: `${day(range.endISO)}T23:59:59${offset(range.endISO)}`
33790
+ };
33768
33791
  }
33769
33792
  async loadData() {
33770
33793
  if (this.isLoading) return;
@@ -33784,7 +33807,7 @@ var DeviceReportModal = class {
33784
33807
  if (xlsBtn) xlsBtn.disabled = true;
33785
33808
  spinner.style.display = "inline-block";
33786
33809
  try {
33787
- const { startISO, endISO } = this.dateRangePicker.getDates();
33810
+ const { startISO, endISO } = this.resolveQueryWindow(this.dateRangePicker.getDates());
33788
33811
  this.exportPeriod = { startISO, endISO };
33789
33812
  if (!startISO || !endISO) {
33790
33813
  this.showError("Selecione um per\xEDodo v\xE1lido");
@@ -36347,7 +36370,8 @@ var AllReportModal = class {
36347
36370
  this.dateRangePicker = await attach(dateRangeInput, {
36348
36371
  presetStart: this.getDefaultStartDate(),
36349
36372
  presetEnd: this.getDefaultEndDate(),
36350
- maxRangeDays: 31,
36373
+ // Ciclo de rateio (dia D → dia D do mês seguinte) tem até 32 dias corridos (ex.: 15/08→15/09)
36374
+ maxRangeDays: 32,
36351
36375
  parentEl: this.modal.element,
36352
36376
  onApply: ({ startISO, endISO }) => {
36353
36377
  this.hideError();
@@ -36355,7 +36379,7 @@ var AllReportModal = class {
36355
36379
  }
36356
36380
  });
36357
36381
  } catch (error) {
36358
- this.debugLog("DateRangePicker initialization failed, using fallback:", error);
36382
+ this.debugLog("DateRangePicker initialization failed:", error);
36359
36383
  }
36360
36384
  }
36361
36385
  async loadData() {
@@ -5455,7 +5455,7 @@
5455
5455
 
5456
5456
  // package.json
5457
5457
  var package_default = {
5458
- version: "0.1.541"};
5458
+ version: "0.1.544"};
5459
5459
 
5460
5460
  // src/utils/format/energy.ts
5461
5461
  function formatPower(value, decimals = 2) {
@@ -5580,7 +5580,7 @@
5580
5580
  minimumFractionDigits: 2,
5581
5581
  maximumFractionDigits: 2
5582
5582
  });
5583
- return `${formattedValue} m.c.a.`;
5583
+ return `${formattedValue} M.C.A`;
5584
5584
  }
5585
5585
  function calcDeltaPercent(prev, current) {
5586
5586
  if (prev === null || prev === void 0 || isNaN(prev) || current === null || current === void 0 || isNaN(current)) {
@@ -22521,7 +22521,14 @@
22521
22521
  };
22522
22522
  const isEnergyDevice2 = (deviceType2) => isEnergyDeviceType(deviceType2);
22523
22523
  const isTemperatureDevice2 = (deviceType2) => isTemperatureDeviceType(deviceType2);
22524
+ const isTankDevice2 = deviceType === "TANK" || deviceType === "CAIXA_DAGUA";
22525
+ const percentageForDisplay = isTankDevice2 ? (waterPercentage || 0) * 100 : perc;
22526
+ const tankLevelCm = isTankDevice2 ? Number(waterLevel ?? val) : null;
22527
+ const _pctDecimals = resolvePercentDecimals(percentDecimals);
22524
22528
  const formatCardValue = (value, deviceType2) => {
22529
+ if (isTankDevice2) {
22530
+ return `${percentageForDisplay.toFixed(_pctDecimals).replace(".", ",")}%`;
22531
+ }
22525
22532
  const numValue = Number(value) || 0;
22526
22533
  getDeviceCategory(deviceType2);
22527
22534
  if (isEnergyDevice2(deviceType2)) {
@@ -22809,11 +22816,8 @@
22809
22816
  }
22810
22817
  return getStaticDeviceImage(nameType);
22811
22818
  };
22812
- const isTankDevice2 = deviceType === "TANK" || deviceType === "CAIXA_DAGUA";
22813
22819
  const isTermostatoDevice = deviceType?.toUpperCase() === "TERMOSTATO";
22814
22820
  const isEnergyDeviceFlag = isEnergyDevice2(deviceType);
22815
- const percentageForDisplay = isTankDevice2 ? (waterPercentage || 0) * 100 : perc;
22816
- const _pctDecimals = resolvePercentDecimals(percentDecimals);
22817
22821
  const calculateTempStatus2 = () => {
22818
22822
  if (temperatureStatus) return temperatureStatus;
22819
22823
  const currentTemp = Number(val) || 0;
@@ -22892,7 +22896,7 @@
22892
22896
  <span class="consumption-value">${formatCardValue(cardEntity.lastValue, deviceType)}</span>
22893
22897
  </div>
22894
22898
  </div>
22895
- ${!isTermostatoDevice ? `<span class="device-percentage-badge percentage-tooltip-trigger" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important; cursor: help;">${percentageForDisplay.toFixed(_pctDecimals).replace(".", ",")}%</span>` : tempDeviationPercent ? `<span class="device-percentage-badge temp-deviation-badge temp-comparison-tooltip-trigger" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important; color: ${tempDeviationPercent.isAbove ? "#ef4444" : tempDeviationPercent.isBelow ? "#3b82f6" : "#6b7280"}; font-weight: 600; cursor: help;">${tempDeviationPercent.sign}${tempDeviationPercent.value.toFixed(1)}%</span>` : ""}
22899
+ ${isTankDevice2 ? `<span class="device-percentage-badge device-tank-level-badge" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important;">${formatTankHeadFromCm(tankLevelCm)}</span>` : !isTermostatoDevice ? `<span class="device-percentage-badge percentage-tooltip-trigger" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important; cursor: help;">${percentageForDisplay.toFixed(_pctDecimals).replace(".", ",")}%</span>` : tempDeviationPercent ? `<span class="device-percentage-badge temp-deviation-badge temp-comparison-tooltip-trigger" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important; color: ${tempDeviationPercent.isAbove ? "#ef4444" : tempDeviationPercent.isBelow ? "#3b82f6" : "#6b7280"}; font-weight: 600; cursor: help;">${tempDeviationPercent.sign}${tempDeviationPercent.value.toFixed(1)}%</span>` : ""}
22896
22900
  </div>
22897
22901
  </div>
22898
22902
  </div>
@@ -30330,6 +30334,9 @@
30330
30334
  firstDay: 1
30331
30335
  };
30332
30336
  }
30337
+ function buildMaxSpan(maxRangeDays) {
30338
+ return { days: maxRangeDays, milliseconds: -1 };
30339
+ }
30333
30340
  var CDNLoader = class {
30334
30341
  static jQueryInstance = null;
30335
30342
  static loadingPromise = null;
@@ -30492,7 +30499,7 @@
30492
30499
  autoUpdateInput: true,
30493
30500
  linkedCalendars: true,
30494
30501
  showCustomRangeLabel: true,
30495
- maxSpan: { days: maxRangeDays },
30502
+ maxSpan: buildMaxSpan(maxRangeDays),
30496
30503
  maxDate: moment().endOf("day"),
30497
30504
  startDate,
30498
30505
  endDate,
@@ -39076,7 +39083,8 @@
39076
39083
  this.dateRangePicker = await attach(input, {
39077
39084
  presetStart,
39078
39085
  presetEnd,
39079
- maxRangeDays: 31,
39086
+ // Ciclo de rateio (dia D → dia D do mês seguinte) tem até 32 dias corridos (ex.: 15/08→15/09)
39087
+ maxRangeDays: 32,
39080
39088
  includeTime: this.granularity === "1h",
39081
39089
  timePrecision: "minute",
39082
39090
  parentEl: this.modal.element,
@@ -39086,8 +39094,23 @@
39086
39094
  }
39087
39095
  });
39088
39096
  } catch (error) {
39089
- console.warn("DateRangePicker initialization failed, using fallback:", error);
39090
- }
39097
+ console.warn("DateRangePicker initialization failed:", error);
39098
+ }
39099
+ }
39100
+ // Janela da consulta. No 1d a API recebe dias inteiros — os MESMOS dias que viram
39101
+ // linhas no zero-fill (rangeDaysInclusive): início 00:00:00 e fim 23:59:59. Um fim à
39102
+ // meia-noite (ex.: 15/09T00:00:00, exclusivo na API) não vira mais um dia "0,00" que
39103
+ // nem foi consultado. No 1h vale a hora escolhida.
39104
+ // Contrato do getDates(): hora LOCAL + offset (YYYY-MM-DDTHH:mm:ss±HH:MM) — os 10
39105
+ // primeiros caracteres são o dia exibido e os 6 últimos, o offset.
39106
+ resolveQueryWindow(range) {
39107
+ if (this.granularity === "1h" || !range.startISO || !range.endISO) return range;
39108
+ const day = (iso) => iso.slice(0, 10);
39109
+ const offset = (iso) => iso.slice(-6);
39110
+ return {
39111
+ startISO: `${day(range.startISO)}T00:00:00${offset(range.startISO)}`,
39112
+ endISO: `${day(range.endISO)}T23:59:59${offset(range.endISO)}`
39113
+ };
39091
39114
  }
39092
39115
  async loadData() {
39093
39116
  if (this.isLoading) return;
@@ -39107,7 +39130,7 @@
39107
39130
  if (xlsBtn) xlsBtn.disabled = true;
39108
39131
  spinner.style.display = "inline-block";
39109
39132
  try {
39110
- const { startISO, endISO } = this.dateRangePicker.getDates();
39133
+ const { startISO, endISO } = this.resolveQueryWindow(this.dateRangePicker.getDates());
39111
39134
  this.exportPeriod = { startISO, endISO };
39112
39135
  if (!startISO || !endISO) {
39113
39136
  this.showError("Selecione um per\xEDodo v\xE1lido");
@@ -41670,7 +41693,8 @@
41670
41693
  this.dateRangePicker = await attach(dateRangeInput, {
41671
41694
  presetStart: this.getDefaultStartDate(),
41672
41695
  presetEnd: this.getDefaultEndDate(),
41673
- maxRangeDays: 31,
41696
+ // Ciclo de rateio (dia D → dia D do mês seguinte) tem até 32 dias corridos (ex.: 15/08→15/09)
41697
+ maxRangeDays: 32,
41674
41698
  parentEl: this.modal.element,
41675
41699
  onApply: ({ startISO, endISO }) => {
41676
41700
  this.hideError();
@@ -41678,7 +41702,7 @@
41678
41702
  }
41679
41703
  });
41680
41704
  } catch (error) {
41681
- this.debugLog("DateRangePicker initialization failed, using fallback:", error);
41705
+ this.debugLog("DateRangePicker initialization failed:", error);
41682
41706
  }
41683
41707
  }
41684
41708
  async loadData() {