Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(web): add info card #16931

Open
wants to merge 33 commits into
base: main
Choose a base branch
from
Open

feat(web): add info card #16931

wants to merge 33 commits into from

Conversation

thorkellmani
Copy link
Member

@thorkellmani thorkellmani commented Nov 19, 2024

What

New <InfoCard /> component for web

Screenshots / Gifs

Attach Screenshots / Gifs to help reviewers understand the scope of the pull request

Checklist:

  • I have performed a self-review of my own code
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • Formatting passes locally with my changes
  • I have rebased against main before asking for a review

Summary by CodeRabbit

  • New Features

    • Introduced new InfoCard, DetailedInfoCard, and SimpleInfoCard components for enhanced display of grant information.
    • Added a toggle button in the SearchResultsContent component to switch between grid and list views for displaying grants.
    • Implemented localization support with new message definitions for grant statuses and display options.
  • Bug Fixes

    • Improved data handling in the SearchResultsContent component to ensure valid grant entries are processed.
  • Documentation

    • Updated messages for improved clarity in the application.
  • Chores

    • Removed obsolete PlazaCard component and associated styles.

Copy link
Contributor

coderabbitai bot commented Nov 19, 2024

Walkthrough

The pull request introduces several changes across multiple files, primarily focusing on the restructuring and enhancement of the InfoCard component suite. It includes the addition of new components such as InfoCard, DetailedInfoCard, and SimpleInfoCard, alongside their respective styles. The PlazaCard component is removed, and ownership assignments in the .github/CODEOWNERS file are updated. Additionally, several utility functions and GraphQL queries are modified to improve functionality and data handling.

Changes

File Change Summary
.github/CODEOWNERS Ownership for /apps/web/components/PlazaCard/ removed; ownership for /apps/web/components/InfoCard/ added to @island-is/hugsmidjan.
apps/web/components/InfoCard/DetailedInfoCard.tsx Introduced DetailedInfoCard component with new DetailedProps type; updated rendering logic and state management using useWindowSize.
apps/web/components/InfoCard/InfoCard.css.ts Added new CSS styles for InfoCard components: infoCardSmall, infoCard, infoCardWide, wideTitleBox.
apps/web/components/InfoCard/InfoCard.tsx Introduced InfoCard component that conditionally renders DetailedInfoCard or SimpleInfoCard based on the variant prop.
`apps/web/components/InfoCard/InfoCardWrapper.tsx Added InfoCardWrapper component to render a collection of InfoCard components with responsive layout based on props.
`apps/web/components/InfoCard/SimpleInfoCard.tsx Introduced SimpleInfoCard component with responsive rendering logic based on props.
apps/web/components/PlazaCard/PlazaCard.css.ts Deleted the file containing styles for PlazaCard.
apps/web/components/real.ts Removed export for PlazaCard; added exports for InfoCard and InfoCardWrapper.
apps/web/screens/Grants/SearchResults/SearchResultsContent.tsx Updated to use InfoCardWrapper instead of PlazaCard, added state for toggling layout between grid and list views.
apps/web/screens/Grants/messages.ts Added new messages for grid and list display, and updated existing messages for clarity.
apps/web/screens/Grants/utils.ts Restructured generateStatusTag function and added parseStatus function for improved status handling.
apps/web/pages/en/grants-plaza/grant/[id].ts Introduced a new server-side rendered page for grant details.
apps/web/pages/en/grants-plaza/grants/index.ts Introduced a new server-side rendered page for grants listing.
apps/web/pages/en/grants-plaza/index.ts Introduced a new server-side rendered page for the Grants Plaza feature.
apps/web/screens/Grants/Grant/Grant.tsx Added imports for generateStatusTag and parseStatus functions.
`apps/web/screens/Grants/Grant/GrantSidebar.tsx Updated to use useIntl for internationalization; added parseStatus for status handling.
`apps/web/screens/Grants/Home/GrantsHome.tsx Minor adjustments in variable naming and prop handling in GrantsHomePage.
apps/web/screens/queries/Grants.ts Modified GraphQL queries to remove and add specific fields related to grant status.
libs/cms/src/lib/cms.elasticsearch.service.ts Removed unused imports and simplified getGrants method parameters.
libs/cms/src/lib/models/grant.model.ts Expanded GrantStatus enum, removed fields from Grant class, and refactored mapGrant function for improved status and date handling.
libs/cms/src/lib/search/importers/grants.service.ts Refined grant processing logic in doMapping method, including updates to status handling.

Possibly related PRs

Suggested labels

automerge

Suggested reviewers

  • oddsson
  • robertaandersen

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Experiment)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

codecov bot commented Nov 19, 2024

Codecov Report

Attention: Patch coverage is 6.16740% with 213 lines in your changes missing coverage. Please review.

Project coverage is 35.71%. Comparing base (32a256e) to head (5fd3723).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
apps/web/screens/Grants/utils.ts 0.00% 47 Missing ⚠️
libs/cms/src/lib/models/grant.model.ts 23.33% 46 Missing ⚠️
...eens/Grants/SearchResults/SearchResultsContent.tsx 0.00% 33 Missing ⚠️
apps/web/components/InfoCard/DetailedInfoCard.tsx 0.00% 27 Missing ⚠️
apps/web/components/InfoCard/SimpleInfoCard.tsx 0.00% 21 Missing ⚠️
apps/web/components/InfoCard/InfoCardWrapper.tsx 0.00% 13 Missing ⚠️
apps/web/components/InfoCard/InfoCard.tsx 0.00% 8 Missing ⚠️
apps/web/screens/Grants/Grant/GrantSidebar.tsx 0.00% 5 Missing ⚠️
...ibs/cms/src/lib/search/importers/grants.service.ts 0.00% 5 Missing ⚠️
apps/web/pages/en/grants-plaza/grant/[id].ts 0.00% 2 Missing ⚠️
... and 3 more
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main   #16931      +/-   ##
==========================================
- Coverage   35.76%   35.71%   -0.06%     
==========================================
  Files        6931     6937       +6     
  Lines      147977   148394     +417     
  Branches    42173    42397     +224     
