مشروع عملي: بناء بطاقة تعريف (Profile Card) قابلة لإعادة الاستخدام بمعلومات متغيرة


اليوم، سنقوم ببناء مكون React.js قوي وقابل لإعادة الاستخدام: بطاقة تعريف شخصية (Profile Card). سنتعلم كيفية تمرير البيانات المتغيرة عبر الخصائص (Props) لإنشاء بطاقات متعددة بتصميم واحد.

الخطوة 1: تهيئة المكون الأساسي واستقبال الخصائص (Props)

في هذه الخطوة، سنقوم بإنشاء المكون الوظيفي ProfileCard وتحديد الخصائص الأساسية التي سيستقبلها، مثل الاسم، المسمى الوظيفي، ورابط الصورة.

import React from 'react';

// تعريف مكون ProfileCard كدالة تستقبل الخصائص (props)
const ProfileCard = ({ name, title, imageUrl }) => {
  return (
    <div className="profile-card-container">
      {/* عرض الصورة الشخصية، مع استخدام رابط الصورة المستلم كخاصية */}
      <img src={imageUrl} alt={name} className="profile-card-image" />
      {/* عرض اسم الشخص المستلم كخاصية */}
      <h2 className="profile-card-name">{name}</h2>
      {/* عرض المسمى الوظيفي المستلم كخاصية */}
      <h3 className="profile-card-title">{title}</h3>
      {/* باقي تفاصيل البطاقة ستضاف في الخطوات التالية */}
    </div>
  );
};

export default ProfileCard;

ملاحظة تقنية: استخدام { } داخل JSX يسمح لنا بتضمين تعبيرات JavaScript، مثل قيم الخصائص name و title و imageUrl.

الخطوة 2: إضافة التفاصيل والوصف

الآن، سنوسع المكون ليشمل حقل وصف اختياري، مما يجعله أكثر مرونة في عرض المعلومات.

import React from 'react';

const ProfileCard = ({ name, title, imageUrl, description }) => {
  return (
    <div className="profile-card-container">
      <img src={imageUrl} alt={name} className="profile-card-image" />
      <h2 className="profile-card-name">{name}</h2>
      <h3 className="profile-card-title">{title}</h3>
      {/* عرض الوصف إذا كان موجوداً. هذا يجعل حقل الوصف اختيارياً */}
      {description && <p className="profile-card-description">{description}</p>}
      {/* باقي تفاصيل البطاقة ستضاف في الخطوات التالية */}
    </div>
  );
};

export default ProfileCard;

ملاحظة تقنية: التعبير {description && <p>...</p>} هو طريقة شائعة في React للقيام بالتقديم الشرطي (Conditional Rendering). إذا كانت قيمة description صحيحة (ليست null أو undefined أو سلسلة فارغة)، فسيتم عرض الفقرة، وإلا فلن يتم عرضها.

الخطوة 3: دمج روابط التواصل الاجتماعي

سنضيف الآن القدرة على عرض روابط متعددة للتواصل الاجتماعي، مع استخدام التكرار على مصفوفة من الروابط.

import React from 'react';

// تعريف مكون ProfileCard كدالة تستقبل الخصائص (props) المتعددة
const ProfileCard = ({ name, title, imageUrl, description, socialLinks }) => {
  return (
    <div className="profile-card-container">
      <img src={imageUrl} alt={name} className="profile-card-image" />
      <h2 className="profile-card-name">{name}</h2>
      <h3 className="profile-card-title">{title}</h3>
      {description && <p className="profile-card-description">{description}</p>}

      {/* قسم لعرض روابط التواصل الاجتماعي */}
      {socialLinks && socialLinks.length > 0 && (
        <div className="profile-card-social">
          {/* تكرار (map) على مصفوفة الروابط لإنشاء عنصر 'a' لكل رابط */}
          {socialLinks.map((link, index) => (
            <a key={index} href={link.url} target="_blank" rel="noopener noreferrer">
              {/* يمكن استخدام أيقونات هنا بدلاً من النص، مثل Font Awesome */}
              {link.platform}
            </a>
          ))}
        </div>
      )}
    </div>
  );
};

