diff --git a/.firebaserc b/.firebaserc index a78ff03..dc10c99 100644 --- a/.firebaserc +++ b/.firebaserc @@ -10,6 +10,9 @@ ], "qa": [ "hpos-qa" + ], + "dev": [ + "hpos-dev" ] } } diff --git a/README.md b/README.md index ced62e2..c777ea0 100644 --- a/README.md +++ b/README.md @@ -14,4 +14,22 @@ http://localhost:3000 + +### add target (multi site), if not already defined for that site + + firebase target:apply hosting dev1 hpos-dev1 + +### add or change to firebase.json + + "target": "dev1", + +### run build + + npm build + + +### deploy + + firebase deploy --only hosting:dev + pyinstaller --noconfirm --noconsole -i "smi.ico" --windowed --clean hemocube.py diff --git a/src/assets/auto_analysis_help-1.png b/src/assets/auto_analysis_help-1.png new file mode 100644 index 0000000..d016749 Binary files /dev/null and b/src/assets/auto_analysis_help-1.png differ diff --git a/src/assets/auto_analysis_help-2.png b/src/assets/auto_analysis_help-2.png new file mode 100644 index 0000000..d5c3e87 Binary files /dev/null and b/src/assets/auto_analysis_help-2.png differ diff --git a/src/assets/auto_analysis_help-3.png b/src/assets/auto_analysis_help-3.png new file mode 100644 index 0000000..8e168c0 Binary files /dev/null and b/src/assets/auto_analysis_help-3.png differ diff --git a/src/assets/raw_data_help_1.png b/src/assets/raw_data_help_1.png new file mode 100644 index 0000000..b2c4d35 Binary files /dev/null and b/src/assets/raw_data_help_1.png differ diff --git a/src/assets/raw_data_help_2.png b/src/assets/raw_data_help_2.png new file mode 100644 index 0000000..c913f41 Binary files /dev/null and b/src/assets/raw_data_help_2.png differ diff --git a/src/assets/raw_data_help_3.png b/src/assets/raw_data_help_3.png new file mode 100644 index 0000000..7548e60 Binary files /dev/null and b/src/assets/raw_data_help_3.png differ diff --git a/src/assets/registration_help_1.png b/src/assets/registration_help_1.png new file mode 100644 index 0000000..764d1f7 Binary files /dev/null and b/src/assets/registration_help_1.png differ diff --git a/src/assets/registration_help_2.png b/src/assets/registration_help_2.png new file mode 100644 index 0000000..0f4613f Binary files /dev/null and b/src/assets/registration_help_2.png differ diff --git a/src/assets/registration_help_3.png b/src/assets/registration_help_3.png new file mode 100644 index 0000000..043f5dc Binary files /dev/null and b/src/assets/registration_help_3.png differ diff --git a/src/components/Accuracy.css b/src/components/Accuracy.css new file mode 100644 index 0000000..5a71fbb --- /dev/null +++ b/src/components/Accuracy.css @@ -0,0 +1,63 @@ +.button { + background-color: #4CAF50; + /* Green */ + border: none; + color: white; + /* padding: 15px 32px; */ + padding: 5px 10px; + text-align: center; + text-decoration: none; + display: inline-block; + font-size: 16px; + margin: 15px; +} + +.file-row { + flex-direction: row; + display: flex; + justify-content: center; + align-items: center; + margin: 1.5rem; +} + +.file-label { + margin: 10px; +} + +.dates { + flex-direction: row; + display: flex; + justify-content: center; + align-items: center; + margin: 1.5rem; +} + +.start-date { + margin: 10px; +} + +.end-date { + margin: 10px; +} + +.download-row { + flex-direction: row; + display: flex; + justify-content: center; + align-items: center; + margin: 1.5rem; +} + +.loading-icon { + animation: rotate 2s linear infinite; +} + +@keyframes rotate { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +} \ No newline at end of file diff --git a/src/components/Accuracy.js b/src/components/Accuracy.js new file mode 100644 index 0000000..db5c3b9 --- /dev/null +++ b/src/components/Accuracy.js @@ -0,0 +1,107 @@ +import React, { useState } from 'react'; +import { FaInfoCircle } from "react-icons/fa"; +import { AiOutlineLoading } from "react-icons/ai"; +import DatePicker from "react-datepicker"; +import moment from 'moment'; +import axios from 'axios'; + +import "react-datepicker/dist/react-datepicker.css"; +import './Accuracy.css'; + +function Accuracy({ show }) { + const [showCardInfo, setShowCardInfo] = useState(false); + const [startDate, setStartDate] = useState(""); + const [endDate, setEndDate] = useState(""); + const [selectedFile, setSelectedFile] = useState(null); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); // New state for handling errors + + const handleFileChange = (event) => { + setSelectedFile(event.target.files[0]); + }; + + + const fetchFile = async (start_date, end_date) => { + try { + setLoading(true); + setError(null); // Reset error state before making a new request + + if (selectedFile) { + const formData = new FormData(); + formData.append('file', selectedFile); + + const queryString = `start_date=${moment(startDate).format( + 'YYYY-MM-DD' + )}&end_date=${moment(endDate).format('YYYY-MM-DD')}`; + + const url = `https://asia-south1-hpos-af3cc.cloudfunctions.net/performance?${queryString}`; + + // Make a POST request using the Fetch API + const response = await fetch(url, { + method: 'POST', + body: formData, + headers: { + // Add any necessary headers + // 'Authorization': 'Bearer YOUR_ACCESS_TOKEN', + }, + }); + + // Check if the request was successful (status code 2xx) + if (response.ok) { + // Create a blob from the response data + const blob = await response.blob(); + + // Create a download link and trigger a click to download the file + const link = document.createElement('a'); + link.href = window.URL.createObjectURL(blob); + link.download = 'autoanlysis.xlsx'; // Set the desired file name + document.body.appendChild(link); + link.click(); + + // Clean up + document.body.removeChild(link); + } else { + console.error('Error downloading file:', response.statusText); + setError('Error downloading file. Please try again.'); // Set error message + } + } else { + setError("Select file from reference device"); + } + } catch (error) { + console.error('Error downloading file:', error); + setError('Error downloading file. Please try again.'); // Set error message + } finally { + setLoading(false); // Set loading back to false when the request completes + } + }; + + + return ( +
+