==========================================
+ Hits        52931    53003      +72     
- Misses      95046    95391     +345     
Flag Coverage Δ
api 3.33% <ø> (ø)
api-domains-auth-admin 48.49% <ø> (ø)
api-domains-communications 39.41% <21.53%> (-0.02%) ⬇️
application-system-api 38.75% <21.53%> (+<0.01%) ⬆️
application-template-api-modules 27.82% <21.53%> (+0.01%) ⬆️
cms 0.39% <0.00%> (-0.01%) ⬇️
cms-translations 38.74% <21.53%> (-0.02%) ⬇️
judicial-system-api 20.16% <ø> (ø)
judicial-system-backend 55.85% <21.53%> (-0.03%) ⬇️
services-user-notification 46.55% <21.53%> (-0.03%) ⬇️
web 2.41% <0.00%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
apps/web/screens/Grants/Grant/Grant.tsx 0.00% <ø> (ø)
apps/web/screens/Grants/messages.ts 0.00% <ø> (ø)
apps/web/screens/queries/Grants.ts 0.00% <ø> (ø)
libs/cms/src/lib/cms.elasticsearch.service.ts 2.89% <ø> (+0.02%) ⬆️
apps/web/pages/en/grants-plaza/grant/[id].ts 0.00% <0.00%> (ø)
apps/web/pages/en/grants-plaza/grants/index.ts 0.00% <0.00%> (ø)
apps/web/pages/en/grants-plaza/index.ts 0.00% <0.00%> (ø)
apps/web/screens/Grants/Home/GrantsHome.tsx 0.00% <0.00%> (ø)
apps/web/screens/Grants/Grant/GrantSidebar.tsx 0.00% <0.00%> (ø)
...ibs/cms/src/lib/search/importers/grants.service.ts 11.11% <0.00%> (+0.17%) ⬆️
... and 7 more

... and 22 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 32a256e...5fd3723. Read the comment docs.

@datadog-island-is
Copy link

datadog-island-is bot commented Nov 19, 2024

Datadog Report

All test runs cb85639 🔗

11 Total Test Services: 0 Failed, 10 Passed
🔻 Test Sessions change in coverage: 5 decreased, 24 no change

Test Services
This report shows up to 10 services
Service Name Failed Known Flaky New Flaky Passed Skipped Total Time Code Coverage Change Test Service View
api 0 0 0 4 0 3.36s 1 no change Link
api-domains-auth-admin 0 0 0 18 0 15.13s 1 no change Link
api-domains-communications 0 0 0 5 0 37.79s 1 decreased (-0.05%) Link
api-domains-license-service 0 0 0 0 0 580.22ms 1 no change Link
application-system-api 0 0 0 46 0 2m 19.01s 1 no change Link
application-template-api-modules 0 0 0 118 0 2m 48.63s 1 no change Link
cms-translations 0 0 0 3 0 28.59s 1 decreased (-0.04%) Link
judicial-system-api 0 0 0 61 0 7s 1 no change Link
judicial-system-backend 0 0 0 21286 0 24m 9.63s 1 decreased (-0.04%) Link
services-user-notification 0 0 0 51 0 1m 35.18s 1 decreased (-0.04%) Link

🔻 Code Coverage Decreases vs Default Branch (5)

  • api-domains-communications - jest 48.53% (-0.05%) - Details
  • judicial-system-backend - jest 59.48% (-0.04%) - Details
  • cms-translations - jest 48.18% (-0.04%) - Details
  • services-user-notification - jest 68.95% (-0.04%) - Details
  • web - jest 3.25% (-0.02%) - Details

@thorkellmani thorkellmani added the automerge Merge this PR as soon as all checks pass label Dec 4, 2024
@thorkellmani thorkellmani marked this pull request as ready for review December 4, 2024 15:19
@thorkellmani thorkellmani requested review from a team as code owners December 4, 2024 15:19
@thorkellmani thorkellmani added the deploy-feature Deploys features to dev label Dec 4, 2024
Copy link
Contributor

github-actions bot commented Dec 4, 2024

Affected services are: air-discount-scheme-api,api,application-system-api,judicial-system-api,judicial-system-backend,services-search-indexer,services-user-notification,web,
Feature deployment of your services will begin shortly. Your feature will be accessible here:
https://featadd-info-card-api-catalogue.dev01.devland.is/api
https://featadd-info-card-application-callback-xrd.internal.dev01.devland.is/application-payment
https://featadd-info-card-application-callback-xrd.internal.dev01.devland.is/applications
https://featadd-info-card-application-payment-callback-xrd.internal.dev01.devland.is/application-payment
https://featadd-info-card-application-payment-callback-xrd.internal.dev01.devland.is/applications
https://featadd-info-card-beta.dev01.devland.is/
https://featadd-info-card-beta.dev01.devland.is/api
https://featadd-info-card-beta.dev01.devland.is/bff
https://featadd-info-card-beta.dev01.devland.is/samradsgatt
https://featadd-info-card-beta.dev01.devland.is/stjornbord/bff
https://featadd-info-card-loftbru-cf.dev01.devland.is/
https://featadd-info-card-loftbru-cf.dev01.devland.is/api/graphql
https://featadd-info-card-loftbru.dev01.devland.is/
https://featadd-info-card-loftbru.dev01.devland.is/api/graphql

Deployed services: application-system-api,api,web,air-discount-scheme-api,application-system-api-worker,consultation-portal,services-bff-portals-admin,services-bff-portals-my-pages,air-discount-scheme-web.
Excluded services: search-indexer-service,user-notification,user-notification-worker,user-notification-cleanup-worker

Copy link
Member

@disaerna disaerna left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯 + Would like to have the Info card added to the Island UI library 🤓

Copy link
Member

