'use client'; import { useState, useEffect } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { Download, Loader2 } from 'lucide-react'; import { OrderRecord } from '@/src/types'; interface ExportButtonProps { currentOrders?: OrderRecord[]; filters?: { search?: string; status?: string; dateFrom?: string; dateTo?: string; }; } export function ExportButton({ currentOrders = [], filters = {} }: ExportButtonProps) { const [isExporting, setIsExporting] = useState(false); const [showDropdown, setShowDropdown] = useState(false); // Close dropdown on escape key useEffect(() => { const handleEscape = (e: KeyboardEvent) => { if (e.key === 'Escape') setShowDropdown(false); }; if (showDropdown) { document.addEventListener('keydown', handleEscape); return () => document.removeEventListener('keydown', handleEscape); } }, [showDropdown]); const formatDate = (dateString: string | undefined) => { if (!dateString) return ''; return new Date(dateString).toISOString(); }; const formatCurrency = (amount: string | undefined) => { if (!amount) return ''; return (parseFloat(amount) / 100).toFixed(2); }; const convertToCSV = (orders: OrderRecord[]): string => { if (orders.length === 0) return ''; // CSV Headers const headers = [ 'Order ID', 'Status', 'Source', 'Created At', 'Updated At', 'Customer Name', 'Customer Email', 'Customer Phone', 'Business Name', 'Tax ID Type', 'Tax ID Value', 'Base Amount', 'Processing Fee', 'Total Amount', 'Currency', 'Payment Method', 'Stripe Session ID', 'Stripe Payment Intent', 'Stripe Customer ID', 'CO2 Tons', 'Portfolio ID', 'Portfolio Name', 'Wren Order ID', 'Certificate URL', 'Fulfilled At', 'Billing Line 1', 'Billing Line 2', 'Billing City', 'Billing State', 'Billing Postal Code', 'Billing Country', 'Vessel Name', 'IMO Number', 'Vessel Type', 'Vessel Length', 'Departure Port', 'Arrival Port', 'Distance', 'Avg Speed', 'Duration', 'Engine Power', 'Notes', ]; // CSV Rows const rows = orders.map((order) => [ order.orderId, order.status, order.source || '', formatDate(order.CreatedAt), formatDate(order.UpdatedAt), order.customerName, order.customerEmail, order.customerPhone || '', order.businessName || '', order.taxIdType || '', order.taxIdValue || '', formatCurrency(order.baseAmount), formatCurrency(order.processingFee), formatCurrency(order.totalAmount), order.currency, order.paymentMethod || '', order.stripeSessionId || '', order.stripePaymentIntent || '', order.stripeCustomerId || '', parseFloat(order.co2Tons).toFixed(2), order.portfolioId, order.portfolioName || '', order.wrenOrderId || '', order.certificateUrl || '', formatDate(order.fulfilledAt), order.billingLine1 || '', order.billingLine2 || '', order.billingCity || '', order.billingState || '', order.billingPostalCode || '', order.billingCountry || '', order.vesselName || '', order.imoNumber || '', order.vesselType || '', order.vesselLength || '', order.departurePort || '', order.arrivalPort || '', order.distance || '', order.avgSpeed || '', order.duration || '', order.enginePower || '', order.notes || '', ]); // Escape CSV fields (handle commas, quotes, newlines) const escapeCSVField = (field: string | number) => { const stringField = String(field); if ( stringField.includes(',') || stringField.includes('"') || stringField.includes('\n') ) { return `"${stringField.replace(/"/g, '""')}"`; } return stringField; }; // Build CSV const csvContent = [ headers.map(escapeCSVField).join(','), ...rows.map((row) => row.map(escapeCSVField).join(',')), ].join('\n'); return csvContent; }; const downloadCSV = (csvContent: string, filename: string) => { const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); const link = document.createElement('a'); const url = URL.createObjectURL(blob); link.setAttribute('href', url); link.setAttribute('download', filename); link.style.visibility = 'hidden'; document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(url); }; const handleExportCurrent = () => { setIsExporting(true); setShowDropdown(false); try { const csvContent = convertToCSV(currentOrders); const timestamp = new Date().toISOString().split('T')[0]; const filename = `orders-current-${timestamp}.csv`; downloadCSV(csvContent, filename); } catch (error) { console.error('Export failed:', error); alert('Failed to export orders. Please try again.'); } finally { setTimeout(() => setIsExporting(false), 1000); } }; const handleExportAll = async () => { setIsExporting(true); setShowDropdown(false); try { // Build query params with current filters const params = new URLSearchParams(); params.append('limit', '10000'); // High limit to get all params.append('offset', '0'); if (filters.search) params.append('search', filters.search); if (filters.status) params.append('status', filters.status); if (filters.dateFrom) params.append('dateFrom', filters.dateFrom); if (filters.dateTo) params.append('dateTo', filters.dateTo); // Fetch all orders const response = await fetch(`/api/admin/orders?${params}`); const data = await response.json(); if (!response.ok) { throw new Error(data.error || 'Failed to fetch orders'); } const allOrders = data.data.list || []; const csvContent = convertToCSV(allOrders); const timestamp = new Date().toISOString().split('T')[0]; const filename = `orders-all-${timestamp}.csv`; downloadCSV(csvContent, filename); } catch (error) { console.error('Export failed:', error); alert('Failed to export all orders. Please try again.'); } finally { setTimeout(() => setIsExporting(false), 1000); } }; return (