diff --git a/api/templates/study-sites-template.csv b/api/templates/study-sites-template.csv
index d571a77d..ac4889bd 100644
--- a/api/templates/study-sites-template.csv
+++ b/api/templates/study-sites-template.csv
@@ -1,3 +1,3 @@
-Proposal ID,Principal Investigator,Site Number,Site ID,CTSA ID,Site Name, Date Protocol Sent (mm-dd-yyyy),Date Contract Sent (mm-dd-yyyy),Date of IRB Submission (mm-dd-yyyy),Date of IRB Approval (mm-dd-yyyy),Date of Contract Execution (mm-dd-yyyy),Last Patient First Visit (mm-dd-yyyy),Date of Site Activation (mm-dd-yyyy),First Patient First Visit (mm-dd-yyyy),Number of Patients Consented,Number of Patients Enrolled,Number of Patients Withdrawn,Number of Patients Expected,Queries per total data elements,Number of Protocol Deviations,data Element,lost To FollowUp
-ProposalID,principalInvestigator,siteNumber,siteId,ctsaId,siteName,dateRegPacketSent,dateContractSent,dateIrbSubmission,dateIrbApproval,dateContractExecution,lpfv,dateSiteActivated,fpfv,patientsConsentedCount,patientsEnrolledCount,patientsWithdrawnCount,patientsExpectedCount,queriesCount,protocolDeviationsCount,dataElement,lostToFollowUp
+Proposal ID,Principal Investigator,Site Number,Site ID,CTSA ID,Site Name, Date Protocol Sent (mm-dd-yyyy),Date Contract Sent (mm-dd-yyyy),Date of IRB Submission (mm-dd-yyyy),Date of IRB Approval (mm-dd-yyyy),Date of Contract Execution (mm-dd-yyyy),Last Patient First Visit (mm-dd-yyyy),Date of Site Activation (mm-dd-yyyy),First Patient First Visit (mm-dd-yyyy),Number of Patients Consented,Number of Patients Enrolled,Number of Patients Withdrawn,Number of Patients Expected,Number of Queries,Number of Protocol Deviations,lost To FollowUp
+ProposalID,principalInvestigator,siteNumber,siteId,ctsaId,siteName,dateRegPacketSent,dateContractSent,dateIrbSubmission,dateIrbApproval,dateContractExecution,lpfv,dateSiteActivated,fpfv,patientsConsentedCount,patientsEnrolledCount,patientsWithdrawnCount,patientsExpectedCount,queriesCount,protocolDeviationsCount,lostToFollowUp
,,,,,,,,,,,,,,,,,,,,,
\ No newline at end of file
diff --git a/frontend/src/components/Tables/DetailPanels/SiteDetailPanel.js b/frontend/src/components/Tables/DetailPanels/SiteDetailPanel.js
index 9aab1b69..0f9c1796 100644
--- a/frontend/src/components/Tables/DetailPanels/SiteDetailPanel.js
+++ b/frontend/src/components/Tables/DetailPanels/SiteDetailPanel.js
@@ -4,12 +4,14 @@ import { DetailPanel } from './DetailPanel'
import { StarBullet } from '../../Bullets'
import { formatDate } from '../../../utils/DateFormat'
+const invalidDisplay = 'N/A'
+
export const dayCount = (startDate, endDate) => {
if (startDate && endDate) {
const num = Math.round((new Date(endDate) - new Date(startDate)) / (1000 * 60 * 60 * 24))
return `${ num } day${ num === 1 ? '' : 's' }`
} else {
- return 'N/A'
+ return invalidDisplay
}
}
@@ -17,10 +19,10 @@ export const displayRatio = (a, b, precision = 2) => {
a = parseInt(a)
b = parseInt(b)
if ( !a || !b ) {
- return 'N/A'
+ return invalidDisplay
}
if (a === 0) {
- if (b === 0) return `N/A`
+ if (b === 0) return invalidDisplay
return `0% (${ a }/${ b })`
}
return b !== 0
@@ -28,9 +30,16 @@ export const displayRatio = (a, b, precision = 2) => {
: `N/A`
}
+const displayRatioAsWholeNumberString = (a, b) => {
+ return b === 0 ? invalidDisplay : `${ Math.round(a / b) } ≈ ${ a } / ${ b }`
+}
+
export const SiteDetailPanel = props => {
const {
- siteName, dateRegPacketSent, dateContractSent, dateIrbSubmission, dateIrbApproval, dateContractExecution, dateSiteActivated, lpfv, fpfv, patientsConsentedCount, patientsEnrolledCount, patientsWithdrawnCount, patientsExpectedCount, queriesCount, protocolDeviationsCount, dataElement
+ siteName, dateRegPacketSent, dateContractSent, dateIrbSubmission, dateIrbApproval,
+ dateContractExecution, dateSiteActivated, lpfv, fpfv, patientsConsentedCount, patientsEnrolledCount,
+ patientsWithdrawnCount, patientsExpectedCount, queriesCount, protocolDeviationsCount, dataElement,
+ queriesPerConsentedPatient,
} = props
return (
@@ -87,7 +96,7 @@ export const SiteDetailPanel = props => {
-
+
diff --git a/frontend/src/components/Tables/SitesTable.js b/frontend/src/components/Tables/SitesTable.js
index 6aeba484..a77ee05f 100644
--- a/frontend/src/components/Tables/SitesTable.js
+++ b/frontend/src/components/Tables/SitesTable.js
@@ -4,6 +4,12 @@ import { StoreContext } from '../../contexts/StoreContext'
import { SiteDetailPanel, dayCount, displayRatio } from './DetailPanels'
import { EnrollmentBar } from '../Widgets/EnrollmentBar'
+const invalidDisplay = 'N/A'
+
+const ratioAsWholeNumberString = (a, b) => {
+ return b === 0 ? invalidDisplay : Math.round(a / b)
+}
+
export const SitesTable = props => {
let { title, sites } = props
const [store, ] = useContext(StoreContext)
@@ -28,7 +34,7 @@ export const SitesTable = props => {
site.actualToExpectedRandomizedPtRatio = displayRatio(site.patientsEnrolledCount, site.patientsExpectedCount)
site.ratioRandomizedPtsDropout = displayRatio(site.patientsWithdrawnCount, site.patientsEnrolledCount)
site.majorProtocolDeviationsPerRandomizedPt = displayRatio( site.protocolDeviationsCount, site.patientsEnrolledCount)
- site.queriesPerDataElement = displayRatio(site.queriesCount, site.dataElement )
+ site.queriesPerConsentedPatient = ratioAsWholeNumberString(site.queriesCount, site.patientsConsentedCount )
})
}
}, [sites, store.proposals])
@@ -59,7 +65,7 @@ export const SitesTable = props => {
return (
{
{ title: 'Patients Enrolled', field: 'patientsEnrolledCount', hidden: true, },
{ title: 'Patients Withdrawn', field: 'patientsWithdrawnCount', hidden: true, },
{ title: 'Patients Expected', field: 'patientsExpectedCount', hidden: true, },
- { title: 'Queries Count', field: 'queriesCount', hidden: true, },
{ title: 'Protocol Deviations', field: 'protocolDeviationsCount', hidden: true, },
- { title: 'Data Element', field: 'dataElement', hidden: true, },
{ title: 'Lost to Follow Up', field: 'lostToFollowUp', hidden: true, },
{ title: 'Protocol to FPFV', field: 'protocolToFpfv', hidden: true, },
{ title: 'Contract Execution Time', field: 'contractExecutionTime', hidden: true, },
@@ -96,7 +100,12 @@ export const SitesTable = props => {
{ title: 'Actual to expected randomized patient ratio', field: 'actualToExpectedRandomizedPtRatio', hidden: true, },
{ title: 'Ratio of randomized patients that dropout of the study', field: 'ratioRandomizedPtsDropout', hidden: true, },
{ title: 'Major Protocol deviations per randomized patient', field: 'majorProtocolDeviationsPerRandomizedPt', hidden: true, },
- { title: 'Queries per data element', field: 'queriesPerDataElement', hidden: true, }
+ { title: 'Number of Queries', field: 'queriesCount', hidden: true, },
+ {
+ title: 'Queries per patient',
+ render: row => row.queriesPerConsentedPatient,
+ hidden: true,
+ },
]
}
data={ sites }
diff --git a/frontend/src/views/Studies/CombinedMetrics.js b/frontend/src/views/Studies/CombinedMetrics.js
index 136d361f..ddfd2f19 100644
--- a/frontend/src/views/Studies/CombinedMetrics.js
+++ b/frontend/src/views/Studies/CombinedMetrics.js
@@ -42,35 +42,69 @@ export const CombinedMetrics = ({ study, studyProfile, sites }) => {
return sites.reduce((sum, site) => sum + site[key], 0)
}
- const ratioString = (a, b, precision = 2) => {
- return b === 0 ? invalidDisplay : `${ (100 * a/b).toFixed(precision) }% (${ a }/${ b })`
+ const ratioAsPercentString = (a, b, precision = 2) => {
+ return b === 0 ? invalidDisplay : `${ (100 * a/b).toFixed(precision) }% ≈ ${ a } / ${ b }`
}
- const item = (label, value) => (
+ const ratioAsWholeNumberString = (a, b) => {
+ return b === 0 ? invalidDisplay : `${ Math.round(a / b) } ≈ ${ a } / ${ b }`
+ }
+
+ const Metric = React.useCallback(({ label, value }) => (
- )
+ ), [])
return (
- { item('Activation (protocol to FPFV)', dayString(averageDays('dateRegPacketSent', 'fpfv'))) }
- { item('Contract execution time', dayString(averageDays('dateContractSent', 'dateContractExecution'))) }
- { item('sIRB approval time', dayString(averageDays('dateIrbSubmission', 'dateIrbApproval'))) }
- { item('Site open to FPFV', dayString(averageDays('dateSiteActivated', 'fpfv'))) }
- { item('Site open to LPFV', dayString(averageDays('dateSiteActivated', 'lpfv'))) }
+
+
+
+
+
- { item('Percent of consented patients randomized', ratioString(sum('patientsEnrolledCount'), sum('patientsConsentedCount'))) }
- { item('Actual to expected randomized patient ratio', ratioString(sum('patientsEnrolledCount'), sum('patientsExpectedCount'))) }
- { item('Ratio of randomized patients that dropped out of the study', ratioString(sum('patientsWithdrawnCount'), sum('patientsEnrolledCount'))) }
- { item('Major protocol deviations per randomized patients', ratioString(sum('protocolDeviationsCount'), sum('patientsEnrolledCount'))) }
- { item('Queries per data element', ratioString(sum('queriesCount'), sum('dataElement'))) }
+
+
+
+
+