![]() Server : Apache/2 System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64 User : gositeme ( 1004) PHP Version : 8.2.29 Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname Directory : /home/gositeme/domains/lavocat.ca/public_html/src/components/ |
import React, { useState } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { Share2, Facebook, Twitter, Linkedin, MessageCircle, Copy, Check, Loader2 } from 'lucide-react';
import { useSocialShare } from '../hooks/useSocialShare';
import toast from 'react-hot-toast';
interface EnhancedShareButtonProps {
url: string;
title: string;
description: string;
image?: string;
hashtags?: string[];
className?: string;
variant?: 'default' | 'minimal' | 'floating';
}
const EnhancedShareButton: React.FC<EnhancedShareButtonProps> = ({
url,
title,
description,
image,
hashtags = [],
className = '',
variant = 'default'
}) => {
const [showShareMenu, setShowShareMenu] = useState(false);
const [copied, setCopied] = useState(false);
const {
shareToFacebook,
shareToTwitter,
shareToLinkedIn,
shareToWhatsApp,
copyToClipboard,
isSharing,
shareError
} = useSocialShare();
const shareData = {
url,
title,
description,
image,
hashtags
};
const handleShare = async (platform: string) => {
try {
switch (platform) {
case 'facebook':
await shareToFacebook(shareData);
toast.success('Shared to Facebook!');
break;
case 'twitter':
await shareToTwitter(shareData);
toast.success('Shared to Twitter!');
break;
case 'linkedin':
await shareToLinkedIn(shareData);
toast.success('Shared to LinkedIn!');
break;
case 'whatsapp':
await shareToWhatsApp(shareData);
toast.success('Shared to WhatsApp!');
break;
case 'copy':
await copyToClipboard(shareData);
setCopied(true);
toast.success('Link copied to clipboard!');
setTimeout(() => setCopied(false), 2000);
break;
}
} catch (error) {
toast.error(`Failed to share to ${platform}`);
console.error(`Share error for ${platform}:`, error);
}
setShowShareMenu(false);
};
const shareOptions = [
{
platform: 'facebook',
label: 'Facebook',
icon: Facebook,
color: 'text-blue-600',
bgColor: 'hover:bg-blue-50',
action: () => handleShare('facebook')
},
{
platform: 'twitter',
label: 'Twitter',
icon: Twitter,
color: 'text-blue-400',
bgColor: 'hover:bg-blue-50',
action: () => handleShare('twitter')
},
{
platform: 'linkedin',
label: 'LinkedIn',
icon: Linkedin,
color: 'text-blue-700',
bgColor: 'hover:bg-blue-50',
action: () => handleShare('linkedin')
},
{
platform: 'whatsapp',
label: 'WhatsApp',
icon: MessageCircle,
color: 'text-green-600',
bgColor: 'hover:bg-green-50',
action: () => handleShare('whatsapp')
},
{
platform: 'copy',
label: copied ? 'Copied!' : 'Copy Link',
icon: copied ? Check : Copy,
color: copied ? 'text-green-600' : 'text-gray-600',
bgColor: copied ? 'bg-green-50' : 'hover:bg-gray-50',
action: () => handleShare('copy')
}
];
const getButtonStyles = () => {
switch (variant) {
case 'minimal':
return 'p-2 text-gray-600 hover:text-gray-800 hover:bg-gray-100 rounded-full transition-colors';
case 'floating':
return 'fixed bottom-6 right-6 p-4 bg-blue-600 text-white rounded-full shadow-lg hover:bg-blue-700 transition-colors z-50';
default:
return 'flex items-center gap-2 px-4 py-2 bg-white/20 hover:bg-white/30 text-white rounded-lg transition-colors';
}
};
const getMenuStyles = () => {
switch (variant) {
case 'minimal':
return 'absolute top-full right-0 mt-2 bg-white rounded-lg shadow-lg border border-gray-200 p-2 min-w-[200px] z-50';
case 'floating':
return 'absolute bottom-full right-0 mb-2 bg-white rounded-lg shadow-lg border border-gray-200 p-2 min-w-[200px] z-50';
default:
return 'absolute top-full right-0 mt-2 bg-white rounded-lg shadow-lg border border-gray-200 p-2 min-w-[200px] z-50';
}
};
return (
<div className={`relative ${className}`}>
<button
onClick={() => setShowShareMenu(!showShareMenu)}
className={getButtonStyles()}
disabled={isSharing}
>
{isSharing ? (
<Loader2 className="h-4 w-4 animate-spin" />
) : (
<Share2 className="h-4 w-4" />
)}
{variant !== 'minimal' && variant !== 'floating' && (
<span>Share</span>
)}
</button>
<AnimatePresence>
{showShareMenu && (
<motion.div
initial={{ opacity: 0, scale: 0.95, y: -10 }}
animate={{ opacity: 1, scale: 1, y: 0 }}
exit={{ opacity: 0, scale: 0.95, y: -10 }}
transition={{ duration: 0.15 }}
className={getMenuStyles()}
>
<div className="space-y-1">
{shareOptions.map((option) => {
const IconComponent = option.icon;
return (
<button
key={option.platform}
onClick={option.action}
disabled={isSharing}
className={`w-full flex items-center gap-3 px-3 py-2 text-sm rounded-md transition-colors ${option.bgColor} ${option.color} disabled:opacity-50 disabled:cursor-not-allowed`}
>
<IconComponent className="h-4 w-4" />
<span>{option.label}</span>
{isSharing && option.platform === 'facebook' && (
<Loader2 className="h-3 w-3 animate-spin ml-auto" />
)}
</button>
);
})}
</div>
</motion.div>
)}
</AnimatePresence>
{/* Error display */}
{shareError && (
<div className="absolute top-full left-0 mt-2 bg-red-50 border border-red-200 text-red-700 px-3 py-2 rounded-md text-sm max-w-xs">
{shareError}
</div>
)}
{/* Click outside to close */}
{showShareMenu && (
<div
className="fixed inset-0 z-40"
onClick={() => setShowShareMenu(false)}
/>
)}
</div>
);
};
export default EnhancedShareButton;