- Set up main entry point for React application. - Create About, Home, NotFound, Privacy, and Terms pages with SEO support. - Implement API service for file uploads and task management. - Add global styles using Tailwind CSS. - Create utility functions for SEO and text processing. - Configure Vite for development and production builds. - Set up Nginx configuration for serving frontend and backend. - Add scripts for cleanup of expired files and sitemap generation. - Implement deployment script for production environment.
94 lines
3.3 KiB
TypeScript
94 lines
3.3 KiB
TypeScript
import { useTranslation } from 'react-i18next';
|
|
import { Helmet } from 'react-helmet-async';
|
|
import {
|
|
FileText,
|
|
FileOutput,
|
|
Minimize2,
|
|
ImageIcon,
|
|
Film,
|
|
Hash,
|
|
Eraser,
|
|
} from 'lucide-react';
|
|
import ToolCard from '@/components/shared/ToolCard';
|
|
import AdSlot from '@/components/layout/AdSlot';
|
|
|
|
interface ToolInfo {
|
|
key: string;
|
|
path: string;
|
|
icon: React.ReactNode;
|
|
bgColor: string;
|
|
}
|
|
|
|
const tools: ToolInfo[] = [
|
|
{ key: 'pdfToWord', path: '/tools/pdf-to-word', icon: <FileText className="h-6 w-6 text-red-600" />, bgColor: 'bg-red-50' },
|
|
{ key: 'wordToPdf', path: '/tools/word-to-pdf', icon: <FileOutput className="h-6 w-6 text-blue-600" />, bgColor: 'bg-blue-50' },
|
|
{ key: 'compressPdf', path: '/tools/compress-pdf', icon: <Minimize2 className="h-6 w-6 text-orange-600" />, bgColor: 'bg-orange-50' },
|
|
{ key: 'imageConvert', path: '/tools/image-converter', icon: <ImageIcon className="h-6 w-6 text-purple-600" />, bgColor: 'bg-purple-50' },
|
|
{ key: 'videoToGif', path: '/tools/video-to-gif', icon: <Film className="h-6 w-6 text-emerald-600" />, bgColor: 'bg-emerald-50' },
|
|
{ key: 'wordCounter', path: '/tools/word-counter', icon: <Hash className="h-6 w-6 text-blue-600" />, bgColor: 'bg-blue-50' },
|
|
{ key: 'textCleaner', path: '/tools/text-cleaner', icon: <Eraser className="h-6 w-6 text-indigo-600" />, bgColor: 'bg-indigo-50' },
|
|
];
|
|
|
|
export default function HomePage() {
|
|
const { t } = useTranslation();
|
|
|
|
return (
|
|
<>
|
|
<Helmet>
|
|
<title>{t('common.appName')} — {t('home.heroSub')}</title>
|
|
<meta name="description" content={t('home.heroSub')} />
|
|
<link rel="canonical" href={window.location.origin} />
|
|
<script type="application/ld+json">
|
|
{JSON.stringify({
|
|
'@context': 'https://schema.org',
|
|
'@type': 'WebSite',
|
|
name: t('common.appName'),
|
|
url: window.location.origin,
|
|
description: t('home.heroSub'),
|
|
potentialAction: {
|
|
'@type': 'SearchAction',
|
|
target: `${window.location.origin}/tools/{search_term_string}`,
|
|
'query-input': 'required name=search_term_string',
|
|
},
|
|
})}
|
|
</script>
|
|
</Helmet>
|
|
|
|
{/* Hero Section */}
|
|
<section className="py-12 text-center sm:py-16">
|
|
<h1 className="text-4xl font-bold tracking-tight text-slate-900 sm:text-5xl">
|
|
{t('home.hero')}
|
|
</h1>
|
|
<p className="mx-auto mt-4 max-w-xl text-lg text-slate-500">
|
|
{t('home.heroSub')}
|
|
</p>
|
|
</section>
|
|
|
|
{/* Ad Slot */}
|
|
<AdSlot slot="home-top" format="horizontal" className="mb-8" />
|
|
|
|
{/* Tools Grid */}
|
|
<section>
|
|
<h2 className="mb-6 text-center text-xl font-semibold text-slate-800">
|
|
{t('home.popularTools')}
|
|
</h2>
|
|
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
|
{tools.map((tool) => (
|
|
<ToolCard
|
|
key={tool.key}
|
|
to={tool.path}
|
|
icon={tool.icon}
|
|
title={t(`tools.${tool.key}.title`)}
|
|
description={t(`tools.${tool.key}.shortDesc`)}
|
|
bgColor={tool.bgColor}
|
|
/>
|
|
))}
|
|
</div>
|
|
</section>
|
|
|
|
{/* Ad Slot - Bottom */}
|
|
<AdSlot slot="home-bottom" className="mt-12" />
|
|
</>
|
|
);
|
|
}
|