Skip to content

Commit

Permalink
feed refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
taronaleksanian committed Sep 12, 2024
1 parent b2ceae2 commit af66fd5
Show file tree
Hide file tree
Showing 30 changed files with 626 additions and 208 deletions.
4 changes: 2 additions & 2 deletions apps/vite/src/routes/feed/index.lazy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ export const Route = createLazyFileRoute('/feed/')({

export default function FeedNav() {
return (
<AuthWrapper>
<>
<FeedScreen />
</AuthWrapper>
</>
);
}
1 change: 1 addition & 0 deletions packages/app/hooks/pagination/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './useInfinitePagination';
58 changes: 58 additions & 0 deletions packages/app/hooks/pagination/useInfinitePagination.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { type Dispatch, type SetStateAction, useEffect, useRef } from 'react';

const DEFAULT_LIMIT = 20;

export const getPaginationInitialParams = (defaultPage = 1) => ({
limit: DEFAULT_LIMIT,
offset: getOffset(defaultPage, DEFAULT_LIMIT),
});

export interface PaginationParams {
limit: number;
offset: number;
}

interface PaginationOptions {
nextPage?: number;
enabled?: boolean;
defaultPage?: number;
}

export const useInfinitePagination = (
fetchFunction: () => void,
paginationParams: PaginationParams,
setPaginationParams: Dispatch<SetStateAction<PaginationParams>>,
options: PaginationOptions = {},
) => {
const initialRender = useRef(false);
const { nextPage, enabled = true } = options;

const fetchNextPage = () => {
setPaginationParams((prev) => ({
...prev,
offset: nextPage,
}));
};

useEffect(() => {
const run = () => {
if (!initialRender.current) {
initialRender.current = true;
return;
}
if (!enabled) {
return;
}

fetchFunction();
};

run();
}, [paginationParams.limit, paginationParams.offset, enabled]);

return { fetchNextPage };
};

function getOffset(page: number, limit: number) {
return (page - 1) * limit;
}
11 changes: 3 additions & 8 deletions packages/app/modules/feed/components/FeedCard/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down
5 changes: 3 additions & 2 deletions packages/app/modules/feed/components/FeedSearchFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,8 @@ export const FeedSearchFilter = ({
</RSwitch>*/}
</RStack>
)}
<RStack
{/* DISABLE SORTS */}
{/* <RStack
style={{
flexDirection: 'row',
alignItems: 'center',
Expand All @@ -190,7 +191,7 @@ export const FeedSearchFilter = ({
placeholder={queryString}
/>
</View>
</RStack>
</RStack> */}
{(feedType === 'userPacks' || feedType === 'userTrips') && (
<RButton
style={{ marginLeft: 'auto', marginTop: 8 }}
Expand Down
3 changes: 2 additions & 1 deletion packages/app/modules/feed/hooks/useAddFavorite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ export function useAddFavorite() {
onSuccess: () => {
// 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);
},
});
Expand Down
37 changes: 29 additions & 8 deletions packages/app/modules/feed/hooks/useFeed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ interface UseFeedResult {
isLoading: boolean;
refetch?: () => void;
setPage?: (page: number) => void;
hasMore?: boolean;
fetchNextPage?: (isInitialFetch?: boolean) => Promise<void>;
nextPage?: number | boolean;
fetchNextPage?: () => void;
}

export const useFeed = ({
Expand All @@ -18,25 +18,46 @@ export const useFeed = ({
feedType = 'public',
selectedTypes = { pack: true, trip: true },
id,
searchQuery,
}: Partial<{
queryString: string;
ownerId: string;
feedType: string;
selectedTypes: Object;
searchQuery?: string;
id: string;
}> = {}): UseFeedResult => {
const publicFeed = usePublicFeed(
queryString,
searchQuery,
selectedTypes,
feedType === 'public',
);
const userPacks = useUserPacks(
ownerId || undefined,
{ searchTerm: searchQuery },
queryString,
feedType === 'userPacks',
);
const userTrips = useUserTrips(
ownerId || undefined,
feedType === 'userTrips',
);
const similarPacks = useSimilarPacks(id, feedType === 'similarPacks');
const similarItems = useSimilarItems(id, feedType === 'similarItems');

switch (feedType) {
case 'public':
return usePublicFeed(queryString, selectedTypes); // Use the typed return from usePublicFeed
return publicFeed;
case 'userPacks':
return useUserPacks(ownerId || undefined, queryString);
return userPacks;
case 'userTrips':
return useUserTrips(ownerId || undefined);
return userTrips;
case 'similarPacks':
return useSimilarPacks(id);
return similarPacks;
case 'similarItems':
return useSimilarItems(id);
return similarItems;
default:
return { data: null, isLoading: true };
}
};
};
134 changes: 43 additions & 91 deletions packages/app/modules/feed/hooks/usePublicFeed.ts
Original file line number Diff line number Diff line change
@@ -1,101 +1,53 @@
import { queryTrpc } from 'app/trpc';
import { useState, useEffect } from 'react';

type DataType = {
type: string;
id: string;
duration: string;
name: string;
description: string;
createdAt: string | null;
updatedAt: string | null;
pack_id: string | null;
owner_id: string | null;
is_public: boolean | null;
}[];

type OptionalDataType = DataType[];
import {
getPaginationInitialParams,
type PaginationParams,
useInfinitePagination,
} from 'app/hooks/pagination';
import { useState } from 'react';

export const usePublicFeed = (
queryString: string,
queryBy,
searchQuery: string,
selectedTypes,
initialPage = 1,
initialLimit = 4
enabled = false,
) => {
const [page, setPage] = useState(initialPage);
const [data, setData] = useState<OptionalDataType>([]);
const [hasMore, setHasMore] = useState(true);
const [isLoading, setIsLoading] = useState(false);
const [isFetchingNextPage, setIsFetchingNextPage] = useState(false);

// Fetch public packs using the useQuery hook
const {
data: publicPacksData,
isLoading: isPacksLoading,
refetch: refetchPacks,
} = queryTrpc.getPublicPacks.useQuery(
{ queryBy: queryString ?? 'Favorite', page, limit: initialLimit },
{ keepPreviousData: true, enabled: selectedTypes.pack }
);

// Fetch public trips using the useQuery hook
const {
data: publicTripsData,
isLoading: isTripsLoading,
refetch: refetchTrips,
} = queryTrpc.getPublicTripsRoute.useQuery(
{ queryBy: queryString ?? 'Favorite' },
{ enabled: selectedTypes.trip && publicPacksData?.length > 0 }
const [allData, setAllData] = useState([]);
const [pagination, setPagination] = useState<PaginationParams>(
getPaginationInitialParams(),
);

// Ensure that fetching logic behaves consistently
useEffect(() => {
const processFetchedData = () => {
if (!isPacksLoading && !isTripsLoading && (publicPacksData || publicTripsData)) {
let newData: OptionalDataType = [];

// Fetch and append packs
if (selectedTypes.pack && publicPacksData) {
newData = [...newData, ...publicPacksData.map((item) => ({ ...item, type: 'pack' }))];
}

// Fetch and append trips
if (selectedTypes.trip && publicTripsData) {
newData = [...newData, ...publicTripsData.map((item) => ({ ...item, type: 'trip' }))];
const { data, isLoading, refetch } = queryTrpc.getPublicFeed.useQuery(
{ queryBy: queryBy ?? 'Favorites', pagination, searchTerm: searchQuery },
{
enabled,
refetchOnWindowFocus: false,
onSuccess: (newData) => {
if (newData?.data) {
setAllData((prevData) => {
if (pagination.offset === 0) {
return newData.data;
}

return [...prevData, ...newData.data];
});
}
},
onError: (error) => console.error('Error fetching public packs:', error),
},
);
const { fetchNextPage } = useInfinitePagination(
refetch,
pagination,
setPagination,
{ nextPage: data?.nextOffset, enabled },
);

// Update data in state
setData((prevData) => {
return page === initialPage ? newData : [...prevData, ...newData]; // Append for subsequent pages
});

// Set `hasMore` based on the data fetched
setHasMore(newData.length === initialLimit);

// Reset loading states
setIsLoading(false);
setIsFetchingNextPage(false);
}
};

processFetchedData();
}, [publicPacksData, publicTripsData, page, selectedTypes]);

// Fetch the next page of data
const fetchNextPage = async () => {
if (hasMore && !isLoading && !isFetchingNextPage) {
setIsFetchingNextPage(true);
setPage((prevPage) => prevPage + 1); // Increment the page before fetching new data

// Fetch packs and trips for the next page
await refetchPacks();
if (selectedTypes.trip) {
await refetchTrips();
}

setIsFetchingNextPage(false); // Reset fetching state after data fetch
}
return {
data: allData,
isLoading,
refetch,
fetchNextPage,
nextPage: data?.nextOffset || false,
error: null,
};

return { data, isLoading, hasMore, fetchNextPage, refetch: refetchPacks };
};
3 changes: 2 additions & 1 deletion packages/app/modules/feed/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading

0 comments on commit af66fd5

Please sign in to comment.