import React, { useEffect, useRef, useState } from 'react'; import { LuCheck, LuCopy, LuFileText, LuHelpCircle, LuTag, LuType, LuWand2, } from 'react-icons/lu'; import { copyToClipboard } from '../../lib/clipboard'; import { faqPairsToHtml, htmlToPlainText, looksLikeHtml, } from '../../lib/inline-result-html'; import type { ContentCheckerFixResult } from '../../service/content-generator/content-generator.interface'; /** Rendered-description styling (mirrors the catalog-quality result card). */ const RENDERED_CLASS = 'space-y-2 text-sm leading-relaxed text-gray-900 [&_h1]:text-lg [&_h1]:font-semibold [&_h2]:mt-3 [&_h2]:font-semibold [&_h3]:mt-3 [&_h3]:font-semibold [&_h4]:font-semibold [&_p]:my-1 [&_ul]:list-disc [&_ul]:pl-5 [&_ol]:list-decimal [&_ol]:pl-5 [&_li]:my-0.5 [&_strong]:font-semibold'; /** How long the "Copied" state stays on a copy chip. */ const COPIED_FLASH_MS = 2000; /** Props for {@link CheckerFixCard}. */ interface CheckerFixCardProps { result: ContentCheckerFixResult; } /** Props for the small copy button used across the card's sections. */ interface CopyChipProps { label: string; copied: boolean; onCopy: () => void; } /** * Small outline copy button with a timed "Copied" state. * * @param {CopyChipProps} props - Label, copied flag, and click handler. * @return {JSX.Element} The copy button. */ const CopyChip = ({ label, copied, onCopy }: CopyChipProps): JSX.Element => ( ); /** * Full result of the Content Checker "Fix with AI" action: improved title, * rendered description, SEO fields, tags, and FAQ - each with its own copy * action so the merchant can paste fields straight into their store admin. * * @param {CheckerFixCardProps} props - The generated content row. * @return {JSX.Element} The fix result card. */ const CheckerFixCard = ({ result }: CheckerFixCardProps): JSX.Element => { const [copiedKey, setCopiedKey] = useState(null); const cardRef = useRef(null); useEffect(() => { cardRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' }); }, []); const copy = async (value: string, key: string): Promise => { if (await copyToClipboard(value)) { setCopiedKey(key); window.setTimeout(() => setCopiedKey(null), COPIED_FLASH_MS); } }; const descriptionIsHtml = looksLikeHtml(result.improved_description); const descriptionText = descriptionIsHtml ? htmlToPlainText(result.improved_description) : result.improved_description; const faqHtml = result.faq_pairs.length > 0 ? faqPairsToHtml(result.faq_pairs) : ''; const faqText = result.faq_pairs .map(pair => `Q: ${pair.q}\nA: ${pair.a}`) .join('\n\n'); const tagsText = result.tags.join(', '); const seoRows = [ { key: 'seo_title', label: 'SEO title', value: result.seo_title }, { key: 'seo_description', label: 'SEO description', value: result.seo_description, }, { key: 'short_description', label: 'Short description', value: result.short_description, }, ].filter(row => row.value.trim().length > 0); return (

AI Fix Ready to copy

Generated with your Product Content pipeline. Copy each field into your store admin.

{result.improved_title && (

Title

{result.improved_title}

void copy(result.improved_title, 'title')} />
)} {result.improved_description && (

Description

{descriptionIsHtml && ( void copy(result.improved_description, 'description-html') } /> )} void copy(descriptionText, 'description-text')} />
{descriptionIsHtml ? (
) : (

{result.improved_description}

)}
)} {seoRows.length > 0 && (
{seoRows.map(row => (

{row.label}

void copy(row.value, row.key)} />

{row.value}

))}
)} {result.tags.length > 0 && (

Tags

void copy(tagsText, 'tags')} />
{result.tags.map((tag, tagIndex) => ( {tag} ))}
)} {result.faq_pairs.length > 0 && (

FAQ

void copy(faqHtml, 'faq-html')} /> void copy(faqText, 'faq-text')} />
{result.faq_pairs.map((pair, pairIndex) => (

{pair.q}

{pair.a}

))}
)}
); }; export default CheckerFixCard;