박정하 박정하 2023-11-10
231110 박정하 기기정보조회
@9d24e4a3ea42c84f82142b24461874aed15ece51
client/views/component/Calendar_admin.jsx
--- client/views/component/Calendar_admin.jsx
+++ client/views/component/Calendar_admin.jsx
@@ -15,8 +15,78 @@
 
   //전역 변수 저장 객체
   const state = useSelector((state) => { return state });
-  
+
   const [value, setValue] = useState(new Date());
+  const activeDate = moment(value).format('YYYY-MM-DD');
+
+  const monthOfActiveDate = moment(value).format('YYYY-MM');
+  const [activeMonth, setActiveMonth] = useState(monthOfActiveDate);
+
+  const getActiveMonth = (activeStartDate) => {
+    const newActiveMonth = moment(activeStartDate).format('YYYY-MM');
+    setActiveMonth(newActiveMonth);
+  };
+
+  const CalendarInner = (date) => {
+    var medicationData = '';
+    var temperatureData = '';
+    var todayTemperature = [];
+
+    data['equipmentRecordDataList'].map((item, idx) => {
+      if (item['date'] === date['date']) {
+        var medicationTotal = item['DAWN'] + item['MORNING'] + item['AFTERNOON'] + item['NIGHT'] + item['MIDNIGHT'];
+        if (typeof medicationTotal === 'string') {
+          medicationData = '-';
+        } else {
+          medicationData = medicationTotal + '/5'
+        }
+
+        if (CommonUtil.isEmpty(item['02:00']) == false) {
+          if (typeof item['02:00'] != 'string') {
+            todayTemperature.push(item['02:00']);
+          }
+        }
+        if (CommonUtil.isEmpty(item['10:00']) == false) {
+          if (typeof item['10:00'] != 'string') {
+            todayTemperature.push(item['10:00']);
+          }
+        }
+        if (CommonUtil.isEmpty(item['14:00']) == false) {
+          if (typeof item['14:00'] != 'string') {
+            todayTemperature.push(item['14:00']);
+          }
+        }
+        if (CommonUtil.isEmpty(item['23:00']) == false) {
+          if (typeof item['23:00'] != 'string') {
+            todayTemperature.push(item['23:00']);
+          }
+        }
+      }
+    })
+
+    if (todayTemperature == '-') {
+      temperatureData = '-'
+    } else {
+      if (todayTemperature.length > 0) {
+        if (moment(date['date']).format("MM") >= 11 || moment(date['date']).format("MM") <= 2) {
+          temperatureData = Math.min.apply(null, todayTemperature) + '℃'
+        } else {
+          temperatureData = Math.max.apply(null, todayTemperature) + '℃'
+        }
+      }
+    }
+
+    return (
+      <>
+        <div>{medicationData}</div>
+        <div>{temperatureData}</div>
+      </>
+    )
+  }
+
+  React.useEffect(() => {
+    data.onChangeMonth(activeMonth);
+  }, [activeMonth])
 
   return (
     <>
@@ -27,12 +97,18 @@
           return (
             <>
               <div className="calendar-data">
-                <div>3/5</div>
-                <div>30℃</div>
+                <CalendarInner date={moment(date).format("YYYY-MM-DD")} />
               </div>
             </>
           );
         }}
+        onActiveStartDateChange={({ activeStartDate }) =>
+          getActiveMonth(activeStartDate)
+        }
+        onClickDay={(date, event) => {
+          let sendData = { date: moment(date).format("YYYY-MM-DD") };
+          data.onClick(sendData);
+        }}
       />
     </>
   );
 
