Spaces:
Sleeping
Sleeping
| import React, { useState } from "react"; | |
| import { motion, AnimatePresence } from "framer-motion"; | |
| import { | |
| Download, | |
| Braces, | |
| FileCode2, | |
| Check, | |
| Share2, | |
| FileJson, | |
| Copy, | |
| Mail, | |
| Link2, | |
| } from "lucide-react"; | |
| import { Button } from "@/components/ui/button"; | |
| import { | |
| DropdownMenu, | |
| DropdownMenuContent, | |
| DropdownMenuItem, | |
| DropdownMenuSeparator, | |
| DropdownMenuTrigger, | |
| } from "@/components/ui/dropdown-menu"; | |
| import { cn } from "@/lib/utils"; | |
| export default function ExportButtons({ isComplete }) { | |
| const [downloading, setDownloading] = useState(null); | |
| const [copied, setCopied] = useState(false); | |
| const handleDownload = (format) => { | |
| setDownloading(format); | |
| // Simulate download | |
| setTimeout(() => { | |
| setDownloading(null); | |
| }, 1500); | |
| }; | |
| const handleCopyLink = () => { | |
| setCopied(true); | |
| setTimeout(() => setCopied(false), 2000); | |
| }; | |
| if (!isComplete) return null; | |
| return ( | |
| <motion.div | |
| initial={{ opacity: 0, y: 20 }} | |
| animate={{ opacity: 1, y: 0 }} | |
| className="flex items-center gap-3" | |
| > | |
| {/* JSON Download */} | |
| <Button | |
| onClick={() => handleDownload("json")} | |
| disabled={downloading === "json"} | |
| className={cn( | |
| "h-11 px-5 rounded-xl font-semibold transition-all duration-200", | |
| "bg-gradient-to-r from-indigo-600 to-violet-600 hover:from-indigo-700 hover:to-violet-700", | |
| "shadow-lg shadow-indigo-500/25 hover:shadow-xl hover:shadow-indigo-500/30", | |
| "text-white" | |
| )} | |
| > | |
| <AnimatePresence mode="wait"> | |
| {downloading === "json" ? ( | |
| <motion.div | |
| key="loading" | |
| initial={{ opacity: 0, scale: 0.8 }} | |
| animate={{ opacity: 1, scale: 1 }} | |
| exit={{ opacity: 0, scale: 0.8 }} | |
| className="flex items-center gap-2" | |
| > | |
| <motion.div | |
| animate={{ rotate: 360 }} | |
| transition={{ duration: 1, repeat: Infinity, ease: "linear" }} | |
| > | |
| <Download className="h-4 w-4" /> | |
| </motion.div> | |
| Downloading... | |
| </motion.div> | |
| ) : ( | |
| <motion.div | |
| key="default" | |
| initial={{ opacity: 0, scale: 0.8 }} | |
| animate={{ opacity: 1, scale: 1 }} | |
| exit={{ opacity: 0, scale: 0.8 }} | |
| className="flex items-center gap-2" | |
| > | |
| <Braces className="h-4 w-4" /> | |
| Download JSON | |
| </motion.div> | |
| )} | |
| </AnimatePresence> | |
| </Button> | |
| {/* XML Download */} | |
| <Button | |
| onClick={() => handleDownload("xml")} | |
| disabled={downloading === "xml"} | |
| variant="outline" | |
| className={cn( | |
| "h-11 px-5 rounded-xl font-semibold transition-all duration-200", | |
| "border-2 border-slate-200 hover:border-slate-300", | |
| "hover:bg-slate-50" | |
| )} | |
| > | |
| <AnimatePresence mode="wait"> | |
| {downloading === "xml" ? ( | |
| <motion.div | |
| key="loading" | |
| initial={{ opacity: 0, scale: 0.8 }} | |
| animate={{ opacity: 1, scale: 1 }} | |
| exit={{ opacity: 0, scale: 0.8 }} | |
| className="flex items-center gap-2" | |
| > | |
| <motion.div | |
| animate={{ rotate: 360 }} | |
| transition={{ duration: 1, repeat: Infinity, ease: "linear" }} | |
| > | |
| <Download className="h-4 w-4" /> | |
| </motion.div> | |
| Downloading... | |
| </motion.div> | |
| ) : ( | |
| <motion.div | |
| key="default" | |
| initial={{ opacity: 0, scale: 0.8 }} | |
| animate={{ opacity: 1, scale: 1 }} | |
| exit={{ opacity: 0, scale: 0.8 }} | |
| className="flex items-center gap-2" | |
| > | |
| <FileCode2 className="h-4 w-4" /> | |
| Download XML | |
| </motion.div> | |
| )} | |
| </AnimatePresence> | |
| </Button> | |
| {/* More Options Dropdown */} | |
| <DropdownMenu> | |
| <DropdownMenuTrigger asChild> | |
| <Button variant="ghost" className="h-11 w-11 rounded-xl"> | |
| <Share2 className="h-4 w-4" /> | |
| </Button> | |
| </DropdownMenuTrigger> | |
| <DropdownMenuContent align="end" className="w-48 rounded-xl p-2"> | |
| <DropdownMenuItem | |
| className="rounded-lg cursor-pointer" | |
| onClick={handleCopyLink} | |
| > | |
| {copied ? ( | |
| <Check className="h-4 w-4 mr-2 text-emerald-500" /> | |
| ) : ( | |
| <Link2 className="h-4 w-4 mr-2" /> | |
| )} | |
| {copied ? "Link copied!" : "Copy share link"} | |
| </DropdownMenuItem> | |
| <DropdownMenuItem className="rounded-lg cursor-pointer"> | |
| <Copy className="h-4 w-4 mr-2" /> | |
| Copy to clipboard | |
| </DropdownMenuItem> | |
| <DropdownMenuSeparator /> | |
| <DropdownMenuItem className="rounded-lg cursor-pointer"> | |
| <Mail className="h-4 w-4 mr-2" /> | |
| Send via email | |
| </DropdownMenuItem> | |
| <DropdownMenuItem className="rounded-lg cursor-pointer"> | |
| <FileJson className="h-4 w-4 mr-2" /> | |
| Export to Google Sheets | |
| </DropdownMenuItem> | |
| </DropdownMenuContent> | |
| </DropdownMenu> | |
| </motion.div> | |
| ); | |
| } | |