Refactor code structure for improved readability and maintainability /SEO Content (3 languages, 32 tools each):

en.json — Full English SEO content added
ar.json — Full Arabic SEO content added
fr.json — Full French SEO content added
This commit is contained in:
Your Name
2026-03-09 00:07:03 +02:00
parent b5606c2d2d
commit b9900106b2
7 changed files with 1188 additions and 22 deletions

View File

@@ -1,5 +1,6 @@
import { useState } from 'react';
import { ChevronDown, ChevronUp } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import type { ToolFAQ } from '@/config/seoData';
interface FAQSectionProps {
@@ -7,6 +8,7 @@ interface FAQSectionProps {
}
export default function FAQSection({ faqs }: FAQSectionProps) {
const { t } = useTranslation();
const [openIndex, setOpenIndex] = useState<number | null>(0);
if (!faqs || faqs.length === 0) return null;
@@ -14,7 +16,7 @@ export default function FAQSection({ faqs }: FAQSectionProps) {
return (
<section className="mt-12">
<h2 className="mb-6 text-xl font-bold text-slate-900 dark:text-white">
Frequently Asked Questions
{t('seo.headings.faq')}
</h2>
<div className="divide-y divide-slate-200 rounded-xl border border-slate-200 bg-white dark:divide-slate-700 dark:border-slate-700 dark:bg-slate-800">
{faqs.map((faq, idx) => {

View File

@@ -1,4 +1,5 @@
import { Link } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { getToolSEO } from '@/config/seoData';
interface RelatedToolsProps {
@@ -14,6 +15,7 @@ const CATEGORY_COLORS: Record<string, string> = {
};
export default function RelatedTools({ currentSlug }: RelatedToolsProps) {
const { t } = useTranslation();
const currentTool = getToolSEO(currentSlug);
if (!currentTool) return null;
@@ -26,7 +28,7 @@ export default function RelatedTools({ currentSlug }: RelatedToolsProps) {
return (
<section className="mt-12">
<h2 className="mb-6 text-xl font-bold text-slate-900 dark:text-white">
Related Tools
{t('seo.headings.relatedTools')}
</h2>
<div className="grid gap-4 sm:grid-cols-2">
{relatedTools.map((tool) => (

View File

@@ -6,6 +6,11 @@ import { generateToolSchema, generateBreadcrumbs, generateFAQ } from '@/utils/se
import FAQSection from './FAQSection';
import RelatedTools from './RelatedTools';
interface SEOFAQ {
q: string;
a: string;
}
interface ToolLandingPageProps {
/** The tool slug matching seoData.ts entries */
slug: string;
@@ -76,28 +81,78 @@ export default function ToolLandingPage({ slug, children }: ToolLandingPageProps
{/* SEO Content Below Tool */}
<div className="mx-auto mt-16 max-w-3xl">
{/* Feature bullets */}
{seo.features.length > 0 && (
<section className="mb-12">
<h2 className="mb-4 text-xl font-bold text-slate-900 dark:text-white">
Why Use Our {toolTitle}?
</h2>
<p className="mb-6 text-slate-600 dark:text-slate-400">
{toolDesc}
</p>
<ul className="space-y-3">
{seo.features.map((feature, idx) => (
<li key={idx} className="flex items-start gap-3">
<CheckCircle className="mt-0.5 h-5 w-5 shrink-0 text-green-500" />
<span className="text-slate-700 dark:text-slate-300">{feature}</span>
</li>
))}
</ul>
</section>
)}
{/* What this tool does */}
<section className="mb-12">
<h2 className="mb-4 text-xl font-bold text-slate-900 dark:text-white">
{t('seo.headings.whatItDoes')}
</h2>
<p className="text-slate-600 dark:text-slate-400">
{t(`seo.${seo.i18nKey}.whatItDoes`)}
</p>
</section>
{/* How to use */}
{(() => {
const steps = t(`seo.${seo.i18nKey}.howToUse`, { returnObjects: true }) as string[];
return Array.isArray(steps) && steps.length > 0 ? (
<section className="mb-12">
<h2 className="mb-4 text-xl font-bold text-slate-900 dark:text-white">
{t('seo.headings.howToUse')}
</h2>
<ol className="list-decimal space-y-2 pl-5 text-slate-700 dark:text-slate-300">
{steps.map((step, idx) => (
<li key={idx}>{step}</li>
))}
</ol>
</section>
) : null;
})()}
{/* Benefits */}
{(() => {
const benefits = t(`seo.${seo.i18nKey}.benefits`, { returnObjects: true }) as string[];
return Array.isArray(benefits) && benefits.length > 0 ? (
<section className="mb-12">
<h2 className="mb-4 text-xl font-bold text-slate-900 dark:text-white">
{t('seo.headings.whyUse', { tool: toolTitle })}
</h2>
<ul className="space-y-3">
{benefits.map((benefit, idx) => (
<li key={idx} className="flex items-start gap-3">
<CheckCircle className="mt-0.5 h-5 w-5 shrink-0 text-green-500" />
<span className="text-slate-700 dark:text-slate-300">{benefit}</span>
</li>
))}
</ul>
</section>
) : null;
})()}
{/* Common use cases */}
{(() => {
const useCases = t(`seo.${seo.i18nKey}.useCases`, { returnObjects: true }) as string[];
return Array.isArray(useCases) && useCases.length > 0 ? (
<section className="mb-12">
<h2 className="mb-4 text-xl font-bold text-slate-900 dark:text-white">
{t('seo.headings.useCases')}
</h2>
<ul className="list-disc space-y-2 pl-5 text-slate-700 dark:text-slate-300">
{useCases.map((useCase, idx) => (
<li key={idx}>{useCase}</li>
))}
</ul>
</section>
) : null;
})()}
{/* FAQ Section */}
<FAQSection faqs={seo.faqs} />
{(() => {
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 <FAQSection faqs={faqs} />;
})()}
{/* Related Tools */}
<RelatedTools currentSlug={slug} />