diff --git a/frontend/src/__test__/components/ComingSoonModal.test.tsx b/frontend/src/__test__/components/ComingSoonModal.test.tsx new file mode 100644 index 00000000..037e6f3c --- /dev/null +++ b/frontend/src/__test__/components/ComingSoonModal.test.tsx @@ -0,0 +1,27 @@ +//vite test for the ComingSoonModal component +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import { describe, expect, it, vi } from 'vitest'; +import ComingSoonModal from '../../components/ComingSoonModal'; + +describe('ComingSoonModal', () => { + it('renders the modal', () => { + render(); + expect(screen.getByText('Coming Soon')).toBeInTheDocument(); + expect(screen.getByText('An opening details page is in development.')).toBeInTheDocument(); + }); + + it('renders the modal with the correct opening ID', () => { + render(); + expect(screen.getByText('Opening ID: 1234')).toBeInTheDocument(); + }); + + it('calls the setOpeningDetails function when the modal is closed', async() => { + const setOpeningDetails = vi.fn(); + render(); + const closeButton = screen.getByRole('button', { name: 'Close' }); + await closeButton.click(); + expect(setOpeningDetails).toHaveBeenCalled(); + }); + +}); \ No newline at end of file diff --git a/frontend/src/components/ComingSoonModal/index.tsx b/frontend/src/components/ComingSoonModal/index.tsx new file mode 100644 index 00000000..e61e3add --- /dev/null +++ b/frontend/src/components/ComingSoonModal/index.tsx @@ -0,0 +1,26 @@ +import { Modal } from "@carbon/react"; +interface IComingSoonModal { + openingDetails: string; + setOpeningDetails: (openingDetails: string) => void; +} + +const ComingSoonModal: React.FC = ({ + openingDetails, + setOpeningDetails, +}) => { + return ( + 0} + onRequestClose={() => setOpeningDetails("")} + passiveModal + modalHeading="Coming Soon" + modalLabel={`Opening ID: ${openingDetails}`} + > +

An opening details page is in development.


+

+ {` Until it's available, search for ${openingDetails} in RESULTS to view the opening details.`} +

+
+ ); +}; +export default ComingSoonModal; diff --git a/frontend/src/components/ComingSoonModal/styles.scss b/frontend/src/components/ComingSoonModal/styles.scss new file mode 100644 index 00000000..24f7eaf4 --- /dev/null +++ b/frontend/src/components/ComingSoonModal/styles.scss @@ -0,0 +1,7 @@ +@use '@bcgov-nr/nr-theme/design-tokens/variables.scss' as vars; +@use '@carbon/type'; + +.modal-subtext { + @include type.type-style('body-02'); + font-size: 14px; +} diff --git a/frontend/src/components/SilvicultureSearch/Openings/SearchScreenDataTable/index.tsx b/frontend/src/components/SilvicultureSearch/Openings/SearchScreenDataTable/index.tsx index 4e9d6de9..2e11c97e 100644 --- a/frontend/src/components/SilvicultureSearch/Openings/SearchScreenDataTable/index.tsx +++ b/frontend/src/components/SilvicultureSearch/Openings/SearchScreenDataTable/index.tsx @@ -22,8 +22,6 @@ import { Row, Column, MenuItemDivider, - Modal, - ActionableNotification } from "@carbon/react"; import * as Icons from "@carbon/icons-react"; import StatusTag from "../../../StatusTag"; @@ -46,6 +44,7 @@ import { usePostViewedOpening } from "../../../../services/queries/dashboard/das import { useNotification } from '../../../../contexts/NotificationProvider'; import TruncatedText from "../../../TruncatedText"; import FriendlyDate from "../../../FriendlyDate"; +import ComingSoonModal from "../../../ComingSoonModal"; interface ISearchScreenDataTable { @@ -85,7 +84,7 @@ const SearchScreenDataTable: React.FC = ({ const [openDownload, setOpenDownload] = useState(false); const [selectedRows, setSelectedRows] = useState([]); // State to store selected rows const [toastText, setToastText] = useState(null); - const [openingDetails, setOpeningDetails] = useState(false); + const [openingDetails, setOpeningDetails] = useState(''); const { mutate: markAsViewedOpening, isError, error } = usePostViewedOpening(); const navigate = useNavigate(); @@ -134,7 +133,7 @@ const SearchScreenDataTable: React.FC = ({ // Call the mutation to mark as viewed markAsViewedOpening(openingId, { onSuccess: () => { - setOpeningDetails(true) + setOpeningDetails(openingId.toString()); }, onError: (err: any) => { // Display error notification (UI needs to be designed for this) @@ -316,7 +315,9 @@ const SearchScreenDataTable: React.FC = ({ {headers.map((header) => header.selected ? ( - {header.header} + + {header.header} + ) : null )} @@ -326,24 +327,29 @@ const SearchScreenDataTable: React.FC = ({ rows.map((row: any, i: number) => ( { + //add the api call to send the viewed opening + handleRowClick(row.openingId); + }} > {headers.map((header) => header.selected ? ( (cellRefs.current[i] = el)} key={header.key} - className={header.key === "actions" && showSpatial ? "p-0" : null} - onClick={() => { - if(header.key !== "actions") - handleRowClick(row.openingId); - } + className={ + header.key === "actions" && showSpatial ? "p-0" : null } + onClick={() => { + if (header.key !== "actions") + handleRowClick(row.openingId); + }} > {header.key === "statusDescription" ? ( ) : header.key === "actions" ? ( @@ -355,7 +361,17 @@ const SearchScreenDataTable: React.FC = ({ align="bottom-left" autoAlign > -
+
e.stopPropagation()} + role="button" + tabIndex={0} + onKeyDown={(e) => { + if (e.key === 'Enter' || e.key === ' ') { + handleRowSelectionChanged(row.openingId); + } + }} + > = ({ ) : header.header === "Category" ? ( - - ) : header.key === 'disturbanceStartDate' ? ( + + ) : header.key === "disturbanceStartDate" ? ( ) : ( row[header.key] @@ -453,12 +474,9 @@ const SearchScreenDataTable: React.FC = ({ /> )} - setOpeningDetails(false)} - passiveModal - modalHeading="We are working hard to get this feature asap, unfortunately you cannot view the opening details from SILVA atm." - modalLabel="Opening Details" + );