client/views/component/chart/Chart12.jsx (added)
+++ client/views/component/chart/Chart12.jsx
@@ -0,0 +1,105 @@
+import React, { Component } from "react";
+import * as am5 from "@amcharts/amcharts5";
+import * as am5xy from "@amcharts/amcharts5/xy";
+import am5themes_Animated from "@amcharts/amcharts5/themes/Animated";
+import CommonUtil from "../../../resources/js/CommonUtil";
+
+var globalObject = {}
+
+export default function Chart12({ data }) {
+  const createChart = (drawChart) => {
+    if (globalObject[drawChart]) {
+      globalObject[drawChart].dispose()
+    }
+
+    console.log('createChart12 data : ', data);
+
+    let root = am5.Root.new("Chart12");
+    root._logo.dispose();
+
+
+    // Set themes
+    // https://www.amcharts.com/docs/v5/concepts/themes/
+    root.setThemes([
+      am5themes_Animated.new(root)
+    ]);
+
+
+    // Create chart
+    // https://www.amcharts.com/docs/v5/charts/xy-chart/
+    let chart = root.container.children.push(am5xy.XYChart.new(root, {
+      panX: true,
+      panY: true,
+      wheelX: "panX",
+      wheelY: "zoomX",
+      pinchZoomX: true
+    }));
+
+
+    // Add cursor
+    // https://www.amcharts.com/docs/v5/charts/xy-chart/cursor/
+    let cursor = chart.set("cursor", am5xy.XYCursor.new(root, {
+      behavior: "none"
+    }));
+    cursor.lineY.set("visible", false);
+
+
+    // Create axes
+    // https://www.amcharts.com/docs/v5/charts/xy-chart/axes/
+    let xAxis = chart.xAxes.push(am5xy.DateAxis.new(root, {
+      baseInterval: {
+        timeUnit: "day",
+        count: 1
+      },
+      renderer: am5xy.AxisRendererX.new(root, {}),
+      tooltip: am5.Tooltip.new(root, {})
+    }));
+
+    let yAxis = chart.yAxes.push(am5xy.ValueAxis.new(root, {
+      min: 0,
+      max: 100,
+      renderer: am5xy.AxisRendererY.new(root, {})
+    }));
+
+
+    // Add series
+    // https://www.amcharts.com/docs/v5/charts/xy-chart/series/
+    let series = chart.series.push(am5xy.LineSeries.new(root, {
+      name: "Series",
+      xAxis: xAxis,
+      yAxis: yAxis,
+      valueYField: "medicationAvg",
+      valueXField: "datetime",
+      tooltip: am5.Tooltip.new(root, {
+        labelText: "{valueY}"
+      })
+    }));
+    series.strokes.template.setAll({
+      strokeWidth: 2,
+      strokeDasharray: [3, 3],
+    });
+
+
+    // Set data
+    series.data.setAll(data);
+
+
+    // Make stuff animate on load
+    // https://www.amcharts.com/docs/v5/concepts/animations/
+    series.appear(1000);
+    chart.appear(1000, 100);
+
+    globalObject[drawChart] = root
+  }
+
+  React.useEffect(() => {
+    if (CommonUtil.isEmpty(data) == false) {
+      console.log('React.useEffect chart2 data : ', data);
+      createChart();
+    }
+  }, [data])
+
+  return (
+    <div id="Chart12" style={{ width: "100%", height: "100%" }}></div>
+  )
+}(No newline at end of file)
client/views/pages/equipment/EquipmentDataSelect.jsx
--- client/views/pages/equipment/EquipmentDataSelect.jsx
+++ client/views/pages/equipment/EquipmentDataSelect.jsx
@@ -1,4 +1,4 @@
-import React from "react";
+import React, { useState } from "react";
 import { useNavigate, useLocation } from "react-router";
 import { useSelector } from "react-redux";
 
@@ -8,8 +8,9 @@
 import DetailTitle from "../../component/DetailTitle.jsx";
 import Modal from "../../component/Modal.jsx";
 import CalendarAdmin from "../../component/Calendar_admin.jsx";
-import Chart9 from "../../component/chart/Chart9.jsx";
+import Chart12 from "../../component/chart/Chart12.jsx";
 import Senior from '../../../resources/files/images/senior.png';
