This repository has no description
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}