Auto Analysis

+
+
Reference file
+ +
+
+
+ setStartDate(date)} placeholderText='start date' /> +
+
+ setEndDate(date)} placeholderText='end date' /> +
+
+
+
fetchFile(startDate, endDate)}> + {loading ? ( + + ) : ( + 'Download Excel' + )} +
+
+ {error &&
{error}
} {/* Display error message if there's an error */} +
+ ); +} +export default Accuracy; \ No newline at end of file diff --git a/src/components/AppInstallation.js b/src/components/AppInstallation.js index a462674..67c2877 100644 --- a/src/components/AppInstallation.js +++ b/src/components/AppInstallation.js @@ -12,10 +12,11 @@ const AppInstallation = () => { return (
-
-

App Installation

-

First try the firebase app distribution which is email linked. After adding the email from backend. Check the email to get started.

-
Alternative Method: Testing 2.1.27 (Preprod - 07-11-2023)
+

App Installation

+ +

First try the firebase app distribution which is email linked. After adding the email from backend. Check the email to get started.

+ {/*
+
Testing 2.1.27 (Preprod - 07-11-2023)
icon @@ -29,7 +30,7 @@ const AppInstallation = () => {
  • install the downloaded apk and give permissions
  • -
    +
    */}
    ) } diff --git a/src/components/CurveFit.css b/src/components/CurveFit.css new file mode 100644 index 0000000..e69de29 diff --git a/src/components/CurveFit.js b/src/components/CurveFit.js new file mode 100644 index 0000000..0395374 --- /dev/null +++ b/src/components/CurveFit.js @@ -0,0 +1,56 @@ +import React, { useEffect, useState } from 'react'; +import { FaInfoCircle } from "react-icons/fa"; +import axios from 'axios'; + +import './CurveFit.css'; +import ImageDownloader from './ImageDownloader'; + +function CurveFit({ show }) { + const [showCardInfo, setShowCardInfo] = useState(false); + const [svgData, setSvgData] = useState(null); + + const fetchSvg = () => { + axios({ + method: 'get', + url: "https://asia-south1-hpos-qa.cloudfunctions.net/curvefit", + data: { + "_id": "id", + "underMedication": false, + "underTransfusion": false, + "userImageURL": "https://hpos-prod.web.app/logo.png" + }, + withCredentials: false, + secure: false, + headers: { + "Content-Type": "application/json", + // "x-client": "e16a1bd15af2ee640f5a7a18c8d8333f5f01f7c66e003bbc21ee52870f1bce27", + }, + }) + .then(response => response.data) + .then((data) => { + // setMessage(`${id} is being created`); + // setSvgData(data?.plot?.replace('\"', '').replace('\n', '').replace('"', "'")); + }) + .catch((err) => { + console.log(err); + // setMessage(`error: ${err?.message}`); + }); + } + + useEffect(() => { + if (!svgData) { + // fetchSvg(); + } + }, []); + + return ( +
    +

    Curve Fit

    + {/* ; */} + + + {/* */} +
    + ); +} +export default CurveFit; \ No newline at end of file diff --git a/src/components/Help.css b/src/components/Help.css new file mode 100644 index 0000000..93cb4f2 --- /dev/null +++ b/src/components/Help.css @@ -0,0 +1,19 @@ +.step-title { + font-weight: 600; + margin: 10px; + margin-top: 50px; +} + +.help-image { + margin: 10px; +} + +.step-description { + margin: 10px; +} + +.help-feature { + font-weight: 900; + font-size: 1.5rem; + margin: 10px; +} \ No newline at end of file diff --git a/src/components/Help.js b/src/components/Help.js new file mode 100644 index 0000000..40da380 --- /dev/null +++ b/src/components/Help.js @@ -0,0 +1,128 @@ +import React, { useState } from 'react'; +import Accordion from '@mui/material/Accordion'; +import AccordionDetails from '@mui/material/AccordionDetails'; +import AccordionSummary from '@mui/material/AccordionSummary'; +import Typography from '@mui/material/Typography'; +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; + +import './Help.css'; + +function Help({ url, show }) { + const [startDate, setStartDate] = useState(""); + const [endDate, setEndDate] = useState(""); + + const [expanded, setExpanded] = useState(false); + + const handleChange = + (panel) => (event, isExpanded) => { + setExpanded(isExpanded ? panel : false); + }; + + return ( +
    + + } + aria-controls="panel1bh-content" + id="panel1bh-header" + > + + Auto Analysis + + Auto Analysis of device data with dye and HB + + + +
    Step 1:
    +
    Click on the start date tab and select the necessary date. Repeat the same process on the end date tab as well.
    + icon + +
    Step 2:
    +
    Select an end date, it has to be at least one date post the start date.
    + icon + +
    Step 3:
    +
    Click on the Download Excel button and wait for the document to download.
    + icon +
    +
    +
    + + + + } + aria-controls="panel2bh-content" + id="panel2bh-header" + > + Raw Data + + Download raw data + + + + +
    Step 1:
    +
    Click on the start date tab and select the necessary date. Repeat the same process on the end date tab as well.
    + icon + icon + +
    Step 2:
    +
    Click on the Download Excel button and wait for the document to download.
    + icon +
    +
    +
    + + + + } + aria-controls="panel3bh-content" + id="panel3bh-header" + > + + Registration + + + Create and clear entries for taking readings in devices + + + + + +
    Step 1:
    +
    Enter the sample or solution name in the name tab with appropriate format given below.
    + icon + + +
    Step 2:
    +
    Click on the create button to get an ID and you will receive a confirmation message. + +If you wish to clear the generated IDs click on the clear button and you will receive a confirmation message.
    + icon + icon +
    +
    +
    + + + {/* + } + aria-controls="panel4bh-content" + id="panel4bh-header" + > + Personal data + + + + Nunc vitae orci ultricies, auctor nunc in, volutpat nisl. Integer sit + amet egestas eros, vitae egestas augue. Duis vel est augue. + + + */} +
    + ); +} +export default Help; \ No newline at end of file diff --git a/src/components/ImageDownloader.js b/src/components/ImageDownloader.js new file mode 100644 index 0000000..cfbac45 --- /dev/null +++ b/src/components/ImageDownloader.js @@ -0,0 +1,47 @@ +import React, { useState } from 'react'; + +const ImageDownloader = () => { + const [imageUrl, setImageUrl] = useState(''); + const [imageData, setImageData] = useState(null); + + const handleInputChange = (e) => { + setImageUrl(e.target.value); + }; + + const handleFetchImage = async () => { + try { + const response = await fetch(imageUrl, { mode: 'no-cors'}); + const blob = await response.blob(); + console.log(blob); + setImageData(URL.createObjectURL(blob)); + } catch (error) { + console.error('Error fetching image:', error); + } + }; + + const handleDownloadImage = () => { + const link = document.createElement('a'); + link.href = imageData; + link.download = 'downloaded_image'; + link.click(); + }; + + return ( +
    + + + + {imageData && ( +
    + Downloadable + +
    + )} +
    + ); +}; + +export default ImageDownloader; diff --git a/src/components/Precision.css b/src/components/Precision.css new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Precision.js b/src/components/Precision.js new file mode 100644 index 0000000..c13bc48 --- /dev/null +++ b/src/components/Precision.js @@ -0,0 +1,15 @@ +import React, { useState } from 'react'; +import { FaInfoCircle } from "react-icons/fa"; + +import './Precision.css'; + +function Precision({ show }) { + const [showCardInfo, setShowCardInfo] = useState(false); + + return ( +
    +

    Precision

    +
    + ); +} +export default Precision; \ No newline at end of file diff --git a/src/components/Registration.css b/src/components/Registration.css index f42955c..76788ad 100644 --- a/src/components/Registration.css +++ b/src/components/Registration.css @@ -25,4 +25,8 @@ display: inline-block; font-size: 16px; margin: 5px; +} + +.format-text { + color: red; } \ No newline at end of file diff --git a/src/components/Registration.js b/src/components/Registration.js index b6f5150..111ab9b 100644 --- a/src/components/Registration.js +++ b/src/components/Registration.js @@ -91,10 +91,11 @@ function Registration() {
    +
    Correct formats for automatic analysis are: 100 UMOL KMNO4, 290uM KMnO4, KMnO4-720umol, 350 UMOL TAR, Tar-120umol, HB-13-N-4, HB-11-4
    -
    createUser()}>Create User
    +
    createUser()}>Create
    clearsUsers()}>Clear
    diff --git a/src/firebase.js b/src/firebase.js index 43e4185..06c8e73 100644 --- a/src/firebase.js +++ b/src/firebase.js @@ -28,14 +28,37 @@ import { getAnalytics } from "firebase/analytics"; /* preprod */ const firebaseConfig = { - apiKey: "AIzaSyB2-suWmKh2PgQbRmx7rzPjYhgoovQIsQ8", - authDomain: "hpos-preprod.firebaseapp.com", - projectId: "hpos-preprod", - storageBucket: "hpos-preprod.appspot.com", - messagingSenderId: "121176529204", - appId: "1:121176529204:web:6c0db8e642992192bbed61", - measurementId: "G-GYM6LRQ8KR" -}; + apiKey: "AIzaSyBFl_YkJ5PMIvMY3G70313SyrqemjFnUv8", + authDomain: "hpos-af3cc.firebaseapp.com", + projectId: "hpos-af3cc", + storageBucket: "hpos-af3cc.appspot.com", + messagingSenderId: "650071678820", + appId: "1:650071678820:web:ce50538bf46632d46c6471", + measurementId: "G-6JHQ47S9DD" + }; + +// /* qa: hpos-qa */ +// const firebaseConfig = { +// apiKey: "AIzaSyCF7BNZ5vOMQIpKRi_vxquzWP5pIjcb59I", +// authDomain: "hpos-qa.firebaseapp.com", +// projectId: "hpos-qa", +// storageBucket: "hpos-qa.appspot.com", +// messagingSenderId: "1004619739289", +// appId: "1:1004619739289:web:c3ee0c0127f0d073e5c808", +// measurementId: "G-4MSTJHE64W" +// }; + + +// /* preprod */ +// const firebaseConfig = { +// apiKey: "AIzaSyB2-suWmKh2PgQbRmx7rzPjYhgoovQIsQ8", +// authDomain: "hpos-preprod.firebaseapp.com", +// projectId: "hpos-preprod", +// storageBucket: "hpos-preprod.appspot.com", +// messagingSenderId: "121176529204", +// appId: "1:121176529204:web:6c0db8e642992192bbed61", +// measurementId: "G-GYM6LRQ8KR" +// }; // /* prod */ // const firebaseConfig = { diff --git a/src/routes/appRoutes.js b/src/routes/appRoutes.js index a174bb1..6926704 100644 --- a/src/routes/appRoutes.js +++ b/src/routes/appRoutes.js @@ -4,12 +4,16 @@ import AppsOutlinedIcon from '@mui/icons-material/AppsOutlined'; import TestAnalytics from "../components/TestAnalytics"; import HomePage from '../components/HomePage'; import Devices from '../components/Devices'; -import { Download } from '@mui/icons-material'; +import { Download, FactCheck } from '@mui/icons-material'; import ExportData from '../components/ExportData'; import Registration from '../components/Registration'; -import { FaAndroid, FaFlask, FaPhone, FaSearch, FaUser } from 'react-icons/fa'; +import { FaAndroid, FaArrowCircleLeft, FaBars, FaBezierCurve, FaChalkboardTeacher, FaChartArea, FaChartLine, FaCheck, FaExclamation, FaFlask, FaGolfBall, FaPhone, FaQuestionCircle, FaSearch, FaUser } from 'react-icons/fa'; import AppInstallation from '../components/AppInstallation'; import Samples from '../components/Samples'; +import Precision from '../components/Precision'; +import Accuracy from '../components/Accuracy'; +import CurveFit from '../components/CurveFit'; +import Help from '../components/Help'; const appRoutes = [ { @@ -40,7 +44,7 @@ const appRoutes = [ element: , state: "downloaddata", sidebarProps: { - displayText: "Data Download", + displayText: "Raw Data", icon: } }, @@ -71,6 +75,42 @@ const appRoutes = [ icon: } }, + // { + // path: "/precision", + // element: , + // state: "precision", + // sidebarProps: { + // displayText: "Precision", + // icon: + // } + // }, + { + path: "/autoanalysis", + element: , + state: "autoanalysis", + sidebarProps: { + displayText: "Auto Analysis (NEW)", + icon: + } + }, + // { + // path: "/curvefit", + // element: , + // state: "curvefit", + // sidebarProps: { + // displayText: "Linear Fit", + // icon: + // } + // }, + { + path: "/helpcenter", + element: , + state: "helpcenter", + sidebarProps: { + displayText: "Help Center", + icon: + } + }, ] export default appRoutes; \ No newline at end of file