+import CommonUtil from "../../../resources/js/CommonUtil.js";
 
 export default function EquipmentDataSelect() {
   const navigate = useNavigate();
@@ -17,25 +18,16 @@
 
   //전역 변수 저장 객체
   const state = useSelector((state) => { return state });
-  console.log("state: ", state);
 
-  //장비 초기값
-  const equipment = useLocation()['state']['equipment'];
+  const now = new Date();
+  const [equipmentSearch, setEquipmentSearch] = React.useState({
+    'equipment_serial_number': location.state['equipment_serial_number'],
+    'search_date': now.getFullYear() + "-" + (now.getMonth() + 1)
+  })
 
-  //장비 데이터 조회
-  const equipmentDataSelect = () => {
-    fetch("/user/equipmentDataSelect.json", {
-      method: "POST",
-      headers: {
-        'Content-Type': 'application/json; charset=UTF-8'
-      },
-      body: JSON.stringify(equipment),
-    }).then((response) => response.json()).then((data) => {
-      console.log("equipmentDataSelect data : ", data);
-    }).catch((error) => {
-      console.log('equipmentDataSelect() /user/equipmentDataSelect.json error : ', error);
-    });
-  };
+  const [equipmentRecordDataList, setEquipmentRecordDataList] = useState([]);
+
+  const [modalDate, setModalDate] = React.useState(null);
 
   const [modalOpen, setModalOpen] = React.useState(false);
   const openModal = () => {
@@ -47,10 +39,130 @@
 
   const calerndarClick = (data) => {
     console.log("calerndarClick - date, visitRecord", data);
+    setModalDate(data.date);
     openModal();
   }
 
-  const DateMedication = () => {
+  const calerndarChangeMonth = (data) => {
+    equipmentRecordDataSearchList(data);
+  }
+
+  //장비 데이터 조회
+  const equipmentRecordDataSearchList = (search_date) => {
+    equipmentSearch['search_date'] = CommonUtil.isEmpty(search_date) ? now.getFullYear() + "-" + (now.getMonth() + 1) : search_date;
+    setEquipmentSearch({ ...equipmentSearch });
+
+    console.log("search_date : ", equipmentSearch)
+
+    fetch("/equipment/equipmentRecordDataList.json", {
+      method: "POST",
+      headers: {
+        'Content-Type': 'application/json; charset=UTF-8'
+      },
+      body: JSON.stringify(equipmentSearch),
+    }).then((response) => response.json()).then((data) => {
+      var codeList = [];
+      data.map((item, idx) => {
+        var code = {
+          date: item['date'],
+          datetime: new Date(item['date']).getTime(),
+          DAWN: "-",
+          MORNING: "-",
+          AFTERNOON: "-",
+          NIGHT: "-",
+          MIDNIGHT: "-",
+          "02:00": "-",
+          "10:00": "-",
+          "14:00": "-",
+          "23:00": "-",
+          battery: "-",
+        }
+
+        if (CommonUtil.isEmpty(item['medication_time_code_list']) == false) {
+          code['DAWN'] = 0;
+          code['MORNING'] = 0;
+          code['AFTERNOON'] = 0;
+          code['NIGHT'] = 0;
+          code['MIDNIGHT'] = 0;
+
+          item['medication_time_code_list'].map((item1, idx1) => {
+            if (item1 == "DAWN") {
+              code['DAWN'] = 1
+            }
+            if (item1 == "MORNING") {
+              code['MORNING'] = 1
+            }
+            if (item1 == "AFTERNOON") {
+              code['AFTERNOON'] = 1
+            }
+            if (item1 == "NIGHT") {
+              code['NIGHT'] = 1
+            }
+            if (item1 == "MIDNIGHT") {
+              code['MIDNIGHT'] = 1
+            }
+          })
+
+          code['medicationAvg'] = ((code['DAWN'] + code['MORNING'] + code['AFTERNOON'] + code['NIGHT'] + code['MIDNIGHT']) / 5) * 100;
+        }
+
+        if (CommonUtil.isEmpty(item['temperature_datetime']) == false) {
+          for (let i = 0; i < item['temperature_datetime'].length; i++) {
+            code[item['temperature_datetime'][i].substr(11, 5)] = item['temperature_data'][i]
+          }
+        }
+        if (CommonUtil.isEmpty(item['battery_power_data']) == false) {
+          code['battery'] = item['battery_power_data']
+        };
+        codeList.push(code);
+      })
+      setEquipmentRecordDataList(codeList);
+    }).catch((error) => {
+      console.log('equipmentRecordDataList() /equipment/equipmentRecordDataList.json error : ', error);
+    });
+  };
+
+  const ModalInner = () => {
+    var clickDayData = {};
+    equipmentRecordDataList.map((item, idx) => {
+      if (item['date'] == modalDate) {
+        if (CommonUtil.isEmpty(item['DAWN']) == false && CommonUtil.isEmpty(item['MORNING']) == false && CommonUtil.isEmpty(item['AFTERNOON']) == false && CommonUtil.isEmpty(item['NIGHT']) == false && CommonUtil.isEmpty(item['MIDNIGHT']) == false) {
+          item['medication'] = true;
+        }
+        if (CommonUtil.isEmpty(item['02:00']) == false && CommonUtil.isEmpty(item['10:00']) == false && CommonUtil.isEmpty(item['14:00']) == false && CommonUtil.isEmpty(item['23:00']) == false) {
+          item['temperature'] = true;
+          if (item['02:00'] == '-') {
+            item['02:00'] = item['02:00'];
+          } else {
+            item['02:00'] = item['02:00'] + '℃';
+          }
+          if (item['10:00'] == '-') {
+            item['10:00'] = item['10:00'];
+          } else {
+            item['10:00'] = item['10:00'] + '℃';
+          }
+          if (item['14:00'] == '-') {
+            item['14:00'] = item['14:00'];
+          } else {
+            item['14:00'] = item['14:00'] + '℃';
+          }
+          if (item['23:00'] == '-') {
+            item['23:00'] = item['23:00'];
+          } else {
+            item['23:00'] = item['23:00'] + '℃';
+          }
+        }
+        if (CommonUtil.isEmpty(item['battery']) == false) {
+          item['battery_check'] = true;
+          if (item['battery'] == '-') {
+            item['battery'] = item['battery'];
+          } else {
+            item['battery'] = item['battery'] + '%';
+          }
+        }
+        clickDayData = item;
+      }
+    })
     return (
       <>
         <tr>
@@ -62,15 +174,16 @@
           <th>취침</th>
         </tr>
         <tr>
-          <td colSpan={5}>정보가 없습니다.</td>
+          {clickDayData['medication'] == true ? (
+            <>
+              <td>{clickDayData['DAWN']}</td>
+              <td>{clickDayData['MORNING']}</td>
+              <td>{clickDayData['AFTERNOON']}</td>
+              <td>{clickDayData['NIGHT']}</td>
+              <td>{clickDayData['MIDNIGHT']}</td>
+            </>
+          ) : <td colSpan={5}>데이터가 없습니다.</td>}
         </tr>
-      </>
-    )
-  }
-
-  const DateTemperature = () => {
-    return (
-      <>
         <tr>
           <th rowSpan={2}>온도</th>
           <th>02:00</th>
@@ -79,30 +192,40 @@
           <th>23:00</th>
         </tr>
         <tr>
-          <td colSpan={4}>정보가 없습니다.</td>
+          {clickDayData['temperature'] == true ? (
+            <>
+              <td>{clickDayData['02:00']}</td>
+              <td>{clickDayData['10:00']}</td>
+              <td>{clickDayData['14:00']}</td>
+              <td>{clickDayData['23:00']}</td>
+            </>
+          ) : <td colSpan={4}>데이터가 없습니다.</td>}
+        </tr>
+        <tr>
+          <th>배터리</th>
+          <td colSpan={5}>
+            {clickDayData['battery_check'] == true ? (
+              clickDayData['battery']
+            ) : '데이터가 없습니다.'}
+          </td>
         </tr>
       </>
     )
   }
 
-  const DateBattery = () => {
-    return (
-      <tr>
-        <th>배터리</th>
-        <td colSpan={5}>정보가 없습니다.</td>
-      </tr>
-    )
-  }
+  React.useEffect(() => {
+    equipmentRecordDataSearchList();
+  }, [])
 
 
   return (
     <>
       <main className="pink">
         <div className="flex-start main-guardian"><img src={Senior} alt="" />
-          <Title title={equipment['equipment_serial_number']} explanation={"복약, 온도, 배터리 현황을 확인하세요."} />
+          <Title title={equipmentSearch['equipment_serial_number']} explanation={"복약, 온도, 배터리 현황을 확인하세요."} />
         </div>
 
-        <CalendarAdmin data={{ onClick: calerndarClick }} />
+        <CalendarAdmin data={{ equipmentRecordDataList: equipmentRecordDataList, onClick: calerndarClick, onChangeMonth: calerndarChangeMonth }} />
 
         <div className="content-wrap margin-top">
           <div className="margin-top">
@@ -128,28 +251,34 @@
               </thead>
 
               <tbody>
-                <tr>
-                  <td>2023-11-07</td>
-                  <td>0</td>
-                  <td>1</td>
-                  <td>1</td>
-                  <td>1</td>
-                  <td>0</td>
-                  <td>20℃</td>
-                  <td>25℃</td>
-                  <td>30℃</td>
-                  <td>20℃</td>
-                  <td>99%</td>
-                </tr>
+                {CommonUtil.isEmpty(equipmentRecordDataList) == false ?
+                  equipmentRecordDataList.map((item, idx) => {
+                    return (
+                      <tr>
+                        <td>{item['date']}</td>
+                        <td>{item['DAWN']}</td>
+                        <td>{item['MORNING']}</td>
+                        <td>{item['AFTERNOON']}</td>
+                        <td>{item['NIGHT']}</td>
+                        <td>{item['MIDNIGHT']}</td>
+                        <td>{item['02:00'] != '-' ? item['02:00'] + '℃' : '-'}</td>
+                        <td>{item['10:00'] != '-' ? item['10:00'] + '℃' : '-'}</td>
+                        <td>{item['14:00'] != '-' ? item['14:00'] + '℃' : '-'}</td>
+                        <td>{item['23:00'] != '-' ? item['23:00'] + '℃' : '-'}</td>
+                        <td>{item['battery'] != '-' ? item['battery'] + '%' : '-'}</td>
+                      </tr>
+                    )
+                  })
+                  : <tr><td colSpan={11}>조회된 데이터가 없습니다.</td></tr>}
               </tbody>
             </table>
           </div>
         </div>
 
         <div className="content-wrap margin-top">
-          <DetailTitle contentTitle={"대상자의 복약률을 확인 할 수 있습니다."} />
+          <DetailTitle contentTitle={"기기의 복약률을 확인 할 수 있습니다."} />
           <div className="main-guardian-chart margin-top">
-            <Chart9 />
+            <Chart12 data={equipmentRecordDataList} />
           </div>
         </div>
 
@@ -161,9 +290,7 @@
           <div className="modal-visit board-wrap">
             <table className="margin-bottom">
               <tbody>
-                <DateMedication />
-                <DateTemperature />
-                <DateBattery />
+                <ModalInner />
               </tbody>
             </table>
           </div>
client/views/pages/equipment/EquipmentSelect.jsx
--- client/views/pages/equipment/EquipmentSelect.jsx
+++ client/views/pages/equipment/EquipmentSelect.jsx
@@ -583,7 +583,7 @@
                   <td data-label="상태">{equipmentStates[item['equipment_state']]}</td>
                   <td data-label="관리">
                     <button className={"btn-small gray-btn"} onClick={() => modalEquipmentOpen(item)}>정보 수정</button>
-                    <button className={"btn-small gray-btn"} onClick={() => { navigate("/EquipmentDataSelect", { state: { equipment: item } }) }}>기기데이터 정보 조회</button>
+                    <button className={"btn-small gray-btn"} onClick={() => { navigate("/EquipmentDataSelect", { state: { equipment_serial_number: item['equipment_serial_number'] } }) }}>정보 조회</button>
                   </td>
                 </tr>
               )
@@ -665,9 +665,9 @@
                   {isEquipmentDelivery == false ?
                     <td data-label="관리">
                       <button className={"btn-small gray-btn"} onClick={() => modalEquipmentOpen(item)}>정보 수정</button>
+                      <button className={"btn-small gray-btn"} onClick={() => { navigate("/EquipmentDataSelect", { state: { equipment_serial_number: item['equipment_serial_number'] } }) }}>정보 조회</button>
                     </td>
                     : null}
-
                 </tr>
               )
             })}
@@ -776,6 +776,7 @@
                       </td>
                       <td data-label="관리">
                         <button className={"btn-small gray-btn"} onClick={() => modalEquipmentOpen(item)}>정보 수정</button>
+                        <button className={"btn-small gray-btn"} onClick={() => { navigate("/EquipmentDataSelect", { state: { equipment_serial_number: item['equipment_serial_number'] } }) }}>정보 조회</button>
                       </td>
                     </tr>
                   )
client/views/pages/healthcare/HealthcareSelectOne.jsx
--- client/views/pages/healthcare/HealthcareSelectOne.jsx
+++ client/views/pages/healthcare/HealthcareSelectOne.jsx
@@ -510,7 +510,7 @@
         <div className="flex-start main-guardian"><img src={Senior} alt="" />
           <Title title={`${senior['user_name']} 어르신`} explanation={"방문, 복약, 온도, 배터리 현황을 확인하세요."} />
         </div>
-
+ 
         <div className="btn-wrap flex-end margin-bottom">
           <button className="btn-small gray-btn" onClick={() => { setVisitRecordInit(); openModal(); }}>방문등록</button>
         </div>
Add a comment
List