@kenyaemr/esm-facility-dashboard-app 5.4.1-pre.1966 → 5.4.1-pre.1969

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/routes.json CHANGED
@@ -1 +1 @@
1
- {"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"kenyaemrCharts":"^1.6.7"},"extensions":[{"component":"surveillanceDashboardLink","name":"surveillance-dashboard-link","slot":"facility-dashboard-left-panel-slot"},{"component":"aboveSiteDashboardLink","name":"above-site-dashboard-link","slot":"facility-dashboard-left-panel-slot"}],"workspaces":[],"modals":[],"pages":[{"component":"root","route":"facility-dashboard"}],"version":"5.4.1-pre.1966"}
1
+ {"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"kenyaemrCharts":"^1.6.7"},"extensions":[{"component":"surveillanceDashboardLink","name":"surveillance-dashboard-link","slot":"facility-dashboard-left-panel-slot"},{"component":"aboveSiteDashboardLink","name":"above-site-dashboard-link","slot":"facility-dashboard-left-panel-slot"}],"workspaces":[],"modals":[],"pages":[{"component":"root","route":"facility-dashboard"}],"version":"5.4.1-pre.1969"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kenyaemr/esm-facility-dashboard-app",
3
- "version": "5.4.1-pre.1966",
3
+ "version": "5.4.1-pre.1969",
4
4
  "description": "Facility dashboard app",
5
5
  "browser": "dist/kenyaemr-esm-facility-dashboard-app.js",
6
6
  "main": "src/index.ts",
package/src/constants.ts CHANGED
@@ -9,9 +9,7 @@ export const today = () => {
9
9
  };
10
10
 
11
11
  export const sevenDaysAgo = () => {
12
- const date = today(); // Get today's date
13
- date.setDate(date.getDate() - 7); // Subtract 7 days
14
- return date;
12
+ return dayjs().subtract(7, 'day').toDate();
15
13
  };
16
14
 
17
15
  export const DATE_PICKER_CONTROL_FORMAT = 'd/m/Y';
@@ -23,13 +21,21 @@ export const formatNewDate = (date: Date | null | undefined) => {
23
21
  };
24
22
 
25
23
  // Generate Dammy dates
26
- export const sevenDaysRunningDates = (index: number) => {
27
- const date = new Date(today());
28
- date.setDate(today().getDate() - index);
29
- const formattedDate = date.toISOString().split('T')[0];
30
- return formattedDate;
24
+ export const sevenDaysRunningDates = (index: number, endDate: Date = new Date()): string => {
25
+ const date = new Date(endDate);
26
+ date.setDate(date.getDate() - index);
27
+ return date.toISOString().split('T')[0];
31
28
  };
32
29
 
33
30
  export const formattedDate = (date: Date) => {
34
31
  return date ? dayjs(date).format(DATE_PICKER_FORMAT) : '';
35
32
  };
33
+
34
+ export const getNumberOfDays = (startDate?: Date, endDate?: Date) => {
35
+ if (!startDate || !endDate) {
36
+ return 7;
37
+ }
38
+ const start = dayjs(startDate);
39
+ const end = dayjs(endDate);
40
+ return end.diff(start, 'day');
41
+ };
@@ -33,7 +33,7 @@ const useFacilityDashboardSurveillance = (startDate?: Date, endDate?: Date) => {
33
33
  }, []);
34
34
 
35
35
  return {
36
- surveillanceSummary: error ? null : data?.data,
36
+ surveillanceSummary: data?.data ?? null,
37
37
  getIndication,
38
38
  getPercentage,
39
39
  isLoading,
@@ -0,0 +1,46 @@
1
+ import { useMemo } from 'react';
2
+ import { SurveillanceSummary } from '../types';
3
+ import dayjs from 'dayjs';
4
+
5
+ export const useChartDomain = (
6
+ data: Array<{ group?: string; day: string; value: number }>,
7
+ valueKey = 'value',
8
+ minPadding = 0,
9
+ maxPadding = 0.1,
10
+ ) => {
11
+ return useMemo(() => {
12
+ if (!data?.length) {
13
+ return [0, 10];
14
+ }
15
+
16
+ const values = data.map((item) => item[valueKey]);
17
+ const minValue = Math.min(...values);
18
+ const maxValue = Math.max(...values, 10);
19
+
20
+ const paddedMin = Math.floor(minValue * (1 - minPadding));
21
+ const paddedMax = Math.ceil(maxValue * (1 + maxPadding));
22
+
23
+ return [paddedMin, paddedMax];
24
+ }, [data, valueKey, minPadding, maxPadding]);
25
+ };
26
+
27
+ export const useSurveillanceData = <T extends keyof SurveillanceSummary>(
28
+ surveillanceSummary: SurveillanceSummary | null,
29
+ key: T,
30
+ ) => {
31
+ return useMemo(() => {
32
+ if (!surveillanceSummary || !surveillanceSummary[key]) {
33
+ return [];
34
+ }
35
+
36
+ const data = (surveillanceSummary[key] as any)?.data || [];
37
+
38
+ return Array.isArray(data)
39
+ ? data
40
+ .filter((record) => record?.day)
41
+ .sort((firstSurveillanceRecord, secondSurveillanceRecord) =>
42
+ dayjs(firstSurveillanceRecord.day).diff(dayjs(secondSurveillanceRecord.day)),
43
+ )
44
+ : data;
45
+ }, [surveillanceSummary, key]);
46
+ };
@@ -0,0 +1,56 @@
1
+ import { ScaleTypes, StackedBarChart, StackedBarChartOptions } from '@carbon/charts-react';
2
+ import { Layer } from '@carbon/react';
3
+ import React from 'react';
4
+ import { useTranslation } from 'react-i18next';
5
+ import styles from './charts.scss';
6
+ import { useChartDomain } from '../../hooks/useSurveillanceData';
7
+
8
+ type Props = {
9
+ data: Array<{ group?: string; day: string; value: number }>;
10
+ height?: string;
11
+ };
12
+
13
+ const BaseArtProgressTrackingChart: React.FC<Props> = ({ data, height = '400px' }) => {
14
+ const { t } = useTranslation();
15
+
16
+ const [minValue, maxValue] = useChartDomain(data);
17
+
18
+ const options: StackedBarChartOptions = {
19
+ title: t('progressInAddressingLinkedToArt', 'Progress in addressing Linkage to ART'),
20
+ legend: {
21
+ enabled: true,
22
+ },
23
+ axes: {
24
+ bottom: {
25
+ title: t('day', 'Day'),
26
+ mapsTo: 'day',
27
+ scaleType: ScaleTypes.LABELS,
28
+ },
29
+ left: {
30
+ title: t('numberHivPositive', 'Number HIV positive'),
31
+ mapsTo: 'value',
32
+ scaleType: ScaleTypes.LINEAR,
33
+ domain: [minValue, maxValue],
34
+ },
35
+ },
36
+ color: {
37
+ scale: {
38
+ ContactedAndLinked: '#00416a', // Dark Imperial Blue
39
+ ContactedButNotLinked: '#c46210', // Alloy Orange
40
+ NotContacted: '#195905', // Lincoln Green
41
+ },
42
+ },
43
+ height,
44
+ data: {
45
+ groupMapsTo: 'group',
46
+ },
47
+ };
48
+
49
+ return (
50
+ <Layer className={styles.chartContainer}>
51
+ <StackedBarChart options={options} data={data} />
52
+ </Layer>
53
+ );
54
+ };
55
+
56
+ export default BaseArtProgressTrackingChart;
@@ -1,20 +1,23 @@
1
1
  import { LineChart, LineChartOptions, ScaleTypes } from '@carbon/charts-react';
2
2
  import '@carbon/charts/styles.css';
3
3
  import { Layer } from '@carbon/react';
4
- import React from 'react';
4
+ import React, { useMemo } from 'react';
5
5
  import { useTranslation } from 'react-i18next';
6
6
  import styles from './charts.scss';
7
+ import { useChartDomain } from '../../hooks/useSurveillanceData';
7
8
 
8
9
  type Props = {
9
10
  data: Array<{
10
- week: string;
11
- abnomallPercentage: number;
11
+ day: string;
12
+ value: number;
12
13
  }>;
13
14
  title: string;
14
15
  yAxisTitle: string;
16
+ height?: string;
15
17
  };
16
- const BaseIndicatorTrendChart: React.FC<Props> = ({ data, title, yAxisTitle }) => {
18
+ const BaseIndicatorTrendChart: React.FC<Props> = ({ data, title, yAxisTitle, height = '400px' }) => {
17
19
  const { t } = useTranslation();
20
+ const [minValue, maxValue] = useChartDomain(data);
18
21
  const options: LineChartOptions = {
19
22
  title: title,
20
23
  legend: {
@@ -23,18 +26,18 @@ const BaseIndicatorTrendChart: React.FC<Props> = ({ data, title, yAxisTitle }) =
23
26
  axes: {
24
27
  left: {
25
28
  title: yAxisTitle,
26
- percentage: true,
27
29
  scaleType: ScaleTypes.LINEAR,
30
+ domain: [minValue, maxValue],
28
31
  includeZero: true,
29
- mapsTo: 'abnomallPercentage',
32
+ mapsTo: 'value',
30
33
  },
31
34
  bottom: {
32
- title: t('durationInDays', 'Duration in days'),
35
+ title: t('day', 'Day'),
33
36
  scaleType: ScaleTypes.LABELS,
34
- mapsTo: 'week',
37
+ mapsTo: 'day',
35
38
  },
36
39
  },
37
- height: '400px',
40
+ height,
38
41
  };
39
42
 
40
43
  return (
@@ -31,8 +31,8 @@ const BaseProgressTrackingChart: React.FC<Props> = ({ data }) => {
31
31
  },
32
32
  color: {
33
33
  scale: {
34
- Pending: '#0000ff',
35
- Completed: '#ff0000',
34
+ Declined: '#00416a', //Dark Imperial Blue
35
+ StartedPrEP: '#c46210', //Alloy Orange
36
36
  },
37
37
  },
38
38
  height: '400px',
@@ -5,21 +5,3 @@
5
5
  .chartContainer {
6
6
  padding: layout.$spacing-05;
7
7
  }
8
-
9
- .chartGroupContainer {
10
- display: flex !important;
11
- flex-flow: row wrap !important;
12
- }
13
- .tendChart {
14
- flex: 50%;
15
- }
16
-
17
- .trackingChart {
18
- flex: 50;
19
- }
20
-
21
- @media (max-width: 800px) {
22
- .chartGroupContainer {
23
- flex-direction: column;
24
- }
25
- }
@@ -3,53 +3,49 @@ import React, { useMemo } from 'react';
3
3
  import { useTranslation } from 'react-i18next';
4
4
  import BaseIndicatorTrendChart from './base-indicator-trend-chart.component';
5
5
  import BaseProgressTrackingChart from './base-progress-tracking-chart.component';
6
- import { sevenDaysRunningDates } from '../../constants';
6
+ import { getNumberOfDays, sevenDaysRunningDates } from '../../constants';
7
7
  import styles from './charts.scss';
8
+ type DelayedEACChartsProps = {
9
+ startDate?: Date;
10
+ endDate?: Date;
11
+ };
8
12
 
9
- const DelayedEACCharts = () => {
13
+ const DelayedEACCharts: React.FC<DelayedEACChartsProps> = ({ startDate, endDate }) => {
10
14
  const { t } = useTranslation();
11
15
  const generateRandomData = (numRecords: number) => {
12
16
  return Array.from({ length: numRecords }, (_, i) => ({
13
- week: sevenDaysRunningDates(i),
14
- abnomallPercentage: Math.floor(Math.random() * 50),
17
+ day: sevenDaysRunningDates(i, endDate),
18
+ value: Math.floor(Math.random() * 50),
15
19
  }));
16
20
  };
17
21
 
22
+ const numberSequence = useMemo(() => Math.max(1, getNumberOfDays(startDate, endDate)), [startDate, endDate]);
23
+
18
24
  const generateRandomDataProgress = (numRecords: number) => {
19
25
  const data = [];
20
26
  for (let i = 1; i <= numRecords; i++) {
21
27
  data.push({
22
28
  group: 'Pending',
23
- key: sevenDaysRunningDates(i),
29
+ key: sevenDaysRunningDates(i, endDate),
24
30
  value: Math.floor(Math.random() * 50),
25
31
  });
26
32
  data.push({
27
33
  group: 'Completed',
28
- key: sevenDaysRunningDates(i),
34
+ key: sevenDaysRunningDates(i, endDate),
29
35
  value: Math.floor(Math.random() * 50),
30
36
  });
31
37
  }
32
38
  return data;
33
39
  };
34
40
 
35
- const data = useMemo(() => generateRandomDataProgress(7), []);
36
-
37
- const values = useMemo(() => generateRandomData(7), []);
41
+ const data = useMemo(() => generateRandomDataProgress(numberSequence), [numberSequence, startDate, endDate]);
42
+ const values = useMemo(() => generateRandomData(numberSequence), [numberSequence, startDate, endDate]);
38
43
  return (
39
- <>
40
- <div className={styles.chartGroupContainer}>
41
- <div className={styles.tendChart}>
42
- <BaseIndicatorTrendChart
43
- data={values}
44
- title={t('delayedEAC', 'Delayed EAC')}
45
- yAxisTitle={t('percentageDelatedEAC', '% Delayed EAC')}
46
- />
47
- </div>
48
- <div className={styles.trackingChart}>
49
- <BaseProgressTrackingChart data={data} />
50
- </div>
51
- </div>
52
- </>
44
+ <BaseIndicatorTrendChart
45
+ data={values}
46
+ title={t('delayedEAC', 'Delayed enhanced adherence counselling')}
47
+ yAxisTitle={t('percentageDelatedEAC', '% Delayed EAC')}
48
+ />
53
49
  );
54
50
  };
55
51
 
@@ -3,53 +3,47 @@ import React, { useMemo } from 'react';
3
3
  import { useTranslation } from 'react-i18next';
4
4
  import BaseIndicatorTrendChart from './base-indicator-trend-chart.component';
5
5
  import BaseProgressTrackingChart from './base-progress-tracking-chart.component';
6
- import { sevenDaysRunningDates } from '../../constants';
6
+ import { getNumberOfDays, sevenDaysRunningDates } from '../../constants';
7
7
  import styles from './charts.scss';
8
-
9
- const DNAPCRPendingCharts = () => {
8
+ type DNAPCRPendingChartsProps = {
9
+ startDate?: Date;
10
+ endDate?: Date;
11
+ };
12
+ const DNAPCRPendingCharts: React.FC<DNAPCRPendingChartsProps> = ({ startDate, endDate }) => {
10
13
  const { t } = useTranslation();
11
14
  const generateRandomData = (numRecords: number) => {
12
15
  return Array.from({ length: numRecords }, (_, i) => ({
13
- week: sevenDaysRunningDates(i),
14
- abnomallPercentage: Math.floor(Math.random() * 50),
16
+ day: sevenDaysRunningDates(i, endDate),
17
+ value: Math.floor(Math.random() * 50),
15
18
  }));
16
19
  };
17
20
 
21
+ const numberSequence = useMemo(() => Math.max(1, getNumberOfDays(startDate, endDate)), [startDate, endDate]);
18
22
  const generateRandomDataProgress = (numRecords: number) => {
19
23
  const data = [];
20
24
  for (let i = 1; i <= numRecords; i++) {
21
25
  data.push({
22
26
  group: 'Pending',
23
- key: sevenDaysRunningDates(i),
27
+ key: sevenDaysRunningDates(i, endDate),
24
28
  value: Math.floor(Math.random() * 50),
25
29
  });
26
30
  data.push({
27
31
  group: 'Completed',
28
- key: sevenDaysRunningDates(i),
32
+ key: sevenDaysRunningDates(i, endDate),
29
33
  value: Math.floor(Math.random() * 50),
30
34
  });
31
35
  }
32
36
  return data;
33
37
  };
34
38
 
35
- const data = useMemo(() => generateRandomDataProgress(7), []);
36
-
37
- const values = useMemo(() => generateRandomData(7), []);
39
+ const data = useMemo(() => generateRandomDataProgress(numberSequence), [numberSequence, startDate, endDate]);
40
+ const values = useMemo(() => generateRandomData(numberSequence), [numberSequence, startDate, endDate]);
38
41
  return (
39
- <>
40
- <div className={styles.chartGroupContainer}>
41
- <div className={styles.tendChart}>
42
- <BaseIndicatorTrendChart
43
- data={values}
44
- title={t('dnapcrPending', 'Pending DNA-PCR Results')}
45
- yAxisTitle={t('percentagePendingPCRDNAResults', '% of pending PCR-DNA Results')}
46
- />
47
- </div>
48
- <div className={styles.trackingChart}>
49
- <BaseProgressTrackingChart data={data} />
50
- </div>
51
- </div>
52
- </>
42
+ <BaseIndicatorTrendChart
43
+ data={values}
44
+ title={t('dnapcrPending', 'HEI (6-8 weeks) without DNA-PCR Results')}
45
+ yAxisTitle={t('percentagePendingPCRDNAResults', '% of HEI (6-8 weeks) without DNA-PCR Results')}
46
+ />
53
47
  );
54
48
  };
55
49
 
@@ -3,53 +3,49 @@ import React, { useMemo } from 'react';
3
3
  import { useTranslation } from 'react-i18next';
4
4
  import BaseIndicatorTrendChart from './base-indicator-trend-chart.component';
5
5
  import BaseProgressTrackingChart from './base-progress-tracking-chart.component';
6
- import { sevenDaysRunningDates } from '../../constants';
6
+ import { getNumberOfDays, sevenDaysRunningDates } from '../../constants';
7
7
  import styles from './charts.scss';
8
+ type HEIFinalOutcomesChartProps = {
9
+ startDate?: Date;
10
+ endDate?: Date;
11
+ };
8
12
 
9
- const HEIFinalOutcomesChart = () => {
13
+ const HEIFinalOutcomesChart: React.FC<HEIFinalOutcomesChartProps> = ({ startDate, endDate }) => {
10
14
  const { t } = useTranslation();
11
15
  const generateRandomData = (numRecords: number) => {
12
16
  return Array.from({ length: numRecords }, (_, i) => ({
13
- week: sevenDaysRunningDates(i),
14
- abnomallPercentage: Math.floor(Math.random() * 50),
17
+ day: sevenDaysRunningDates(i),
18
+ value: Math.floor(Math.random() * 50),
15
19
  }));
16
20
  };
17
21
 
22
+ const numberSequence = useMemo(() => Math.max(0, getNumberOfDays(startDate, endDate)), [startDate, endDate]);
23
+
18
24
  const generateRandomDataProgress = (numRecords: number) => {
19
25
  const data = [];
20
26
  for (let i = 1; i <= numRecords; i++) {
21
27
  data.push({
22
28
  group: 'Pending',
23
- key: sevenDaysRunningDates(i),
29
+ key: sevenDaysRunningDates(i, endDate),
24
30
  value: Math.floor(Math.random() * 50),
25
31
  });
26
32
  data.push({
27
33
  group: 'Completed',
28
- key: sevenDaysRunningDates(i),
34
+ key: sevenDaysRunningDates(i, endDate),
29
35
  value: Math.floor(Math.random() * 50),
30
36
  });
31
37
  }
32
38
  return data;
33
39
  };
34
40
 
35
- const data = useMemo(() => generateRandomDataProgress(7), []);
36
-
37
- const values = useMemo(() => generateRandomData(7), []);
41
+ const data = useMemo(() => generateRandomDataProgress(numberSequence), [numberSequence, startDate, endDate]);
42
+ const values = useMemo(() => generateRandomData(numberSequence), [numberSequence, startDate, endDate]);
38
43
  return (
39
- <>
40
- <div className={styles.chartGroupContainer}>
41
- <div className={styles.tendChart}>
42
- <BaseIndicatorTrendChart
43
- data={values}
44
- title={t('heiFinalOutcomes', 'HEI Final Outcomes')}
45
- yAxisTitle={t('percentageHEIOutcome', '% 24 month old HEI without documented outcomes')}
46
- />
47
- </div>
48
- <div className={styles.trackingChart}>
49
- <BaseProgressTrackingChart data={data} />
50
- </div>
51
- </div>
52
- </>
44
+ <BaseIndicatorTrendChart
45
+ data={values}
46
+ title={t('heiFinalOutcomes', 'Undocumented final outcome')}
47
+ yAxisTitle={t('percentageHEIOutcome', '% of Undocumented final outcome')}
48
+ />
53
49
  );
54
50
  };
55
51
 
@@ -2,54 +2,33 @@ import '@carbon/charts/styles.css';
2
2
  import React, { useMemo } from 'react';
3
3
  import { useTranslation } from 'react-i18next';
4
4
  import BaseIndicatorTrendChart from './base-indicator-trend-chart.component';
5
- import BaseProgressTrackingChart from './base-progress-tracking-chart.component';
6
- import { sevenDaysRunningDates } from '../../constants';
7
- import styles from './charts.scss';
8
- const HIVPositiveNotLinkedToART = () => {
5
+ import BaseArtProgressTrackingChart from './base-art-progress-tracking-chart.component';
6
+ import useFacilityDashboardSurveillance from '../../hooks/useFacilityDashboardSurveillance';
7
+ import { useSurveillanceData } from '../../hooks/useSurveillanceData';
8
+ type HIVPositiveNotLinkedToARTProps = {
9
+ startDate?: Date;
10
+ endDate?: Date;
11
+ };
12
+ const HIVPositiveNotLinkedToART: React.FC<HIVPositiveNotLinkedToARTProps> = ({ startDate, endDate }) => {
9
13
  const { t } = useTranslation();
10
14
 
11
- const generateRandomData = (numRecords: number) => {
12
- return Array.from({ length: numRecords }, (_, i) => ({
13
- week: sevenDaysRunningDates(i),
14
- abnomallPercentage: Math.floor(Math.random() * 50),
15
- }));
16
- };
15
+ const { error, isLoading, surveillanceSummary } = useFacilityDashboardSurveillance(startDate, endDate);
17
16
 
18
- const generateRandomDataProgress = (numRecords: number) => {
19
- const data = [];
20
- for (let i = 1; i <= numRecords; i++) {
21
- const formattedDate = sevenDaysRunningDates(i);
22
- data.push({
23
- group: 'Pending',
24
- key: formattedDate,
25
- value: Math.floor(Math.random() * 50),
26
- });
27
- data.push({
28
- group: 'Completed',
29
- key: formattedDate,
30
- value: Math.floor(Math.random() * 50),
31
- });
32
- }
33
- return data;
34
- };
17
+ const hivPositivePatientValue = useSurveillanceData(surveillanceSummary, 'getMonthlyHivPositiveNotLinked');
35
18
 
36
- const data = useMemo(() => generateRandomDataProgress(7), []);
19
+ const monthlyHivPositivePatientData = useSurveillanceData(
20
+ surveillanceSummary,
21
+ 'getMonthlyHivPositiveNotLinkedPatients',
22
+ );
37
23
 
38
- const values = useMemo(() => generateRandomData(7), []);
39
24
  return (
40
25
  <>
41
- <div className={styles.chartGroupContainer}>
42
- <div className={styles.tendChart}>
43
- <BaseIndicatorTrendChart
44
- data={values}
45
- title={t('hivPositiveNotLinkedToART', 'HIV +VE Not linked to ART')}
46
- yAxisTitle={t('percentageTestedPositiveNotLinked', '% tested positive not linked')}
47
- />
48
- </div>
49
- <div className={styles.trackingChart}>
50
- <BaseProgressTrackingChart data={data} />
51
- </div>
52
- </div>
26
+ <BaseIndicatorTrendChart
27
+ data={hivPositivePatientValue}
28
+ title={t('hivPositiveNotLinkedToART', 'HIV +VE Not linked to ART')}
29
+ yAxisTitle={t('numberTestedPositiveNotLinked', 'no tested positive not linked')}
30
+ />
31
+ <BaseArtProgressTrackingChart data={monthlyHivPositivePatientData} />
53
32
  </>
54
33
  );
55
34
  };
@@ -3,53 +3,48 @@ import React, { useMemo } from 'react';
3
3
  import { useTranslation } from 'react-i18next';
4
4
  import BaseIndicatorTrendChart from './base-indicator-trend-chart.component';
5
5
  import BaseProgressTrackingChart from './base-progress-tracking-chart.component';
6
- import { sevenDaysRunningDates } from '../../constants';
6
+ import { getNumberOfDays, sevenDaysRunningDates } from '../../constants';
7
7
  import styles from './charts.scss';
8
-
9
- const MissedOpportunityChart = () => {
8
+ type MissedOpportunityChartProps = {
9
+ startDate?: Date;
10
+ endDate?: Date;
11
+ };
12
+ const MissedOpportunityChart: React.FC<MissedOpportunityChartProps> = ({ startDate, endDate }) => {
10
13
  const { t } = useTranslation();
11
14
  const generateRandomData = (numRecords: number) => {
12
15
  return Array.from({ length: numRecords }, (_, i) => ({
13
- week: sevenDaysRunningDates(i),
14
- abnomallPercentage: Math.floor(Math.random() * 50),
16
+ day: sevenDaysRunningDates(i, endDate),
17
+ value: Math.floor(Math.random() * 50),
15
18
  }));
16
19
  };
17
20
 
21
+ const numberSequence = useMemo(() => Math.max(1, getNumberOfDays(startDate, endDate)), [startDate, endDate]);
22
+
18
23
  const generateRandomDataProgress = (numRecords: number) => {
19
24
  const data = [];
20
25
  for (let i = 1; i <= numRecords; i++) {
21
26
  data.push({
22
27
  group: 'Pending',
23
- key: sevenDaysRunningDates(i),
28
+ key: sevenDaysRunningDates(i, endDate),
24
29
  value: Math.floor(Math.random() * 50),
25
30
  });
26
31
  data.push({
27
32
  group: 'Completed',
28
- key: sevenDaysRunningDates(i),
33
+ key: sevenDaysRunningDates(i, endDate),
29
34
  value: Math.floor(Math.random() * 50),
30
35
  });
31
36
  }
32
37
  return data;
33
38
  };
34
39
 
35
- const data = useMemo(() => generateRandomDataProgress(40), []);
36
-
37
- const values = useMemo(() => generateRandomData(40), []);
40
+ const data = useMemo(() => generateRandomDataProgress(numberSequence), [numberSequence, startDate, endDate]);
41
+ const values = useMemo(() => generateRandomData(numberSequence), [numberSequence, startDate, endDate]);
38
42
  return (
39
- <>
40
- <div className={styles.chartGroupContainer}>
41
- <div className={styles.tendChart}>
42
- <BaseIndicatorTrendChart
43
- data={values}
44
- title={t('missedoppotunityVL', 'Missed opportunity VL')}
45
- yAxisTitle={t('percentageMissedVL', '% of missed opportunity VL')}
46
- />
47
- </div>
48
- <div className={styles.trackingChart}>
49
- <BaseProgressTrackingChart data={data} />
50
- </div>
51
- </div>
52
- </>
43
+ <BaseIndicatorTrendChart
44
+ data={values}
45
+ title={t('missedoppotunityVL', 'Missed opportunity in viral load testing')}
46
+ yAxisTitle={t('percentageMissedVL', '% of missed opportunity VL')}
47
+ />
53
48
  );
54
49
  };
55
50