Skip to content

Commit

Permalink
added dashboard and all corresponsding files, updated tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Kilian Berres authored and Kilian Berres committed Jul 17, 2024
1 parent 25b314d commit 4b0ae4b
Show file tree
Hide file tree
Showing 27 changed files with 8,379 additions and 2,960 deletions.
3 changes: 3 additions & 0 deletions mocks/comet-extras.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import React from 'react';

export const Spinner = ({ loadingText }: { loadingText: string }) => <div role="status">{loadingText}</div>;
4 changes: 4 additions & 0 deletions mocks/comet-uswds.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import React from 'react';

export const Card = ({ children }: { children: React.ReactNode }) => <div>{children}</div>;
export const CardBody = ({ children }: { children: React.ReactNode }) => <div>{children}</div>;
16 changes: 16 additions & 0 deletions mocks/mock-spacecraft.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Spacecraft } from '../src/types/spacecraft';

export const mockData: { items: Spacecraft[] } = {
items: [
{ id: 1, name: 'Spacecraft 1', affiliation: 'Affiliation 1', dimensions: 'Dimensions 1', appearances: 5 },
{ id: 2, name: 'Spacecraft 2', affiliation: 'Affiliation 2', dimensions: 'Dimensions 2', appearances: 3 },
{ id: 3, name: 'Spacecraft 3', affiliation: 'Affiliation 3', dimensions: 'Dimensions 3', appearances: 7 },
{ id: 4, name: 'Spacecraft 4', affiliation: 'Affiliation 4', dimensions: 'Dimensions 4', appearances: 2 },
{ id: 5, name: 'Spacecraft 5', affiliation: 'Affiliation 5', dimensions: 'Dimensions 5', appearances: 4 },
{ id: 6, name: 'Spacecraft 6', affiliation: 'Affiliation 6', dimensions: 'Dimensions 6', appearances: 6 },
{ id: 7, name: 'Spacecraft 7', affiliation: 'Affiliation 7', dimensions: 'Dimensions 7', appearances: 1 },
{ id: 8, name: 'Spacecraft 8', affiliation: 'Affiliation 8', dimensions: 'Dimensions 8', appearances: 8 },
{ id: 9, name: 'Spacecraft 9', affiliation: 'Affiliation 9', dimensions: 'Dimensions 9', appearances: 9 },
{ id: 10, name: 'Spacecraft 10', affiliation: 'Affiliation 10', dimensions: 'Dimensions 10', appearances: 0 },
],
};
10,454 changes: 7,530 additions & 2,924 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,20 @@
"postinstall": "node ./scripts/postinstall.js"
},
"dependencies": {
"@metrostar/comet-data-viz": "^1.1.5",
"@metrostar/comet-extras": "^1.3.5",
"@metrostar/comet-uswds": "2.1.2",
"@tanstack/react-query": "5.50.1",
"@types/axios": "^0.14.0",
"@uswds/uswds": "^3.8.0",
"axios": "^1.7.2",
"axios-mock-adapter": "^1.22.0",
"next": "latest",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.52.1",
"react-oidc-context": "^3.1.0",
"react-router-dom": "^6.24.1",
"recoil": "0.7.7"
},
"devDependencies": {
Expand All @@ -30,6 +37,7 @@
"@vitejs/plugin-react": "^4.3.1",
"@vitest/coverage-v8": "^2.0.1",
"@vitest/ui": "^2.0.1",
"jest": "^29.7.0",
"jsdom": "^24.1.0",
"sass": "^1.70.0",
"tsconfig-paths": "4.2.0",
Expand Down
21 changes: 21 additions & 0 deletions src/app/dashboard/dashboard-bar-chart/dashboard-bar-chart.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { mockData } from '../../../data/spacecraft';
import { act, render } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import { RecoilRoot } from 'recoil';
import { DashboardBarChart } from './dashboard-bar-chart';

describe('DashboardBarChart', () => {
test('should render successfully', async () => {
const { baseElement } = render(
<RecoilRoot>
<BrowserRouter>
<DashboardBarChart items={mockData.items} />
</BrowserRouter>
</RecoilRoot>,
);
await act(async () => {
expect(baseElement).toBeTruthy();
});
expect(baseElement.querySelector('.VictoryContainer')).toBeDefined();
});
});
55 changes: 55 additions & 0 deletions src/app/dashboard/dashboard-bar-chart/dashboard-bar-chart.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"use client";

import { BarGraph } from '@metrostar/comet-data-viz';
import { Spacecraft } from '../../../types/spacecraft';
import React, { useEffect, useState } from 'react';
import { ChartData } from '../types';

interface DashboardBarChartProps {
items: Spacecraft[] | undefined;
}

export const DashboardBarChart = ({
items,
}: DashboardBarChartProps): React.ReactElement => {
const [data, setData] = useState<ChartData[]>();
useEffect(() => {
if (items) {
const newData: ChartData[] = [];
const set = new Set<string>();
items.forEach((item: Spacecraft) => {
set.add(item.appearances.toString());
});

set.forEach((name: string) => {
const total = items.filter(
(item: Spacecraft) => item.appearances.toString() === name,
).length;
newData.push({ x: name, y: total });
});
setData(newData);
}
}, [items]);

return data ? (
<div
style={{
height: '300px',
width: '400px',
}}
>
<BarGraph
chart={{
height: 300,
title: 'Spacecraft Appearance Bar Graph',
width: 375,
}}
alignment="start"
data={data}
color="#0d7ea2"
/>
</div>
) : (
<></>
);
};
21 changes: 21 additions & 0 deletions src/app/dashboard/dashboard-pie-chart/dashboard-pie-chart.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { mockData } from '../../../data/spacecraft';
import { act, render } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import { RecoilRoot } from 'recoil';
import { DashboardPieChart } from './dashboard-pie-chart';

describe('DashboardPieChart', () => {
test('should render successfully', async () => {
const { baseElement } = render(
<RecoilRoot>
<BrowserRouter>
<DashboardPieChart items={mockData.items} />
</BrowserRouter>
</RecoilRoot>,
);
await act(async () => {
expect(baseElement).toBeTruthy();
});
expect(baseElement.querySelector('.VictoryContainer')).toBeDefined();
});
});
53 changes: 53 additions & 0 deletions src/app/dashboard/dashboard-pie-chart/dashboard-pie-chart.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"use client";

import { PieChart } from '@metrostar/comet-data-viz';
import { Spacecraft } from '../../../types/spacecraft';
import React, { useEffect, useState } from 'react';
import { ChartData } from '../types';

interface DashboardPieChartProps {
items: Spacecraft[] | undefined;
}

export const DashboardPieChart = ({
items,
}: DashboardPieChartProps): React.ReactElement => {
const [data, setData] = useState<ChartData[]>();
useEffect(() => {
if (items) {
const newData: ChartData[] = [];
const set = new Set<string>();
items.forEach((item: Spacecraft) => {
set.add(item.affiliation);
});

set.forEach((name: string) => {
const total = items.filter(
(item: Spacecraft) => item.affiliation === name,
).length;
newData.push({ x: name.replace('Affiliation ', ''), y: total });
});
setData(newData);
}
}, [items]);

return data ? (
<div
style={{
height: '300px',
width: '400px',
}}
>
<PieChart
title="Spacecraft Affiliation Pie Chart"
innerRadius={60}
width={375}
height={300}
data={data}
colors={['#0d7ea2', '#cd425b']}
/>
</div>
) : (
<></>
);
};
66 changes: 66 additions & 0 deletions src/app/dashboard/dashboard-table/dashboard-table.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { mockData } from '../../../../mocks/mock-spacecraft';
import { act, render } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import { RecoilRoot } from 'recoil';
import { DashboardTable } from './dashboard-table';
import { vi } from 'vitest';
import { Spacecraft } from 'spacecraft';


// Mock the DataTable component
vi.mock('@metrostar/comet-extras', async (importOriginal) => {
const actual = (await importOriginal()) || {};
return {
...actual,
DataTable: ({ columns, data }) => (
<table className="data-table">
<thead>
<tr>
{columns.map((col) => (
<th key={col.accessorKey}>{col.header}</th>
))}
</tr>
</thead>
<tbody>
{data.map((row, index) => (
<tr key={index}>
{columns.map((col) => (
<td key={col.accessorKey}>{row[col.accessorKey]}</td>
))}
</tr>
))}
</tbody>
</table>
),
};
});

describe('DashboardTable', () => {
test('should render successfully', () => {
const { baseElement } = render(
<RecoilRoot>
<BrowserRouter>
<DashboardTable items={[]} />
</BrowserRouter>
</RecoilRoot>,
);
expect(baseElement).toBeTruthy();
});

test('should render with mock data', async () => {
const { baseElement } = render(
<RecoilRoot>
<BrowserRouter>
<DashboardTable items={mockData.items as Spacecraft[]} />
</BrowserRouter>
</RecoilRoot>,
);
await act(async () => {
expect(baseElement).toBeTruthy();
});
expect(baseElement.querySelector('.data-table')).toBeDefined();
expect(
baseElement.querySelectorAll('.data-table > tbody > tr'),
).toHaveLength(10);
});
});
87 changes: 87 additions & 0 deletions src/app/dashboard/dashboard-table/dashboard-table.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
"use client";

import { DataTable } from '@metrostar/comet-extras';
import { Spacecraft } from '../../../types/spacecraft';
import { ColumnDef } from '@tanstack/react-table';
import React, { useEffect, useState } from 'react';
import Link from 'next/link';
import { TableData } from '../types';

interface DashboardTableProps {
items: Spacecraft[] | undefined;
}

export const DashboardTable = ({
items,
}: DashboardTableProps): React.ReactElement => {
const [data, setData] = useState<TableData[]>();

// Ensure window-related operations run only on the client side
React.useEffect(() => {
if (typeof window !== 'undefined' && items) {
console.log('ITEMS: ', items)
const newData: TableData[] = [];
items.forEach((item: Spacecraft) => {
newData.push({
name: (
// <Link id={`details-link-${item.id}`} href={`/details/${item.id}`}>
<Link id={`details-link-${item.id}`} href={`../../details/${item.id}`}>
{item.name}
</Link>
),
affiliation: item.affiliation,
dimensions: item.dimensions,
appearances: item.appearances,
});
});
setData(newData);
}
}, [items]);

// Log details folder to console
React.useEffect(() => {
if (typeof window !== 'undefined') {
console.log('Details folder:', items);
}
}, [items]);

const cols = React.useMemo<ColumnDef<TableData>[]>(
() => [
{
accessorKey: 'name',
header: 'Name',
cell: (info) => info.getValue(),
},
{
accessorKey: 'affiliation',
header: 'Affiliation',
cell: (info) => info.getValue(),
},
{
accessorKey: 'dimensions',
header: 'Dimensions',
cell: (info) => info.getValue(),
},
{
accessorKey: 'appearances',
header: 'Appearances',
cell: (info) => info.getValue(),
},
],
[],
);

return data ? (
<DataTable
id="launch-table"
className="width-full"
columns={cols}
data={data}
sortable
sortCol="appearances"
sortDir="desc"
/>
) : (
<></>
);
};
Loading

0 comments on commit 4b0ae4b

Please sign in to comment.