File size: 2,839 Bytes
5575628
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
"use client";

import { useState, useRef, useEffect } from "react";
import { FileDown, ChevronDown, Loader2 } from "lucide-react";
import { EXPORT_FORMATS } from "@/lib/export-utils";
import type { AnalysisResult } from "@/lib/types";

export function ExportDropdown({ results }: { results: AnalysisResult }) {
  const [open, setOpen] = useState(false);
  const [exporting, setExporting] = useState<string | null>(null);
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    function handleClickOutside(e: MouseEvent) {
      if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false);
    }
    document.addEventListener("mousedown", handleClickOutside);
    return () => document.removeEventListener("mousedown", handleClickOutside);
  }, []);

  async function handleExport(key: string, fn: (r: AnalysisResult) => void | Promise<any>) {
    setExporting(key);
    try {
      await fn(results);
    } catch (e) {
      console.error("Export failed:", e);
    }
    setExporting(null);
    setOpen(false);
  }

  return (
    <div ref={ref} className="relative">
      <button
        onClick={() => setOpen(!open)}
        className="inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium text-zinc-600 bg-white border border-zinc-200 rounded-lg hover:bg-zinc-50 hover:border-zinc-300 transition-all shadow-sm"
      >
        <FileDown className="w-3.5 h-3.5" />
        Export
        <ChevronDown className={`w-3 h-3 transition-transform ${open ? "rotate-180" : ""}`} />
      </button>

      {open && (
        <div className="absolute right-0 top-full mt-1.5 w-64 bg-white border border-zinc-200 rounded-xl shadow-xl z-50 overflow-hidden animate-in fade-in slide-in-from-top-1 duration-150">
          <div className="px-3 py-2 border-b border-zinc-100">
            <p className="text-[10px] font-semibold text-zinc-400 uppercase tracking-wider">Export Report</p>
          </div>
          <div className="py-1">
            {EXPORT_FORMATS.map((fmt) => (
              <button
                key={fmt.key}
                onClick={() => handleExport(fmt.key, fmt.fn)}
                disabled={exporting !== null}
                className="w-full flex items-center gap-3 px-3 py-2.5 text-left hover:bg-zinc-50 transition-colors disabled:opacity-40"
              >
                <span className="text-base w-5 text-center">{fmt.icon}</span>
                <div className="flex-1 min-w-0">
                  <p className="text-sm font-medium text-zinc-700">{fmt.label}</p>
                  <p className="text-[10px] text-zinc-400">{fmt.description}</p>
                </div>
                {exporting === fmt.key && <Loader2 className="w-3.5 h-3.5 text-zinc-400 animate-spin" />}
              </button>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}