UPRI-NOAH / noah-frontend

Repository for NOAH Frontend code
0 stars 1 forks source link

feat(studio)(qc-iot)(qc-sensor-details)[PWA]: Design mobile view for IoT popup details #398

Closed ramoncomendadorjr closed 3 months ago

ramoncomendadorjr commented 3 months ago

Description

map-playground.component.ts

getScreenSize(event?)

Description: Monitors window resize events and updates the component's screen dimensions (screenWidth and screenHeight) whenever the window size changes.

  @HostListener('window:resize', ['$event'])
  getScreenSize(event?) {
    this.screenWidth = window.innerWidth;
    this.screenHeight = window.innerHeight;
  }

Functions for IOT Sensor Details

getFormattedIoTtype(item: any): string

Description: Returns a user-friendly string representation of the IoT type ("Rain" for 'rain', "Flood" for 'flood')

  getFormattedIoTtype(item: any): string {
    switch (item.iot_type) {
      case 'rain':
        return 'Rain';
      case 'flood':
        return 'Flood';
      default:
        return 'Unknown';
    }
  }

getFormattedCategory(item: any): string

Description: Categorizes the data based on the latest_data field and IoT type. For rain sensors, it categorizes the intensity as "LIGHT," "HEAVY," "INTENSE," or "TORRENTIAL." For flood sensors, it categorizes the level as "LOW," "MEDIUM," or "HIGH."

  getFormattedCategory(item: any): string {
    switch (item.iot_type) {
      case 'rain':
        if (item.latest_data <= 7.5) {
          return 'LIGHT';
        } else if (item.latest_data > 7.5 && item.latest_data <= 15) {
          return 'HEAVY';
        } else if (item.latest_data > 15 && item.latest_data <= 30) {
          return 'INTENSE';
        } else {
          return 'TORRENTIAL';
        }
      case 'flood':
        if (item.latest_data <= 0.5) {
          return 'LOW';
        } else if (item.latest_data > 0.5 && item.latest_data <= 1.5) {
          return 'MEDIUM';
        } else {
          return 'HIGH';
        }
      default:
        return 'UNKNOWN';
    }
  }

getStatusDynamicStyle(item: any): { [key: string]: string }

Description: Returns a dynamic style object for the status text based on the sensor's status. Colors: Green for "Active," Grey for "Inactive," and Black for unknown status.

  getStatusDynamicStyle(item: any): { [key: string]: string } {
    switch (item.status) {
      case 'Active':
        return { color: 'green' };
      case 'Inactive':
        return { color: 'grey' };
      default:
        return { color: 'black' };
    }
  }

getCategoryDynamicStyle(item: any): { [key: string]: string }

Description: Returns a dynamic style object for the category text based on the sensor's latest data. Colors vary depending on the intensity or level for rain and flood sensors.

  getCategoryDynamicStyle(item: any): { [key: string]: string } {
    switch (item.iot_type) {
      case 'rain':
        if (item.latest_data <= 7.5) {
          return { color: '#d1d5d8' };
        } else if (item.latest_data > 7.5 && item.latest_data <= 15) {
          return { color: '#f2c94c' };
        } else if (item.latest_data > 15 && item.latest_data <= 30) {
          return { color: '#f2994a' };
        } else {
          return { color: '#eb5757' };
        }
      case 'flood':
        if (item.latest_data <= 0.5) {
          return { color: '#f2c94c' };
        } else if (item.latest_data > 0.5 && item.latest_data <= 1.5) {
          return { color: '#f2994a' };
        } else {
          return { color: '#eb5757' };
        }
      default:
        return { color: 'black' };
    }
  }

Sensor Details in Popup for Mobile Setup

const popUpMobileView = new mapboxgl.Popup({
      closeButton: false,
      closeOnClick: true,
      maxWidth: 'auto',
    });
