24 Commits

Author SHA1 Message Date
Mariya Varghese
cbd252b6ad Upload New File 2023-08-08 09:56:12 +00:00
Pritimay Sarkar
31a4b3f278 Merge branch 'Sruthikbs-main-patch-74927' into 'main'
Updated report format

See merge request sminnovations/hpos-web!2
2023-08-08 03:04:33 +00:00
Pritimay Sarkar
f8a8c6a789 make font italic 2023-08-07 14:24:02 +05:30
Pritimay Sarkar
0715733163 update report text 2023-08-07 14:19:50 +05:30
Pritimay Sarkar
aefcecf90f fix two page problem 2023-08-07 14:08:58 +05:30
Pritimay Sarkar
ebd9d23f12 add colors for print 2023-08-07 13:41:09 +05:30
Pritimay Sarkar
e681a4a9bf iadd logo 2023-08-07 13:33:16 +05:30
Pritimay Sarkar
f17408f5ce Merge branch 'main' of https://gitlab.com/sminnovations/hpos-web 2023-08-07 13:13:28 +05:30
Pritimay Sarkar
60a8044041 update to new format 2023-08-07 13:12:36 +05:30
Sruthi K
2d040ff1c8 Updated report format 2023-08-07 06:15:41 +00:00
Pritimay Sarkar
e9da7a7983 Merge branch 'Sruthikbs-main-patch-93603' into 'main'
Update report_template.html

See merge request sminnovations/hpos-web!1
2023-08-07 06:14:13 +00:00
Sruthi K
4579ad914d Update report_template.html 2023-08-07 06:12:08 +00:00
Pritimay Sarkar
b4ab8cbff0 fix css for bar graph and main screen 2023-08-07 09:56:23 +05:30
Pritimay Sarkar
d35510d39a change margins 2023-08-06 15:34:59 +05:30
Pritimay Sarkar
5af8197664 format the template 2023-08-06 15:25:56 +05:30
Pritimay Sarkar
29b7db446e add text content in template 2023-08-06 14:01:52 +05:30
Pritimay Sarkar
ca71641341 add report html template
- change arduino stub output to generate error
2023-08-06 13:55:17 +05:30
Pritimay Sarkar
45aecc658e adjust for ring buffer consideration 2023-08-05 10:38:52 +05:30
Pritimay Sarkar
5524f135ff rename file 2023-08-05 00:29:08 +05:30
Pritimay Sarkar
65f5fdc428 add commands 2023-08-05 00:22:39 +05:30
Pritimay Sarkar
4bf75a2473 add sample flow 2023-08-04 23:57:32 +05:30
Pritimay Sarkar
87e4ca7c9a add dev firmware for hpos app 2023-08-04 23:50:47 +05:30
Pritimay Sarkar
e34a618198 remove scroll in analytics page
- add searchable dropdown in analytics page
2023-08-03 11:51:14 +05:30
Pritimay Sarkar
f9c054c62b calibration 2023-08-03 00:27:26 +05:30
22 changed files with 563 additions and 40 deletions

View File

@@ -0,0 +1,45 @@
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println("SN:182829");
// while (Serial.available() == 0) {} //wait for data available
// String bufferCommand = Serial.readString(); //read until timeout
// bufferCommand.trim(); // remove any \r \n whitespace at the end of the String
// if (bufferCommand == "B") {
// Serial.println("#Start Buffer");
// delay(2000);
// Serial.println("#Buffer Completed");
// }
// while (Serial.available() == 0) {} //wait for data available
// String SampleCommand = Serial.readString(); //read until timeout
// SampleCommand.trim(); // remove any \r \n whitespace at the end of the String
// if (SampleCommand == "S") {
// Serial.println("#Sample Started");
// delay(2000);
// Serial.println("#Sample Completed");
// }
// while (Serial.available() == 0) {} //wait for data available
// String resultCommand = Serial.readString(); //read until timeout
// resultCommand.trim(); // remove any \r \n whitespace at the end of the String
// if (resultCommand == "R") {
// delay(3000);
// Serial.println("RESULT SN 18291 1937.23 2828.11 28211.20 121829.12 REND");
// delay(15000);
// }
while (Serial.available() == 0) {} //wait for data available
String resultCommand = Serial.readString(); //read until timeout
resultCommand.trim(); // remove any \r \n whitespace at the end of the String
if (resultCommand == "B") {
delay(3000);
Serial.println("ERROR 500 REND");
delay(15000);
}
}