export default ProfileCard;

ملاحظة تقنية: عند تكرار عناصر في React (مثل استخدام .map())، يجب توفير خاصية key فريدة لكل عنصر. يساعد هذا React على تحديد العناصر التي تغيرت أو تمت إضافتها أو إزالتها بكفاءة. في هذا المثال، استخدمنا index كـ key، ولكن في التطبيقات الحقيقية، يفضل استخدام معرف فريد من البيانات نفسها.

الكود النهائي الكامل

هذا هو الكود الكامل لمكون ProfileCard الذي قمنا ببنائه، بالإضافة إلى مثال على كيفية استخدامه في مكون App.js لإنشاء بطاقات متعددة.

// ProfileCard.js
import React from 'react';

const ProfileCard = ({ name, title, imageUrl, description, socialLinks }) => {
  return (
    <div className="profile-card-container">
      <img src={imageUrl} alt={name} className="profile-card-image" />
      <h2 className="profile-card-name">{name}</h2>
      <h3 className="profile-card-title">{title}</h3>
      {description && <p className="profile-card-description">{description}</p>}

      {socialLinks && socialLinks.length > 0 && (
        <div className="profile-card-social">
          {socialLinks.map((link, index) => (
            <a key={index} href={link.url} target="_blank" rel="noopener noreferrer">
              {link.platform}
            </a>
          ))}
        </div>
      )}
    </div>
  );
};

export default ProfileCard;

// App.js (مثال على كيفية استخدام المكون)
import React from 'react';
import ProfileCard from './ProfileCard'; // تأكد من المسار الصحيح للملف

function App() {
  const userData1 = {
    name: 'أحمد علي',
    title: 'مهندس برمجيات',
    imageUrl: 'https://via.placeholder.com/150/007bff/ffffff?text=Ahmed',
    description: 'مهندس برمجيات ذو خبرة في تطوير تطبيقات الويب باستخدام React و Node.js.',
    socialLinks: [
      { platform: 'LinkedIn', url: 'https://linkedin.com/in/ahmedali' },
      { platform: 'GitHub', url: 'https://github.com/ahmedali' }
    ]
  };

  const userData2 = {
    name: 'فاطمة الزهراء',
    title: 'مصممة واجهة المستخدم/تجربة المستخدم',
    imageUrl: 'https://via.placeholder.com/150/28a745/ffffff?text=Fatima',
    description: 'مصممة شغوفة بإنشاء تجارب مستخدم بديهية وجمالية.',
    socialLinks: [
      { platform: 'Behance', url: 'https://behance.net/fatimaz' },
      { platform: 'Portfolio', url: 'https://fatimaz.dev' }
    ]
  };

  const userData3 = {
    name: 'محمد خالد',
    title: 'مدير مشروع',
    imageUrl: 'https://via.placeholder.com/150/dc3545/ffffff?text=Mohamed',
    // لا يوجد وصف لهذه البطاقة لاختبار التقديم الشرطي
    socialLinks: [
      { platform: 'LinkedIn', url: 'https://linkedin.com/in/mohamedkhaled' }
    ]
  };

  return (
    <div style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'center', gap: '20px' }}>
      <ProfileCard {...userData1} />
      <ProfileCard {...userData2} />
      <ProfileCard {...userData3} />
    </div>
  );
}

export default App;

النتيجة المتوقعة

عند تشغيل الكود أعلاه في تطبيق React، ستظهر ثلاث بطاقات تعريف (Profile Cards) مختلفة في التصميم، كل منها يعرض معلومات فريدة تم تمريرها كخصائص (props). البطاقات ستكون منسقة بشكل جيد وتتضمن الصورة، الاسم، المسمى الوظيفي، الوصف (إذا كان موجوداً)، وروابط التواصل الاجتماعي. المكون قابل لإعادة الاستخدام بالكامل، مما يسمح لك بإنشاء عدد لا نهائي من البطاقات بمعلومات مختلفة باستخدام نفس هيكل المكون.