ArchivePage

 const latestBooks = data?.slice(0, 5);


// استيراد Hooks من React
// useEffect = لتنفيذ كود عند تحميل الكومبوننت أو تغير القيم
// useState = لإنشاء state محلي (غير مستخدم هنا فعلياً لكنه مستورد)
import { useEffect, useState } from "react";

// استيراد Hooks من Redux
// useDispatch = لإرسال actions إلى الـ store
// useSelector = لقراءة البيانات من Redux store
import { useDispatch, useSelector } from "react-redux";

// useParams = لقراءة القيم من رابط الصفحة (URL)
// هنا نستخدمه للحصول على id التصنيف
import { useParams } from "react-router-dom";

// كومبوننت لعرض بطاقة كتاب واحدة
import Book from "../../components/Book/Book";

// api instance (axios) — غير مستخدم هنا حالياً
import api from "../../api";

// Action لجلب جميع الكتب من السيرفر وتخزينها في Redux
import { getAllBooks } from "../../store/booksSlice";

function ArchivePage() {

    // قراءة id التصنيف من الرابط
    // مثال: /category/3 → id = 3
    const { id } = useParams();

    // إنشاء dispatch لإرسال actions إلى Redux
    const dispatch = useDispatch();

    // قراءة البيانات من Redux store
    // state.products = اسم slice داخل store
    // data = قائمة الكتب
    // isLoading = حالة التحميل
    // error = في حال حدوث خطأ
    const { data, isLoading, error } = useSelector((state) => state.products);

    // فلترة الكتب حسب التصنيف الحالي
    // categories عبارة عن Array لذلك نستخدم some()
    // some() تعني: هل يحتوي الكتاب على هذا التصنيف؟
    const filteredBooks = data.filter((book) =>
        book.categories?.some((cat) => cat.id === Number(id))
    );

    // طباعة النتائج في الكونسول للمراقبة
    console.log(filteredBooks)

    // useEffect يعمل عند تحميل الصفحة لأول مرة
    useEffect(() => {

        // إذا كانت Redux فارغة (بعد refresh مثلاً)
        // نقوم بجلب الكتب من السيرفر مرة أخرى
        if (!data.length) dispatch(getAllBooks());

    }, []); // [] = يعمل مرة واحدة فقط عند تحميل الصفحة

    return (
        <div>

            {/* عنوان الصفحة (فارغ حالياً) */}
            <h1 className="text-center"></h1>

            <div className="container">

                {/* شبكة عرض الكتب */}
                <div className="row row-cols-lg-5">

                    {
                        // عرض الكتب بعد الفلترة
                        // map() تمر على كل كتاب وتعرضه
                        filteredBooks?.map((book) => (
                            <Book book={book} />
                        ))
                    }

                </div>

            </div>

        </div>
    )
}

export default ArchivePage;
JavaScript
🧠 أولاً: السطر الكامل
const filteredBooks = data.filter((book) =>
book.categories?.some((cat) => cat.id === Number(id)
);
JavaScript
🎯 ماذا نريد أن نفعل؟

نريد:

اختيار الكتب التي تنتمي للتصنيف الحالي فقط.

🧩 لنفهم شكل البيانات أولاً

شكل الكتب داخل data

data = [
  {
    id: 1,
    name: "Book A",
    categories: [
      { id: 2, name: "Programming" },
      { id: 5, name: "Web" }
    ]
  },
  {
    id: 2,
    name: "Book B",
    categories: [
      { id: 3, name: "Design" }
    ]
  }
]
JavaScript
🧩 قيمة id من الرابط

لو الرابط:

/category/2
JavaScript

فإن:

id = "2"   // string
JavaScript
🧠 لذلك نحوله إلى رقم
Number(id) = 2
JavaScript
🚀 الآن نشرح السطر جزء جزء
✅ الجزء 1 — filter()
data.filter(...)
JavaScript
ماذا يفعل؟

يمر على كل كتاب ويقرر:

👉 هل نحتفظ به أم نحذفه؟

القاعدة:

إذا رجع الشرط:

trueيبقى الكتاب
falseيتم حذفه
JavaScript
🧩 مثال بسيط
[1,2,3,4].filter(num => num > 2)
JavaScript

النتيجة:

[3,4]
JavaScript
🧠 إذن:

filter = “فلترة العناصر”

✅ الجزء 2 — book.categories

هذا يعني:

👉 الوصول إلى تصنيفات الكتاب.

لماذا استخدمنا ?.
book.categories?.some(...)
JavaScript

لأن بعض الكتب قد لا تحتوي على تصنيفات.

بدون ?. سيحدث crash.

🧠 إذن:
?. = optional chaining
JavaScript

تعني:

إذا لم يوجد categories لا تنفذ الكود.

✅ الجزء 3 — some()

هذا هو الجزء الأهم.

ماذا يفعل some ؟

يمر على Array ويجيب:

👉 هل يوجد عنصر واحد على الأقل يحقق الشرط؟

يرجع فقط:
true أو false
JavaScript
🧩 مثال بسيط
[1,2,3].some(n => n === 2)
JavaScript

النتيجة:

true
JavaScript

[1,2,3].some(n => n === 5)
JavaScript

النتيجة:

false
JavaScript

🧠 إذن:

some = “هل يوجد عنصر مطابق؟”

✅ الجزء 4 — cat.id === Number(id)

هذا هو الشرط.

يعني:

👉 هل ID التصنيف داخل الكتاب يساوي ID التصنيف من الرابط؟

🎯 الآن نربط كل شيء معاً
🧠 كيف يعمل الكود فعلياً؟

React يقوم بالآتي:

الخطوة 1

يمر على كل كتاب:

book1
book2
book3
JavaScript
الخطوة 2

لكل كتاب:

يدخل إلى categories

الخطوة 3

يفحص:

هل يوجد تصنيف id = 2 ؟

الخطوة 4

إذا نعم:

some() → true
JavaScript

➡️ filter يحتفظ بالكتاب.

إذا لا:

some() → false
JavaScript

➡️ filter يحذف الكتاب.

🧩 مثال عملي كامل

البيانات

id = 2Book A categories = [2,5]
Book B categories = [3]
JavaScript

النتيجة

Book Aيحتوي 2يظهر
Book Bلا يحتوييُحذف
JavaScript
🏆 الناتج النهائي
filteredBooks = 
[
  Book A
]
JavaScript
🧠 لماذا استخدمنا some وليس filter؟

لأننا لا نريد كل التصنيفات.

نريد فقط:

👉 معرفة هل يوجد واحد مطابق.

⭐ الفرق بين filter و some
الدالةترجع
filterArray جديد
sometrue / false

💡 الصيغة البشرية للكود

يمكن قراءته هكذا:

خذ جميع الكتب التي تحتوي على تصنيف id يساوي id الموجود في الرابط.

🏆 الخلاصة النهائية

السطر يفعل 4 أشياء:

1️⃣ يمر على الكتب
2️⃣ يدخل إلى تصنيفات كل كتاب
3️⃣ يبحث عن تصنيف مطابق
4️⃣ يحتفظ بالكتاب إذا وجده