Binary file not shown.

64
scripts/UserCollection.py Normal file
View File

@@ -0,0 +1,64 @@
import os
import firebase_admin
from IPython.core.display import Image
from IPython.core.display_functions import display
from firebase_admin import credentials
from firebase_admin import firestore
import pandas as pd
import datetime
print("pritimay")
# Initialize Firebase Admin SDK
cred = credentials.Certificate(r'C:\Users\smila\PycharmProjects\pythonProject\hpos-prod-firebase-adminsdk-bionp-5486f7becd.json') # Replace with your own service account key path
firebase_admin.initialize_app(cred)
# Get a reference to the Firestore database
db = firestore.client()
# Specify the collections
patient_collection = db.collection("patientData")
test_collection = db.collection("testData")
start_date = input("Please enter the start date (yyyy-mm-dd): ")
end_date = input("Please enter the end date (yyyy-mm-dd): ")
query = patient_collection.where("createdAt", ">=", start_date).where("createdAt", "<", end_date)
patient_docs = query.stream()
# Prepare data to store in CSV
data = []
for patient_doc in patient_docs:
patient_data = patient_doc.to_dict()
patient_id = patient_data["_id"]
# Query the document from testData collection based on the common _id
test_docs = test_collection.where("_id", "==", patient_id).stream()
for test_doc in test_docs:
test_data = test_doc.to_dict()
# Combine the data from both collections into a single dictionary
combined_data = {**patient_data, **test_data}
# Skip if the csvPath is not a valid URL
data.append(combined_data)
# Convert the data to a DataFrame
df = pd.DataFrame(data)
print(df.size)
# Save the DataFrame to a CSV file
output_filename = "data.csv"
df.to_csv(output_filename, index=False)
downloads_dir = os.path.join(os.path.expanduser("~"), "Downloads")
output_path = os.path.join(downloads_dir, output_filename)
df.to_csv(output_path, index=False)
print(f"Data saved to '{output_path}'")
# Close the Firebase Admin SDK
firebase_admin.delete_app(firebase_admin.get_app())

BIN
scripts/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

BIN
scripts/logo_nobg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View File

