alireza-hadizadeh:  fill these file and make forms as component to be reuseable in create and update for index to make it like  role/index file 
 and for form component like category-form

GitHub Copilot: Okay, I can help you with that. Here's how you can structure your coupon management:

First, let's update the migration to include timestamps and modify the Coupon model to handle JSON casting and date formatting.

````php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('coupons', function (Blueprint $table) {
            $table->id();

            // general info
            $table->string('code')->unique();
            $table->text('description')->nullable();
            $table->enum('type', ['Percentage Discount', 'Fixed Cart Discount', 'Fixed Product Discount']);
            $table->decimal('amount', 10, 2);
            $table->boolean('allow_free_shipment')->default(false);
            $table->timestamp('expire_date')->nullable();

            // usage restriction
            $table->decimal('max_discount', 10, 2)->nullable();
            $table->decimal('minimum_spend', 10, 2)->nullable();
            $table->decimal('maximum_spend', 10, 2)->nullable();

            $table->boolean('individual_use_only')->default(false);
            $table->boolean('exclude_sale_items')->default(false);

            $table->json('products')->nullable();
            $table->json('exclude_products')->nullable();
            $table->json('product_categories')->nullable();
            $table->json('exclude_categories')->nullable();
            $table->json('allowed_emails')->nullable();

            // usage limits
            $table->unsignedInteger('usage_limit')->nullable();
            $table->unsignedInteger('product_limit')->nullable(); // Usage limit per item in cart
            $table->unsignedInteger('usage_limit_per_user')->nullable();
            
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('coupons');
    }
};
````

````php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Coupon extends Model
{
    use HasFactory;

    protected $fillable = [
        'code',
        'description',
        'type',
        'amount',
        'allow_free_shipment',
        'expire_date',
        'max_discount',
        'minimum_spend',
        'maximum_spend',
        'individual_use_only',
        'exclude_sale_items',
        'products',
        'exclude_products',
        'product_categories',
        'exclude_categories',
        'allowed_emails',
        'usage_limit',
        'product_limit',
        'usage_limit_per_user',
    ];

    protected $casts = [
        'allow_free_shipment' => 'boolean',
        'expire_date' => 'datetime',
        'individual_use_only' => 'boolean',
        'exclude_sale_items' => 'boolean',
        'products' => 'array',
        'exclude_products' => 'array',
        'product_categories' => 'array',
        'exclude_categories' => 'array',
        'allowed_emails' => 'array',
        'amount' => 'float',
        'max_discount' => 'float',
        'minimum_spend' => 'float',
        'maximum_spend' => 'float',
    ];

    public const TYPES = ['Percentage Discount', 'Fixed Cart Discount', 'Fixed Product Discount'];
}
````

Next, create the reusable form component:

**`resources\views\components\syndron\form\coupon-form.blade.php`**
````php
@props(['coupon' => null, 'productsList' => [], 'categoriesList' => []])

@php
    $isEdit = isset($coupon) && $coupon->exists;
    $couponTypes = \App\Models\Coupon::TYPES;
@endphp

