From c4a53e4e478095da5650435db496b1cf4f5ac8c0 Mon Sep 17 00:00:00 2001 From: Paulo Gomes da Cruz Junior Date: Tue, 12 Nov 2024 13:28:28 -0800 Subject: [PATCH 1/2] fix(SILVA-566): close advanced search when user click on search (#459) --- .../SilvicultureSearch/Openings/OpeningsSearchBar/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/components/SilvicultureSearch/Openings/OpeningsSearchBar/index.tsx b/frontend/src/components/SilvicultureSearch/Openings/OpeningsSearchBar/index.tsx index 173840aa..ad4fb002 100644 --- a/frontend/src/components/SilvicultureSearch/Openings/OpeningsSearchBar/index.tsx +++ b/frontend/src/components/SilvicultureSearch/Openings/OpeningsSearchBar/index.tsx @@ -31,6 +31,7 @@ const OpeningsSearchBar: React.FC = ({ const handleSearchClick = () => { onSearchClick(); + setIsOpen(false); }; const handleInputChange = (e: React.ChangeEvent) => { From ca0ddf7343b098eb8cbb589357824c4c6d5e26ce Mon Sep 17 00:00:00 2001 From: Paulo Gomes da Cruz Junior Date: Tue, 12 Nov 2024 13:45:00 -0800 Subject: [PATCH 2/2] fix(SILVA-562): fixing search result size and value (#460) --- frontend/package-lock.json | 17 +++- frontend/package.json | 1 + .../__test__/components/FriendlyDate.test.tsx | 79 +++++++++++++++++++ .../src/components/FriendlyDate/index.tsx | 34 ++++++++ .../Openings/SearchScreenDataTable/index.tsx | 5 +- .../SearchScreenDataTable/testData.ts | 2 +- frontend/src/contexts/PaginationProvider.tsx | 4 +- 7 files changed, 135 insertions(+), 7 deletions(-) create mode 100644 frontend/src/__test__/components/FriendlyDate.test.tsx create mode 100644 frontend/src/components/FriendlyDate/index.tsx diff --git a/frontend/package-lock.json b/frontend/package-lock.json index e8055a65..ccf6c592 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -19,6 +19,7 @@ "@vitejs/plugin-react-swc": "^3.3.2", "aws-amplify": "^6.7.0", "axios": "^1.6.8", + "date-fns": "^4.1.0", "jspdf": "^2.5.2", "jspdf-autotable": "^3.8.3", "leaflet": "^1.9.4", @@ -1725,6 +1726,16 @@ "react-dom": "^16.8.6 || ^17.0.1 || ^18.2.0" } }, + "node_modules/@carbon/charts/node_modules/date-fns": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, "node_modules/@carbon/colors": { "version": "11.28.0", "resolved": "https://registry.npmjs.org/@carbon/colors/-/colors-11.28.0.tgz", @@ -7170,9 +7181,9 @@ } }, "node_modules/date-fns": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", - "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", "license": "MIT", "funding": { "type": "github", diff --git a/frontend/package.json b/frontend/package.json index 4646a57d..f1023b8c 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -15,6 +15,7 @@ "@vitejs/plugin-react-swc": "^3.3.2", "aws-amplify": "^6.7.0", "axios": "^1.6.8", + "date-fns": "^4.1.0", "jspdf": "^2.5.2", "jspdf-autotable": "^3.8.3", "leaflet": "^1.9.4", diff --git a/frontend/src/__test__/components/FriendlyDate.test.tsx b/frontend/src/__test__/components/FriendlyDate.test.tsx new file mode 100644 index 00000000..bb3db789 --- /dev/null +++ b/frontend/src/__test__/components/FriendlyDate.test.tsx @@ -0,0 +1,79 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import { vi } from 'vitest'; +import FriendlyDate from '../../components/FriendlyDate'; + +// Mock Tooltip component from Carbon to ensure tests run without extra dependencies +vi.mock('@carbon/react', () => { + const Tooltip = ({ label, children }) => {children}; + return { Tooltip }; +}); + +// Mock `Date.now` for consistent testing +beforeAll(() => { + vi.useFakeTimers(); + vi.setSystemTime(new Date('2024-01-24T00:00:00')); // Set a fixed date for testing +}); + +afterAll(() => { + vi.useRealTimers(); +}); + +describe('FriendlyDate Component', () => { + + it('displays "Today" for today\'s date', () => { + render(); + expect(screen.getByText("Today")).toBeInTheDocument(); + }); + + it('displays "Yesterday" for a date one day ago', () => { + render(); + expect(screen.getByText("Yesterday")).toBeInTheDocument(); + }); + + it('displays relative time within the last week', () => { + render(); + expect(screen.getByText("3 days ago")).toBeInTheDocument(); + }); + + it('displays exact date for dates older than a week', () => { + render(); + expect(screen.getByText("23 days ago")).toBeInTheDocument(); + }); + + it('displays friendly date format for future dates', () => { + render(); + expect(screen.getByText("in 29 days")).toBeInTheDocument(); + }); + + it('renders tooltip with full text on hover', async () => { + const {container} = render(); + expect(container.querySelector('span').getAttribute('data-tooltip')).toBe("Feb 22, 2024"); + }); + + it('renders an empty span for null dates', () => { + const {getByTestId} = render(); + expect(getByTestId("friendly-date")).toBeInTheDocument(); + + }); + + it('renders an empty span for undefined dates', () => { + const {getByTestId} = render(); + expect(getByTestId("friendly-date")).toBeInTheDocument(); + + }); + + it('renders an empty span for invalid', () => { + const {getByTestId} = render(); + expect(getByTestId("friendly-date")).toBeInTheDocument(); + + }); + + it('renders an empty span for empty', () => { + const {getByTestId} = render(); + expect(getByTestId("friendly-date")).toBeInTheDocument(); + + }); + + +}); diff --git a/frontend/src/components/FriendlyDate/index.tsx b/frontend/src/components/FriendlyDate/index.tsx new file mode 100644 index 00000000..e49acbd2 --- /dev/null +++ b/frontend/src/components/FriendlyDate/index.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { formatDistanceToNow, format, parseISO, isToday, isYesterday } from 'date-fns'; +import { Tooltip } from '@carbon/react'; + +interface FriendlyDateProps { + date: string | null | undefined; // The date string in ISO format +} + +const FriendlyDate: React.FC = ({ date }) => { + + if(!date) return ; + + try{ + const parsedDate = parseISO(date); + const cleanDate = format(parsedDate, "MMM dd, yyyy"); + + const formattedDate = isToday(parsedDate) + ? "Today" + : isYesterday(parsedDate) + ? "Yesterday" + : formatDistanceToNow(parsedDate, { addSuffix: true }); + + return + {formattedDate} + ; + } catch(e){ + return ; + } +}; + +export default FriendlyDate; \ No newline at end of file diff --git a/frontend/src/components/SilvicultureSearch/Openings/SearchScreenDataTable/index.tsx b/frontend/src/components/SilvicultureSearch/Openings/SearchScreenDataTable/index.tsx index 17b32c8a..b3fc8766 100644 --- a/frontend/src/components/SilvicultureSearch/Openings/SearchScreenDataTable/index.tsx +++ b/frontend/src/components/SilvicultureSearch/Openings/SearchScreenDataTable/index.tsx @@ -42,6 +42,7 @@ import { import { useNavigate } from "react-router-dom"; import { setOpeningFavorite } from '../../../../services/OpeningFavouriteService'; import { useNotification } from "../../../../contexts/NotificationProvider"; +import FriendlyDate from "../../../FriendlyDate"; interface ISearchScreenDataTable { rows: OpeningsSearch[]; @@ -348,6 +349,8 @@ const SearchScreenDataTable: React.FC = ({ row["categoryCode"] + " - " + row["categoryDescription"] + ) : header.key === 'disturbanceStartDate' ? ( + ) : ( row[header.key] )} @@ -375,7 +378,7 @@ const SearchScreenDataTable: React.FC = ({ backwardText="Previous page" forwardText="Next page" pageSize={itemsPerPage} - pageSizes={[5, 20, 50, 200, 400]} + pageSizes={[20, 40, 60, 80, 100]} itemsPerPageText="Items per page" page={currentPage} onChange={({ diff --git a/frontend/src/components/SilvicultureSearch/Openings/SearchScreenDataTable/testData.ts b/frontend/src/components/SilvicultureSearch/Openings/SearchScreenDataTable/testData.ts index f8c6d7ba..dc6fd942 100644 --- a/frontend/src/components/SilvicultureSearch/Openings/SearchScreenDataTable/testData.ts +++ b/frontend/src/components/SilvicultureSearch/Openings/SearchScreenDataTable/testData.ts @@ -49,7 +49,7 @@ export const columns: ITableHeader[] = [ { key: 'disturbanceStartDate', header: 'Disturbance Date', - selected: false + selected: true } ]; diff --git a/frontend/src/contexts/PaginationProvider.tsx b/frontend/src/contexts/PaginationProvider.tsx index 4a89251a..5ae52963 100644 --- a/frontend/src/contexts/PaginationProvider.tsx +++ b/frontend/src/contexts/PaginationProvider.tsx @@ -3,9 +3,9 @@ import PaginationContext, { PaginationContextData } from "./PaginationContext"; const PaginationProvider: React.FC<{children: React.ReactNode}> = ({ children }) => { const [data, setData] = useState([]); - const [initialItemsPerPage, setInitialItemsPerPage] = useState(0); + const [initialItemsPerPage, setInitialItemsPerPage] = useState(20); const [currentPage, setCurrentPage] = useState(1); - const [itemsPerPage, setItemsPerPage] = useState(5); + const [itemsPerPage, setItemsPerPage] = useState(20); const [totalResultItems, setTotalResultItems] = useState(0); // State for totalResultItems // Update the total number of pages when itemsPerPage changes