ميزة: إضافة مكوني ProcedureSelection و StepProgress لأداة مخططات التدفق بصيغة PDF

- تنفيذ مكون ProcedureSelection لتمكين المستخدمين من اختيار الإجراءات من قائمة، وإدارة الاختيارات، ومعالجة الإجراءات المرفوضة.

- إنشاء مكون StepProgress لعرض تقدم معالج متعدد الخطوات بشكل مرئي.

- تعريف أنواع مشتركة للإجراءات، وخطوات التدفق، ورسائل الدردشة في ملف types.ts.

- إضافة اختبارات وحدة لخطافات useFileUpload و useTaskPolling لضمان الأداء السليم ومعالجة الأخطاء.

- تنفيذ اختبارات واجهة برمجة التطبيقات (API) للتحقق من تنسيقات نقاط النهاية وضمان اتساق ربط الواجهة الأمامية بالخلفية.
This commit is contained in:
Your Name
2026-03-06 17:16:09 +02:00
parent 2e97741d60
commit cfbcc8bd79
62 changed files with 10567 additions and 101 deletions

View File

@@ -17,6 +17,8 @@ import {
Lock,
Unlock,
ListOrdered,
PenLine,
GitBranch,
} from 'lucide-react';
import ToolCard from '@/components/shared/ToolCard';
import HeroUploadZone from '@/components/shared/HeroUploadZone';
@@ -29,7 +31,8 @@ interface ToolInfo {
bgColor: string;
}
const tools: ToolInfo[] = [
const pdfTools: ToolInfo[] = [
{ key: 'pdfEditor', path: '/tools/pdf-editor', icon: <PenLine className="h-6 w-6 text-rose-600" />, bgColor: 'bg-rose-50' },
{ 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' },
@@ -42,6 +45,10 @@ const tools: ToolInfo[] = [
{ key: 'protectPdf', path: '/tools/protect-pdf', icon: <Lock className="h-6 w-6 text-red-600" />, bgColor: 'bg-red-50' },
{ key: 'unlockPdf', path: '/tools/unlock-pdf', icon: <Unlock className="h-6 w-6 text-green-600" />, bgColor: 'bg-green-50' },
{ key: 'pageNumbers', path: '/tools/page-numbers', icon: <ListOrdered className="h-6 w-6 text-sky-600" />, bgColor: 'bg-sky-50' },
{ key: 'pdfFlowchart', path: '/tools/pdf-flowchart', icon: <GitBranch className="h-6 w-6 text-indigo-600" />, bgColor: 'bg-indigo-50' },
];
const otherTools: ToolInfo[] = [
{ 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' },
@@ -74,16 +81,18 @@ export default function HomePage() {
</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 dark:text-white">
{t('home.hero')}
</h1>
<p className="mx-auto mt-4 max-w-xl text-lg text-slate-500 dark:text-slate-400">
{t('home.heroSub')}
</p>
<section className="py-12 sm:py-20 bg-gradient-to-b from-slate-50 to-white dark:from-slate-900 dark:to-slate-950 px-4 mb-10 rounded-b-[3rem]">
<div className="max-w-4xl mx-auto text-center">
<h1 className="text-4xl font-extrabold tracking-tight text-slate-900 sm:text-6xl dark:text-white mb-6">
{t('home.hero')}
</h1>
<p className="mx-auto max-w-2xl text-lg text-slate-600 dark:text-slate-400 mb-10 leading-relaxed">
{t('home.heroSub')}
</p>
{/* Smart Upload Zone */}
<HeroUploadZone />
{/* Smart Upload Zone */}
<HeroUploadZone />
</div>
</section>
{/* Ad Slot */}
@@ -92,10 +101,26 @@ export default function HomePage() {
{/* Tools Grid */}
<section>
<h2 className="mb-6 text-center text-xl font-semibold text-slate-800 dark:text-slate-200">
{t('home.popularTools')}
{t('home.pdfTools')}
</h2>
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
{tools.map((tool) => (
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 mb-10">
{pdfTools.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>
<h2 className="mb-6 text-center text-xl font-semibold text-slate-800 dark:text-slate-200">
{t('home.otherTools', 'Other Tools')}
</h2>
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 mb-12">
{otherTools.map((tool) => (
<ToolCard
key={tool.key}
to={tool.path}
@@ -108,6 +133,48 @@ export default function HomePage() {
</div>
</section>
{/* Features / Why Choose Us */}
<section className="py-16 bg-slate-50 dark:bg-slate-900 rounded-3xl mb-12 px-6 sm:px-12 text-center">
<h2 className="text-3xl font-bold tracking-tight text-slate-900 dark:text-white mb-10">
{t('home.featuresTitle', 'A smarter way to convert and edit online')}
</h2>
<div className="grid gap-8 sm:grid-cols-3 text-center">
<div className="flex flex-col items-center">
<div className="flex h-16 w-16 items-center justify-center rounded-2xl bg-blue-100 text-blue-600 dark:bg-blue-900/30 dark:text-blue-400 mb-6">
<Layers className="h-8 w-8" />
</div>
<h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 mb-2">
{t('home.feature1Title', 'One complete workspace')}
</h3>
<p className="text-slate-500 dark:text-slate-400">
{t('home.feature1Desc', 'Edit, convert, compress, merge, split without switching tabs.')}
</p>
</div>
<div className="flex flex-col items-center">
<div className="flex h-16 w-16 items-center justify-center rounded-2xl bg-emerald-100 text-emerald-600 dark:bg-emerald-900/30 dark:text-emerald-400 mb-6">
<span className="text-2xl font-bold inline-block">100%</span>
</div>
<h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 mb-2">
{t('home.feature2Title', 'Accuracy you can trust')}
</h3>
<p className="text-slate-500 dark:text-slate-400">
{t('home.feature2Desc', 'Get pixel-perfect, editable files in seconds with zero quality loss.')}
</p>
</div>
<div className="flex flex-col items-center">
<div className="flex h-16 w-16 items-center justify-center rounded-2xl bg-red-100 text-red-600 dark:bg-red-900/30 dark:text-red-400 mb-6">
<Lock className="h-8 w-8" />
</div>
<h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100 mb-2">
{t('home.feature3Title', 'Built-in security')}
</h3>
<p className="text-slate-500 dark:text-slate-400">
{t('home.feature3Desc', 'Access files securely, protected by automatic encryption.')}
</p>
</div>
</div>
</section>
{/* Ad Slot - Bottom */}
<AdSlot slot="home-bottom" className="mt-12" />
</>