@disaerna disaerna left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When reviewing the feature deplouy I noticed a few things:

  • Border radius is too small
  • Hover state is off
  • Tags are missing
  • Link button is missing
  • Icons are too small

@thorkellmani thorkellmani removed the automerge Merge this PR as soon as all checks pass label Dec 5, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Outside diff range and nitpick comments (6)
apps/web/components/InfoCard/DetailedInfoCard.tsx (1)

69-69: Ensure alt attribute for images is provided

The img element should have a meaningful alt attribute for accessibility. Since logoAlt is optional, there is a possibility of the alt attribute being undefined. Consider providing a default alt text or making logoAlt a required prop to improve accessibility.

Apply this diff to set a default alt text:

 return (
   <Box style={{ flex: '0 0 40px' }}>
-    <img height={40} src={logo} alt={logoAlt} />
+    <img height={40} src={logo} alt={logoAlt || 'Logo'} />
   </Box>
 )

Alternatively, make logoAlt a required prop:

 export type DetailedProps = BaseProps & {
   logo?: string
-  logoAlt?: string
+  logoAlt: string
   subEyebrow?: string
   //max 5 lines
   detailLines?: Array<{
     icon: IconMapIcon
     text: string
   }>
   tags?: Array<ActionCardProps['tag']>
 }
apps/web/screens/Grants/utils.ts (1)

Removing GrantStatus.SeeDescription case requires additional changes in the codebase

The verification reveals that GrantStatus.SEE_DESCRIPTION is still actively used in the codebase:

  • It's defined in libs/cms/src/lib/models/grant.model.ts
  • It's referenced in libs/cms/src/lib/search/importers/grants.service.ts
  • The status is assigned in the grant model when certain conditions are met

The removal of this case from generateStatusTag will cause undefined to be returned when SEE_DESCRIPTION status is encountered, which could lead to UI issues in:

  • apps/web/screens/Grants/Grant/GrantSidebar.tsx
  • apps/web/screens/Grants/SearchResults/SearchResultsContent.tsx
🔗 Analysis chain

Line range hint 4-18: Verify the impact of removing GrantStatus.SeeDescription case

By removing the GrantStatus.SeeDescription case from generateStatusTag, any instances where this status is used will now return undefined. Ensure that this change does not cause unintended behavior in the application.

Run the following script to check for usages of GrantStatus.SeeDescription:

This will help identify if there are any remaining references that need to be addressed.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all usages of GrantStatus.SeeDescription

# Search for any occurrences of GrantStatus.SeeDescription in the codebase
rg 'GrantStatus\.SeeDescription'

Length of output: 34


Script:

#!/bin/bash
# Let's first check the GrantStatus enum definition to understand all possible values
rg -A 5 "enum GrantStatus" 

# Also search for any imports or references to GrantStatus
rg "GrantStatus"

# Let's also check the actual usage of generateStatusTag function
rg "generateStatusTag"

Length of output: 2671

apps/web/components/InfoCard/InfoCard.tsx (1)

17-24: Consider making the variant prop required for clarity

Currently, the variant prop is optional for the simple variant and required for the detailed variant. This could lead to confusion and potential bugs if the prop is omitted unintentionally. Making variant a required prop improves type safety and clarity.

Apply this diff to adjust the InfoCardProps type:

 export type InfoCardProps =
