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

Hikmat Jaafer

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

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

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

كل منشورات العضو Hikmat Jaafer

  1. مرحباً 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 وقمت بتعيين العرض والارتفاع وفقاً لاحتياجاتك. يمكنك تعديل الأبعاد وفقاً للحجم الذي تريده.
  2. نعم , سيتم تحميل جزء من الكود في 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..." أثناء التحميل. وهكذا سيتم تحميل المكونات اللازمة فقط عندما يتم طلبها بواسطة المستخدم، مما يؤدي إلى تحسين أداء التطبيق وتوفير الوقت والموارد كما تريد .
  3. دورة علوم الحاسوب مقدمة للمبتدئين في مجال البرمجة , فهي تعرف الطالب بمكونات الحاسوب و أنظمة التشغيل بالإضافة إلى أساسيات البرمجة و التفكير المنطقي. و أي شخص يريد الدخول في مجال البرمجة فعليه البدء بهذه الدورة, أما إذا كان المتعلم يمتلك خبرة سابقة في مجال البرمجة فيمكنه تخطي هذه الدورة. و بعد أن ينهي المتعلم دورة علوم الحاسوب يستطيع اختيار المجال الذي يريد التخصص فيه و يشترك بالدورة التي تناسب هذا المجال. لذلك عليك الاستمرار بمتابعة هذه الدورة اذا كنت جديد في مجال البرمجة . وبعد الانتهاء منها تستطيع التخصص في ألعاب الأندرويد. يمكنك الاشتراك بدورة تطوير التطبيقات باستخدام لغة javascript هذه الدورة تتعلم أساسيات مكتبة react native و javascript و تقوم بتطوير تطبيق جوال, و لكن بعد أن تتعلم الأساسيات عليك أن تتوسع أكثر بالاجتهاد الشخصي لتستطيع تطوير الألعاب , هناك عدة مكتبات وإطارات تعمل مع React Native وتساعد في تطوير الألعاب بشكل فعال بعض هذه المكتبات تتضمن: Expo-THREE React Native Game Engine React Native Unity Integration React Native SpriteKit
  4. مرحباً أحمد , نعم يمكنك فعل ذلك من خلال تصميم عدة 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.
  5. قمت بالإطلاع على الكود لديك في عربة التسوق , يوجد أخطاء في 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 تستخدمه بهذا الشكل . بعد تطبيق هذه الملاحظات سوف تجد أن التطبيق يعمل بشكل صحيح كم في الصورة المرفقة يوجد أخطاء أخرى في الأزرار والتصميم وغيره من الأخطاء , ما أنصحك به قم بحل الأخطاء البرمجية أولاً ثم قم بحل أخطاء التصميم .
  6. هذه بعض الحلول لبعض الثغرات : الوصول غير المصرح به (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):التحقق من صحة البيانات المدخلة لضمان أنها تتوافق مع الصيغة المتوقعة.
  7. وعليكم السلام , أهلاً أحمد جيد جداً , هل يمكنك إرفاق الكود لديك بعد إجراء التعديلات ؟ ويمكنك إرفاقه كالتالي ( لكي يصبح حجم الملف المضغوط صغير ) : أولاً قم بتحديد المجلدات واستثناء مجلد node_modules . بعد ذلك يمكنك ضغط المجلد باستخدام اي برنامج ضغط , كما قمت من قبل . أو يمكنك رفع الكود على مستودع GitLab أو GitHub ومشاركته معنا باستخدام رابط المشاركة .
  8. مرحباً 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 .
  9. بما أن مشروع الأدمن يعمل على المسار 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
  10. مرحباً حارث , التدريب على التصاميم يمكن أن يكون عملية شاملة تشمل عدة خطوات ومراحل، سأوضح لك بعض الطرق المشهورة لتدريب التصميم مع أمثلة: التعليم الأكاديمي : هذا النوع من التدريب يشمل الحصول على درجة جامعية في التصميم الجرافيكي أو التصميم الصناعي. يتضمن البرنامج دراسة النظريات والمفاهيم الأساسية للتصميم بالإضافة إلى التطبيق العملي. على سبيل المثال، جامعات مثل Rhode Island School of Design وRoyal College of Art توفر برامج متميزة في هذا المجال. الدورات التدريبية عبر الإنترنت: هناك عدة منصات تقدم دورات تدريبية في مجالات التصميم المختلفة، بما في ذلك تصميم الجرافيك وتجربة المستخدم والتصميم الصناعي. هذه الدورات غالبا ما تكون مدعومة بمشاريع عملية لتطبيق المفاهيم المدرسة. المشاركة في ورش العمل والمسابقات : أيضاً هناك نوع أخر مثل ورش العمل والمسابقات , إذ توفر ورش العمل والمسابقات فرصة رائعة لتعلم المهارات الجديدة وتطبيقها على مشاريع فعلية. يمكنك البحث عن ورش العمل والمسابقات المحلية أو الدولية في مجال التصميم والمشاركة فيها. على سبيل المثال، يمكنك الانضمام إلى مسابقة تصميم شعار لشركة محلية . التعلم من الخبراء والمجتمعات المحترفة: يمكنك الانضمام إلى مجتمعات مثل Dribbble وBehance والمشاركة في المناقشات ومشاهدة أعمال الآخرين والتعلم منهم. كما يمكنك حضور المؤتمرات وورش العمل التي تقدمها الشركات المتخصصة في التصميم للتعرف على أحدث التطورات في المجال. تعتبر هذه الطرق الشائعة للتدريب على التصميم وجذب العميل من خلال تصميم جيد , ويمكنك الدمج بين عدة أنواع تعلم . وبشكل عام , يمكنك حضور دورات تدريبية , ومن ثم المشاركة في المسابقات , وبعدها رؤية المجتمعات المتعلقة بالتصميم وحضور الإجتماعات الخاصة بهذا الموضوع .
  11. التركيز في مشروع واحد يعطيك فرصة في التعمق وفهم التفاصيل بصورة أفضل , و هذا الشيء يفيدك في تطوير مهاراتك, لكن إذا بقي تركيزك على مشروع واحد لن تكتسب مهارات جديدة فيمابعد , و لذلك عليك المساهمة في مشاريع أخرى متنوعة لكي تكسب مهارات جديدة, ولكن عليك أن تدير و تنظم طريقة تعلمك لكي لاتضيع وقتك بدون فائدة و لكي تحصل على أفضل نتيجة , ولكن من الخطأ أن تبدأ بالمساهمة بعدة مشاريع معا لأن ذلك سيجعلك تتشتت و لن تستطيع التركيز في أي شيء , لذلك بداية عليك أن تساهم في مشروع واحد و عندما تصبح متمكن فيه و تفهم تفاصيله و تمتلك الخبرات اللازمة لإنجاز هذا المشروع تنتقل للبدء بالمساهمة في مشروع آخر مختلف لكي تكسب مهارات وخبرات جديدة . و عليك أن تختار المشاريع التي تتناسب مع اهتماماتك ومهاراتك الحالية، وتقدم لك الفرصة للتعلم والنمو.
  12. مرحباً أحمد , من الجيد أنك تقوم ببناء موقع متجر إلكتروني والمتابعة في البحث عن الاخطاء والحلول , لكن نحن نريد نقوم بكسبك الخبرة اللازمة للدخول في سوق العمل إن كان في الشركات أو من خلال العمل 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 , وعندما تواجهك أي سؤال يمكنك طرحه هنا .
  13. مرحباً , يمكنك استخدام extension خاصة بكل لغة ( حسب اللغة التي تريدها ) , مثلاً اكستنشن خاصة ب Bootstrap , او في react , او python . و يمكنك أيضاً استخدام ذكاء اصطناعي داخل VS Code , أحدهم يسمى BITO , هو يقدم عدة ميزات , منها المساعدة في الإكمال التلقائي للكتابة . ويمكنك أيضاً استخدام هذه extension لمساعدتك في توليد الأكواد أو فهم أي كود من خلال المحادثة كما في الصورة المرفقة
  14. مرحباً , إن كنت تقصد كيف يمكن كتابة كود لعملية حسابية في SQL Server من خلال حقلين من جدول , فهذا مثال بسيط كيف يمكنك فعل ذلك : SELECT Number1, Number2, (Number1 + Number2) AS Sum FROM TableName; هذا الاستعلام يختار الأعداد من الجدول، ثم يقوم بإجراء الجمع بين العددين ويظهر الناتج في عمود يسمى Sum . مثال أخر أكثر تعقيداً : SELECT Product, SUM(Quantity) AS TotalQuantity, SUM(UnitPrice * Quantity) AS TotalSalesAmount, CASE WHEN SUM(Quantity) > 200 THEN SUM(UnitPrice * Quantity) * 0.9 ELSE SUM(UnitPrice * Quantity) END AS TotalSalesWithDiscount FROM Sales GROUP BY Product HAVING SUM(Quantity) > 100; أفترضت وجود جدول يسمى Sales ويحتوي على الأعمدة التالية: Product و Quantity و UnitPrice , و نريد حساب إجمالي مبلغ المبيعات لكل منتج حيث تكون الكمية المباعة أكبر من 100، ونريد أيضا تضمين خصم بنسبة 10٪ للمنتجات التي تزيد كميتها المباعة عن 200. فلاحظ أنه في البداية قمت باختيار اسم المنتج و إجمالي الكمية المباعة (TotalQuantity) وإجمالي مبلغ المبيعات (TotalSalesAmount) وإجمالي مبلغ المبيعات مع تطبيق الخصم (TotalSalesWithDiscount). أيضاً لاحظ أنني قمت باستخدام دالة SUM لحساب الكمية الإجمالية المباعة وإجمالي مبلغ المبيعات لكل منتج. واستخدمت CASE لتطبيق خصم بنسبة 10٪ على إجمالي مبلغ المبيعات للمنتجات التي يزيد مجموع الكميات المباعة من 200. وأقوم بتجميع النتائج حسب عمود Product. كما استخدمت الشرط HAVING لتصفية المنتجات التي تكون كميتها المباعة أقل من 100.
  15. مرحباً, أنت تقوم ببعض العمليات على profile slice , ولكن ما تواجهه أنه البيانات تزول عندما تقوم بتحديث الصفحة أو إعادة تحميلها بأي شكل , هذا بالطبع سيحدث كون redux toolkit بشكل إفتراضي لا تقوم بحفظ البيانات بشكل دائم في المتصفح ( local storage او اي شكل اخر ) , وإنما تقوم بحفظها بشكل مؤقت في المتصفح وعند إعادة تحميل الصفحة سوف تزول جميع العمليات التي قمت بها . لحل هذه المشكلة ( او ما تبحث عنه ) يمكنك فعلها بطريقتين: إما باستخدام localStorage , وتقوم بحفظ وتعديل البيانات في localStorage كلما قمت بتعديل redux toolkit slice , وفي كل مرة تقوم بتشغيل التطبيق تفحص إذا كان هناك بيانات مخزنة في localStorage فتقوم بإستردادها ل profile slice , يمكنك تعديل الكود لديك كالشكل التالي : أولاً قم بتحديث create profile action لتتضمن تخزين البيانات في local storage : export function createProfile(newProfile) { return async(dispatch, getState) => { try { dispatch(profileActions.setLoading()) const { data } = await axios.post(PROFILE_URL, newProfile, { headers: { 'x-auth-token': getState().auth.user.token } }) dispatch(profileActions.setProfile(data)) dispatch(profileActions.setIsProfileCreated()) localStorage.setItem('profileData', JSON.stringify(data)); setTimeout( () => dispatch(profileActions.clearIsProfileCreated()), 2000 ); } catch (error) { const err = error.response?.data.msg if (err) { dispatch(alertActions.createAlert(err)); dispatch(alertActions.clearAlert(err)); } const errors = error.response.data.errors errors?.forEach((err) => { dispatch(alertActions.createAlert(err.msg)); dispatch(alertActions.clearAlert(err.id)); }); dispatch(profileActions.clearLoading()) } } } ثانياً ، عند بدء التطبيق، يمكنك التحقق مما إذا كانت هناك بيانات مخزنة واستخدامها , يمكنك وضع الكود التالي في layout او component الصفحة الاساسية . useEffect(() => { const storedData = localStorage.getItem('profileData'); if (storedData) { dispatch(profileActions.setProfile(JSON.parse(storedData))); } }, []); الطريقة الثانية , تسمى هذه التقنية redux persist , هي مكتبة تساعد في حفظ حالة التطبيق في تطبيقات React Redux عبر عملية التخزين المحلي. تسمح هذه المكتبة بالاحتفاظ بحالة Redux الحالية حتى بعد إعادة تحميل الصفحة أو إعادة فتح التطبيق عن طريق استخدام localStorage أو AsyncStorage في React Native.
  16. وعليكم السلام , أرجو طرح الأسئلة الخاصة بالدورات ضمن التعليقات تحت فيديو الدورة , وطرح الأسئلة العامة هنا , بالنسبة لسؤالك , عندما قمت بطباعة getModel بدلاً من setModel ، فقد قمت بطباعة قيمة النموذج المخزنة في الكائن $vehicle. هذا يعني أنك تحصل على قيمة النموذج المحددة للسيارة، وليس قيمة مختلفة تم تعيينها. ودوال set تستخدم لتعيين قيمة جديدة لخاصية في الكائن، بينما تستخدم دوال get لاسترجاع القيمة الموجودة. بالنسبة لماذا قام المدرب باستخدام الشرط if في دالة setYear , فهنا قمنا باستخدامها للتحقق مما إذا كان العام المراد تعيينه هو قيمة صحيحة (integer) أم لا , وفي حال إذا كان العام ليس صحيحًا، سيتم توليد (Exception) يشير إلى أن العام غير صالح. بالنسبة لسؤالك حول تعقيد التعامل مع التطبيقات, يعتمد تعقيد التعامل مع التطبيقات على العديد من العوامل، بما في ذلك حجم التطبيق وتعقيده . ففي التطبيقات الكبيرة والمعقدة، قد تتطلب عمليات الإدخال والإخراج والتحقق من البيانات والتعامل مع الأخطاء والاستثناءات الكثير من الشفافية والتحكم الدقيق. ويمكن أن تكون التطبيقات المعقدة أكثر تعقيدًا في تصميمها وتطويرها، ولكن يمكن التعامل مع هذا الأمر من خلال تنظيم الشيفرة واستخدام مفاهيم البرمجة المناسبة مثل الإنكابسوليشن والتحقق من الأخطاء والاستثناءات. لا تقلق , مع التقدم في التعلم سوف تجدي هذه الخطوات سهلة جداً بالتوفيق
  17. وعليكم السلام , يجب عليك وضع كلاس acc-title كالتالي : .acc-title { display: flex; align-items: center; justify-content: center; } ليتم وضع جميع العناصر بداخله على سوية واحدة , مثلاً ممكن أن يكون الكود كاملاً كالتالي ( يمكنك إرفاق كامل الكود مع styles الخاصة به للتوضيح أكثر ) : <!DOCTYPE html> <html> <head> <title></title> <style> .acc-tool1 { background-color: red; text-align: center; } .acc-title { display: flex; align-items: center; justify-content: center; } .author-img2 { margin-right: 10px; border-radius: 100px; } .acc-title i { margin-left: 10px; padding: 40px } </style> </head> <body> <div class="acc-tool1"> <div class="acc-item"> <div onclick="window.open('https://youtube.com/@khatar_official');"> <div class="acc-title"> <div class="author-img2 radius100px"><img height="40" width="40" src="https://blogger.googleusercontent.com/img/a/AVvXsEjcnncOCeoSzijTrJkMRofEAfTbPHxMi4YRNkhAP8PUuNIvaoKioud-tHURilzjXIi6heOrfmVKMhJ71oqD5p3hPsKq9kwmuHsoyxS1B9dequ8talfFmNV62QMWbLHtpF2b45moj_hB1EOAf1RMqtx2zzXRWGbMeQC5EXsFAtRmi76Uv55cxGazBhhoKDaI=s1600" /> </div> اشترك في قناتي علي اليوتيوب <i class="fab fa-download" style="color: white; font-size: 18px; font-weight: 400;"></i> </div> </div> </div> </div> </body> </html>
  18. وعليكم السلام , دورة حياة أي مشروع برمجي تكون تحت مسمى SDLC وهي مجموعة مراحل يجب تنفيذها لبناء المشروع البرمجي بشكل صحيح ( كما تم شرحه من قبل المدرب عدنان ) , أما عن تنفيذ هذه المراحل فيكمن من خلال نماذج دورة حياة تطوير المشروع البرمجي SDLC Models ويوجد عدة نماذج لدورة حياة تطوير البرمجيات , كل نموذج له مزاياه وعيوبه ويناسب أنواع مختلفة من المشاريع والظروف : نموذج الشلال (Waterfall Model) هذا النموذج يتبع نهجا خطيا حيث تتقدم المراحل بتتابع وتباعد ثابت. تبدأ المراحل بالتحليل والتصميم وتنتهي بالتطوير والاختبار ثم التشغيل. يناسب المشاريع ذات المتطلبات الثابتة والمعروفة بوضوح. نموذج التطوير التسلسلي (Sequential Development Model) يشبه نموذج الشلال إلى حد كبير ولكن يسمح بتكرار المراحل إذا لزم الأمر. يمكن تكرار مرحلة معينة بعد اكتشاف العيوب في المراحل اللاحقة. يمكن أن يكون أكثر مرونة من نموذج الشلال ولكن قد يزيد من تكاليف التطوير النموذج التكراري (Iterative Model) ينشئ التطبيق في سلسلة من الدورات القصيرة المتكررة. كل دورة تنتهي بتسليم تطبيق يضيف ميزات جديدة أو يصحح العيوب ( أي يتم تسليم version ثم version اخر ). يسمح بتغيير المتطلبات والتحسين المستمر. النموذج التكراري التكيفي (Adaptive Iterative Model) يجمع بين النموذج التكراري والتحديد التكيفي. يتم تحديد الخطوات القادمة بناءً على الاستجابة للتغييرات التي تطرأ خلال التطوير. النموذج الرشيق (Agile Model) يركز على التعاون بين فريق التطوير والعملاء. يسمح بالتطوير التدريجي والتحسين المستمر عبر الدورات القصيرة والمرنة. يناسب المشاريع التي تتطلب استجابة سريعة للتغييرات والتكيف مع المتطلبات المتغيرة. يوجد عدة نماذج أخرى , لكن هذه أشهرها ولا أظن أنك ستحتاج إلى غيرها إلا في بعض الحالات النادرة. أيضاً غالب المشاريع في الشركات تعتمد على Agile Model , فهي مناسبة لمشاريع كبيرة وربما تكون متطلباتها غير واضحة بشكل كامل في البداية. وتعتبر الأكثر شهرة ( هذا لا يعني أنه لا يوجد مشاريع تعتمد على النماذج الأخرى ).
  19. لا يمكن استخدام ChatGPT 4 مجاناً من خلال مواقع معينة أو تطبيقات. في الوقت الحالي، تعتمد استخدامات تقنية models مثل ChatGPT على خدمات " المعالجة السحابية أو البنية التحتية المدارة بمقابل " من قبل شركات مثل Open AI وهي غالبا ما تكون مدفوعة. لذلك يمكن الوصول إلى ChatGPT 4 واستخدامه عن طريق منصات Open AI المدفوعة التي تقدمها الشركة. قد تكون هناك بعض النسخ التجريبية المجانية المتاحة للتجربة، ولكن الاستخدام المستمر والشامل يتطلب عادة الاشتراك أو دفع رسوم مقابل الخدمة. بالنسبة لي , أستخدم في بعض الأحيان ChatGPT 3.5 , هو نوعا ما مساعد في بعض الأمور ,كما أجد كثير من الأحيان إجابات خاطئة منه ( وبشكل كبير ) , يمكنك الاعتماد عليه فقط في بعض الأحيان للحصول على سرعة اجابة , اما كمعلومات دقيقة وربما يكون من الصعب إيجادها عبر الانترنت , فستجد بعض الاخطاء من إجاباته.
  20. وعليكم السلام, أهلاً أيمن, بالطبع في بداية الطريق ستجد صعوبة في إيجاد أول عمل , أو أول فريق عمل , أو أول شركة توظيف . فهذا حال دخول أي مجال عمل في الحياة . لكن إليك بعض النصائح أو الطرق ستساعدك جيداً في الحصول على أول عمل : أولاً أنت طالب في أكاديمية حسوب , وبالتالي لك الحق أن تتواصل مع مركز المساعدة ليقومون بمساعدتك بشكل شخصي من قبل فريق بعيد لبناء سيرتك الذاتية وفي الحصول على أول عمل خلال مدة أقل من 6 أشهر , وفي حال عدم حصولك على عمل خلال 6 أشهر لك الحق بطلب إرجاع كامل المبلغ . أما عن نصيحة شخصية وعملية من قبلي , فيجب عليك فهم السوق بشكل جيد لتتمكن من الحصول على اول عمل من خلال مواقع العمل الحرة ( مثل مستقل ) . مثلاً صحيح أنه أغلب أصحاب المشاريع يقومون بطلب الخبرة من المستقل , لكن ربما يكون بإمكانك أنت القيام بنفس العمل لكن بسعر أقل , وبالتأكيد سيقبل ذلك بعض أصحاب العمل ( تذكر أن جميع المستقلين قاموا أبضاً بالبدء من الصفر ) . قمت بتوضيح كيف يمكنك العمل في مستقل في هذا التعليق , يمكنك قراءته والاستفادة منه : بالنسبة للعمل ضمن فريق , ما أجده هو أنه يمكنك التقديم ( ربما برسائل خاصة ) إلى بعض الشركات ك junior او كتدريب , وهذا سيمنحك معرفة كاملة كيف يكون العمل ضمن الشركات وفرق العمل , وبالتأكيد ستحصل على خبرة عالية من العمل ضمن فريق .
  21. يمكنك استخدام مفهوم (List Comprehension) في بايثون لاستخراج الأرقام الزوجية أو الفردية. وهي طريقة بسيطة وشائعة في بايثون, مثلاً : لاستخراج الأرقام الزوجية: numbers = [1, 4, 2, 3, 7, 12, 16, 23, 24] even_numbers = [num for num in numbers if num % 2 == 0] print(even_numbers) فتكون النتيجة : [4, 2, 12, 16, 24] ولاستخراج الأرقام الفردية: numbers = [1, 4, 2, 3, 7, 12, 16, 23, 24] odd_numbers = [num for num in numbers if num % 2 != 0] print(odd_numbers) النتيجة: [1, 3, 7, 23] لاحظ في الامثلة السابقة قمت باستخدام التعبير [num for num in numbers if condition] حيث تكون num هي المتغير المؤقت لكل عنصر في القائمة numbers، وتكون condition هي الشرط الذي يحدد ما إذا كان يتم استبعاد العنصر أم لا. في حالتنا، يتم فحص العنصر إذا كان يمثل رقما زوجيا أو فرديا باستخدام عملية باقي القسمة %، ثم يتم إضافته إلى القائمة الجديدة (even_numbers أو odd_numbers) حسب الشرط المحدد.
  22. رسالة التعطيل التي تلقيتها تشير إلى أن حسابك لا يزال معطلاً بسبب عدم احتواء موقع الويب المدرج في ملفك الشخصي على المعلومات اللازمة لتحديد ما إذا كان نشاطك التجاري يتوافق مع سياسة الأعمال لـ WhatsApp. لذلك يجب عليك التأكد من أن ملفك الشخصي في منصة WhatsApp Business يحتوي على المعلومات الكاملة والدقيقة لنشاطك التجاري، بما في ذلك موقع الويب الخاص بك. يجب أن يتضمن الموقع معلومات الاتصال بك ووصفاً واضحاً للخدمات أو المنتجات التي تقدمها. بعد تحديث بيانات ملفك الشخصي, قد تحتاج إلى الاتصال بفريق دعم WhatsApp Business لإبلاغهم بمشكلتك وتوضيح المعلومات اللازمة وأنك قمت بتعديلها. أيضاً بعدها ربما يقوم فريق الدعم بطلب منك تقديم معلومات إضافية أو إجراء خطوات محددة لتفعيل الحساب مجدداً .
  23. وعليكم السلام , يوجد عدة أمور يمكن من خلالها جعل الفيديو سريع التشغيل , ربما التطبيق يستخدم تقنية تسمى تسريع السرعة (Speed Acceleration)، والتي تزيد من سرعة تشغيل المقاطع بمعدل أسرع من السرعة الأصلية للفيديو. هذا يعني أن الإطارات (frames) تعرض بشكل أسرع، مما يؤدي إلى سرعة عرض أعلى. أو ربما يقوم التطبيق بإعادة ترميز المقاطع بتنسيق مختلف أو باستخدام تقنيات ضغط أكثر فعالية، مما يقلل من حجم الملفات ويسمح بتشغيلها بسرعة أكبر. ولكن قد يؤدي ذلك أيضاً إلى تأثير على جودة الصورة. أو ربما يقوم التطبيق باستخدام تقنيات PreLoading , والتي يقوم بتحميل مقاطع الفيديو مسبقاً في الذاكرة مما يجعل يمكن تشغيلها بسلاسة وبسرعة عالية دون تقطيع .
  24. تظهر هذه المشكلة عندما يتم قفل ال navigation في تطبيق Flutter أثناء تحميل صفحة جديدة. يتم فحص هذا الشرط بواسطة الإصدارات الأحدث من Flutter للتحقق من عدم قفل ال navigation بشكل خاطئ. لذلك يجب عليك استخدام أحدث إصدار من Flutter والمكتبات المرتبطة به.يمكنك تحديث Flutter باستخدام الأمر التالي flutter upgrade او ربما تحتاج لمسح مجلد ("pubspec.lock") وإعادة تشغيل محاكي Flutter. يمكنك استخدام الأمر التالي : flutter clean إن لم تنجح أي من الحلول السابقة , فربما يوجد أخطاء في الكود الخاص بك , تحديداً ربما تقوم بقفل navigation او أنك تقوم بتحميل صفحة جديدة بشكل غير صحيح .
  25. وعليكم السلام, تأكيد أنك قمت بمحاولة حذف الأرقام وطرق الدفع بالطريقة الصحيحة وفقاً لإرشادات ميتا. إرشادات ميتا تختلف قليلا من تطبيق لأخر من ميتا ( facebook , whatsapp bussniess , whatsapp )و إذا كنت متأكدًا من أنك قمت بذلك ومع ذلك لا يزال الخطأ مستمراً، يمكنك محاولة الاتصال بدعم ميتا للحصول على المساعدة. للتواصل مع دعم ميتا, هناك طريقتين إما من التطبيق الذي تستخدمه أو من الموقع مباشرة . الطريقة الأولى من خلال التطبيق الذي تستخدمه , قد تختلف حسب التطبيق، لكن اتبع الخطوات التالية في التطبيق : افتح التطبيق أو الموقع الخاص بـتطبيق ميتا الذي تستخدمه لإدارة حافظتك الإعلانية. ابحث عن قائمة "المساعدة" أو "الدعم" داخل التطبيق أو الموقع. الطريقة الثانية , من الموقع الخاص بالتطبيق , ل whatsapp يكون هذا الرابط : https://faq.whatsapp.com/481188387305001
×
×
  • أضف...