Skip to content

fix: asyncdata already mounted part 3 #11491

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

Merged
merged 13 commits into from
Mar 26, 2025

Conversation

preschian
Copy link
Member

@preschian preschian commented Mar 19, 2025

Thank you for your contribution to the Koda - Generative Art Marketplace.

👇 __ Let's make a quick check before the contribution.

PR Type

  • Bugfix
  • Feature
  • Refactoring

Context

Summary by CodeRabbit

  • New Features

    • The generative carousel now displays NFT content only when available, ensuring a cleaner browsing experience.
    • The landing page conditionally showcases drop-based carousels, presenting users with only relevant collections.
  • Refactor

    • Data retrieval across collection details, user statistics, activity feeds, and search has been optimized for faster, more accurate results.
    • Enhanced endpoint fallback mechanisms improve overall application stability.
    • Improved handling of undefined values in data fetching processes for better reliability.

Copy link

coderabbitai bot commented Mar 19, 2025

Walkthrough

This pull request refactors several components and utility modules by updating data fetching methods, type annotations, and control flows. Changes include replacing GraphQL hooks with direct Apollo Client queries, introducing new queries and fragments, and removing deprecated functions. The carousel and activity components have been updated for better data handling and conditional rendering based on the existence of relevant items. Additionally, type adjustments and modifications to exported functions improve clarity and maintainability throughout the codebase.

Changes