const popupContent = `
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
  href="https://fonts.googleapis.com/css2?family=Inter:wght@100..900&family=Nunito:ital,wght@0,200..1000;1,200..1000&display=swap"
  rel="stylesheet">

<div style="font-family: Nunito; padding: 16px; width: 90vw;">
  <div style="display: flex; justify-content: space-between">
    <div>
      <img src="assets/icons/noah_logo.png" alt=""
        style="height: 16px; display: inline-block; margin-right: 8px; vertical-align: middle;">
      <div style="font-size: 20px; font-weight: bold; display: inline-block; vertical-align: middle;">IoT Sensor Details
      </div>
    </div>

  </div>

  <hr
    style="height: 1px; border: none; border-top: 1px solid #ededed; margin-top: 16px; margin-bottom: 16px; width: 100%; align-items: center;">

  <div
    style="background-color: white; border-width: 1px; border-style: solid; border-color: #ededed; border-radius: 8px; padding: 16px;">
    <div style="display: flex; justify-content: space-between; align-items: center;">
      <div style="font-size: 18px; font-weight: bold; display: inline-block; padding: 0px; margin-right: 50px;">${name}
      </div>
      <div style="font-size: 18px; font-weight: bold; display: inline-block; text-align: right;"><span id="category"
          ${this.getCategoryDynamicStyle( parseFloat(iotTypeLatestData), iotType )}>${this.getFormattedCategory(
          iotType,
          parseFloat(iotTypeLatestData)
          )}</span><br><span id="iotTypeLatestData">${iotTypeLatestData}</span></div>
    </div>

    <div style="display: flex; justify-content: space-between; align-items: center;">
      <div style="font-size: 14px; display: inline-block; padding: 0px; margin-right: 50px;" id="iotType">
        ${this.getFormattedIoTtype(
        iotType
        )}</div>
      <div style="font-size: 14px; font-weight: bold; display: inline-block; text-align: right;"><span id="status"
          ${this.getStatusDynamicStyle( status )}>${status}</span> &middot ${formattedBatPercent}</div>
    </div>
  </div>

  <div style="height: 16px;"></div>

  <div id="qc-chart-mobile"
    style="display: flex; justify-content: center; align-items: center; padding: 8px; width: 100%; border-style: solid; border-radius: 8px; border: 1px solid #ededed; z-index: auto;">

  </div>

</div>

`;

Sensor Graph in Popup for Mobile Setup

async showQcChartMobile(pk: number, appID: string, qcSensorType: QuezonCitySensorType)

Description: Similar function to showQcChart but targeted div is 'qc-mobile-chart' instead of 'graph-dom'.

async showQcChartMobile(
    pk: number,
    appID: string,
    qcSensorType: QuezonCitySensorType
  ) {
  ...
  const chart = Highcharts.stockChart('qc-chart-mobile', options);
  ...
}

Main function for adding popup

showQcDataPoints(qcSensorType: QuezonCitySensorType)

showQcDataPoints(qcSensorType: QuezonCitySensorType) {
  ...
  const popUpMobileView = new mapboxgl.Popup({
    closeButton: false,
    closeOnClick: true,
    maxWidth: 'auto',
  });
  ...
  if (this.screenWidth < 768) {
    this.map.on('click', qcSensorType, (e) => {
      const coordinates = (
        e.features[0].geometry as any
      ).coordinates.slice();
      _this.map.flyTo({
        center: (e.features[0].geometry as any).coordinates.slice(),
        zoom: 13,
        offset: [0, -315],
        essential: true,
      });
      const name = e.features[0].properties.name;
      const iotType = e.features[0].properties.iot_type;
      const status = e.features[0].properties.status;
      const latestData = e.features[0].properties.latest_data;
      const batPercent = e.features[0].properties.battery_percent;
      const municity = e.features[0].properties.municity;
      this.municity = municity;
      const formattedBatPercent =
        batPercent && batPercent !== 'null'
          ? `${batPercent}%`
          : 'Not Available';
      const iotTypeLatestData =
        iotType && iotType == 'flood'
          ? `${latestData}m`
          : `${latestData}mm`;

      while (Math.abs(e.lnglat - coordinates[0]) > 180) {
        coordinates[0] += e.lnglat.lng > coordinates[0] ? 360 : -360;
      }

      const popupContent = ...
      const pk = e.features[0].properties.pk;

    popUpMobileView.setLngLat(coordinates).setHTML(popupContent);
    _this.showQcChartMobile(+pk, name, qcSensorType);
    popUpMobileView.addTo(_this.map);

    ...

  }
}

Images

Current Design

BEFORE  IoT Graph

New Design

AFTER  IoT Sensor Details