|
1 | 1 | import React from 'react';
|
2 | 2 | import WebMetrics from './WebMetrics';
|
3 | 3 |
|
4 |
| -/* |
5 |
| - Used to render a container for all of the 'Web Metrics' tab |
6 |
| -*/ |
7 |
| - |
8 | 4 | const WebMetricsContainer = (props) => {
|
9 | 5 | const { webMetrics } = props;
|
| 6 | + // Add default values for all color variables |
| 7 | + let LCPColor = '#fc2000'; // Default to poor/red |
| 8 | + let FIDColor = '#fc2000'; |
| 9 | + let FCPColor = '#fc2000'; |
| 10 | + let TTFBColor = '#fc2000'; |
| 11 | + let CLSColor = '#fc2000'; |
| 12 | + let INPColor = '#fc2000'; |
10 | 13 |
|
11 |
| - let LCPColor: String; |
12 |
| - let FIDColor: String; |
13 |
| - let FCPColor: String; |
14 |
| - let TTFBColor: String; |
15 |
| - let CLSColor: String; |
16 |
| - let INPColor: String; |
17 |
| - |
18 |
| - // adjust the strings that represent colors of the webmetrics performance bar for 'Largest Contentful Paint (LCP)', 'First Input Delay (FID)', 'First Contentfuly Paint (FCP)', 'Time to First Byte (TTFB)', 'Cumulative Layout Shift (CLS)', and 'Interaction to Next Paint (INP)' based on webMetrics outputs. |
19 |
| - if (webMetrics.LCP <= 2500) LCPColor = '#0bce6b'; |
20 |
| - if (webMetrics.LCP > 2500 && webMetrics.LCP <= 4000) LCPColor = '#fc5a03'; |
21 |
| - if (webMetrics.LCP > 4000) LCPColor = '#fc2000'; |
| 14 | + // Ensure webMetrics exists and has valid values |
| 15 | + if (webMetrics) { |
| 16 | + // LCP color logic |
| 17 | + if (typeof webMetrics.LCP === 'number') { |
| 18 | + if (webMetrics.LCP <= 2500) LCPColor = '#0bce6b'; |
| 19 | + else if (webMetrics.LCP <= 4000) LCPColor = '#fc5a03'; |
| 20 | + } |
22 | 21 |
|
23 |
| - if (webMetrics.FID <= 100) FIDColor = '#0bce6b'; |
24 |
| - if (webMetrics.FID > 100 && webMetrics.FID <= 300) FIDColor = '#fc5a03'; |
25 |
| - if (webMetrics.FID > 300) FIDColor = '#fc2000'; |
| 22 | + // FID color logic |
| 23 | + if (typeof webMetrics.FID === 'number') { |
| 24 | + if (webMetrics.FID <= 100) FIDColor = '#0bce6b'; |
| 25 | + else if (webMetrics.FID <= 300) FIDColor = '#fc5a03'; |
| 26 | + } |
26 | 27 |
|
27 |
| - if (webMetrics.FCP <= 1800) FCPColor = '#0bce6b'; |
28 |
| - if (webMetrics.FCP > 1800 && webMetrics.FCP <= 3000) FCPColor = '#fc5a03'; |
29 |
| - if (webMetrics.FCP > 3000) FCPColor = '#fc2000'; |
| 28 | + // FCP color logic |
| 29 | + if (typeof webMetrics.FCP === 'number') { |
| 30 | + if (webMetrics.FCP <= 1800) FCPColor = '#0bce6b'; |
| 31 | + else if (webMetrics.FCP <= 3000) FCPColor = '#fc5a03'; |
| 32 | + } |
30 | 33 |
|
31 |
| - if (webMetrics.TTFB <= 800) TTFBColor = '#0bce6b'; |
32 |
| - if (webMetrics.TTFB > 800 && webMetrics.TTFB <= 1800) TTFBColor = '#fc5a03'; |
33 |
| - if (webMetrics.TTFB > 1800) TTFBColor = '#fc2000'; |
| 34 | + // TTFB color logic |
| 35 | + if (typeof webMetrics.TTFB === 'number') { |
| 36 | + if (webMetrics.TTFB <= 800) TTFBColor = '#0bce6b'; |
| 37 | + else if (webMetrics.TTFB <= 1800) TTFBColor = '#fc5a03'; |
| 38 | + } |
34 | 39 |
|
35 |
| - if (webMetrics.CLS <= 0.1) CLSColor = '#0bce6b'; |
36 |
| - if (webMetrics.CLS > 0.1 && webMetrics.CLS <= 0.25) CLSColor = '#fc5a03'; |
37 |
| - if (webMetrics.CLS > 0.25) CLSColor = '#fc2000'; |
| 40 | + // CLS color logic |
| 41 | + if (typeof webMetrics.CLS === 'number') { |
| 42 | + if (webMetrics.CLS <= 0.1) CLSColor = '#0bce6b'; |
| 43 | + else if (webMetrics.CLS <= 0.25) CLSColor = '#fc5a03'; |
| 44 | + } |
38 | 45 |
|
39 |
| - if (webMetrics.INP <= 200) INPColor = '#0bce6b'; |
40 |
| - if (webMetrics.INP > 200 && webMetrics.INP <= 500) INPColor = '#fc5a03'; |
41 |
| - if (webMetrics.INP > 500) INPColor = '#fc2000'; |
| 46 | + // INP color logic |
| 47 | + if (typeof webMetrics.INP === 'number') { |
| 48 | + if (webMetrics.INP <= 200) INPColor = '#0bce6b'; |
| 49 | + else if (webMetrics.INP <= 500) INPColor = '#fc5a03'; |
| 50 | + } |
| 51 | + } |
42 | 52 |
|
43 | 53 | return (
|
44 | 54 | <div className='web-metrics-container'>
|
45 | 55 | <WebMetrics
|
46 | 56 | color={LCPColor}
|
47 |
| - series={webMetrics.LCP ? [webMetrics.LCP / 70 < 100 ? webMetrics.LCP / 70 : 100] : 0} |
48 |
| - formatted={(_) => |
| 57 | + series={webMetrics.LCP ? [webMetrics.LCP / 70 < 100 ? webMetrics.LCP / 70 : 100] : [0]} |
| 58 | + formatted={(value) => |
49 | 59 | typeof webMetrics.LCP !== 'number' ? '- ms' : `${webMetrics.LCP.toFixed(2)} ms`
|
50 | 60 | }
|
51 | 61 | score={['2500 ms', '4000 ms']}
|
52 |
| - overLimit={webMetrics.LCP > 7000} |
| 62 | + overLimit={webMetrics.LCP ? webMetrics.LCP > 7000 : false} |
53 | 63 | label='Largest Contentful Paint'
|
54 | 64 | name='Largest Contentful Paint'
|
55 | 65 | description='Measures loading performance.'
|
56 | 66 | />
|
57 | 67 | <WebMetrics
|
58 | 68 | color={FIDColor}
|
59 |
| - series={webMetrics.FID ? [webMetrics.FID / 5 < 100 ? webMetrics.FID / 5 : 100] : 0} |
60 |
| - formatted={(_) => |
| 69 | + series={webMetrics.FID ? [webMetrics.FID / 5 < 100 ? webMetrics.FID / 5 : 100] : [0]} |
| 70 | + formatted={(value) => |
61 | 71 | typeof webMetrics.FID !== 'number' ? '- ms' : `${webMetrics.FID.toFixed(2)} ms`
|
62 | 72 | }
|
63 | 73 | score={['100 ms', '300 ms']}
|
64 |
| - overLimit={webMetrics.FID > 500} |
| 74 | + overLimit={webMetrics.FID ? webMetrics.FID > 500 : false} |
65 | 75 | label='First Input Delay'
|
66 | 76 | name='First Input Delay'
|
67 | 77 | description='Measures interactivity.'
|
68 | 78 | />
|
69 | 79 | <WebMetrics
|
70 | 80 | color={FCPColor}
|
71 |
| - series={webMetrics.FCP ? [webMetrics.FCP / 50 < 100 ? webMetrics.FCP / 50 : 100] : 0} |
72 |
| - formatted={(_) => |
| 81 | + series={webMetrics.FCP ? [webMetrics.FCP / 50 < 100 ? webMetrics.FCP / 50 : 100] : [0]} |
| 82 | + formatted={(value) => |
73 | 83 | typeof webMetrics.FCP !== 'number' ? '- ms' : `${webMetrics.FCP.toFixed(2)} ms`
|
74 | 84 | }
|
75 | 85 | score={['1800 ms', '3000 ms']}
|
76 |
| - overLimit={webMetrics.FCP > 5000} |
| 86 | + overLimit={webMetrics.FCP ? webMetrics.FCP > 5000 : false} |
77 | 87 | label='First Contentful Paint'
|
78 | 88 | name='First Contentful Paint'
|
79 | 89 | description='Measures the time it takes the browser to render the first piece of DOM content.'
|
80 | 90 | />
|
81 | 91 | <WebMetrics
|
82 | 92 | color={TTFBColor}
|
83 |
| - series={webMetrics.TTFB ? [webMetrics.TTFB / 30 < 100 ? webMetrics.TTFB / 30 : 100] : 0} |
84 |
| - formatted={(_) => |
| 93 | + series={webMetrics.TTFB ? [webMetrics.TTFB / 30 < 100 ? webMetrics.TTFB / 30 : 100] : [0]} |
| 94 | + formatted={(value) => |
85 | 95 | typeof webMetrics.TTFB !== 'number' ? '- ms' : `${webMetrics.TTFB.toFixed(2)} ms`
|
86 | 96 | }
|
87 | 97 | score={['800 ms', '1800 ms']}
|
88 |
| - overLimit={webMetrics.TTFB > 3000} |
| 98 | + overLimit={webMetrics.TTFB ? webMetrics.TTFB > 3000 : false} |
89 | 99 | label='Time To First Byte'
|
90 | 100 | name='Time to First Byte'
|
91 | 101 | description='Measures the time it takes for a browser to receive the first byte of page content.'
|
92 | 102 | />
|
93 | 103 | <WebMetrics
|
94 | 104 | color={CLSColor}
|
95 |
| - series={webMetrics.CLS ? [webMetrics.CLS * 200 < 100 ? webMetrics.CLS * 200 : 100] : 0} |
96 |
| - formatted={(_) => |
| 105 | + series={webMetrics.CLS ? [webMetrics.CLS * 200 < 100 ? webMetrics.CLS * 200 : 100] : [0]} |
| 106 | + formatted={(value) => |
97 | 107 | `CLS Score: ${
|
98 | 108 | typeof webMetrics.CLS !== 'number'
|
99 | 109 | ? 'N/A'
|
100 | 110 | : `${webMetrics.CLS < 0.01 ? '~0' : webMetrics.CLS.toFixed(2)}`
|
101 | 111 | }`
|
102 | 112 | }
|
103 | 113 | score={['0.1', '0.25']}
|
104 |
| - overLimit={webMetrics.CLS > 0.5} |
| 114 | + overLimit={webMetrics.CLS ? webMetrics.CLS > 0.5 : false} |
105 | 115 | label='Cumulative Layout Shift'
|
106 | 116 | name='Cumulative Layout Shift'
|
107 | 117 | description={`Quantifies the visual stability of a web page by measuring layout shifts during the application's loading and interaction.`}
|
108 | 118 | />
|
109 | 119 | <WebMetrics
|
110 | 120 | color={INPColor}
|
111 |
| - series={webMetrics.INP ? [webMetrics.INP / 7 < 100 ? webMetrics.INP / 7 : 100] : 0} |
112 |
| - formatted={(_) => |
| 121 | + series={webMetrics.INP ? [webMetrics.INP / 7 < 100 ? webMetrics.INP / 7 : 100] : [0]} |
| 122 | + formatted={(value) => |
113 | 123 | typeof webMetrics.INP !== 'number' ? '- ms' : `${webMetrics.INP.toFixed(2)} ms`
|
114 | 124 | }
|
115 | 125 | score={['200 ms', '500 ms']}
|
116 |
| - overLimit={webMetrics.INP > 700} |
| 126 | + overLimit={webMetrics.INP ? webMetrics.INP > 700 : false} |
117 | 127 | label='Interaction to Next Paint'
|
118 | 128 | name='Interaction to Next Paint'
|
119 | 129 | description={`Assesses a page's overall responsiveness to user interactions by observing the latency of all click, tap, and keyboard interactions that occur throughout the lifespan of a user's visit to a page`}
|
|
0 commit comments