← back to Dear Bubbe Nextjs

components/ShareModal.tsx

272 lines

'use client'

import { useState, useEffect } from 'react'

interface ShareModalProps {
  isOpen: boolean
  onClose: () => void
  messageToShare: string
}

export default function ShareModal({ isOpen, onClose, messageToShare }: ShareModalProps) {
  const [copied, setCopied] = useState(false)
  const [activeButton, setActiveButton] = useState<string | null>(null)

  useEffect(() => {
    if (isOpen) {
      document.body.style.overflow = 'hidden'
    } else {
      document.body.style.overflow = 'unset'
    }
    return () => {
      document.body.style.overflow = 'unset'
    }
  }, [isOpen])

  if (!isOpen) return null

  // Format message for sharing (remove any HTML or special characters)
  const cleanMessage = messageToShare.replace(/<[^>]*>/g, '')
  
  // Truncate for social media if too long
  const twitterMessage = cleanMessage.length > 280 ? cleanMessage.substring(0, 277) + '...' : cleanMessage
  
  // Add hashtag
  const shareText = `${cleanMessage}\n\n#DearBubbe #BubbeAdvice #JewishGrandma`
  const shortShareText = `${twitterMessage}\n\n#DearBubbe`

  const handleCopyText = async () => {
    try {
      await navigator.clipboard.writeText(shareText)
      setCopied(true)
      setActiveButton('copy')
      setTimeout(() => {
        setCopied(false)
        setActiveButton(null)
      }, 2000)
    } catch (err) {
      console.error('Failed to copy text:', err)
    }
  }

  const handleShare = (platform: string, action: () => void) => {
    setActiveButton(platform)
    action()
    setTimeout(() => setActiveButton(null), 1000)
  }

  const handleShareToX = () => {
    const url = `https://twitter.com/intent/tweet?text=${encodeURIComponent(shortShareText)}`
    window.open(url, '_blank')
  }

  const handleShareToFacebook = () => {
    const url = `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent('http://45.61.58.125:3011')}&quote=${encodeURIComponent(shareText)}`
    window.open(url, '_blank')
  }

  const handleShareToTikTok = () => {
    // TikTok doesn't have direct share API - open app/website
    window.open('https://www.tiktok.com/upload', '_blank')
    // Copy text for user to paste
    handleCopyText()
  }

  const handleShareToInstagram = () => {
    // Instagram doesn't allow direct text sharing via web - copy text
    handleCopyText()
    // Open Instagram
    window.open('https://www.instagram.com', '_blank')
  }

  const handleEmailShare = () => {
    const subject = '👵 Bubbe gave me advice!'
    const body = `Check out what Bubbe said:\n\n${shareText}\n\n❤️ Get your own advice from Bubbe at: http://45.61.58.125:3011`
    const mailtoUrl = `mailto:?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`
    window.location.href = mailtoUrl
  }

  const handleWhatsAppShare = () => {
    const url = `https://wa.me/?text=${encodeURIComponent(shareText + '\n\n👵 Talk to Bubbe: http://45.61.58.125:3011')}`
    window.open(url, '_blank')
  }

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center p-4 animate-in fade-in duration-300">
      {/* Backdrop with blur */}
      <div 
        className="absolute inset-0 bg-gradient-to-br from-amber-900/40 via-orange-900/30 to-red-900/40 backdrop-blur-xl"
        onClick={onClose}
      />
      
      {/* Modal */}
      <div className="relative bg-gradient-to-br from-white via-amber-50 to-orange-50 rounded-3xl max-w-md w-full p-8 shadow-[0_20px_60px_rgba(0,0,0,0.3)] border border-amber-200/50 animate-in slide-in-from-bottom-5 duration-400">
        
        {/* Decorative circles */}
        <div className="absolute -top-10 -right-10 w-32 h-32 bg-gradient-to-br from-amber-300 to-orange-400 rounded-full opacity-20 blur-2xl" />
        <div className="absolute -bottom-10 -left-10 w-40 h-40 bg-gradient-to-br from-orange-300 to-red-400 rounded-full opacity-20 blur-2xl" />
        
        {/* Header */}
        <div className="relative flex justify-between items-start mb-6">
          <div>
            <h2 className="text-3xl font-bold bg-gradient-to-r from-amber-600 to-orange-600 bg-clip-text text-transparent">
              Share Bubbe's Wisdom
            </h2>
            <p className="text-sm text-amber-700 mt-1 font-medium">Spread the chutzpah! 💫</p>
          </div>
          <button 
            onClick={onClose}
            className="group relative p-2 rounded-full bg-white/80 hover:bg-white shadow-lg transition-all duration-300 hover:scale-110"
          >
            <svg className="w-5 h-5 text-gray-600 group-hover:text-red-500 transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
            </svg>
          </button>
        </div>

        {/* Message Preview */}
        <div className="relative mb-8">
          <div className="absolute inset-0 bg-gradient-to-br from-amber-100 to-orange-100 rounded-2xl blur-xl opacity-50" />
          <div className="relative bg-gradient-to-br from-white/90 to-amber-50/90 rounded-2xl p-5 max-h-36 overflow-y-auto shadow-inner border border-amber-200/30">
            <div className="absolute top-2 left-2 text-6xl opacity-10">💬</div>
            <p className="text-sm text-gray-800 font-medium leading-relaxed relative z-10">
              {cleanMessage}
            </p>
          </div>
        </div>

        {/* Share Options Grid */}
        <div className="grid grid-cols-3 gap-3 mb-6">
          {/* Copy Text */}
          <button
            onClick={handleCopyText}
            className={`group relative overflow-hidden flex flex-col items-center p-4 rounded-2xl transition-all duration-300 transform hover:scale-105 ${
              activeButton === 'copy' 
                ? 'bg-gradient-to-br from-green-400 to-green-500 shadow-lg shadow-green-500/30' 
                : 'bg-gradient-to-br from-gray-100 to-gray-200 hover:from-gray-200 hover:to-gray-300 shadow-md'
            }`}
          >
            <div className="absolute inset-0 bg-gradient-to-t from-white/0 to-white/20 opacity-0 group-hover:opacity-100 transition-opacity" />
            <svg className={`w-7 h-7 mb-2 transition-colors ${activeButton === 'copy' ? 'text-white' : 'text-gray-700'}`} fill="none" stroke="currentColor" viewBox="0 0 24 24">
              {copied ? (
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
              ) : (
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3" />
              )}
            </svg>
            <span className={`text-xs font-bold ${activeButton === 'copy' ? 'text-white' : 'text-gray-700'}`}>
              {copied ? 'Copied!' : 'Copy'}
            </span>
          </button>

          {/* X (Twitter) */}
          <button
            onClick={() => handleShare('x', handleShareToX)}
            className={`group relative overflow-hidden flex flex-col items-center p-4 rounded-2xl transition-all duration-300 transform hover:scale-105 ${
              activeButton === 'x'
                ? 'bg-black shadow-lg shadow-black/30'
                : 'bg-gradient-to-br from-gray-800 to-black hover:from-black hover:to-gray-800 shadow-md'
            }`}
          >
            <div className="absolute inset-0 bg-gradient-to-t from-white/0 to-white/10 opacity-0 group-hover:opacity-100 transition-opacity" />
            <svg className="w-7 h-7 mb-2 text-white" viewBox="0 0 24 24" fill="currentColor">
              <path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/>
            </svg>
            <span className="text-xs text-white font-bold">X</span>
          </button>

          {/* Facebook */}
          <button
            onClick={() => handleShare('facebook', handleShareToFacebook)}
            className={`group relative overflow-hidden flex flex-col items-center p-4 rounded-2xl transition-all duration-300 transform hover:scale-105 ${
              activeButton === 'facebook'
                ? 'bg-gradient-to-br from-blue-500 to-blue-700 shadow-lg shadow-blue-500/30'
                : 'bg-gradient-to-br from-blue-500 to-blue-600 hover:from-blue-600 hover:to-blue-700 shadow-md'
            }`}
          >
            <div className="absolute inset-0 bg-gradient-to-t from-white/0 to-white/20 opacity-0 group-hover:opacity-100 transition-opacity" />
            <svg className="w-7 h-7 mb-2 text-white" fill="currentColor" viewBox="0 0 24 24">
              <path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/>
            </svg>
            <span className="text-xs text-white font-bold">Facebook</span>
          </button>

          {/* TikTok */}
          <button
            onClick={() => handleShare('tiktok', handleShareToTikTok)}
            className={`group relative overflow-hidden flex flex-col items-center p-4 rounded-2xl transition-all duration-300 transform hover:scale-105 ${
              activeButton === 'tiktok'
                ? 'bg-gradient-to-br from-pink-500 via-purple-500 to-indigo-500 shadow-lg shadow-purple-500/30'
                : 'bg-gradient-to-br from-pink-400 via-purple-500 to-indigo-500 hover:from-pink-500 hover:to-indigo-600 shadow-md'
            }`}
          >
            <div className="absolute inset-0 bg-gradient-to-t from-white/0 to-white/20 opacity-0 group-hover:opacity-100 transition-opacity" />
            <svg className="w-7 h-7 mb-2 text-white" fill="currentColor" viewBox="0 0 24 24">
              <path d="M12.525.02c1.31-.02 2.61-.01 3.91-.02.08 1.53.63 3.09 1.75 4.17 1.12 1.11 2.7 1.62 4.24 1.79v4.03c-1.44-.05-2.89-.35-4.2-.97-.57-.26-1.1-.59-1.62-.93-.01 2.92.01 5.84-.02 8.75-.08 1.4-.54 2.79-1.35 3.94-1.31 1.92-3.58 3.17-5.91 3.21-1.43.08-2.86-.31-4.08-1.03-2.02-1.19-3.44-3.37-3.65-5.71-.02-.5-.03-1-.01-1.49.18-1.9 1.12-3.72 2.58-4.96 1.66-1.44 3.98-2.13 6.15-1.72.02 1.48-.04 2.96-.04 4.44-.99-.32-2.15-.23-3.02.37-.63.41-1.11 1.04-1.36 1.75-.21.51-.15 1.07-.14 1.61.24 1.64 1.82 3.02 3.5 2.87 1.12-.01 2.19-.66 2.77-1.61.19-.33.4-.67.41-1.06.1-1.79.06-3.57.07-5.36.01-4.03-.01-8.05.02-12.07z"/>
            </svg>
            <span className="text-xs text-white font-bold">TikTok</span>
          </button>

          {/* Instagram */}
          <button
            onClick={() => handleShare('instagram', handleShareToInstagram)}
            className={`group relative overflow-hidden flex flex-col items-center p-4 rounded-2xl transition-all duration-300 transform hover:scale-105 ${
              activeButton === 'instagram'
                ? 'bg-gradient-to-br from-purple-500 via-pink-500 to-yellow-500 shadow-lg shadow-pink-500/30'
                : 'bg-gradient-to-br from-purple-400 via-pink-500 to-orange-400 hover:from-purple-500 hover:to-orange-500 shadow-md'
            }`}
          >
            <div className="absolute inset-0 bg-gradient-to-t from-white/0 to-white/20 opacity-0 group-hover:opacity-100 transition-opacity" />
            <svg className="w-7 h-7 mb-2 text-white" fill="currentColor" viewBox="0 0 24 24">
              <path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zM5.838 12a6.162 6.162 0 1112.324 0 6.162 6.162 0 01-12.324 0zM12 16a4 4 0 110-8 4 4 0 010 8zm4.965-10.405a1.44 1.44 0 112.881.001 1.44 1.44 0 01-2.881-.001z"/>
            </svg>
            <span className="text-xs text-white font-bold">Instagram</span>
          </button>

          {/* Email */}
          <button
            onClick={() => handleShare('email', handleEmailShare)}
            className={`group relative overflow-hidden flex flex-col items-center p-4 rounded-2xl transition-all duration-300 transform hover:scale-105 ${
              activeButton === 'email'
                ? 'bg-gradient-to-br from-indigo-500 to-purple-600 shadow-lg shadow-indigo-500/30'
                : 'bg-gradient-to-br from-indigo-400 to-purple-500 hover:from-indigo-500 hover:to-purple-600 shadow-md'
            }`}
          >
            <div className="absolute inset-0 bg-gradient-to-t from-white/0 to-white/20 opacity-0 group-hover:opacity-100 transition-opacity" />
            <svg className="w-7 h-7 mb-2 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
            </svg>
            <span className="text-xs text-white font-bold">Email</span>
          </button>
        </div>

        {/* WhatsApp Button - Full Width with gradient */}
        <button
          onClick={() => handleShare('whatsapp', handleWhatsAppShare)}
          className={`group relative overflow-hidden w-full flex items-center justify-center p-4 rounded-2xl transition-all duration-300 transform hover:scale-[1.02] ${
            activeButton === 'whatsapp'
              ? 'bg-gradient-to-r from-green-500 to-green-600 shadow-lg shadow-green-500/30'
              : 'bg-gradient-to-r from-green-400 to-green-500 hover:from-green-500 hover:to-green-600 shadow-md'
          }`}
        >
          <div className="absolute inset-0 bg-gradient-to-t from-white/0 to-white/20 opacity-0 group-hover:opacity-100 transition-opacity" />
          <svg className="w-6 h-6 mr-3 text-white" fill="currentColor" viewBox="0 0 24 24">
            <path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.149-.67.149-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.074-.297-.149-1.255-.462-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.297-.347.446-.521.151-.172.2-.296.3-.495.099-.198.05-.372-.025-.521-.075-.148-.669-1.611-.916-2.206-.242-.579-.487-.501-.669-.51l-.57-.01c-.198 0-.52.074-.792.372s-1.04 1.016-1.04 2.479 1.065 2.876 1.213 3.074c.149.198 2.095 3.2 5.076 4.487.709.306 1.263.489 1.694.626.712.226 1.36.194 1.872.118.571-.085 1.758-.719 2.006-1.413.248-.695.248-1.29.173-1.414-.074-.123-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413Z"/>
          </svg>
          <span className="text-white font-bold">Share on WhatsApp</span>
        </button>

        {/* Footer Note with animation */}
        <div className="mt-6 text-center">
          <p className={`text-xs font-medium transition-all duration-500 ${
            copied 
              ? 'text-green-600 scale-105' 
              : 'text-amber-600'
          }`}>
            {copied ? '✨ Text copied! Ready to paste!' : "👵 Share Bubbe's wisdom with the world!"}
          </p>
        </div>
      </div>
    </div>
  )
}