-
المساهمات
19744 -
تاريخ الانضمام
-
تاريخ آخر زيارة
-
عدد الأيام التي تصدر بها
472
نوع المحتوى
ريادة الأعمال
البرمجة
التصميم
DevOps
التسويق والمبيعات
العمل الحر
البرامج والتطبيقات
آخر التحديثات
قصص نجاح
أسئلة وأجوبة
كتب
دورات
كل منشورات العضو Mustafa Suleiman
-
ليست تلك هي الطريقة الصحيحة والعملية، في الواقع العملي الأمر يتم إما عن طريق SaaS أي تطوير منصة لتوفير خدمة من خلال موقع بحيث ستقوم بتثبيت Odoo على خادم سحابي VPS والمتوفر من خلال DigitalOcean, Vultr, AWS وغيرهم، ثم يستخدم العملاء المنصة. والبديل الثاني هو الإعتماد على Docker وتلك تقنية تقوم بتغليف التطبيقات وتبعياتها في حاويات معزولة، بمعنى ستقوم بإنشاء ملف docker-compose.yml يحدد كيفية تشغيل Odoo و PostgreSQL معًا، والعميل سيحتاج فقط إلى تثبيت برنامج Docker Desktop ثم يقوم بتشغيل مشروعك بأمر واحد بسيط. والبيئة ستعمل بنفس الطريقة على أي جهاز مثبت عليه Docker، لكن ذلك يحتاج إلى خبرة تقنية من قبل العميل، لذا الحل الأول هو الأفضل. بخصوص طريقتك حاليًا يوجد مشكلتان، الخطأ الأول يحدث أولًا UnicodeEncodeError: 'charmap' codec can't encode character '\u010d'، فيفشل Odoo فى إنشاء جداول النظام ثم تُعاد المحاولة فيجد الجدول مفقودًا UnicodeEncodeError: 'charmap' codec can't encode character '\u010d'. بالتالي مجلد البيانات الذى أنشأته لـ PostgreSQL مهيَّأ بترميز WIN1252/CP1250 وهو الترميز الافتراضى على Windows في حال لم تُحدد شيئًا عند تهيئة قاعدة البيانات. وOdoo يحتوى على أسماء وحدات فيها الحرف č وغيره من Unicode، وتلك الأحرف لا يمكن تمثيلها داخل WIN1252، فيفشل الإدراج فى أول جدول ir_module_module. أي قاعدة البيانات نفسها ليست بترميز UTF-8، ولذلك تنهار عملية التهيئة، لذا عليك بالتالي: أوقف PostgreSQL إن كان يعمل من خلال تنفيذ الأمر التالي في CMD وليس powershell لكن قم بتشغيله بصلاحيات administrator: pg_ctl -D data stop -m fast ثم أعد تسمية المجلد data القديم أو احذفه بتفيذ التالي في المسار الذي به مجلد data في المشروع: ren data data_old -- ثم أنشئ مجلد data جديد مهيأ بترميز UTF-8 من خلال تنفيذ: set LANG=en_US.UTF-8 ثم: bin\initdb.exe ^ -D data ^ -U odoo ^ -A md5 -W odoo ^ -E UTF8 ^ --locale=C ثم عليك إنشاء قاعدة بيانات Odoo جديدة في Postgres. وللعلم لو أردت أتمتة الأمر لعميلك، فقم بتضمين أوامر initdb و pg_ctl في ملف start.bat بحيث ينفذ التهيئة تلقائيًّا إذا لم يجد PG_VERSION داخل data.
-
المقال جيد، وذكرت معظم العوامل الحقيقية المؤثرة في السعر، وما يحتاج إلى توضيح هو التفرقة بين تطوير Native (Swift/Kotlin) و Cross-platform (Flutter/React Native) وتأثير ذلك على التكلفة. أيضًا توضيح تكلفة الاستضافة، ورسوم المتاجر وهي 99 دولار لـ App Store سنوياً بجانب عمولة 15–30٪ على المبيعات وGooglePlay بتكلفة 25 مرة واحدة فقط. أيضًا توضيح رحلة تطوير التطبيق من الفكرة إلى الإطلاق، ولو استطعت قم بتطوير أداة لحساب تكلفة التطبيق من خلال بعض المُدخلات وذلك بشكل تقديري، فذلك من شأنه خلق Topic Cluster قوي ويُعزز Authority موقعك عند جوجل. وقم بوضع CTA ثابتاً في نهاية المقال، أي زر احصل على عرض سعر مجاني خلال 24 ساعة، مع تجربة استخدام أزرار واتساب أو نموذج الاتصال لتقليل العوائق أو التعقيدات التي تمنع المستخدم من إكمال الإجراء المطلوب. وأدخل كلمات LSI المذكورة على الأقل 4 إلى 5 مرات.
-
ستجد أسفل فيديو الدرس في نهاية الصفحة صندوق تعليقات كما هنا، أرجو طرح الأسئلة أسفل الدرس وليس هنا في قسم أسئلة البرمجة حيث نطرح الأسئلة العامة الغير متعلقة بمحتوى الدورة أو الدرس، وذلك لمساعدتك بشكل أفضل.
-
تحدث أخطاء في الكثير من الأحيان عند رفع المشروع على الاستضافة، فهل يعمل بشكل جيد محليًا؟ في حال ذلك قم بتوضيح الخطأ الذي يظهر لك على render
-
ستجد أسفل فيديو الدرس في نهاية الصفحة صندوق تعليقات كما هنا، أرجو طرح الأسئلة أسفل الدرس وليس هنا في قسم أسئلة البرمجة حيث نطرح الأسئلة العامة الغير متعلقة بمحتوى الدورة أو الدرس، وذلك لمساعدتك بشكل أفضل.
-
في مكون CartContext.jsx هنا: return savedCart ? JSON.parse(savedCart) : [] المشكلة في JSON.parse() حيث تقرأ قيمة ليست بصيغة JSON، وتلك القيمة تبدأ بحرف u، وغالبًا هي كلمة undefined. تفقد القيم التي في localStorage وسبب المشكلة في الحفظ، أو قم بمعالجة الأخطاء الواردة أثناء جلب تلك القيمة بإرجاع مصفوفة فارغة: const [cartItems, setCartItems] = useState(() => { try { const savedCart = localStorage.getItem('cartItems'); return savedCart ? JSON.parse(savedCart) : []; } catch (error) { console.error("Failed to parse cart items from localStorage", error); return []; } });
-
الفكرة ليس في إعادة تكرار مشاهدة الشرح، ذلك مضيعة للوقت والمجهود إلا في حال انقطعت لمدة طويلة أي شهر مثلاً، أيضًا لا أقصد دراسة يوم واحد ثم الإنقطاع 3 أيام، ففي البداية أنت بحاجة إلى الاستمرارية لتثبيت ما تعلمته، وليس عليك أنّ تتذكر الأساسيات دائمًا، بل أن تستطيع استعادتها سريعًا عندما تحتاجها. بالتالي عليك بالممارسة العملية لتثبيت ما تعلمته والوقوف على نقاط الضعف، فتعلم قيادة السيارة بشكل نظري مختلف تمامًا عن قيادتها، نفس الأمر بالنسبة لمشاهدة الدروس دونّ الممارسة العملية، والأفضل هو إعادة تنفيذ المشاريع العملية التي قمت بها من قبل لاسترجاع ما تعلمته وكذلك للمراجعة. وخصص النسبة الأكبر من وقتك للتطبيق العملي أي 50% في البداية وتزداد إلى 70% كلما تقدمت،بجانب تنفيذ تمارين أو مشاريع متدرجة الصعوبة، قم أيضًا بحل مساءل برمجية على منصة Codewars.
-
متاح نشر مقالات بالأكاديمية فقط وليس الكتب، حيث يتم إختيار موضوع الكتاب من قبل فريق التحرير المختص بذلك ويتم إعداد محتواه من قبلهم. ستجد تفصيل هنا:
-
في ملف main.js في دالة generateAPIResponse قمت هنا: div.classList.remove("load"); بحذف كلاس load بينما الكلاس الذي يجب حذفه هو loading لكونه يقوم بتطبيق تنسيق display: none أي إخفاء العنصر ولا يتم عرض المحادثة في الصفحة. div.classList.remove("loading");
-
المسار يحتوي على shoping%20store، والرمز %20 هو الترميز الخاص بالمسافة في الروابط، والعديد من أدوات البناء مثل Rollup لا تتعامل بشكل جيد مع المسافات في مسارات الملفات، لذا عليك إعادة تسمية المجلد لإزالة المسافة وضع مكانها شرطة سفلية _ أيضًا قم بحذف مجلد node_modules وملف package-lock.json ثم إعادة تثبيت الحزم: npm i ثم تحديث الحزم: npm update ولو استمر الخطأ قم بتجربة: npm cache clean --force npm i
-
يجب توضيح ما الذي تحاول تنفيذه للحصول على إجابة مفيدة، حاليًا ما هو المشروع وما هي المشكلة بالضبط، ولو فرت مجلد المشروع أو الملفات لكان أفضل
- 8 اجابة
-
- 1
-
-
Render ومثيلاتها Heroku، Vercel، Fly.io تستخدم Ephemeral Filesystem أي نظام ملفات مؤقت، بالتالي لا يمكن الكتابة على القرص بشكل دائم، الملفات المؤقتة تُحذف في أي وقت وليس لديك صلاحيات الكتابة في بعض المجلدات. أبسط حل هو استخدام Memory Storage في Multer حيث لا يتم إنشاء ملف على القرص إطلاقاً، بل يبقى كل شيء فى الـ RAM، يناسب أغلب الاستضافات المجانية. أو الرفع المباشر على cloudinary عن طريق Signed Upload.
- 1 جواب
-
- 1
-
-
لا حاجة إليها بالنسبة لك، وحتى في الشركات لا يتم استخدامها إلا في حالات محددة فقط بسبب التعقيد في عملية تطوير GraphQL، أي لو لديك واجهة خلفية سيتم استخدامها من قبل تطبيقات مختلفة أي منصات مختلفة Web و Mobile و Smart TV، وبيانات معقدة مع علاقات كثيرة، أيضًا فرق كبيرة تعمل على نفس الـ API، وعند الحاجة لتقليل استهلاك البيانات للموبايل مثلاً. لكن في أغلب الأحوال ما ستقوم به هو مشروع بسيط أو متوسط، وستحتاج إلى عمليات CRUD أساسية فقط.
-
الفكرة أنّ الروابط لها قواعد صارمة، وبعض الأحرف لها معنى خاص في الروابط، وتسمى الأحرف المحجوزة، ومنها: & : للفصل بين متغيرات متعددة في الرابط name=ali&city=riyadh? ? : لبدء جزء الاستعلام في الرابط. / : للفصل بين أجزاء المسار. # : للإشارة إلى جزء معين في الصفحة. (المسافة): غير مسموح بها في الروابط. +, :, @ وغيرها الكثير ستحدث مشكلة لو أردت إرسال نص يحتوي على أحد تلك الأحرف كقيمة في رابط كالتالي: https://test.com/search?q=C++ & Java المتصفح أو الخادم سيفسر الرابط بشكل خاطئ، وسيعتقد أن المتغير q قيمته C++ وأن Java هو متغير آخر بدون اسم، لأن حرف & يفصل بين المتغيرات. لذا encodeURIComponent تعمل على حل المشكلة عن طريق تحويل أو ترميز كل الأحرف الخاصة والغير آمنة إلى صيغة خاصة تسمى الترميز المئوي وهي تبدأ بعلامة % متبوعة برقمين ست عشريين. فنفس الرابط السابق سيبدوا كالتالي بعد الترميز: https://test.com/search?q=C%2B%2B%20%26%20Java وعندما يستقبل الخادم الرابط، سيعرف كيف يفك ترميز القيمة C%2B%2B%20%26%20Java ليعيدها إلى شكلها الأصلي C++ & Java، وبذلك يتم البحث بشكل صحيح.
-
في حال لديك وقت للدراسة، فالمسارات التالية بدورة علوم الحاسوب ستوفر لك أرض صلبة للوقوف عليها لدراسة دورة متقدمة مثل دورة الذكاء الاصطناعي: مدخل إلى علوم الحاسوب أساسيات البرمجة قواعد البيانات إلى عالم الويب البرمجة كائنية التوجه أساسيات هندسة البرمجيات إعادة تصميم البرمجيات Refactoring كذلك دراسة أساسيات الرياضيات اللازمة لتعلم الآلة: ثم دراسة دورة الذكاء الاصطناعي، وبعد الإنتهاء منها تستطيع العودة لدورة علوم الحاسوب ودراسة المسارات المتبقية: الخوارزميات وبنى المعطيات أنماط التصميم أنظمة التشغيل ونظام لينكس
- 6 اجابة
-
- 1
-
-
ستحتاج إلى الأساسيات وتستطيع دراسة الدورة بدونها لا مشكلة، لكن ستواجه صعوبة في استيعاب المفاهيم وما يحدث في الخلفية، لكن الأساسيات فقط، فالتعمق سيستغرق وقت وستفقد الحماس والدافع، والكثير من المفاهيم الرياضية لن تحتاجها فعليًا. لذا في البداية خصص شهر لدراسة الرياضيات، ودراسة التالي: ابدء بالجبر الخطي ودراسة المصفوفات، العمليات الأساسية، الضرب النقطي. ثم التفاضل ودراسة المشتقات، قاعدة السلسلة، التدرج. ثم الإحصاء ودراسة المتوسط، الانحراف المعياري، التوزيعات الأساسية بعد ذلك كلما واجهتك مفاهيم رياضية، توقف وادرسها. ستجد تفصيل هنا:
-
المطلوب هو المشاريع العملية الكاملة، بالإضافة إلى التطبيقات العملية كما في مسار التطبيقات العملية باستخدام بايثون، بينما التمارين البسيطة لشرح الأساسيات كالتي في قسم أساسيات بايثون فهي غير مطلوبة. بينما المشاريع العملية الكاملة مثل تطبيق إدارة المهام يتم رفعه على مستودع GitHub منفرد خاص به، وكذلك المشاريع العملية الخاصة بمسار تحليل البيانات. ومسار تعلم الآلة لا يوجد به مشروع عملي بشكل منفرد، بل تم تضمين ذلك في الشرح، بالتالي أرجو إنشاء مجلد للدورة، ثم بداخله إنشاء مجلد لكل مسار، وبداخل كل مجلد تضعين التطبيقات الخاصة بكل درس، ثم رفع ما بداخل المجلد الرئيسي للدورة بالكامل على مستودع GitHub خاص بك. وبالنسبة للإختبار، فسيتم سؤالك عن الـ 4 مسارات فقط، وإختبارك بهم، وآلية الإختبار كالتالي: إجراء محادثة صوتيّة لمدة 30 دقيقة يطرح المدرّب عليك أسئلة متعلّقة بالدورة والأمور التي نفّذتيها خلالها. يحدد لكِ المدرّب مشروعًا مرتبطًا بما قمتي به أثناء الدورة لتنفيذه خلال فترة محددة تتراوح بين أسبوع إلى أسبوعين. إجراء محادثة صوتيّة أخرى لمدّة 30 دقيقة يناقش بها مشروعك وما نفذتيه وتطرح أسئلة خلالها. إن سارت على جميع الخطوات السابقة بشكل صحيح، تحصلين على الشهادة أو يرشدك المدرّب لأماكن القصور ويطلب منك تداركها ثم التواصل معنا من جديد.
- 1 جواب
-
- 1
-
-
عذرًا على أي إنزعاج أثناء تواجدك بالأكاديمية، سيتم إيصال رسالتك للفريق المختص بالإختبارات والرد على رسالتك عما قريب، هناك ضغط فقط في الوقت الحالي لذا سيتم مراجعة مشروعك والعودة إليك لإخبارك بالنتيجة.
- 3 اجابة
-
- 1
-
-
الأمر بحاجة إلى تفصيل، لكن الصورة العامة هي عن طريق الـ API فهو حلقة الوصل بين الواجهة الأمامية والخلفية، وبين البرامج عامًة، ويتم إنشائه في الواجهة الخلفية Back-End من خلال لغة برمجة خاصة بالواجهة الخلفية مثل PHP أو C# مثلاً، وللعلم جافاسكريبت يتوفر لها بيئة تشغيل للواجهة الخلفية وهي Node.js ثم يتم استخدام مكتبة أو إطار للمساعدة في عملية التطوير مثل Express.js في حالة Node.js ويتم إنشاء نقاط نهاية أو عناوين API بشكل بسيط، وتحديد نوع الطلب الذي سيتم التعامل معه عند إرسال الطلب للـ API، والأنواع هي GET, POST, PUT, PATCH, DELETE. ثم كتابة منطق لمعالجة الطلب المُرسل من قبل الواجهة الأمامية ويتم إرسال رد للواجهة الأمامية، ستجد تفصيل هنا:
- 2 اجابة
-
- 1
-
-
ستجد أسفل فيديو الدرس في نهاية الصفحة صندوق تعليقات كما هنا، أرجو طرح الأسئلة أسفل الدرس وليس هنا في قسم أسئلة البرمجة حيث نطرح الأسئلة العامة الغير متعلقة بمحتوى الدورة أو الدرس، وذلك لمساعدتك بشكل أفضل.
-
تقصد نقل سطر الكود إلى مكان آخر؟ قم بالوقوف عند السطر الذي تريده بالضغط بمؤشر الفأرة أو التنقل بالأسهم، ثم اضغط على ALT + سهم للأعلى أو الأسفل لنقل السطر من مكانه
-
ستحتاج إلى دراسة المسارات التالية فقط إذا أردت أن تصبح مطور Front-End: أساسيات لغة JavaScript أساسيات React.js تطبيق دردشة يشبه WhatsApp أساسيات TypeScript إنشاء تطبيق أسئلة وأجوبة باستخدام Next.js تطبيق تعلم اللغات باستخدام Next.js وتقنيات الذكاء الاصطناعي تطبيقات الويب التقدمية PWA بجانب دراسة المسار الأول من دورة تطوير واجهات المستخدم، فهو متاح بشكل مجاني لك.
-
كلاهما يؤديان نفس الغرض، لكن من خلال خطاف useEffect فستعمل دالة fetch تلقائيًا عند تحميل المكون بسبب مصفوفة الإعتماديات الفارغة [] بالتالي سيتم جلب البيانات في البداية في حال ذلك كان مطلوب، لكن يتم استخدام then وهي طريقة قديمة، الأفضل async-await وأيضًا لا يتم معالجة الأخطاء من خلال try-catch أما دالة async/await فهي مستقلة ولا تعمل إلا عند استدعائها بنفسك مثلاً عند النقر على زر، وتتبع النهج الحديث في التعامل مع العمليات الغير متزامنة وتعتمد على try-catch. وللعلم هناك خطأ في الكود حيث هنا const data = res.json() فـ res.json() هي عملية غير متزامنة وتعيد Promise، يجب أن تنتظرها باستخدام await لتضمن الحصول على البيانات الفعلية وليس الـ Promise نفسه. والحل الأفضل هو الجمع بين الطريقتين كالتالي: const fetchCategories = async () => { try { const res = await fetch('api/categories'); const data = await res.json(); setCategories(data); return data; } catch (error) { console.error('خطأ في جلب التصنيفات:', error); setError(error.message); return null; } finally { setLoading(false); } }; useEffect(() => { setLoading(true); fetchCategories(); }, []);
-
ذلك خطاف من مكتبة react-router-dom يوفر معلومات كاملة عن الرابط الحالي الذي يتصفحه المستخدم داخل تطبيقك، وفي الواقع العملي ستستخدمه في معرفة الصفحات التي يزورها المستخدمون لإرسال تلك المعلومات إلى خدمات مثل Google Analytics مثلاً. import { useLocation } from 'react-router-dom'; import { useEffect } from 'react'; import { analytics } from './analytics-service'; function AnalyticsTracker() { const location = useLocation(); useEffect(() => { console.log(`المستخدم زار الصفحة: ${location.pathname}`); analytics.trackPageView(location.pathname + location.search); }, [location.pathname]); return null; } أو في حال لديك صفحة لعرض المنتجات، وتريد السماح للمستخدم بفلترة النتائج حسب الفئة والسعر، فستظهر تلك الفلاتر في الرابط، أي كالتالي (/products?category=laptops&sort=price_asc) وبناءًا عليها تقوم بطلب البيانات من قاعدة البيانات عن طريق توظيف location.search مع URLSearchParams المتوفر في المتصفح كـ API. import { useLocation } from 'react-router-dom'; import { useState, useEffect } from 'react'; function ProductListPage() { const location = useLocation(); const [products, setProducts] = useState([]); useEffect(() => { const queryParams = new URLSearchParams(location.search); const category = queryParams.get('category'); const sortBy = queryParams.get('sort'); console.log(`جلب المنتجات من الفئة: ${category}, مرتبة حسب: ${sortBy}`); // هنا تقوم بطلب البيانات من الـ API بناءً على هذه المتغيرات fetchAPI(`/api/products?category=${category}&sort=${sortBy}`) .then(data => setProducts(data)); }, [location.search]); / return ( <div> </div> ); } أو لو لديك صفحة قائمة المنتجات، وعندما يضغط المستخدم على منتج، تريد إرسال بيانات هذا المنتج (الاسم، السعر، الصورة) إلى صفحة تفاصيل المنتج لتظهر فوراً بينما يتم تحميل باقي التفاصيل، فستعتمد على location.state: import { Link } from 'react-router-dom'; function ProductItem({ product }) { return ( // نستخدم الخاصية "state" في مكون Link <Link to={`/products/${product.id}`} state={{ productData: product }}> <div> <h3>{product.name}</h3> <p>{product.price}</p> </div> </Link> ); } ثم استقبال البيانات في صفحة تفاصيل المنتج: import { useLocation, useParams } from 'react-router-dom'; import { useState, useEffect } from 'react'; function ProductDetailPage() { const location = useLocation(); const { id } = useParams(); const initialData = location.state?.productData; const [product, setProduct] = useState(initialData); useEffect(() => { if (!product) { console.log("البيانات غير موجودة في state، جاري طلبها من الـ API..."); fetchAPI(`/api/products/${id}`).then(data => setProduct(data)); } }, [id, product]); if (!product) { return <div>جاري التحميل...</div>; } return ( <div> <h1>{product.name}</h1> <p>السعر: {product.price}</p> </div> ); } كذلك لو لديك صفحة إعدادات بها عدة تبويبات مختلفة Profile, Account, Notifications وتريد أن يكون الرابط هو الذي يحدد أي قسم يتم عرضه، بمعنى أي قسم يجب أن يكون نشطًا بناءًا على الرابط؟ فستحتاج إلى استخدام location.pathname أو location.hash.
