لو عايز تعمل برنامج لتصميم جمعية شهرية باستخدام Laravel، الفكرة هنا إنك بتعمل تطبيق ويب بحيث يكون لكل واحد من الاعضاء اكثر من دور ومبلغ شهري يدفعه والدور يشيل اكثر من عضو . الجمعية دي تعتبر مفهوم واسع، بتلاقيها في ثقافات كتير وأحيانًا بمعاني مختلفة، زي الصندوق العائلي، أو زي جمعيات الأصدقاء اللي كل شهر حد منهم بياخد “النوبة” بتاعته. Laravel هيسهل عليك الموضوع جدًا لإنه بيوفر الأدوات اللي هتساعدك تدير قاعدة البيانات، وتعمل روابط بين الأعضاء والجمعيات والأدوار بشكل منظم. وكمان تقدر تتحكم في المبالغ الشهرية لكل عضو ولكل دور، ودا بيساعد الجمعية إنها تشتغل بشكل منظم وسهل الفهم لكل الناس المشتركة فيها.
الجمعية الشهرية باستخدام لارافيل
المتطلبات
تكلمنا في السابق عن الادوات المستخدمة مثل فيجوال ستوديو كود كمحرر لكتابة الكود و composer لتثبيت لارافيل ونود جي اس لرياكت وهنا نستخدم رياكت للاستفادة من قوتة في الواجهه الامامية و عدم التحميل الكامل للصفحة اثناء ادخال بيانات جديدة
تثبيت laravel
				
					composer create-project laravel/laravel Associations 
				
			بعد التثبيت الدخول علي فولدر المشروع بالكود التالي
				
					cd Associations 
				
			تثبيت Breeze
				
					composer require laravel/breeze --dev 
				
			تثبيت React
				
					php artisan breeze:install react 
				
			ضبط اعدادات ملف env.
				
					DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=association_db
DB_USERNAME=root
DB_PASSWORD= 
				
			قمنا بانشاء قاعدة بيانات باسم association_db ونقوم بترحيلها باستخدام migrate
				
					php artisan migrate 
				
			سيطلب منك انشاء قاعدة بيانات جديدة باسم association_db
بعد الموافقة علي انشاء قاعدة البيانات نكون قد اتممنا الجزء الاول وهو authentication بهذا الشكل
اضافة animate
				
					npm install animate.css --save 
				
			بعد ذلك نضع الكود التالي في صفحة app.jsx لاستيراد animation
				
					import 'animate.css'; 
				
			انشاء جدول الجمعيات Associations
سوف نقوم بانشاء موديل وكنترولر وميجريشن للجمعيات باتباع التالي
				
					php artisan make:model Association -mrc 
				
			المايجريشن migrate
سوف يكون الجدول الخاص بالجمعيات عبارة عن اسم الجمعية وعدد الاشهر واجمالي المبلغ الشهري علي اعتبار ان الدور كل شهر من database اختيار migrations ثم اختيار جدول associations ويكون بالشكل التالي
				
					public function up(): void
    {
        Schema::create('associations', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->integer('total_months');
            $table->decimal('role_price', 10, 2);
            $table->timestamps();
        });
    } 
				
			ثم ترحيل الجدول لقواعد البيانات باستخدام الامر التالي
				
					php artisan migrate 
				
			الموديل Model
من app اختيار Models ثم Association واضافة الكود التالي
				
					class Association extends Model
{
    protected $fillable = ['name', 'total_months', 'role_price'];
} 
				
			كونترولر Controller
من app اختيار http ثم controller ثم AssociationController واضافة الكود التالي للصفحة بحيث يتم استيراد الموديل واضافة index و store
				
					namespace App\Http\Controllers;
use App\Models\Association;
use Illuminate\Http\Request;
use Inertia\Inertia;
class AssociationController extends Controller
{
    
    public function index()
    {
        $associations = Association::all();
        return Inertia::render('Associations/Index', [
            'associations' => $associations
        ]);
    }
    
 
    public function store(Request $request)
    {
        $validated = $request->validate([
            'name' => 'required|string|max:255',
            'total_months' => 'required|integer|min:1',
            'role_price' => 'required|numeric|min:0',
        ]);
        $group = Association::create([
            'name' => $validated['name'],
            'total_months' => $validated['total_months'],
            'role_price' => $validated['role_price'],
        ]);
        return redirect()->route('associations.index');
    }
 
				
			التوجهات (الراوت) Routes
من routes نذهب الي web واضافة الكود
				