-  | (BaseProps & {
-      variant?: 'simple'
+  | (BaseProps & ({
+      variant: 'simple'
     })
   | (DetailedProps & {
     variant: 'detailed'
   })

Alternatively, set a default value for the variant prop in the InfoCard component:

 export const InfoCard = (props: InfoCardProps) => {
+  const { variant = 'simple' } = props
-  if (props.variant === 'detailed') {
+  if (variant === 'detailed') {
     return <DetailedInfoCard {...props} />
   } else {
     return <SimpleInfoCard {...props} />
   }
 }

This ensures that the component behaves predictably even if variant is not explicitly provided.

apps/web/components/InfoCard/InfoCardWrapper.tsx (1)

21-26: Consider memoizing the width check

The window size check could be optimized using useMemo to prevent unnecessary re-renders.

+ const isMobileWidth = useMemo(
+   () => width < theme.breakpoints.md,
+   [width]
+ )

  useEffect(() => {
-   if (width < theme.breakpoints.md) {
+   if (isMobileWidth) {
      return setIsMobile(true)
    }
    setIsMobile(false)
-  }, [width])
+  }, [isMobileWidth])
apps/web/screens/Grants/SearchResults/SearchResultsContent.tsx (2)

106-107: Address the TODO comment for application deadline text.

The hardcoded deadline text needs to be replaced with the actual deadline from the data.

Would you like me to help implement the dynamic deadline text using the grant data?


58-123: Consider extracting the card data transformation logic.

The current implementation has complex data transformation logic inline. Consider extracting this into a separate utility function for better maintainability and reusability.

+const transformGrantToCardData = (grant: Grant, formatMessage: FormatMessage, locale: Locale, linkResolver: LinkResolver) => {
+  if (!grant || !grant.applicationId) {
+    return null
+  }
+
+  return {
+    eyebrow: grant.fund?.title ?? grant.name ?? '',
+    subEyebrow: grant.fund?.parentOrganization?.title,
+    // ... rest of the transformation
+  }
+}

 return (
   <>
     {grants?.length ? (
       <InfoCardWrapper
         columns={!isGridLayout ? 1 : 2}
         variant="detailed"
-        cards={grants?.map((grant) => {
-          if (!grant || !grant.applicationId) {
-            return null
-          }
-          return { ... }
-        }).filter(isDefined) ?? []}
+        cards={grants?.map(grant => 
+          transformGrantToCardData(grant, formatMessage, locale, linkResolver)
+        ).filter(isDefined) ?? []}
       />
     ) : undefined}
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 5c8c1b9 and f80f403.

📒 Files selected for processing (12)
  • .github/CODEOWNERS (1 hunks)
  • apps/web/components/InfoCard/DetailedInfoCard.tsx (1 hunks)
  • apps/web/components/InfoCard/InfoCard.css.ts (1 hunks)
  • apps/web/components/InfoCard/InfoCard.tsx (1 hunks)
  • apps/web/components/InfoCard/InfoCardWrapper.tsx (1 hunks)
  • apps/web/components/InfoCard/SimpleInfoCard.tsx (1 hunks)
  • apps/web/components/PlazaCard/PlazaCard.css.ts (0 hunks)
  • apps/web/components/PlazaCard/PlazaCard.tsx (0 hunks)
  • apps/web/components/real.ts (1 hunks)
  • apps/web/screens/Grants/SearchResults/SearchResultsContent.tsx (2 hunks)
  • apps/web/screens/Grants/messages.ts (1 hunks)
  • apps/web/screens/Grants/utils.ts (1 hunks)
💤 Files with no reviewable changes (2)
  • apps/web/components/PlazaCard/PlazaCard.css.ts
  • apps/web/components/PlazaCard/PlazaCard.tsx
🧰 Additional context used
📓 Path-based instructions (9)
apps/web/components/real.ts (1)

Pattern apps/**/*: "Confirm that the code adheres to the following:

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/web/screens/Grants/messages.ts (1)

Pattern apps/**/*: "Confirm that the code adheres to the following:

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/web/screens/Grants/utils.ts (1)

Pattern apps/**/*: "Confirm that the code adheres to the following:

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/web/components/InfoCard/InfoCard.css.ts (1)

Pattern apps/**/*: "Confirm that the code adheres to the following:

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/web/components/InfoCard/InfoCard.tsx (1)

Pattern apps/**/*: "Confirm that the code adheres to the following:

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/web/components/InfoCard/DetailedInfoCard.tsx (1)

Pattern apps/**/*: "Confirm that the code adheres to the following:

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/web/components/InfoCard/SimpleInfoCard.tsx (1)

Pattern apps/**/*: "Confirm that the code adheres to the following:

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/web/screens/Grants/SearchResults/SearchResultsContent.tsx (1)

Pattern apps/**/*: "Confirm that the code adheres to the following:

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/web/components/InfoCard/InfoCardWrapper.tsx (1)

Pattern apps/**/*: "Confirm that the code adheres to the following:

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
🪛 Biome (1.9.4)
apps/web/components/InfoCard/DetailedInfoCard.tsx

[error] 119-119: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

apps/web/components/InfoCard/InfoCardWrapper.tsx

[error] 32-32: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 41-45: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

🔇 Additional comments (5)
apps/web/components/InfoCard/InfoCard.css.ts (1)

1-17: Styles are appropriately defined

The CSS styles are correctly defined using @vanilla-extract/css, providing clear and maintainable styling for the InfoCard components.

apps/web/components/real.ts (1)

15-16: Verify the removal of PlazaCard export

The PlazaCard export has been removed and replaced with InfoCard exports. Let's verify there are no remaining usages of PlazaCard in the codebase.

✅ Verification successful

PlazaCard removal appears safe

No references to PlazaCard were found in the codebase, suggesting that its removal from the exports is safe and won't cause any breaking changes.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining references to PlazaCard
rg "PlazaCard" --type ts --type tsx

# Search for any imports from the old path
rg "from ['\"]@island\.is/web/components['\"]" --type ts --type tsx -A 5 | grep -i plaza

Length of output: 186


Script:

#!/bin/bash
# Search for any remaining references to PlazaCard without file type restrictions
rg "PlazaCard"

# Search for any imports containing Plaza
rg "import.*Plaza"

# List all TypeScript and JavaScript files that might reference PlazaCard
fd "\.(ts|tsx|js|jsx)$" -x grep -l "Plaza"

Length of output: 175

apps/web/screens/Grants/SearchResults/SearchResultsContent.tsx (1)

31-54: LGTM: Layout toggle implementation is clean and follows best practices.

The implementation:

  • Uses appropriate state management with useState
  • Implements responsive design by hiding toggle on mobile
  • Follows accessibility best practices with Button component
  • Uses localized messages for button text
apps/web/screens/Grants/messages.ts (1)

9-16: LGTM: Message definitions follow established patterns.

The new messages for grid/list display options are:

  • Properly structured with unique IDs
  • Follow the existing naming convention
  • Include appropriate default messages in Icelandic
.github/CODEOWNERS (1)

135-135: LGTM: Ownership assignment is correct.

The InfoCard component ownership is properly assigned to the @island-is/hugsmidjan team, consistent with their ownership of other web components in the grants domain.

Comment on lines +55 to +60
useEffect(() => {
if (width < theme.breakpoints.lg) {
return setIsTablet(true)
}
setIsTablet(false)
}, [width])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix incorrect use of return in useEffect

The useEffect hook should not return the result of setIsTablet(true) as it is not a cleanup function. Returning a value from useEffect other than a cleanup function can lead to unexpected behavior.

Apply this diff to fix the issue:

 useEffect(() => {
   if (width < theme.breakpoints.lg) {
-    return setIsTablet(true)
+    setIsTablet(true)
   } else {
     setIsTablet(false)
   }
-  }, [width])
+}, [width])
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
if (width < theme.breakpoints.lg) {
return setIsTablet(true)
}
setIsTablet(false)
}, [width])
useEffect(() => {
if (width < theme.breakpoints.lg) {
setIsTablet(true)
} else {
setIsTablet(false)
}
}, [width])

Comment on lines +114 to +125
.map((tag) => {
if (!tag) {
return null
}
return (
<Tag disabled variant={tag.variant}>
{tag.label}
</Tag>
)
})
.filter(isDefined)}
</Inline>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add a unique key prop to elements in list rendering

When rendering a list of items in React using map, each element should have a unique key prop. In the tags.map() function, the Tag components are missing a key prop, which can lead to rendering issues and warnings in the console.

