This repository has no description
7.0 kB
258 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 {filter === 'mine' && (
184 <ActionIcon
185 variant="light"
186 color="blue"
187 size={38}
188 radius={'xl'}
189 onClick={() => setShowCollectionDrawer(true)}
190 aria-label="Create collection"
191 >
192 <FiPlus size={18} />
193 </ActionIcon>
194 )}
195 <LinkButton variant="light" color="blue" href={viewAllHref}>
196 View all
197 </LinkButton>
198 </Group>
199 </Group>
200
201 <Group gap={'xs'}>
202 <Button
203 variant={filter === 'mine' ? 'filled' : 'light'}
204 color="gray"
205 size="xs"
206 radius={'md'}
207 onClick={() => setFilter('mine')}
208 >
209 My Collections
210 </Button>
211 <Button
212 variant={filter === 'following' ? 'filled' : 'light'}
213 color="gray"
214 size="xs"
215 radius={'md'}
216 onClick={() => setFilter('following')}
217 >
218 Following
219 </Button>
220 <Button
221 variant={filter === 'contributed' ? 'filled' : 'light'}
222 color="gray"
223 size="xs"
224 radius={'md'}
225 onClick={() => setFilter('contributed')}
226 >
227 Contributed to
228 </Button>
229 </Group>
230
231 <Suspense fallback={<CollectionsListSkeleton />}>
232 {filter === 'mine' && (
233 <MyCollectionsList
234 onCreateCollection={() => setShowCollectionDrawer(true)}
235 settings={settings}
236 />
237 )}
238 {filter === 'following' && (
239 <FollowingCollectionsList
240 identifier={profile.handle}
241 settings={settings}
242 />
243 )}
244 {filter === 'contributed' && (
245 <ContributedCollectionsList
246 identifier={profile.handle}
247 settings={settings}
248 />
249 )}
250 </Suspense>
251
252 <CreateCollectionDrawer
253 isOpen={showCollectionDrawer}
254 onClose={() => setShowCollectionDrawer(false)}
255 />
256 </Stack>
257 );
258}