From 92610420d24150ed376f7bb4a3d5074a2b18d722 Mon Sep 17 00:00:00 2001 From: pinocchio-life-like Date: Mon, 16 Sep 2024 12:40:16 +0300 Subject: [PATCH] checkout tarons commits --- .../modules/feed/components/FeedCard/utils.ts | 11 +-- .../feed/components/FeedSearchFilter.tsx | 5 +- .../app/modules/feed/hooks/useAddFavorite.ts | 3 +- packages/app/modules/feed/hooks/useFeed.ts | 3 +- .../app/modules/feed/hooks/usePublicFeed.ts | 91 +++++++++++-------- packages/app/modules/feed/model.ts | 3 +- .../app/modules/item/hooks/useSimilarItems.ts | 3 +- .../components/PackCard/PackPrimaryCard.tsx | 19 ++-- .../app/modules/pack/hooks/useSimilarPacks.ts | 3 +- .../app/modules/trip/hooks/useUserTrips.ts | 7 +- packages/app/modules/user/hooks/useProfile.ts | 2 +- 11 files changed, 87 insertions(+), 63 deletions(-) diff --git a/packages/app/modules/feed/components/FeedCard/utils.ts b/packages/app/modules/feed/components/FeedCard/utils.ts index e4bdab926..34b4d1097 100644 --- a/packages/app/modules/feed/components/FeedCard/utils.ts +++ b/packages/app/modules/feed/components/FeedCard/utils.ts @@ -29,15 +29,10 @@ export const feedItemPackCardConverter: Converter< ? roundNumber(input.similarityScore) : undefined, weight: input.total_weight, - quantity: - input?.itemPacks?.reduce( - (accumulator, currentValue) => - accumulator + currentValue?.item?.quantity, - 0, - ) ?? 0, + quantity: input.quantity, }, - isUserFavorite: input?.userFavoritePacks?.some( - (obj) => obj?.userId === currentUserId, + isUserFavorite: input?.userFavoritePacks?.some?.( + (userId) => userId === currentUserId, ), favoriteCount: input.favorites_count, }; diff --git a/packages/app/modules/feed/components/FeedSearchFilter.tsx b/packages/app/modules/feed/components/FeedSearchFilter.tsx index 555d337c0..318e34d4b 100644 --- a/packages/app/modules/feed/components/FeedSearchFilter.tsx +++ b/packages/app/modules/feed/components/FeedSearchFilter.tsx @@ -164,7 +164,8 @@ export const FeedSearchFilter = ({ */} )} - - + */} {(feedType === 'userPacks' || feedType === 'userTrips') && ( { // Invalidate and refetch. Update to be more specific utils.getUserFavorites.invalidate(); - utils.getPublicPacks.invalidate(); + utils.getUserPacksFeed.invalidate(); + utils.getPublicFeed.invalidate(); utils.getPacks.invalidate(userId ? { ownerId: userId } : undefined); }, }); diff --git a/packages/app/modules/feed/hooks/useFeed.ts b/packages/app/modules/feed/hooks/useFeed.ts index 9678d5749..56c20d57d 100644 --- a/packages/app/modules/feed/hooks/useFeed.ts +++ b/packages/app/modules/feed/hooks/useFeed.ts @@ -25,10 +25,9 @@ export const useFeed = ({ selectedTypes: Object; id: string; }> = {}): UseFeedResult => { - console.log("querystring", queryString) switch (feedType) { case 'public': - return usePublicFeed(queryString, selectedTypes); // Use the typed return from usePublicFeed + return usePublicFeed(queryString, selectedTypes); case 'userPacks': return useUserPacks(ownerId || undefined, queryString); case 'userTrips': diff --git a/packages/app/modules/feed/hooks/usePublicFeed.ts b/packages/app/modules/feed/hooks/usePublicFeed.ts index 0e7361317..af9e968d2 100644 --- a/packages/app/modules/feed/hooks/usePublicFeed.ts +++ b/packages/app/modules/feed/hooks/usePublicFeed.ts @@ -1,5 +1,6 @@ import { queryTrpc } from 'app/trpc'; -import { useState, useEffect, useCallback } from 'react'; +import { useState, useEffect, useCallback, useMemo } from 'react'; +import { debounce } from 'lodash'; type DataType = { type: string; @@ -20,7 +21,7 @@ export const usePublicFeed = ( queryString: string, selectedTypes, initialPage = 1, - initialLimit = 10 + initialLimit = 10 ) => { const [page, setPage] = useState(initialPage); const [data, setData] = useState([]); @@ -48,51 +49,69 @@ export const usePublicFeed = ( { enabled: selectedTypes.trip } ); - useEffect(() => { - const processFetchedData = () => { - // if (!isPacksLoading && !isTripsLoading && (publicPacksData || publicTripsData)) { - if (!isPacksLoading && (publicPacksData || publicTripsData)) { - let newData: OptionalDataType = []; + // Process fetched data + const processedData = useMemo(() => { + let newData: OptionalDataType = []; - // Add packs to the data - if (selectedTypes.pack && publicPacksData) { - newData = [...newData, ...publicPacksData.map((item) => ({ ...item, type: 'pack' }))]; - } + if (selectedTypes.pack && publicPacksData) { + newData = [...newData, ...publicPacksData.map((item) => ({ ...item, type: 'pack' }))]; + } - // Add trips to the data - if (selectedTypes.trip && publicTripsData) { - newData = [...newData, ...publicTripsData.map((item) => ({ ...item, type: 'trip' }))]; - } + if (selectedTypes.trip && publicTripsData) { + newData = [...newData, ...publicTripsData.map((item) => ({ ...item, type: 'trip' }))]; + } - // Append or reset data based on the current page - setData((prevData) => (page === initialPage ? newData : [...prevData, ...newData])); + return newData; + }, [publicPacksData, publicTripsData, selectedTypes]); - // Check if there is more data to fetch (if the fetched data length is less than the limit, there's no more data) + // Use effect to update data and loading states + useEffect(() => { + const processFetchedData = () => { + // if (!isPacksLoading && !isTripsLoading && processedData.length > 0) { + if (!isPacksLoading && processedData.length > 0) { + // Only update if data is different to avoid unnecessary re-renders + setData((prevData) => { + const newData = page === initialPage ? processedData : [...prevData, ...processedData]; + return JSON.stringify(newData) !== JSON.stringify(prevData) ? newData : prevData; + }); + + // Check if there is more data to fetch const hasMorePacks = publicPacksData && publicPacksData.length === initialLimit; const hasMoreTrips = publicTripsData && publicTripsData.length === initialLimit; - - setHasMore(hasMorePacks || hasMoreTrips); // Properly set `hasMore` - - setIsFetchingNextPage(false); - setIsLoading(false); + setHasMore(hasMorePacks || hasMoreTrips); } + + setIsFetchingNextPage(false); + setIsLoading(false); }; processFetchedData(); - }, [publicPacksData, publicTripsData, isPacksLoading, isTripsLoading, page, selectedTypes]); - - // Fetch next page of data - const fetchNextPage = useCallback(async () => { - if (hasMore && !isFetchingNextPage && !isLoading) { - setIsFetchingNextPage(true); - setPage((prevPage) => prevPage + 1); - - await refetchPacks(); - if (selectedTypes.trip) { - await refetchTrips(); + }, [ + publicPacksData, + publicTripsData, + isPacksLoading, + isTripsLoading, + page, + processedData, + initialPage, + initialLimit, + ]); + + // Debounced fetchNextPage to prevent rapid triggers + const fetchNextPage = useCallback( + debounce(async () => { + if (hasMore && !isFetchingNextPage && !isLoading) { + setIsFetchingNextPage(true); + setPage((prevPage) => prevPage + 1); + + await refetchPacks(); + if (selectedTypes.trip) { + await refetchTrips(); + } } - } - }, [hasMore, isFetchingNextPage, isLoading, refetchPacks, refetchTrips, selectedTypes]); + }, 300), // Debounce with a delay of 300ms + [hasMore, isFetchingNextPage, isLoading, refetchPacks, refetchTrips, selectedTypes] + ); return { data, isLoading, hasMore, fetchNextPage, refetch: refetchPacks, isFetchingNextPage }; }; diff --git a/packages/app/modules/feed/model.ts b/packages/app/modules/feed/model.ts index be9222733..076634bf8 100644 --- a/packages/app/modules/feed/model.ts +++ b/packages/app/modules/feed/model.ts @@ -16,7 +16,8 @@ export interface FeedItem { favorited_by: Array<{ id: string; }>; - userFavoritePacks?: Array<{ userId: string }>; + quantity?: number; + userFavoritePacks?: string[]; favorites_count: number; owner_id: string | { id: string }; destination: string; diff --git a/packages/app/modules/item/hooks/useSimilarItems.ts b/packages/app/modules/item/hooks/useSimilarItems.ts index fefe2f753..5a6074d81 100644 --- a/packages/app/modules/item/hooks/useSimilarItems.ts +++ b/packages/app/modules/item/hooks/useSimilarItems.ts @@ -1,10 +1,11 @@ import { queryTrpc } from 'app/trpc'; -export const useSimilarItems = (id: string) => { +export const useSimilarItems = (id: string, enabled = true) => { const { data, error, isLoading, refetch } = queryTrpc.getSimilarItems.useQuery( { id, limit: 10 }, { + enabled, refetchOnWindowFocus: true, }, ); diff --git a/packages/app/modules/pack/components/PackCard/PackPrimaryCard.tsx b/packages/app/modules/pack/components/PackCard/PackPrimaryCard.tsx index 4c624cded..3494e7bdd 100644 --- a/packages/app/modules/pack/components/PackCard/PackPrimaryCard.tsx +++ b/packages/app/modules/pack/components/PackCard/PackPrimaryCard.tsx @@ -10,19 +10,22 @@ import { type PackDetails } from 'app/modules/pack/model'; import { DuplicateIcon } from 'app/assets/icons'; import { useItemWeightUnit } from 'app/modules/item'; import { convertWeight } from 'app/utils/convertWeight'; +import { roundNumber } from 'app/utils'; interface PackCardProps extends FeedCardProps {} export const PackPrimaryCard: FC = (props) => { const [weightUnit] = useItemWeightUnit(); - const packDetails = Object.entries(props.details).map(([key, value]) => ({ - key, - label: key, - value: - key === 'weight' - ? `${convertWeight(value, 'g', weightUnit)} ${weightUnit}` - : value, - })); + const packDetails = Object.entries(props.details) + .filter(([key]) => key !== 'similarityScore') + .map(([key, value]) => ({ + key, + label: key, + value: + key === 'weight' + ? `${roundNumber(convertWeight(value, 'kg', weightUnit))} ${weightUnit}` + : value, + })); return ( { +export const useSimilarPacks = (id: string, enabled: boolean = true) => { const { data, error, isLoading, refetch } = queryTrpc.getSimilarPacks.useQuery( { id, limit: 10 }, { + enabled, refetchOnWindowFocus: true, }, ); diff --git a/packages/app/modules/trip/hooks/useUserTrips.ts b/packages/app/modules/trip/hooks/useUserTrips.ts index ca731a001..5f20dd98e 100644 --- a/packages/app/modules/trip/hooks/useUserTrips.ts +++ b/packages/app/modules/trip/hooks/useUserTrips.ts @@ -1,8 +1,11 @@ import { queryTrpc } from 'app/trpc'; -export const useUserTrips = (ownerId: string | undefined) => { +export const useUserTrips = ( + ownerId: string | undefined, + queryEnabled: boolean = true, +) => { // If ownerId is not provided, don’t run the query. - const enabled = !!ownerId; + const enabled = queryEnabled && !!ownerId; // Leverage the query hook provided by tRPC const { data, error, isLoading, refetch } = queryTrpc.getTrips.useQuery( diff --git a/packages/app/modules/user/hooks/useProfile.ts b/packages/app/modules/user/hooks/useProfile.ts index 88057499e..d09fe3722 100644 --- a/packages/app/modules/user/hooks/useProfile.ts +++ b/packages/app/modules/user/hooks/useProfile.ts @@ -14,7 +14,7 @@ export const useProfile = (id = null) => { data: allPacks, isLoading: allPacksLoading, error: allPacksError, - } = useUserPacks(userId); // TODO: Add enabled as parameter + } = useUserPacks(userId, { isPublic: true }, '', true); // TODO: Add enabled as parameter const { data: allTrips,