This repository has no description
0

Configure Feed

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

semble / src / webapp / features / collections / components / collectionActions / CollectionActions.tsx
7.1 kB 218 lines
1import { Collection, CollectionAccessType } from '@semble/types'; 2import { Group, Menu, ActionIcon, CopyButton } from '@mantine/core'; 3import EditCollectionModal from '../editCollectionModal/EditCollectionModal'; 4import DeleteCollectionModal from '../deleteCollectionModal/DeleteCollectionModal'; 5import { BsThreeDots, BsPencilFill, BsTrash2Fill } from 'react-icons/bs'; 6import { MdIosShare } from 'react-icons/md'; 7import { Fragment, useState } from 'react'; 8import { useAuth } from '@/hooks/useAuth'; 9import { FiPlus } from 'react-icons/fi'; 10import AddCardDrawer from '@/features/cards/components/addCardDrawer/AddCardDrawer'; 11import AddCardToModal from '@/features/cards/components/addCardToModal/AddCardToModal'; 12import { notifications } from '@mantine/notifications'; 13import FollowButton from '@/features/follows/components/followButton/FollowButton'; 14import useGetCardFromMyLibrary from '@/features/cards/lib/queries/useGetCardFromMyLibrary'; 15import useSembleLibraries from '@/features/semble/lib/queries/useSembleLibraries'; 16import { IoMdCheckmark } from 'react-icons/io'; 17import { FaRegNoteSticky } from 'react-icons/fa6'; 18import { TbPlugConnected } from 'react-icons/tb'; 19import AddConnectionModal from '@/features/connections/components/addConnectionModal/AddConnectionModal'; 20 21interface Props { 22 collection: Collection & { 23 rkey: string; 24 }; 25} 26 27function AuthenticatedCollectionActions({ collection }: Props) { 28 const { user } = useAuth(); 29 const [showAddDrawer, setShowAddDrawer] = useState(false); 30 const [showSaveToLibraryModal, setShowSaveToLibraryModal] = useState(false); 31 const [showAddConnectionModal, setShowAddConnectionModal] = useState(false); 32 33 const isAuthor = user?.handle === collection.author?.handle; 34 const canAddCard = 35 collection.accessType === CollectionAccessType.OPEN || isAuthor; 36 37 const collectionPageUrl = `${process.env.NEXT_PUBLIC_APP_URL}/profile/${collection.author?.handle}/collections/${collection.rkey}`; 38 39 const cardStatus = useGetCardFromMyLibrary({ url: collectionPageUrl }); 40 const isInYourLibrary = cardStatus.data.card?.urlInLibrary; 41 42 const { data: librariesData } = useSembleLibraries({ 43 url: collectionPageUrl, 44 }); 45 const allLibraries = 46 librariesData?.pages.flatMap((page) => page.libraries ?? []) ?? []; 47 const urlLibraryCount = allLibraries.length ?? 0; 48 49 return ( 50 <Fragment> 51 <Menu shadow="sm"> 52 <Menu.Target> 53 <ActionIcon size="lg" radius={'xl'}> 54 <FiPlus size={18} /> 55 </ActionIcon> 56 </Menu.Target> 57 <Menu.Dropdown> 58 {canAddCard && ( 59 <Menu.Item 60 leftSection={<FaRegNoteSticky />} 61 onClick={() => setShowAddDrawer(true)} 62 > 63 Add card to collection 64 </Menu.Item> 65 )} 66 <Menu.Item 67 leftSection={isInYourLibrary ? <IoMdCheckmark /> : <FiPlus />} 68 onClick={() => setShowSaveToLibraryModal(true)} 69 > 70 {isInYourLibrary ? 'Collection saved' : 'Save collection'} 71 </Menu.Item> 72 </Menu.Dropdown> 73 </Menu> 74 75 <ActionIcon 76 variant="light" 77 color="green" 78 size="lg" 79 radius={'xl'} 80 onClick={() => { 81 setShowAddConnectionModal(true); 82 }} 83 > 84 <TbPlugConnected size={18} /> 85 </ActionIcon> 86 87 {!isAuthor && ( 88 <FollowButton 89 targetId={collection.id} 90 targetType="COLLECTION" 91 targetHandle={collection.author.handle} 92 initialIsFollowing={collection.isFollowing} 93 /> 94 )} 95 96 <AddConnectionModal 97 isOpen={showAddConnectionModal} 98 onClose={() => setShowAddConnectionModal(false)} 99 sourceUrl={collectionPageUrl} 100 /> 101 102 <AddCardToModal 103 isOpen={showSaveToLibraryModal} 104 onClose={() => setShowSaveToLibraryModal(false)} 105 url={collectionPageUrl} 106 cardId={cardStatus.data.card?.id} 107 note={cardStatus.data.card?.note?.text} 108 isInYourLibrary={isInYourLibrary} 109 urlLibraryCount={urlLibraryCount} 110 /> 111 112 {user && ( 113 <AddCardDrawer 114 isOpen={showAddDrawer} 115 onClose={() => setShowAddDrawer(false)} 116 selectedCollection={collection} 117 /> 118 )} 119 </Fragment> 120 ); 121} 122 123function AuthorCollectionMenu({ collection }: Props) { 124 const [showEditModal, setShowEditModal] = useState(false); 125 const [showDeleteModal, setShowDeleteModal] = useState(false); 126 127 return ( 128 <Fragment> 129 <Menu shadow="sm"> 130 <Menu.Target> 131 <ActionIcon variant="light" color={'gray'} size={'lg'} radius={'xl'}> 132 <BsThreeDots size={22} /> 133 </ActionIcon> 134 </Menu.Target> 135 <Menu.Dropdown> 136 <Menu.Item 137 onClick={() => setShowEditModal(true)} 138 leftSection={<BsPencilFill />} 139 > 140 Edit collection 141 </Menu.Item> 142 <Menu.Item 143 color="red" 144 leftSection={<BsTrash2Fill />} 145 onClick={() => setShowDeleteModal(true)} 146 > 147 Delete collection 148 </Menu.Item> 149 </Menu.Dropdown> 150 </Menu> 151 152 <EditCollectionModal 153 isOpen={showEditModal} 154 onClose={() => setShowEditModal(false)} 155 collection={{ 156 id: collection.id, 157 rkey: collection.rkey, 158 name: collection.name, 159 description: collection.description, 160 accessType: collection.accessType, 161 uri: collection.uri, 162 authorHandle: collection.author?.handle, 163 }} 164 /> 165 <DeleteCollectionModal 166 isOpen={showDeleteModal} 167 onClose={() => setShowDeleteModal(false)} 168 collectionId={collection.id} 169 /> 170 </Fragment> 171 ); 172} 173 174export default function CollectionActions(props: Props) { 175 const { isAuthenticated, user } = useAuth(); 176 177 const isAuthor = 178 isAuthenticated && user?.handle === props.collection.author?.handle; 179 180 const shareLink = 181 typeof window !== 'undefined' 182 ? `${window.location.origin}/profile/${props.collection.author?.handle}/collections/${props.collection.rkey}` 183 : ''; 184 185 return ( 186 <Fragment> 187 <Group gap={'xs'}> 188 {isAuthenticated && ( 189 <AuthenticatedCollectionActions collection={props.collection} /> 190 )} 191 192 <CopyButton value={shareLink}> 193 {({ copy }) => ( 194 <ActionIcon 195 variant="light" 196 color="gray" 197 size={'lg'} 198 radius={'xl'} 199 onClick={(e) => { 200 e.stopPropagation(); 201 copy(); 202 notifications.show({ 203 message: 'Link copied!', 204 position: 'top-center', 205 id: props.collection.id, 206 }); 207 }} 208 > 209 <MdIosShare size={18} /> 210 </ActionIcon> 211 )} 212 </CopyButton> 213 214 {isAuthor && <AuthorCollectionMenu collection={props.collection} />} 215 </Group> 216 </Fragment> 217 ); 218}