					//namespace
use App\Http\Controllers\AssociationController;   
// code
Route::resource('associations', AssociationController::class)
    ->middleware(['auth', 'verified']);
 
				
			الواجهه الامامية لصفحة الجمعيات Associations/Index
من داخل resources\js\Pages نقوم بانشاء Associations وداخلة ملف Index.jsx ولصق الكود التالي
				
					
import React, { useState } from 'react';
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout';
import InputError from '@/Components/InputError';
import PrimaryButton from '@/Components/PrimaryButton';
import { useForm, Head, Link } from '@inertiajs/react';
export default function Associations({ auth, associations }) {
    const { data, setData, post, processing, reset, errors } = useForm({
        name: '',
        total_months: '',
        role_price: ''
    });
    const handleSubmit = (e) => {
        e.preventDefault();
        post(route('associations.store'), { onSuccess: () => reset() });
    };
    return (
        
            
            
            
                        
                    
                    
                        {associations.map((association, index) => (
                            
                                
                                    
                                        
                                        
                                            {association.name}
                                        
                                        
                                        {association.total_months} شهر
                                        {association.role_price} في الشهر
                                    
                                    
                                        
                                    
                                
                            
                        ))}
                    
              لمشاهدة ما تم تنفيذة استخدم الامر التالي ثم قم بادخال بيانات للتاكد من ان الكود سليم
				
					npm run dev 
				
			يجب اضافة اسم الصفحة لل navbar لسهولة التصفح وبالتالي يمكنك اضافة باقي الصفحات باتباعك نفس الطريقة
نذهب الي مجلد Layouts ومن داخلة نختار AuthenticatedLayout.jsx ثم نضيف الكود التالي بعد كود dashboard وتعديل الروت الخاص بالصفحة بالشكل التالي
				
					
                                
                                    Dashboard
                                 
                                
                                    Association
                                 
                             
				
			قمنا باضافة navlink خاص بصفحة association بعد صفحة dashboard وتعديل الروت الخاص بة وسنقوم ايضا باضافتة مرة اخري في نفس الصفحة لكن ResponsiveNavLink
				
					
                        
                            Dashboard
                         
                        
                            Association
                         
                    
 
				
			انشاء جدول الادوار Roles
				
					php artisan make:model Role -mrc 
				
			المايجريشن migrate
سيرتبط جدول الادوار بجدول الجمعيات حيث ان لكل جمعية اكثر من دور بالتالي سوف يتم انشاء الادوار الخاصة بكل جمعية بمجرد تسجيل الجمعية واختيار عدد الادوار وسيتم احتساب اول شهر في الجمعية من تاريخ تسجيل البيان. لنري ذلك
				
					public function up(): void
    {
        Schema::create('roles', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('start_date')->nullable();
            $table->foreignId('association_id')->constrained()->onDelete('cascade');
            $table->timestamps();
        });
    } 
				
			
				
					// للترحيل 
php artisan migrate 
				
			الموديل Model
				
					// role model
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
    protected $fillable = [
        'name', 
        'association_id',
        'start_date',
    ];
    
    public function associations()
    {
        return $this->belongsTo(Association::class);
    }
} 
				
			ويجب اضافة الكود التالي في موديل Association للعلاقة بين الجمعية والادوار
				
					// association model
public function roles()
    {
        return $this->hasMany(Role::class);
    } 
				
			كونترولر Controller
سوف نضيف الي index في RoleController كل تفاصيل الادوار الخاصة بجمعية معينة بالشكل الاتي
				
					 
use App\Models\Association;
use Inertia\Inertia;
// code
 public function index()
    {
        $associations = Association::with(['roles'])->get();
        
        return Inertia::render('Roles/Index', [
            'associations' => $associations,
        ]);
    } 
				
			بعد ذلك نقوم باضافة الادوار الي store في AssociationController الذي يقوم باضافة الادوار الي الجمعية بعد ادخال بيانات الجمعية لتصبح بالشكل التالي
				
					// استدعاء
use Carbon\Carbon;
use Illuminate\Http\RedirectResponse;
use App\Models\Role;
// code
public function store(Request $request): RedirectResponse
{
    $validated = $request->validate([
        'name' => 'required|string|max:255',
        'total_months' => 'required|integer|min:1',
        'role_price' => 'required|numeric|min:0',
    ]);
    $association = Association::create([
        'name' => $validated['name'],
        'total_months' => $validated['total_months'],
        'role_price' => $validated['role_price'],
    ]);
    // لإضافة الأدوار عند إنشاء جمعية جديدة مع تواريخ البداية لكل دور
    $role_names = [
        'الأول', 'الثاني', 'الثالث', 'الرابع', 'الخامس', 'السادس', 'السابع', 'الثامن', 'التاسع', 'العاشر',
        'الحادي عشر', 'الثاني عشر', 'الثالث عشر', 'الرابع عشر', 'الخامس عشر', 'السادس عشر', 'السابع عشر',
        'الثامن عشر', 'التاسع عشر', 'العشرون'
    ];
    // تاريخ بداية الأدوار
    $startDate = Carbon::now()->startOfMonth(); // البداية من بداية الشهر الحالي
    for ($i = 0; $i < $validated['total_months']; $i++) {
        // زيادة عدد الأشهر لكل دور
        $roleDate = $startDate->copy()->addMonths($i)->format('m-Y');
        Role::create([
            'name' => $role_names[$i] ?? 'الدور ' . ($i + 1),
            'association_id' => $association->id,
            'start_date' => $roleDate, // حفظ الشهر والسنة بدون تكرار
        ]);
    }
    return redirect(route('associations.index'));
} 
				
			التوجهات (الراوت) Routes
				
					//namespace
use App\Http\Controllers\RoleController;
//code
Route::resource('roles', RoleController::class)
     ->middleware(['auth', 'verified']);
 
				
			الواجهه الامامية لصفحة الادوار Roles/Index
				
					//resources\js\Pages\Roles\Index.jsx
import React, { useState } from 'react';
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout';
import { Head, useForm } from '@inertiajs/react';
export default function Roles({ auth, associations }) {
    
    return (
        
            
            
            
                    {associations.map((association, index) => (
                        
                            
                                {association.name}
                                عدد الأشهر: {association.total_months}
                                مبلغ الدور: {association.role_price}
                                
                                أدوار الجمعية
                                
                                        {association.roles.map((role, roleIndex) => (
                                             openModal(association, role)}
                                            >
                                                
                                                
                                                
                                                        {role.name}
                                                        {role.start_date}
                                                    
                                                       
                                                    
                                                
                                            
                                        ))}
                                    
                            
                        
                    ))}
                
              بعد ذلك اضافة navlink خاص بصفحة roles مثل الصفحة السابقة
				
					npm run dev 
				
			بهذا قد قمنا بتنفيذ الجزء الخاص باضافة الجمعية وعدد الادوار بها مع احتساب اول شهر فيها من حين ادخال البيانات ونظرا لطول المقال تم تقسيمه الي جزئين


								
								
								
								
								
								
								
								



