bookwiz.io / components / DownloadDropdown.tsx
DownloadDropdown.tsx
Raw
'use client'

import { useState, useRef, useEffect } from 'react'
import { IoChevronDownOutline, IoDocumentTextOutline } from 'react-icons/io5'
import { FiDownload } from 'react-icons/fi'
import { FileSystemItem } from '@/lib/types/database'
import { downloadCurrentFormat, downloadAsPDF, downloadAsPDFFromEditor, getFormatDisplayName } from '@/lib/utils/download-utils'
import { Editor } from '@tiptap/react'

interface DownloadDropdownProps {
  file: FileSystemItem
  className?: string
  editor?: Editor | null // Optional TipTap editor instance for better PDF export
}

export default function DownloadDropdown({ file, className = '', editor }: DownloadDropdownProps) {
  const [isOpen, setIsOpen] = useState(false)
  const [isDownloading, setIsDownloading] = useState(false)
  const [downloadType, setDownloadType] = useState<'current' | 'pdf' | null>(null)
  const [error, setError] = useState<string | null>(null)
  const dropdownRef = useRef<HTMLDivElement>(null)

  // Close dropdown when clicking outside
  useEffect(() => {
    function handleClickOutside(event: MouseEvent) {
      if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
        setIsOpen(false)
      }
    }

    document.addEventListener('mousedown', handleClickOutside)
    return () => document.removeEventListener('mousedown', handleClickOutside)
  }, [])

  const handleDownloadCurrent = async () => {
    setIsDownloading(true)
    setDownloadType('current')
    setIsOpen(false)
    setError(null)
    
    try {
      downloadCurrentFormat(file)
    } catch (error) {
      console.error('Error downloading file:', error)
      setError('Failed to download file')
    } finally {
      setTimeout(() => {
        setIsDownloading(false)
        setDownloadType(null)
      }, 1000) // Small delay to show success
    }
  }

  const handleDownloadPDF = async () => {
    setIsDownloading(true)
    setDownloadType('pdf')
    setIsOpen(false)
    setError(null)
    
    try {
      const fileName = file.name.replace(/\.[^/.]+$/, '')
      
      // Use TipTap editor for better PDF export if available
      if (editor) {
        await downloadAsPDFFromEditor(editor, fileName)
      } else {
        // Fallback to markdown parsing
        await downloadAsPDF(file)
      }
    } catch (error) {
      console.error('Error downloading PDF:', error)
      setError('Failed to generate PDF')
    } finally {
      setTimeout(() => {
        setIsDownloading(false)
        setDownloadType(null)
      }, 1000) // Small delay to show success
    }
  }

  if (!file || file.type !== 'file' || !file.content) {
    return null
  }

  const formatName = getFormatDisplayName(file.file_extension || undefined)
  const pdfDescription = editor 
    ? 'Professional PDF with perfect formatting' 
    : 'Formatted document with tables & links'

  return (
    <div className={`relative ${className}`} ref={dropdownRef}>
      <button
        onClick={() => setIsOpen(!isOpen)}
        disabled={isDownloading}
        className="flex items-center gap-1.5 px-2.5 py-1.5 text-xs text-slate-400 hover:text-slate-200 hover:bg-slate-600/50 rounded-md transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed border border-slate-700/50 hover:border-slate-600/50"
        title="Download file"
      >
        <FiDownload className="w-3.5 h-3.5" />
        <IoChevronDownOutline className={`w-3 h-3 transition-transform duration-200 ${isOpen ? 'rotate-180' : ''}`} />
      </button>

      {isOpen && (
        <div className="absolute right-0 top-full mt-1 bg-slate-800 border border-slate-700 rounded-md shadow-lg py-1 z-50 min-w-[180px]">
          <button
            onClick={handleDownloadCurrent}
            disabled={isDownloading}
            className="w-full px-3 py-2 text-left text-sm text-slate-200 hover:bg-slate-700 transition-colors flex items-center gap-2 disabled:opacity-50"
          >
            <IoDocumentTextOutline className="w-4 h-4 text-slate-400" />
            <div className="flex flex-col">
              <span>Current Format</span>
              <span className="text-xs text-slate-500">{formatName}</span>
            </div>
          </button>
          
          <button
            onClick={handleDownloadPDF}
            disabled={isDownloading}
            className="w-full px-3 py-2 text-left text-sm text-slate-200 hover:bg-slate-700 transition-colors flex items-center gap-2 disabled:opacity-50"
          >
            <IoDocumentTextOutline className="w-4 h-4 text-red-400" />
            <div className="flex flex-col">
              <span>PDF {editor && <span className="text-xs text-teal-400"></span>}</span>
              <span className="text-xs text-slate-500">{pdfDescription}</span>
            </div>
          </button>
          
          {isDownloading && (
            <div className="px-3 py-2 text-xs text-slate-400 border-t border-slate-600">
              {error ? (
                <span className="text-red-400">{error}</span>
              ) : (
                <span>
                  {downloadType === 'pdf' 
                    ? (editor ? 'Generating PDF from editor...' : 'Converting markdown to PDF...') 
                    : 'Preparing download...'
                  }
                </span>
              )}
            </div>
          )}
        </div>
      )}
    </div>
  )
}