Apply this diff to fix the issue:

 {tags
-  .map((tag) => {
+  .map((tag, index) => {
     if (!tag) {
       return null
     }
     return (
-      <Tag disabled variant={tag.variant}>
+      <Tag key={tag.label} disabled variant={tag.variant}>
         {tag.label}
       </Tag>
     )
   })
   .filter(isDefined)}

Ensure that tag.label is unique. If it is not guaranteed to be unique, consider using an index or another unique identifier.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.map((tag) => {
if (!tag) {
return null
}
return (
<Tag disabled variant={tag.variant}>
{tag.label}
</Tag>
)
})
.filter(isDefined)}
</Inline>
.map((tag, index) => {
if (!tag) {
return null
}
return (
<Tag key={tag.label} disabled variant={tag.variant}>
{tag.label}
</Tag>
)
})
.filter(isDefined)}
</Inline>
🧰 Tools
🪛 Biome (1.9.4)

[error] 119-119: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

Comment on lines +40 to +46
{cards.map((c) => (
<InfoCard
variant={variant}
size={columns === 3 ? 'small' : 'medium'}
{...c}
/>
))}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add missing key prop to mapped InfoCard components

Similar to the previous issue, add a unique key prop here as well.

         <InfoCard
+          key={c.id ?? c.title}
           variant={variant}
           size={columns === 3 ? 'small' : 'medium'}
           {...c}
         />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{cards.map((c) => (
<InfoCard
variant={variant}
size={columns === 3 ? 'small' : 'medium'}
{...c}
/>
))}
{cards.map((c) => (
<InfoCard
key={c.id ?? c.title}
variant={variant}
size={columns === 3 ? 'small' : 'medium'}
{...c}
/>
))}
🧰 Tools
🪛 Biome (1.9.4)

[error] 41-45: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

Comment on lines +31 to +33
{cards.map((c) => (
<InfoCard variant={variant} size={'large'} {...c} />
))}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add missing key prop to mapped InfoCard components

React requires a unique key prop when rendering elements in an array to optimize rendering and maintain component state correctly.

-          <InfoCard variant={variant} size={'large'} {...c} />
+          <InfoCard key={c.id ?? c.title} variant={variant} size={'large'} {...c} />

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Biome (1.9.4)

[error] 32-32: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

Comment on lines +28 to +36
const [isTablet, setIsTablet] = useState(false)
const { width } = useWindowSize()

useEffect(() => {
if (width < theme.breakpoints.lg) {
return setIsTablet(true)
}
setIsTablet(false)
}, [width])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Extract window size logic into a custom hook

The window size check logic is duplicated from InfoCardWrapper. Consider extracting it into a shared custom hook.

Create a new hook file useDeviceSize.ts:

import { useState, useEffect } from 'react'
import { useWindowSize } from 'react-use'
import { theme } from '@island.is/island-ui/theme'

export const useDeviceSize = () => {
  const [isTablet, setIsTablet] = useState(false)
  const { width } = useWindowSize()

  useEffect(() => {
    setIsTablet(width < theme.breakpoints.lg)
  }, [width])

  return { isTablet }
}

Then update the component:

- const [isTablet, setIsTablet] = useState(false)
- const { width } = useWindowSize()
- 
- useEffect(() => {
-   if (width < theme.breakpoints.lg) {
-     return setIsTablet(true)
-   }
-   setIsTablet(false)
- }, [width])
+ const { isTablet } = useDeviceSize()

