import { useState } from 'react'; import { __, sprintf } from '@wordpress/i18n'; import clsx from 'clsx'; import Icon from '@/utils/Icon'; import { formatNumber } from '@/utils/formatting'; import type { SearchQueryRow } from '@/api/getSearchQueriesData'; import { getSearchQueryBarWidth } from './searchQueriesUtils'; const COLLAPSED_ROW_COUNT = 5; type SearchQueriesTableProps = { rows: SearchQueryRow[]; opportunity: SearchQueryRow | null; }; type SearchQueriesRowsProps = SearchQueriesTableProps & { maxClicks: number; }; type SearchQueriesToggleProps = { isExpanded: boolean; rowCount: number; onToggle: () => void; }; /** * Return rows in the order used by both the table and its expand control. */ const sortSearchQueryRows = ( rows: SearchQueryRow[]): SearchQueryRow[] => [ ...rows ].sort( ( first, second ) => second.clicks - first.clicks ); /** * Limit the initial table without changing the click-sorted source rows. */ const getVisibleSearchQueryRows = ( rows: SearchQueryRow[], isExpanded: boolean ): SearchQueryRow[] => isExpanded ? rows : rows.slice( 0, COLLAPSED_ROW_COUNT ); /** * Highest click count used to scale the relative row bars. */ const getMaxSearchQueryClicks = ( rows: SearchQueryRow[]): number => rows[ 0 ]?.clicks ?? 0; /** * Render the metric rows independently from the table controls. */ const SearchQueriesRows = ({ rows, opportunity, maxClicks }: SearchQueriesRowsProps ) => ( <> {rows.map( ( row ) => { const isOpportunity = opportunity?.query === row.query; const barWidth = getSearchQueryBarWidth( row.clicks, maxClicks ); return (

{ row.query }

{ formatNumber( row.clicks ) } { formatNumber( row.impressions ) } { formatNumber( row.position, 1, false ) } ); }) } ); /** * Expand or collapse query rows when more than the initial five are present. */ const SearchQueriesToggle = ({ isExpanded, rowCount, onToggle }: SearchQueriesToggleProps ) => { if ( rowCount <= COLLAPSED_ROW_COUNT ) { return null; } return ( ); }; /** * Displays click-sorted Search Console query rows with progressive disclosure. * * @param props - Component properties. * @param props.rows - Query rows. * @param props.opportunity - Opportunity row highlighted in amber. * @return Compact search query table. */ export const SearchQueriesTable = ({ rows, opportunity }: SearchQueriesTableProps ) => { const [ isExpanded, setIsExpanded ] = useState( false ); const sortedRows = sortSearchQueryRows( rows ); const visibleRows = getVisibleSearchQueryRows( sortedRows, isExpanded ); const maxClicks = getMaxSearchQueryClicks( sortedRows ); return (
{ __( 'Query', 'burst-statistics' ) } { __( 'Clicks', 'burst-statistics' ) } { __( 'Impr.', 'burst-statistics' ) } { __( 'Pos.', 'burst-statistics' ) }
setIsExpanded( ! isExpanded ) } />
); };