File(s) Change Summary
components/carousel/CarouselTypeGenerative.vue
components/carousel/utils/useCarouselEvents.ts
Removed the nfts variable in favor of a new collectionIds prop; merged and sorted event lists via useEvents; added conditional rendering for CarouselIndex; exported useEvents and sortNfts and removed the deprecated useCarouselGenerativeNftEvents function.
components/collection/utils/useCollectionDetails.ts Refactored fetching of collection details and sold data by replacing GraphQL hooks with direct Apollo Client queries; introduced the fetchStats function; adjusted type annotations for data properties and refined handling of undefined values.
components/identity/utils/useIdentity.ts Removed the file containing functionality for fetching sold NFT data and the related NFTListSold interface.
components/identity/utils/useIdentityStats.ts Updated internal logic to use a direct Apollo Client query (using userStatsByAccount), managing loading state with reactive references and removing GraphQL hook-based error handling.
components/landing/LandingPage.vue Added a conditional rendering of LazyCarouselTypeGenerative based on the non-empty dropsAhp array; defined and populated dropsAhp asynchronously by calling getDrops with specific parameters.
components/profile/ProfileActivitySummery.vue Modified the computation of the activity.estimatedValue label by converting stats.value.listedValue to a string using toString().
components/profile/activityTab/Activity.vue Switched to an Apollo Client query for event fetching using allEventsByProfile, updated the events type from InteractionEnum[] to Interaction[], incorporated sortBy from lodash for sorting, and revised filtering logic to check string values for interaction types.
composables/useSearchNfts.ts Replaced the GraphQL hook with a direct Apollo Client query using the nftListWithSearch query; redefined the refetch method and improved state management for loading and data.
plugins/apollo.client.ts Modified the GraphQL endpoint configuration to include a fallback value ('ahp') when the endpoint is not provided by the context.
Queries and Fragments:
queries/fragments/typed/collectionMeta.ts
queries/subsquid/general/allEventsByProfile.ts
queries/subsquid/general/collectionStatsById.ts
queries/subsquid/general/nftListSoldByCollection.ts
queries/subsquid/general/userStatsByAccount.ts
Introduced new GraphQL fragments and queries; updated the query structure (removing __typename where applicable) and shifted from legacy fragment import syntax to explicit ES6 module imports; ensured queries are encapsulated within the graphql function for modularity and clarity.
types/index.ts Updated the Interaction interface by changing the type of blockNumber from `string
utils/math.ts Updated the getVolume function signature by removing the explicit type for the events parameter, affecting type safety.
utils/sorting.ts Removed the sortedEventByDate function along with its associated import for the Interaction type; the remaining sorting utility (sortItemListByIds) remains unchanged.

Sequence Diagram(s)

sequenceDiagram
    participant CarouselComp as CarouselTypeGenerative.vue
    participant UseEvents as useEvents (Carousel Utils)
    participant DataMerge as Computed Data
    participant CarouselIdx as CarouselIndex Component

    CarouselComp->>CarouselComp: Receive collectionIds prop
    CarouselComp->>UseEvents: Call useEvents(chain, type, limit, collectionIds)
    UseEvents->>DataMerge: Fetch ahpEventsNewestList & ahpEventsLatestSales
    DataMerge->>DataMerge: Merge, deduplicate (via unionBy), and sort events
    CarouselComp->>CarouselIdx: Conditionally render CarouselIndex if data array is non-empty
Loading
sequenceDiagram
    participant Activity as Activity.vue
    participant Apollo as Apollo Client
    participant Query as allEventsByProfile Query
    participant SortBy as Lodash sortBy

    Activity->>Apollo: Execute allEventsByProfile query onMounted
    Apollo->>Activity: Return events data
    Activity->>SortBy: Sort events based on timestamp
    Activity->>Activity: Filter events by string type (e.g., 'buy', 'sale')
Loading

Suggested reviewers

  • Jarsen136
  • hassnian
  • vikiival

Poem

I hopped through the code with a cheerful beat,
Fixing and refactoring with nimble feet.
Carousels twirl and queries gleam,
Data flows smooth like a running stream.
My rabbit heart cheers with every line,
Coding magic—so fluffy and divine! 🥕🐇
Hurray for clean code and adventures sublime!


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Free

📥 Commits

Reviewing files that changed from the base of the PR and between 522c314 and 7ecb084.

📒 Files selected for processing (18)
  • components/carousel/CarouselTypeGenerative.vue (1 hunks)
  • components/carousel/utils/useCarouselEvents.ts (5 hunks)
  • components/collection/utils/useCollectionDetails.ts (5 hunks)
  • components/identity/utils/useIdentity.ts (0 hunks)
  • components/identity/utils/useIdentityStats.ts (2 hunks)
  • components/landing/LandingPage.vue (3 hunks)
  • components/profile/ProfileActivitySummery.vue (1 hunks)
  • components/profile/activityTab/Activity.vue (2 hunks)
  • composables/useSearchNfts.ts (2 hunks)
  • plugins/apollo.client.ts (1 hunks)
  • queries/fragments/typed/collectionMeta.ts (1 hunks)
  • queries/subsquid/general/allEventsByProfile.ts (2 hunks)
  • queries/subsquid/general/collectionStatsById.ts (1 hunks)
  • queries/subsquid/general/nftListSoldByCollection.ts (2 hunks)
  • queries/subsquid/general/userStatsByAccount.ts (2 hunks)
  • types/index.ts (1 hunks)
  • utils/math.ts (1 hunks)
  • utils/sorting.ts (0 hunks)
💤 Files with no reviewable changes (2)
  • utils/sorting.ts
  • components/identity/utils/useIdentity.ts

🪧 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 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.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

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

netlify bot commented Mar 19, 2025

Deploy Preview for koda-canary ready!

Name Link
🔨 Latest commit 7ecb084
🔍 Latest deploy log https://app.netlify.com/sites/koda-canary/deploys/67dbd9907dc295000843ef8c
😎 Deploy Preview https://deploy-preview-11491--koda-canary.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@preschian preschian marked this pull request as ready for review March 19, 2025 09:50
@preschian preschian requested a review from a team as a code owner March 19, 2025 09:50
@preschian preschian requested review from vikiival and Jarsen136 and removed request for a team March 19, 2025 09:50
Copy link

cloudflare-workers-and-pages bot commented Mar 19, 2025

Deploying koda-art-prod with  Cloudflare Pages  Cloudflare Pages

Latest commit: 7ecb084
Status: ✅  Deploy successful!
Preview URL: https://29f6342c.kodaart-production.pages.dev
Branch Preview URL: https://refactor--asyncdata-already.kodaart-production.pages.dev

View logs

Copy link

@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

🧹 Nitpick comments (4)
components/landing/LandingPage.vue (1)

21-24: Ensure defensive checks for dropsAhp before accessing .length.
If getDrops fails or returns undefined, this might throw an error. Consider making a null-safe check or guaranteeing dropsAhp is always an array.

You might, for example:

-<LazyCarouselTypeGenerative
-  v-if="dropsAhp.length"
-  :collection-ids="dropsAhp"
/>
+<LazyCarouselTypeGenerative
+  v-if="dropsAhp?.length"
+  :collection-ids="dropsAhp"
/>
components/carousel/utils/useCarouselEvents.ts (1)

80-84: Potential race condition in data fetching

The where object used in the fetch call depends on reactive references (excludeNfts and excludeCollections), but the fetch is called only once when the function is first executed. If these values change after the initial fetch, the query won't be re-executed with the updated values.

Consider moving the fetch call inside a watchEffect to re-fetch when dependencies change:

- fetchLatestEvents(chain, type, where).then((result) => {
-   data.value = result.data
- })
+ watchEffect(async () => {
+   const currentWhere = createEventQuery(
+     type,
+     excludeNfts,
+     excludeCollections,
+     collectionIds,
+   )
+   const result = await fetchLatestEvents(chain, type, currentWhere)
+   data.value = result.data
+ })
components/collection/utils/useCollectionDetails.ts (2)

26-36: Consider adding error handling to fetchStats

The fetchStats function looks good but lacks error handling, which could lead to silent failures if the API request fails.

 const fetchStats = () => {
   $apolloClient.query({
     query: collectionStatsById,
     variables: variables.value,
     context: {
       endpoint: urlPrefix.value,
     },
-  }).then((res) => {
-    data.value = res.data
-  })
+  }).then((res) => {
+    data.value = res.data
+  }).catch((error) => {
+    console.error('Error fetching collection stats:', error)
+  })
 }

96-114: Inconsistent pattern with useCollectionSoldData

Unlike useCollectionDetails, the useCollectionSoldData function executes the query immediately without providing a dedicated function for re-fetching, and lacks error handling.

Consider refactoring to match the pattern used in useCollectionDetails:

 export function useCollectionSoldData({ address, collectionId }) {
   const data = ref<ResultOf<typeof nftListSoldByCollection>>()
 
   const { $apolloClient } = useNuxtApp()
   const { urlPrefix } = usePrefix()
 
-  $apolloClient.query({
-    query: nftListSoldByCollection,
-    variables: {
-      account: address,
-      limit: 3,
-      orderBy: 'price_DESC',
-      collectionId,
-    },
-    context: {
-      endpoint: urlPrefix.value,
-    },
-  }).then((res) => {
-    data.value = res.data
-  })
+  const fetchSoldData = () => {
+    $apolloClient.query({
+      query: nftListSoldByCollection,
+      variables: {
+        account: address,
+        limit: 3,
+        orderBy: 'price_DESC',
+        collectionId,
+      },
+      context: {
+        endpoint: urlPrefix.value,
+      },
+    }).then((res) => {
+      data.value = res.data
+    }).catch((error) => {
+      console.error('Error fetching sold NFT data:', error)
+    })
+  }
+
+  fetchSoldData()
 
-  return { nftEntities: computed(() => data.value?.nftEntities?.length ? data.value.nftEntities : []) }
+  return { 
+    nftEntities: computed(() => data.value?.nftEntities?.length ? data.value.nftEntities : []),
+    refetch: fetchSoldData
+  }
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 522c314 and 02481e5.

📒 Files selected for processing (18)
  • components/carousel/CarouselTypeGenerative.vue (1 hunks)
  • components/carousel/utils/useCarouselEvents.ts (5 hunks)
  • components/collection/utils/useCollectionDetails.ts (5 hunks)
  • components/identity/utils/useIdentity.ts (0 hunks)
  • components/identity/utils/useIdentityStats.ts (2 hunks)
  • components/landing/LandingPage.vue (3 hunks)
  • components/profile/ProfileActivitySummery.vue (1 hunks)
  • components/profile/activityTab/Activity.vue (2 hunks)
  • composables/useSearchNfts.ts (2 hunks)
  • plugins/apollo.client.ts (1 hunks)
  • queries/fragments/typed/collectionMeta.ts (1 hunks)
  • queries/subsquid/general/allEventsByProfile.ts (2 hunks)
  • queries/subsquid/general/collectionStatsById.ts (1 hunks)
  • queries/subsquid/general/nftListSoldByCollection.ts (2 hunks)
  • queries/subsquid/general/userStatsByAccount.ts (2 hunks)
  • types/index.ts (1 hunks)
  • utils/math.ts (1 hunks)
  • utils/sorting.ts (0 hunks)
💤 Files with no reviewable changes (2)
  • components/identity/utils/useIdentity.ts
  • utils/sorting.ts
🧰 Additional context used
🧬 Code Definitions (1)
queries/subsquid/general/nftListSoldByCollection.ts (1)
queries/fragments/typed/collectionMeta.ts (1) (1)
  • collectionMetaFragment (3-9)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: shard (1, 10)
  • GitHub Check: Cloudflare Pages: koda-art-prod
🔇 Additional comments (26)
queries/subsquid/general/userStatsByAccount.ts (1)

1-3: Improved query export structure using graphql client wrapper

The refactoring correctly wraps the GraphQL query with the graphql function imported from the client module, providing better type safety and a more consistent approach to query definitions across the codebase. This aligns with the PR objective of refactoring for better maintainability.

Also applies to: 41-41

queries/subsquid/general/allEventsByProfile.ts (1)

1-4: Well-structured query export with proper formatting

The implementation correctly wraps the GraphQL query with the graphql function from the client module, maintaining proper formatting with template literals. This standardized approach to query definitions enhances maintainability and type safety across the codebase.

Also applies to: 32-33

queries/fragments/typed/collectionMeta.ts (1)

1-9: Good implementation of reusable GraphQL fragment

The introduction of this GraphQL fragment is a positive addition that promotes code reuse and modularity. By extracting the collection metadata into a reusable fragment, the code reduces duplication and improves maintainability when this data needs to be used across multiple queries.

plugins/apollo.client.ts (1)

8-8: Good addition of fallback endpoint value

This change adds a necessary fallback mechanism that prevents potential runtime errors when the endpoint is not provided in the context. By defaulting to 'ahp' when endpoint is falsy, the code ensures that the Apollo client always has a valid GraphQL endpoint to connect to.

components/profile/ProfileActivitySummery.vue (1)

76-76: Ensure consistent data type handling.

Converting listedValue to a string is appropriate since the CommonTokenMoney component likely expects string input for proper rendering. This change improves type safety and prevents potential rendering issues with bigint values.

queries/subsquid/general/collectionStatsById.ts (1)

1-26: Well-structured GraphQL query for collection statistics.

The query is well organized and fetches the necessary data efficiently. It properly separates different types of NFTs (base, listed, sales) which allows for clear data processing on the client side.

components/landing/LandingPage.vue (1)

45-45: Import looks appropriate.
No issues detected with this import usage.

queries/subsquid/general/nftListSoldByCollection.ts (3)

1-4: Imports are clear and modular.
Transitioning to explicit ES imports is a recommended practice for clarity.


6-6: Exporting a default GraphQL query object is a clean approach.
No concerns here.


32-38: Embedding a fragments array is a structured strategy.
This approach nicely keeps your fragments grouped with the query for improved maintainability.

composables/useSearchNfts.ts (3)

1-2: Imports look correct.
No issues with referencing ResultOf or nftListWithSearch.


39-41: Immediate fetch is straightforward.
This ensures data is loaded quickly, though remember to handle any potential concurrency with overlapping requests if triggered multiple times.


45-45: Refetch alias is consistent.
No further comments; approach looks good.

components/carousel/CarouselTypeGenerative.vue (3)

4-4: Good conditional rendering improvement!

Adding this v-if condition prevents rendering the carousel when there's no data, which is a great UI improvement.


15-16: Improved data handling with proper collection filtering

This refactoring improves the carousel component by:

  1. Using the utility functions directly rather than relying on a custom hook
  2. Properly consolidating data from two different event sources
  3. Using unionBy to remove duplicates based on 'id'
  4. Ensuring proper sorting for display

The approach is more maintainable and allows for better control over the data flow.

Also applies to: 31-39


19-21: Good component design with props

Making the component accept collectionIds as a prop improves reusability and encapsulation. This allows parent components to control which collections should be displayed.

components/profile/activityTab/Activity.vue (1)

63-63: Good migration from enums to string literals

The refactoring from using InteractionEnum to string literals makes the code easier to understand and maintain. The mapping object now clearly shows which interaction types correspond to which filter categories.

The updated check for 'BUY' interaction in the filter logic is also correct.

Also applies to: 102-106, 109-112

components/carousel/utils/useCarouselEvents.ts (1)

54-54: Good function exports and type safety improvements

Making useEvents and sortNfts exported functions improves modularity and reusability across the codebase. The function can now be imported in other components, as seen in CarouselTypeGenerative.vue.

Adding proper type annotation to the data ref with ResultOf<typeof latestEvents> improves type safety and developer experience.

Also applies to: 81-81, 152-152

components/collection/utils/useCollectionDetails.ts (8)

2-3: Import structure improved with proper type imports

The imports have been updated to include proper typing with ResultOf from gql.tada, which provides better type safety for GraphQL queries. The new imports for collection stats and sold NFT list queries support the refactored data fetching approach.

Also applies to: 5-9


20-22: Good setup of Apollo client and URL prefix

Properly extracting the Apollo client and URL prefix from the Nuxt app to support direct query execution.


23-23: Type safety improvement with ResultOf

Using ResultOf<typeof collectionStatsById> provides precise typing that reflects the structure of the data returned by the query, which improves type safety and IDE autocompletion.


38-38: Initial data fetching

Immediately calling fetchStats() ensures data is loaded when the component mounts, which is appropriate for this use case.


51-51: Improved null safety with nullish coalescing

Good use of the nullish coalescing operator (??) to handle potentially undefined values for maxSupply and item prices, making the code more robust.

Also applies to: 56-56


70-70: Reactive data fetching with watch

Setting up a watcher to call fetchStats when variables change ensures the data stays in sync with the query parameters.


74-74: Updated refetch method

Updating the refetch reference to use the new fetchStats function aligns with the refactored data-fetching strategy.


116-116: Good use of computed property with null checking

The computed property properly handles cases where nftEntities might be null, undefined, or empty by returning an empty array as a fallback.

@vikiival vikiival requested a review from Copilot March 19, 2025 12:48
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR addresses the duplicate items issue on the carousel landing page by refactoring several GraphQL queries and related components while also updating type definitions and query handling. Key changes include the introduction of new GraphQL queries using Apollo Client, modifications to type definitions (e.g. changing blockNumber to allow null), and refactoring of carousel event handling and sorting.

Reviewed Changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
queries/subsquid/general/collectionStatsById.ts New query for collection stats
composables/useSearchNfts.ts Replaced useGraphql with Apollo Client query
components/collection/utils/useCollectionDetails.ts Updated query fetching & data processing
queries/fragments/typed/collectionMeta.ts Added new fragment for collection metadata
components/identity/utils/useIdentityStats.ts Updated user stats query with Apollo Client
plugins/apollo.client.ts Added fallback endpoint for GraphQL client
queries/subsquid/general/allEventsByProfile.ts Removed unnecessary __typename fields
queries/subsquid/general/userStatsByAccount.ts Updated user stats query definition
queries/subsquid/general/nftListSoldByCollection.ts Modernized query fragment imports
types/index.ts Updated blockNumber type definition
components/carousel/utils/useCarouselEvents.ts Refactored carousel event fetching and sorting
utils/math.ts Adjusted getVolume function signature
utils/sorting.ts Removed unused sorting function
components/carousel/CarouselTypeGenerative.vue Updated carousel component to use new event fetching
components/identity/utils/useIdentity.ts Removed unused identity sold data helper
components/landing/LandingPage.vue Updated landing page to conditionally display carousel
components/profile/ProfileActivitySummery.vue Converted listedValue to string for display
components/profile/activityTab/Activity.vue Updated profile activities handling with Apollo Client
Comments suppressed due to low confidence (1)

types/index.ts:127

  • Changing the type of blockNumber from 'string | number' to 'string | null' may affect parts of the code that assume a number; please confirm that all references handle a possible null value.
blockNumber: string | null

Copy link

@preschian preschian requested a review from hassnian March 25, 2025 04:38
@preschian preschian added this pull request to the merge queue Mar 26, 2025
Merged via the queue into main with commit 1a47def Mar 26, 2025
27 of 28 checks passed
@preschian preschian deleted the refactor--asyncdata-already-mounted-part-3 branch March 26, 2025 13:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants