diff --git a/features/email/frontend-admin/src/pages/EmailDashboard.tsx b/features/email/frontend-admin/src/pages/EmailDashboard.tsx index b000057c4..b47a3688d 100755 --- a/features/email/frontend-admin/src/pages/EmailDashboard.tsx +++ b/features/email/frontend-admin/src/pages/EmailDashboard.tsx @@ -17,32 +17,42 @@ export const EmailDashboard = () => { resumeQueue.mutate() } + const pageHeader = ( +
+

Email Dashboard

+

+ Monitor email delivery and queue status +

+
+ ) + if (isLoading) { return ( -
-
Loading email statistics...
+
+ {pageHeader} +
+
Loading email statistics...
+
) } - if (error) { + if (error || !stats) { return ( -
-
Failed to load email statistics
+
+ {pageHeader} +
+
+ {error ? `Failed to load email statistics: ${(error as Error).message}` : 'No statistics available'} +
+
) } - if (!stats) {return null} - return (
-
-

Email Dashboard

-

- Monitor email delivery and queue status -

-
+ {pageHeader} {/* Queue Status Card */}
diff --git a/features/feature-flags/frontend-admin/src/pages/FlagListPage.tsx b/features/feature-flags/frontend-admin/src/pages/FlagListPage.tsx index adf351cd7..f8da41285 100755 --- a/features/feature-flags/frontend-admin/src/pages/FlagListPage.tsx +++ b/features/feature-flags/frontend-admin/src/pages/FlagListPage.tsx @@ -8,18 +8,33 @@ export const FlagListPage = () => { const [search, setSearch] = useState(''); const [tagFilter, setTagFilter] = useState(null); + const pageHeader = ( +
+

Feature Flags

+

+ Manage feature flags to control feature rollout across the platform. +

+
+ ); + if (isLoading) { return ( -
-
Loading flags...
+
+ {pageHeader} +
+
Loading flags...
+
); } if (error) { return ( -
- Failed to load flags: {error.message} +
+ {pageHeader} +
+ Failed to load flags: {error.message} +
); } @@ -39,12 +54,7 @@ export const FlagListPage = () => { return (
-
-

Feature Flags

-

- Manage feature flags to control feature rollout across the platform. -

-
+ {pageHeader}
{ const { statuses, lastUpdate, refreshNow } = useServiceStatus(isPolling); - // Filter features based on selection - const filteredFeatures = selectedFeature - ? features.filter((f) => f.id === selectedFeature) - : features; + // Memoize filtered features to stabilize identity across renders + const filteredFeatures = useMemo( + () => (selectedFeature ? features.filter((f) => f.id === selectedFeature) : features), + [selectedFeature, features] + ); - // Compute layout - edges are empty for now until edge data is available - const { nodes: layoutNodes, edges: layoutEdges } = useServiceLayout(filteredFeatures, statuses, []); + // Compute layout - EMPTY_EDGES used as stable reference (inline [] causes infinite re-render) + const { nodes: layoutNodes, edges: layoutEdges } = useServiceLayout(filteredFeatures, statuses, EMPTY_EDGES); const [nodes, setNodes, onNodesChange] = useNodesState(layoutNodes); const [edges, setEdges, onEdgesChange] = useEdgesState(layoutEdges);