@@ -0,0 +1,235 @@
<!DOCTYPE html>
<html>
<head>
<style>
@media print {
body {
-webkit-print-color-adjust: exact;
}
}
.person-details-row {
display: flex;
flex-direction: row;
}
.person-details-col {
display: flex;
flex-direction: column;
height: 90px;
width: 50%;
margin: 1px;
border: 0;
}
.test-details-row {
border: 0;
}
.test-details-col {
height: 100px;
}
.test-cell-div {
/* border: 1px solid black; */
border-collapse: collapse;
height: 20px;
padding: 10px;
}
.table-header {
border: 1px solid black;
margin: 0 0 -10px 10px;
background-color: rgb(191, 191, 191);
text-align: center;
justify-content: center;
align-items: center;
display: flex;
font-weight: 600;
height: 50px;
width: 98%;
}
@media print {
.table-header {
background-color: rgb(191, 191, 191) !important;
print-color-adjust: exact;
}
}
@media print {
.vendorListHeading th {
color: white !important;
}
}
.test-method {
font-weight: 200 !important;
color: rgb(191, 191, 191);
}
.result-value {
justify-content: center;
align-items: center;
display: flex;
}
.end-of-report {
display: flex;
align-items: center;
justify-content: center;
}
.logo {
display: flex;
justify-content: center;
align-items: center;
}
table,
th,
td {
border: 1px solid black;
border-collapse: collapse;
}
ul {
list-style-type: none;
/* margin: 0; */
/* padding: 0; */
}
</style>
</head>
<body>
<div>
<div class="logo">
<img src="./logo_nobg.png" width="128" height="128" alt="sickle cell logo" />
</div>
<table style="border: 1px solid black; margin: 10px; width: 98%;">
<tr class="person-details-row">
<td class="person-details-col" style="border-right: 2; width: 70%;">
<div><strong>Name:</strong></div>
<div><strong>Age / Gender:</strong></div>
<div><strong>Sample type:</strong></div>
<div><strong>Family History of Sickle Cell Anemia:</strong></div>
</td>
<td class="person-details-col" style="width: 30%;">
<div><strong>Marital Status:</strong></div>
<div><strong>Test Date:</strong></div>
<div><strong>ABHA ID:</strong></div>
<div><strong>Sample ID:</strong></div>
</td>
</tr>
</table>
</div>
<div style="height: 2px;width: 98%; background-color: rgb(56, 105, 166); margin: 30px 10px 40px 10px;"></div>
<div>
<div class="table-header">POINT OF CARE SICKLE CELL ANEMIA TEST</div>
<table class="test-details-table" style="border: 1px solid black; margin: 10px; width: 98%;">
<tr style="height: 50px;">
<th>
Test Description
</th>
<th>
RESULT
</th>
<th>
REFERENCE RANGES
</th>
</tr>
<tr class="test-details-row">
<td class="test-details-col" style="width: 20%; margin: 10px;">
<div style="margin: 10px;">Sickle Cell
Anemia
<div class="test-method">(Method: HPOS)</div>
</div>
</td>
<td style="width: 30%;">
<div class="result-value">Ra = 0.16</div>
<!-- <div class="test-cell-div">Normal</div>
<div class="test-cell-div">Sickle Cell Trait</div>
<div class="test-cell-div">Sickle Cell Disease</div>
<div class="test-cell-div">Negative Borderline</div>
<div class="test-cell-div">Positive Borderline</div> -->
</td>
<td style="width: 50%;">
<div class="test-cell-div">
< 0.16: Normal (HbA)</div>
<div class="test-cell-div">0.165 0.235: Sickle-cell Trait (HbAS)</div>
<div class="test-cell-div">> 0.24: Sickle-cell Disease (HbSS)</div>
<div class="test-cell-div">0.16-0.165: Inconclusive (Negative Borderline)</div>
<div class="test-cell-div">0.235 0.24: Inconclusive (Positive Borderline)</div>
</td>
<!-- <td style="width: 25%;">
<div class="test-cell-div">Normal</div>
<div class="test-cell-div">Sickle Cell Trait</div>
<div class="test-cell-div">Sickle Cell Disease</div>
<div class="test-cell-div">Recommended for HPLC or Electrophoresis Tests</div>
<div class="test-cell-div">Recommended for HPLC or Electrophore</div>
</td> -->
</tr>
</table>
</div>
<div>
<!-- <div style="font-weight: 600; margin: 10px;">INTERPRETATION:</div> -->
<div style="margin: 10px;">
<strong>Test Principle:</strong> This point of care quantitative diagnostic test for sickle-cell anemia
works on the principle of absorption
spectroscopy. The test helps in differentiating heterozygous/homozygous hemoglobin from normal hemoglobin.
</div>
<div style="margin: 10px;">
<strong>Method:</strong> High Performance Optical Spectroscopy (HPOS) for detection of Sickle cell trait and
sickle cell disease in whole blood capillary blood samples.
</div>
<div style="margin: 10px;">
<strong> Note:</strong>
<!-- <ul>
<li>a. Blood transfusion may have an impact on the test results.</li>
<li>
b. Patients already on sickle-cell medications may impact test results.
</li>
</ul> -->
Borderline cases are reported as inconclusive. It may occur due to several factors such as medication,
transfusion, field conditions and assay process. Further clinical tests are recommended in these cases for
diagnosis.
</div>
<div
style="margin: 80px 10px 20px 50px; width: 88%; display: flex; flex-direction: row; justify-content: space-between; align-items: center;">
<div style="margin: 5px;">DATE:</div>
<div style="margin: 5px;">Hematologist</div>
</div>
<!-- <div style="margin: 30px;">
This report is for the perusal of doctor only. Not for medico legal cases. Clinical correlation is
essential.
Please contact us in case of unexpected result.
</div> -->
<div style="height: 3px;width: 98%; background-color: black;"></div>
<div class="end-of-report">
*** END OF REPORT ***</div>
<div style="display: flex; justify-content: center; align-items: center; flex-direction: column;">
<div style="font-style: italic;">
This is an electronically generated report. Generated at HH:MM hrs on DD-MMM-YYYY.
</div>
<div>
Note: Assay results should be correlated clinically with other clinical findings
</div>
</div>
</div>
</body>
</html>

