1
- import { Fragment , useState } from "react"
1
+ import { Fragment , useState , ReactNode } from "react"
2
2
import { Menu , Transition } from "@headlessui/react"
3
- import { OpenInBrowser , Trash , Copy } from "iconoir-react"
3
+ import { OpenInBrowser , Trash , Copy , Pin } from "iconoir-react"
4
4
import { toast } from "sonner"
5
- import DeleteModal from "./DeleteModal"
5
+ import { useBookmarkStore } from "../stores/BookmarkStore"
6
+ import { useAuthStore } from "../stores/AuthStore"
6
7
import useClipboard from "../hooks/useClipboard"
8
+ import DeleteModal from "./DeleteModal"
7
9
8
10
type Props = {
9
11
bookmark : Bookmark
10
12
}
11
13
12
14
const BookmarkDropdown = ( { bookmark } : Props ) => {
15
+ const { fetch : getBookmarks , update : updateBookmark } = useBookmarkStore ( state => ( { fetch : state . fetch , update : state . update } ) )
13
16
const { copy } = useClipboard ( )
17
+ const session = useAuthStore ( state => state . session )
18
+ const userId = session ?. user . id
14
19
const [ isModalOpen , setIsModalOpen ] = useState < boolean > ( false )
15
20
16
21
const openInNewTab = ( url : string ) => window . open ( url , "_blank" )
17
22
23
+ const pinBookmark = async ( ) => {
24
+ if ( ! userId ) return
25
+ const response = await updateBookmark ( bookmark . id , { ...bookmark , pinned : ! bookmark . pinned } )
26
+ if ( ! response . success ) return toast . error ( response . data )
27
+ getBookmarks ( userId )
28
+ }
29
+
18
30
const copyUrl = ( url : string ) => {
19
31
copy ( url )
20
32
toast ( "URL copied to clipboard!" , { style : { backgroundColor : "#18181b" , borderColor : "#3f3f46" } } )
@@ -30,27 +42,18 @@ const BookmarkDropdown = ({ bookmark }: Props) => {
30
42
</ Menu . Button >
31
43
< Transition as = { Fragment } enter = "transition ease-out duration-100" enterFrom = "transform opacity-0 scale-95" enterTo = "transform opacity-100 scale-100" leave = "transition ease-in duration-100" leaveFrom = "transform opacity-100 scale-100" leaveTo = "transform opacity-0 scale-95" >
32
44
< Menu . Items className = "absolute p-[1px] right-0 w-40 mt-2 origin-top-right bg-zinc-200 rounded-md text-sm z-20 shadow-xl focus:outline-non will-change-transform" >
33
- < Menu . Item >
34
- { ( { active } ) => (
35
- < button onClick = { ( ) => openInNewTab ( bookmark . url ) } className = { `${ active ? "bg-zinc-800 text-zinc-200" : "text-zinc-900" } flex gap-1 w-full items-center rounded-[5px] p-2` } >
36
- < OpenInBrowser width = { 16 } strokeWidth = { 1.75 } /> Open in new tab
37
- </ button >
38
- ) }
39
- </ Menu . Item >
40
- < Menu . Item >
41
- { ( { active } ) => (
42
- < button onClick = { ( ) => copyUrl ( bookmark . url ) } className = { `${ active ? "bg-zinc-800 text-zinc-200" : "text-zinc-900" } flex gap-1 w-full items-center rounded-[5px] p-2` } >
43
- < Copy width = { 16 } strokeWidth = { 1.75 } /> Copy URL
44
- </ button >
45
- ) }
46
- </ Menu . Item >
47
- < Menu . Item >
48
- { ( { active } ) => (
49
- < button onClick = { ( ) => setIsModalOpen ( true ) } className = { `${ active ? "bg-zinc-800 text-zinc-200" : "text-zinc-900" } flex gap-1 w-full items-center rounded-[5px] p-2` } >
50
- < Trash width = { 16 } strokeWidth = { 1.75 } /> Delete
51
- </ button >
52
- ) }
53
- </ Menu . Item >
45
+ < MenuItem onClick = { ( ) => openInNewTab ( bookmark . url ) } >
46
+ < OpenInBrowser width = { 16 } strokeWidth = { 1.75 } /> Open in new tab
47
+ </ MenuItem >
48
+ < MenuItem onClick = { ( ) => copyUrl ( bookmark . url ) } >
49
+ < Copy width = { 16 } strokeWidth = { 1.75 } /> Copy URL
50
+ </ MenuItem >
51
+ < MenuItem onClick = { pinBookmark } >
52
+ < Pin width = { 16 } strokeWidth = { 1.75 } /> { bookmark . pinned ? "Unpin" : "Pin to top" }
53
+ </ MenuItem >
54
+ < MenuItem onClick = { ( ) => setIsModalOpen ( true ) } >
55
+ < Trash width = { 16 } strokeWidth = { 1.75 } /> Delete
56
+ </ MenuItem >
54
57
</ Menu . Items >
55
58
</ Transition >
56
59
</ Menu >
@@ -59,4 +62,21 @@ const BookmarkDropdown = ({ bookmark }: Props) => {
59
62
)
60
63
}
61
64
65
+ type MenuItemProps = {
66
+ onClick : React . MouseEventHandler < HTMLButtonElement >
67
+ children : ReactNode
68
+ }
69
+
70
+ const MenuItem = ( { onClick, children } : MenuItemProps ) => {
71
+ return (
72
+ < Menu . Item >
73
+ { ( { active } ) => (
74
+ < button onClick = { onClick } className = { `${ active ? "bg-zinc-800 text-zinc-200" : "text-zinc-900" } flex gap-1 w-full items-center rounded-[5px] p-2` } >
75
+ { children }
76
+ </ button >
77
+ ) }
78
+ </ Menu . Item >
79
+ )
80
+ }
81
+
62
82
export default BookmarkDropdown
0 commit comments