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