View File

@@ -50,7 +50,7 @@ body {
display: inline-flex;
flex-direction: row;
font-size: xx-large;
background-color: rgb(215, 192, 252);
background-color: rgb(207, 235, 250);
}
.last-update {
@@ -146,7 +146,7 @@ body {
text-align: center;
align-self: center;
font-size: xx-large;
background-color: rgb(215, 192, 252);
background-color: rgb(207, 235, 250);
}
.nscm-logo {
@@ -206,7 +206,7 @@ body {
text-align: center;
align-self: center;
font-size: xx-large;
background-color: rgb(215, 192, 252);
background-color: rgb(207, 235, 250);
}
}
@@ -253,7 +253,7 @@ body {
text-align: center;
align-self: center;
font-size: xx-large;
background-color: rgb(215, 192, 252);
background-color: rgb(207, 235, 250);
}
.title-text {
@@ -289,7 +289,7 @@ body {
}
.cards-container {
height: 80vh;
height: 90vh;
justify-content: center;
align-items: center;
display: flex;
@@ -307,7 +307,7 @@ body {
text-align: center;
align-self: center;
font-size: xx-large;
background-color: rgb(215, 192, 252);
background-color: rgb(207, 235, 250);
}
.title-text {
@@ -356,7 +356,7 @@ body {
}
.cards-container {
height: 80vh;
height: 90vh;
justify-content: center;
align-items: center;
display: flex;
@@ -372,7 +372,7 @@ body {
.dashboard-title {
text-align: center;
align-self: center;
background-color: rgb(215, 192, 252);
background-color: rgb(207, 235, 250);
}
.title-text {

View File

@@ -0,0 +1,9 @@
.page-title {
/* width: 100vw; */
padding: 10px;
text-align: center;
background: rgb(207, 235, 250);
color: black;
font-size: 30px;
font-family: sans-serif;
}

View File

@@ -0,0 +1,78 @@
import React, { useEffect, useState } from 'react';
import { query, collection, onSnapshot } from 'firebase/firestore';
import Dropdown from 'react-dropdown';
import 'react-dropdown/style.css';
import moment from 'moment';
import db from '../firebase';
import './Calibrations.css';
const Calibrations = () => {
const [device, setDevice] = useState("Select a device");
const [devices, setDevices] = useState([]);
const [curDeviceData, setCurDeviceData] = useState(null);
const changeDevice = ({ value }) => {
setDevice(value);
}
const toggleShowDevice = () => {
console.log(devices.filter(x => x.deviceId === device))
setCurDeviceData(devices.find(x => x.deviceId === device));
// if (!device) {
// setCurDeviceData(devices.filter(x => x.deviceId === device));
// } else {
// setDevice(null);
// }
}
useEffect(() => {
if (!devices?.length) {
const q = query(collection(db, "devices"));
const unsub = onSnapshot(q, (querySnapshot) => {
const testDevices = [];
querySnapshot.forEach((document) => {
const deviceData = document.data();
testDevices.push(deviceData);
});
setDevices(testDevices);
});
return () => unsub;
}
}, [device, curDeviceData]);
return (
<div className="calibrations-page">
<div className='page-title'>Calibrations</div>
<div className='dropdown-group'>
<Dropdown className='device-dropdown' options={devices?.map(x => x.deviceId)} onChange={changeDevice} value={device} placeholder="Select an device" />
<button className='clear-button' onClick={toggleShowDevice}><img className="graph-icon" src={require('../assets/graph_icon.png')} alt='icon'></img>{device ? 'Clear' : 'Show'}</button>
</div>
<div className='graph-person-conatiner'>
{curDeviceData && <div className='test-details'>
<table>
<tr>
<th>key</th>
<th>value</th>
</tr>
<tr>
<td>device</td> <td>{curDeviceData?.deviceId} </td>
</tr>
<tr>
<td>calibratedAt</td> <td>{curDeviceData?.calibratedAt} </td>
</tr>
<tr>
<td>coefficients</td> <td>{curDeviceData?.coefficients?.toString()} </td>
</tr>
</table>
</div>}
</div>
</div>
)
}
export default Calibrations;

View File

@@ -2,12 +2,14 @@
display: none;
}
.title {
.insights-title {
/* width: 100vw; */
padding: 10px;
text-align: center;
background: rgb(215, 192, 252);
background: rgb(207, 235, 250);
color: black;
font-size: 30px;
font-family: sans-serif;
}
.device-dropdown {
@@ -79,7 +81,7 @@
background-color: rgb(207, 235, 250);
width: 10vw;
height: 5vh;
margin: 5px;
/* margin: 5px; */
border-radius: 10px;
font-size: medium;
font-weight: 600;

View File

@@ -1,8 +1,9 @@
import React, { useEffect, useState } from 'react';
import React, { useEffect, useState, useRef } from 'react';
import { query, collection, onSnapshot } from 'firebase/firestore';
import Dropdown from 'react-dropdown';
import 'react-dropdown/style.css';
import moment from 'moment';
import Select from 'react-select';
import DeviceGraph from "./DeviceGraph";
import db from '../firebase';
@@ -18,11 +19,15 @@ const Devices = () => {
const [tests, setTests] = useState([]);
const [allTests, setAllTests] = useState(null);
const [showGraph, setShowGraph] = useState(false);
const selectDateDropdownRef = useRef();
const selectTestDropdownRef = useRef();
const changeDevice = ({ value }) => {
setDevice(value);
setTestDate(null);
setCurTest(null);
selectDateDropdownRef.current?.setValue("");
selectTestDropdownRef.current?.setValue("");
setDays([...new Set(allTests
.filter((x) => x.deviceSerialNumber === value)
.map(x => moment(x.testTime).format("YYYY-MM-DD")))]
@@ -32,6 +37,7 @@ const Devices = () => {
const changeTestDate = ({ value }) => {
setTestDate(value);
selectTestDropdownRef.current?.setValue("");
setCurTest(null);
setCurTestData(null);
setShowGraph(false);
@@ -84,22 +90,45 @@ const Devices = () => {
return (
<div className="devices-page">
<div className='title'>Insights</div>
<div className='insights-title'>Insights</div>
<div className='dropdown-group'>
<Dropdown className='device-dropdown' options={devices} onChange={changeDevice} value={device} placeholder="Select an device" />
{/* <Dropdown className='device-dropdown' options={devices} onChange={changeDevice} value={device} placeholder="Select an device" />
<Dropdown className='day-dropdown' options={days} onChange={changeTestDate} value={testDate} placeholder="Select an test date" />
<Dropdown className='test-dropdown' options={tests} onChange={changeTest} value={curTest} placeholder="Select an test" />
<Dropdown className='test-dropdown' options={tests} onChange={changeTest} value={curTest} placeholder="Select an test" /> */}
{/* <Select className='device-dropdown' options={devices.map(x => { return { value: x, label: x }; })} menuPlacement='auto' maxMenuHeight={250} menuShouldScrollIntoView={true} onChange={changeDevice} />
<Select className='day-dropdown' options={days.map(x => { return { value: x, label: x }; })} menuPlacement='auto' maxMenuHeight={250} menuShouldScrollIntoView={true} onChange={changeTestDate} />
<Select className='test-dropdown' options={tests.map(x => { return { value: x, label: x }; })} menuPlacement='auto' maxMenuHeight={220} menuShouldScrollIntoView={true} onChange={changeTestDate} /> */}
<Select
className='device-dropdown'
defaultValue={{ label: "Select a device", value: "Select a device" }}
options={devices.map(x => { return { value: x, label: x }; })}
menuPlacement='auto'
maxMenuHeight={250}
menuShouldScrollIntoView={true}
onChange={changeDevice} />
<Select
ref={selectDateDropdownRef}
className='day-dropdown'
defaultValue={{ label: "Select a test date", value: "Select a test date" }}
options={days.map(x => { return { value: x, label: x }; })}
menuPlacement='auto'
maxMenuHeight={250}
menuShouldScrollIntoView={true}
onChange={changeTestDate} />
<Select
ref={selectTestDropdownRef}
className='test-dropdown'
defaultValue={{ label: "Select a test", value: "Select a test" }}
options={tests.map(x => { return { value: x, label: x }; })}
menuPlacement='auto'
maxMenuHeight={220}
menuShouldScrollIntoView={true}
onChange={changeTest} />
<button className='clear-button' onClick={toggleShowGraph}><img className="graph-icon" src={require('../assets/graph_icon.png')} alt='icon'></img>{curTestData ? 'Clear' : 'Show'}</button>
</div>
<div className='graph-person-conatiner'>
{!curTestData && <div className='refresh-graph-message'>Select test device, date and person to get the detailed graph. Then, click show button to render graph.</div>}
{curTestData?.csvPath && <DeviceGraph url={curTestData?.csvPath} show={showGraph} />}
{curTestData?.csvPath && curTestData?.testType !== 'HEMOCUBE' && <DeviceGraph url={curTestData?.csvPath} show={showGraph} />}
{curTestData && <div className='test-details'>
<table>
@@ -122,6 +151,26 @@ const Devices = () => {
<tr>
<td>result</td> <td>{curTestData?.result}</td>
</tr>
{curTestData?.testType === 'HEMOCUBE' && <tr>
<td>calculatedRatio</td>
<td>{curTestData?.calculatedRatio}</td>
</tr>}
{curTestData?.testType === 'HEMOCUBE' && <tr>
<td>deviceRatio</td>
<td>{curTestData?.deviceRatio}</td>
</tr>}
{curTestData?.testType === 'HEMOCUBE' && <tr>
<td>green led Average</td>
<td>{curTestData?.led1Average}</td>
</tr>}
{curTestData?.testType === 'HEMOCUBE' && <tr>
<td>blue led Average</td>
<td>{curTestData?.led2Average}</td>
</tr>}
{curTestData?.testType === 'HEMOCUBE' && <tr>
<td>blue led Average</td>
<td>{curTestData?.led2Average}</td>
</tr>}
</table>
{/* <img src={curTestData?.userImageURL} width={100} height={150} /> */}
</div>}

View File

@@ -1,6 +1,6 @@
.locations-card {
width: 40vw;
height: 45vh;
height: 40vh;
background-color: white;
margin: 10px;
display: flex;
@@ -15,7 +15,7 @@
.locations-graph-card {
width: 40vw;
height: 45vh;
height: 40vh;
background-color: white;
margin: 10px;
border-style: solid;
@@ -27,7 +27,7 @@
.locations-card-title {
text-align: center;
font-weight: 600;
padding-top: 10px;
/* padding-top: 10px; */
display: flex;
align-items: center;
justify-content: center;

View File

@@ -6,7 +6,7 @@
.resultratio-graph-card {
width: 40vw;
height: 45vh;
height: 40vh;
background-color: white;
margin: 10px;
border-style: solid;

View File

@@ -24,7 +24,7 @@ class ScatterPlot extends Component {
if (!data) return;
// set the dimensions and margins of the graph
var margin = { top: 10, right: 30, bottom: 30, left: 60 },
var margin = { top: 10, right: 30, bottom: 40, left: 60 },
width = 460 - margin.left - margin.right,
height = 250 - margin.top - margin.bottom;

View File

@@ -1,17 +1,38 @@
.container {
.analytics-page::-webkit-scrollbar {
display: none;
}
.analytics-title::-webkit-scrollbar {
display: none;
}
.analytics-page {
width: 100vw;
}
.analytics-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 50vh;
font-family: sans-serif;
}
.analytics-title {
padding: 10px;
text-align: center;
background: rgb(207, 235, 250);
color: black;
font-size: 30px;
font-family: sans-serif;
}
@media screen and (min-width: 900px) {
.container {
.analytics-container {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
height: 50vh;
height: 45vh;
}
}

View File

@@ -82,8 +82,8 @@ const TestAnalytics = () => {
}, [curTestData, curTest, device, testDate]);
return (
<div className="devices-page">
<div className='title'>Analytics</div>
<div className="analytics-page">
<div className='analytics-title'>Analytics</div>
{/* <div className='dropdown-group'>
<Dropdown className='device-dropdown' options={devices} onChange={changeDevice} value={device} placeholder="Select an device" />
<Dropdown className='day-dropdown' options={days} onChange={changeTestDate} value={testDate} placeholder="Select an test date" />
@@ -92,11 +92,11 @@ const TestAnalytics = () => {
<button className='clear-button' onClick={toggleShowGraph}><img className="graph-icon" src={require('./graph_icon.png')}></img>{curTestData ? 'Clear' : 'Show'}</button>
</div> */}
<div className='container'>
<div className='analytics-container'>
{dailyCategoryCounts && <TestAnalyticsPie data={dailyCategoryCounts} />}
{dailyResults && <TestAnalyticsGraph data={dailyResults} />}
</div>
<div className='container'>
<div className='analytics-container'>
{allTests && <ScatterPlot data={allTests} />}
{allTests && <Locations />}
</div>

View File

@@ -6,7 +6,7 @@
.tests-count-card {
width: 40vw;
height: 45vh;
height: 40vh;
background-color: white;
margin: 10px;
/* display: flex;
@@ -58,4 +58,18 @@
font-size: x-small;
font-weight: 400;
padding: 0.5em;
}
div#tests-count-graph {
height: 180px;
width: 430px;
/* border: 2px solid #000; */
overflow-y: auto;
}
svg#bargraph {
height: 180px; /* 500px; */
width: 700px; /* 1100px; */
/* border: 1px dotted #ccc; */
/* background-color: #ccc; */
}

View File

@@ -25,11 +25,12 @@ class TestAnalyticsGraph extends Component {
data.reverse();
var margin = { top: 60, right: 20, bottom: 30, left: 50 },
width = 520 - margin.left - margin.right,
height = 220 - margin.top - margin.bottom;
var margin = { top: 30, right: 20, bottom: 50, left: 15 },
width = 700 - margin.left - margin.right,
height = 180 - margin.top - margin.bottom;
var svg = d3.select("#tests-count-graph").append('svg')
.attr("id", "bargraph")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g").attr("transform",
@@ -40,7 +41,7 @@ class TestAnalyticsGraph extends Component {
yScale = d3.scaleLinear().range([height, 0]);
var g = svg.append("g")
.attr("transform", "translate(" + 10 + "," + 10 + ")");
.attr("transform", "translate(" + 5 + "," + 5 + ")");
xScale.domain(data.map(function (d) { return moment(d.date).format("MM-DD"); }));

View File

@@ -6,7 +6,7 @@
.category-graph-card {
width: 40vw;
height: 45vh;
height: 40vh;
background-color: white;
margin: 10px;
border-style: solid;

View File

@@ -24,7 +24,7 @@ class TestAnalyticsPie extends Component {
drawChart(data) {
if (!data) return;
var margin = { top: 30, right: 10, bottom: 15, left: 25 },
var margin = { top: 15, right: 10, bottom: 45, left: 10 },
width = 480 - margin.left - margin.right,
height = 250 - margin.top - margin.bottom,
radius = Math.min(width, height) / 2;

View File

@@ -44,7 +44,7 @@ const WorldMap = () => {
}
return (
<svg width={ '40vw' } height={ '50vh' } viewBox="0 0 800 450">
<svg width={ '40vw' } height={ '35vh' } viewBox="0 0 800 450">
<g className="countries">
{
geographies.map((d,i) => (

View File

@@ -11,6 +11,7 @@ import Devices from './components/Devices';
import TestAnalytics from './components/TestAnalytics';
import WorldMap from './components/WorldMap';
import RegistraionChart from './RegistraionChart';
import Calibrations from './components/Calibrations';
const router = createBrowserRouter([
{
@@ -32,6 +33,10 @@ const router = createBrowserRouter([
{
path: "/map",
element: <RegistraionChart />,
},
{
path: "/calibrations",
element: <Calibrations />,
}
]);