11import { useState } from "react"
22import Image from "next/image"
3- import { Check , Clock , Copy , Folder , Link2 , Tag , Loader2 } from "lucide-react"
3+ import { Check , Clock , Copy , Folder , Tag , Loader2 , Share2 , Twitter , Facebook , Linkedin } from "lucide-react"
44
55import { ArticleWithRelations } from "@/lib/agents/researcher/researcher"
66import { Badge } from "@/components/ui/badge"
@@ -30,7 +30,7 @@ function GenerateImageButton({
3030 disabled : boolean
3131} ) {
3232 return (
33- < Button onClick = { onClick } disabled = { disabled } >
33+ < Button onClick = { onClick } disabled = { disabled } variant = "outline" >
3434 { disabled ? (
3535 < >
3636 < Loader2 className = "mr-2 h-4 w-4 animate-spin" />
@@ -56,6 +56,7 @@ export default function ArticleRenderer({
5656 const [ isGeneratingImage , setIsGeneratingImage ] = useState ( false )
5757 const [ imageUrl , setImageUrl ] = useState < string | null > ( null )
5858 const [ error , setError ] = useState ( "" )
59+ const [ isCopiedUrl , setIsCopiedUrl ] = useState ( false )
5960
6061 const {
6162 title,
@@ -123,6 +124,47 @@ ${sources?.map((source) => `- [${source.title}](${source.url})`).join("\n")}
123124 } )
124125 }
125126
127+ const copyUrlToClipboard = ( ) => {
128+ const url = window . location . href ;
129+ navigator . clipboard
130+ . writeText ( url )
131+ . then ( ( ) => {
132+ setIsCopiedUrl ( true )
133+ toast ( {
134+ title : "Copied URL to clipboard" ,
135+ description :
136+ "The article URL has been copied to the clipboard." ,
137+ } )
138+ setTimeout ( ( ) => setIsCopiedUrl ( false ) , 3000 ) // Reset after 3 seconds
139+ } )
140+ . catch ( ( err ) => {
141+ console . error ( "Failed to copy URL: " , err )
142+ toast ( {
143+ title : "Failed to copy URL" ,
144+ description : "An error occurred while copying the URL." ,
145+ variant : "destructive" ,
146+ } )
147+ } )
148+ }
149+
150+ const shareToTwitter = ( ) => {
151+ const url = window . location . href ;
152+ const twitterUrl = `https://twitter.com/intent/tweet?url=${ encodeURIComponent ( url ) } &text=${ encodeURIComponent ( title ) } ` ;
153+ window . open ( twitterUrl , "_blank" ) ;
154+ }
155+
156+ const shareToFacebook = ( ) => {
157+ const url = window . location . href ;
158+ const facebookUrl = `https://www.facebook.com/sharer/sharer.php?u=${ encodeURIComponent ( url ) } ` ;
159+ window . open ( facebookUrl , "_blank" ) ;
160+ }
161+
162+ const shareToLinkedIn = ( ) => {
163+ const url = window . location . href ;
164+ const linkedInUrl = `https://www.linkedin.com/shareArticle?url=${ encodeURIComponent ( url ) } &title=${ encodeURIComponent ( title ) } ` ;
165+ window . open ( linkedInUrl , "_blank" ) ;
166+ }
167+
126168 // Add this function to handle article deletion
127169 async function handleDeleteArticle ( ) {
128170 if ( ! currentUserId ) {
@@ -160,6 +202,17 @@ ${sources?.map((source) => `- [${source.title}](${source.url})`).join("\n")}
160202 < CardTitle > { title } </ CardTitle >
161203 < CardDescription > { description } </ CardDescription >
162204 </ CardHeader >
205+ { featuredImage && (
206+ < div className = "mx-auto my-4 w-[90%]" >
207+ < Image
208+ src = { featuredImage }
209+ alt = { `Featured image for ${ title } ` }
210+ width = { 1024 }
211+ height = { 1024 }
212+ className = "h-auto w-full rounded-lg"
213+ />
214+ </ div >
215+ ) }
163216 < Separator className = "mx-auto my-4 w-[90%]" />
164217 < CardContent >
165218 < CustomReactMarkdown > { content } </ CustomReactMarkdown >
@@ -178,18 +231,6 @@ ${sources?.map((source) => `- [${source.title}](${source.url})`).join("\n")}
178231 < CardTitle > Article Info</ CardTitle >
179232 </ CardHeader >
180233 < CardContent className = "space-y-2" >
181- { featuredImage && (
182- < div className = "mb-4" >
183- < Image
184- src = { featuredImage }
185- alt = { `Featured image for ${ title } ` }
186- width = { 1024 }
187- height = { 1024 }
188- className = "h-auto w-full rounded-lg"
189- />
190- </ div >
191- ) }
192-
193234 < div className = "flex items-center space-x-2" >
194235 < Folder className = "h-4 w-4" />
195236 < span > { category ?. name } </ span >
@@ -208,6 +249,7 @@ ${sources?.map((source) => `- [${source.title}](${source.url})`).join("\n")}
208249 </ div >
209250 < div className = "flex items-center space-x-2" >
210251 < Button
252+ variant = "outline"
211253 onClick = { copyToClipboard }
212254 className = "mt-2"
213255 disabled = { isCopied }
@@ -225,6 +267,37 @@ ${sources?.map((source) => `- [${source.title}](${source.url})`).join("\n")}
225267 ) }
226268 </ Button >
227269 </ div >
270+ < div className = "flex items-center space-x-2" >
271+ < Button
272+ variant = "outline"
273+ onClick = { copyUrlToClipboard }
274+ className = "mt-2"
275+ disabled = { isCopiedUrl }
276+ >
277+ { isCopiedUrl ? (
278+ < >
279+ < Check className = "mr-2 h-4 w-4" />
280+ Copied URL!
281+ </ >
282+ ) : (
283+ < >
284+ < Share2 className = "mr-2 h-4 w-4" />
285+ Copy Sharing URL
286+ </ >
287+ ) }
288+ </ Button >
289+ </ div >
290+ < div className = "flex space-x-4 mt-2" >
291+ < Button variant = "outline" onClick = { shareToTwitter } >
292+ < Twitter className = "mr-2 h-4 w-4" />
293+ </ Button >
294+ < Button variant = "outline" onClick = { shareToFacebook } >
295+ < Facebook className = "mr-2 h-4 w-4" />
296+ </ Button >
297+ < Button variant = "outline" onClick = { shareToLinkedIn } >
298+ < Linkedin className = "mr-2 h-4 w-4" />
299+ </ Button >
300+ </ div >
228301 < div className = "flex flex-col space-y-2" >
229302 < GenerateImageButton
230303 onClick = { handleGenerateImage }
0 commit comments