import React, { useState, useEffect, useMemo, useCallback } from "react";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import {
ShoppingCart,
UserPlus,
AlertCircle,
Package,
DollarSign,
FileText,
XCircle,
ChevronRight,
Tag,
Box,
Activity,
RefreshCcw,
} from "lucide-react";
import { DateTime } from "luxon";
import { Skeleton } from "@/components/ui/skeleton";
const LoadingState = () => (
{[...Array(5)].map((_, i) => (
))}
);
const formatCurrency = (value) => {
if (!value || isNaN(value)) return "$0.00";
return new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}).format(value);
};
const formatShipMethod = (method) => {
if (!method) return "Standard Shipping";
return method
.replace("usps_", "USPS ")
.replace("ups_", "UPS ")
.replace("fedex_", "FedEx ")
.replace(/_/g, " ")
.split(" ")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");
};
const formatShipMethodSimple = (method) => {
if (!method) return 'Standard';
if (method.includes('usps')) return 'USPS';
if (method.includes('fedex')) return 'FedEx';
if (method.includes('ups')) return 'UPS';
return 'Standard';
};
const PromotionalInfo = ({ details }) => {
if (!details?.PromosUsedReg?.length && !details?.PointsDiscount) return null;
return (
Savings Applied
{Array.isArray(details.PromosUsedReg) &&
details.PromosUsedReg.map(([code, amount], index) => (
{code}
-{formatCurrency(amount)}
))}
{details.PointsDiscount > 0 && (
Points Discount
-{formatCurrency(details.PointsDiscount)}
)}
);
};
const EmptyState = () => (
No activity yet today
Recent activity will appear here as it happens
);
const ProductCard = ({ product }) => (
{product.ProductName || 'Unnamed Product'}
{product.ItemStatus === "Pre-Order" && (
Pre-order
)}
{product.Brand && (
{product.Brand}
)}
{product.SKU && (
SKU: {product.SKU}
)}
{formatCurrency(product.ItemPrice)}
Qty: {product.Quantity || product.QuantityOrdered || 1}
{product.RowTotal && (
Total: {formatCurrency(product.RowTotal)}
)}
);
const OrderSummary = ({ details }) => (
Subtotal
Items ({details.Items?.length || 0})
{formatCurrency(details.Subtotal)}
{details.PointsDiscount > 0 && (
Points Discount
-{formatCurrency(details.PointsDiscount)}
)}
{details.TotalDiscounts > 0 && (
Discounts
-{formatCurrency(details.TotalDiscounts)}
)}
Shipping
Shipping Cost
{formatCurrency(details.ShippingTotal)}
{details.RushFee > 0 && (
Rush Fee
{formatCurrency(details.RushFee)}
)}
{details.SalesTax > 0 && (
Sales Tax
{formatCurrency(details.SalesTax)}
)}
Total
{details.TotalSavings > 0 && (
You saved {formatCurrency(details.TotalSavings)}
)}
{formatCurrency(details.TotalAmount)}
{details.Payments?.length > 0 && (
Payment Details
{details.Payments.map(([method, amount], index) => (
{method}
{formatCurrency(amount)}
))}
)}
);
const ShippingInfo = ({ details }) => (
Shipping Address
{details.ShippingName || 'Customer'}
{details.ShippingStreet1}
{details.ShippingStreet2 &&
{details.ShippingStreet2}
}
{details.ShippingCity}, {details.ShippingState} {details.ShippingZip}
{details.ShippingCountry !== "US" && (
{details.ShippingCountry}
)}
{details.TrackingNumber && (
Tracking Information
{formatShipMethod(details.ShipMethod)}
{details.TrackingNumber}
)}
);
const OrderStatusTags = ({ details }) => (
{details.HasPreorder && (
Includes Pre-order
)}
{details.LocalPickup && (
Local Pickup
)}
{details.IsOnHold && (
On Hold
)}
{details.HasDigiItem && (
Digital Items
)}
{details.HasNotions && (
Includes Notions
)}
{details.HasDigitalGC && (
Gift Card
)}
{details.StillOwes && (
Payment Due
)}
{details.PaymentsHasCustomerCredit && (
Store Credit Used
)}
{details.WasHeld && (
Was On Hold
)}
{details.IsShorted && (
Partial Shipment
)}
);
const EventFeed = () => {
const [events, setEvents] = useState([]);
const [selectedEvent, setSelectedEvent] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
const [lastUpdate, setLastUpdate] = useState(null);
// Updated fetchEvents function to handle a simpler response
const fetchEvents = async () => {
try {
setIsLoading(true);
const response = await fetch("/api/klaviyo/events/feed");
if (!response.ok) {
throw new Error(`Failed to fetch events: ${response.status}`);
}
const data = await response.json();
// Handle both possible response formats
const eventData = data.data || data;
if (!Array.isArray(eventData)) {
throw new Error('Invalid event data format - expected an array');
}
// Process the events
const processedEvents = eventData
.filter(event => event && event.type && event.timestamp) // Filter out invalid events
.map(event => ({
id: event.id,
type: event.type.toLowerCase(),
timestamp: DateTime.fromISO(event.timestamp),
details: {
OrderId: event.details?.OrderId || event.details?.FromOrder || 'Unknown',
ShippingName: event.details?.ShippingName || event.details?.EmailAddress || 'Unknown Customer',
EmailAddress: event.details?.EmailAddress || '',
TotalAmount: parseFloat(event.details?.TotalAmount || event.details?.PaymentAmount) || 0,
Items: Array.isArray(event.details?.Items) ? event.details.Items.map(item => ({
...item,
ItemPrice: parseFloat(item.ItemPrice) || 0,
Quantity: parseInt(item.Quantity) || 1,
RowTotal: parseFloat(item.RowTotal) || parseFloat(item.ItemPrice) * (parseInt(item.Quantity) || 1)
})) : [],
HasPreorder: event.details?.HasPreorder || event.details?.Items?.some(item => item.ItemStatus === 'Pre-Order'),
LocalPickup: !!event.details?.LocalPickup,
IsOnHold: !!event.details?.IsOnHold,
TrackingNumber: event.details?.TrackingNumber,
ShipMethod: event.details?.ShipMethod,
PaymentMethod: event.details?.PaymentMethod,
...event.details
}
}))
.sort((a, b) => b.timestamp - a.timestamp);
setEvents(processedEvents);
setLastUpdate(DateTime.now());
setError(null);
} catch (err) {
console.error("[EVENT FEED] Error:", err);
setError(err.message);
} finally {
setIsLoading(false);
}
};
useEffect(() => {
fetchEvents();
const interval = setInterval(fetchEvents, 60000);
return () => clearInterval(interval);
}, []);
const getEventIcon = (type) => {
switch (type) {
case "placed_order":
return ;
case "shipped_order":
return ;
case "account_created":
return ;
case "canceled_order":
return ;
case "payment_refunded":
return ;
case "new_blog_post":
return ;
default:
return ;
}
};
const getEventColor = (type) => {
switch (type) {
case "placed_order":
return "bg-green-500";
case "shipped_order":
return "bg-purple-500";
case "account_created":
return "bg-blue-500";
case "canceled_order":
return "bg-red-500";
case "payment_refunded":
return "bg-orange-500";
case "new_blog_post":
return "bg-yellow-500";
default:
return "bg-gray-500";
}
};
const getEventTitle = (type) => {
switch (type) {
case "placed_order":
return "Order Placed";
case "shipped_order":
return "Order Shipped";
case "account_created":
return "Account Created";
case "canceled_order":
return "Order Canceled";
case "payment_refunded":
return "Payment Refunded";
case "new_blog_post":
return "New Blog Post";
default:
return "Event";
}
};
const ShipmentStatus = ({ status, quantity }) => {
const getStatusInfo = (status) => {
switch (status?.toLowerCase()) {
case "shipped":
return {
color: "bg-green-100 text-green-800 dark:bg-green-900/20 dark:text-green-400",
};
case "partial":
return {
color: "bg-yellow-100 text-yellow-800 dark:bg-yellow-900/20 dark:text-yellow-400",
};
case "pre-order":
return {
color: "bg-blue-100 text-blue-800 dark:bg-blue-900/20 dark:text-blue-400",
};
case "refunded":
return {
color: "bg-red-100 text-red-800 dark:bg-red-900/20 dark:text-red-400",
};
default:
return {
color: "bg-gray-100 text-gray-800 dark:bg-gray-900/20 dark:text-gray-400",
};
}
};
const statusInfo = getStatusInfo(status);
return (
{status} {quantity > 1 && `(${quantity})`}
);
};
const renderEventInlineInfo = useCallback((event) => {
const details = event.details || {};
switch (event.type) {
case 'placed_order':
return (
{details.ShippingName}
•
#{details.OrderId}
{formatCurrency(details.TotalAmount)}
•
{details.Items?.length || 0} items
);
case 'shipped_order':
return (
<>
{details.ShippingName}
•
#{details.OrderId}
{formatShipMethodSimple(details.ShipMethod)}
{details.TrackingNumber && (
<>
•
{details.TrackingNumber}
>
)}
>
);
case "account_created":
return (
<>
{details.FirstName || ''} {details.LastName || ''}
{details.EmailAddress}
>
);
case "canceled_order":
return (
<>
{details.ShippingName}
•
#{details.OrderId}
{details.CancelReason || details.CancelMessage || "No reason provided"}
>
);
case "payment_refunded":
return (
<>
{details.FirstName || ''} {details.LastName || ''}
•
Order #{details.FromOrder}
{formatCurrency(details.PaymentAmount)}
•
{details.PaymentName}
>
);
case "new_blog_post":
return (
<>
{details.title}
{details.description}
>
);
default:
return (
No details available
);
}
}, []);
const renderEventDetails = (event) => {
const details = event.details || {};
switch (event.type) {
case 'placed_order':
return (
{details.BillingName && details.BillingName !== details.ShippingName && (
Billing Address
{details.BillingName}
{details.BillingStreet1}
{details.BillingStreet2 &&
{details.BillingStreet2}
}
{details.BillingCity}, {details.BillingState} {details.BillingZip}
)}
{details.Items?.length > 0 && (
Order Items ({details.Items.length})
{details.Items.map((item, index) => (
{item.ImgThumb && (
)}
{item.ProductName}
{item.ItemStatus === 'Pre-Order' && (
Pre-order {item.ItemEta && `(ETA: ${item.ItemEta})`}
)}
SKU: {item.SKU}
{item.Brand &&
Brand: {item.Brand}
}
Qty: {item.Quantity} × {formatCurrency(item.ItemPrice)}
{item.Categories?.length > 0 && (
{item.Categories.map((category, idx) => (
{category}
))}
)}
{formatCurrency(item.RowTotal)}
))}
)}
);
case "shipped_order":
return (
Shipment Details
Shipped via {formatShipMethod(details.ShipMethod)}
{details.TrackingNumber && (
Tracking Number:
{details.TrackingNumber}
)}
{details.Items?.length > 0 && (
Shipped Items ({details.Items.length})
{details.Items.map((item, index) => (
0 ? "Partial" : "Shipped",
}}
/>
))}
)}
);
case "account_created":
return (
{details.FirstName} {details.LastName}
{details.EmailAddress}
);
case "canceled_order":
return (
Cancellation Details
{(details.CancelReason || details.CancelMessage) && (
{details.CancelReason || details.CancelMessage}
)}
{details.Items?.length > 0 && (
Canceled Items ({details.Items.length})
{details.Items.map((item, index) => (
))}
)}
);
case "payment_refunded":
return (
Refund Details
Customer
{details.FirstName} {details.LastName}
Original Order
#{details.FromOrder}
Payment Method
{details.PaymentName}
Refund Amount
{formatCurrency(details.PaymentAmount)}
{details.OrderMessage && (
Refund Reason
{details.OrderMessage}
)}
{details.EmailAddress && (
Email:
{details.EmailAddress}
)}
{/* If there are refunded items */}
{details.RefundedItems?.length > 0 && (
Refunded Items ({details.RefundedItems.length})
{details.RefundedItems.map((item, index) => (
))}
)}
);
case "new_blog_post":
return (
{details.title}
{details.description && (
"),
}}
/>
)}
);
default:
return (
{JSON.stringify(details, null, 2)}
);
}
};
const renderContent = useMemo(() => {
if (isLoading && events.length === 0) {
return ;
}
if (error) {
return (
Error Loading Feed
{error}
Try Again
);
}
if (!events || events.length === 0) {
return ;
}
return (
{events.map((event) => (
setSelectedEvent(event)}
>
{getEventIcon(event.type)}
{getEventTitle(event.type)}
{renderEventInlineInfo(event)}
{event.timestamp instanceof DateTime
? event.timestamp.toFormat("h:mm a")
: DateTime.fromISO(event.timestamp).toFormat("h:mm a")}
))}
);
}, [events, isLoading, error, renderEventInlineInfo]);
return (
<>
Activity Feed
{lastUpdate && (
Last updated: {lastUpdate.toFormat("hh:mm a")}
)}
{renderContent}
{selectedEvent && (
setSelectedEvent(null)}
>
{getEventIcon(selectedEvent.type)}
{getEventTitle(selectedEvent.type)}
{selectedEvent.timestamp.toFormat('MMMM d, yyyy - h:mm a')}
{renderEventDetails(selectedEvent)}
)}
>
);
};
export default EventFeed;