This repository has no description
8.6 kB
274 lines
1'use client';
2
3import {
4 type UrlCard,
5 type Collection,
6 type User,
7 CollectionAccessType,
8} from '@/api-client';
9import { ActionIcon, Button, CopyButton, Group, Menu } from '@mantine/core';
10import { Fragment, useState } from 'react';
11import { FiPlus } from 'react-icons/fi';
12import { BsThreeDots, BsTrash2Fill } from 'react-icons/bs';
13import RemoveCardFromCollectionModal from '../removeCardFromCollectionModal/RemoveCardFromCollectionModal';
14import RemoveCardFromLibraryModal from '../removeCardFromLibraryModal/RemoveCardFromLibraryModal';
15import AddCardToModal from '@/features/cards/components/addCardToModal/AddCardToModal';
16import { MdIosShare, MdOutlineStickyNote2 } from 'react-icons/md';
17import NoteCardModal from '@/features/notes/components/noteCardModal/NoteCardModal';
18import { useAuth } from '@/hooks/useAuth';
19import { IoMdCheckmark } from 'react-icons/io';
20import { notifications } from '@mantine/notifications';
21import { BiCopy } from 'react-icons/bi';
22import { CardSaveAnalyticsContext } from '@/features/analytics/types';
23import { TbPlugConnected } from 'react-icons/tb';
24import AddConnectionModal from '@/features/connections/components/addConnectionModal/AddConnectionModal';
25import { AiOutlineDisconnect } from 'react-icons/ai';
26import { useWebHaptics } from 'web-haptics/react';
27
28interface Props {
29 id: string;
30 cardContent: UrlCard['cardContent'];
31 cardCount: number;
32 cardAuthor?: User;
33 authorHandle?: string;
34 note?: UrlCard['note'];
35 currentCollection?: Collection;
36 urlLibraryCount: number;
37 urlIsInLibrary: boolean;
38 urlIsConnected?: boolean;
39 urlConnectionCount: number;
40 viaCardId?: string;
41 semblePageUrl?: string;
42 analyticsContext?: CardSaveAnalyticsContext;
43}
44
45export default function UrlCardActions(props: Props) {
46 const { isAuthenticated, user } = useAuth();
47
48 const userId = user?.id;
49 const userHandle = user?.handle;
50
51 const isAuthor =
52 !!user &&
53 (props.authorHandle
54 ? userHandle === props.authorHandle
55 : userId === props.cardAuthor?.id);
56
57 const isOpenCollection =
58 props.currentCollection?.accessType === CollectionAccessType.OPEN;
59
60 const isCardAdder = userId === props.cardAuthor?.id;
61 const isCollectionOwner = userId === props.currentCollection?.author.id;
62
63 const canRemoveFromOpenCollection =
64 !!user && isOpenCollection && (isCardAdder || isCollectionOwner);
65
66 const canRemoveFromLibrary = isAuthor && props.urlIsInLibrary;
67
68 const [showNoteModal, setShowNoteModal] = useState(false);
69 const [showRemoveFromCollectionModal, setShowRemoveFromCollectionModal] =
70 useState(false);
71 const [showRemoveFromLibaryModal, setShowRemoveFromLibraryModal] =
72 useState(false);
73 const [showAddToModal, setShowAddToModal] = useState(false);
74 const [showAddConnectionModal, setShowAddConnectionModal] = useState(false);
75
76 const { trigger } = useWebHaptics();
77
78 if (!isAuthenticated) {
79 return null;
80 }
81
82 return (
83 <Fragment>
84 <Group justify="space-between">
85 <Group gap={'xs'}>
86 <Button
87 variant="light"
88 color={'gray'}
89 size="xs"
90 radius={'xl'}
91 leftSection={
92 props.urlLibraryCount > 0 ? (
93 props.urlIsInLibrary ? (
94 <IoMdCheckmark size={18} />
95 ) : (
96 <FiPlus size={18} />
97 )
98 ) : undefined
99 }
100 onClick={(e) => {
101 e.stopPropagation();
102 trigger();
103 setShowAddToModal(true);
104 }}
105 >
106 {props.urlLibraryCount ? (
107 props.urlLibraryCount
108 ) : props.urlIsInLibrary ? (
109 <IoMdCheckmark size={18} />
110 ) : (
111 <FiPlus size={18} />
112 )}
113 </Button>
114 <Button
115 variant="light"
116 color="gray"
117 c={props.urlIsConnected ? 'green' : 'gray'}
118 size="xs"
119 radius={'xl'}
120 leftSection={
121 props.urlConnectionCount > 0 ? (
122 <TbPlugConnected size={15} />
123 ) : undefined
124 }
125 onClick={(e) => {
126 e.stopPropagation();
127 trigger();
128 setShowAddConnectionModal(true);
129 }}
130 >
131 {props.urlConnectionCount ? (
132 props.urlConnectionCount
133 ) : (
134 <TbPlugConnected size={15} />
135 )}
136 </Button>
137
138 {props.note && (
139 <ActionIcon
140 variant="light"
141 color="gray"
142 radius={'xl'}
143 onClick={(e) => {
144 e.stopPropagation();
145 setShowNoteModal(true);
146 }}
147 >
148 <MdOutlineStickyNote2 />
149 </ActionIcon>
150 )}
151 </Group>
152
153 <Menu shadow="sm">
154 <Menu.Target>
155 <ActionIcon
156 variant="light"
157 color={'gray'}
158 radius={'xl'}
159 onClick={(e) => e.stopPropagation()}
160 >
161 <BsThreeDots size={18} />
162 </ActionIcon>
163 </Menu.Target>
164 <Menu.Dropdown>
165 <CopyButton value={props.cardContent.url}>
166 {({ copy }) => (
167 <Menu.Item
168 leftSection={<BiCopy />}
169 onClick={(e) => {
170 e.stopPropagation();
171 copy();
172 notifications.show({
173 message: 'Link copied!',
174 position: 'top-center',
175 });
176 }}
177 >
178 Copy link
179 </Menu.Item>
180 )}
181 </CopyButton>
182
183 <CopyButton
184 value={`${process.env.NEXT_PUBLIC_APP_URL}/url?id=${props.cardContent.url}`}
185 >
186 {({ copy }) => (
187 <Menu.Item
188 leftSection={<MdIosShare />}
189 onClick={(e) => {
190 e.stopPropagation();
191 copy();
192 notifications.show({
193 message: 'Semble link copied!',
194 position: 'top-center',
195 });
196 }}
197 >
198 Share Semble page
199 </Menu.Item>
200 )}
201 </CopyButton>
202
203 {props.currentCollection &&
204 (isAuthor || canRemoveFromOpenCollection) && (
205 <Menu.Item
206 leftSection={<AiOutlineDisconnect />}
207 onClick={(e) => {
208 e.stopPropagation();
209 setShowRemoveFromCollectionModal(true);
210 }}
211 >
212 Remove from this collection
213 </Menu.Item>
214 )}
215 {canRemoveFromLibrary && (
216 <Menu.Item
217 color="red"
218 leftSection={<BsTrash2Fill />}
219 onClick={(e) => {
220 e.stopPropagation();
221 setShowRemoveFromLibraryModal(true);
222 }}
223 >
224 Remove from library
225 </Menu.Item>
226 )}
227 </Menu.Dropdown>
228 </Menu>
229 </Group>
230
231 <AddCardToModal
232 isOpen={showAddToModal}
233 onClose={() => setShowAddToModal(false)}
234 url={props.cardContent.url}
235 cardContent={props.cardContent}
236 cardId={props.id}
237 note={props.note?.text}
238 isInYourLibrary={props.urlIsInLibrary}
239 urlLibraryCount={props.urlLibraryCount}
240 viaCardId={props.viaCardId}
241 analyticsContext={props.analyticsContext}
242 />
243
244 <AddConnectionModal
245 isOpen={showAddConnectionModal}
246 onClose={() => setShowAddConnectionModal(false)}
247 sourceUrl={props.cardContent.url}
248 targetUrl={props.semblePageUrl}
249 />
250
251 <NoteCardModal
252 isOpen={showNoteModal}
253 onClose={() => setShowNoteModal(false)}
254 note={props.note}
255 cardContent={props.cardContent}
256 cardAuthor={props.cardAuthor}
257 />
258
259 {props.currentCollection && (
260 <RemoveCardFromCollectionModal
261 isOpen={showRemoveFromCollectionModal}
262 onClose={() => setShowRemoveFromCollectionModal(false)}
263 cardId={props.id}
264 collectionId={props.currentCollection.id}
265 />
266 )}
267 <RemoveCardFromLibraryModal
268 isOpen={showRemoveFromLibaryModal}
269 onClose={() => setShowRemoveFromLibraryModal(false)}
270 cardId={props.id}
271 />
272 </Fragment>
273 );
274}