This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

semble / src / webapp / features / home / components / recentCollections / RecentCollections.tsx
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}