diff --git a/src/components/Chart/Chart.tsx b/src/components/Chart/Chart.tsx
index 4b80aa9..6d6c277 100644
--- a/src/components/Chart/Chart.tsx
+++ b/src/components/Chart/Chart.tsx
@@ -1,36 +1,96 @@
import { useState, useEffect } from 'react';
import Highcharts from 'highcharts';
import { CircularProgress } from '@mui/material';
-import { chartOptions } from '../../data/chart-options';
+import { getTotalStatus } from '../../utils/get-mock-data';
+import { useDateRange } from '../../hooks/useDateRange';
+import dayjs from 'dayjs';
+
+import type { Options, SeriesOptionsType } from 'highcharts';
+import type { TotalStatus } from '../../types/status';
import './Chart.css';
const Chart = () => {
const [isLoading, setIsLoading] = useState(true);
+ const { date } = useDateRange();
+
useEffect(() => {
- // simulate fetch
- try {
- setTimeout(() => {
+ let isMounted: boolean = true;
+
+ const fetchData = async () => {
+ try {
+ await new Promise((resolve) => setTimeout(resolve, 1100));
+
+ if (!isMounted) return;
+
+ const chartTitle: string = 'Status Totals';
+ const chartCategoriesX: string[] = ['Open', 'Closed', 'In Progress'];
+ const chartTitleY: string = 'Total';
+
+ const totalStatus: TotalStatus = getTotalStatus(dayjs(date.startDate), dayjs(date.endDate));
+
+ const chartSeries: SeriesOptionsType[] = [
+ {
+ data: [
+ {
+ y: totalStatus.Open,
+ color: '#DEC5E3',
+ },
+ {
+ y: totalStatus.Closed,
+ color: '#81F7E5',
+ },
+ {
+ y: totalStatus['In Progress'],
+ color: '#B6DCFE',
+ },
+ ],
+ },
+ ] as SeriesOptionsType[];
+
+ const chartOptions = (): Options => ({
+ chart: {
+ type: 'column',
+ },
+ title: {
+ text: chartTitle,
+ },
+ xAxis: {
+ categories: chartCategoriesX,
+ },
+ yAxis: {
+ title: {
+ text: chartTitleY,
+ },
+ },
+ series: chartSeries,
+ accessibility: {
+ enabled: true,
+ },
+ colors: ['#000000'],
+ });
+
const columnChart: Highcharts.Options = chartOptions();
- // check if the element exists/is mounted before rendering
- if (document.getElementById('chart1')) {
+ if (isMounted && document.getElementById('chart1')) {
Highcharts.chart('chart1', columnChart);
}
- }, 1100);
- // catch any thrown errors
- } catch (err) {
- console.error(err);
- }
+ } catch (err) {
+ console.error(err);
+ } finally {
+ if (isMounted) {
+ setIsLoading(false);
+ }
+ }
+ };
+
+ fetchData();
- // clean up
return () => {
- setTimeout(() => {
- setIsLoading(false);
- }, 1100);
+ isMounted = false;
};
- }, []);
+ }, [date.startDate, date.endDate]);
return (
diff --git a/src/components/DataGridTable/DataGridTable.tsx b/src/components/DataGridTable/DataGridTable.tsx
index 56ff4a9..92f3f48 100644
--- a/src/components/DataGridTable/DataGridTable.tsx
+++ b/src/components/DataGridTable/DataGridTable.tsx
@@ -17,20 +17,34 @@ const DataGridTable = () => {
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
- setTimeout(() => {
- // filter rows based on date range
- const filtered: GridTable['rows'] = gridTable.rows.filter((field) =>
- isBetween(dayjs(field.DateCreated), dayjs(date.startDate), dayjs(date.endDate))
- );
+ let isMounted: boolean = true;
- setFilterRows(filtered);
- }, 500);
+ const fetchData = async () => {
+ try {
+ await new Promise((resolve) => setTimeout(resolve, 1100));
+
+ if (!isMounted) return;
+
+ // filter rows based on date range
+ const filtered: GridTable['rows'] = gridTable.rows.filter((field) =>
+ isBetween(dayjs(field.DateCreated), dayjs(date.startDate), dayjs(date.endDate))
+ );
+
+ setFilterRows(filtered);
+ } catch (err) {
+ console.error(err);
+ } finally {
+ if (isMounted) {
+ setIsLoading(false);
+ }
+ }
+ };
+
+ fetchData();
// clean up
return () => {
- setTimeout(() => {
- setIsLoading(false);
- }, 1100);
+ isMounted = false;
};
}, [date]);
diff --git a/src/data/data.ts b/src/data/data.ts
index 1eed37d..03a60b6 100644
--- a/src/data/data.ts
+++ b/src/data/data.ts
@@ -1,53 +1,6 @@
+import data from './json/data.json';
+
import type { MockData } from '../types/mockdata';
// mock data
-export const mockData: MockData[] = [
- {
- id: 1,
- title: 'Set 1',
- description: 'Description for Set 1',
- dateCreated: '01/01/2024',
- status: 'Open',
- comments: 'No comments.',
- },
- {
- id: 2,
- title: 'Set 2',
- description: 'Description for Set 2',
- dateCreated: '01/02/2024',
- status: 'Open',
- comments: 'No comments.',
- },
- {
- id: 3,
- title: 'Set 3',
- description: 'Description for Set 3',
- dateCreated: '01/03/2024',
- status: 'Closed',
- comments: 'No comments.',
- },
- {
- id: 4,
- title: 'Set 4',
- description: 'Description for Set 4',
- dateCreated: '01/04/2024',
- status: 'Closed',
- comments: 'No comments.',
- },
- {
- id: 5,
- title: 'Set 5',
- description: 'Description for Set 5',
- dateCreated: '01/05/2024',
- status: 'In Progress',
- comments: 'No comments.',
- },
- {
- id: 6,
- title: 'Set 6',
- description: 'Description for Set 6',
- dateCreated: '01/06/2024',
- status: 'In Progress',
- comments: 'No comments.',
- },
-];
+export const mockData: MockData[] = JSON.parse(JSON.stringify(data));
diff --git a/src/data/json/data.json b/src/data/json/data.json
new file mode 100644
index 0000000..e1382d6
--- /dev/null
+++ b/src/data/json/data.json
@@ -0,0 +1,50 @@
+[
+ {
+ "id": 1,
+ "title": "Set 1",
+ "description": "Description for Set 1",
+ "dateCreated": "01/01/2024",
+ "status": "Open",
+ "comments": "No comments."
+ },
+ {
+ "id": 2,
+ "title": "Set 2",
+ "description": "Description for Set 2",
+ "dateCreated": "01/02/2024",
+ "status": "Open",
+ "comments": "No comments."
+ },
+ {
+ "id": 3,
+ "title": "Set 3",
+ "description": "Description for Set 3",
+ "dateCreated": "01/03/2024",
+ "status": "Closed",
+ "comments": "No comments."
+ },
+ {
+ "id": 4,
+ "title": "Set 4",
+ "description": "Description for Set 4",
+ "dateCreated": "01/04/2024",
+ "status": "Closed",
+ "comments": "No comments."
+ },
+ {
+ "id": 5,
+ "title": "Set 5",
+ "description": "Description for Set 5",
+ "dateCreated": "01/05/2024",
+ "status": "In Progress",
+ "comments": "No comments."
+ },
+ {
+ "id": 6,
+ "title": "Set 6",
+ "description": "Description for Set 6",
+ "dateCreated": "01/06/2024",
+ "status": "In Progress",
+ "comments": "No comments."
+ }
+]
diff --git a/src/types/status.ts b/src/types/status.ts
index a32313a..fece602 100644
--- a/src/types/status.ts
+++ b/src/types/status.ts
@@ -1 +1,7 @@
export type Status = 'Open' | 'Closed' | 'In Progress';
+
+export type TotalStatus = {
+ Open: number;
+ Closed: number;
+ 'In Progress': number;
+};
diff --git a/src/utils/get-mock-data.ts b/src/utils/get-mock-data.ts
index ddd3d64..3f0ffc5 100644
--- a/src/utils/get-mock-data.ts
+++ b/src/utils/get-mock-data.ts
@@ -1,6 +1,24 @@
import { mockData } from '../data/data';
+import dayjs from 'dayjs';
-import type { Status } from '../types/status';
+import type { Dayjs } from 'dayjs';
+import type { MockData } from '../types/mockdata';
+import type { TotalStatus } from '../types/status';
+
+/**
+ * Filter by date range.
+ *
+ * @param start Start date
+ * @param end End date
+ * @returns
+ */
+export function filterByDateRange(start: string | Dayjs, end: string | Dayjs): MockData[] {
+ const filter: MockData[] = mockData.filter(
+ (props) => dayjs(props.dateCreated) >= dayjs(start) && dayjs(props.dateCreated) <= dayjs(end)
+ );
+
+ return filter;
+}
/**
* Get total mock data entries
@@ -11,14 +29,35 @@ export function getTotalMockData(): number {
return mockData?.length;
}
-export function getTotalStatus(status: Status): number {
- let statusCount: number = 0;
+/**
+ * Get total data entries by status.
+ *
+ * @param status Status to filter by
+ * @param start Start of date range
+ * @param end End of date range
+ * @returns Object with the total of each status
+ */
+export function getTotalStatus(start: Dayjs, end: Dayjs): TotalStatus {
+ let openCount: number = 0;
+ let closedCount: number = 0;
+ let inProgressCount: number = 0;
- mockData.map((data) => {
- if (data.status === status) {
- statusCount++;
+ filterByDateRange(start, end).map((props) => {
+ switch (props.status) {
+ case 'Open':
+ openCount++;
+ break;
+ case 'Closed':
+ closedCount++;
+ break;
+ case 'In Progress':
+ inProgressCount++;
}
});
- return statusCount;
+ return {
+ Open: openCount,
+ Closed: closedCount,
+ 'In Progress': inProgressCount,
+ };
}