This repository has no description
semble
/
src
/
webapp
/
features
/
cards
/
containers
/
cardsContainerContent
/
CardsContainerContent.tsx
3.6 kB
116 lines
1import { CardSortField, SortOrder, UrlType } from '@semble/types';
2import CardsContainerSkeleton from '../cardsContainer/Skeleton.CardsContainer';
3import CardsContainerError from '../cardsContainer/Error.CardsContainer';
4import { Container, Grid } from '@mantine/core';
5import ProfileEmptyTab from '@/features/profile/components/profileEmptyTab/ProfileEmptyTab';
6import InfiniteScroll from '@/components/contentDisplay/infiniteScroll/InfiniteScroll';
7import UrlCard from '../../components/urlCard/UrlCard';
8import useCards from '../../lib/queries/useCards';
9import { useNavbarContext } from '@/providers/navbar';
10import { FaRegNoteSticky } from 'react-icons/fa6';
11import { useUserSettings } from '@/features/settings/lib/queries/useUserSettings';
12import { useSearchParams, usePathname } from 'next/navigation';
13import { CardSaveSource } from '@/features/analytics/types';
14
15interface Props {
16 handle: string;
17}
18
19const sortOrderMap: Record<CardSortField, SortOrder> = {
20 [CardSortField.UPDATED_AT]: SortOrder.DESC,
21 [CardSortField.CREATED_AT]: SortOrder.ASC,
22 [CardSortField.LIBRARY_COUNT]: SortOrder.DESC,
23};
24
25export default function CardsContainerContent(props: Props) {
26 const pathname = usePathname();
27 const { desktopOpened } = useNavbarContext();
28 const { settings } = useUserSettings();
29
30 const searchParams = useSearchParams();
31 const selectedUrlType = searchParams.get('type') as UrlType;
32
33 const sortBy =
34 (searchParams.get('sort') as CardSortField) ?? CardSortField.UPDATED_AT;
35
36 const {
37 data,
38 error,
39 fetchNextPage,
40 hasNextPage,
41 isFetchingNextPage,
42 isPending,
43 } = useCards({
44 didOrHandle: props.handle,
45 sortBy: sortBy,
46 sortOrder: sortOrderMap[sortBy],
47 urlType: selectedUrlType,
48 });
49
50 const allCards = data?.pages.flatMap((page) => page.cards ?? []) ?? [];
51
52 if (isPending) {
53 return <CardsContainerSkeleton />;
54 }
55
56 if (error) {
57 return <CardsContainerError />;
58 }
59
60 if (allCards.length === 0) {
61 return (
62 <Container px="xs" py={'xl'} size="xl">
63 <ProfileEmptyTab
64 message={selectedUrlType ? `No ${selectedUrlType} cards` : 'No cards'}
65 icon={FaRegNoteSticky}
66 />
67 </Container>
68 );
69 }
70
71 return (
72 <InfiniteScroll
73 dataLength={allCards.length}
74 hasMore={!!hasNextPage}
75 isInitialLoading={isPending}
76 isLoading={isFetchingNextPage}
77 loadMore={fetchNextPage}
78 >
79 <Grid gutter="xs">
80 {allCards.map((card) => (
81 <Grid.Col
82 key={card.id}
83 span={{
84 base: 12,
85 xs: settings.cardView !== 'grid' ? 12 : desktopOpened ? 12 : 6,
86 sm: settings.cardView !== 'grid' ? 12 : desktopOpened ? 6 : 4,
87 md: settings.cardView !== 'grid' ? 12 : 4,
88 lg: settings.cardView !== 'grid' ? 12 : 3,
89 }}
90 >
91 <UrlCard
92 id={card.id}
93 url={card.url}
94 uri={card.uri}
95 cardContent={card.cardContent}
96 note={card.note}
97 authorHandle={props.handle}
98 cardAuthor={card.author}
99 urlLibraryCount={card.urlLibraryCount}
100 urlIsInLibrary={card.urlInLibrary}
101 viaCardId={card.id}
102 analyticsContext={{
103 saveSource: CardSaveSource.PROFILE,
104 activeFilters: {
105 urlType: selectedUrlType,
106 sort: sortBy,
107 },
108 pagePath: pathname,
109 }}
110 />
111 </Grid.Col>
112 ))}
113 </Grid>
114 </InfiniteScroll>
115 );
116}