2023-04-23 08:26:39 -05:00
// Copyright (C) 2022-present Daniel31x13 <daniel31x13@gmail.com>
// This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3.
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
2023-05-27 11:29:39 -05:00
import { LinkIncludingCollectionAndTags } from "@/types/global" ;
2023-03-10 13:25:33 -06:00
import {
faFolder ,
faArrowUpRightFromSquare ,
faEllipsis ,
} from "@fortawesome/free-solid-svg-icons" ;
2023-03-10 23:10:10 -06:00
import { faFileImage , faFilePdf } from "@fortawesome/free-regular-svg-icons" ;
2023-03-10 13:25:33 -06:00
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome" ;
import { useState } from "react" ;
2023-03-10 23:10:10 -06:00
import Image from "next/image" ;
2023-03-22 18:11:54 -05:00
import Dropdown from "./Dropdown" ;
2023-03-23 10:25:17 -05:00
import useLinkStore from "@/store/links" ;
2023-03-28 02:31:50 -05:00
import Modal from "./Modal" ;
2023-05-27 12:49:09 -05:00
import LinkModal from "./Modal/LinkModal" ;
2023-05-01 05:07:01 -05:00
import Link from "next/link" ;
2023-03-05 15:03:20 -06:00
2023-05-27 11:53:02 -05:00
type Props = {
2023-05-27 11:29:39 -05:00
link : LinkIncludingCollectionAndTags ;
2023-03-05 15:03:20 -06:00
count : number ;
2023-05-27 11:53:02 -05:00
} ;
export default function ( { link , count } : Props ) {
2023-04-23 08:26:39 -05:00
const [ expandDropdown , setExpandDropdown ] = useState ( false ) ;
2023-03-28 02:31:50 -05:00
const [ editModal , setEditModal ] = useState ( false ) ;
2023-03-10 13:25:33 -06:00
2023-03-23 10:25:17 -05:00
const { removeLink } = useLinkStore ( ) ;
2023-03-28 21:45:25 -05:00
const url = new URL ( link . url ) ;
2023-05-27 11:29:39 -05:00
const formattedDate = new Date ( link . createdAt as string ) . toLocaleString (
"en-US" ,
{
year : "numeric" ,
month : "short" ,
day : "numeric" ,
}
) ;
2023-03-10 13:25:33 -06:00
2023-03-28 02:31:50 -05:00
const toggleEditModal = ( ) = > {
setEditModal ( ! editModal ) ;
} ;
2023-03-05 15:03:20 -06:00
return (
2023-05-25 13:44:08 -05:00
< div className = "border border-sky-100 bg-gray-100 p-5 rounded-md flex items-start relative gap-5 sm:gap-10 group/item" >
2023-03-28 02:31:50 -05:00
{ editModal ? (
< Modal toggleModal = { toggleEditModal } >
2023-05-27 12:49:09 -05:00
< LinkModal
toggleLinkModal = { toggleEditModal }
activeLink = { link }
method = "UPDATE"
/ >
2023-03-28 02:31:50 -05:00
< / Modal >
) : null }
2023-03-10 23:10:10 -06:00
< Image
2023-03-28 21:45:25 -05:00
src = { ` https://t2.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url= ${ url . origin } &size=32 ` }
2023-05-24 15:33:41 -05:00
width = { 42 }
height = { 42 }
2023-03-10 23:10:10 -06:00
alt = ""
2023-05-25 09:17:20 -05:00
className = "select-none mt-3 z-10 rounded-full shadow border-[3px] border-sky-100"
2023-03-10 23:10:10 -06:00
draggable = "false"
2023-03-25 09:17:34 -05:00
onError = { ( e ) = > {
const target = e . target as HTMLElement ;
target . style . opacity = "0" ;
} }
2023-03-10 23:10:10 -06:00
/ >
2023-03-25 09:17:34 -05:00
< Image
2023-03-28 21:45:25 -05:00
src = { ` https://t2.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url= ${ url . origin } &size=32 ` }
2023-03-25 09:17:34 -05:00
width = { 80 }
height = { 80 }
alt = ""
2023-05-01 15:00:23 -05:00
className = "blur-sm absolute left-2 opacity-40 select-none hidden sm:block"
2023-03-25 09:17:34 -05:00
draggable = "false"
onError = { ( e ) = > {
const target = e . target as HTMLElement ;
target . style . opacity = "0" ;
} }
/ >
2023-05-24 19:51:29 -05:00
< div className = "flex justify-between gap-5 w-full h-full z-0" >
< div className = "flex flex-col justify-between" >
2023-03-10 13:25:33 -06:00
< div className = "flex items-baseline gap-1" >
< p className = "text-sm text-sky-300 font-bold" > { count + 1 } . < / p >
< p className = "text-lg text-sky-600" > { link . name } < / p >
< / div >
< p className = "text-sky-400 text-sm font-medium" > { link . title } < / p >
< div className = "flex gap-3 items-center flex-wrap my-3" >
2023-05-01 05:07:01 -05:00
< Link href = { ` /collections/ ${ link . collection . id } ` } >
< div className = "flex items-center gap-1 cursor-pointer hover:opacity-60 duration-100" >
< FontAwesomeIcon icon = { faFolder } className = "w-4 text-sky-300" / >
< p className = "text-sky-900" > { link . collection . name } < / p >
< / div >
< / Link >
2023-03-10 13:25:33 -06:00
< div className = "flex gap-1 items-center flex-wrap" >
{ link . tags . map ( ( e , i ) = > (
2023-05-01 05:07:01 -05:00
< Link key = { i } href = { ` /tags/ ${ e . id } ` } >
< p className = "px-2 py-1 bg-sky-200 text-sky-700 text-xs rounded-3xl cursor-pointer hover:bg-sky-100 duration-100" >
# { e . name }
< / p >
< / Link >
2023-03-10 13:25:33 -06:00
) ) }
< / div >
< / div >
2023-03-10 23:10:10 -06:00
< div className = "flex gap-2 items-center flex-wrap" >
2023-03-10 13:25:33 -06:00
< p className = "text-gray-500" > { formattedDate } < / p >
2023-03-10 23:10:10 -06:00
< a href = { link . url } target = "_blank" className = "group/url" >
2023-03-10 13:25:33 -06:00
< div className = "text-gray-500 font-bold flex items-center gap-1" >
2023-03-28 21:45:25 -05:00
< p > { url . host } < / p >
2023-03-10 13:25:33 -06:00
< FontAwesomeIcon
icon = { faArrowUpRightFromSquare }
2023-03-10 23:10:10 -06:00
className = "w-3 opacity-0 group-hover/url:opacity-100 duration-75"
2023-03-10 13:25:33 -06:00
/ >
< / div >
< / a >
< / div >
< / div >
2023-03-22 18:11:54 -05:00
< div className = "flex flex-col justify-between items-end relative" >
2023-03-28 02:31:50 -05:00
< div
2023-04-23 08:26:39 -05:00
onClick = { ( ) = > setExpandDropdown ( ! expandDropdown ) }
2023-05-27 22:21:35 -05:00
id = { "expand-dropdown" + link . id }
2023-03-28 02:31:50 -05:00
className = "text-gray-500 inline-flex rounded-md cursor-pointer hover:bg-white hover:outline outline-sky-100 outline-1 duration-100 p-1"
>
< FontAwesomeIcon
icon = { faEllipsis }
title = "More"
2023-05-25 13:44:08 -05:00
className = "w-5 h-5"
2023-05-27 22:21:35 -05:00
id = { "expand-dropdown" + link . id }
2023-03-28 02:31:50 -05:00
/ >
< / div >
2023-05-24 19:51:29 -05:00
< div className = "relative" >
< div className = "flex flex-col items-end justify-center gap-1" >
2023-03-10 13:25:33 -06:00
< a
href = { ` /api/archives/ ${ link . collectionId } / ${ encodeURIComponent (
link . screenshotPath
) } ` }
2023-03-10 23:10:10 -06:00
target = "_blank"
2023-05-14 10:41:08 -05:00
title = "Screenshot"
2023-03-10 13:25:33 -06:00
>
< FontAwesomeIcon
icon = { faFileImage }
2023-05-24 19:51:29 -05:00
className = "w-5 h-5 text-sky-600 cursor-pointer hover:text-sky-500 duration-100"
2023-03-10 13:25:33 -06:00
/ >
< / a >
< a
href = { ` /api/archives/ ${ link . collectionId } / ${ encodeURIComponent (
link . pdfPath
) } ` }
2023-03-10 23:10:10 -06:00
target = "_blank"
2023-05-14 10:41:08 -05:00
title = "PDF"
2023-03-10 13:25:33 -06:00
>
< FontAwesomeIcon
icon = { faFilePdf }
2023-05-24 19:51:29 -05:00
className = "w-5 h-5 text-sky-600 cursor-pointer hover:text-sky-500 duration-100"
2023-03-10 13:25:33 -06:00
/ >
< / a >
< / div >
< / div >
2023-03-22 18:11:54 -05:00
2023-04-23 08:26:39 -05:00
{ expandDropdown ? (
2023-03-22 18:11:54 -05:00
< Dropdown
items = { [
{
name : "Edit" ,
2023-03-28 02:31:50 -05:00
onClick : ( ) = > {
setEditModal ( true ) ;
2023-04-23 08:26:39 -05:00
setExpandDropdown ( false ) ;
2023-03-28 02:31:50 -05:00
} ,
2023-03-22 18:11:54 -05:00
} ,
{
name : "Delete" ,
2023-03-28 02:31:50 -05:00
onClick : ( ) = > {
removeLink ( link ) ;
2023-04-23 08:26:39 -05:00
setExpandDropdown ( false ) ;
2023-03-28 02:31:50 -05:00
} ,
2023-03-22 18:11:54 -05:00
} ,
] }
2023-03-23 10:25:17 -05:00
onClickOutside = { ( e : Event ) = > {
const target = e . target as HTMLInputElement ;
2023-05-27 22:21:35 -05:00
if ( target . id !== "expand-dropdown" + link . id )
setExpandDropdown ( false ) ;
2023-03-23 10:25:17 -05:00
} }
2023-05-27 22:21:35 -05:00
className = "absolute top-7 right-0 w-36"
2023-03-22 18:11:54 -05:00
/ >
) : null }
2023-03-10 13:25:33 -06:00
< / div >
2023-03-05 15:03:20 -06:00
< / div >
< / div >
) ;
}