"use client"; import React, { useState, useEffect, memo } from "react"; const WebVitalsDashboard = memo(() => { const [vitals, setVitals] = useState({ lcp: { value: 0, rating: "unknown" }, fid: { value: 0, rating: "unknown" }, cls: { value: 0, rating: "unknown" }, fcp: { value: 0, rating: "unknown" }, ttfb: { value: 0, rating: "unknown" }, }); const [metrics, setMetrics] = useState({}); const [loading, setLoading] = useState(true); useEffect(() => { // Fetch Web Vitals data from API const fetchVitals = async () => { try { const response = await fetch("/api/web-vitals"); const data = await response.json(); setMetrics(data.metrics || {}); } catch (error) { console.error("Error fetching web vitals:", error); } finally { setLoading(false); } }; fetchVitals(); // Set up Web Vitals tracking if (typeof window !== "undefined") { import("web-vitals").then( ({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { // Track Largest Contentful Paint getLCP((metric) => { setVitals((prev) => ({ ...prev, lcp: { value: Math.round(metric.value), rating: metric.rating, }, })); }); // Track First Input Delay getFID((metric) => { setVitals((prev) => ({ ...prev, fid: { value: Math.round(metric.value), rating: metric.rating, }, })); }); // Track Cumulative Layout Shift getCLS((metric) => { setVitals((prev) => ({ ...prev, cls: { value: Math.round(metric.value * 1000) / 1000, rating: metric.rating, }, })); }); // Track First Contentful Paint getFCP((metric) => { setVitals((prev) => ({ ...prev, fcp: { value: Math.round(metric.value), rating: metric.rating, }, })); }); // Track Time to First Byte getTTFB((metric) => { setVitals((prev) => ({ ...prev, ttfb: { value: Math.round(metric.value), rating: metric.rating, }, })); }); } ); } }, []); const getRatingColor = (rating) => { switch (rating) { case "good": return "text-green-600 bg-green-50"; case "needs-improvement": return "text-yellow-600 bg-yellow-50"; case "poor": return "text-red-600 bg-red-50"; default: return "text-gray-600 bg-gray-50"; } }; const getRatingIcon = (rating) => { switch (rating) { case "good": return "✅"; case "needs-improvement": return "⚠️"; case "poor": return "❌"; default: return "❓"; } }; const formatValue = (metric, value) => { if (metric === "cls") { return value.toFixed(3); } return `${value}ms`; }; if (loading) { return (