<form class="" action="{{ $isEdit ? route('admin.coupons.update', $coupon) : route('admin.coupons.store') }}" method="POST">
    @csrf
    @if($isEdit)
        @method('PUT')
    @endif

    <div class="row">
        {{-- General Information --}}
        <div class="col-md-6">
            <div class="card mb-3">
                <div class="card-header">
                    {{ __('General Information') }}
                </div>
                <div class="card-body">
                    <div class="mb-3">
                        <label class="form-label" for="code">{{ __('Coupon Code') }} <span class="text-danger">*</span></label>
                        <input type="text" name="code" id="code" value="{{ old('code', $coupon->code ?? '') }}" class="form-control @error('code') is-invalid @enderror" required>
                        @error('code')
                            <div class="invalid-feedback">{{ $message }}</div>
                        @enderror
                    </div>

                    <div class="mb-3">
                        <label class="form-label" for="description">{{ __('Description') }}</label>
                        <textarea name="description" id="description" class="form-control @error('description') is-invalid @enderror" rows="3">{{ old('description', $coupon->description ?? '') }}</textarea>
                        @error('description')
                            <div class="invalid-feedback">{{ $message }}</div>
                        @enderror
                    </div>

                    <div class="mb-3">
                        <label class="form-label" for="type">{{ __('Discount Type') }} <span class="text-danger">*</span></label>
                        <select name="type" id="type" class="form-select @error('type') is-invalid @enderror" required>
                            @foreach($couponTypes as $type)
                                <option value="{{ $type }}" {{ old('type', $coupon->type ?? '') == $type ? 'selected' : '' }}>{{ $type }}</option>
                            @endforeach
                        </select>
                        @error('type')
                            <div class="invalid-feedback">{{ $message }}</div>
                        @enderror
                    </div>

                    <div class="mb-3">
                        <label class="form-label" for="amount">{{ __('Coupon Amount') }} <span class="text-danger">*</span></label>
                        <input type="number" step="0.01" name="amount" id="amount" value="{{ old('amount', $coupon->amount ?? '') }}" class="form-control @error('amount') is-invalid @enderror" required>
                        @error('amount')
                            <div class="invalid-feedback">{{ $message }}</div>
                        @enderror
                    </div>

                    <div class="mb-3">
                        <label class="form-label" for="expire_date">{{ __('Expire Date') }}</label>
                        <input type="datetime-local" name="expire_date" id="expire_date" value="{{ old('expire_date', $coupon->expire_date ? \Carbon\Carbon::parse($coupon->expire_date)->format('Y-m-d\TH:i') : '') }}" class="form-control @error('expire_date') is-invalid @enderror">
                        @error('expire_date')
                            <div class="invalid-feedback">{{ $message }}</div>
                        @enderror
                    </div>

                    <div class="form-check mb-3">
                        <input class="form-check-input" type="checkbox" name="allow_free_shipment" id="allow_free_shipment" value="1" {{ old('allow_free_shipment', $coupon->allow_free_shipment ?? false) ? 'checked' : '' }}>
                        <label class="form-check-label" for="allow_free_shipment">
                            {{ __('Allow Free Shipment') }}
                        </label>
                    </div>
                </div>
            </div>
        </div>

        {{-- Usage Restriction --}}
        <div class="col-md-6">
            <div class="card mb-3">
                <div class="card-header">
                    {{ __('Usage Restriction') }}
                </div>
                <div class="card-body">
                    <div class="mb-3">
                        <label class="form-label" for="minimum_spend">{{ __('Minimum Spend') }}</label>
                        <input type="number" step="0.01" name="minimum_spend" id="minimum_spend" value="{{ old('minimum_spend', $coupon->minimum_spend ?? '') }}" class="form-control @error('minimum_spend') is-invalid @enderror">
                        @error('minimum_spend')
                            <div class="invalid-feedback">{{ $message }}</div>
                        @enderror
                    </div>

                    <div class="mb-3">
                        <label class="form-label" for="maximum_spend">{{ __('Maximum Spend') }}</label>
                        <input type="number" step="0.01" name="maximum_spend" id="maximum_spend" value="{{ old('maximum_spend', $coupon->maximum_spend ?? '') }}" class="form-control @error('maximum_spend') is-invalid @enderror">
                        @error('maximum_spend')
                            <div class="invalid-feedback">{{ $message }}</div>
                        @enderror
                    </div>
                     <div class="mb-3">
                        <label class="form-label" for="max_discount">{{ __('Maximum Discount (for percentage type)') }}</label>
                        <input type="number" step="0.01" name="max_discount" id="max_discount" value="{{ old('max_discount', $coupon->max_discount ?? '') }}" class="form-control @error('max_discount') is-invalid @enderror">
                        @error('max_discount')
                            <div class="invalid-feedback">{{ $message }}</div>
                        @enderror
                    </div>

                    <div class="form-check mb-3">
                        <input class="form-check-input" type="checkbox" name="individual_use_only" id="individual_use_only" value="1" {{ old('individual_use_only', $coupon->individual_use_only ?? false) ? 'checked' : '' }}>
                        <label class="form-check-label" for="individual_use_only">
                            {{ __('Individual Use Only') }}
                        </label>
                    </div>

                    <div class="form-check mb-3">
                        <input class="form-check-input" type="checkbox" name="exclude_sale_items" id="exclude_sale_items" value="1" {{ old('exclude_sale_items', $coupon->exclude_sale_items ?? false) ? 'checked' : '' }}>
                        <label class="form-check-label" for="exclude_sale_items">
                            {{ __('Exclude Sale Items') }}
                        </label>
                    </div>

                    {{-- For simplicity, using textareas for JSON fields. Consider using select2 or similar for better UX --}}
                    <div class="mb-3">
                        <label class="form-label" for="products">{{ __('Products (comma-separated IDs)') }}</label>
                        <textarea name="products_text" id="products" class="form-control @error('products') is-invalid @enderror" rows="2">{{ old('products_text', $coupon && is_array($coupon->products) ? implode(',', $coupon->products) : '') }}</textarea>
                        @error('products') <div class="invalid-feedback">{{ $message }}</div> @enderror
                    </div>
                    <div class="mb-3">
                        <label class="form-label" for="exclude_products">{{ __('Exclude Products (comma-separated IDs)') }}</label>
                        <textarea name="exclude_products_text" id="exclude_products" class="form-control @error('exclude_products') is-invalid @enderror" rows="2">{{ old('exclude_products_text', $coupon && is_array($coupon->exclude_products) ? implode(',', $coupon->exclude_products) : '') }}</textarea>
                        @error('exclude_products') <div class="invalid-feedback">{{ $message }}</div> @enderror
                    </div>
                    <div class="mb-3">
                        <label class="form-label" for="product_categories">{{ __('Product Categories (comma-separated IDs)') }}</label>
                        <textarea name="product_categories_text" id="product_categories" class="form-control @error('product_categories') is-invalid @enderror" rows="2">{{ old('product_categories_text', $coupon && is_array($coupon->product_categories) ? implode(',', $coupon->product_categories) : '') }}</textarea>
                        @error('product_categories') <div class="invalid-feedback">{{ $message }}</div> @enderror
                    </div>
                    <div class="mb-3">
                        <label class="form-label" for="exclude_categories">{{ __('Exclude Categories (comma-separated IDs)') }}</label>
                        <textarea name="exclude_categories_text" id="exclude_categories" class="form-control @error('exclude_categories') is-invalid @enderror" rows="2">{{ old('exclude_categories_text', $coupon && is_array($coupon->exclude_categories) ? implode(',', $coupon->exclude_categories) : '') }}</textarea>
                        @error('exclude_categories') <div class="invalid-feedback">{{ $message }}</div> @enderror
                    </div>
                    <div class="mb-3">
                        <label class="form-label" for="allowed_emails">{{ __('Allowed Emails (comma-separated)') }}</label>
                        <textarea name="allowed_emails_text" id="allowed_emails" class="form-control @error('allowed_emails') is-invalid @enderror" rows="2">{{ old('allowed_emails_text', $coupon && is_array($coupon->allowed_emails) ? implode(',', $coupon->allowed_emails) : '') }}</textarea>
                        @error('allowed_emails') <div class="invalid-feedback">{{ $message }}</div> @enderror
                    </div>
                </div>
            </div>
        </div>
    </div>

    <div class="row">
        {{-- Usage Limits --}}
        <div class="col-md-12">
            <div class="card mb-3">
                <div class="card-header">
                    {{ __('Usage Limits') }}
                </div>
                <div class="card-body">
                    <div class="row">
                        <div class="col-md-4 mb-3">
                            <label class="form-label" for="usage_limit">{{ __('Usage Limit Per Coupon') }}</label>
                            <input type="number" name="usage_limit" id="usage_limit" value="{{ old('usage_limit', $coupon->usage_limit ?? '') }}" class="form-control @error('usage_limit') is-invalid @enderror">
                            @error('usage_limit')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>

                        <div class="col-md-4 mb-3">
                            <label class="form-label" for="product_limit">{{ __('Limit Usage To X Items') }}</label>
                            <input type="number" name="product_limit" id="product_limit" value="{{ old('product_limit', $coupon->product_limit ?? '') }}" class="form-control @error('product_limit') is-invalid @enderror">
                            @error('product_limit')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>

                        <div class="col-md-4 mb-3">
                            <label class="form-label" for="usage_limit_per_user">{{ __('Usage Limit Per User') }}</label>
                            <input type="number" name="usage_limit_per_user" id="usage_limit_per_user" value="{{ old('usage_limit_per_user', $coupon->usage_limit_per_user ?? '') }}" class="form-control @error('usage_limit_per_user') is-invalid @enderror">
                            @error('usage_limit_per_user')
                                <div class="invalid-feedback">{{ $message }}</div>
                            @enderror
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <button type="submit" class="btn btn-primary">{{ $isEdit ? __('Update Coupon') : __('Create Coupon') }}</button>
    <a href="{{ route('admin.coupons.index') }}" class="btn btn-secondary">{{ __('Cancel') }}</a>
