This repository has no description
semble
/
src
/
webapp
/
features
/
collections
/
containers
/
collectionContainer
/
CollectionContainer.tsx
4.8 kB
172 lines
1'use client';
2
3import {
4 Anchor,
5 Box,
6 Button,
7 Container,
8 Grid,
9 Group,
10 Stack,
11 Text,
12 Title,
13 Center,
14 Avatar,
15} from '@mantine/core';
16import useCollection from '../../lib/queries/useCollection';
17import UrlCard from '@/features/cards/components/urlCard/UrlCard';
18import Link from 'next/link';
19import { useState } from 'react';
20import { FiPlus } from 'react-icons/fi';
21import AddCardDrawer from '@/features/cards/components/addCardDrawer/AddCardDrawer';
22import CollectionActions from '../../components/collectionActions/CollectionActions';
23import CollectionContainerError from './Error.CollectionContainer';
24import CollectionContainerSkeleton from './Skeleton.CollectionContainer';
25
26interface Props {
27 rkey: string;
28 handle: string;
29}
30
31export default function CollectionContainer(props: Props) {
32 const {
33 data,
34 isPending,
35 error,
36 fetchNextPage,
37 hasNextPage,
38 isFetchingNextPage,
39 } = useCollection({ rkey: props.rkey, handle: props.handle });
40
41 const [showAddDrawer, setShowAddDrawer] = useState(false);
42
43 if (isPending) {
44 return <CollectionContainerSkeleton />;
45 }
46
47 if (error) {
48 return <CollectionContainerError />;
49 }
50
51 const firstPage = data.pages[0];
52 const allCards = data.pages.flatMap((page) => page.urlCards ?? []);
53
54 return (
55 <Container p="xs" size="xl">
56 <Stack justify="flex-start">
57 <Group justify="space-between" align="start">
58 <Stack gap={0}>
59 <Text fw={700} c="grape">
60 Collection
61 </Text>
62 <Title order={1}>{firstPage.name}</Title>
63 {firstPage.description && (
64 <Text c="gray" mt="lg">
65 {firstPage.description}
66 </Text>
67 )}
68 </Stack>
69
70 <Group gap={'xs'}>
71 <Text fw={600} c="gray.7">
72 By
73 </Text>
74 <Group gap={5}>
75 <Avatar
76 size={'sm'}
77 component={Link}
78 href={`/profile/${firstPage.author.handle}`}
79 src={firstPage.author.avatarUrl}
80 alt={`${firstPage.author.name}'s' avatar`}
81 />
82 <Anchor
83 component={Link}
84 href={`/profile/${firstPage.author.handle}`}
85 fw={700}
86 c="blue"
87 >
88 {firstPage.author.name}
89 </Anchor>
90 </Group>
91 </Group>
92 </Group>
93
94 <Group justify="end">
95 <CollectionActions
96 id={firstPage.id}
97 rkey={props.rkey}
98 name={firstPage.name}
99 description={firstPage.description}
100 authorHandle={firstPage.author.handle}
101 />
102 </Group>
103
104 {allCards.length > 0 ? (
105 <>
106 <Grid gutter="md">
107 {allCards.map((card) => (
108 <Grid.Col
109 key={card.id}
110 span={{ base: 12, xs: 6, sm: 4, lg: 3 }}
111 >
112 <UrlCard
113 id={card.id}
114 url={card.url}
115 cardContent={card.cardContent}
116 authorHandle={firstPage.author.handle}
117 cardAuthor={firstPage.author}
118 note={card.note}
119 urlLibraryCount={card.urlLibraryCount}
120 urlIsInLibrary={card.urlInLibrary}
121 currentCollection={firstPage}
122 />
123 </Grid.Col>
124 ))}
125 </Grid>
126
127 {hasNextPage && (
128 <Center>
129 <Button
130 mt="md"
131 variant="light"
132 color="gray"
133 onClick={() => fetchNextPage()}
134 loading={isFetchingNextPage}
135 >
136 {isFetchingNextPage ? 'Loading more...' : 'Load More'}
137 </Button>
138 </Center>
139 )}
140 </>
141 ) : (
142 <Stack align="center" gap="xs">
143 <Text fz="h3" fw={600} c="gray">
144 No cards
145 </Text>
146 <Button
147 variant="light"
148 color="gray"
149 size="md"
150 rightSection={<FiPlus size={22} />}
151 onClick={() => setShowAddDrawer(true)}
152 >
153 Add your first card
154 </Button>
155 </Stack>
156 )}
157 </Stack>
158
159 <Box>
160 <AddCardDrawer
161 isOpen={showAddDrawer}
162 onClose={() => setShowAddDrawer(false)}
163 selectedCollection={{
164 id: firstPage.id,
165 name: firstPage.name,
166 cardCount: allCards.length,
167 }}
168 />
169 </Box>
170 </Container>
171 );
172}