22
33import { useState , useEffect } from 'react' ;
44import { AnimatePresence , motion } from 'framer-motion' ;
5- import { X , RefreshCw } from 'lucide-react' ;
5+ import { X , RefreshCw , Share2 } from 'lucide-react' ;
66import Link from 'next/link' ;
77import { toast } from 'sonner' ;
88import type { Achievement } from '@/types/dashboard' ;
@@ -19,6 +19,7 @@ import StatsCard from './StatsCard';
1919import ComparisonStatsCard from './ComparisonStatsCard' ;
2020import RadarChart from './RadarChart' ;
2121import GrowthTrendChart from './GrowthTrendChart' ;
22+ import { useRouter } from 'next/navigation' ;
2223
2324// Define the dashboard data structure
2425interface DashboardData {
@@ -68,6 +69,7 @@ interface DashboardData {
6869interface DashboardClientProps {
6970 initialData : DashboardData ;
7071 username : string ;
72+ compareData ?: DashboardData | null ;
7173}
7274
7375export interface ProfileMetrics {
@@ -311,13 +313,14 @@ function getPersonalityTags(
311313// DashboardClient Component
312314// ------------------------------------------------------------
313315
314- export default function DashboardClient ( { initialData, username } : DashboardClientProps ) {
315- const [ secondUserData , setSecondUserData ] = useState < DashboardData | null > ( null ) ;
316- const [ isCompareMode , setIsCompareMode ] = useState ( false ) ;
316+ export default function DashboardClient ( { initialData, username, compareData = null , } : DashboardClientProps ) {
317+ const [ secondUserData , setSecondUserData ] = useState < DashboardData | null > ( compareData ) ;
318+ const [ isCompareMode , setIsCompareMode ] = useState ( Boolean ( compareData ) ) ;
317319 const [ isModalOpen , setIsModalOpen ] = useState ( false ) ;
318320 const [ secondUsernameInput , setSecondUsernameInput ] = useState ( '' ) ;
319321 const [ isLoadingSecond , setIsLoadingSecond ] = useState ( false ) ;
320322 const [ compareError , setCompareError ] = useState < string | null > ( null ) ;
323+ const router = useRouter ( ) ;
321324
322325 // Close modal on escape key
323326 useEffect ( ( ) => {
@@ -362,6 +365,11 @@ export default function DashboardClient({ initialData, username }: DashboardClie
362365 const data = await res . json ( ) ;
363366 setSecondUserData ( data ) ;
364367 setIsCompareMode ( true ) ;
368+
369+ router . replace (
370+ `/dashboard/${ username } ?compare=${ data . profile . username } `
371+ ) ;
372+
365373 setIsModalOpen ( false ) ;
366374 toast . success ( `Comparing ${ username } vs ${ data . profile . username } ` ) ;
367375 } catch ( err : unknown ) {
@@ -376,9 +384,33 @@ export default function DashboardClient({ initialData, username }: DashboardClie
376384 const handleExitCompare = ( ) => {
377385 setIsCompareMode ( false ) ;
378386 setSecondUserData ( null ) ;
387+
388+ router . replace ( `/dashboard/${ username } ` ) ;
389+
379390 toast . info ( 'Returned to single profile view' ) ;
380391 } ;
381392
393+ const handleShareComparison = async ( ) => {
394+ if ( ! secondUserData ) return ;
395+
396+ const compareUrl = `${ window . location . origin } /dashboard/${ username } ?compare=${ secondUserData . profile . username } ` ;
397+
398+ try {
399+ if ( navigator . share ) {
400+ await navigator . share ( {
401+ title : `${ username } vs ${ secondUserData . profile . username } ` ,
402+ text : 'Check out this GitHub profile comparison' ,
403+ url : compareUrl ,
404+ } ) ;
405+ } else {
406+ await navigator . clipboard . writeText ( compareUrl ) ;
407+ toast . success ( 'Comparison link copied!' ) ;
408+ }
409+ } catch {
410+ // user cancelled share dialog
411+ }
412+ } ;
413+
382414 // ------------------------------------------------------------
383415 // Compare Mode Statistics Calculations
384416 // ------------------------------------------------------------
@@ -477,6 +509,17 @@ export default function DashboardClient({ initialData, username }: DashboardClie
477509 Compare Profile
478510 </ button >
479511 ) }
512+ { isCompareMode && secondUserData && (
513+ < button
514+ onClick = { handleShareComparison }
515+ className = "flex items-center gap-2 rounded-xl border border-black/10 dark:border-[rgba(255,255,255,0.15)] bg-blue-600 hover:bg-blue-700 px-4 py-2 text-sm font-semibold text-white transition-all duration-200 active:scale-[0.98]"
516+ >
517+ < Share2 size = { 16 } />
518+ Share Comparison
519+ </ button >
520+ ) }
521+
522+
480523 < RefreshButton username = { username } />
481524 < Link
482525 href = "/"
0 commit comments