</form>
````

Now, update the `CouponController`:

````php
_projects\Laravel\e-commerce-v2\app\Http\Controllers\Admin\CouponController.php
<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Coupon;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;

class CouponController extends Controller
{
    private function processJsonInput(Request $request, array $fields): array
    {
        $data = [];
        foreach ($fields as $field) {
            $textField = $field . '_text';
            if ($request->filled($textField)) {
                $data[$field] = array_map('trim', explode(',', $request->input($textField)));
            } else {
                $data[$field] = null; // or [] depending on desired default
            }
        }
        return $data;
    }

    private function getValidationRules($couponId = null): array
    {
        return [
            'code' => ['required', 'string', 'max:255', Rule::unique('coupons')->ignore($couponId)],
            'description' => ['nullable', 'string'],
            'type' => ['required', Rule::in(Coupon::TYPES)],
            'amount' => ['required', 'numeric', 'min:0'],
            'allow_free_shipment' => ['nullable', 'boolean'],
            'expire_date' => ['nullable', 'date'],
            'max_discount' => ['nullable', 'numeric', 'min:0'],
            'minimum_spend' => ['nullable', 'numeric', 'min:0'],
            'maximum_spend' => ['nullable', 'numeric', 'min:0', 'gte:minimum_spend'],
            'individual_use_only' => ['nullable', 'boolean'],
            'exclude_sale_items' => ['nullable', 'boolean'],
            'products_text' => ['nullable', 'string'],
            'exclude_products_text' => ['nullable', 'string'],
            'product_categories_text' => ['nullable', 'string'],
            'exclude_categories_text' => ['nullable', 'string'],
            'allowed_emails_text' => ['nullable', 'string'],
            'usage_limit' => ['nullable', 'integer', 'min:0'],
            'product_limit' => ['nullable', 'integer', 'min:0'],
            'usage_limit_per_user' => ['nullable', 'integer', 'min:0'],
        ];
    }

