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

Mustafa Suleiman

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

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

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

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

    300

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

  1. لكي تتأكد من أن الدالة handlevalid() وطباعة console.log(auth) تعملان بعد انتهاء عملية login()، عليك باستخدام مفهوم Promises في JavaScript. أي عدل الكود كما يلي في ملف authAction.js: import { postDataApi } from "../../utils/fetchDataApi"; export const login = (data) => async (dispatch) => { try { const res = await postDataApi(`login`, data); localStorage.setItem('login', true); dispatch({ type: "AUTH", payload: { token: res.data.access_token, user: res.data.user } }); localStorage.setItem('login', true); console.log(res); return res; // يتم إرجاع الاستجابة لتصبح متاحة للدالة المستدعاة } catch (error) { // إدارة الأخطاء هنا } }; في ملف login.jsx: import { login } from "../../redux/actions/authActions.js"; const handleChange = (e) => { const { name, value } = e.target; setUserData({ ...userData, [name]: value }); }; const handlevalid = async () => { if (auth.token) { setIsCorrect(true); } else { setIsCorrect(false); } }; const handleLogin = async (e) => { e.preventDefault(); setUserData({ email, password }); try { const res = await dispatch(login(userData)); // انتظر حتى انتهاء العملية console.log(res); // استخدم الاستجابة المتاحة هنا handlevalid(); console.log(auth); } catch (error) { // إدارة الأخطاء هنا } }; مع هذه التغييرات، الآن الدالة handleLogin() ستنتظر انتهاء العملية في login() باستخدام الكلمة المفتاحية await وستحتفظ بالاستجابة في المتغير res. بعد ذلك، تستطيع استخدام الاستجابة في console.log(res) أو أي عملية أخرى قبل استدعاء handlevalid() وconsole.log(auth).
  2. حاول تجربة استخدام المتغير العالمي $_SERVER['HTTP_REFERER'] في صفحة page.php للتحقق من الموقع الذي يحاول الوصول إلى الصفحة عبر iframe. وتستطيع التحقق من قيمة المتغير ومقارنتها بعنوان الموقع المسموح به (domain2.com)، وإذا كانت مختلفة، يمكنك عرض رسالة "غير مسموح". وإليك مثال لكود PHP بإمكانك استخدامه في صفحة page.php: <?php $allowedDomain = 'http://domain2.com'; // التحقق من وجود قيمة referer ومقارنتها بالموقع المسموح به if (isset($_SERVER['HTTP_REFERER']) && strpos($_SERVER['HTTP_REFERER'], $allowedDomain) !== 0) { echo "غير مسموح"; exit; } // استمرار في عرض محتوى الصفحة ?> <!DOCTYPE html> <html> <head> <title>صفحة</title> </head> <body> <!-- محتوى الصفحة هنا --> </body> </html> ولاحظ أنه على الرغم من أن هذا الحل يعمل في معظم الحالات، إلا أنه يعتمد على قيمة $_SERVER['HTTP_REFERER'] التي يتم إرسالها من المستعرض، والتي قد تكون غير موثوقة في بعض الحالات. وربما من الأفضل استخدام حلول قائمة على الجانب الخادم، مثل .htaccess، إذا كنت ترغب في تعزيز الأمان.
  3. من الأفضل قراءة المستندات الخاصة بمكتبة Three.js وهي متوفرة بالعربية أيضًا من خلال الرابط التالي: https://threejs.org/docs/#manual/ar/introduction/Installation حيث أنها ستوفر لك الطريقة السليمة لاستخدام المكتبة. وبخصوص الكود الخاص بك لاحظي أنه في السكريبت لم يتم استدعاء GLTFLoader و DRACOLoader بشكل صحيح في الكود الخاص بك. فأنت قمت باستدعاء المكتبة باسم THREE وبالتالي يجب استيراد الدوال المرادة منها. والصحيح هو تعريف المتغيرات GLTFLoader و DRACOLoader واستخدامها فيما بعد، على النحو التالي: const loader = new THREE.GLTFLoader(); const draco = new THREE.DRACOLoader(); draco.setDecoderPath('/examples/jsm/libs/draco/'); loader.setDRACOLoader(draco); حاولي استخدام الكود التالي حيث قمت باستيراد المكتبات عن طريق CDN وكتابة HTML والسكريبت في صفحة واحدة لمعرفة أين يقع الخطأ بالضبط: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="https://cdn.jsdelivr.net/npm/three@0.131.2/build/three.js"></script> <script src="https://cdn.jsdelivr.net/npm/three@0.131.2/examples/js/loaders/GLTFLoader.js"></script> <title>3D</title> <style> body { margin: 0; overflow: hidden; } </style> </head> <body> <script> const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.z = 5; const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); const loader = new THREE.GLTFLoader(); loader.load( 'path/to/your/home.glb', function (gltf) { scene.add(gltf.scene); }, undefined, function (error) { console.error('An error occurred while loading the model:', error); } ); function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); } animate(); </script> </body> </html>
  4. حاول استخدام التعديل التالي على ملف .htaccess: RewriteEngine On RewriteBase / RewriteRule ^egypt/([^/]+)/?$ egypt.php?id=$1 [QSA,L] RewriteRule ^egypt/([^/]+)/([^/]+)/?$ egypt.php?id=$1&id1=$2 [QSA,L] RewriteRule ^egypt/([^/]+)/([^/]+)/([^/]+)/?$ egypt.php?id=$1&id1=$2&id3=$3 [QSA,L] وذلك التعديل يتيح لك استخدام الروابط التي تحددها بصورة صحيحة. الـRewriteRule الأولى تتعامل مع الرابط الأساسي، وتحوّل www.example.com/egypt/cairo/ إلى www.example.com/egypt.php?id=cairo. الـRewriteRule الثانية تتعامل مع رابط يحتوي على متغيرين، وتحوّل www.example.com/egypt/cairo/almaadi/ إلى www.example.com/egypt.php?id=cairo&id1=almaadi. أما الـRewriteRule الثالثة، فتتعامل مع رابط يحتوي على ثلاثة متغيرات، وتحوّل www.example.com/egypt/cairo/almaadi/rent/ إلى www.example.com/egypt.php?id=cairo&id1=almaadi&id3=rent. ويرجى التأكد من أنك قمت بتمكين مود Rewrite في خادم الويب الذي تستخدمه وأن ملف .htaccess موجود في المسار الصحيح. كما يجب أن يكون لديك صلاحيات القراءة والكتابة على ملف .htaccess.
  5. في البداية يجب تجنب الدخول لمشاهدة الدورات من أكثر من 3 أجهزة فذلك قد يعرض حسابك للإيقاف المؤقت لتفقد السبب. وتستطيع مشاهدة الدورة كما يحلو لك في الوقت الذي تريده وإنهائها في الميعاد الذي تريده، ودخول الإمتحان في الوقت الذي تريده والتطبيق بالطريقة التي تريدها لكن يجب تسليم نفس المشاريع الخاصة بالدورة، وتستطيع دخول الإمتحان بعد إنهاء 4 مسارات من أي دورة ولكن لا أنصحك بذلك وأنهي الدورة بالكامل. مما يعني أنه تستطيع مشاهدة الدورة على التابلت، والتطبيق على اللاب توب، وعند الحاجة إلى نسخ كود مثلاً أو تنزيل المرفقات الخاصة بالمسار أو الدرس، فتستطيع القيام بذلك عن طريق اللاب توب. وأيضًا لا تنسى رفع المشروع الخاص بك على GitHub.
  6. السبب وراء وضع الـ abstract class في بداية قائمة الـ states في فلاتر BLOC هو لتوفير واجهة مشتركة لجميع حالات الحالة (states) المحتملة التي يمكن أن يتبعها Cubit أو Bloc. وباستخدام الـ abstract class ، تستطيع تعريف مجموعة محددة من الحالات الأساسية التي قد يعتمدها Cubit أو Bloc دون الحاجة إلى إعادة تعريف الأساليب الأساسية في كل مرة. والكود في الصورة، تم به تعريف NewestBooksState كـ abstract class وتنفيذها من قبل عدة حالات محددة، مثل NewestBooksInitial و NewestBooksLoading و NewestBooksFailure و NewestBooksSuccess. ومن خلال استخدام abstract class، تستطيع توحيد النهج وتطبيق المنطق المشترك بين حالات الحالة المختلفة، مثل توفير قائمة الممتلكات (props) المشتركة وأي أساليب أخرى ترغب في تعريفها لجميع حالات الحالة. أيضًا بوجود abstract class، بإمكانك استخدام المتغيرات من نوع NewestBooksState للإشارة إلى أي حالة من حالات الحالة، مما يسهل تحديد الحالة الحالية واتخاذ الإجراءات المناسبة في الـ Cubit أو Bloc الخاص بك. وسأقدم لك مثالًا يوضح كيفية استخدام الفئة المجردة (abstract class) في فلاتر BLOC، ولنفترض أن لدينا Cubit لإدارة حالة قائمة أحدث الكتب في تطبيق مكتبة. فتستطيع كتابة الفئات المختلفة على النحو التالي: import 'package:equatable/equatable.dart'; abstract class NewestBooksState extends Equatable { const NewestBooksState(); @override List<Object> get props => []; } class NewestBooksInitial extends NewestBooksState {} class NewestBooksLoading extends NewestBooksState {} class NewestBooksFailure extends NewestBooksState { final String error; const NewestBooksFailure(this.error); @override List<Object> get props => [error]; } class NewestBooksSuccess extends NewestBooksState { final List<Book> books; const NewestBooksSuccess(this.books); @override List<Object> get props => [books]; } هنا لدينا الفئة المجردة NewestBooksState التي تم تنفيذها من قبل عدة حالات محددة. وNewestBooksState يحتوي على المنطق المشترك لجميع حالات الحالة، والذي يشمل تنفيذ props لإعطاء معرف فريد لكل حالة، وذلك لتمكين المقارنة والتعامل مع التغييرات في الحالة بشكل فعال. NewestBooksInitial: حالة البداية، ويمثل الحالة الأولية للقائمة. NewestBooksLoading: حالة التحميل، ويشير إلى أن القائمة تحمل البيانات حاليًا. NewestBooksFailure: حالة الفشل، ويشير إلى حدوث خطأ أثناء جلب البيانات، ويحتوي على رسالة الخطأ المحددة. NewestBooksSuccess: حالة النجاح، ويشير إلى أن البيانات تم جلبها بنجاح، ويحتوي على قائمة الكتب الأحدث. وباستخدام الفئة المجردة NewestBooksState وحالاتها المحددة، يمكنك توحيد المنطق وإدارة حالة قائمة الكتب في Cubit الخاص بك، وإصدار حالة معينة باستخدام emit داخل Cubit بناءً على المنطق والأحداث التي تحدث في التطبيق.
  7. في دورة تطوير التطبيقات باستخدام لغة JavaScript ستتعلم التالي: الأسس البرمجية السليمة للغة JavaScript الإضافات الحديثة في نسخة ES6 من اللغة تطوير تطبيقات الخادم باستخدام بيئة Node.js أساسيات مكتبة React.js وبناء تطبيق ملاحظات باستخدامها أساسيات مكتبة React Native و Expo تطوير تطبيق جوال للوصل بين الأطباء والمرضى بالاعتماد على React Native التعرف على التطبيقات التي تتطلب اتصالًا مستمرًا بين المتصفح والخادم بناء تطبيق محادثة يشبه تطبيق WhatsApp إنشاء تطبيق أسئلة وأجوبة ونقاشات مع تصيير من جهة الخادم Server-side Rendering عبر إطار العمل Next.js بناء واجهات أمامية باستخدام React.js مع مكتبة Material-UI إنشاء تطبيقات سطح مكتب باستخدام JavaScript باستخدام إطار العمل Electron.js بناء تطبيق جوال لشبكة تواصل اجتماعي باستخدام إطار العمل Ionic ومكتبة React.js وبخصوص React فستقوم بتعلم الأساسيات عن طريق بناء تطبيق ملاحظات Todo list، وبعد ذلك ستقوم ببناء مشروع كبير عبارة عن تطبيق محادثة يشبه تطبيق WhatsApp فالواجهة الأمامية ستكون عن طريق React والواجهة الخلفية بواسطة node.js. وأيضًا ستقوم ببناء نسخة لتطبيق الهاتف عن طريق React Native. وفي المشروع ستتعلم كيف يمكن إدارة عملية تسجيل الدخول وإنشاء الحسابات والتواصل عن طريق WebSockets والحماية والتحقق وقواعد البيانات و API. وأيضًا ستقوم ببناء تطبيق أسئلة وأجوبة باستخدام Next.js وهو إطار مطلوب بشكل أساسي في سوق العمل بالنسبة لوظيفة React developer وأيضًا بتعلمك node.js ستصبح مطور Full stack مما يحسن فرصتك في البداية وستحصل على معرض أعمال قوي من خلال تلك المشاريع ولكن يجب التطبيق بمفردك بعد مشاهدة المدرب.
  8. لا يوجد دورة متخصصة في الأمن السيبراني ضمن أكاديمية حسوب، ولكن ستحتاج إلى دورة علوم الحاسوب حيث أنها أساسية إذا اردت التخصص في ذلك المجال. وإليك نقاش حول تلك الدورة: وبخصوص المسار الخاص بالأمن السيبراني فأنصحك بقراءة النقاش التالي حيث تم الإجابة بالتفصيل:
  9. قبل الدخول في مجال يجب إجراء بحث وافي، وتفقد المنافسين وحجم الزيارات وإمكانية المنافسة، وهل هناك مساحة لتوفير شيء جديد أو أفضل مما هو موجود؟ فإذا كانت الإجابة لا، فعليك البحث عن مجال آخر لموقعك، ويجب عليك إختيار مجال تستطيع أن تضيف فيه بخبراتك ومعلوماتك بحيث تتميز عن الباقيين وإلا سيصبح موقعك مثلهم أو أقل. ومجال مثل الكوبونات والخصومات بحاجة إلى بناء روابط خلفية قوية على كلمات صعبة المنافسة، وأيضًا بعض الإعلانات، بالإضافة إلى إنشاء محتوى للتسويق لتلك الكوبونات، مثل مراجعات عن أشهر المنتجات والماركات ثم إضافة كوبونات الخصم داخل المقالة، أو كتابة مقالات لكل عنوان لديك في الموقع بدلاً من كتابة سطرين لكل عنوان وهو أمر غير جيد بالنسبة لجوجل. وأيضًا لا تقم بحشو الكلمات في أسفل الموقع بل قم بكتابة نص يوضح طبيعة عمل الموقع وبه كلمة مفتاحية تستهدفها. وبأي حال من الأحوال لا تنتظر أي عائد سواء من قناة يوتيوب أو موقع إلا بعد مرور سنة، وخلال تلك السنة يجب بذل الجهد وتوفير محتوى قوي وأيضًا محتوي يتطلب أن يقوم الزائر بالضغط على الرابط وتصفحه لا أن يشاهد المعلومة من الخارج حيث سيظهرها جوجل له. وتستطيع بيع الموقع، والتوجه لإنشاء موقع آخر لكتابة المقالات في مجال تحبه وبه عائد جيد من خلال حجم مقبول من الزيارات، ويجب إنشاء محتوى قوي وليس محتوى سريع فهو لن يفيدك على المدى الطويل فبعد أسبوع سيختفي ذلك المحتوى من جوجل في حال وجود محتوى أفضل منه. وأنصحك بإيجاد وظيفة، والعمل على الموقع بشكل جانبي لحين استقراره وتحقيق عائد منه.
  10. ببساطة إذا كانت مواصفات حاسوبك غير كافية بالنسبة للمشروع الذي تعمل عليه، فتستطيع استخدام Google Colab، حيث المستخدمين المجانيين على Google Colab يحصلون على وصول مجاني إلى وحدات المعالجة الرسومية (GPU) ووحدات المعالجة الرسومية المتخصصة (TPU) لمدة تصل إلى 12 ساعة. ويتم توفير GPU runtime في Colab مع المواصفات التالية: وحدة المعالجة المركزية Intel Xeon @2.20 جيجاهرتز، 13 جيجابايت من ذاكرة الوصول العشوائي (RAM)، وحدة Tesla K80 للتسريع، و 12 جيجابايت من ذاكرة الوصول العشوائي GDDR5 VRAM. أما TPU runtime في Colab، فهو يتألف من وحدة المعالجة المركزية Intel Xeon @2.30 جيجاهرتز، 13 جيجابايت من ذاكرة الوصول العشوائي (RAM)، وحدة TPU سحابية بقوة حوسبة تصل إلى 180 تيرافلوبس. باختصار، يعني ذلك أنه يمكنك الاستفادة من قدرات GPU و TPU القوية لتنفيذ العمليات الحسابية المكثفة والمتقدمة في مجال التعلم الآلي وتحليل البيانات. وتتوفر موارد الحاسوب هذه مجانًا لمدة تصل إلى 12 ساعة، والتي يمكن استخدامها لتشغيل النماذج وتدريبها وتحليل البيانات بشكل فعال. بعد انتهاء الـ 12 ساعة على Google Colab، يتم إلغاء جلسة العمل الحالية ويتعين عليك إعادة تشغيلها، ويعني ذلك أن أي عمل غير محفوظ سيتم فقده، بما في ذلك البيانات والنماذج والتعديلات التي تم إجراؤها خلال الجلسة. وتستطيع يمكنك حفظ النتائج والملفات الضرورية قبل انتهاء الجلسة الحالية، عن طريق حفظ البيانات في حساب Google Drive الخاص بك أو تنزيلها إلى جهاز الكمبيوتر الشخصي الخاص بك. أيضًا استخدام الوظيفة "Save a copy in Drive" في Google Colab لحفظ الدفتر الحالي في Google Drive قبل انتهاء الوقت المحدد. معالجات m مصممة بواسطة Apple ومبنية على تقنية ARM، تتميز بأداء مذهل وكفاءة عالية في استخدام الطاقة. فمع معالج M2، ستستفيد من أداء محسّن وتسارع لعمليات التعلم الآلي، ويحتوي المعالج M2 على مجموعة متنوعة من وحدات المعالجة المركزية ووحدات المعالجة الرسومية المتكاملة، مما يسمح بتنفيذ عمليات التعلم العميق بسرعة وكفاءة. بالإضافة إلى ذلك، يشتمل على وحدة Neural Engine التي توفر قدرات تسريع متقدمة لعمليات التعلم الآلي. ومن المهم أيضًا أن تنظر إلى الذاكرة والتخزين في الجهاز، حيث توفر MacBook الجديدة غالبًا ذواكر وتخزين فائقة السرعة، مما يساعد على تسريع عمليات التعلم الآلي وتحليل البيانات. ولكن إذا كان لديك كرت شاشة قوي على نظام الويندوز فستحصل على أداء مشابه حيث أن العامل الأساسي هو كرت الشاشة، يأتي بعده المعالج ثم الرامات.
  11. حاول إضافة شرط داخل دالة changeCurrency لتغيير رمز العملة بناءً على اللغة المحددة، وتستطيع استخدام دالة app()->getLocale() للحصول على اللغة المحددة في Laravel. public function changeCurrency(Request $request) { $currencyCode = $request->currency_code; $language = app()->getLocale(); // تحديد رمز العملة بناءً على اللغة $currencySymbol = ($language == 'ar') ? 'دج' : 'DA'; $currency = Currency::where('code', $currencyCode)->first(); $request->session()->put('currency_code', $currencyCode); $request->session()->put('currency_symbol', $currencySymbol); $request->session()->put('currency_exchange_rate', $currency->exchange_rate); flash(translate('Currency changed to ') . $currency->name)->success(); } قمت بإضافة شرط للتحقق من اللغة المحددة. إذا كانت اللغة 'ar' (عربي)، وسيتم تعيين رمز العملة إلى 'دج'، وإلا سيتم تعيينه إلى 'DA'. احفظ التعديلات واختبر الموقع عند تغيير لغة الموقع للتحقق من تغيير رمز العملة بناءً على اللغة المحددة، ويرجى ملاحظة أنه قد تحتاج إلى إعادة تشغيل الخادم أو مسح ذاكرة التخزين المؤقت لتطبيق السكريبت (مثل مسح مجلد bootstrap/cache في Laravel) لتطبيق التغييرات يدويًا أو من خلال الأمر: php artisan optimize:clear
  12. الأسئلة الإمتحانية لا يتم الإجابة بشكل مباشر عليها، ويمكن إرشادك لطريقة الحل، وإذا تم توفير كود اذكر المشكلة التي تواجهك به لمساعدتك. بخصوص التمرين الأول سأجيب عليه لتوضيح طريقة الحل، وسأترك باقي الأسئلة لك لحلها: عليك بإنشاء متغيرين لتتبع الأعداد التي ستتم طباعتها، واحد للترتيب التصاعدي والآخر للترتيب التنازلي. تهيئة المتغيرين بقيمة صفر. استخدمي حلقة التكرار (حلقة for أو حلقة while) للتكرار من 1 إلى 100. داخل الحلقة، قم بإجراء الخطوات التالية: افحصي إذا كان المتغير الخاص بالترتيب التصاعدي أقل من 100، فإذا كان الشرط صحيحًا، قومي بطباعة القيمة وزيادة المتغير بواحد. افحصي إذا كان المتغير الخاص بالترتيب التنازلي أقل من 100، وإذا كان الشرط صحيحًا، قومي بزيادة المتغير بواحد. بعد انتهاء الحلقة، ستكون قد تم طباعة الأعداد المطلوبة. ومخطط التدفق سأتركه لك لحله، وهنا شرح ومصادر ستفيدك: وبخصوص خريطة التدفق فقومي بقراءة التالي: وأيضًا بعض المصادر المفيدة. https://wiki.hsoub.com/Algorithms
  13. أرجو منك إرفاق الكود في سؤالك من خلال الضغط على الكود <> عند كتابة السؤال. ومن الصعب تحديد بالضبط ما هي المشكلة التي تواجهها في رمز React الذي قدمته، حيث يجب تحديد ما الذي تريد فعله وشرحه بالضبط، وأيضًا توفير مجلد المشروع إن أمكن. ومع ذلك، هناك بعض الأخطاء الواضحة في الرمز التي يمكن تصحيحها: في البداية، يجب أن تتأكد من تشغيل كود React داخل وحدة الإرسال الصحيحة. يجب أن يتم وضع الكود داخل مكون React مثل class App extends React.Component ويتم استدعائه في ReactDOM.render(). وأيضًا عليك باستخدام className بحرف c صغير وليس كبير C والدالة map التي تستخدمها لتكرار this.state.users غير صحيحة، حيث يجب أن تكون هناك قوسين مستديرين بعد map لتحديد الدالة المراد تنفيذها على كل عنصر.، مثلاً: this.state.users.map((ele) => { // code }). أيضًا يجب أن يكون لديك عناصر users صحيحة داخل المصفوفة. حالياً، لديك قوسين مفتوحين بدون أي شيء داخلهما قبل العنصر الأول وبعد العنصر الثاني في المصفوفة يجب أن تتأكد من تنسيق البيانات بشكل صحيح.
  14. 1- ستجد خيار باسم setup & configurations اضغط عليه ومنه اختر Languages. 2- قم بإختيار اللغة الإفتراضية للموقع من الأعلى ثم اضغط save. 3- ستجد خيار باسم add new language قم بالضغط عليه واكتب ar وسيظهر لك العربية اخترها ثم احفظ من خلال save 4- بجانب اللغة العربية قم بتفعيل الزر الخاص بتحويل تنسيق الموقع من اليمين إلى اليسار RTL. 5- ستجد بجانب اللغة العربية زر الترجمة بجانب علامة القلم اضغط عليه ثم بترجمة العملة كما تريد.
  15. تجاهلي الرسالة التالية: packages are looking for funding run `npm fund` for details حيث أنه يخبرك بتنفيذ الأمر npm fund، وسيتم عرض قائمة بجميع الوحدات والحزم التي قمت بتثبيتها والتي تم إنشاؤها بواسطة شركات أو منظمات تحتاج إلى دعم مالي لمشاريعها في مجال تقنية المعلومات. وستظهر لك قائمة بصفحات الويب التي يمكنك من خلالها إرسال الأموال لهذه الشركات أو المنظمات. وتستطيعي تعطيل ظهور تلك الرسالة عن طريق الأمر التالي: npm config set fund false --global وبخصوص parcel من الأفضل استخدام parcel بشكل محلي داخل المشروع وليس global، لذلك عليك بحذف النسخة التي قمتي بتحميلها بشكل global بالأمر التالي: npm un parcel -g بعد ذلك تثبيت الحزمة بالشكل التالي: npm install --save-dev parcel وتستطيعي تشغيل المشروع من خلال الأمر التالي مباشرًة: npx parcel src/index.html ولاحظي أنه يتم تشغيل الملف index.html في مجلد src. والأفضل استخدام السكريبت في ملف package.json بالشكل التالي: { "name": "my-project", "source": "src/index.html", "scripts": { "start": "parcel", "build": "parcel build" }, "devDependencies": { "parcel": "latest" } } ولاحظي أنه في source تم تحديد الملف الرئيسي للمشروع، وتستطيعي تشغيل المشروع الآن عن طريق الأمر npm start. وتستطيعي قراءة الشرح الخاص بـ Parcel من المستند الرسمي: https://parceljs.org/getting-started/webapp/
  16. عندما يتعلق الأمر بتخزين البيانات في قاعدة البيانات، هناك عدة طرق يمكن اتباعها، وسأقدم لك بعض الأفكار العامة حول كيفية تخزين البيانات التي تم توضيحها في استفسارك. بالنسبة للخانات الثابتة، بإمكانك اتخاذ قرار بين تخزين القيم المباشرة أو استخدام المعرفات والربط ببيانات أخرى. ولنستخدم مثالك "اسم الكتاب: أبيض وأسود". تستطيع أن تقرر تخزين النص "أبيض وأسود" مباشرة كقيمة في قاعدة البيانات وجعلها حقلًا في الجدول الخاص بالمواضيع، أو باستطاعتك إنشاء جدول منفصل للكتب وتخزين تفاصيل الكتب فيه، مع إضافة حقل يحمل معرف الكتاب في جدول المواضيع للإشارة إلى الكتاب المحدد. بالنسبة للغات المتعددة، فإذا كنت ترغب في دعم العربية والإنجليزية في التطبيق، تستطيع تخزين اسم الكتاب باللغتين في قاعدة البيانات. مثلاً، إضافة حقول مثل "اسم الكتاب بالعربية" و "اسم الكتاب بالإنجليزية"، وبمثل هذا النهج، يمكن للتطبيق استخدام النص المناسب بناءً على لغة تفضيل المستخدم أو اختياراته. وتذكر أن الطريقة الأفضل والصحيحة لتخزين البيانات تعتمد على احتياجات تطبيقك. ,إذا كنت تستخدم قاعدة بيانات Firebase، فإنها توفر لك بنية لتخزين البيانات تعتمد على مفهوم الوثائق والمجموعات في قاعدة البيانات. حيث أن في Firebase، يتم تخزين البيانات في وثائق (Documents)، وهي هيكل تخزين قابل للتنفيذ يتكون من مجموعة من الحقول وقيمها. يمكنك أن تنظر إلى الوثيقة كإدخال مستقل في قاعدة البيانات. وبناءً على ما تم شرحه، تستطيع تخزين الخانات الثابتة (مثل نوع المشاركة ونوع الكتاب ورقم الإصدار) كحقول في وثيقة الموضوع، وتخزين القيم المباشرة لهذه الخانات مباشرة في حقولها بقاعدة البيانات. مثلاً، إنشاء وثيقة لكل موضوع وتتضمن حقولًا مثل "عنوان الموضوع" و "نوع المشاركة" و "نوع الكتاب" و "رقم الإصدار"، وتخزين القيم المدخلة من المستخدمين في هذه الحقول. في Firebase، بإمكانك أيضًا تخزين قيم متعددة لنفس الحقل باستخدام مفهوم المصفوفات. وبالتالي، تستطيع تخزين أسماء الكتب بالعربية والإنجليزية في نفس الحقل، مثل ["أبيض وأسود", "Black and White"].
  17. الدالة الأولى: function increase(num) { num++; console.log(num); } تستقبل معامل واحد يُسمى num، وداخل الدالة، يتم استخدام المعامل المؤقت ++ لزيادة قيمة num بمقدار واحد. ثم طباعة القيمة المحدثة لـ num، في هذه الحالة، سيتم زيادة قيمة num من 1 إلى 2، وبعد ذلك ستُطبع القيمة 2. الدالة الثانية: function increase(number) { return number++; } الدالة أيضًا تستقبل معامل واحد يُسمى number، داخل الدالة، يستخدم المعامل المؤقت ++ لزيادة قيمة number بمقدار واحد. ومع ذلك، يتم إرجاع القيمة الأصلية لـ number (قبل زيادتها)، حيث ستُرجع الدالة قيمة 1 (القيمة الأصلية لـ number) وليس القيمة المحدثة (2). ولكن ما السبب؟ السبب يكمن في المعامل ++، فهو معامل يُستخدم لزيادة قيمة متغير بمقدار واحد. وهناك فرق بين استخدام ++ قبل اسم المتغير وبعده. فإذا استخدمته قبل اسم المتغير ويعرف باسم pre-increment: ++num ستتم زيادة قيمة المتغير ومن ثم يتم استخدام القيمة المحدثة. أما إذا استخدمته بعد اسم المتغير، ويعرف باسم post-increment: num++، فسيتم استخدام القيمة الأصلية للمتغير ومن ثم يتم زيادة قيمته. مثال لتوضيح الاستخدام: let num = 1; console.log(++num); // ستُطبع القيمة 2 (تم زيادة القيمة قبل الاستخدام) console.log(num++); // ستُطبع القيمة 2 (ت بمعنى أنك لو أردت أن يتم إرجاع قيمة 2 من الدالة الثانية وليس 1 عليك تعديل المعامل ليصبح قبل المتغير بالشكل التالي: function increase(number) { return ++number; }
  18. للاستفادة من التاريخ الهجري في لغة JavaScript، تستطيع استخدام المكتبة المعروفة باسم "Hijri.js"، وهي مكتبة JavaScript مفتوحة المصدر تتيح لك التعامل مع التواريخ الهجرية، يمكنك تنزيل المكتبة من مستودع GitHub الخاص بها. ولتثبيت المكتبة باستخدام مدير حزم npm، استخدم الأمر التالي: npm install hijri.js بعد تثبيت المكتبة، قم باستيرادها في مشروعك بالشكل التالي: const HijriDate = require('hijri.js'); // مثال على كيفية إنشاء تاريخ هجري جديد const hijriDate = new HijriDate(); console.log(hijriDate.toString()); // يقوم بطباعة التاريخ الهجري الحالي // يمكنك أيضًا تعيين تاريخ هجري محدد const specificDate = new HijriDate(1443, 9, 1); console.log(specificDate.toString()); // يقوم بطباعة التاريخ الهجري المحدد بالنسبة لـ React Native، لا يوجد مكتبة محددة للتعامل مع التواريخ الهجرية في React Native بشكل مدمج، لذلك عليك بالإعتماد على مكتبة جافاسكريبت مثل Hijri.js المذكورة أعلاه في مشروع React Native بنفس الطريقة الموضحة في الأمثلة. وهناك أيضًا مكتبة moment-hijri لعرض التاريخ الهجري وهي إضافة لمكتبة moment.js الخاصة بالتواريخ. وهنا شرح استخدامها، وهي بسيطة: https://github.com/xsoh/moment-hijri استخدام التاريخ الهجري في جافا سكريبت بدون مكتبة سأشرح لك كيف يمكن القيام بذلك، لكن من الأسهل استخدام مكتبة جاهزة، وسنعتمد على الدوال والعمليات المتاحة في JavaScript للتعامل مع التواريخ وبعض الحسابات الرياضية يدويًا. // تحويل التاريخ الميلادي إلى هجري function convertToHijri(gregorianDate) { const dateObj = new Date(gregorianDate); const year = dateObj.getFullYear(); const month = dateObj.getMonth() + 1; const day = dateObj.getDate(); // الحساب المبسط للتاريخ الهجري const jd = Math.floor((11 * year + 3) / 30) + 354 * year + 30 * month - Math.floor((month - 1) / 2) + day + 1948440 - 385; const yearHijri = Math.floor((11 * jd + 3) / 30); const monthHijri = Math.floor(12 * (jd - Math.floor((30 * yearHijri + 3) / 11)) + 6) / 354; const dayHijri = jd - Math.floor((30 * yearHijri + 3 * monthHijri - 1) / 11); return { year: yearHijri, month: monthHijri, day: dayHijri }; } // مثال لاستخدام الدالة const gregorianDate = '2023-05-22'; const hijriDate = convertToHijri(gregorianDate); console.log(hijriDate); تحتوي الدالة convertToHijri في المثال أعلاه على خوارزمية بسيطة لتحويل التاريخ الميلادي إلى التاريخ الهجري. تستخدم الدالة Date المدمجة في JavaScript لإنشاء كائن تاريخ ميلادي من التاريخ الذي تريد تحويله. ثم يتم استخدام المعادلات المحسوبة يدويًا لتحويل التاريخ الميلادي إلى التاريخ الهجري. وإرجاع النتيجة في شكل كائن يحتوي على السنة الهجرية والشهر واليوم. ويرجى ملاحظة أن هذا مثال بسيط ولا يعتبر دقيقًا بنسبة 100٪ بالنسبة للحسابات المعقدة للتاريخ الهجري، حيث يوجد عدد من القواعد والتعقيدات في حساب التاريخ الهجري التقليدي التي لم تتم مراعاتها في هذا المثال. لذلك من الأفضل استخدام مكتبة خارجية إذا كنت تحتاج إلى دقة ومرونة أكثر في التعامل مع التاريخ الهجري.
  19. إذا قمت بإنشاء مشروع واحد في Firebase للاشتراك في الخدمة المشتركة بين تطبيق المستخدم وتطبيق مقدم الخدمة، فسوق يؤدي إلى تلقي الإشعارات في كلا التطبيقين، وهذا يحدث لأن المشروع في Firebase يعتبر كمنطقة مشتركة لجميع التطبيقات المرتبطة به. فإذا كنت ترغب في تجنب تلقي الإشعارات في كلا التطبيقين، تستطيع اتخاذ إحدى الخيارات التالية: 1- إنشاء مشروع مستقل في Firebase لكل تطبيق (تطبيق المستخدم وتطبيق مقدم الخدمة)، مما سيفصل الإشعارات والتكوينات بين التطبيقين ويحد من تكرار الإشعارات. 2- استخدام العلامات Tags في Firebase لتمييز المستخدمين ومقدمي الخدمة وإرسال الإشعارات بناءً على العلامات المحددة، عن طريق تعيين علامات مختلفة لكل تطبيق واستخدامها في عمليات إرسال الإشعارات لتحديد المستلم المناسب. بمعنى في تطبيق المستخدم: عند تسجيل المستخدم في التطبيق، يتم تعيين علامة مثل "user_app" للمستخدم باستخدام دالة setUserProperty في Firebase. عند إرسال الإشعارات إلى مستخدمي التطبيق، قم بتحديد العلامة "user_app" كجزء من المستخدمين المستهدفين. في تطبيق مقدم الخدمة: عند تسجيل مقدم الخدمة في التطبيق، يتم تعيين علامة مثل "provider_app" لمقدم الخدمة باستخدام دالة setUserProperty في Firebase. عند إرسال الإشعارات إلى مقدمي الخدمة، قم بتحديد العلامة "provider_app" كجزء من المستخدمين المستهدفين. عمومًا، من الأفضل تصميم تطبيق Firebase بشكل منفصل لكل تطبيق، خاصة إذا كانت التطبيقات مستقلة تمامًا ولها متطلبات واحتياجات مختلفة.
  20. برمجة الروبوتات وتعلم الآلة هما مفاهيم مترابطة ولكن لهما اختلافات واضحةK إليك الفرق بينهما: برمجة الروبوتات: تشير إلى عملية كتابة الشفرات البرمجية التي تتحكم في سلوك الروبوتات. تركز على تحديد تعليمات محددة للروبوت لأداء مهام محددة. يتم برمجة الروبوت بواسطة المطور بشكل صريح، حيث يتم تحديد كل خطوة يجب على الروبوت اتخاذها. تعلم الآلة: يشير إلى قدرة النظم الآلية على استخلاص الأنماط والمعرفة من البيانات وتحسين أداءها تلقائيًا عن طريق الخبرة. يهدف إلى تطوير نماذج أو خوارزميات قادرة على التعلم من البيانات واتخاذ قرارات بناءً على هذا التعلم. يعتمد على تدريب النماذج باستخدام مجموعة واسعة من البيانات لتحقيق القدرة على التعلم والتكيف. ببساطة، برمجة الروبوتات تتعامل بشكل مباشر مع برمجة سلوك الروبوت وتوجيهه بتعليمات محددة، في حين أن تعلم الآلة يركز على تطوير نماذج أو خوارزميات تستفيد من البيانات والتجارب لتعلم وتحسين أداء النظام الآلي.
  21. تستطيع استخدام كلمة مرور مختلفة لكل قاعدة بيانات على حدى في MongoDB، وذلك بتكرار الخطوات التي أشار إليك بها محمد، لإنشاء مستخدم وتعيين كلمة مرور جديدة لكل قاعدة بيانات ترغب في استخدامها. أيضًا بإمكانك استخدام نفس المستخدم وكلمة المرور لعدة قواعد بيانات إذا كنت ترغب في ذلك. وسأشرح لك الكود: use اسم_قاعدة_البيانات db.createUser({ user: "اسم_المستخدم", pwd: "كلمة_المرور", roles: [ { role: "اسم_الدور", db: "اسم_قاعدة_البيانات" } ] }) 1- use اسم_قاعدة_البيانات: هذا الأمر يستخدم للتبديل إلى قاعدة البيانات التي ترغب في إنشاء مستخدم لها، واستبدل "اسم_قاعدة_البيانات" بالاسم الذي ترغب في استخدامه لقاعدة البيانات. 2- db.createUser(): يستخدم لإنشاء مستخدم جديد وتعيين كلمة مرور له. وعليك باستبدال "اسم_المستخدم" و"كلمة_المرور" بالقيم الخاصة بالمستخدم الذي ترغب في إنشائه. 3- roles: [ { role: "اسم_الدور", db: "اسم_قاعدة_البيانات" } ]: في هذا الجزء من الكود، يتم تحديد الدور (role) الذي يحدد الصلاحيات والامتيازات التي يمتلكها المستخدم. وعليك استبدال "اسم_الدور" بدور MongoDB المناسب لاحتياجاتك، مثلاً استخدام "readWrite" لمنح المستخدم صلاحيات القراءة والكتابة. وإليك بعض الأمثلة للأدوار الشائعة ووصفها: read: يمنح المستخدم صلاحية القراءة فقط للمجموعات والمجموعات الفرعية. readWrite: يمنح المستخدم صلاحية القراءة والكتابة للمجموعات والمجموعات الفرعية. dbAdmin: يمنح المستخدم صلاحية الإدارة لقاعدة البيانات المحددة، بما في ذلك إنشاء وحذف المجموعات وإجراء العمليات الإدارية الأخرى. userAdmin: يمنح المستخدم صلاحية إدارة المستخدمين في قاعدة البيانات، مثل إنشاء وحذف المستخدمين وتعديل الأذونات. dbOwner: يمنح المستخدم جميع صلاحيات القراءة والكتابة والإدارة في قاعدة البيانات، بما في ذلك إنشاء وحذف المجموعات وإجراء العمليات الإدارية وإدارة المستخدمين. وتذكر أنه يمكنك تعيين عدة أدوار للمستخدم عن طريق تكرار الكود المذكور في قوسين مربعين ضمن roles. مثال: roles: [ { role: "readWrite", db: "اسم_قاعدة_البيانات" }, { role: "dbAdmin", db: "اسم_قاعدة_البيانات" } ] ويجب الإنتباه إلى أنه عليك إمتلاك صلاحية كافية لإنشاء المستخدم وتعيين كلمة المرور، حيث ستحتاج إلى تشغيل هذه الأوامر باستخدام مستخدم يحمل صلاحية الإدارة (مثل المستخدم الأولي "admin") لكي تتمكن من إنشاء المستخدم بنجاح.
  22. مساحة عرض الصورة على موقع مستقل هي 128 في 128 بكسل والنسخة المصغرة منها هي 36 في 36 بكسل، أي للحصول على أفضل عرض للصورة، من الأفضل رفع صورة مربعة بأي مقاس على الموقع. ويجب أن تكون الصورة إحترافية وليست صورة سيلفي أو ليست صورة شخصية لك. أما إذا كنت تتسائل من أجل تصميم حجم مشابه لها في تصميمك، فعليك بإختيار الحجم المناسب الذي يتناسب مع باقي مكونات التصميم، وأيضًا عرض الصورة بشكل واضح.
  23. عند وضع Column داخل SingleChildScrollView، بإمكان لـ Column أن يتمدد بشكل لا محدود في الاتجاه الرأسي داخل SingleChildScrollView. وبالتالي، لن يتم رمي استثناء عند تمرير المحتوى. وهناك بعض التناقض في الشروط التي يتم فيها رمي استثناء عند استخدام Expanded داخل SingleChildScrollView. في الواقع، إذا وضعت Expanded داخل SingleChildScrollView، ستحدث استثناءات لأن Expanded يحاول التمدد لاستغلال المساحة المتبقية، في حين يسمح SingleChildScrollView بالتمدد غير المحدود. ففي حالة وضع Column بداخل SingleChildScrollView، يتم تطبيق تمدد Column على العناصر الموجودة داخلها فقط، وليس على الـ SingleChildScrollView نفسه. ببساطة، SingleChildScrollView يعمل على إظهار المحتوى الذي يتجاوز المساحة المتاحة على الشاشة بواسطة التمرير، في حين يتمدد Column فقط بناءً على المحتوى الذي يحتويه. وإليك مثالًا بسيطًا يوضح استخدام Column داخل SingleChildScrollView بدون حدوث استثناء: import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Example', home: Scaffold( appBar: AppBar( title: Text('Example'), ), body: SingleChildScrollView( child: Column( children: [ Container( height: 200, // ارتفاع ثابت للمثال color: Colors.blue, ), Container( height: 200, color: Colors.green, ), Container( height: 200, color: Colors.red, ), // يمكنك إضافة المزيد من العناصر هنا ], ), ), ), ); } } تم وضع Column داخل SingleChildScrollView وتحديد ارتفاع ثابت لكل عنصر في Column، بغض النظر عن عدد العناصر، ستظهر جميعها داخل SingleChildScrollView ويمكن التمرير لعرض المحتوى الكامل.
  24. كلاهما مطلوبان في سوق العمل، والأمر يتوقف على سوق العمل لديك، عليك بالبحث على مواقع مثل LinkedIn وIndeed وبعيد أو أي موقع آخر شهير للوظائف في بلدك، فمثلاً في مصر يوجد Wuzzuf. ولا تأخذ كلامي بنسبة 100% على أنه الصحيح عليك بالبحث لتتخذ قرارك، وعامًة في العالم العربي المطلوب بكثرة بالنسبة للمبتدأين في مجال البرمجة هو PHP وإطار لارافيل وورد بريس، وأيضًا إطار .NET المعتمد على لغة C# وغالبًا يتم استخدام Angular بالنسبة للواجهة الأمامية عند استخدام .NET وذلك ليس شرط بالطبع حيث تستطيع إنشاء واجهة أمامية بدون Angular. أما الـ MERN Stack فستجد فرص بلا شك، لكن عادة ما يتم طلب خبرة سنة حيث أن React وNode.js يعتمدوا على الكثير من المكتبات الأخرى لذلك أنت بحاجة إلى خبرة حقيقية من خلال بناء مشاريع ومواجهة الأخطاء الشائعة والتعود عليها، حتى يتم قبولك في وظيفة. وهناك بعض الشركات التي توفر فرص عمل بخبرة بسيطة أي لا يشترط خبرة سنة في حال كنت مطور MERN أي مطور Full stack، وبالطبع يجب وجود مشاريع حقيقية وليست مجرد نماذج بسيطة بمعرض أعمالك باي حال من الأحوال. وهناك دورة تطوير التطبيقات باستخدام لغة JavaScript توفر لك التطبيق على مشاريع لوضعها بمعرض أعمالك، وهي خاصة بمسار MERN. وأيضًا هناك دورة تطوير تطبيقات الويب باستخدام لغة PHP وإطار لارافيل وورد بريس. أي أنه عليك بالبحث عن متطلبات الوظائف الخاصة بمستوى Junior أو Entry level أو خبرة سنة وقرر على ذلك الأساس. فإذا كان لديك الوقت ولست على عجلة للحصول على وظيفة، فقم بتعلم مسار MERN، والعكس صحيح بالنسبة PHP. وإذا أردت التخصص في الواجهة الأمامية فقط فعليك بتعلم Angular إذا أردت التوظيف بشكل سريع، والعكس صحيح بالنسبة لـ React. أما إذا أردت العمل على مواقع العمل الحر فيجب عليك أن تكون مطور Full stack، وبالنسبة للمواقع العربية فعليك تعلم PHP ولارافيل وورد بريس. وأكرر، يجب أن تقوم بالبحث عن الوظائف المتاحة في سوق العمل المحلي لديك وتقرر على هذا الأساس.
  25. عند وضع Column widget داخل SingleChildScrollView، فإنه لا يحدث استثناء (exception) لأن SingleChildScrollView يسمح بالتمدد (expansion) غير محدود في الاتجاه الرأسي، بغض النظر عن عدد عناصر Column. SingleChildScrollView يعمل على إظهار كل عناصر القائمة بطريقة يمكن التمرير (scrollable) حتى وإن كانت أكثر من المساحة المتاحة على الشاشة. وعندما يكون لديك عنصر واحد فقط في SingleChildScrollView، ويمكن لـ Column أن يتمدد (expand) بشكل غير محدود في الاتجاه الرأسي ليتناسب مع حجم محتواه. أما بالنسبة لاستخدام Expanded داخل SingleChildScrollView، فالمشكلة تكمن في أن Expanded يحاول التمدد بنسبة معينة مقابل المساحة المتبقية، ولكن بسبب وجود SingleChildScrollView الذي يسمح بالتمدد غير المحدود، يكون هناك صراع بين الـ Expanded و SingleChildScrollView في التمدد، وهذا ما يتسبب في رمي استثناء (exception). وإذا أردت استخدام Column داخل SingleChildScrollView وتجنب الاستثناء، تستطيع استخدام واجهة ConstrainedBox لتحديد حجم ثابت لـ Column، بحيث لا يحاول التمدد بشكل غير مناسب. مثال للتوضيح: import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Example', home: Scaffold( appBar: AppBar( title: Text('Example'), ), body: SingleChildScrollView( child: ConstrainedBox( constraints: BoxConstraints(), // قيود خالية، لا تحدد أي قيود على الحجم child: Column( children: [ // عناصر القائمة هنا // يمكنك وضع قائمة طويلة هنا دون حدوث استثناء ], ), ), ), ), ); } }
×
×
  • أضف...