From 82710ca9979917fb3d30e92a7572584a64a037e3 Mon Sep 17 00:00:00 2001 From: Huy Tran Date: Mon, 20 Jan 2025 21:25:12 -0500 Subject: [PATCH 01/19] feat: Implement individual catalog card --- src/components/core/CatalogCard.module.css | 60 ++++++++++++ src/components/core/CatalogCard.tsx | 105 +++++++++++++++++++++ src/stories/CatalogCard.stories.tsx | 38 ++++++++ 3 files changed, 203 insertions(+) create mode 100644 src/components/core/CatalogCard.module.css create mode 100644 src/components/core/CatalogCard.tsx create mode 100644 src/stories/CatalogCard.stories.tsx diff --git a/src/components/core/CatalogCard.module.css b/src/components/core/CatalogCard.module.css new file mode 100644 index 0000000..583841c --- /dev/null +++ b/src/components/core/CatalogCard.module.css @@ -0,0 +1,60 @@ +.cardContainer * { + padding: 0; + margin: 0; +} + +.cardContainer { + display: flex; + flex-direction: column; + border-radius: 8px; + padding: 12px; + border: 1px solid #00000027; + gap: 32px; +} + +.infoContainer { + display: flex; + flex-direction: column; + gap: 8px; +} + +.title { + font-size: 20px; +} + +.description { + font-size: 14px; + font-weight: 400; +} + +.date { + font-size: var(--font-size-small); + font-weight: 400; + color: #0000009b; +} + +.footerContainer { + display: flex; + justify-content: space-between; + align-items: center; +} + +.tag { + /* display: inline-block; */ + font-size: var(--font-size-base); + padding: 2px 6px; + border-radius: 3px; + color: white; +} + +.browseButton { + color: #202020; + font-size: var(--font-size-base); +} + +.readMore { + border: none; + text-decoration: underline; + cursor: pointer; + background: none; +} \ No newline at end of file diff --git a/src/components/core/CatalogCard.tsx b/src/components/core/CatalogCard.tsx new file mode 100644 index 0000000..90b601b --- /dev/null +++ b/src/components/core/CatalogCard.tsx @@ -0,0 +1,105 @@ +import { useMemo, useState } from "react"; +import { Button, Link } from "react-aria-components"; + +import { DateValue } from "react-aria"; +import styles from "./CatalogCard.module.css"; + +type IndicatorTag = "API" | "Catalog"; + +const MAX_LENGTH = 250; + +export interface CatalogCardProps { + title: string; + description: string; + temporalExtent: [DateValue, DateValue?]; + indicatorTag?: IndicatorTag; +} + +const Tag = ({ indicatorTag }: { indicatorTag: IndicatorTag }) => ( +
+ {indicatorTag} +
+); + +export const CatalogCard = ({ + title, + description: initialDescription, + temporalExtent, + indicatorTag, +}: CatalogCardProps) => { + const [shouldTruncateDescription, setShouldTruncateDescription] = + useState(true); + + const shouldShowReadMore = useMemo( + () => initialDescription.length > MAX_LENGTH, + [initialDescription.length], + ); + + const description = useMemo( + () => + shouldTruncateDescription + ? `${initialDescription.slice(0, MAX_LENGTH)}...` + : initialDescription, + [initialDescription, shouldTruncateDescription], + ); + + const dateRange = useMemo(() => { + const startDate = temporalExtent[0].toString(); + + let endDate: string = ""; + + // Check if end date exists and compare with start date + if ( + temporalExtent[1] && + temporalExtent[1].compare(temporalExtent[0]) !== 0 + ) { + endDate = temporalExtent[1].toString(); + } + + return `${startDate}${endDate ? ` - ${endDate}` : ""}`; + }, [temporalExtent]); + + return ( +
+
+

{title}

+

+ {description}{" "} + {shouldShowReadMore && ( + + )} +

+

{dateRange}

+
+
+
{indicatorTag && }
+
+ + Browse + +
+
+
+ ); +}; diff --git a/src/stories/CatalogCard.stories.tsx b/src/stories/CatalogCard.stories.tsx new file mode 100644 index 0000000..f49fdce --- /dev/null +++ b/src/stories/CatalogCard.stories.tsx @@ -0,0 +1,38 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { CalendarDateTime } from "@internationalized/date"; +import { CatalogCard } from "../components/core/CatalogCard"; + +const meta = { + title: "Core/CatalogCard", + component: CatalogCard, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +const shortDescription = "Lorem ipsum dolor sit amet"; +const longDescription = + "The Kentucky From Above ([KyFromAbove](https://kyfromabove.ky.gov)) program has acquired aerial imagery and elevation (LiDAR) data for the Commonwealth of Kentucky since 2011. The catalog will be subdivided into separate catalogs for orthorectified imagery, oblique imagery, LiDAR-derived digital elevation models (DEM), and LiDAR point cloud data. The data acquired through KyFromAbove program is free to download and consume. All imagery within the catalog uses the Cloud-Optimized Geotiff (COG) format. With the exception of the Phase1 point cloud LAZ files, all LAZ files use the Cloud-Optimized Point Cloud (COPC) format.\n\nSee also:\n\n- [STAC Browser version](https://radiantearth.github.io/stac-browser/#/external/kyfromabove-stac.s3.us-west-1.amazonaws.com/catalog.json)"; + +export const Default: Story = { + args: { + title: "This is a title", + description: longDescription, + temporalExtent: [ + new CalendarDateTime(2024, 1, 1), + new CalendarDateTime(2025, 1, 1), + ], + indicatorTag: "API", + }, +}; + +export const MissingDate: Story = { + args: { + title: "This is a title", + description: shortDescription, + temporalExtent: [new CalendarDateTime(2024, 1, 1)], + indicatorTag: "Catalog", + }, +}; From 66774c37d1756d63ffa48a61607db8d8d2c02c61 Mon Sep 17 00:00:00 2001 From: Huy Tran Date: Tue, 21 Jan 2025 00:09:27 -0500 Subject: [PATCH 02/19] Add render prop --- src/components/core/CatalogCard.module.css | 10 ++++ src/components/core/CatalogCard.tsx | 58 +++++++++++----------- src/stories/CatalogCard.stories.tsx | 10 ++++ 3 files changed, 49 insertions(+), 29 deletions(-) diff --git a/src/components/core/CatalogCard.module.css b/src/components/core/CatalogCard.module.css index 583841c..de3ac55 100644 --- a/src/components/core/CatalogCard.module.css +++ b/src/components/core/CatalogCard.module.css @@ -47,6 +47,16 @@ color: white; } +.tagAPI { + background-color: #FFC5003B; + color: #A16B00; +} + +.tagCatalog { + background-color: #00000010; + color: #0000009B; +} + .browseButton { color: #202020; font-size: var(--font-size-base); diff --git a/src/components/core/CatalogCard.tsx b/src/components/core/CatalogCard.tsx index 90b601b..16aaf70 100644 --- a/src/components/core/CatalogCard.tsx +++ b/src/components/core/CatalogCard.tsx @@ -1,4 +1,4 @@ -import { useMemo, useState } from "react"; +import { useMemo, useState, JSX } from "react"; import { Button, Link } from "react-aria-components"; import { DateValue } from "react-aria"; @@ -13,15 +13,14 @@ export interface CatalogCardProps { description: string; temporalExtent: [DateValue, DateValue?]; indicatorTag?: IndicatorTag; + renderDescription?: (description: string) => JSX.Element; } const Tag = ({ indicatorTag }: { indicatorTag: IndicatorTag }) => (
{indicatorTag}
@@ -32,21 +31,19 @@ export const CatalogCard = ({ description: initialDescription, temporalExtent, indicatorTag, + renderDescription, }: CatalogCardProps) => { const [shouldTruncateDescription, setShouldTruncateDescription] = useState(true); - const shouldShowReadMore = useMemo( - () => initialDescription.length > MAX_LENGTH, - [initialDescription.length], - ); + const isLongText = initialDescription.length > MAX_LENGTH; const description = useMemo( () => shouldTruncateDescription - ? `${initialDescription.slice(0, MAX_LENGTH)}...` + ? `${initialDescription.slice(0, MAX_LENGTH)}${isLongText ? "..." : ""}` : initialDescription, - [initialDescription, shouldTruncateDescription], + [initialDescription, isLongText, shouldTruncateDescription], ); const dateRange = useMemo(() => { @@ -65,27 +62,30 @@ export const CatalogCard = ({ return `${startDate}${endDate ? ` - ${endDate}` : ""}`; }, [temporalExtent]); + const renderDefaultDescription = () => ( +

+ {description}{" "} + {isLongText && ( + + )} +

+ ); + return (

{title}

-

- {description}{" "} - {shouldShowReadMore && ( - - )} -

+ {renderDescription + ? renderDescription(initialDescription) + : renderDefaultDescription()}

{dateRange}

diff --git a/src/stories/CatalogCard.stories.tsx b/src/stories/CatalogCard.stories.tsx index f49fdce..c88a08b 100644 --- a/src/stories/CatalogCard.stories.tsx +++ b/src/stories/CatalogCard.stories.tsx @@ -36,3 +36,13 @@ export const MissingDate: Story = { indicatorTag: "Catalog", }, }; + +export const CustomDescription: Story = { + args: { + title: "This is a title", + description: longDescription, + temporalExtent: [new CalendarDateTime(2024, 1, 1)], + indicatorTag: "Catalog", + renderDescription: (description) => (

{description}

) + }, +} From 4a683afc67224aae53557edfae36d41d138d6aba Mon Sep 17 00:00:00 2001 From: Huy Tran Date: Tue, 21 Jan 2025 10:04:47 -0500 Subject: [PATCH 03/19] feat: Implement Catalog list container --- src/components/composite/Catalog.module.css | 37 ++++++++++++++ src/components/composite/Catalog.stories.tsx | 52 ++++++++++++++++++++ src/components/composite/Catalog.tsx | 20 ++++++++ src/components/core/CatalogCard.module.css | 3 +- src/components/core/CatalogCard.tsx | 15 ++++-- src/stories/CatalogCard.stories.tsx | 8 +-- 6 files changed, 125 insertions(+), 10 deletions(-) create mode 100644 src/components/composite/Catalog.module.css create mode 100644 src/components/composite/Catalog.stories.tsx create mode 100644 src/components/composite/Catalog.tsx diff --git a/src/components/composite/Catalog.module.css b/src/components/composite/Catalog.module.css new file mode 100644 index 0000000..24b17d6 --- /dev/null +++ b/src/components/composite/Catalog.module.css @@ -0,0 +1,37 @@ +.catalogContainer, .catalogList { + display: flex; + flex-direction: column; +} + +.catalogList { + gap: 24px; +} + +.catalogContainer { + height: 100%; + overflow-y: auto; + gap: 16px; +} + +.catalogHeader { + display: flex; + align-items: center; + gap: 8px; +} + +.catalogHeader h2 { + font-size: 28; + font-weight: 700; +} + +.catalogHeader span { + width: 16px; + height: 16px; + background: #000; + border-radius: 100%; + display: inline-flex; + justify-content: center; + align-items: center; + color: #fff; + font-size: 8px; +} \ No newline at end of file diff --git a/src/components/composite/Catalog.stories.tsx b/src/components/composite/Catalog.stories.tsx new file mode 100644 index 0000000..fba5ca5 --- /dev/null +++ b/src/components/composite/Catalog.stories.tsx @@ -0,0 +1,52 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { CalendarDateTime } from "@internationalized/date"; +import { Catalog } from "./Catalog"; +import { BaseCatalog } from "../core/CatalogCard"; + +const meta = { + title: "Composite/Catalog", + component: Catalog, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +const longDescription = + "The Kentucky From Above ([KyFromAbove](https://kyfromabove.ky.gov)) program has acquired aerial imagery and elevation (LiDAR) data for the Commonwealth of Kentucky since 2011. The catalog will be subdivided into separate catalogs for orthorectified imagery, oblique imagery, LiDAR-derived digital elevation models (DEM), and LiDAR point cloud data. The data acquired through KyFromAbove program is free to download and consume. All imagery within the catalog uses the Cloud-Optimized Geotiff (COG) format. With the exception of the Phase1 point cloud LAZ files, all LAZ files use the Cloud-Optimized Point Cloud (COPC) format.\n\nSee also:\n\n- [STAC Browser version](https://radiantearth.github.io/stac-browser/#/external/kyfromabove-stac.s3.us-west-1.amazonaws.com/catalog.json)"; + +const catalogs: BaseCatalog[] = [ + { + title: "Catalog 1", + description: longDescription, + temporalExtent: [ + new CalendarDateTime(2024, 1, 1, 12, 22, 11), + ], + indicatorTag: "API", + }, + { + title: "Catalog 2", + description: "Catalog 2 Description", + temporalExtent: [ + new CalendarDateTime(2024, 1, 1), + new CalendarDateTime(2024, 1, 1), + ], + indicatorTag: "API", + }, + { + title: "Catalog 3", + description: "Catalog 3 Description", + temporalExtent: [ + new CalendarDateTime(2024, 1, 1), + new CalendarDateTime(2025, 1, 1), + ], + indicatorTag: "API", + }, +]; + +export const Default: Story = { + args: { + catalogs, + }, +}; diff --git a/src/components/composite/Catalog.tsx b/src/components/composite/Catalog.tsx new file mode 100644 index 0000000..689ff44 --- /dev/null +++ b/src/components/composite/Catalog.tsx @@ -0,0 +1,20 @@ +import styles from "./Catalog.module.css"; +import { type BaseCatalog, CatalogCard } from "../core/CatalogCard"; + +export interface CatalogProps { + catalogs: BaseCatalog[]; +} + +export const Catalog = ({ catalogs, ...props }: CatalogProps) => ( +
+
+

Catalogs

+ {catalogs.length} +
+
+ {catalogs.map((catalog) => ( + + ))} +
+
+); diff --git a/src/components/core/CatalogCard.module.css b/src/components/core/CatalogCard.module.css index de3ac55..6864d7a 100644 --- a/src/components/core/CatalogCard.module.css +++ b/src/components/core/CatalogCard.module.css @@ -23,7 +23,7 @@ } .description { - font-size: 14px; + font-size: var(--font-size-base); font-weight: 400; } @@ -40,7 +40,6 @@ } .tag { - /* display: inline-block; */ font-size: var(--font-size-base); padding: 2px 6px; border-radius: 3px; diff --git a/src/components/core/CatalogCard.tsx b/src/components/core/CatalogCard.tsx index 16aaf70..7f6f7d8 100644 --- a/src/components/core/CatalogCard.tsx +++ b/src/components/core/CatalogCard.tsx @@ -1,21 +1,26 @@ import { useMemo, useState, JSX } from "react"; import { Button, Link } from "react-aria-components"; -import { DateValue } from "react-aria"; +import type { DateValue } from "react-aria"; import styles from "./CatalogCard.module.css"; -type IndicatorTag = "API" | "Catalog"; +export type TemporalExtent = [DateValue, DateValue?]; -const MAX_LENGTH = 250; +export type IndicatorTag = "API" | "Catalog"; -export interface CatalogCardProps { +export interface BaseCatalog { title: string; description: string; - temporalExtent: [DateValue, DateValue?]; + temporalExtent: TemporalExtent; indicatorTag?: IndicatorTag; +} + +export interface CatalogCardProps extends BaseCatalog { renderDescription?: (description: string) => JSX.Element; } +const MAX_LENGTH = 250; + const Tag = ({ indicatorTag }: { indicatorTag: IndicatorTag }) => (
(

{description}

) + renderDescription: (description) => ( +

{description}

+ ), }, -} +}; From 7f2343c7a10a407219f51abf11aaea77cdaafed0 Mon Sep 17 00:00:00 2001 From: Huy Tran Date: Tue, 21 Jan 2025 10:08:09 -0500 Subject: [PATCH 04/19] feat: Add id to catalog object --- src/components/composite/Catalog.stories.tsx | 3 +++ src/components/composite/Catalog.tsx | 2 +- src/components/core/CatalogCard.tsx | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/composite/Catalog.stories.tsx b/src/components/composite/Catalog.stories.tsx index fba5ca5..89b904d 100644 --- a/src/components/composite/Catalog.stories.tsx +++ b/src/components/composite/Catalog.stories.tsx @@ -18,6 +18,7 @@ const longDescription = const catalogs: BaseCatalog[] = [ { + id: "1", title: "Catalog 1", description: longDescription, temporalExtent: [ @@ -26,6 +27,7 @@ const catalogs: BaseCatalog[] = [ indicatorTag: "API", }, { + id: "2", title: "Catalog 2", description: "Catalog 2 Description", temporalExtent: [ @@ -35,6 +37,7 @@ const catalogs: BaseCatalog[] = [ indicatorTag: "API", }, { + id: "3", title: "Catalog 3", description: "Catalog 3 Description", temporalExtent: [ diff --git a/src/components/composite/Catalog.tsx b/src/components/composite/Catalog.tsx index 689ff44..1fb9f36 100644 --- a/src/components/composite/Catalog.tsx +++ b/src/components/composite/Catalog.tsx @@ -13,7 +13,7 @@ export const Catalog = ({ catalogs, ...props }: CatalogProps) => (
{catalogs.map((catalog) => ( - + ))}
diff --git a/src/components/core/CatalogCard.tsx b/src/components/core/CatalogCard.tsx index 7f6f7d8..b5de55d 100644 --- a/src/components/core/CatalogCard.tsx +++ b/src/components/core/CatalogCard.tsx @@ -9,6 +9,8 @@ export type TemporalExtent = [DateValue, DateValue?]; export type IndicatorTag = "API" | "Catalog"; export interface BaseCatalog { + // eslint-disable-next-line react/no-unused-prop-types + id: string; title: string; description: string; temporalExtent: TemporalExtent; From 1e6cd1ca5ef0e428006b80a6be3ffe4b05780b90 Mon Sep 17 00:00:00 2001 From: Huy Tran Date: Tue, 21 Jan 2025 10:13:32 -0500 Subject: [PATCH 05/19] fix: Move story to correct directory --- src/{components/composite => stories}/Catalog.stories.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename src/{components/composite => stories}/Catalog.stories.tsx (94%) diff --git a/src/components/composite/Catalog.stories.tsx b/src/stories/Catalog.stories.tsx similarity index 94% rename from src/components/composite/Catalog.stories.tsx rename to src/stories/Catalog.stories.tsx index 89b904d..8d5f08a 100644 --- a/src/components/composite/Catalog.stories.tsx +++ b/src/stories/Catalog.stories.tsx @@ -1,8 +1,8 @@ import type { Meta, StoryObj } from "@storybook/react"; import { CalendarDateTime } from "@internationalized/date"; -import { Catalog } from "./Catalog"; -import { BaseCatalog } from "../core/CatalogCard"; +import { Catalog } from "../components/composite/Catalog"; +import { BaseCatalog } from "../components/core/CatalogCard"; const meta = { title: "Composite/Catalog", From 379d5ece63acda814ff84e3f2f45fbb6c275bbd2 Mon Sep 17 00:00:00 2001 From: Huy Tran Date: Tue, 21 Jan 2025 13:43:00 -0500 Subject: [PATCH 06/19] fix: Fix catalog number style --- src/components/composite/Catalog.module.css | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/components/composite/Catalog.module.css b/src/components/composite/Catalog.module.css index 24b17d6..bfaaee6 100644 --- a/src/components/composite/Catalog.module.css +++ b/src/components/composite/Catalog.module.css @@ -1,4 +1,5 @@ -.catalogContainer, .catalogList { +.catalogContainer, +.catalogList { display: flex; flex-direction: column; } @@ -25,13 +26,16 @@ } .catalogHeader span { - width: 16px; - height: 16px; + padding: 4px; background: #000; - border-radius: 100%; + border-radius: 50%; display: inline-flex; justify-content: center; align-items: center; color: #fff; font-size: 8px; -} \ No newline at end of file + white-space: nowrap; + aspect-ratio: 1/1; + flex-shrink: 0; + min-width: 16px; +} From 1ce92c50ebe440459ddda2d96b94499a5533f659 Mon Sep 17 00:00:00 2001 From: Huy Tran Date: Wed, 22 Jan 2025 10:03:34 -0500 Subject: [PATCH 07/19] feat: Add truncate text util function --- src/components/composite/Catalog.tsx | 1 + src/components/core/CatalogCard.tsx | 11 ++++++----- src/utils/exampleFunction.js | 19 ------------------- src/utils/index.js | 1 - src/utils/index.ts | 1 + src/utils/strings.ts | 4 ++++ 6 files changed, 12 insertions(+), 25 deletions(-) delete mode 100644 src/utils/exampleFunction.js delete mode 100644 src/utils/index.js create mode 100644 src/utils/index.ts create mode 100644 src/utils/strings.ts diff --git a/src/components/composite/Catalog.tsx b/src/components/composite/Catalog.tsx index 1fb9f36..a7ecd6d 100644 --- a/src/components/composite/Catalog.tsx +++ b/src/components/composite/Catalog.tsx @@ -3,6 +3,7 @@ import { type BaseCatalog, CatalogCard } from "../core/CatalogCard"; export interface CatalogProps { catalogs: BaseCatalog[]; + maxDescriptionLength?: number; } export const Catalog = ({ catalogs, ...props }: CatalogProps) => ( diff --git a/src/components/core/CatalogCard.tsx b/src/components/core/CatalogCard.tsx index b5de55d..2fe2e3d 100644 --- a/src/components/core/CatalogCard.tsx +++ b/src/components/core/CatalogCard.tsx @@ -3,6 +3,7 @@ import { Button, Link } from "react-aria-components"; import type { DateValue } from "react-aria"; import styles from "./CatalogCard.module.css"; +import { truncateText } from "../../utils"; export type TemporalExtent = [DateValue, DateValue?]; @@ -18,6 +19,7 @@ export interface BaseCatalog { } export interface CatalogCardProps extends BaseCatalog { + maxDescriptionLength?: number; renderDescription?: (description: string) => JSX.Element; } @@ -38,19 +40,18 @@ export const CatalogCard = ({ description: initialDescription, temporalExtent, indicatorTag, + maxDescriptionLength = MAX_LENGTH, renderDescription, }: CatalogCardProps) => { const [shouldTruncateDescription, setShouldTruncateDescription] = useState(true); - const isLongText = initialDescription.length > MAX_LENGTH; - const description = useMemo( () => shouldTruncateDescription - ? `${initialDescription.slice(0, MAX_LENGTH)}${isLongText ? "..." : ""}` + ? truncateText(initialDescription, maxDescriptionLength) : initialDescription, - [initialDescription, isLongText, shouldTruncateDescription], + [initialDescription, maxDescriptionLength, shouldTruncateDescription], ); const dateRange = useMemo(() => { @@ -72,7 +73,7 @@ export const CatalogCard = ({ const renderDefaultDescription = () => (

{description}{" "} - {isLongText && ( + {initialDescription.length > maxDescriptionLength && ( From a0014b9638626b938513cf46bcfc64959b6bb91d Mon Sep 17 00:00:00 2001 From: Huy Tran Date: Wed, 22 Jan 2025 10:28:15 -0500 Subject: [PATCH 09/19] fix: Use default Date object --- src/components/composite/Catalog.module.css | 2 +- src/components/core/CatalogCard.module.css | 2 +- src/components/core/CatalogCard.tsx | 20 +++++++++----------- src/stories/Catalog.stories.tsx | 11 +++++------ src/stories/CatalogCard.stories.tsx | 12 +++++++----- 5 files changed, 23 insertions(+), 24 deletions(-) diff --git a/src/components/composite/Catalog.module.css b/src/components/composite/Catalog.module.css index bfaaee6..1ecee78 100644 --- a/src/components/composite/Catalog.module.css +++ b/src/components/composite/Catalog.module.css @@ -33,7 +33,7 @@ justify-content: center; align-items: center; color: #fff; - font-size: 8px; + font-size: 10px; white-space: nowrap; aspect-ratio: 1/1; flex-shrink: 0; diff --git a/src/components/core/CatalogCard.module.css b/src/components/core/CatalogCard.module.css index 6864d7a..5f4d13e 100644 --- a/src/components/core/CatalogCard.module.css +++ b/src/components/core/CatalogCard.module.css @@ -61,7 +61,7 @@ font-size: var(--font-size-base); } -.readMore { +.button { border: none; text-decoration: underline; cursor: pointer; diff --git a/src/components/core/CatalogCard.tsx b/src/components/core/CatalogCard.tsx index 109964e..d7d4b7f 100644 --- a/src/components/core/CatalogCard.tsx +++ b/src/components/core/CatalogCard.tsx @@ -1,11 +1,11 @@ import { useMemo, useState, JSX } from "react"; -import { Button, Link } from "react-aria-components"; +import { Button } from "react-aria-components"; -import type { DateValue } from "react-aria"; +import type { PressEvent } from "react-aria"; import styles from "./CatalogCard.module.css"; import { truncateText } from "../../utils"; -export type TemporalExtent = [DateValue, DateValue?]; +export type TemporalExtent = [Date, Date?]; export type IndicatorTag = "API" | "Catalog"; @@ -19,6 +19,7 @@ export interface BaseCatalog { } export interface CatalogCardProps extends BaseCatalog { + onBrowsePress?: (e: PressEvent) => void; maxDescriptionLength?: number; renderDescription?: (description: string) => JSX.Element; } @@ -41,6 +42,7 @@ export const CatalogCard = ({ temporalExtent, indicatorTag, maxDescriptionLength = MAX_LENGTH, + onBrowsePress, renderDescription, }: CatalogCardProps) => { const [shouldTruncateDescription, setShouldTruncateDescription] = @@ -62,7 +64,7 @@ export const CatalogCard = ({ // Check if end date exists and compare with start date if ( temporalExtent[1] && - temporalExtent[1].compare(temporalExtent[0]) !== 0 + temporalExtent[1].getTime() > temporalExtent[0].getTime() ) { endDate = temporalExtent[1].toString(); } @@ -75,7 +77,7 @@ export const CatalogCard = ({ {description}{" "} {initialDescription.length > maxDescriptionLength && (

diff --git a/src/stories/Catalog.stories.tsx b/src/stories/Catalog.stories.tsx index 8d5f08a..d09bd3f 100644 --- a/src/stories/Catalog.stories.tsx +++ b/src/stories/Catalog.stories.tsx @@ -1,6 +1,5 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { CalendarDateTime } from "@internationalized/date"; import { Catalog } from "../components/composite/Catalog"; import { BaseCatalog } from "../components/core/CatalogCard"; @@ -22,7 +21,7 @@ const catalogs: BaseCatalog[] = [ title: "Catalog 1", description: longDescription, temporalExtent: [ - new CalendarDateTime(2024, 1, 1, 12, 22, 11), + new Date(2024, 1, 1, 12, 22, 11), ], indicatorTag: "API", }, @@ -31,8 +30,8 @@ const catalogs: BaseCatalog[] = [ title: "Catalog 2", description: "Catalog 2 Description", temporalExtent: [ - new CalendarDateTime(2024, 1, 1), - new CalendarDateTime(2024, 1, 1), + new Date(2024, 1, 1), + new Date(2024, 1, 1), ], indicatorTag: "API", }, @@ -41,8 +40,8 @@ const catalogs: BaseCatalog[] = [ title: "Catalog 3", description: "Catalog 3 Description", temporalExtent: [ - new CalendarDateTime(2024, 1, 1), - new CalendarDateTime(2025, 1, 1), + new Date(2024, 1, 1), + new Date(2025, 1, 1), ], indicatorTag: "API", }, diff --git a/src/stories/CatalogCard.stories.tsx b/src/stories/CatalogCard.stories.tsx index 862ef9f..1bcbd76 100644 --- a/src/stories/CatalogCard.stories.tsx +++ b/src/stories/CatalogCard.stories.tsx @@ -1,6 +1,5 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { CalendarDateTime } from "@internationalized/date"; import { CatalogCard } from "../components/core/CatalogCard"; const meta = { @@ -18,11 +17,12 @@ const longDescription = export const Default: Story = { args: { + id: "1", title: "This is a title", description: longDescription, temporalExtent: [ - new CalendarDateTime(2024, 1, 1), - new CalendarDateTime(2025, 1, 1), + new Date(2024, 1, 1), + new Date(2025, 1, 1), ], indicatorTag: "API", }, @@ -30,18 +30,20 @@ export const Default: Story = { export const MissingDate: Story = { args: { + id: "1", title: "This is a title", description: shortDescription, - temporalExtent: [new CalendarDateTime(2024, 1, 1)], + temporalExtent: [new Date(2024, 1, 1)], indicatorTag: "Catalog", }, }; export const CustomDescriptionRender: Story = { args: { + id: "1", title: "This is a title", description: longDescription, - temporalExtent: [new CalendarDateTime(2024, 1, 1)], + temporalExtent: [new Date(2024, 1, 1)], indicatorTag: "Catalog", renderDescription: (description) => (

{description}

From 841eef494cf9238d38238063316ca11bac96ce5b Mon Sep 17 00:00:00 2001 From: Huy Tran Date: Wed, 22 Jan 2025 10:34:48 -0500 Subject: [PATCH 10/19] fix: Convert date to utc string --- src/components/core/CatalogCard.tsx | 6 +++--- src/stories/Catalog.stories.tsx | 2 +- src/utils/strings.ts | 9 +++++++++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/components/core/CatalogCard.tsx b/src/components/core/CatalogCard.tsx index d7d4b7f..b66b98b 100644 --- a/src/components/core/CatalogCard.tsx +++ b/src/components/core/CatalogCard.tsx @@ -3,7 +3,7 @@ import { Button } from "react-aria-components"; import type { PressEvent } from "react-aria"; import styles from "./CatalogCard.module.css"; -import { truncateText } from "../../utils"; +import { convertDateToUTCString, truncateText } from "../../utils"; export type TemporalExtent = [Date, Date?]; @@ -57,7 +57,7 @@ export const CatalogCard = ({ ); const dateRange = useMemo(() => { - const startDate = temporalExtent[0].toString(); + const startDate = convertDateToUTCString(temporalExtent[0]); let endDate: string = ""; @@ -66,7 +66,7 @@ export const CatalogCard = ({ temporalExtent[1] && temporalExtent[1].getTime() > temporalExtent[0].getTime() ) { - endDate = temporalExtent[1].toString(); + endDate = convertDateToUTCString(temporalExtent[1]); } return `${startDate}${endDate ? ` - ${endDate}` : ""}`; diff --git a/src/stories/Catalog.stories.tsx b/src/stories/Catalog.stories.tsx index d09bd3f..5eaa10f 100644 --- a/src/stories/Catalog.stories.tsx +++ b/src/stories/Catalog.stories.tsx @@ -41,7 +41,7 @@ const catalogs: BaseCatalog[] = [ description: "Catalog 3 Description", temporalExtent: [ new Date(2024, 1, 1), - new Date(2025, 1, 1), + new Date(), ], indicatorTag: "API", }, diff --git a/src/utils/strings.ts b/src/utils/strings.ts index 4638dff..0a36df1 100644 --- a/src/utils/strings.ts +++ b/src/utils/strings.ts @@ -2,3 +2,12 @@ export const truncateText = (text: string, maxLength: number) => { if (text.length <= maxLength) return text; return `${text.slice(0, maxLength)}...`; }; + +export const convertDateToUTCString = (date: Date) => { + const formattedDate = + `${date.getUTCMonth() + 1}/${date.getUTCDate()}/${date.getUTCFullYear()}, ` + + `${date.getUTCHours() % 12 || 12}:${date.getUTCMinutes().toString().padStart(2, "0")}:${date.getUTCSeconds().toString().padStart(2, "0")} ` + + `${date.getUTCHours() < 12 ? "AM" : "PM"} UTC`; + + return formattedDate; +}; From 53df28e6adf27f38097701423a936c308557a241 Mon Sep 17 00:00:00 2001 From: Huy Tran Date: Wed, 22 Jan 2025 11:23:59 -0500 Subject: [PATCH 11/19] Add empty screen --- src/components/composite/Catalog.tsx | 29 ++++++++++++++++++++-------- src/stories/Catalog.stories.tsx | 6 ++++++ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/components/composite/Catalog.tsx b/src/components/composite/Catalog.tsx index a7ecd6d..6979622 100644 --- a/src/components/composite/Catalog.tsx +++ b/src/components/composite/Catalog.tsx @@ -2,20 +2,33 @@ import styles from "./Catalog.module.css"; import { type BaseCatalog, CatalogCard } from "../core/CatalogCard"; export interface CatalogProps { - catalogs: BaseCatalog[]; + catalogs: BaseCatalog[] | null | undefined; + isLoading?: boolean; maxDescriptionLength?: number; } -export const Catalog = ({ catalogs, ...props }: CatalogProps) => ( +const Loading = () =>
Loading...
; + +const Empty = () =>
No catalogs available.
; + +export const Catalog = ({ catalogs, isLoading, ...props }: CatalogProps) => (

Catalogs

- {catalogs.length} -
-
- {catalogs.map((catalog) => ( - - ))} + {Array.isArray(catalogs) ? catalogs.length : 0}
+ {isLoading ? ( + + ) : ( +
+ {Array.isArray(catalogs) ? ( + catalogs.map((catalog) => ( + + )) + ) : ( + + )} +
+ )}
); diff --git a/src/stories/Catalog.stories.tsx b/src/stories/Catalog.stories.tsx index 5eaa10f..a46b88c 100644 --- a/src/stories/Catalog.stories.tsx +++ b/src/stories/Catalog.stories.tsx @@ -52,3 +52,9 @@ export const Default: Story = { catalogs, }, }; + +export const EmptyList: Story = { + args: { + catalogs: null, + }, +}; From 071ca2513470755d69bdc9890870002b6c40c042 Mon Sep 17 00:00:00 2001 From: Huy Tran Date: Wed, 22 Jan 2025 11:34:42 -0500 Subject: [PATCH 12/19] chore: Rename to CatalogList --- ...alog.module.css => CatalogList.module.css} | 0 .../{Catalog.tsx => CatalogList.tsx} | 19 +++++++++++++++---- ...og.stories.tsx => CatalogList.stories.tsx} | 8 ++++---- 3 files changed, 19 insertions(+), 8 deletions(-) rename src/components/composite/{Catalog.module.css => CatalogList.module.css} (100%) rename src/components/composite/{Catalog.tsx => CatalogList.tsx} (62%) rename src/stories/{Catalog.stories.tsx => CatalogList.stories.tsx} (91%) diff --git a/src/components/composite/Catalog.module.css b/src/components/composite/CatalogList.module.css similarity index 100% rename from src/components/composite/Catalog.module.css rename to src/components/composite/CatalogList.module.css diff --git a/src/components/composite/Catalog.tsx b/src/components/composite/CatalogList.tsx similarity index 62% rename from src/components/composite/Catalog.tsx rename to src/components/composite/CatalogList.tsx index 6979622..ffdc08d 100644 --- a/src/components/composite/Catalog.tsx +++ b/src/components/composite/CatalogList.tsx @@ -1,8 +1,9 @@ -import styles from "./Catalog.module.css"; +import styles from "./CatalogList.module.css"; import { type BaseCatalog, CatalogCard } from "../core/CatalogCard"; export interface CatalogProps { catalogs: BaseCatalog[] | null | undefined; + className?: string; isLoading?: boolean; maxDescriptionLength?: number; } @@ -11,8 +12,14 @@ const Loading = () =>
Loading...
; const Empty = () =>
No catalogs available.
; -export const Catalog = ({ catalogs, isLoading, ...props }: CatalogProps) => ( -
+export const CatalogList = ({ + catalogs, + isLoading, + className, + maxDescriptionLength, + ...props +}: CatalogProps) => ( +

Catalogs

{Array.isArray(catalogs) ? catalogs.length : 0} @@ -23,7 +30,11 @@ export const Catalog = ({ catalogs, isLoading, ...props }: CatalogProps) => (
{Array.isArray(catalogs) ? ( catalogs.map((catalog) => ( - + )) ) : ( diff --git a/src/stories/Catalog.stories.tsx b/src/stories/CatalogList.stories.tsx similarity index 91% rename from src/stories/Catalog.stories.tsx rename to src/stories/CatalogList.stories.tsx index a46b88c..58abfe5 100644 --- a/src/stories/Catalog.stories.tsx +++ b/src/stories/CatalogList.stories.tsx @@ -1,12 +1,12 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { Catalog } from "../components/composite/Catalog"; +import { CatalogList } from "../components/composite/CatalogList"; import { BaseCatalog } from "../components/core/CatalogCard"; const meta = { - title: "Composite/Catalog", - component: Catalog, -} satisfies Meta; + title: "Composite/CatalogList", + component: CatalogList, +} satisfies Meta; export default meta; From 3f43f0f0c8d772cc8bd2b716c58e49aff64aed21 Mon Sep 17 00:00:00 2001 From: Huy Tran Date: Wed, 22 Jan 2025 12:08:52 -0500 Subject: [PATCH 13/19] Add test for catalog card --- src/components/core/CatalogCard.test.tsx | 86 ++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/components/core/CatalogCard.test.tsx diff --git a/src/components/core/CatalogCard.test.tsx b/src/components/core/CatalogCard.test.tsx new file mode 100644 index 0000000..9e89ebc --- /dev/null +++ b/src/components/core/CatalogCard.test.tsx @@ -0,0 +1,86 @@ +import { render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { CatalogCard, type BaseCatalog } from "./CatalogCard"; + +const shortDescription = "Lorem ipsum dolor sit amet"; +const longDescription = + "Lorem ipsum dolor sit amet consectetur adipisicing elit. Minus in quam quod amet eaque rem, sit ex consequatur delectus porro a aliquid neque aliquam illum odit fuga libero suscipit quisquam."; + +const shortCatalog: BaseCatalog = { + id: "1", + title: "Catalog 1", + description: shortDescription, + temporalExtent: [new Date(2024, 1, 1), new Date(2025, 1, 1)], + indicatorTag: "API", +}; + +const longCatalog: BaseCatalog = { + id: "@", + title: "Catalog 2", + description: longDescription, + temporalExtent: [new Date(2024, 1, 1), new Date(2025, 1, 1)], +}; + +describe("CatalogCard", () => { + it("renders all components correctly", async () => { + render(); + expect(screen.getByText("Catalog 1")).toBeInTheDocument(); + expect( + screen.getByText( + "2/1/2024, 5:00:00 AM UTC - 2/1/2025, 5:00:00 AM UTC", + ), + ).toBeInTheDocument(); + expect(screen.getByText(shortDescription)).toBeInTheDocument(); + expect(screen.queryByText("Read More")).not.toBeInTheDocument(); + expect(screen.queryByText("Browse")).toBeInTheDocument(); + expect(screen.queryByText("API")).toBeInTheDocument(); + }); + + it("displays full and truncated description", async () => { + const user = userEvent.setup(); + const maxLength = 10; + render( + , + ); + expect(screen.getByText("Catalog 2")).toBeInTheDocument(); + expect( + screen.getByText(`${longDescription.slice(0, maxLength)}...`), + ).toBeInTheDocument(); + const readMoreButton = screen.getByRole("button", { + name: "Read more", + }); + expect(readMoreButton).toHaveTextContent("Read More"); + await user.click(readMoreButton); + expect(readMoreButton).toHaveTextContent("Read Less"); + expect(screen.getByText(`${longDescription}`)).toBeInTheDocument(); + }); + + it("renders one date when only one date is provided", () => { + const date = new Date(2024, 1, 1); + render(); + expect( + screen.getByText("2/1/2024, 5:00:00 AM UTC"), + ).toBeInTheDocument(); + }); + + it("renders one date when two dates are the same", () => { + const date1 = new Date(2024, 1, 1); + const date2 = new Date(2024, 1, 1); + render( + , + ); + expect( + screen.getByText("2/1/2024, 5:00:00 AM UTC"), + ).toBeInTheDocument(); + }); + + it("renders custom description", () => { + render( +

Custom Description

} + />, + ); + expect(screen.getByText("Custom Description")).toBeInTheDocument(); + }); +}); From 1936678fab02b6b2ddaa544b4cd179176be0c8e2 Mon Sep 17 00:00:00 2001 From: Huy Tran Date: Wed, 22 Jan 2025 15:23:23 -0500 Subject: [PATCH 14/19] feat: Add test for CatalogList --- src/components/composite/CatalogList.test.tsx | 51 +++++++++++++++++++ src/components/composite/CatalogList.tsx | 4 +- 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 src/components/composite/CatalogList.test.tsx diff --git a/src/components/composite/CatalogList.test.tsx b/src/components/composite/CatalogList.test.tsx new file mode 100644 index 0000000..f5657a2 --- /dev/null +++ b/src/components/composite/CatalogList.test.tsx @@ -0,0 +1,51 @@ +import { render, screen } from "@testing-library/react"; +import { BaseCatalog } from "../core/CatalogCard"; +import { CatalogList } from "./CatalogList"; + +const shortDescription = "Lorem ipsum dolor sit amet"; +const longDescription = + "Lorem ipsum dolor sit amet consectetur adipisicing elit. Minus in quam quod amet eaque rem, sit ex consequatur delectus porro a aliquid neque aliquam illum odit fuga libero suscipit quisquam."; + +const shortCatalog: BaseCatalog = { + id: "1", + title: "Catalog 1", + description: shortDescription, + temporalExtent: [new Date(2024, 1, 1), new Date(2025, 1, 1)], + indicatorTag: "API", +}; + +const longCatalog: BaseCatalog = { + id: "2", + title: "Catalog 2", + description: longDescription, + temporalExtent: [new Date(2024, 1, 1), new Date(2025, 1, 1)], +}; + +const catalogs = [shortCatalog, longCatalog]; + +describe("CatalogList", () => { + it("renders catalog list", async () => { + render(); + expect(screen.getByText("Catalogs")).toBeInTheDocument(); + expect(screen.getByTestId("catalogSize")).toHaveTextContent("2"); + expect(screen.getByText("Catalog 1")).toBeInTheDocument(); + expect(screen.getByText("Catalog 2")).toBeInTheDocument(); + }); + + it("renders empty list", async () => { + render(); + expect(screen.getByText("Catalogs")).toBeInTheDocument(); + expect(screen.getByTestId("catalogSize")).toHaveTextContent("0"); + expect(screen.getByText("No catalogs available.")).toBeInTheDocument(); + + render(); + expect(screen.getByText("No catalogs available.")).toBeInTheDocument(); + }); + + it("renders loading state", async () => { + render(); + expect(screen.getByText("Catalogs")).toBeInTheDocument(); + expect(screen.getByTestId("catalogSize")).toHaveTextContent("0"); + expect(screen.getByText("Loading...")).toBeInTheDocument(); + }); +}); diff --git a/src/components/composite/CatalogList.tsx b/src/components/composite/CatalogList.tsx index ffdc08d..296ecc8 100644 --- a/src/components/composite/CatalogList.tsx +++ b/src/components/composite/CatalogList.tsx @@ -22,7 +22,9 @@ export const CatalogList = ({

Catalogs

- {Array.isArray(catalogs) ? catalogs.length : 0} + + {Array.isArray(catalogs) && !isLoading ? catalogs.length : 0} +
{isLoading ? ( From b8e0e2d863e969df18ac8b63b8fa413d5e5d0273 Mon Sep 17 00:00:00 2001 From: Huy Tran Date: Wed, 22 Jan 2025 15:35:39 -0500 Subject: [PATCH 15/19] fix: Create Date object with UTC --- src/components/core/CatalogCard.test.tsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/core/CatalogCard.test.tsx b/src/components/core/CatalogCard.test.tsx index 9e89ebc..b74b656 100644 --- a/src/components/core/CatalogCard.test.tsx +++ b/src/components/core/CatalogCard.test.tsx @@ -10,15 +10,15 @@ const shortCatalog: BaseCatalog = { id: "1", title: "Catalog 1", description: shortDescription, - temporalExtent: [new Date(2024, 1, 1), new Date(2025, 1, 1)], + temporalExtent: [new Date(Date.UTC(2024, 1, 1)), new Date(Date.UTC(2025, 1, 1))], indicatorTag: "API", }; const longCatalog: BaseCatalog = { - id: "@", + id: "2", title: "Catalog 2", description: longDescription, - temporalExtent: [new Date(2024, 1, 1), new Date(2025, 1, 1)], + temporalExtent: [new Date(Date.UTC(2024, 1, 1)), new Date(Date.UTC(2025, 1, 1))], }; describe("CatalogCard", () => { @@ -27,7 +27,7 @@ describe("CatalogCard", () => { expect(screen.getByText("Catalog 1")).toBeInTheDocument(); expect( screen.getByText( - "2/1/2024, 5:00:00 AM UTC - 2/1/2025, 5:00:00 AM UTC", + "2/1/2024, 12:00:00 AM UTC - 2/1/2025, 12:00:00 AM UTC", ), ).toBeInTheDocument(); expect(screen.getByText(shortDescription)).toBeInTheDocument(); @@ -56,21 +56,21 @@ describe("CatalogCard", () => { }); it("renders one date when only one date is provided", () => { - const date = new Date(2024, 1, 1); + const date = new Date(Date.UTC(2024, 1, 1, 9, 0, 0)); render(); expect( - screen.getByText("2/1/2024, 5:00:00 AM UTC"), + screen.getByText("2/1/2024, 9:00:00 AM UTC"), ).toBeInTheDocument(); }); it("renders one date when two dates are the same", () => { - const date1 = new Date(2024, 1, 1); - const date2 = new Date(2024, 1, 1); + const date1 = new Date(Date.UTC(2024, 1, 1, 0, 0, 0)); + const date2 = new Date(Date.UTC(2024, 1, 1, 0, 0, 0)); render( , ); expect( - screen.getByText("2/1/2024, 5:00:00 AM UTC"), + screen.getByText("2/1/2024, 12:00:00 AM UTC"), ).toBeInTheDocument(); }); From 63aa0fac8cbb816274f40a44d6a0b32527f1ea0c Mon Sep 17 00:00:00 2001 From: Huy Tran Date: Thu, 23 Jan 2025 19:46:29 -0500 Subject: [PATCH 16/19] fix: Use ID as title when title is not provided --- src/components/core/CatalogCard.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/components/core/CatalogCard.tsx b/src/components/core/CatalogCard.tsx index b66b98b..35b0d4b 100644 --- a/src/components/core/CatalogCard.tsx +++ b/src/components/core/CatalogCard.tsx @@ -10,11 +10,10 @@ export type TemporalExtent = [Date, Date?]; export type IndicatorTag = "API" | "Catalog"; export interface BaseCatalog { - // eslint-disable-next-line react/no-unused-prop-types id: string; - title: string; + title?: string; description: string; - temporalExtent: TemporalExtent; + temporalExtent?: TemporalExtent; indicatorTag?: IndicatorTag; } @@ -37,6 +36,7 @@ const Tag = ({ indicatorTag }: { indicatorTag: IndicatorTag }) => ( ); export const CatalogCard = ({ + id, title, description: initialDescription, temporalExtent, @@ -57,6 +57,8 @@ export const CatalogCard = ({ ); const dateRange = useMemo(() => { + if (!temporalExtent) return ""; + const startDate = convertDateToUTCString(temporalExtent[0]); let endDate: string = ""; @@ -93,7 +95,7 @@ export const CatalogCard = ({ return (
-

{title}

+

{title ?? `ID: ${id}`}

{renderDescription ? renderDescription(initialDescription) : renderDefaultDescription()} From 2df5b84245c8cf328988a114975926738fb090a6 Mon Sep 17 00:00:00 2001 From: Huy Tran Date: Thu, 23 Jan 2025 19:46:51 -0500 Subject: [PATCH 17/19] chore: Add test stories --- src/stories/CatalogCard.stories.tsx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/stories/CatalogCard.stories.tsx b/src/stories/CatalogCard.stories.tsx index 1bcbd76..1f44fbe 100644 --- a/src/stories/CatalogCard.stories.tsx +++ b/src/stories/CatalogCard.stories.tsx @@ -38,6 +38,24 @@ export const MissingDate: Story = { }, }; +export const NoDate: Story = { + args: { + id: "1", + title: "This is a title", + description: shortDescription, + indicatorTag: "Catalog", + }, +}; + +export const NoTitle: Story = { + args: { + id: "1", + description: shortDescription, + temporalExtent: [new Date(2024, 1, 1)], + indicatorTag: "Catalog", + }, +} + export const CustomDescriptionRender: Story = { args: { id: "1", From a99a3f59bc3f465a14dcf488927823a640ba2dae Mon Sep 17 00:00:00 2001 From: Huy Tran Date: Thu, 23 Jan 2025 20:01:50 -0500 Subject: [PATCH 18/19] chore: Update directory structure for Catalog --- .../Catalog}/CatalogCard.module.css | 0 .../Catalog}/CatalogCard.test.tsx | 3 ++- .../{core => composite/Catalog}/CatalogCard.tsx | 15 ++------------- .../{ => Catalog}/CatalogList.module.css | 0 .../{ => Catalog}/CatalogList.test.tsx | 2 +- .../composite/{ => Catalog}/CatalogList.tsx | 3 ++- src/components/composite/Catalog/index.ts | 3 +++ src/components/composite/Catalog/types.ts | 11 +++++++++++ src/stories/CatalogCard.stories.tsx | 2 +- src/stories/CatalogList.stories.tsx | 17 ++++------------- 10 files changed, 26 insertions(+), 30 deletions(-) rename src/components/{core => composite/Catalog}/CatalogCard.module.css (100%) rename src/components/{core => composite/Catalog}/CatalogCard.test.tsx (97%) rename src/components/{core => composite/Catalog}/CatalogCard.tsx (90%) rename src/components/composite/{ => Catalog}/CatalogList.module.css (100%) rename src/components/composite/{ => Catalog}/CatalogList.test.tsx (97%) rename src/components/composite/{ => Catalog}/CatalogList.tsx (94%) create mode 100644 src/components/composite/Catalog/index.ts create mode 100644 src/components/composite/Catalog/types.ts diff --git a/src/components/core/CatalogCard.module.css b/src/components/composite/Catalog/CatalogCard.module.css similarity index 100% rename from src/components/core/CatalogCard.module.css rename to src/components/composite/Catalog/CatalogCard.module.css diff --git a/src/components/core/CatalogCard.test.tsx b/src/components/composite/Catalog/CatalogCard.test.tsx similarity index 97% rename from src/components/core/CatalogCard.test.tsx rename to src/components/composite/Catalog/CatalogCard.test.tsx index b74b656..309a905 100644 --- a/src/components/core/CatalogCard.test.tsx +++ b/src/components/composite/Catalog/CatalogCard.test.tsx @@ -1,6 +1,7 @@ import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; -import { CatalogCard, type BaseCatalog } from "./CatalogCard"; +import { CatalogCard } from "./CatalogCard"; +import { BaseCatalog } from "./types"; const shortDescription = "Lorem ipsum dolor sit amet"; const longDescription = diff --git a/src/components/core/CatalogCard.tsx b/src/components/composite/Catalog/CatalogCard.tsx similarity index 90% rename from src/components/core/CatalogCard.tsx rename to src/components/composite/Catalog/CatalogCard.tsx index 35b0d4b..98badf4 100644 --- a/src/components/core/CatalogCard.tsx +++ b/src/components/composite/Catalog/CatalogCard.tsx @@ -3,19 +3,8 @@ import { Button } from "react-aria-components"; import type { PressEvent } from "react-aria"; import styles from "./CatalogCard.module.css"; -import { convertDateToUTCString, truncateText } from "../../utils"; - -export type TemporalExtent = [Date, Date?]; - -export type IndicatorTag = "API" | "Catalog"; - -export interface BaseCatalog { - id: string; - title?: string; - description: string; - temporalExtent?: TemporalExtent; - indicatorTag?: IndicatorTag; -} +import { convertDateToUTCString, truncateText } from "../../../utils"; +import { BaseCatalog, IndicatorTag } from "./types"; export interface CatalogCardProps extends BaseCatalog { onBrowsePress?: (e: PressEvent) => void; diff --git a/src/components/composite/CatalogList.module.css b/src/components/composite/Catalog/CatalogList.module.css similarity index 100% rename from src/components/composite/CatalogList.module.css rename to src/components/composite/Catalog/CatalogList.module.css diff --git a/src/components/composite/CatalogList.test.tsx b/src/components/composite/Catalog/CatalogList.test.tsx similarity index 97% rename from src/components/composite/CatalogList.test.tsx rename to src/components/composite/Catalog/CatalogList.test.tsx index f5657a2..35ddecc 100644 --- a/src/components/composite/CatalogList.test.tsx +++ b/src/components/composite/Catalog/CatalogList.test.tsx @@ -1,5 +1,5 @@ import { render, screen } from "@testing-library/react"; -import { BaseCatalog } from "../core/CatalogCard"; +import { BaseCatalog } from "./types"; import { CatalogList } from "./CatalogList"; const shortDescription = "Lorem ipsum dolor sit amet"; diff --git a/src/components/composite/CatalogList.tsx b/src/components/composite/Catalog/CatalogList.tsx similarity index 94% rename from src/components/composite/CatalogList.tsx rename to src/components/composite/Catalog/CatalogList.tsx index 296ecc8..522a007 100644 --- a/src/components/composite/CatalogList.tsx +++ b/src/components/composite/Catalog/CatalogList.tsx @@ -1,5 +1,6 @@ import styles from "./CatalogList.module.css"; -import { type BaseCatalog, CatalogCard } from "../core/CatalogCard"; +import { CatalogCard } from "./CatalogCard"; +import { BaseCatalog } from "./types"; export interface CatalogProps { catalogs: BaseCatalog[] | null | undefined; diff --git a/src/components/composite/Catalog/index.ts b/src/components/composite/Catalog/index.ts new file mode 100644 index 0000000..77cdd9c --- /dev/null +++ b/src/components/composite/Catalog/index.ts @@ -0,0 +1,3 @@ +export { CatalogCard } from "./CatalogCard"; +export { CatalogList } from "./CatalogList"; +export * from './types' diff --git a/src/components/composite/Catalog/types.ts b/src/components/composite/Catalog/types.ts new file mode 100644 index 0000000..930311a --- /dev/null +++ b/src/components/composite/Catalog/types.ts @@ -0,0 +1,11 @@ +export type TemporalExtent = [Date, Date?]; + +export type IndicatorTag = "API" | "Catalog"; + +export interface BaseCatalog { + id: string; + title?: string; + description: string; + temporalExtent?: TemporalExtent; + indicatorTag?: IndicatorTag; +} diff --git a/src/stories/CatalogCard.stories.tsx b/src/stories/CatalogCard.stories.tsx index 1f44fbe..6329ead 100644 --- a/src/stories/CatalogCard.stories.tsx +++ b/src/stories/CatalogCard.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { CatalogCard } from "../components/core/CatalogCard"; +import { CatalogCard } from "../components/composite/Catalog"; const meta = { title: "Core/CatalogCard", diff --git a/src/stories/CatalogList.stories.tsx b/src/stories/CatalogList.stories.tsx index 58abfe5..7f2450b 100644 --- a/src/stories/CatalogList.stories.tsx +++ b/src/stories/CatalogList.stories.tsx @@ -1,7 +1,6 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { CatalogList } from "../components/composite/CatalogList"; -import { BaseCatalog } from "../components/core/CatalogCard"; +import { CatalogList, type BaseCatalog } from "../components/composite/Catalog"; const meta = { title: "Composite/CatalogList", @@ -20,29 +19,21 @@ const catalogs: BaseCatalog[] = [ id: "1", title: "Catalog 1", description: longDescription, - temporalExtent: [ - new Date(2024, 1, 1, 12, 22, 11), - ], + temporalExtent: [new Date(2024, 1, 1, 12, 22, 11)], indicatorTag: "API", }, { id: "2", title: "Catalog 2", description: "Catalog 2 Description", - temporalExtent: [ - new Date(2024, 1, 1), - new Date(2024, 1, 1), - ], + temporalExtent: [new Date(2024, 1, 1), new Date(2024, 1, 1)], indicatorTag: "API", }, { id: "3", title: "Catalog 3", description: "Catalog 3 Description", - temporalExtent: [ - new Date(2024, 1, 1), - new Date(), - ], + temporalExtent: [new Date(2024, 1, 1), new Date()], indicatorTag: "API", }, ]; From 592145778830f42b0265458bc91a1fd640865a1a Mon Sep 17 00:00:00 2001 From: Huy Tran Date: Fri, 24 Jan 2025 14:18:59 -0500 Subject: [PATCH 19/19] fix: Add background white to card --- src/components/composite/Catalog/CatalogCard.module.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/composite/Catalog/CatalogCard.module.css b/src/components/composite/Catalog/CatalogCard.module.css index 5f4d13e..2f483d4 100644 --- a/src/components/composite/Catalog/CatalogCard.module.css +++ b/src/components/composite/Catalog/CatalogCard.module.css @@ -9,6 +9,7 @@ border-radius: 8px; padding: 12px; border: 1px solid #00000027; + background: white; gap: 32px; }