    public function index()
    {
        $coupons = Coupon::latest()->paginate(15);
        return view('pages.admin.coupon.index', compact('coupons'));
    }

    public function create()
    {
        return view('pages.admin.coupon.create');
    }

    public function store(Request $request)
    {
        $validatedData = $request->validate($this->getValidationRules());

        $jsonFieldsData = $this->processJsonInput($request, [
            'products', 'exclude_products', 'product_categories', 'exclude_categories', 'allowed_emails'
        ]);

        $couponData = array_merge(
            $request->except(['_token', '_method', 'products_text', 'exclude_products_text', 'product_categories_text', 'exclude_categories_text', 'allowed_emails_text']),
            $jsonFieldsData
        );
        
        $couponData['allow_free_shipment'] = $request->has('allow_free_shipment');
        $couponData['individual_use_only'] = $request->has('individual_use_only');
        $couponData['exclude_sale_items'] = $request->has('exclude_sale_items');


        Coupon::create($couponData);

        return redirect()->route('admin.coupons.index')->with('success', __('Coupon created successfully.'));
    }

    public function show(Coupon $coupon)
    {
        return view('pages.admin.coupon.show', compact('coupon'));
    }

    public function edit(Coupon $coupon)
    {
        return view('pages.admin.coupon.edit', compact('coupon'));
    }

    public function update(Request $request, Coupon $coupon)
    {
        $validatedData = $request->validate($this->getValidationRules($coupon->id));
        
        $jsonFieldsData = $this->processJsonInput($request, [
            'products', 'exclude_products', 'product_categories', 'exclude_categories', 'allowed_emails'
        ]);

        $couponData = array_merge(
            $request->except(['_token', '_method', 'products_text', 'exclude_products_text', 'product_categories_text', 'exclude_categories_text', 'allowed_emails_text']),
            $jsonFieldsData
        );

        $couponData['allow_free_shipment'] = $request->has('allow_free_shipment');
        $couponData['individual_use_only'] = $request->has('individual_use_only');
        $couponData['exclude_sale_items'] = $request->has('exclude_sale_items');

        $coupon->update($couponData);

        return redirect()->route('admin.coupons.index')->with('success', __('Coupon updated successfully.'));
    }

    public function destroy(Coupon $coupon)
    {
        $coupon->delete();
        return redirect()->route('admin.coupons.index')->with('success', __('Coupon deleted successfully.'));
    }
}
````

Now, the view files:

**index.blade.php**
````php
@extends('layouts.syndron.app')

