import React, { useState, useEffect, useCallback } from "react"; import gorgiasService from "../../services/gorgiasService"; import { getDateRange } from "../../utils/dateUtils"; import { Card, CardContent, CardHeader } from "@/components/ui/card"; import { Select, SelectTrigger, SelectContent, SelectItem, } from "@/components/ui/select"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { Skeleton } from "@/components/ui/skeleton"; import { Clock, Star, Users, MessageSquare, Mail, Send } from "lucide-react"; const TIME_RANGES = { 7: "Last 7 Days", 14: "Last 14 Days", 30: "Last 30 Days", 90: "Last 90 Days", }; const formatDuration = (seconds) => { const hours = Math.floor(seconds / 3600); const minutes = Math.floor((seconds % 3600) / 60); return hours > 0 ? `${hours}h ${minutes}m` : `${minutes}m`; }; const MetricCard = ({ title, value, delta, suffix = "", icon: Icon, colorClass = "blue", more_is_better = true, loading = false, }) => { const getDeltaColor = (d) => { if (d === 0) return "text-gray-600 dark:text-gray-400"; const isPositive = d > 0; return isPositive === more_is_better ? "text-green-600 dark:text-green-500" : "text-red-600 dark:text-red-500"; }; const formatDelta = (d) => { if (d === undefined || d === null) return null; if (d === 0) return "0"; return (d > 0 ? "+" : "") + d + suffix; }; const colorMapping = { blue: "bg-blue-50 dark:bg-blue-900/20 border-blue-100 dark:border-blue-800/50 text-blue-600 dark:text-blue-400", green: "bg-green-50 dark:bg-green-900/20 border-green-100 dark:border-green-800/50 text-green-600 dark:text-green-400", purple: "bg-purple-50 dark:bg-purple-900/20 border-purple-100 dark:border-purple-800/50 text-purple-600 dark:text-purple-400", indigo: "bg-indigo-50 dark:bg-indigo-900/20 border-indigo-100 dark:border-indigo-800/50 text-indigo-600 dark:text-indigo-400", orange: "bg-orange-50 dark:bg-orange-900/20 border-orange-100 dark:border-orange-800/50 text-orange-600 dark:text-orange-400", teal: "bg-teal-50 dark:bg-teal-900/20 border-teal-100 dark:border-teal-800/50 text-teal-600 dark:text-teal-400", cyan: "bg-cyan-50 dark:bg-cyan-900/20 border-cyan-100 dark:border-cyan-800/50 text-cyan-600 dark:text-cyan-400", }; const baseColors = colorMapping[colorClass]; return (

{title}

{loading ? ( ) : ( <>
{Icon && }

{typeof value === "number" ? value.toLocaleString() + suffix : value}

{delta !== undefined && (

{formatDelta(delta)}

)} )}
); }; const TableSkeleton = () => (
); const GorgiasSummary = () => { const [timeRange, setTimeRange] = useState(7); const [data, setData] = useState({}); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const loadStats = useCallback(async () => { setLoading(true); const filters = getDateRange(timeRange); try { const [overview, channelStats, agentStats, satisfaction, selfService] = await Promise.all([ gorgiasService.fetchStatistics("overview", filters), gorgiasService.fetchStatistics( "tickets-created-per-channel", filters ), gorgiasService.fetchStatistics("tickets-closed-per-agent", filters), gorgiasService.fetchStatistics("satisfaction-surveys", filters), gorgiasService.fetchStatistics("self-service-overview", filters), ]); setData({ overview: overview.data.data.data || [], channels: channelStats.data.data.data.lines || [], agents: agentStats.data.data.data.lines || [], satisfaction: satisfaction.data.data.data || [], selfService: selfService.data.data.data || [], }); setError(null); } catch (err) { console.error("Error loading stats:", err); setError(err.message); } finally { setLoading(false); } }, [timeRange]); useEffect(() => { loadStats(); // Set up auto-refresh every 5 minutes const interval = setInterval(loadStats, 5 * 60 * 1000); return () => clearInterval(interval); }, [loadStats]); // Convert overview array to object for easier access const stats = data.overview?.reduce((acc, item) => { acc[item.name] = item; return acc; }, {}) || {}; // Process satisfaction data const satisfactionStats = data.satisfaction?.reduce((acc, item) => { acc[item.name] = item; return acc; }, {}) || {}; // Process self-service data const selfServiceStats = data.selfService?.reduce((acc, item) => { acc[item.name] = item; return acc; }, {}) || {}; if (error) return

Error: {error}

; return (

Customer Service

{/* Message & Response Metrics */}
{/* Satisfaction & Efficiency */}
{/* Channel Distribution */}

Channel Distribution

{loading ? (
) : ( Channel Total % Δ {data.channels .sort((a, b) => b[1].value - a[1].value) .map((line, index) => ( {line[0].value} {line[1].value} {line[2].value}% 0 ? "text-green-600 dark:text-green-500" : line[3].value < 0 ? "text-red-600 dark:text-red-500" : "dark:text-gray-300" }`} > {line[3].value > 0 ? "+" : ""} {line[3].value} ))}
)}
{/* Agent Performance - Same dark mode updates */}

Agent Performance

{loading ? (
) : ( Agent Closed Rating Δ {data.agents .filter((line) => line[0].value !== "Unassigned") .map((line, index) => ( {line[0].value} {line[1].value} {line[2].value ? `${line[2].value}/5` : "-"} 0 ? "text-green-600 dark:text-green-500" : line[4].value < 0 ? "text-red-600 dark:text-red-500" : "dark:text-gray-300" }`} > {line[4].value > 0 ? "+" : ""} {line[4].value} ))}
)}
); }; export default GorgiasSummary;