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

Hikmat Jaafer

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

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

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

5 متابعين

آخر الزوار

323 زيارة للملف الشخصي

إنجازات Hikmat Jaafer

عضو نشيط

عضو نشيط (3/3)

129

السمعة بالموقع

6

إجابات الأسئلة

  1. مرحباً منصور , ما رأيته في الموقع هو أنك تريد عرض مجموعة صور بشكل بطاقات , وعندما نضغط على أحد الصور , تظهر الصورة بكامل الصفحة ويمكننا التنقل بين الصور مثل Gallery . يوجد مكتبة تسمى react-image-gallery يمكنك استخدامها في مشروعك NextJs لإنشاء معرض صور , سأوضح في المثال التالي كيف يمكن تنزيلها واستخدامها : أولاً قم بتثبيت المكتبة في مشروعك : npm install react-image-gallery لجعل الكود قابل لإعادة الاستخدام وببنية صحيحة , قم بإنشاء component خاص لعرض الصور كالتالي( وليكن ImageGallery.js ) : import React from 'react'; import Gallery from 'react-image-gallery'; import 'react-image-gallery/styles/css/image-gallery.css'; const images = [ { original: 'path/to/image1.jpg', thumbnail: 'path/to/image1_thumbnail.jpg', description: 'Description 1' }, { original: 'path/to/image2.jpg', thumbnail: 'path/to/image2_thumbnail.jpg', description: 'Description 2' }, ]; const ImageGallery = () => { return ( <Gallery items={images} /> ); }; export default ImageGallery; ويمكنك جعل مصفوفة الصور أن تكون ك props بعدها يمكنك استخدام component في صفحة Next js كالتالي : import React from 'react'; import ImageGallery from '../components/ImageGallery'; const GalleryPage = () => { return ( <div> <h1>Gallery</h1> <ImageGallery /> </div> ); }; export default GalleryPage;
  2. هل تقصد فتح البرنامج بكامل الشاشة ( وكأنك ضغطت على أيقونة التكبير ) عندما يفتح البرنامج في البداية ( أي الوضع الافتراضي يكون تكبير للشاشة ) ؟ إذا كان هذا قصدك , فيمكنك فعل ذلك كالتالي ( باستخدام windowManager.screenSize.width و windowManager.screenSize.height ) : import 'package:flutter/material.dart'; import 'package:window_manager/window_manager.dart'; void main() { runApp(MyApp()); makeWindowFullScreen(); } void makeWindowFullScreen() async { WidgetsFlutterBinding.ensureInitialized(); await windowManager.ensureInitialized(); await windowManager.setTitleBarStyle('hidden'); await windowManager.setFullScreen(false); await windowManager.setWindowSize(windowManager.screenSize.width, windowManager.screenSize.height); await windowManager.center(); await windowManager.show(); await windowManager.setSkipTaskbar(false); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('Flutter Desktop App'), ), body: Center( child: Text( 'مرحبا بك في تطبيق فلاتر ديسكتوب', style: TextStyle(fontSize: 24), ), ), ), ); } }
  3. مرحباً Amir, للقيام بتكبير التطبيق عند فتحه، يمكنك استخدام المكتبة نفسها التي ذكرها المدرب مصطفى window_manager ولكن بشكل مختلف. يمكنك استخدام دالة setWindowSize لتحديد حجم النافذة عند الافتتاح. سأقوم بالكود التالي توضيح كيف يمكننا فعل ذلك: import 'package:flutter/material.dart'; import 'package:window_manager/window_manager.dart'; void main() { runApp(MyApp()); makeWindowLarge(); } void makeWindowLarge() async { WidgetsFlutterBinding.ensureInitialized(); await windowManager.ensureInitialized(); await windowManager.setTitleBarStyle('hidden'); await windowManager.setFullScreen(false); await windowManager.setWindowSize(800, 600); // يمكنك تعديل الأبعاد كما تشاء await windowManager.center(); await windowManager.show(); await windowManager.setSkipTaskbar(false); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('Flutter Desktop App'), ), body: Center( child: Text( 'مرحبا بك في تطبيق فلاتر ديسكتوب', style: TextStyle(fontSize: 24), ), ), ), ); } } لاحظ أنني أقوم بفتح التطبيق بحجم محدد بدلاً من الشاشة الكاملة. قمت بتحديد حجم النافذة باستخدام setWindowSize وقمت بتعيين العرض والارتفاع وفقاً لاحتياجاتك. يمكنك تعديل الأبعاد وفقاً للحجم الذي تريده.
  4. نعم , سيتم تحميل جزء من الكود في Sources ضمن developer tools , وسيتحمل بشكل كامل ( يعيد DOM لهذه الصفحة ) فقط عندما يذهب إلى المسار ( أي بهذه الحالة سوف يستطيع المستخدم من الوصول إلى الكود من خلال developer tools ) لكن إذا أردت منع المستخدمين من الوصول , يمكنك استخدام ما يسمى lazy loading , سوف أقوم بإعطاء شرح مختصر مع مثال على ذلك ( سوف نعدل فقط في محتوى ملف App.js ) : مثال باستخدام Lazy Loading : Lazy Loading هو نمط يستخدم لتحميل المحتوى أو المكونات فقط عندما يكون هناك حاجة فعلية لها، بدلاً من تحميلها جميعا في البداية. وبالتالي يساعد هذا النمط في تحسين سرعة التحميل الأولي للصفحة وتوفير موارد الشبكة.و يمكننا استخدام React.lazy و Suspense لتحقيق ذلك كما في المثال التالي : App.js import React, { lazy, Suspense } from 'react'; import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; const CustomerPage = lazy(() => import('./CustomerPage')); const SellerPage = lazy(() => import('./SellerPage')); function App() { return ( <Router> <div> <Suspense fallback={<div>Loading...</div>}> <Switch> <Route path="/seller" component={SellerPage} /> <Route path="/" component={CustomerPage} /> </Switch> </Suspense> </div> </Router> ); } export default App; قمت بتحميل المكونات CustomerPage و SellerPage بشكل lazy loading باستخدام React.lazy. يمكننا استخدام عنصر Suspense كمكون واجهة مستخدم لعرض تحميل أثناء انتظار تحميل المكونات. عنصر fallback يعرض رسالة "Loading..." أثناء التحميل. وهكذا سيتم تحميل المكونات اللازمة فقط عندما يتم طلبها بواسطة المستخدم، مما يؤدي إلى تحسين أداء التطبيق وتوفير الوقت والموارد كما تريد .
  5. دورة علوم الحاسوب مقدمة للمبتدئين في مجال البرمجة , فهي تعرف الطالب بمكونات الحاسوب و أنظمة التشغيل بالإضافة إلى أساسيات البرمجة و التفكير المنطقي. و أي شخص يريد الدخول في مجال البرمجة فعليه البدء بهذه الدورة, أما إذا كان المتعلم يمتلك خبرة سابقة في مجال البرمجة فيمكنه تخطي هذه الدورة. و بعد أن ينهي المتعلم دورة علوم الحاسوب يستطيع اختيار المجال الذي يريد التخصص فيه و يشترك بالدورة التي تناسب هذا المجال. لذلك عليك الاستمرار بمتابعة هذه الدورة اذا كنت جديد في مجال البرمجة . وبعد الانتهاء منها تستطيع التخصص في ألعاب الأندرويد. يمكنك الاشتراك بدورة تطوير التطبيقات باستخدام لغة javascript هذه الدورة تتعلم أساسيات مكتبة react native و javascript و تقوم بتطوير تطبيق جوال, و لكن بعد أن تتعلم الأساسيات عليك أن تتوسع أكثر بالاجتهاد الشخصي لتستطيع تطوير الألعاب , هناك عدة مكتبات وإطارات تعمل مع React Native وتساعد في تطوير الألعاب بشكل فعال بعض هذه المكتبات تتضمن: Expo-THREE React Native Game Engine React Native Unity Integration React Native SpriteKit
  6. مرحباً أحمد , نعم يمكنك فعل ذلك من خلال تصميم عدة routes لعدة مستخدمين , ويمكنك أيضاً فحص ذلك في backend ( لجعل apis أيضاً لا يمكن الوصول إليها إلا من له صلاحية ) . بالنسبة للواجهات الأمامية , يمكنك فعل ذلك باستخدام أحد المكتبات مثل React , هذا مثال يوضح كيف يمكنك تصميم هذه المنهجية : سأقوم بإنشاء تطبيق React يحتوي على صفحتين: صفحة للعميل وصفحة للبائع. ستحتوي كل صفحة على مكوناتها الخاصة وستتحول بينهما باستخدام React Router. في ملف App.js : import React from 'react'; import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; import CustomerPage from './CustomerPage'; import SellerPage from './SellerPage'; function App() { return ( <Router> <div> <Switch> <Route path="/seller"> <SellerPage /> </Route> <Route path="/"> <CustomerPage /> </Route> </Switch> </div> </Router> ); } export default App; في ملف SellerPage : import React from 'react'; function SellerPage() { return ( <div> <h1>Welcome, Seller!</h1> {/* Add seller-specific components and content here */} </div> ); } export default SellerPage; في ملف CustomerPage: import React from 'react'; function CustomerPage() { return ( <div> <h1>Welcome, Customer!</h1> {/* specific components for customer */} </div> ); } export default CustomerPage; ويمكنك التعديل على هذا الكود ليتضم أيضاً عدة أدوار , أي مثلاً يمكنك فحص قيمة ما إذا كان المستخدم الحالي هو seller فقم بعرض صفحات sellers , غير ذلك قم بطباعة صفحات cutsomers.
  7. قمت بالإطلاع على الكود لديك في عربة التسوق , يوجد أخطاء في frontend و backend , إليك التوضيح التالي : في قسم Frontend : عند إضافة بعض المنتجات إلى عربة التسوق والذهاب إلى عربة التسوق , سوف نلاحظ أنها لا تقوم بعرض المنتجات قم بالذهاب إلى صفحة CartPage وقم بطباعة CartItems وسوف تجد أنها مصفوفة فارغة ولا يوجد بها منتجات , وإذا قمت بعمل inspect والذهاب إلى تبويبة Network , سوف تجد أن api cart يعمل ويرجع منتجات , إذن الخطأ هو بطريقة ملئ القيم المرجعة من api في CartItems قم بالذهاب إلى ملف hook => cart => get-all-user-cart-hook , حيث أنك تقوم هنا بتعبة CartItems من Api. ستلاحظ أنه في السطر 32 الملف أنك تقوم بإسناد القيمة res.data.products ل cartItems , قم بطباعة المتغير res وسوف تجده كما في الصور في الاعلى , لاحظ أنه لا يوجد حقل بداخله يسمى products , وإنما ما نريده هو cartItems بدلا من products , فيمكنك تعديل السطر 32 ليصبح هكذا : setCartItems(res.data.cartItems) أيضاً هناك خطأ أخر , لاحظ أن القيم المرحعة من api لا يوجد بها تفاصيل المنتج ( كأسم الصنف , والمنتج والصورة وغيره ) , أي أنه يوجد خطأ أيضاً في إرجاع القيم من api ( خطاً خاص في Backend ). سوف يظهر بعض الأخطاء الأخرى ولا تعمل الصفحة , تجاهلها بينما نقوم بحل مشكلة backend وسوف يعمل بشكل صحيح . في قسم Backend: قم بالتوجه إلى api الخاص بإرجاع المنتجات ل cart , ستجده في السطر 62 ( getLoggedUserCart ) في العنوان التالي : services => cartService.js يجب علينا إصلاح هذا api ليرجع معلومات المنتجات وليس فقط id المنتج , أي يجب عليك تعديله ليصبح كالتالي : // @desc Get logged user cart // @route GET /api/v1/cart // @access Private/User exports.getLoggedUserCart = asyncHandler(async (req, res, next) => { const cart = await Cart.findOne({user: req.user._id}).populate("cartItems.product"); if (!cart) { return next(new ApiError(`There is no cart for this user id: ${req.user._id}`, 404)); } const updatedCartItems = await Promise.all( cart.cartItems.map(async (cartItem) => { if (cartItem.product) { const productDetails = cartItem.product._doc; return {...cartItem._doc, product: productDetails}; } return cartItem; }) ); const tempCart = {...cart._doc, cartItems: updatedCartItems}; res.status(200).json({ status: "success", numOfCartItems: cart.cartItems.length, data: tempCart, }); }); وانتبه لإرجاع تفاصيل المنتج بحقل اسمه product , وذلك لأنك في frontend تستخدمه بهذا الشكل . بعد تطبيق هذه الملاحظات سوف تجد أن التطبيق يعمل بشكل صحيح كم في الصورة المرفقة يوجد أخطاء أخرى في الأزرار والتصميم وغيره من الأخطاء , ما أنصحك به قم بحل الأخطاء البرمجية أولاً ثم قم بحل أخطاء التصميم .
  8. هذه بعض الحلول لبعض الثغرات : الوصول غير المصرح به (Unauthorized Access): يمكنك التحقق من صحة هوية الحساب لضمان أن المستخدمين يتمكنون فقط من الوصول إلى الموارد التي يجب عليهم الوصول إليها. تجاوز الصلاحيات (Privilege Escalation): يمكنك التحقق من صلاحيات المستخدمين لضمان أنهم لا يمكنهم الوصول إلى ميزات أو بيانات ليس لديهم حق الوصول اليها . التعرض للاختراق (SQL Injection): يمكنك استخدام باراميترات مربوطة وعبارات معيارية لتجنب استغلال ثغرات حقل الإدخال في عمليات قاعدة البيانات.و هذا مثال يوضحالفكرة: لو فرضًنا أن لديك جدولًا اسمه users يحتوي على حقلين username و password، ونرغب في تنفيذ استعلام SQL للتحقق مما إذا كان المستخدم موجودًا في الجدول أم لا باستخدام اسم المستخدم وكلمة المرور المدخلة. DECLARE l_username VARCHAR2(100) := :P1_USERNAME; l_password VARCHAR2(100) := :P1_PASSWORD; l_user_id NUMBER; BEGIN SELECT user_id INTO l_user_id FROM users WHERE username = l_username AND password = l_password; EXCEPTION WHEN NO_DATA_FOUND THEN raise_application_error(-20001, 'Invalid username or password.'); END; البرمجيات الضارة (Cross-Site Scripting XSS): يمكنك تنقيح الإدخالات والمخرجات لمنع تنفيذ السكربتات الضارة في المتصفح و هناك عدة طرق لعمل ذلك منها: التطهير (Sanitization): وهي عملية تنقيح البيانات لتنظيف الإدخالات من الأحرف والعلامات الغير مرغوب فيها التعقيد (Encoding):تحويل الأحرف الخاصة إلى رموز مشفرة للحفاظ على سلامة البيانات. التحقق من الصحة (Validation):التحقق من صحة البيانات المدخلة لضمان أنها تتوافق مع الصيغة المتوقعة.
  9. وعليكم السلام , أهلاً أحمد جيد جداً , هل يمكنك إرفاق الكود لديك بعد إجراء التعديلات ؟ ويمكنك إرفاقه كالتالي ( لكي يصبح حجم الملف المضغوط صغير ) : أولاً قم بتحديد المجلدات واستثناء مجلد node_modules . بعد ذلك يمكنك ضغط المجلد باستخدام اي برنامج ضغط , كما قمت من قبل . أو يمكنك رفع الكود على مستودع GitLab أو GitHub ومشاركته معنا باستخدام رابط المشاركة .
  10. مرحباً NAIF, أرى أن هذا سيكون مفيد جداً وخصوصا للمهتمين بالادب العربي , سيساعدهم جداً في تشكيل الكلام. سوف أقوم بتقديم لك كود يضعك على بداية الطريق , ويمكنك استخدامه وتطويره لتصل إلى المطلوب <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Text Formatting</title> <style> body { font-family: Arial, sans-serif; } #inputText, #outputText { width: 100%; height: 200px; margin-bottom: 10px; } </style> </head> <body> <textarea id="inputText" placeholder="Enter your text here"></textarea> <button onclick="formatText()">Format</button> <textarea id="outputText" readonly></textarea> <script> function formatText() { const inputText = document.getElementById('inputText').value; const words = inputText.trim().split(/\s+/); let formattedText = ''; words.forEach((word) => { formattedText += word.split('').join('ـ') + '\n'; }); document.getElementById('outputText').value = formattedText; const element = document.createElement('a'); const file = new Blob([formattedText], { type: 'text/plain' }); element.href = URL.createObjectURL(file); element.download = 'formatted_text.txt'; element.click(); } </script> </body> </html> التابع formatText تقوم بمعالجة النص المدخل وفق الخطوات التالية : تأخذ القيمة المدخلة في المربع النصي. تقوم بتنظيف النص من الفراغات الزائدة في بداية ونهاية النص. تقوم بتقسيم النص إلى كلمات باستخدام الفراغ كفاصل. لكل كلمة، تقوم بتقسيمها إلى أحرف وتستبدل كل حرف بحرف خطي. تُضاف الكلمة المنسقة إلى المتغير formattedText. يتم تحديث المربع النصي الثاني بالنص المنسق. أخيراً يقوم بتحميل الملف المنسق في ملف txt .
  11. بما أن مشروع الأدمن يعمل على المسار wesamelnagah.com:90 فتستطيع بعدة خطوات تغيير نطاقه , الفكرة هي كالتالي: سيبقى مشروع الأدمن على النطاق الحالي و سنقوم بتغيير إعدادات السيرفر لنجعله عندما يتلقى طلبا للنطاق wesamelnagah.com/admin يقوم بإعادة توجيه الطلب للنطاق الحقيقي wesamelnagah.com:90. و هذه الفكرة نظريا يطلق عليها مفهوم ال proxy , و للقيام بها اتبع هذه الخطوات: قم بتسجيل الدخول لحساب ال vps الخاص بك. قم بتثبيت nginx إذا لم تكن قد ثبته من قبل. قم بتهيئة nginx كالتالي: اذهب لمجلد الاعدادات الخاص ب nginx (غالبا في هذا المسار /etc/nginx/sites-available/)=> أنشأ ملف اعدادات جديد تستطيع تسميته بأي اسم تريده => افتح هذا الملف بواسطة محرر نصوص => ضع هذه التعليمات في الملف و احفظه server { listen 80; server_name wesamelnagah.com; location /admin { proxy_pass http://wesamelnagah.com:90; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } قم بتعريف الملف الذي أنشأته في مجلد ال sites-enabled ليتمكن السيرفر من رؤيته و تنفيذه في لينوكس يمكنك استخدام هذه التعليمة : sudo ln -s /etc/nginx/sites-available/اسم الملف الذي أنشأته /etc/nginx/sites-enabled/ أعد تشغيل nginx لكي يقوم بتطبيق التغييرات. قبل أن تعيد التشغيل من الأفضل من أن تقوم بفحص الإعدادات التي أنشأتها للتأكد من عدم وجود أخطاء syntax , يمكنك استخدام هذه التعليمة لعمل ذلك في لينوكس nginx -t
  12. مرحباً حارث , التدريب على التصاميم يمكن أن يكون عملية شاملة تشمل عدة خطوات ومراحل، سأوضح لك بعض الطرق المشهورة لتدريب التصميم مع أمثلة: التعليم الأكاديمي : هذا النوع من التدريب يشمل الحصول على درجة جامعية في التصميم الجرافيكي أو التصميم الصناعي. يتضمن البرنامج دراسة النظريات والمفاهيم الأساسية للتصميم بالإضافة إلى التطبيق العملي. على سبيل المثال، جامعات مثل Rhode Island School of Design وRoyal College of Art توفر برامج متميزة في هذا المجال. الدورات التدريبية عبر الإنترنت: هناك عدة منصات تقدم دورات تدريبية في مجالات التصميم المختلفة، بما في ذلك تصميم الجرافيك وتجربة المستخدم والتصميم الصناعي. هذه الدورات غالبا ما تكون مدعومة بمشاريع عملية لتطبيق المفاهيم المدرسة. المشاركة في ورش العمل والمسابقات : أيضاً هناك نوع أخر مثل ورش العمل والمسابقات , إذ توفر ورش العمل والمسابقات فرصة رائعة لتعلم المهارات الجديدة وتطبيقها على مشاريع فعلية. يمكنك البحث عن ورش العمل والمسابقات المحلية أو الدولية في مجال التصميم والمشاركة فيها. على سبيل المثال، يمكنك الانضمام إلى مسابقة تصميم شعار لشركة محلية . التعلم من الخبراء والمجتمعات المحترفة: يمكنك الانضمام إلى مجتمعات مثل Dribbble وBehance والمشاركة في المناقشات ومشاهدة أعمال الآخرين والتعلم منهم. كما يمكنك حضور المؤتمرات وورش العمل التي تقدمها الشركات المتخصصة في التصميم للتعرف على أحدث التطورات في المجال. تعتبر هذه الطرق الشائعة للتدريب على التصميم وجذب العميل من خلال تصميم جيد , ويمكنك الدمج بين عدة أنواع تعلم . وبشكل عام , يمكنك حضور دورات تدريبية , ومن ثم المشاركة في المسابقات , وبعدها رؤية المجتمعات المتعلقة بالتصميم وحضور الإجتماعات الخاصة بهذا الموضوع .
  13. التركيز في مشروع واحد يعطيك فرصة في التعمق وفهم التفاصيل بصورة أفضل , و هذا الشيء يفيدك في تطوير مهاراتك, لكن إذا بقي تركيزك على مشروع واحد لن تكتسب مهارات جديدة فيمابعد , و لذلك عليك المساهمة في مشاريع أخرى متنوعة لكي تكسب مهارات جديدة, ولكن عليك أن تدير و تنظم طريقة تعلمك لكي لاتضيع وقتك بدون فائدة و لكي تحصل على أفضل نتيجة , ولكن من الخطأ أن تبدأ بالمساهمة بعدة مشاريع معا لأن ذلك سيجعلك تتشتت و لن تستطيع التركيز في أي شيء , لذلك بداية عليك أن تساهم في مشروع واحد و عندما تصبح متمكن فيه و تفهم تفاصيله و تمتلك الخبرات اللازمة لإنجاز هذا المشروع تنتقل للبدء بالمساهمة في مشروع آخر مختلف لكي تكسب مهارات وخبرات جديدة . و عليك أن تختار المشاريع التي تتناسب مع اهتماماتك ومهاراتك الحالية، وتقدم لك الفرصة للتعلم والنمو.
  14. مرحباً أحمد , من الجيد أنك تقوم ببناء موقع متجر إلكتروني والمتابعة في البحث عن الاخطاء والحلول , لكن نحن نريد نقوم بكسبك الخبرة اللازمة للدخول في سوق العمل إن كان في الشركات أو من خلال العمل freelancer , لذلك من الأفضل أن تجد الأخطاء وتقوم بطرحها واحد تلو الأخر ( أو كل مجموعة أخطاء ) بعد محاولتك في حلها , وسوف يقوم فريق المدربين أو أحد الأعضاء بالإجابة عليك والمساعدة قدر الإمكان لكسبك الخبرة اللازمة . قمت بالإطلاع على الكود لديك , وواجهة أول مشكلة في الدخول الى صفحة المنتج , ما لاحظته أنك تقوم ببناء الموقع وفق بنية جيدة جداً وبتقسيم الكود إلى عدة أجزاء و Components وهذا مرغوب جداً لدى الشركات وأصحاب العمل وفي عالم البرمجة ككل , لكن يوجد بعض الأخطاء يجب عليك معرفة كيف تقوم باكتشافها وحلها , فمعرفة كيف كشف هذه الأخطاء مهم جداً لدى شركات البرمجة وأصحاب المشاريع , سوف أقوم بتوضيح أول ما واجهته في صفحة المنتجات : أولاً , يمكنك فتح inspect في المتصفح ورؤية ما يسمى ب console , وفيها يتم عرض جميع الأخطاء التي تحصل في الموقع , ويمكنك أيضاً طباعة متغيرات في الكود لديك ورؤيتها قبل حدوث أي خطأ . عندما نقوم بفتح inspect , يوجد عدة أخطاء , بعضها في التصميم وبعضها في backend , سوف نبدأ بأخطاء خاصة ب frontend . إذا قمنا بعمل scroll في inspect سوف نشاهد الخطاً التالي Uncaught TypeError: oneProducts is undefined هذا الخطأ يشير إلى أن المتغير oneProducts غير معرف , أي أنك تقوم باستخدامه وهو غير معرف بعد أو قيمته undefined , وهذه الحالة تحصل عندما يقوم المبرمج باستخدام متغير ولم يقم بتعريفه , أو أنه يتوقع أن متغيراً ما سوف يكون به قيمة ( مثلاً سوف ترجع هذه القيمة من api من قاعدة البيانات ) ولكنه لم يعالج في حال لم يوجد به قيمة , وهذا ما حصل معك بالفعل لنفترض أنك لا تعلم أين هذا المتغير قمت بتعريفه وأين يحصل وتريد معرفة مكان تعريف هذا المتغير , سوف تجد أسفل الخطأ رقم السطر واسم الملف الذي حدث به الخطأ ( أو إن لم تظهر هذه المعلومات مباشرةً , قم بالضغط على السهم في بداية الخطأ وسوف يفتح مجموعة أسطر في اسفل الخطأ , يمكنك الوصول إلي الخطأ من خلال أول سطر , وهذا يتم في أغلب الأخطاء وليس جميعها ) , وفي مثالنا سوف تجد هذه السطر كما الصورة المرفقة لاحظ أن الخطأ يحصل في ملف view-products-details-hook.js , ضمن component يسمى ViewProductsDetailsHook , في السطر رقم 26 ( رقم السطر مرتبط في نسخة تشغيل المشروع وليس كود المشروع , أي ربما ستجد بعض الاختلاف في رقم السطر , ويمكنك مشاهدته في inspect من خلال الضغط عليه , لكن لن تتمكن من تعديله هنا , سوف يتوجب عليك تعديله في الكود ) . عند الذهاب إلى هذا الملف , سوف نجد الكود التالي : const oneProducts = useSelector((state) => state.allproducts.oneProduct) const oneCategory = useSelector((state) => state.allCategory.oneCategory) const oneBrand = useSelector((state) => state.allBrand.oneBrand) const productLike = useSelector((state) => state.allproducts.productLike) //to show products item let item = []; if (oneProducts.data) لاحظ أنك تقوم باستخدام حقل data من oneProducts مباشرةً من غير أن قوم بالفحص من وجود oneProducts ( أي أن قيمتها موجودة ولا ومعرفة ) , لذلك سوف نقوم بإضافة هذا التحقق لكي تعمل الصفحة حتى ولو كان لم يرجع api بيانات لأي سبب كان , ويمكنك تعديل الكود ليصبح كالتالي : const oneProducts = useSelector((state) => state.allproducts.oneProduct) const oneCategory = useSelector((state) => state.allCategory.oneCategory) const oneBrand = useSelector((state) => state.allBrand.oneBrand) const productLike = useSelector((state) => state.allproducts.productLike) //to show products item let item = []; if (oneProducts?.data) item = oneProducts.data; else item = [] useEffect(() => { if (item?.category) dispatch(getOneCategory(item.category)) if (item?.brand) dispatch(getOneBrand(item.brand)) if (item?.category) dispatch(getProductLike(item.category)) }, [item]) لاحظ أنني قمت بإضافة بإضافة إشارة الاستفهام بعد oneProducts و item , والتي تعني : أنه في حال كان المتغير oneProducts معرف , فقم بالوصول إلى الحقل data , وفي حال كان oneProducts.data موجود , فقم بالتالية : item = oneProducts.data; ويتم التحقق من item بنفس الطريقة. بعد تطبيق هذا التحقق لن يظهر الخطاً الخاص ب oneProducts , لكن سوف تجد أخطاء أخرى تتعلق ب oneCategory وغيرها , أغلبها نفس الخطأ , قم بإصلاح الأخطاء وتابع inspect , وعندما تواجهك أي سؤال يمكنك طرحه هنا .
  15. مرحباً , يمكنك استخدام extension خاصة بكل لغة ( حسب اللغة التي تريدها ) , مثلاً اكستنشن خاصة ب Bootstrap , او في react , او python . و يمكنك أيضاً استخدام ذكاء اصطناعي داخل VS Code , أحدهم يسمى BITO , هو يقدم عدة ميزات , منها المساعدة في الإكمال التلقائي للكتابة . ويمكنك أيضاً استخدام هذه extension لمساعدتك في توليد الأكواد أو فهم أي كود من خلال المحادثة كما في الصورة المرفقة
×
×
  • أضف...