import React, { useState, useMemo, useCallback, useRef, useEffect } from 'react'; import { Toaster } from 'react-hot-toast'; import { FixedSizeList as List, ListChildComponentProps } from 'react-window'; import { filterKeywords, keywordsByDevice, sortKeywords } from '../../utils/client/sortFilter'; import Icon from '../common/Icon'; import Keyword from './Keyword'; import KeywordDetails from './KeywordDetails'; import KeywordFilters from './KeywordFilter'; import Modal from '../common/Modal'; import { useDeleteKeywords, useFavKeywords, useRefreshKeywords } from '../../services/keywords'; import KeywordTagManager from './KeywordTagManager'; import AddTags from './AddTags'; import useWindowResize from '../../hooks/useWindowResize'; import useIsMobile from '../../hooks/useIsMobile'; import { useUpdateSettings } from '../../services/settings'; import { defaultSettings } from '../settings/Settings'; type KeywordsTableProps = { domain: DomainType | null, keywords: KeywordType[], isLoading: boolean, showAddModal: boolean, setShowAddModal: Function, isConsoleIntegrated: boolean, settings?: SettingsType } const KeywordsTable = (props: KeywordsTableProps) => { const titleColumnRef = useRef(null); const { keywords = [], isLoading = true, isConsoleIntegrated = false, settings } = props; const showSCData = isConsoleIntegrated; const [device, setDevice] = useState('desktop'); const [selectedKeywords, setSelectedKeywords] = useState([]); const [showKeyDetails, setShowKeyDetails] = useState(null); const [showRemoveModal, setShowRemoveModal] = useState(false); const [showTagManager, setShowTagManager] = useState(null); const [showAddTags, setShowAddTags] = useState(false); const [SCListHeight, setSCListHeight] = useState(500); const [filterParams, setFilterParams] = useState({ countries: [], tags: [], search: '' }); const [sortBy, setSortBy] = useState('date_asc'); const [scDataType, setScDataType] = useState('threeDays'); const [showScDataTypes, setShowScDataTypes] = useState(false); const [maxTitleColumnWidth, setMaxTitleColumnWidth] = useState(235); const { mutate: deleteMutate } = useDeleteKeywords(() => {}); const { mutate: favoriteMutate } = useFavKeywords(() => {}); const { mutate: refreshMutate } = useRefreshKeywords(() => {}); const [isMobile] = useIsMobile(); useWindowResize(() => { setSCListHeight(window.innerHeight - (isMobile ? 200 : 400)); if (titleColumnRef.current) { setMaxTitleColumnWidth((titleColumnRef.current as HTMLElement).clientWidth); } }); useEffect(() => { if (titleColumnRef.current) { setMaxTitleColumnWidth((titleColumnRef.current as HTMLElement).clientWidth); } }, [titleColumnRef]); const tableColumns = settings?.keywordsColumns || ['Best', 'History', 'Volume', 'Search Console']; const { mutate: updateMutate, isLoading: isUpdatingSettings } = useUpdateSettings(() => console.log('')); const scDataObject:{ [k:string] : string} = { threeDays: 'Last Three Days', sevenDays: 'Last Seven Days', thirtyDays: 'Last Thirty Days', avgThreeDays: 'Last Three Days Avg', avgSevenDays: 'Last Seven Days Avg', avgThirtyDays: 'Last Thirty Days Avg', }; const processedKeywords: {[key:string] : KeywordType[]} = useMemo(() => { const procKeywords = keywords.filter((x) => x.device === device); const filteredKeywords = filterKeywords(procKeywords, filterParams); const sortedKeywords = sortKeywords(filteredKeywords, sortBy, scDataType); return keywordsByDevice(sortedKeywords, device); }, [keywords, device, sortBy, filterParams, scDataType]); const allDomainTags: string[] = useMemo(() => { const allTags = keywords.reduce((acc: string[], keyword) => [...acc, ...keyword.tags], []).filter((t) => t && t.trim() !== ''); return [...new Set(allTags)]; }, [keywords]); const selectKeyword = (keywordID: number) => { console.log('Select Keyword: ', keywordID); let updatedSelectd = [...selectedKeywords, keywordID]; if (selectedKeywords.includes(keywordID)) { updatedSelectd = selectedKeywords.filter((keyID) => keyID !== keywordID); } setSelectedKeywords(updatedSelectd); }; const updateColumns = (column:string) => { const newColumns = tableColumns.includes(column) ? tableColumns.filter((col) => col !== column) : [...tableColumns, column]; updateMutate({ ...defaultSettings, ...settings, keywordsColumns: newColumns }); }; const shouldHideColumn = useCallback((col:string) => { return settings?.keywordsColumns && !settings?.keywordsColumns.includes(col) ? 'lg:hidden' : ''; }, [settings?.keywordsColumns]); const Row = ({ data, index, style }:ListChildComponentProps) => { const keyword = data[index]; return ( refreshMutate({ ids: [keyword.ID] })} favoriteKeyword={favoriteMutate} manageTags={() => setShowTagManager(keyword.ID)} removeKeyword={() => { setSelectedKeywords([keyword.ID]); setShowRemoveModal(true); }} showKeywordDetails={() => setShowKeyDetails(keyword)} lastItem={index === (processedKeywords[device].length - 1)} showSCData={showSCData} scDataType={scDataType} tableColumns={tableColumns} maxTitleColumnWidth={maxTitleColumnWidth} /> ); }; const selectedAllItems = selectedKeywords.length === processedKeywords[device].length; return (
{selectedKeywords.length > 0 && ( )} {selectedKeywords.length === 0 && ( setFilterParams(params)} updateSort={(sorted:string) => setSortBy(sorted)} sortBy={sortBy} keywords={keywords} device={device} setDevice={setDevice} updateColumns={updateColumns} tableColumns={tableColumns} integratedConsole={isConsoleIntegrated} /> )}
{processedKeywords[device] && processedKeywords[device].length > 0 && ( {Row} )} {!isLoading && processedKeywords[device].length === 0 && (

No Keywords Added for this Device Type.

)} {isLoading && (

Loading Keywords...

)}
{showKeyDetails && showKeyDetails.ID && ( setShowKeyDetails(null)} /> )} {showRemoveModal && selectedKeywords.length > 0 && ( { setSelectedKeywords([]); setShowRemoveModal(false); }} title={'Remove Keywords'}>

Are you sure you want to remove {selectedKeywords.length > 1 ? 'these' : 'this'} Keyword?

)} {showTagManager && ( k.ID === showTagManager)} closeModal={() => setShowTagManager(null)} /> )} {showAddTags && ( selectedKeywords.includes(k.ID))} closeModal={() => setShowAddTags(false)} /> )}
); }; export default KeywordsTable;