اذهب إلى المحتوى

Mustafa Suleiman

الأعضاء
  • المساهمات

    19762
  • تاريخ الانضمام

  • تاريخ آخر زيارة

  • عدد الأيام التي تصدر بها

    472

كل منشورات العضو Mustafa Suleiman

  1. مكتبة خاصة بإضافة إشعارات ذات تصميم جميل، وبشكل سريع سهل مع إمكانية التخصيص، وتلك الإشعارات تُعرف باسم Toasts، وهي الرسائل الصغيرة التي تظهر في زاوية الشاشة لإعلام المستخدم بشيء ما حدث، مثل تم الحفظ بنجاح، حدث خطأ، أو جاري التحميل. ومن خلالها تستطيع عرض إشعار بسطر كود واحد فقط: import toast, { Toaster } from 'react-hot-toast'; const notify = () => toast('تم الحفظ بنجاح!'); function App() { return ( <div> <button onClick={notify}>احفظ</button> <Toaster /> </div> ); } كذلك تدعم الـ Promises وتلك من أقوى ميزاتها، أي بسهولة بإمكانك عرض إشعارات مختلفة بناءًا على حالة الـ Promise، بمعنى جاري التنفيذ، نجاح أو فشل، وذلك مناسب للعمليات غير المتزامنة مثل طلبات API. const myPromise = fetchData(); toast.promise(myPromise, { loading: 'جاري الحفظ...', success: <b>تم الحفظ بنجاح!</b>, error: <b>فشل الحفظ.</b>, }); وللعلم يوجد مكتبة أخرى وهي React-Toastify بها خيارات تخصيص متقدمة جدًا، كتغيير شكل شريط التقدم وغيره من التخصيصات.
  2. ما تقصده يسمى Auto import وذلك متاح بالفعل في vscode، تأكد من أنه مُفعل بالضغط على File بالأعلى ثم اختر preferences ثم Settings وابحث عن التالي في شريط البحث: javascript.suggest.autoImports تأكد من أنّ تلك الميزة مُفعلة وبجانبها علامة صح. في حال ما زلت تواجه مشكلة، فقم بتحديد وسم البداية للمكون وليس النهاية، واضغط على CTRL + زر المسافة في لوحة المفاتيح وسيظهر لك إقتراح باستيراده اضغط عليه كالتالي: لاحظ قمت بتحديد كلمة Register فقط في البداية وليس النهاية.
  3. مثل تلك المقالات لن تحقق فائدة في ظل الوضع الحالي، فلا يوجد فرق بينها وبين المقالات الموجودة بالفعل، مجرد عناوين ونقاط بسيطة كتفصيل للعنوان بدون التعمق في موضوع المقالة نفسه. يجب وجود مقالات تعتبر Corner stone للمدونة لديك، بحيث تستهدف بها العملاء المحتملين لك، والأمر بحاجة إلى تفصيل، ستجد ذلك هنا: وبالنسبة للهجة، فذلك غير جيد، اللهجات مناسبة لمواقع التواصل الإجتماعي، بينما على جوجل تكتب بالعربية الفصحى لتتناسب مع الجميع. وأيضًا ليتم فهرسة محتواك بشكل صحيح، فخوارزميات جوجل بالرغم من تطورها، لكنها لا تزال تفهم وتفهرس اللغة العربية الفصحى بشكل أفضل وأوسع من اللهجات المحلية، والكلمات المفتاحية الرئيسية مثل تحليل المنافسين والتسويق الرقمي لها وزن أكبر في البحث. كذلك حاول إنشاء محتوى بالفيديو وليس بشكل نصي، فستحقق نتائج أفضل بلا شك، والمقالات في حال لم تكن متعمقة فلا تحقق فائدة إن كنت تستهدف عملاء من جوجل.
  4. الأمر يتوقف على حجم الصيدلية ووجود سلاسل لها من عدمه، وأيضًا الاحتياجات المُرادة من البرنامج، وبغض النظر عن البرنامج، فالعامل الأكثر أهمية هو توافر الربط الآلي والسلس مع المنصات الحكومية الثلاث الإلزامية: نظام رصد: لتتبع الأدوية من هيئة الغذاء والدواء. خدمة وصفتي: لاستقبال وإدارة الوصفات الإلكترونية. الفوترة الإلكترونية ZATCA: من هيئة الزكاة والضريبة والجمارك. ولا تقبلي بأي نظام يتطلب رفع البيانات يدويًا لتلك المنصات، فيجب أن تكون العملية مؤتمتة بالكامل داخل البرنامج لتجنب الأخطاء والمخالفات. وعامًة يتوفر نظام Aumet كخيار جيد، بسبب بنيته السحابية، ويستخدم الذكاء الاصطناعي لتحسين إدارة المخزون والمبيعات. ويتوفر أيضًا نظام Pharmacare و نظام Titan كأنظمة قوية ومجربة على نطاق واسع في السوق السعودي، ويوفران تحكم كامل في البيانات، ويتم استضافة النظام على خوادم خاصة وليس على السحابة ويتم شراءالرخصة مرة واحدة فقط على عكس Aumet ذو الإشتراك السنوي. والأمر بحاجة إلى مقارنة، لذا الملف التالي به مقارنة شاملة مقارنة بين أنظمة الصيدليات بالسعودية.xlsx
  5. ميثود خاصة بالمصفوفات في جافاسكريبت، للتحقق مما إن كان عنصر واحد على الأقل في المصفوفة يحقق شرط معين، حيث يتم تمرير دالة callback إليها ويتم البحث في المصفوفة بناءًا على المنطق الذي في تلك الدالة، ولو تم إعادة القيمة true لأي عنصر، فدالة some() تتوقف عن العمل فورًا وتُعيد true. const numbers = [1, 3, 5, 7, 8, 9]; const hasEvenNumber = numbers.some(function(number) { return number % 2 === 0; }); console.log(hasEvenNumber); قمت بالتحقق من وجود عدد زوجي في المصفوفة، ونتيجة الطباعة هي True بسبب وجود 8. وكمثال آخر للتحقق من عدم وجود منتج معين في المخزون: const products = [ { name: 'Laptop', inStock: true }, { name: 'Mouse', inStock: true }, { name: 'Keyboard', inStock: false }, { name: 'Monitor', inStock: true } ]; const hasOutOfStockProduct = products.some(product => !product.inStock); console.log(hasOutOfStockProduct); فهنا الدالة some() تبحث عن منتج واحد على الأقل يحقق الشرط !product.inStock أي product.inStock قيمتها false، وعندما تصل إلى 'Keyboard'، يتحقق الشرط، وتُعيد true مباشرًة.
  6. بسبب "type": "module" في package.json، والتي تفرض عليك تضمين امتداد الملف .js في جميع عبارات الاستيراد، أي عليك تحديث جميع عبارات الاستيراد في مشروعك لتتضمن .js
  7. ستجد أسفل فيديو الدرس في نهاية الصفحة صندوق تعليقات كما هنا، أرجو طرح الأسئلة أسفل الدرس وليس هنا في قسم أسئلة البرمجة حيث نطرح الأسئلة العامة الغير متعلقة بمحتوى الدورة أو الدرس، وذلك لمساعدتك بشكل أفضل.
  8. لا مشكلة تستطيع القيام بمشاريع صغيرة سواء Landing Pages, مواقع شخصية أو تطبيقات React بسيطة، تحويل تصاميم PSD/Figma إلى كود HTML. لكن الأفضل هو الإنتظار قليلاً لحين بناء متجر إلكتروني بكامل وظائفه من حيث الواجهة الأمامية، وبعدها تستطيع التقدم على وظائف بأريحية، وأيضًا تعلم أساسيات Next.js فهي لا غنى عنها لمشاريع React حاليًا وليس شرطًا قبل البدء، لكن ستفتح لك فرص أكثر، لذا ابدأ بتعلم الأساسيات أثناء العمل الحر. ثم التعمق في Next.js لتتمكن من تطوير مشاريع Full-stack.
  9. بالطبع ممكن، وذلك متاح عبر منصات العمل الحر مثل مستقل وخمسات وبعيد، أو العمل عن بُعد مع الشركات، لكن يجب تحديد إتجاهك فلو هدفك العمل الحر، فقم بتفقد تلك المنصات ونوعية المشاريع المطلوبة وتعلم المهارات اللازمة لكي تستطيع طرح عرضك على تلك المشاريع ويكون لديك فرصة ومعرض أعمال مناسب. نفس الأمر لو أردت العمل عن بُعد تفقد الوظائف من نوعية Remotely المعروضة على مواقع التوظيف مثل LinkedIn و Indeed وتفقد المهارات اللازمة، لكن المشكلة في وظائف الـ Remotely أنها تتطلب خبرة سنتين أو ثلاث على الأقل. لذا الأنسب لك هو منصات العمل الحر لحين اكتساب خبرة مناسبة لوظائف الـ Remotely.
  10. ما الغرض من الكود؟ حاليًا أنت تقوم بإنشاء نموذج جديد دونّ عرضه، كذلك الدالة بها منطق خاص بملء حقول نصية (item_code.Text, item_name.Text, وخلافه، وتلك الحقول يجب أن تكون موجودة في النموذج الجديد. عامًة قم بعرض النموذج الجديد items frm = new items(); frm.show_recored_date(dataGridView1); frm.Show(); this.Close(); أو قم باستخدام النموذج الحالي، لو الحقول في نفس النموذج حيث لا يجب إنشاء نسخة جديدة، من خلال حذف Dispose(): this.show_recored_date(dataGridView1); لو استمرت المشكلة حاول تمرير البيانات بشكل أفضل كالتالي: public void show_recored_date(DataGridView dataGridView, items targetForm) { if (dataGridView.CurrentRow == null) { MessageBox.Show("الرجاء تحديد صف في الجدول لعرض البيانات."); return; } string item_code_ = Convert.ToString(dataGridView.CurrentRow.Cells[2].Value); string sql = "select * from items where item_code = @itemCode"; using (SqlCommand cmd = new SqlCommand(sql, Class1.sqlCon)) { cmd.Parameters.AddWithValue("@itemCode", item_code_); SqlDataAdapter adp = new SqlDataAdapter(cmd); DataTable dt = new DataTable(); adp.Fill(dt); if (dt.Rows.Count == 0) { MessageBox.Show("لم يتم العثور على بيانات السجل", "رسالة تنبيه"); } else { DataRow dr = dt.Rows[0]; targetForm.item_code.Text = dr["item_code"].ToString(); targetForm.item_name.Text = dr["item_name"].ToString(); targetForm.item_date.Text = dr["item_date"].ToString(); targetForm.item_price.Text = dr["item_price"].ToString(); targetForm.item_qty.Text = dr["item_qty"].ToString(); } } } والاستدعاء: items frm = new items(); show_recored_date(dataGridView1, frm); frm.ShowDialog(); this.Close();
  11. بسبب أنك قمت بتحديد نفس المسار لمكون Background لاحظ path="/" بالتالي تم تجاهل المكون Home وأصبح يتم عرض Background، الصحيح هو تحديد مسار واحد فقط لكل مكون. وأيضًا في الإصدار 6 من react-router-dom، يجب أن تكون جميع مكونات <Route> موجودة داخل مكون <Routes> ليتمكن الراوتر من اختيار المسار الصحيح وعرضه. import Background from "./Components/Background/Background"; import Navbar from "./Components/Navbar/Navbar"; import Home from "./Components/Home/Home"; import { BrowserRouter, Routes, Route } from 'react-router-dom'; function App() { return ( <BrowserRouter> <Background /> <Navbar /> <Routes> <Route path="/" element={<Home />} /> </Routes> </BrowserRouter> ); } export default App; والمكونات <Background /> و<Navbar /> ستكون ثابتة وستظهر في جميع الصفحات حيث لم أقم بتحديد مسار لهم.
  12. جيد جدًا، من المفترض في مشروع X-O تعلمت كيفية إدارة الـ State والتفاعل مع المستخدم عن طريق الأحداث، ومشروع To-Do List تعملت من خلاله عمليات CRUD (Create, Read, Update, Delete)، وهو أساس معظم التطبيقات. وفي مشاريع Portfolio, Restaurant, Hospital تعلمت بناء واجهات المستخدم، تقسيم التطبيق إلى مكونات، وعرض البيانات القادمة من مصدر ثابت، سواء ملف JSON أو بيانات مكتوبة مباشرة في الكود. لكن هل قمت بذلك من خلال مشاهدة شروحات على اليوتيوب؟ في حال ذلك، حاول إذن إعادة مشروع منهم وتنفيذه بمفردك لقياس مدى استيعابك والوقوف على نقاط الضعف، ثم قم بإضافة ميزة لم تكن موجودة في المشروع تستغرق يوم مثلاً في تنفيذها أي ليست ميزة بسيطة. بعد إتمام ما سبق تستطيع الإنتقال لمشروع متقدم أكثر، مثل تطبيق الطقس حيث ستحتاج إلى التعامل مع APIs خارجية مثل OpenWeatherMap API. بعدها انتقل إلى بناء متجر إلكتروني بسيط من أجل تعلم إدارة حالة أكثر تعقيدًا والتنقل بين صفحات متعددة.
  13. ذلك مكون في مشروع React باسم Home، والغرض منه هو عند تحميل المكون لأول مرة، يقوم بجلب بيانات المنتجات من API خارجي لعدة فئات مختلفة. والفئات التي يتم جلبها هي: const categoryData = [ "smartphones", "mobile-accessories", "laptops", "tablets", "sunglasses", "sports-accessories", ] وذلك عن طريق المرور على المصفوفة categoryData من خلال دالة map: const fetchPrduct = async () => { try{ const results = await Promise.all( categoryData.map(async (category) => { const response = await fetch(`https://dummyjson.com/products/category/${category}`); const data = await response.json(); return {[category] : data.products} }) ) Promise.all هنا هو لجلب البيانات لجميع الفئات بشكل متوازٍ في نفس الوقت، حيث دالة all تنتظر حتى يتم إكمال جميع الـ Promises في المصفوفة بنجاح وتسمح بتنفيذ عدة عمليات غير متزامنة مثل طلبات API في نفس الوقت بشكل متوازٍ، بدلاً من انتظار انتهاء كل طلب لبدء الطلب الذي يليه. ثم جمع كل تلك البيانات في كائن واحد، هنا: return {[category] : data.products} لاحظ [category] سيتم استبدالها باسم الفئة الحالية التي في دورة map، ففي جافاسكريبت تستطيع تعيين أسماء الخواص ديناميكيًا في الكائنات بتلك الطريقة. ويخزن الكائن المجمع في حالة أي State المكون ليتم استخدامه لاحقًا، سواء لعرض المنتجات على الصفحة أو غيره. const productsData = Object.assign({}, ...results); setProduct(productsData); و Object.assign دالة لنسخ خصائص كائن أو عدة كائنات إلى كائن آخر، وهنا تم تحديد كائن فارغ { } ليتم نسخ إليه محتوى مصفوفة results والتي بها كائنات، لاحظ ...results تستخدم الـ Spread Operator لتفكيك المصفوفة.
  14. ذلك خطاف من مكتبة react-router-dom ويسمح بالوصول إلى المعلمات أو الـ parameters الديناميكية الموجودة في رابط URL الحالي. أي الرابط التالي test.com/users/ahmed المُعرف هنا هو ahmed وتلك هي صفحة المستخدم، وهنا test.com/products/123 المعُرف هو 123 وسيتم عرض صفحة المنتج الذي يمتلك ذلك المُعرف. لذا بدلاً من إنشاء مكون منفصل لكل مستخدم أو منتج، ستقوم بإنشاء مسار ديناميكي واحد في React Router باستخدام النقطتين الرأسيتين : <Route path="/users/:username" element={<UserProfile />} /> <Route path="/products/:productId" element={<ProductDetails />} /> أي ستحتاج إلى استخدامه لبناء صفحات ديناميكية، من خلال بناء مكون واحد مثل UserProfile, ProductDetails, ArticlePage قادر على عرض بيانات لآلاف العناصر المختلفة، بمعنى صفحة تفاصيل منتج في أمازون، صفحة بروفايل مستخدم في فيسبوك، صفحة مقال في مدونة، ويختلف محتواها باختلاف المُعرف الذي في الرابط. كذلك جلب البيانات من الـ API بشكل فعال، باستخدام المعرف ID المستخرج من useParams لإرسال طلب محدد إلى الـ API، كالتالي: const { postId } = useParams(); useEffect(() => { fetch(`https://api.test.com/posts/${postId}`) .then(res => res.json()) .then(data => setPost(data)); }, [postId]); أيضًا عند قيام المستخدم بنسخ الرابط وإرساله لشخص آخر، ويفتحه ذلك الشخص، سيرى نفس الصفحة بنفس المحتوى تمامًا، بسبب المُعرف الذي في الرابط.
  15. أنت على الطريق الصحيح طالما تجتهد وتلتزم بالتعلم والتطبيق على ما تعلمته وليس المشاهدة فقط، لكن يجب التعمق فيما تتعلمه وليس التنقل بين التقنيات، بمعنى لو تعلمت React لا تنتقل إلى Vue لو أردت تجربتها، إلا بعد فترة شهر على الأقل من دراسة React، أي لا تحكم على أنّ React صعبة أو سهلة وأنت في بداية مرحلة التعلم، فكل شيء صعب تقريبًا في تلك المرحلة بدرجات متفاوتة. المطلوب منك تعلم المهارات اللازمة لسوق العمل وليس ما تُفضله أنت، بالتالي React مثلاً تفتح لك الكثير من الأبواب على عكس Vue، إلا لو كانت مطلوبة في سوق العمل لديك. ولا يصح التسرع والإنتقال للتطبيق على مشروع مُعقد مثل متجر إلكتروني شبيه بأمازون، يجب التدرج في التطبيق العملي، فأولاً من خلال نماذج بسيطة، ثم دمج تلك النماذج لبناء صفحة بسيطة ثم تطوير تلك الصفحة ثم إنشاء صفحات وربطهم ببعضهم البعض، ثم إضافة مزايا للتطبيق لتحسينه. وأثناء ذلك يجب تعلم مفاهيم مثل إدارة الحالة، والتي ستمكنك من تتبع المنتجات في سلة التسوق، وحالة تسجيل دخول المستخدم، المنتجات المفضلة، وخلافه، وذلك يتطلب أدوات متقدمة مثل Redux Toolkit أو Zustand أو على الأقل فهم عميق لـ Context API في React. ومفهوم التوجيه أي Routing، للتنقل بين صفحة المنتجات، صفحة منتج معين، سلة التسوق، صفحة الدفع، ملف المستخدم، وبعدها تتعلم مفهوم المصادقة والتفويض، لتسجيل المستخدمين وتسجيل الدخول وحماية الصفحات الخاصة بالمستخدمين. وكذلك كيفية استخدام الـ API لجلب بيانات خارجية، أي تستطيع جلب منتجات وهمية مثلاً من API خارجي، ومنها Fake Store API.
  16. مكتبة جافاسكريبت خاصة بإنشاء عروض شرائح أي الـ sliders والشرائح الدوارة carousels بشكل تفاعلي ومتجاوبة، وتم تصميمها بشكل أساسي لتوفير أفضل تجربة على الأجهزة التي تعمل باللمس مالهواتف الذكية والأجهزة اللوحية. وهي مستخدمة في غالبية المواقع تقريبًا، لكونها خفيفة وبدون تبعيات، بمعنى أنها لا تعتمد على مكتبات أخرى مثل jQuery، وذلك يجعلها سريعة وخفيفة على أداء الموقع. وتوفر مجموعة واسعة من تأثيرات الانتقال بين الشرائح، وعناصر تحكم متعددة، بجانب ميزة مهمة لتحسين أداء الصفحة، حيث يتم تحميل الصور فقط عندما تقترب الشريحة من العرض، بدلاً من تحميلها كلها مرة واحدة. وباستطاعتك تعديل كل جانب من جوانب الـ Slider تقريبًا عبر الـ API الخاصة بها أو من خلال CSS. ستجد أمثلة هنا: https://swiperjs.com/demos
  17. بالضبط لتحديد الصفحة النشطة حاليًا وإضافة كلاس active إليها، حيث NavLinks.map() تقوم بالمرور على كل عنصر في مصفوفة NavLinks لإنشاء قائمة <li> لكل رابط. و className={ } لكل عنصر <li> في القائمة، لتحديد قيمة الكلاس className بشكل ديناميكي. والشرط location.pathname === item.link ? 'active' : '' هو الجزء الأهم هنا، فهو تعبير شرطي ثلاثي يقوم بالآتي: location.pathname === item.link تعني هل مسار URL الحالي الذي حصلت عليه من useLocation يطابق تمامًا رابط ذلك العنصر item.link الذي يتم عرضه حاليًا في الحلقة؟ ? 'active' ولو الإجابة نعم أي True فالمساران متطابقان، ويتم إعطاء العنصر <li> الكلاس active. وهنا ' ' : تعني كانت لو الإجابة لا False فالمساران غير متطابقين، ولن يتم إضافة أي كلاس بل سلسلة نصية فارغة.
  18. يجب توحيد المعايير بمعنى structure موحد للـ API كالتالي: /api/v1/users: get: summary: جلب قائمة المستخدمين parameters: - page - limit responses: 200: Success 401: Unauthorized وإعتماد API-First Designأي تصميم الـ API قبل البرمجة ومراجعة التصميم مع فريق العمل. كذلك استخدم Versioning واضح، بمعنى إدارة الإصدارات: /api/v1/ و /api/v2/ مع توثيف التغييرات بين الإصدارات لتوضيح ما تم تغييره، وتوفير أمثلة واقعية، و ربط التوثيق بـ CI/CD لتحديثه تلقائيًا مع كل تغيير. لو ما سبق موجود بالفعل، إذن يجب العمل على توفير Wiki مركزي، وتنفيذ مراجعة للكود تشمل مراجعة التوثيق بشكل دوري، وإنشاء API Style Guide موحد للفريق. كذلك إعتماد أداة حديثة مثل Apidog والتي تعتبر أداة شاملة بدلاً من استخدام أدوات متفرقة.
  19. حاليًا Apidog أفضل وعملي أكثر من Postman، فهو بمثابة أداة شاملة، لكونه يدمج تصميم وتوثيق واختبار ومحاكاة الـ API في منصة واحدة، وذلك يقلل من الحاجة للتنقل بين أدوات متعددة مثل Postman و Swagger و Mockoon. ويوفر محرر رسومي أيضًا وويدعم مواصفات OpenAPI لتصميم الـ API من البدايةن والتغييرات في التصميم تنعكس تلقائيًا على التوثيق والاختبار. كذلك واجهة رسومية سهلة لإضافة الاختبارات بدون الحاجة لكتابة كود، ويدعم سكربتات الاختبار المخصصة، ويوفر إنشاء Mock Server تلقائيًا بناءًا على تصميم الـ API، ثم توليد بيانات وهمية ذكية كأسماء وإيميلات إعتمادًا على نوع الحقل. ويتم إنشاء التوثيق مباشرًة أثناء تصميم الـ API، والتوثيق تفاعلي وبتصميم جيد وجاهز للمشاركة مع فريق الـ Frontend، حيث كل شيء مبني حول فكرة التعاون، فالتغييرات التي يجريها مصمم الـ API تظهر فورًا للمختبر ومطور الواجهة الأمامية.
  20. هناك أمر هام بجانب ما تم تفصيله وهو، عندما يتغير عنوان URL بسبب نقر المستخدم على <Link> أو استخدام useNavigate، فخطاف useLocation يتسبب في إعادة تصيير أي re-render للمكون الذي يستخدمه، لذا واجهة المستخدم سيتم تحديثها تلقائيًا لتعكس المسار الجديد. بمعنى لو يوجد Sidebar وتريد تظليل الرابط النشط حاليًا، فاستخدام useLocation().pathname سيضمن تحديث التظليل فورًا عند التنقل بين الصفحات. كذلك تستطيع استخدام كائن location.search لتحليل متغيرات البحث لاستخراج قيمة معينة، كالتالي: import { useLocation } from "react-router-dom"; const ProductPage = () => { const location = useLocation(); const queryParams = new URLSearchParams(location.search); const refValue = queryParams.get('ref'); if (refValue === 'google') { console.log("User came from Google!"); } return <div>Product Details</div>; }; أو في صفحة البحث عند النقر على المنتج: <Link to={`/products/${product.id}`} state={{ from: '/search?q=laptops' }} > View Product </Link> وفي صفحة المنتج: import { useLocation, Link } from "react-router-dom"; const ProductDetails = () => { const location = useLocation(); const fromPath = location.state?.from; return ( <div> <h1>Product Details</h1> {fromPath && <Link to={fromPath}>← Back to search results</Link>} </div> ); }; بالتالي لو المستخدم قادم من صفحة البحث، سيتم إظهار رابط العودة إلى البحث.
  21. يوجد أدوات أجنبية لكن تدعم العربية بشكل ممتاز، وهي Postman و Swagger، حيث توفر دعم باللغة العربية من ناحية البيانات والتوثيق، بالتالي الصعوبة لغير متحدثي العربية هو في التعود على الواجهة الإنجليزية، ولكن مع الاستخدام تصبح سهلة جداً. ففي Postman متاح كتابة أسماء الـ Collections والـ Requests باللغة العربية، كذلك إرسال بيانات JSON Body تحتوي على نصوص عربية بالكامل: { "userName": "أحمد ", "address": { "city": "الرياض", "street": "شارع الملك فهد" } } وكتابة توثيق كامل لكل endpoint باللغة العربية، يشمل وصف الـ API، وصف المتغيرات، والأمثلة. بالنسبة لـ Swagger فمتاح كتابة كل الأوصاف، الملخصات، والأمثلة باللغة العربية داخل ملف الـ swagger.yaml.
  22. المشروع لديك سليم لا مشكلة به، لكن المشكلة من المتصفح جوجل كروم نفسه، فهو يُضيف مساحة بيضاء زائدة ناحية اليسار أو اليمين أحيانًا، لذا لحل تلك المشكلة قم بوضع التالي أثناء التطوير في ملف app.css html, body { overflow-x:hidden; } أو تستطيع استخدام الإضافة التالية لإختبار التجاوبية: Pixefy - Responsive Design Checker المشكلة الوحيدة التي ستظهر خاصة بقسم contact US في أصغر مساحة شاشة، بسبب وجود padding لذا قم بحذفه عن طريق تطبيق التالي: @media (max-width: 320px) { .doctors { max-width: 1200px; margin: auto; /* padding: 0 3rem; */ margin-top: 28%; } }
  23. الجميع مر بتلك المرحلة، لكن هونًا على نفسك، كيف تقارن بمن حصد نتاج سنوات من الجد والإجتهاد والخبرة الناتجة عن مواجهة الكثير من الأخطاء والتجربة العملية، الأمر غير منطقي بالمرة. فكر بشكل مختلف، أي بعقلية إيجابية ومنطق سليم، بأن تطمح للوصول لما هم عليه الآن أو بنسبة 50% حتى بعد سنتين أو ثلاث من الآن، حسب مستوى الخبرة الذي تقارن نفسك به، بالتالي كن واقعي ولا تضع آمال ليست عملية كأن تصل لنفس مستوى شخص ذو خبرة 5 سنوات خلال السنة الأولى مثلاً. الأفضل أن تقارن نفسك بنفسك كل فترة وتفقد مستوى تقدمك، والتعلم من لهم خبرة في المجال وليس مقارنة نفسك بهم، لكن يجب التخطيط وليس ترك الأمر بشكل عبثي، بمعنى تلتزم بخارطة طريق roadmap خلال فترة زمنية محددة. وكن واثق بأنّ الصبر والاستمرار هما المفتاح للوصول ما تريده وتحقيق شيء ذو قيمة، بدونهم لن تصل حتى لو كنت الأذكى.
  24. اسم الملف ليس إلزامي تستطيع تسميته كما تريد، لكن الأفضل هو client.js ويتم به وضع الكود الذي يضيف التفاعلية لواجهة المستخدم بعد استلام كود HTML من الخادم أي السيرفر، وذلك في حال سيتم استخدام الـ SSR بالمشروع. أي باستخدام React مع Express.js، لكن لا حاجة إلى طالما Next.js يوفر ذلك وأفضل:
  25. تلك خاصية أي prop نمررها لمكون BrowserRouter في React Router، لإخباره بأن التطبيق لا يعمل على الدومين الرئيسي بل يعمل داخل مجلد فرعي، أي دومين فرعي. بمعنى لو أردت وضع التطبيق داخل مجلد فرعي اسمه my-app، فستصبح الروابط كالتالي: https://www.test.com/my-app/ (الصفحة الرئيسية) صحفات أخرى https://www.test.com/my-app/about https://www.test.com/my-app/contact بالتالي لو قمت باستخدام المسار كالتالي <Link to="/about">، فسيحاول المتصفح الذهاب إلى https://www.test.com/about ,`g; مسار خاطئ سيؤدي إلى صفحة خطأ 404 Not Found. لذا من خلال basename أنت تخبر React Router أن المسار الأساسي لجميع روابطك هو /my-app، وبالتالي سيعرف كيف يبني الروابط بشكل صحيح. import { BrowserRouter, Routes, Route, Link } from 'react-router-dom'; function HomePage() { return <h1>الصفحة الرئيسية</h1>; } function AboutPage() { return <h1>صفحة من نحن</h1>; } function App() { return ( <BrowserRouter basename="/my-app"> <nav> <Link to="/">الرئيسية</Link> | <Link to="/about">من نحن</Link> </nav> <Routes> <Route path="/" element={<HomePage />} /> <Route path="/about" element={<AboutPage />} /> </Routes> </BrowserRouter> ); } export default App;
×
×
  • أضف...