This repository has no description
6.9 kB
256 lines
1'use client';
2
3import CollectionCard from '@/features/collections/components/collectionCard/CollectionCard';
4import CollectionCardSkeleton from '@/features/collections/components/collectionCard/Skeleton.CollectionCard';
5import CreateCollectionDrawer from '@/features/collections/components/createCollectionDrawer/CreateCollectionDrawer';
6import useMyCollections from '@/features/collections/lib/queries/useMyCollections';
7import useOpenCollectionsWithContributor from '@/features/collections/lib/queries/useOpenCollectionsWithContributor';
8import useFollowingCollections from '@/features/follows/lib/queries/useFollowingCollections';
9import useMyProfile from '@/features/profile/lib/queries/useMyProfile';
10import {
11 Stack,
12 Button,
13 Text,
14 SimpleGrid,
15 Group,
16 Title,
17 ActionIcon,
18} from '@mantine/core';
19import { Suspense, useState } from 'react';
20import { BiCollection } from 'react-icons/bi';
21import { FiPlus } from 'react-icons/fi';
22import { useUserSettings } from '@/features/settings/lib/queries/useUserSettings';
23import { LinkButton } from '@/components/link/MantineLink';
24
25type CollectionFilter = 'mine' | 'following' | 'contributed';
26
27function CollectionsListSkeleton() {
28 return (
29 <SimpleGrid cols={{ base: 1, sm: 2, lg: 4 }} spacing="xs">
30 {Array.from({ length: 4 }).map((_, i) => (
31 <CollectionCardSkeleton key={i} />
32 ))}
33 </SimpleGrid>
34 );
35}
36
37function MyCollectionsList({
38 onCreateCollection,
39 settings,
40}: {
41 onCreateCollection: () => void;
42 settings: ReturnType<typeof useUserSettings>['settings'];
43}) {
44 const { data: collectionsData } = useMyCollections({ limit: 4 });
45 const collections =
46 collectionsData.pages.flatMap((page) => page.collections) ?? [];
47
48 if (collections.length === 0) {
49 return (
50 <Stack align="center" gap="xs">
51 <Text fz="h3" fw={600} c="gray">
52 No collections
53 </Text>
54 <Button
55 onClick={onCreateCollection}
56 variant="light"
57 color="gray"
58 size="md"
59 rightSection={<FiPlus size={22} />}
60 >
61 Create your first collection
62 </Button>
63 </Stack>
64 );
65 }
66
67 return (
68 <SimpleGrid
69 cols={
70 settings.collectionView !== 'grid'
71 ? { base: 1 }
72 : { base: 1, sm: 2, lg: 4 }
73 }
74 spacing="xs"
75 >
76 {collections.map((collection) => (
77 <CollectionCard key={collection.id} collection={collection} />
78 ))}
79 </SimpleGrid>
80 );
81}
82
83function FollowingCollectionsList({
84 identifier,
85 settings,
86}: {
87 identifier: string;
88 settings: ReturnType<typeof useUserSettings>['settings'];
89}) {
90 const { data: collectionsData } = useFollowingCollections({
91 identifier,
92 limit: 4,
93 });
94 const collections =
95 collectionsData.pages.flatMap((page) => page.collections) ?? [];
96
97 if (collections.length === 0) {
98 return (
99 <Stack align="center" gap="xs">
100 <Text fz="h3" fw={600} c="gray">
101 Not following any collections
102 </Text>
103 </Stack>
104 );
105 }
106
107 return (
108 <SimpleGrid
109 cols={
110 settings.collectionView !== 'grid'
111 ? { base: 1 }
112 : { base: 1, sm: 2, lg: 4 }
113 }
114 spacing="xs"
115 >
116 {collections.map((collection) => (
117 <CollectionCard key={collection.id} collection={collection} />
118 ))}
119 </SimpleGrid>
120 );
121}
122
123function ContributedCollectionsList({
124 identifier,
125 settings,
126}: {
127 identifier: string;
128 settings: ReturnType<typeof useUserSettings>['settings'];
129}) {
130 const { data: collectionsData } = useOpenCollectionsWithContributor({
131 identifier,
132 limit: 4,
133 });
134 const collections =
135 collectionsData.pages.flatMap((page) => page.collections) ?? [];
136
137 if (collections.length === 0) {
138 return (
139 <Stack align="center" gap="xs">
140 <Text fz="h3" fw={600} c="gray">
141 No collections contributed to
142 </Text>
143 </Stack>
144 );
145 }
146
147 return (
148 <SimpleGrid
149 cols={
150 settings.collectionView !== 'grid'
151 ? { base: 1 }
152 : { base: 1, sm: 2, lg: 4 }
153 }
154 spacing="xs"
155 >
156 {collections.map((collection) => (
157 <CollectionCard key={collection.id} collection={collection} />
158 ))}
159 </SimpleGrid>
160 );
161}
162
163export default function RecentCollections() {
164 const { settings } = useUserSettings();
165 const [showCollectionDrawer, setShowCollectionDrawer] = useState(false);
166 const [filter, setFilter] = useState<CollectionFilter>('mine');
167 const { data: profile } = useMyProfile();
168
169 const viewAllHref = {
170 mine: `/profile/${profile.handle}/collections`,
171 following: `/profile/${profile.handle}/network/collections-following`,
172 contributed: `/profile/${profile.handle}/network/contributed-to`,
173 }[filter];
174
175 return (
176 <Stack>
177 <Group justify="space-between">
178 <Group gap="xs">
179 <BiCollection size={22} />
180 <Title order={2}>Collections</Title>
181 </Group>
182 <Group gap="xs">
183 <ActionIcon
184 variant="light"
185 color="blue"
186 size={38}
187 radius={'xl'}
188 onClick={() => setShowCollectionDrawer(true)}
189 aria-label="Create collection"
190 >
191 <FiPlus size={18} />
192 </ActionIcon>
193 <LinkButton variant="light" color="blue" href={viewAllHref}>
194 View all
195 </LinkButton>
196 </Group>
197 </Group>
198
199 <Group gap={'xs'}>
200 <Button
201 variant={filter === 'mine' ? 'filled' : 'light'}
202 color="gray"
203 size="xs"
204 radius={'md'}
205 onClick={() => setFilter('mine')}
206 >
207 My Collections
208 </Button>
209 <Button
210 variant={filter === 'following' ? 'filled' : 'light'}
211 color="gray"
212 size="xs"
213 radius={'md'}
214 onClick={() => setFilter('following')}
215 >
216 Following
217 </Button>
218 <Button
219 variant={filter === 'contributed' ? 'filled' : 'light'}
220 color="gray"
221 size="xs"
222 radius={'md'}
223 onClick={() => setFilter('contributed')}
224 >
225 Contributed to
226 </Button>
227 </Group>
228
229 <Suspense fallback={<CollectionsListSkeleton />}>
230 {filter === 'mine' && (
231 <MyCollectionsList
232 onCreateCollection={() => setShowCollectionDrawer(true)}
233 settings={settings}
234 />
235 )}
236 {filter === 'following' && (
237 <FollowingCollectionsList
238 identifier={profile.handle}
239 settings={settings}
240 />
241 )}
242 {filter === 'contributed' && (
243 <ContributedCollectionsList
244 identifier={profile.handle}
245 settings={settings}
246 />
247 )}
248 </Suspense>
249
250 <CreateCollectionDrawer
251 isOpen={showCollectionDrawer}
252 onClose={() => setShowCollectionDrawer(false)}
253 />
254 </Stack>
255 );
256}