import { Helmet } from 'react-helmet-async'; import { useTranslation } from 'react-i18next'; import { CheckCircle } from 'lucide-react'; import { getToolSEO } from '@/config/seoData'; import { buildLanguageAlternates, generateToolSchema, generateBreadcrumbs, generateFAQ, getOgLocale } from '@/utils/seo'; import FAQSection from './FAQSection'; import RelatedTools from './RelatedTools'; import ToolRating from '@/components/shared/ToolRating'; import SharePanel from '@/components/shared/SharePanel'; import ToolWorkflowPanel from '@/components/shared/ToolWorkflowPanel'; import { useToolRating } from '@/hooks/useToolRating'; import { dispatchRatingPrompt } from '@/utils/ratingPrompt'; interface SEOFAQ { q: string; a: string; } interface ToolLandingPageProps { /** The tool slug matching seoData.ts entries */ slug: string; /** The actual tool component rendered inside the landing page */ children: React.ReactNode; } /** * SEO wrapper that adds structured data, FAQ section, related tools, * feature bullets, and proper meta tags around any tool component. */ export default function ToolLandingPage({ slug, children }: ToolLandingPageProps) { const { t, i18n } = useTranslation(); const seo = getToolSEO(slug); const ratingData = useToolRating(slug); // Fallback: just render tool without SEO wrapper if (!seo) return <>{children}; const toolTitle = t(`tools.${seo.i18nKey}.title`); const toolDesc = t(`tools.${seo.i18nKey}.description`); const origin = typeof window !== 'undefined' ? window.location.origin : ''; const path = `/tools/${slug}`; const canonicalUrl = `${origin}${path}`; const languageAlternates = buildLanguageAlternates(origin, path); const currentOgLocale = getOgLocale(i18n.language); const toolSchema = generateToolSchema({ name: toolTitle, description: seo.metaDescription, url: canonicalUrl, category: seo.category === 'PDF' ? 'UtilitiesApplication' : 'WebApplication', ratingValue: ratingData.average, ratingCount: ratingData.count, }); const breadcrumbSchema = generateBreadcrumbs([ { name: t('common.appName'), url: origin }, { name: seo.category, url: `${origin}/#${seo.category.toLowerCase()}` }, { name: toolTitle, url: canonicalUrl }, ]); const faqSchema = seo.faqs.length > 0 ? generateFAQ(seo.faqs) : null; return ( <> {toolTitle} — {seo.titleSuffix} | {t('common.appName')} {languageAlternates.map((alternate) => ( ))} {/* Open Graph */} {languageAlternates .filter((alternate) => alternate.ogLocale !== currentOgLocale) .map((alternate) => ( ))} {/* Twitter */} {/* Structured Data */} {faqSchema && ( )} {/* Tool Interface */} {children}
{/* SEO Content Below Tool */}
{/* What this tool does */}

{t('seo.headings.whatItDoes')}

{t(`seo.${seo.i18nKey}.whatItDoes`)}

{/* How to use */} {(() => { const steps = t(`seo.${seo.i18nKey}.howToUse`, { returnObjects: true }) as string[]; return Array.isArray(steps) && steps.length > 0 ? (

{t('seo.headings.howToUse')}

    {steps.map((step, idx) => (
  1. {step}
  2. ))}
) : null; })()} {/* Benefits */} {(() => { const benefits = t(`seo.${seo.i18nKey}.benefits`, { returnObjects: true }) as string[]; return Array.isArray(benefits) && benefits.length > 0 ? (

{t('seo.headings.whyUse', { tool: toolTitle })}

    {benefits.map((benefit, idx) => (
  • {benefit}
  • ))}
) : null; })()} {/* Common use cases */} {(() => { const useCases = t(`seo.${seo.i18nKey}.useCases`, { returnObjects: true }) as string[]; return Array.isArray(useCases) && useCases.length > 0 ? (

{t('seo.headings.useCases')}

    {useCases.map((useCase, idx) => (
  • {useCase}
  • ))}
) : null; })()} {/* FAQ Section */} {(() => { const faqData = t(`seo.${seo.i18nKey}.faq`, { returnObjects: true }) as SEOFAQ[]; const faqs = Array.isArray(faqData) ? faqData.map((f) => ({ question: f.q, answer: f.a })) : []; return ; })()} {/* Related Tools */} {/* User Rating */}
); }