import {useState} from 'react' import {Text, Stack, Box, Card, Label, Flex, TabList, Tab, TabPanel, Spinner} from '@sanity/ui' import {useQuery} from 'react-query' import {get} from 'lodash-es' import asyncCall from './lib/asyncCall' import performSeoReview from './lib/performSeoReview' import {renderRatingToColor} from './lib/renderRatingToColor' import {resultsLabels} from './lib/resultsLabels' import ErrorStack from './ErrorStack.jsx' import SERPPreview from './SERPPreview.js' import Feedback from './Feedback' import {SEOPaneOptions, SEOPaneProps} from './SEOPane' // @ts-ignore export default function SEOPaneComponent(props: SEOPaneProps) { const {document: sanityDocument, options} = props const [tab, setTab] = useState('') // The `revision` key updates when the document does, refreshing the query const {data, isLoading, error} = useQuery( [`seoReview`, sanityDocument._rev], async () => { if (!sanityDocument._id) { throw new Error('Document is not published') } else if (!options.url) { badOption('url') } // eslint-disable-next-line prefer-const let [keywords, synonyms, url] = await Promise.all([ asyncCall(options.keywords, sanityDocument) as Promise, asyncCall(options.synonyms, sanityDocument) as Promise, asyncCall(options.url, sanityDocument) as Promise, ]) // Visits document path when strings because the asyncCall will have same value as options if (keywords && keywords === options.keywords) keywords = get(sanityDocument, keywords) if (synonyms && synonyms === options.synonyms) synonyms = get(sanityDocument, synonyms) // Tack on keywords and synonyms to seo review response since we use them. return { ...(await performSeoReview(url, keywords, synonyms)), keywords, synonyms, } }, {keepPreviousData: true} ) // Will only show on the first render because of `keepPreviousData` above if (isLoading) { return ( ) } // Bail out on error if (error instanceof Error) { return ( {error.message} {error.stack ? : null} ) } else if (!data) { return Empty response } const {keywords, meta, permalink, resultsMapped, synonyms} = data as any return ( {meta?.title && ( )} {keywords ? `"${keywords}"` : `Not Defined`} {synonyms ? `"${synonyms}"` : `Not Defined`} {Object.keys(resultsMapped).map((key, tabIndex) => ( setTab(key)} selected={tab === key || (!tab && !tabIndex)} /> ))} {Object.keys(resultsMapped).map((key, panelIndex) => (