@section('content')
    <div class="card">
        <div class="card-header d-flex justify-content-between align-items-center">
            <h4>{{ __('Coupons') }}</h4>
            <a class="btn btn-success" href="{{ route('admin.coupons.create') }}">
                <i class="fas fa-plus"></i> {{ __('Create New Coupon') }}
            </a>
        </div>

        <div class="card-body">
            @if(session('success'))
                <div class="alert alert-success" role="alert">
                    {{ session('success') }}
                </div>
            @endif

            <x-syndron.ui.table :columns="[__('Code'), __('Type'), __('Amount'), __('Expire Date'), __('Usage Limit'), __('Actions')]">
                @forelse ($coupons as $coupon)
                    <tr>
                        <td>{{ $coupon->code }}</td>
                        <td>{{ $coupon->type }}</td>
                        <td>
                            @if($coupon->type === 'Percentage Discount')
                                {{ $coupon->amount }}%
                            @else
                                {{-- Format as currency if you have a helper, otherwise just the number --}}
                                {{ number_format($coupon->amount, 2) }}
                            @endif
                        </td>
                        <td>{{ $coupon->expire_date ? $coupon->expire_date->format('Y-m-d H:i') : __('N/A') }}</td>
                        <td>{{ $coupon->usage_limit ?? __('Unlimited') }}</td>
                        <td>
                            <div class="dropdown">
                                <button class="btn btn-secondary btn-sm dropdown-toggle" type="button" id="dropdownMenuButton{{ $coupon->id }}" data-bs-toggle="dropdown" aria-expanded="false">
                                    {{ __('Actions') }}
                                </button>
                                <ul class="dropdown-menu" aria-labelledby="dropdownMenuButton{{ $coupon->id }}">
                                    <li>
                                        <a class="dropdown-item" href="{{ route('admin.coupons.edit', $coupon->id) }}">
                                            <i class="fas fa-edit"></i> {{ __('Edit') }}
                                        </a>
                                    </li>
                                    <li>
                                        <form action="{{ route('admin.coupons.destroy', $coupon->id) }}" method="POST" onsubmit="return confirm('{{ __('Are you sure you want to delete this coupon?') }}');" style="display: inline;">
                                            @csrf
                                            @method('DELETE')
                                            <button class="dropdown-item text-danger" type="submit">
                                                <i class="fas fa-trash"></i> {{ __('Delete') }}
                                            </button>
                                        </form>
                                    </li>
                                </ul>
                            </div>
                        </td>
                    </tr>
                @empty
                    <tr>
                        <td colspan="6" class="text-center">{{ __('No coupons found.') }}</td>
                    </tr>
                @endforelse
            </x-syndron.ui.table>

            @if ($coupons->hasPages())
                <div class="mt-3">
                    {{ $coupons->links() }}
                </div>
            @endif
        </div>
    </div>
@endsection
````

**create.blade.php**
````php
@extends('layouts.syndron.app')

@section('content')
    <div class="card">
        <div class="card-header">
            <h4>{{ __('Create New Coupon') }}</h4>
        </div>
        <div class="card-body">
            <x-syndron.form.coupon-form />
        </div>
    </div>
@endsection
````

**edit.blade.php**
````php
@extends('layouts.syndron.app')

@section('content')
    <div class="card">
        <div class="card-header">
            <h4>{{ __('Edit Coupon') }}: {{ $coupon->code }}</h4>
        </div>
        <div class="card-body">
            <x-syndron.form.coupon-form :coupon="$coupon" />
        </div>
    </div>
@endsection
````

Finally, make sure you have the routes defined, likely in your `routes/admin.php` or web.php file, grouped under an admin prefix and middleware.

Example for web.php (adjust as per your project structure):
````php
// ...existing code...
use App\Http\Controllers\Admin\CouponController;

Route::middleware(['auth', /* other admin middlewares */])->prefix('admin')->name('admin.')->group(function () {
    // ... other admin routes
    Route::resource('coupons', CouponController::class);
});
// ...existing code...
````
Remember to run `php artisan migrate` if you haven't already after updating the migration file. You might need `php artisan migrate:fresh --seed` if you are redoing the table and have test data.

This setup provides a comprehensive CRUD for coupons, using a reusable form component and an index page similar to your roles management. The JSON fields are handled as comma-separated text in the form for simplicity, then processed into arrays in the controller.

Similar code found with 3 license types
