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

سمير عبود

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

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

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

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

    34

كل منشورات العضو سمير عبود

  1. يُمكنك إستخدام Carbon باللغة العربية عن طريق إضافة السطر التالي لمُزود الخدمة AppServiceProvider في الدالة boot: Carbon::setLocale('ar'); و لا تنسى إستدعاء الكلاس فوق: use Carbon\Carbon; أما لجلب السجلات من الأحدث إلى الأقدم عن طريق Eloquent يُمكنك إستخدام نفس الدوال المُتاحة لباني الإستعلامات فهي متاحة أيضاً ل Eloquent بنفس الأسماء مثلاً $posts = Post::latest()->get(); // أو $posts = Post::latest()->paginate(15);
  2. مرحباً عبد القادر، أنت الآن في أواخر الدروس لذلك حاول تعلم مهارة حل المشاكل لأنك ستقضي معظم وقتك في حل مشاكل و أخطاء تواجهك في المُستقبل. بخصوص المشاكل التي تحدث لك فهي بسبب الملف GemFile لذلك أنصحك بإعادة الخطوات المشروحة في الدرس لكن بالطريقة التالية لتصل إلى النتيجة المرغوبة. قم بتحميل هذا الملف الخاص بالمشروع قبل أن تُطبق هذا الدرس: لأنني أجريت الخطوات عليه. بعد ذلك إفتح ملف Gemfile الخاص به و حاول إضافة ال Gems الغير موجودة فيه و التي استخدمها المدرب في الدرس و قد لاحظت أنهما إثنين فقط: gem 'bootstrap-sass' gem 'coffee-rails', '~> 4.2' فقط قم بإضافتهما لملف Gemfile الخاص بك و لا تقم بنسخ الملف من الملفات المرفقة مع الدرس. بعد ذلك إنسخ مُجلد images المُرفق مع الدرس في مُجلد app/assets ثم إنسخ ملفات css من الملفات المُرفقة إلى مُجلد app/assets/stylesheets و قم بحذف ملف application.css كما فعل المُدرب في الدرس. إفتح ملف application.js الموجود في app/assets/javascripts و قم بالتعديل عليه ليُصبح بالشكل التالي: //= require rails-ujs //= require bootstrap-sprockets //= require turbolinks //= require_tree . $( document ).on('turbolinks:load', function() { $("#menu-toggle").click(function(e) { e.preventDefault(); $("#wrapper").toggleClass("toggled"); }); }) بعد ذلك قم بنسخ ملفات locales المُرفقة و ضعها في المسار: config/locales و هما ملفين فقط. بعد ذلك قم بنسخ ما بداخل مُجلد views المُرفق و ضعه في المسار app/views كما فعل المُدرب في الدرس. الآن يوجد لديك خطأ في ملف registrations_controller.rb في كتابة الخاصية description فقد كتبتها descrption أرجو تصحيحها في التابعين account_update_params و sign_up_params ليُصبح المُتحكم بهذا الشكل: class RegistrationsController < Devise::RegistrationsController private def account_update_params params.require(:user).permit(:first_name, :last_name, :description, :email, :country, :language, :gender, :birth_date, :password, :password_confirmation, :current_password) end def sign_up_params params.require(:user).permit(:first_name, :last_name, :description, :email, :password, :password_confirmation) end end الآن قد جهزت كل شيء تذهب إلى الطرفية أو سطر الأوامر و تُنفذ الأمر: bundle install ثم تقوم بتشغيل المشروع: rails s و ستجد أن كل شيء يعمل بشكل جيد. أرجو تنفيذ الخطوات بعناية، و إذا لم تصل إلى النتيجة فاعلم أنك نسيت او تخطيت خطوة ما، و هذا مجلد مشروعك إذا احتجت له: Hsoub_IO.zip إذا اردت تشغيله تحتاج إلى تعديل Gemfile: ruby '2.7.1' إلى الإصدار الخاص بك ثم bundle install. بالتوفيق.
  3. مرحباً عبد القادر، لاحظ ان رسالة الخطأ تُخبرك أنه لا يُمكنك تحديد الحزمة مرتين و كل مرة تُحدد إصدار مُختلف للحزمة في ملف Gemfile و هذه الحزمة هي sass-rails وهي موجودة في السطر رقم 15 و السطر رقم 26 أرجو حذف أحد السطر 15 ثم قم بحفظ الملف و أعد تنفيذ الأمر bundle install ثم أطلعنا على النتيجة، تحياتي لك.
  4. لنفترض أنك جلبت مجموعة من البيانات و قمت بتمريرها لصفحة العرض و لنقل أن المُتغير الذي مررته هو courses بالتالي في صفحة العرض ستقوم بعمل حلقة لعرض هذه البيانات بالشكل التالي مثلاً <ul class="nav flex-column"> @foreach($courses as $course) <li class="nav-item"> <a class="nav-link " href="">{{$course->title}}</a> </li> @endforeach </ul> الآن تريد تغيير طريقة العرض على حسب الid تستخدم التوجيه if الخاص ب blade بهذا الشكل: <ul class="nav flex-column"> @foreach($courses as $course) @if($course->id % 2 == 0) <li class="nav-item"> <a class="nav-link " href="">{{$course->title}}</a> </li> @else <li class="nav-item"> <a class="nav-link text-danger" href="">{{$course->title}}</a> </li> @endif @endforeach </ul> حيث إذا تحقق الشرط تقوم بعرض البيانات بشكل في بلوك if و إذا لم يتحقق تضع الشكل الآخر في جزء else.
  5. تستطيع ان تبدأ التعلم متى ما أردت ذلك، لكن كبداية تحتاج إلى الإطلاع على مجالات البرمجة الموجودة و إختيار المجال الأنسب لك و الذي تُفضله و تبدأ رحلة تعلمك. يُمكنك الإطلاع على هذا المقال المُقدم من أكاديمية حسوب: بعد إختيار المجال الذي تريده، تستطيع أن تبدأ في تعلم التقنيات المُناسبة لذلك المجال.
  6. أعتقد أن علامة النجمة تعني أن ذلك المحتوى أو الدرس تقوم بمتابعته، أما علامة النقطة تعني أن ذلك المحتوى أو الدرس جديد لم تقم بقراءته أو الإطلاع عليه من قبل.
  7. يبدو أن المنفذ الإفتراضي الذي يتم تشغيل خادم websockets عليه من طرف الحزمة قيد التشغيل من طرف برنامج آخر أو Process آخر لذلك عليك تغييره لمنفذ لايتم إستخدامه حيث أنه يُمكن تمرير flag للأمر عن طريق --port و تمرير المنفذ الذي تريد بهذا الشكل: php artisan websockets:serve --port={port} مثال: php artisan websockets:serve --port=3030 كما يُمكن أيضاً تغيير المنفذ من خلال ملف إعدادات الحزمة عن طريق نشر الملف ضمن مجلد الإعدادات: php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="config" بعد ذلك يُمكنك تغيير السطر: 'dashboard' => [ 'port' => env('LARAVEL_WEBSOCKETS_PORT', 6001), ], لاحظ أنه 6001 يُمكنك تغييره او إسناد قيمة ل LARAVEL_WEBSOCKETS_PORT في ملف env.
  8. بخصوص الصنف الذي لا يتم نشره عن طريق أمر: php artisan vendor:publish --tag=jetstream-views تحتاج إلى خطوات إضافية: إنشاء مُجلد Livewire في المسار: app\Http إن لم يكن موجود إنشاء صنف UpdateProfileInformationForm.php داخل المجلد Livewire نسخ مُحتوى الصنف \vendor\laravel\jetstream\src\Http\Livewire\UpdateProfileInformationForm.php إلى الصنف الذي أنشأته مع تعديل مجال الأسماء الخاص به. في مزود الخدمة JetstreamServiceProvider داخل التابع boot قم بإضافة: Livewire::component('profile.update-profile-information-form', UpdateProfileInformationForm::class); و لا تنسى إستدعاء الصنف الذي قمت بإنشائه النُسخة الخاصة بك. use App\Http\Livewire\UpdateProfileInformationForm; بعد ذلك يُمكنك التعديل كيفما شئت على الصنف.
  9. جرب تعليق ذلك السطر و ضع مكانه هذا السطر: Route::get('/', function () { dd("test"); }); ثم قم بعمل clear لأي cache او إعدادات عن طريق الأمر: php artisan optimize:clear ثم حاول تشغيل التطبيق.
  10. ماهو المسار الذي تُحاول الوصول إليه أي مسار من المسارات المرفقة أعلاه ظهرت صفحة 404
  11. لإضافة حقول جديدة تحتاج إتباع الخطوات التالية: إضافة الحقول لملف التهجير الخاص بالمُستخدمين: <?php public function up() { Schema::create('users', function (Blueprint $table) { $table->id(); $table->string('name'); $table->string('company'); // الحقل المضاف $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); $table->rememberToken(); $table->foreignId('current_team_id')->nullable(); $table->text('profile_photo_path')->nullable(); $table->timestamps(); }); } تنفيذ أمر التهجير: php artisan migrate:fresh إضافة الحقول الجديدة لمصفوفة fillable في النموذج User: <?php protected $fillable = [ 'name', 'email', 'password', 'company' ]; بعد ذلك تضيف الحقول لصفحة العرض register.blade.php الموجود في المسار resources\views\auth\register.blade.php <div class="mt-4"> <x-jet-label for="company" value="{{ __('Company') }}" /> <x-jet-input id="company" class="block mt-1 w-full" type="text" name="company" :value="old('company')" required /> </div> ثم تذهب إلى الصنف CreateNewUser الموجود في المسار: app\Actions\Fortify\CreateNewUser.php و تقوم بالتحقق من الحقول المُضافة و إضافتها للتابع create: <?php public function create(array $input) { Validator::make($input, [ 'name' => ['required', 'string', 'max:255'], 'company' => ['required', 'string', 'max:255'], 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], 'password' => $this->passwordRules(), 'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature() ? ['required', 'accepted'] : '', ])->validate(); return DB::transaction(function () use ($input) { return tap(User::create([ 'name' => $input['name'], 'company' => $input['company'], 'email' => $input['email'], 'password' => Hash::make($input['password']), ]), function (User $user) { $this->createTeam($user); }); }); } و الآن قد جهزت كل شيء و تحتاج فقط للتجربة.
  12. السبب في ذلك أن الشرط الذي تستخدمه دائماً مُحقق فأحياناً لا يوجد سجل يُطابق ما تبحث عنه فيُرجع Null و أنت تحاول الوصول للخاصية meta_value من null، الصواب هو ان يكون بهذا الشكل مثلاً: <?php if ( $post_meta->where('meta_key', 'faq_content')->exists() ) { $faq_number = $post_meta->where('meta_key', 'faq_content')->first()->meta_value; } else { $faq_number = 0; } أو بهذا الشكل أحسن: <?php if ( $something = $post_meta->where('meta_key', 'faq_content')->first() ) { $faq_number = $something->meta_value; } else { $faq_number = 0; } أو تبسيط الشرط و إستخدام مُعامل الإندماج الفارغ ( Null coalescing operator): $faq_number = $post_meta->where('meta_key', 'faq_content')->first()->meta_value ?? 0;
  13. توفر لارافيل هذه الخاصية مُسبقاً و ما عليك إلا تفعيلها في المشروع و يتم ذلك عن طريق: تطبيق الواجهة MustVerifyEmail على النموذج User: <?php namespace App\Models; use Illuminate\Contracts\Auth\MustVerifyEmail; // ... class User extends Authenticatable implements MustVerifyEmail { use HasFactory, Notifiable; // ... } بعد ذلك في ملف المسارات تحتاج إلى التعديل على: Auth::routes(); ليُصبح: Auth::routes(['verify' => true]); إذا لم تقم بإضافة إعدادات البريد الإلكتروني في ملف .env يجب إضافتها: MAIL_MAILER=smtp MAIL_HOST=smtp.mailtrap.io MAIL_PORT=2525 MAIL_USERNAME= MAIL_PASSWORD= MAIL_ENCRYPTION=null MAIL_FROM_ADDRESS="laravel@app.com" MAIL_FROM_NAME="${APP_NAME}" يُمكنك إستخدام خدمة mailtrap إن كنت في مرحلة التطوير، بعد ذلك تحتاج إلى حماية المسارات من المستخدمين الذي لم يقومو بتفعيل حسابهم بإضافة ال middleware verified كما هو موضح أدناه: Route::middleware(['verified'])->group(function () { // المسارات التي تريد حمايتها }); و بهذا الشكل إذا قام أحد المُستخدمين الذين لم يُفعلو حسابهم بتصفح هذه المسارات يتم إعادة توجيههم تلقائياً إلى صفحة التحقق من البريد الإلكتروني.
  14. اسم القالب في الموقع الذي أرفقته هو موضوع و هذا كان إسمه سابقاً و الآن إسمه هو بحر و هو قالب مدفوع يُمكنك معرفة إسم القالب لاي موقع إن كان مبني على ووردبريس بالطريقة التالية:
  15. أعتقد أن المُشكلة في جزء with يجب أن تكون بهذا الشكل: $view->with([ 'current_user_notification' => $current_user_notification, 'current_user_notification_count' => $current_user_notification_count ]); ليُصبح الكود ككل بهذا الشكل: <?php View::composer('layouts.dashboard.master', function($view){ $userNoteRepository = resolve(UserNoteRepositoryInterface::class); $current_user_notification = $userNoteRepository->getCurrentUserAlertNotifications(); $current_user_notification_count = count($userNoteRepository->getCurrentUserAlertNotifications()); $view->with([ 'current_user_notification' => $current_user_notification, 'current_user_notification_count' => $current_user_notification_count ]); });
  16. حزمة laravel horizon الإصدار الآخير اي حالياً (5.7) يحتاج إلى هذه المتطلبات: requires php: ^7.3|^8.0 ext-json: * ext-pcntl: * ext-posix: * illuminate/contracts: ^8.17 illuminate/queue: ^8.17 illuminate/support: ^8.17 nesbot/carbon: ^2.17 ramsey/uuid: ^4.0 symfony/error-handler: ^5.0 symfony/process: ^5.0 requires (dev) mockery/mockery: ^1.0 orchestra/testbench: ^6.0 phpunit/phpunit: ^9.0 predis/predis: ^1.1 عليك التحقق منها، إصدار لارافيل الخاص بالمشروع يجب أن يكون أعلى من 8.17 بخصوص المُشكلة التي تواجهك يُمكن حلها بالشكل التالي: تعديل ملف composer.json بإضافة التالي للخاصية config: "config": { "platform": { "ext-pcntl": "7.1", "ext-posix": "7.1" }, } بعد ذلك أعد تنفيذ أمر تثبيت الحزمة: composer require laravel/horizon ثم: php artisan horizon:install
  17. في ملف jetstream.php الخاص بالإعدادات تجد أن jetstream يستخدم: 'profile_photo_disk' => 'public', و إذا ذهبنا إلى ملف الإعدادات الخاص ب filesystem نجد: <?php 'public' => [ 'driver' => 'local', 'root' => storage_path('app/public'), 'url' => env('APP_URL').'/storage', 'visibility' => 'public', ], اي أن ال disk public يعتمد على الثابت: APP_URL في ملف env. و يعتمد على الوصلة التي يتم إنشاؤها بين مُجلد storage و مُجلد public لذلك عليك الإنتباه لهذا الأمر: فأولا قم بإنشاء الوصلة عن طريق الأمر: php artisan storage:link بعد ذلك إن كنت تتصفح المشروع عن طريق: http://127.0.0.1:8000 عليك تعديل قيمة APP_URL بهذا الشكل: APP_URL=http://127.0.0.1:8000 و بهذا الشكل ستظهر الصور بشكل طبيعي، أما إن كنت تستخدم خادم وهمي بالرابط التالي مثلاً: http://cms.test تحتاج إلى وضع ذلك الرابط في APP_URL APP_URL=http://cms.test و في هذه الحالة ستظهر الصورة أيضاً.
  18. بإمكانك إنشاء صفحات عرض للأخطاء خاصة بك او التعديل على صفحات العرض الخاصة بعرض الأخطاء التي تستخدمها لارافيل بنشر مُجلد الأخطاء الذي تستخدمه لارافيل ضمن ملفات مشروعك عن طريق الأمر: php artisan vendor:publish --tag=laravel-errors هذا الأمر سيقوم بعمل نسخ للملفات ضمن مُجلد errors في مُجلد views حيث كل خطأ له ملف بنفس الإسم بالإضافة إلى 3 أنواع من القوالب الجاهزة يُمكنك إستخدامها لنأخذ مثال: 404.blade: @extends('errors::minimal') @section('title', __('Not Found')) @section('code', '404') @section('message', __('Not Found')) يُمكننا تعديله بهذا الشكل: @extends('errors::illustrated-layout') @section('title', __('الصفحة غير موجودة')) @section('code', '404') @section('message', __('الصفحة غير موجودة')) أو إنشاء قالب لصفحات الأخطاء بالشكل الذي نريد ثم نستخدمه.
  19. وسائل سحب الرصيد المتوفرة هي باي بال فقط و للمبالغ أكبر من 25$ إن لم يكن لديك حساب مُفعل على باي بال لا تستطيع السحب، يلجأ المستقلين في هذه الحالة إلى الإستعانة بأصدقاء موثوقين أو أقارب لديهم حساب باي بال كي يلعبو دور الوسيط ثم يقوم هذا الوسيط بتحويل المال لك بعد إستلامه. هناك جهات أخرى تقوم بالتحويل و ذلك بأخذ نسبة من المبلغ بعد التحويل بعد الإتفاق بينكم لكن لا أنصحك بهم فقد لا يكونون موثوقين و قد يضيع جهدك، لذلك من الأحسن أن يكون لديك حساب خاص بك، لكن إن كنت مضطر تأكد من الثقة أولاً.
  20. يُمكن عمل ذلك عن طريق الموصلات او Accessors مثلا لنقل أنه لديك عمود first_name و عمود last_name و تريد الإسم الكامل عند إسترجاع النموذج يُمكنك ذلك عن طريق إنشاء موصل بالشكل التالي في النموذج: public function getFullNameAttribute() { return "{$this->first_name} {$this->last_name}"; } و عند جلب النموذج يُمكنك الوصول للإسم الكامل عن طريق الخاصية: full_name. بنفس الطريقة يُمكنك إستخدام موصل لجلب الخاصية message بالشكل الذي تريد و بداخلها تستخدم الدالة str_replace لإستبدال المفاتيح بما يوافقها من قيم في الخاصية data بهذا الشكل مثلا: public function getFormattedMessageAttribute() { $message = $this->message; foreach ($this-data as $key => $value) { $message = str_replace("{{$key}}", $value, $message); } return $message } ثم عند جلب النموذج يُمكنك الوصول للشكل الذي تريده من خلال الوصول للخاصية formatted_message.
  21. نعم إضافة ملفات تنسيقات خارجية او ملفات جافاسكربت تُضاف بنفس طريقة إضافتها في ملفات ال blade العادية، فمثلا إذا كنت تريد إضافة ملف تنسيقات تحتاج إلى إضافة التوجيه: @yield('custom_css') في ملف layout قبل إستدعاء @livewireStyles ثم تستخدم التوجيه section في ملف ال blade الخاص بالمُكون بالشكل التالي: @section('custom_css') //....CDN @endsection أو يُمكنك إستخدام stack بدل yield بهذا الشكل: @stack('custom_css') ثم في ملف ال blade الخاص بالمُكون تستخدم التوجيه push بهذا الشكل: @push('custom_css') // ..... CDN @endpush
  22. يبدو أن Livewire يكتشف أن العنصر الذي يحتوي على مشغل الفيديو قد تغير ويحاول استبداله. عليك إضافة التوجيه wire:ignore للعُنصر الحاوي لعُنصر الفيديو أو عُنصر الفيديو نفسه: <video class="video-js" wire:ignore> تختلط الأمور على Livewire عندما يتم التلاعب بالصفحة بإستخدام شيفرات جافاسكربت خارجية دون علم Livewire بذلك، مُعظم المشاكل من هذا النوع يتم حلها بإضافة التوجيه او الخاصية "wire:ignore"
  23. في لغة php الدالة موجودة لكن أنت لست مُجبر على إستخدامها عند إنشاء أصناف PHP، بالعكس فالأمر متروك لك و تُستخدم عند حاجتك للدالة و في الوضعيات التي تحتاجها، فبنفس طريقة إنشائك للكلاسات في اللغات الأخرى مثل جافا او بايثون يُمكنك إنشاء الكلاسات في PHP بدون إستخدام الدالة class_exists فلا تحصر نفسك في سياق مُحدد و الدالة ليست موجودة لهذا الأمر فقط، قد تحتاج في جزئية مُحددة من الكود إلى إنشاء كائن من كلاس ما لكن إسم الكلاس هذا ليس معلوماً لديك قد يكون الكلاس موجود أو قد يكون غير موجود فالإسم يأتيك على شكل ديناميكي فهل ستقوم بإنشاء الكائن مُباشرة قد يعطيك خطأ لذلك يُمكن إستخدام الدالة class_exists في هذه الحالة للتأكد من وجود الصنف قبل إنشاء كائن منه و إلا مُعالجة الأمر عن طريق رمي إستثناء او ما إلى ذلك و هذه حالة من الحالات. أعتقد انه حتى لو لم تُوفر اللغات التي ذكرتها دالة مُشابهة إلا انها وفرت طرق للحصول على نفس نتيجة الدالة. أعتقد أيضاً أن إستخدام الدالة في ووردبريس حتى لا يتم إنشاء كلاسات بنفس الأسماء مما قد يُشكل لك بعض المشاكل في التطبيق الخاص بك. إحرص دائما على معرفة ما الذي تفعله الدالة و لا تُقيد نفسك بسياق واحد او إستخدام واحد للدالة و إنما فكر دائماً خارج الصندوق. هناك أيضاً دوال مُشابهة مثل method_exists، function_exists تُوفرها لغة PHP.
  24. يُمكنك إستخدام join لعمل الشيء الذي تُريده بهذا الشكل: لعمل فلترة للمُستخدمين حسب الأكثر طلباً: <?php User::join('orders', 'orders.user_id', '=', 'users.id') ->selectRaw('users.*, count(orders.id) as orders_count, sum(orders.amount) as total_amount') ->groupBy('users.id') ->orderBy('orders_count', 'desc') ->paginate(10); لعمل فلترة للمُستخدمين حسب مجموع قيمة الطلبات: <?php User::join('orders', 'orders.user_id', '=', 'users.id') ->selectRaw('users.*, count(orders.id) as orders_count, sum(orders.amount) as total_amount') ->groupBy('users.id') ->orderBy('total_amount', 'desc') ->paginate(10); أما إن كنت تريد عمل فلترة للمُستخدمين حسب مجموع قيمة الطلبات بالإضافة لتحديد مجال للمجموع يُمكنك ذلك من خلال التالي: <?php $min_amount = 30000; $max_amount = 40000; User::join('orders', 'orders.user_id', '=', 'users.id') ->selectRaw('users.*, count(orders.id) as orders_count, sum(orders.amount) as total_amount') ->groupBy('users.id') ->havingRaw('total_amount >= ? and total_amount <= ?', [$min_amount, $max_amount]) ->orderBy('total_amount', 'desc') ->paginate(10); بنفس الطريقة إن أردت تحديد مجال لعدد الطلبات يُمكنك ذلك أيضاً.
  25. من المفروض عند إنهاء أي مشروع على المنصة يأتيك إشعار في حسابك أنه تم إضافة مبلغ بقيمة كذا لحسابك، لكن هذا المبلغ يكون مُعلق لمُدة 14 يوم علماً أن مدة التعليق تبدأ من اليوم التالي لاستلام المشروع وتستمر حتى انتهاء اليوم الرابع عشر بتوقيت غرينتش. أما زر سحب الرصيد يظهر إذا توفر الحد الأدني للسحب وهو 25 دولار، إذا توفرت كل هذه الشروط و لم تظهر أرباحك مع الرصيد القابل للسحب إفتح صفحة الرصيد لديك و أعد تحديثها أكثر من مرة أو قم بحذف الكاش من المتصفح فعادة المُتصفح لا يقوم بتحميل الصفحة كلها من الخادم و إنما يستخدم ذاكرة التخزين المُؤقت لتسريع عملية التصفح. تأكد أنه يُمكنك دائما مواصلة الدعم الفني للمنصة للإستفسار عن أي شيء تُريده من خلال: مركز المساعدة بفتح تذكرة لإستفسارك و سيرد عليك الإخوة هناك و مُساعدتك.
×
×
  • أضف...