Comment on lines 86 to 107
return (
<FocusableBox
className={
size === 'large'
? styles.infoCardWide
: size === 'small'
? styles.infoCardSmall
: styles.infoCard
}
component={LinkV2}
href={link.href}
background="white"
borderColor="white"
borderWidth="standard"
width="full"
borderRadius="standard"
>
<Box width="full" paddingX={4} paddingY={3}>
{renderHeader()}
{renderContent()}
</Box>
</FocusableBox>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance accessibility with ARIA labels

The card acts as a clickable link but lacks proper accessibility attributes.

     <FocusableBox
+      aria-label={`${eyebrow}: ${title}`}
+      role="article"
       className={
         size === 'large'
           ? styles.infoCardWide

Committable suggestion skipped: line range outside the PR's diff.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Outside diff range and nitpick comments (8)
apps/web/components/InfoCard/DetailedInfoCard.tsx (3)

28-37: LGTM! Consider enhancing the type documentation.

The type definition is well-structured. However, the inline comment about max lines could be more descriptive.

Consider using JSDoc format for better documentation:

-  //max 5 lines
+  /** Maximum of 5 detail lines will be displayed */
   detailLines?: Array<{
     icon: IconMapIcon
     text: string
   }>

52-60: Consider extracting breakpoint logic to a constant

The breakpoint comparison could be more maintainable by extracting the value to a named constant.

+ const TABLET_BREAKPOINT = theme.breakpoints.lg
  const [isTablet, setIsTablet] = useState(false)
  const { width } = useWindowSize()

  useEffect(() => {
-   if (width < theme.breakpoints.lg) {
+   if (width < TABLET_BREAKPOINT) {
      setIsTablet(true)
    } else {
      setIsTablet(false)
    }
  }, [width])

156-189: Consider memoizing render functions for performance

The render functions could benefit from memoization to prevent unnecessary re-renders.

+ const MemoizedContent = React.useMemo(
+   () => (
      <>
        <Text variant="h3" color="blue400">
          {title}
        </Text>
        {description && (
          <Box marginTop={1}>
            <Text>{description}</Text>
          </Box>
        )}
        {renderDetails()}
      </>
+   ),
+   [title, description, renderDetails]
+ )

  const renderContent = () => {
    if (size === 'large' && !isTablet) {
      return (
        <GridContainer>
          <GridRow direction="row">
            <GridColumn span="8/12">
              {MemoizedContent}
            </GridColumn>
            <GridColumn span="4/12">{renderDetails()}</GridColumn>
          </GridRow>
        </GridContainer>
      )
    }
-   return (
-     <>
-       <Text variant="h3" color="blue400">
-         {title}
-       </Text>
-       {description && (
-         <Box marginTop={1}>
-           <Text>{description}</Text>
-         </Box>
-       )}
-       {renderDetails()}
-     </>
-   )
+   return MemoizedContent
  }
apps/web/pages/en/grants-plaza/index.ts (1)

7-7: Consider Dynamic Locale Handling

Hardcoding the locale to 'en' may limit internationalization. Consider making the locale dynamic to support multiple languages and enhance user experience.

apps/web/pages/en/grants-plaza/grant/[id].ts (1)

8-8: Consider Dynamic Locale for Internationalization

Hardcoding 'en' as the locale may restrict access for users in other regions. Implementing dynamic locale support can enhance inclusivity.

apps/web/screens/Grants/utils.ts (1)

28-116: Consider simplifying status parsing logic

The parseStatus function handles multiple cases well but could be simplified by extracting common patterns.

Consider:

  1. Extracting the deadline status formatting logic into a separate function
  2. Creating a mapping object for status messages to reduce repetition
  3. Combining similar cases like ClosedOpeningSoon and ClosedOpeningSoonWithEstimation

Example of status message mapping:

const STATUS_MESSAGES = {
  [GrantStatus.Closed]: (grant: Grant, locale: Locale) => 
    grant.dateTo ? formatMessage(
      containsTimePart(grant.dateTo)
        ? m.search.applicationWasOpenToAndWith
        : m.search.applicationWasOpenTo,
      { arg: formatDate(new Date(grant.dateTo), locale) }
    ) : formatMessage(m.search.applicationClosed),
  // ... other status messages
}
apps/web/screens/Grants/SearchResults/SearchResultsContent.tsx (1)

111-112: Address the TODO comment for deadline text

The comment indicates that the deadline text implementation needs to be completed.

Would you like me to help implement the deadline text logic or create a GitHub issue to track this task?

libs/cms/src/lib/cms.elasticsearch.service.ts (1)

Line range hint 486-580: LGTM: Well-structured grant search implementation

The getGrants method:

  • Properly handles search relevance scoring
  • Maintains efficient pagination
  • Uses appropriate field boosting for title matches
  • Implements proper sorting fallback

Consider adding caching for frequently accessed grants to improve performance, especially for popular search queries.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f80f403 and 5fd3723.

⛔ Files ignored due to path filters (1)
  • libs/cms/src/lib/generated/contentfulTypes.d.ts is excluded by !**/generated/**
📒 Files selected for processing (16)
  • apps/web/components/InfoCard/DetailedInfoCard.tsx (4 hunks)
  • apps/web/components/InfoCard/InfoCard.tsx (1 hunks)
  • apps/web/components/InfoCard/SimpleInfoCard.tsx (1 hunks)
  • apps/web/pages/en/grants-plaza/grant/[id].ts (1 hunks)
  • apps/web/pages/en/grants-plaza/grants/index.ts (1 hunks)
  • apps/web/pages/en/grants-plaza/index.ts (1 hunks)
  • apps/web/screens/Grants/Grant/Grant.tsx (1 hunks)
  • apps/web/screens/Grants/Grant/GrantSidebar.tsx (5 hunks)
  • apps/web/screens/Grants/Home/GrantsHome.tsx (1 hunks)
  • apps/web/screens/Grants/SearchResults/SearchResultsContent.tsx (2 hunks)
  • apps/web/screens/Grants/messages.ts (3 hunks)
  • apps/web/screens/Grants/utils.ts (1 hunks)
  • apps/web/screens/queries/Grants.ts (2 hunks)
  • libs/cms/src/lib/cms.elasticsearch.service.ts (1 hunks)
  • libs/cms/src/lib/models/grant.model.ts (4 hunks)
  • libs/cms/src/lib/search/importers/grants.service.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/web/components/InfoCard/InfoCard.tsx
  • apps/web/components/InfoCard/SimpleInfoCard.tsx
🧰 Additional context used
📓 Path-based instructions (14)
apps/web/pages/en/grants-plaza/grants/index.ts (1)

Pattern apps/**/*: "Confirm that the code adheres to the following:

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/web/pages/en/grants-plaza/grant/[id].ts (1)

Pattern apps/**/*: "Confirm that the code adheres to the following:

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/web/pages/en/grants-plaza/index.ts (1)

Pattern apps/**/*: "Confirm that the code adheres to the following:

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/web/screens/Grants/Home/GrantsHome.tsx (1)

Pattern apps/**/*: "Confirm that the code adheres to the following:

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/web/screens/Grants/Grant/Grant.tsx (1)

Pattern apps/**/*: "Confirm that the code adheres to the following:

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/web/screens/Grants/SearchResults/SearchResultsContent.tsx (1)

Pattern apps/**/*: "Confirm that the code adheres to the following:

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/web/components/InfoCard/DetailedInfoCard.tsx (1)

Pattern apps/**/*: "Confirm that the code adheres to the following:

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/web/screens/queries/Grants.ts (1)

Pattern apps/**/*: "Confirm that the code adheres to the following:

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/web/screens/Grants/utils.ts (1)

Pattern apps/**/*: "Confirm that the code adheres to the following:

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
libs/cms/src/lib/cms.elasticsearch.service.ts (1)

Pattern libs/**/*: "Confirm that the code adheres to the following:

  • Reusability of components and hooks across different NextJS apps.
  • TypeScript usage for defining props and exporting types.
  • Effective tree-shaking and bundling practices."
libs/cms/src/lib/search/importers/grants.service.ts (1)

Pattern libs/**/*: "Confirm that the code adheres to the following:

  • Reusability of components and hooks across different NextJS apps.
  • TypeScript usage for defining props and exporting types.
  • Effective tree-shaking and bundling practices."
libs/cms/src/lib/models/grant.model.ts (1)

Pattern libs/**/*: "Confirm that the code adheres to the following:

  • Reusability of components and hooks across different NextJS apps.
  • TypeScript usage for defining props and exporting types.
  • Effective tree-shaking and bundling practices."
apps/web/screens/Grants/Grant/GrantSidebar.tsx (1)

Pattern apps/**/*: "Confirm that the code adheres to the following:

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
apps/web/screens/Grants/messages.ts (1)

Pattern apps/**/*: "Confirm that the code adheres to the following:

  • NextJS best practices, including file structure, API routes, and static generation methods.
  • Efficient state management and server-side rendering techniques.
  • Optimal use of TypeScript for component and utility type safety."
🪛 Biome (1.9.4)
apps/web/components/InfoCard/DetailedInfoCard.tsx

[error] 119-119: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

🔇 Additional comments (33)
apps/web/components/InfoCard/DetailedInfoCard.tsx (2)

55-60: Fix incorrect use of return in useEffect

The useEffect hook should not return the result of setIsTablet(true) as it is not a cleanup function.


114-125: ⚠️ Potential issue

Add missing key prop to Tag component

React requires a unique key prop when rendering lists of elements.

- <Tag disabled variant={tag.variant}>
+ <Tag key={tag.label} disabled variant={tag.variant}>
    {tag.label}
  </Tag>

Likely invalid or redundant comment.

🧰 Tools
🪛 Biome (1.9.4)

[error] 119-119: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

apps/web/screens/Grants/Grant/GrantSidebar.tsx (8)

2-2: Good Use of useIntl Hook

Replacing useLocale with useIntl improves internationalization handling and aligns with best practices using react-intl.


19-19: Imported Utilities Enhance Status Parsing

Importing generateStatusTag and parseStatus consolidates status-related logic, promoting modularity and reusability.


44-44: Condition Updated for Clarity

Checking !data.length explicitly handles empty arrays, improving readability over a generic falsy check.


56-57: Destructuring formatMessage from useIntl

This aligns with react-intl usage patterns and ensures consistent access to internationalization functions.


58-61: Proper Memoization with Correct Dependencies

Using useMemo for status calculation optimizes performance, and including grant, formatMessage, and locale in dependencies ensures accuracy.


103-104: Displaying deadlineStatus Appropriately

Conditional rendering of status.deadlineStatus maintains robustness by handling cases where the deadline status may be undefined.


111-114: Correct Usage of generateStatusTag

Generating the status label using status.applicationStatus and formatMessage ensures accurate status representation.


119-119: Updated Dependencies in useMemo Hook

Including status in the dependency array of detailPanelData ensures that memoization updates when the status changes.

libs/cms/src/lib/models/grant.model.ts (7)

3-3: Importing IGrantFields for Type Safety

Adding IGrantFields import enhances type safety when accessing grant fields, preventing potential runtime errors.


12-14: Importing Date Utility Functions

Incorporating format, addHours, and isValidDate improves date handling and formatting within the model.


18-25: Expanded GrantStatus Enum

Adding new statuses to GrantStatus allows for more granular representation of grant states, improving clarity across the application.


68-69: Added statusText Field to Grant Model

Including statusText provides additional context for grant statuses, enabling display of custom status notes.


87-119: Effective Implementation of parseStatus Function

The parseStatus function correctly interprets grant statuses based on provided fields and dates, enhancing the accuracy of status classification.


121-131: Creation of parseDate Function for Consistent Date Parsing

The parseDate utility ensures consistent date formatting and correctly adjusts for provided times, improving date data integrity.


133-169: Refactored mapGrant Function with Enhanced Logic

Utilizing parseDate and parseStatus within mapGrant improves data mapping accuracy and maintains consistency across the grant model.

apps/web/pages/en/grants-plaza/index.ts (1)

4-4: Proper Use of getServerSidePropsWrapper

Implementing getServerSidePropsWrapper ensures server-side rendering functions are correctly wrapped, aligning with Next.js best practices.

apps/web/pages/en/grants-plaza/grant/[id].ts (1)

4-4: Effective Use of Server-Side Rendering Wrapper

Employing getServerSidePropsWrapper facilitates proper data fetching on the server side, adhering to Next.js server-side rendering techniques.

apps/web/pages/en/grants-plaza/grants/index.ts (1)

1-12: LGTM - Clean NextJS page implementation

The implementation follows NextJS best practices:

  • Proper use of HOCs for Apollo and localization
  • Correct setup of getServerSideProps
  • Clean separation of concerns
apps/web/screens/queries/Grants.ts (2)

70-72: LGTM - Clean field additions

The addition of statusText, dateFrom, and dateTo fields in GET_GRANT_QUERY aligns with the new status handling approach.


19-19: Verify the removal of applicationDeadlineStatus field

The statusText field has replaced applicationDeadlineStatus and isOpen. Please ensure all components consuming this query have been updated to use the new field structure.

✅ Verification successful

Let me search for more specific information about the GraphQL query usage.


Let me check the actual implementation of the components consuming this query.


Let me check how the status fields are being used in the components.


Let me check the Grant type definition to understand the status fields.


Based on the evidence gathered, I can now provide the final response:

The removal of applicationDeadlineStatus field appears safe

The codebase search shows no direct usage of the removed fields applicationDeadlineStatus or isOpen in relation to the grants query. The only isOpen occurrences found are related to UI components like accordions, menus, and modals. The new statusText field is part of the schema change, and since GraphQL enforces schema compliance at build time, any breaking changes would have been caught during compilation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining usage of old fields
rg "applicationDeadlineStatus|isOpen" --type ts

Length of output: 11154


Script:

#!/bin/bash
# Search for references to the GET_GRANTS_QUERY
rg "GET_GRANTS_QUERY" -A 5 --type ts

Length of output: 2130


Script:

#!/bin/bash
# Check the SearchResultsContent implementation
rg -A 10 "SearchResultsContent" --type ts

Length of output: 3850


Script:

#!/bin/bash
# Check for status-related field usage in the components
ast-grep --pattern 'statusText' 

Length of output: 346


Script:

#!/bin/bash
# Search for Grant type/interface definition
ast-grep --pattern 'type Grant = {
  $$$
}'

# Also try interface
ast-grep --pattern 'interface Grant {
  $$$
}'

Length of output: 94

apps/web/screens/Grants/utils.ts (2)

11-15: LGTM - Well-defined Status interface

The Status interface provides good type safety for the application status handling.


118-130: LGTM - Clean status tag generation

The generateStatusTag function is well-implemented with good type safety and clear conditional logic.

libs/cms/src/lib/search/importers/grants.service.ts (1)

106-117: LGTM: Status handling is well-structured

The new status cases are logically grouped based on their tag type (open/closed), making the code more maintainable and easier to understand.

apps/web/screens/Grants/SearchResults/SearchResultsContent.tsx (4)

1-1: LGTM: Clean implementation of grid layout state

The imports and state management are well-organized, following React best practices for implementing the new grid layout feature.

Also applies to: 6-6, 10-10, 15-15, 31-32


36-54: LGTM: Well-implemented layout toggle

The layout toggle button is properly implemented with:

  • Responsive behavior (hidden on mobile)
  • Dynamic icon and label based on the current layout
  • Consistent styling using the design system

58-128: LGTM: Clean InfoCardWrapper implementation

The InfoCardWrapper implementation is well-structured with proper data mapping and null checks.


Line range hint 129-165: LGTM: Well-implemented empty state

The empty state implementation follows best practices with:

  • Clear messaging
  • Responsive image handling
  • Proper accessibility
apps/web/screens/Grants/Home/GrantsHome.tsx (1)

45-45: LGTM: Clean intl handling

The reorganization of intl handling maintains functionality while improving code organization.

Also applies to: 47-47

apps/web/screens/Grants/messages.ts (2)

9-16: LGTM: Display option messages are well-structured

The new display option messages follow proper i18n patterns and naming conventions.


63-90: LGTM: Application status messages are comprehensive

The new application status messages:

  • Follow proper i18n patterns
  • Use consistent argument placeholders
  • Cover all necessary status scenarios
libs/cms/src/lib/cms.elasticsearch.service.ts (1)

50-50: LGTM: Clean import statement

The removal of unused imports improves code cleanliness.

Comment on lines +5 to +6
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore make web strict
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid Suppressing TypeScript Errors

Disabling linting and TypeScript checks with eslint-disable and @ts-ignore can hide potential issues. It's recommended to resolve the TypeScript errors to maintain strict type safety.

Comment on lines +5 to +6
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore make web strict
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid Suppressing TypeScript Errors

Using eslint-disable and @ts-ignore suppresses important checks. Addressing the underlying TypeScript issues will improve code reliability.

Comment on lines +5 to +7
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore make web strict
//
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove or properly fix the ts-ignore comment

The @ts-ignore comment suggests underlying TypeScript issues that should be addressed rather than suppressed. The comment mentions "make web strict" which indicates this might be related to strict mode configuration.

Please investigate and fix the underlying TypeScript issue. If you need assistance debugging the type error, I can help analyze it.

Comment on lines +17 to +25
const formatDate = (
date: Date,
locale: Locale,
stringFormat = 'dd.MMMM yyyy',
) =>
format(date, stringFormat, {
locale: locale === 'is' ? localeIS : localeEn,
})

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for date formatting

The formatDate function should handle invalid date inputs to prevent runtime errors.

 const formatDate = (
   date: Date,
   locale: Locale,
   stringFormat = 'dd.MMMM yyyy',
-) =>
-  format(date, stringFormat, {
-    locale: locale === 'is' ? localeIS : localeEn,
-  })
+) => {
+  try {
+    return format(date, stringFormat, {
+      locale: locale === 'is' ? localeIS : localeEn,
+    })
+  } catch (error) {
+    console.error('Error formatting date:', error)
+    return ''
+  }
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const formatDate = (
date: Date,
locale: Locale,
stringFormat = 'dd.MMMM yyyy',
) =>
format(date, stringFormat, {
locale: locale === 'is' ? localeIS : localeEn,
})
const formatDate = (
date: Date,
locale: Locale,
stringFormat = 'dd.MMMM yyyy',
) => {
try {
return format(date, stringFormat, {
locale: locale === 'is' ? localeIS : localeEn,
})
} catch (error) {
console.error('Error formatting date:', error)
return ''
}
}

@@ -1,6 +1,7 @@
import { useIntl } from 'react-intl'
import NextLink from 'next/link'
import { useRouter } from 'next/router'
import { generateStatusTag, parseStatus } from '../utils'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Imported utilities are not used in Grant.tsx

While the utilities generateStatusTag and parseStatus are imported in Grant.tsx, they are not actually used within this file. However, from our previous search results, we can see these utilities are properly used in sibling components:

  • GrantSidebar.tsx: Uses both utilities for status display
  • SearchResultsContent.tsx: Uses both utilities for search results display

The import in Grant.tsx appears to be unused and should be removed.

🔗 Analysis chain

Verify the integration of status utilities

The newly imported utilities generateStatusTag and parseStatus should be properly integrated with the grant status handling logic.


Let me generate additional verification to check the usage of these utilities in the Grant.tsx file specifically.


Let me try one more verification with a different approach to check the usage in Grant.tsx.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of imported status utilities
# Test: Search for usage of generateStatusTag and parseStatus
rg -A 5 'generateStatusTag|parseStatus' apps/web/screens/Grants/

Length of output: 4245


Script:

#!/bin/bash
# Search for actual usage of these utilities in Grant.tsx
ast-grep --pattern 'parseStatus($$$)' apps/web/screens/Grants/Grant/Grant.tsx
ast-grep --pattern 'generateStatusTag($$$)' apps/web/screens/Grants/Grant/Grant.tsx

Length of output: 165


Script:

#!/bin/bash
# Get the content of Grant.tsx to verify the usage
cat apps/web/screens/Grants/Grant/Grant.tsx

Length of output: 6114

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
deploy-feature Deploys features to dev
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants