Skip to content

Commit

Permalink
Filter chart based on date range, refactor datagridtable, move mock d…
Browse files Browse the repository at this point in the history
…ata into json file
  • Loading branch information
alexwkleung committed Dec 27, 2024
1 parent e3b8bc0 commit 100cd61
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 83 deletions.
92 changes: 76 additions & 16 deletions src/components/Chart/Chart.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<div className="chart-container-root mt-10">
Expand Down
34 changes: 24 additions & 10 deletions src/components/DataGridTable/DataGridTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,34 @@ const DataGridTable = () => {
const [isLoading, setIsLoading] = useState<boolean>(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]);

Expand Down
53 changes: 3 additions & 50 deletions src/data/data.ts
Original file line number Diff line number Diff line change
@@ -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));
50 changes: 50 additions & 0 deletions src/data/json/data.json
Original file line number Diff line number Diff line change
@@ -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."
}
]
6 changes: 6 additions & 0 deletions src/types/status.ts
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
export type Status = 'Open' | 'Closed' | 'In Progress';

export type TotalStatus = {
Open: number;
Closed: number;
'In Progress': number;
};
53 changes: 46 additions & 7 deletions src/utils/get-mock-data.ts
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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,
};
}

0 comments on commit 100cd61

Please sign in to comment.