From bd743fed05c4b9651a39b6bdfbcac29e099962d8 Mon Sep 17 00:00:00 2001
From: LBSantos <118561969+lucasbuenoencora@users.noreply.github.com>
Date: Wed, 1 Feb 2023 11:01:47 -0300
Subject: [PATCH] feat: existents seedlot (#35)
* feat: create existing seedlot table
* feat: added new components and unit tests
* minor adjustments in layout
---
.../components/ExistingSeedlot.test.tsx | 15 ++++
src/__test__/components/Participants.test.tsx | 44 ++++++++++++
src/__test__/components/SeedlotTable.test.tsx | 51 +++++++++++++
src/components/ExistingSeedlot/index.tsx | 53 ++++++++++++++
src/components/ExistingSeedlot/styles.scss | 51 +++++++++++++
src/components/Participants/index.tsx | 28 ++++++++
src/components/Participants/styles.css | 20 ++++++
src/components/SeedlotTable/index.tsx | 72 +++++++++++++++++++
src/components/SeedlotTable/styles.css | 10 +++
src/components/StatusItem/index.tsx | 3 +
src/enums/ActivityStatus.ts | 3 +-
src/mock-data/ExistingSeedlotItems.ts | 70 ++++++++++++++++++
src/theme/components-overrides.scss | 8 +++
src/types/Seedlot.ts | 13 ++++
src/views/SeedlotDashboard/index.tsx | 7 +-
15 files changed, 442 insertions(+), 6 deletions(-)
create mode 100644 src/__test__/components/ExistingSeedlot.test.tsx
create mode 100644 src/__test__/components/Participants.test.tsx
create mode 100644 src/__test__/components/SeedlotTable.test.tsx
create mode 100644 src/components/ExistingSeedlot/index.tsx
create mode 100644 src/components/ExistingSeedlot/styles.scss
create mode 100644 src/components/Participants/index.tsx
create mode 100644 src/components/Participants/styles.css
create mode 100644 src/components/SeedlotTable/index.tsx
create mode 100644 src/components/SeedlotTable/styles.css
create mode 100644 src/mock-data/ExistingSeedlotItems.ts
create mode 100644 src/types/Seedlot.ts
diff --git a/src/__test__/components/ExistingSeedlot.test.tsx b/src/__test__/components/ExistingSeedlot.test.tsx
new file mode 100644
index 000000000..96cba78ac
--- /dev/null
+++ b/src/__test__/components/ExistingSeedlot.test.tsx
@@ -0,0 +1,15 @@
+/* eslint-disable no-undef */
+import React from 'react';
+import { render, screen } from '@testing-library/react';
+import ExistingSeedlot from '../../components/ExistingSeedlot';
+import '@testing-library/jest-dom';
+
+//TODO test Empty Section
+describe('Existing Seedlot component', () => {
+ it('should render title and subtitle correctly', () => {
+ render();
+
+ expect(screen.getByRole('heading', { level: 3 }).textContent).toEqual('Existing seedlot');
+ expect(screen.getByText('Check a summary of your recent seedlots')).toBeInTheDocument();
+ });
+});
diff --git a/src/__test__/components/Participants.test.tsx b/src/__test__/components/Participants.test.tsx
new file mode 100644
index 000000000..247d01a8f
--- /dev/null
+++ b/src/__test__/components/Participants.test.tsx
@@ -0,0 +1,44 @@
+/* eslint-disable no-undef */
+import React from 'react';
+import { render, screen } from '@testing-library/react';
+import Participants from '../../components/Participants';
+import '@testing-library/jest-dom';
+
+describe('Participants component', () => {
+ const number = 12456;
+ it('should render 3 participants correctly', () => {
+ const elements = ['Participant 1', 'Participant 2', 'Participant 3'];
+ render();
+
+ const images = screen.getAllByRole('img');
+ expect(images).toHaveLength(3);
+ expect(images[0]).toBeInTheDocument();
+ expect(images[0]).toHaveAttribute('alt', 'Participant 1');
+ expect(images[1]).toBeInTheDocument();
+ expect(images[1]).toHaveAttribute('alt', 'Participant 2');
+ expect(images[2]).toBeInTheDocument();
+ expect(images[2]).toHaveAttribute('alt', 'Participant 3');
+ });
+
+ it('should render 2 participants correctly', () => {
+ const elements = ['Participant 1', 'Participant 2'];
+ render();
+
+ const images = screen.getAllByRole('img');
+ expect(images).toHaveLength(2);
+ expect(images[0]).toBeInTheDocument();
+ expect(images[0]).toHaveAttribute('alt', 'Participant 1');
+ expect(images[1]).toBeInTheDocument();
+ expect(images[1]).toHaveAttribute('alt', 'Participant 2');
+ });
+
+ it('should render 1 participant correctly', () => {
+ const elements = ['Participant 1'];
+ render();
+
+ const images = screen.getAllByRole('img');
+ expect(images).toHaveLength(1);
+ expect(images[0]).toBeInTheDocument();
+ expect(images[0]).toHaveAttribute('alt', 'Participant 1');
+ });
+});
diff --git a/src/__test__/components/SeedlotTable.test.tsx b/src/__test__/components/SeedlotTable.test.tsx
new file mode 100644
index 000000000..3fdbb58df
--- /dev/null
+++ b/src/__test__/components/SeedlotTable.test.tsx
@@ -0,0 +1,51 @@
+/* eslint-disable no-undef */
+import React from 'react';
+import { render, screen } from '@testing-library/react';
+import SeedlotTable from '../../components/SeedlotTable';
+import ExistingSeedlotItems from '../../mock-data/ExistingSeedlotItems';
+import '@testing-library/jest-dom';
+
+describe('Seedlot Table component', () => {
+ const listItems = ExistingSeedlotItems;
+ const tableHeaders: string[] = [
+ 'Seedlot number',
+ 'Lot class',
+ 'Lot species',
+ 'Form step',
+ 'Status',
+ 'Participants',
+ 'Created at',
+ 'Last modified',
+ 'Approved at'
+ ];
+
+ beforeEach(() => {
+ render(
+
+ );
+ });
+
+ it('should render headers correctly', () => {
+ const headers = screen.getAllByRole('columnheader');
+ expect(headers).toHaveLength(tableHeaders.length);
+ headers.forEach((th, idx) => {
+ expect(th.textContent).toEqual(tableHeaders[idx]);
+ });
+ });
+
+ it('should render columns correctly', () => {
+ const cells = screen.getAllByRole('cell');
+ expect(cells[0].textContent).toEqual('12456');
+ expect(cells[1].textContent).toEqual('A class');
+ expect(cells[2].textContent).toEqual('SX - Spruce hibrid');
+ expect(cells[3].textContent).toEqual('Collection');
+ expect(cells[4].textContent).toEqual('Incomplete');
+ expect(cells[5]).toBeInTheDocument;
+ expect(cells[6].textContent).toEqual('October 10, 2021');
+ expect(cells[7].textContent).toEqual('December 24, 2022');
+ expect(cells[8].textContent).toEqual('--');
+ });
+});
diff --git a/src/components/ExistingSeedlot/index.tsx b/src/components/ExistingSeedlot/index.tsx
new file mode 100644
index 000000000..76149d392
--- /dev/null
+++ b/src/components/ExistingSeedlot/index.tsx
@@ -0,0 +1,53 @@
+import React from 'react';
+
+import { Row, Column } from '@carbon/react';
+
+import SeedlotTable from '../SeedlotTable';
+import EmptySection from '../EmptySection';
+import Subtitle from '../Subtitle';
+
+import ExistingSeedlotItems from '../../mock-data/ExistingSeedlotItems';
+
+import './styles.scss';
+
+const ExistingSeedlot = () => {
+ const listItems = ExistingSeedlotItems;
+
+ const tableHeaders: string[] = [
+ 'Seedlot number',
+ 'Lot class',
+ 'Lot species',
+ 'Form step',
+ 'Status',
+ 'Participants',
+ 'Created at',
+ 'Last modified',
+ 'Approved at'
+ ];
+
+ return (
+
+
+ Existing seedlot
+
+
+
+
+ {(listItems.length === 0) && (
+
+
+
+ )}
+
+
+ );
+};
+
+export default ExistingSeedlot;
diff --git a/src/components/ExistingSeedlot/styles.scss b/src/components/ExistingSeedlot/styles.scss
new file mode 100644
index 000000000..5d2849a56
--- /dev/null
+++ b/src/components/ExistingSeedlot/styles.scss
@@ -0,0 +1,51 @@
+@use '../../theme/variables.scss' as vars;
+@use '../../theme/colors.scss' as colors;
+
+h4.existing-seedlot-subtitle {
+ padding-bottom: 1rem;
+}
+
+.existing-seedlot {
+ background-color: colors.$white !important;
+ margin-left: 2rem;
+ margin-right: 2rem;
+ border: 1px solid colors.$gray-20;
+ border-radius: 4px;
+}
+
+.seedlot-table {
+ padding: 0 !important;
+}
+
+table.#{vars.$bcgov-prefix}--data-table th,
+table.#{vars.$bcgov-prefix}--data-table td {
+ padding-left: 2rem;
+}
+
+.existing-seedlot-title {
+ padding-left: 2rem;
+}
+
+.existing-seedlot-table {
+ padding: 0 !important;
+}
+
+.empty-existing-seedlot {
+ margin: 3.44rem 0;
+}
+
+@media only screen and (max-width: 1584px) {
+ .existing-seedlot-title {
+ padding-left: 3rem;
+ }
+}
+
+@media only screen and (max-width: 672px) {
+ .existing-seedlot-title {
+ padding-left: 2rem;
+ }
+
+ .existing-seedlot {
+ overflow-x: scroll;
+ }
+}
diff --git a/src/components/Participants/index.tsx b/src/components/Participants/index.tsx
new file mode 100644
index 000000000..9938985aa
--- /dev/null
+++ b/src/components/Participants/index.tsx
@@ -0,0 +1,28 @@
+import React from 'react';
+
+import AvatarImage from '../AvatarImage';
+
+import './styles.css';
+
+interface ParticipantsProps {
+ elements: string[];
+ number: number;
+}
+
+const Participants = ({ elements, number }: ParticipantsProps) => (
+
+ {elements.map((participant, pidx) => (
+
+ ))}
+
+);
+
+export default Participants;
diff --git a/src/components/Participants/styles.css b/src/components/Participants/styles.css
new file mode 100644
index 000000000..32cac9916
--- /dev/null
+++ b/src/components/Participants/styles.css
@@ -0,0 +1,20 @@
+.participants {
+ display: inline-flex;
+}
+
+.img-participant1 {
+ position: relative;
+ z-index: 1;
+}
+
+.img-participant2 {
+ position: relative;
+ z-index: 2;
+ right: 0.2rem;
+}
+
+.img-participant3 {
+ position: relative;
+ z-index: 3;
+ right: 0.4rem;
+}
diff --git a/src/components/SeedlotTable/index.tsx b/src/components/SeedlotTable/index.tsx
new file mode 100644
index 000000000..f80b3ff54
--- /dev/null
+++ b/src/components/SeedlotTable/index.tsx
@@ -0,0 +1,72 @@
+import React from 'react';
+import { hashObject } from 'react-hash-string';
+
+import {
+ Table,
+ TableHead,
+ TableHeader,
+ TableRow,
+ TableBody,
+ TableCell
+} from '@carbon/react';
+
+import Participants from '../Participants';
+import StatusItem from '../StatusItem';
+
+import Seedlot from '../../types/Seedlot';
+
+import './styles.css';
+
+interface TableProps {
+ elements: Seedlot[];
+ headers: string[];
+}
+
+const SeedlotTable = ({ elements, headers }: TableProps) => {
+ const formatDate = (date: string) => {
+ if (typeof date !== 'undefined' && date) {
+ const options: Intl.DateTimeFormatOptions = { year: 'numeric', month: 'long', day: 'numeric' };
+ return new Date(`${date}T00:00:00-08:00`).toLocaleDateString([], options);
+ }
+ return '--';
+ };
+
+ return (
+
+
+
+ {headers.map((header, idx) => (
+
+ ))}
+
+
+
+ {elements.map((item, idx) => (
+
+ {item.number}
+ {`${item.class} class`}
+ {item.lot_species}
+ {item.form_step}
+
+
+
+
+
+
+ {formatDate(item.created_at)}
+ {formatDate(item.last_modified)}
+ {formatDate(item.approved_at)}
+
+ ))}
+
+
+ );
+};
+
+export default SeedlotTable;
diff --git a/src/components/SeedlotTable/styles.css b/src/components/SeedlotTable/styles.css
new file mode 100644
index 000000000..64731c9fa
--- /dev/null
+++ b/src/components/SeedlotTable/styles.css
@@ -0,0 +1,10 @@
+a {
+ color: inherit;
+ text-decoration: inherit
+}
+
+@media only screen and (max-width: 672px) {
+ .seedlot-table {
+ width: 56.25rem;
+ }
+}
diff --git a/src/components/StatusItem/index.tsx b/src/components/StatusItem/index.tsx
index 338dbdfcd..4d74e1e4e 100644
--- a/src/components/StatusItem/index.tsx
+++ b/src/components/StatusItem/index.tsx
@@ -14,6 +14,9 @@ const statusClass = (param: number) => {
case 3:
// Canceled
return 'magenta';
+ case 4:
+ // Incomplete
+ return 'purple';
default:
// Pending
return 'gray';
diff --git a/src/enums/ActivityStatus.ts b/src/enums/ActivityStatus.ts
index bbcd961e5..a1da71b9d 100644
--- a/src/enums/ActivityStatus.ts
+++ b/src/enums/ActivityStatus.ts
@@ -2,7 +2,8 @@ const ACTIVITY_STATUS = {
PENDING: 'Pending',
IN_PROGRESS: 'In progress',
APPROVED: 'Approved',
- CANCELED: 'Canceled'
+ CANCELED: 'Canceled',
+ INCOMPLETE: 'Incomplete'
};
export default ACTIVITY_STATUS;
diff --git a/src/mock-data/ExistingSeedlotItems.ts b/src/mock-data/ExistingSeedlotItems.ts
new file mode 100644
index 000000000..9cfa0523e
--- /dev/null
+++ b/src/mock-data/ExistingSeedlotItems.ts
@@ -0,0 +1,70 @@
+const ExistingSeedlotItems = [
+ {
+ number: 12456,
+ class: 'A',
+ lot_species: 'SX - Spruce hibrid',
+ form_step: 'Collection',
+ status: 4,
+ participants: ['Participant 1', 'Participant 2', 'Participant 3'],
+ created_at: '2021-10-10',
+ last_modified: '2022-12-24',
+ approved_at: ''
+ },
+ {
+ number: 12457,
+ class: 'A',
+ lot_species: 'SX - Spruce hibrid',
+ form_step: 'Collection',
+ status: 4,
+ participants: ['Participant 1', 'Participant 2', 'Participant 3'],
+ created_at: '2021-10-10',
+ last_modified: '2022-12-24',
+ approved_at: ''
+ },
+ {
+ number: 12458,
+ class: 'A',
+ lot_species: 'SX - Spruce hibrid',
+ form_step: 'Collection',
+ status: 4,
+ participants: ['Participant 1', 'Participant 2', 'Participant 3'],
+ created_at: '2021-10-10',
+ last_modified: '2022-12-24',
+ approved_at: ''
+ },
+ {
+ number: 12459,
+ class: 'A',
+ lot_species: 'SX - Spruce hibrid',
+ form_step: 'Collection',
+ status: 0,
+ participants: ['Participant 1', 'Participant 2', 'Participant 3'],
+ created_at: '2021-10-10',
+ last_modified: '2022-12-24',
+ approved_at: ''
+ },
+ {
+ number: 12460,
+ class: 'A',
+ lot_species: 'SX - Spruce hibrid',
+ form_step: 'Collection',
+ status: 0,
+ participants: ['Participant 1', 'Participant 2', 'Participant 3'],
+ created_at: '2021-10-10',
+ last_modified: '2022-12-24',
+ approved_at: ''
+ },
+ {
+ number: 12461,
+ class: 'A',
+ lot_species: 'SX - Spruce hibrid',
+ form_step: 'Collection',
+ status: 0,
+ participants: ['Participant 1', 'Participant 2', 'Participant 3'],
+ created_at: '2021-10-10',
+ last_modified: '2022-12-24',
+ approved_at: '2022-12-25'
+ }
+];
+
+export default ExistingSeedlotItems;
diff --git a/src/theme/components-overrides.scss b/src/theme/components-overrides.scss
index b2182a1ea..badd391a7 100644
--- a/src/theme/components-overrides.scss
+++ b/src/theme/components-overrides.scss
@@ -150,6 +150,14 @@
padding: 0 !important;
}
+.#{variables.$bcgov-prefix}--data-table tr th{
+ background-color: var(--#{variables.$bcgov-prefix}-layer-01);
+}
+
+.#{variables.$bcgov-prefix}--data-table tr td{
+ background-color: var(--#{variables.$bcgov-prefix}-layer-02);
+}
+
.#{variables.$bcgov-prefix}--table-header-label {
font-weight: bold;
}
diff --git a/src/types/Seedlot.ts b/src/types/Seedlot.ts
new file mode 100644
index 000000000..be27cb80a
--- /dev/null
+++ b/src/types/Seedlot.ts
@@ -0,0 +1,13 @@
+type Seedlot = {
+ number: number;
+ class: string;
+ lot_species: string;
+ form_step: string;
+ status: number;
+ participants: string[];
+ created_at: string;
+ last_modified: string;
+ approved_at: string;
+}
+
+export default Seedlot;
diff --git a/src/views/SeedlotDashboard/index.tsx b/src/views/SeedlotDashboard/index.tsx
index 55d7815a3..7be23de1d 100644
--- a/src/views/SeedlotDashboard/index.tsx
+++ b/src/views/SeedlotDashboard/index.tsx
@@ -7,6 +7,7 @@ import {
} from '@carbon/react';
import PageTitle from '../../components/PageTitle';
+import ExistingSeedlot from '../../components/ExistingSeedlot';
import './styles.css';
@@ -42,11 +43,7 @@ const SeedlotDashboard = () => (
-
-
- Exisisting Seedlot Placeholder
-
-
+
);