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