# DataTables Quick Reference Guide

## How to Add DataTables to a New Module

### Step 1: Update Controller

Add the `data()` method to your controller:

```php
<?php

namespace App\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use App\Models\YourModel;
use Illuminate\Http\Request;
use Yajra\DataTables\Facades\DataTables;

class YourController extends Controller
{
    public function index()
    {
        // Remove pagination, pass only needed data
        $relatedData = RelatedModel::active()->get();
        return view('your-module.index', compact('relatedData'));
    }

    public function data(Request $request)
    {
        $query = YourModel::with(['relations']) // Include eager loading
            ->orderBy('date_field', 'desc');      // Default sort

        return DataTables::of($query)
            // Format columns for display
            ->addColumn('column_name', function ($row) {
                return $row->field;
            })
            ->addColumn('formatted_date', function ($row) {
                return $row->date->format('d/m/Y');
            })
            ->addColumn('badge', function ($row) {
                $color = $row->status == 'active' ? 'success' : 'danger';
                return '<span class="badge badge-' . $color . '">' .
                       strtoupper($row->status) . '</span>';
            })
            ->rawColumns(['badge'])  // Allow HTML in these columns
            ->make(true);
    }
}
```

### Step 2: Update View

Replace your static table with DataTables:

```blade
@extends('layouts.app_pwa')

@section('title', 'Your Module')

@section('header-title', 'Your Module')

@section('content')
<!-- Your buttons and stats here -->

<div class="card">
    <div class="card-header">
        <h2 class="card-title">Your Table Title</h2>
    </div>
    <div class="card-body">
        <!-- DataTables table structure -->
        <table id="yourTable" class="table table-striped table-bordered" style="width:100%">
            <thead>
                <tr>
                    <th>Column 1</th>
                    <th>Column 2</th>
                    <th>Column 3</th>
                </tr>
            </thead>
        </table>
    </div>
</div>

<!-- Your modal form here -->

@push('scripts')
<script>
$(document).ready(function() {
    $('#yourTable').DataTable({
        processing: true,
        serverSide: true,
        responsive: true,
        dom: 'Bfrtip',
        buttons: [
            'copy',
            'csv',
            'excel',
            'pdf',
            'print'
        ],
        ajax: {
            url: '{{ route('your-module.data') }}',
            type: 'GET',
            data: function(d) {
                d._token = '{{ csrf_token() }}';
            }
        },
        columns: [
            { data: 'column_name', name: 'db_column' },
            { data: 'formatted_date', name: 'date_field' },
            { data: 'badge', name: 'status', orderable: false, searchable: false }
        ],
        order: [[1, 'desc']],  // Default sort by column 2, descending
        language: {
            url: '//cdn.datatables.net/plug-ins/1.13.6/i18n/id.json'
        }
    });
});

// Your existing modal functions here
</script>
@endpush
@endsection
```

### Step 3: Add Route

```php
// routes/web.php
Route::prefix('your-module')->group(function () {
    Route::get('/', [YourController::class, 'index'])->name('your-module.index');
    Route::get('/data', [YourController::class, 'data'])->name('your-module.data');  // Add this
    Route::post('/', [YourController::class, 'store'])->name('your-module.store');
});
```

## Column Formatting Examples

### Date Formatting:
```php
->addColumn('date_format', function ($row) {
    return $row->date->format('d/m/Y');
})
```

### Number Formatting:
```php
->addColumn('amount_format', function ($row) {
    return number_format($row->amount, 2);
})

->addColumn('weight_format', function ($row) {
    return number_format($row->weight, 1) . ' KG';
})
```

### Badges/Labels:
```php
->addColumn('status_badge', function ($row) {
    $status = $row->status;
    $color = match($status) {
        'active' => 'success',
        'pending' => 'warning',
        'inactive' => 'danger',
        default => 'info'
    };
    return '<span class="badge badge-' . $color . '">' .
           strtoupper($status) . '</span>';
})
```

### Conditional Display:
```php
->addColumn('conditional', function ($row) {
    if ($row->value > 100) {
        return '<span style="color: green;">High</span>';
    } elseif ($row->value > 50) {
        return '<span style="color: orange;">Medium</span>';
    } else {
        return '<span style="color: red;">Low</span>';
    }
})
```

### Relations:
```php
->addColumn('related_name', function ($row) {
    return $row->relation->name ?? '-';
})

->addColumn('created_by', function ($row) {
    return $row->createdBy->name ?? '-';
})
```

### Multiple Values Combined:
```php
->addColumn('full_name', function ($row) {
    return $row->first_name . ' ' . $row->last_name;
})

->addColumn('address', function ($row) {
    return $row->city . ', ' . $row->province;
})
```

### Links/Actions:
```php
->addColumn('actions', function ($row) {
    return '
        <a href="/module/' . $row->id . '" class="btn btn-sm btn-primary">View</a>
        <button onclick="edit(' . $row->id . ')" class="btn btn-sm btn-warning">Edit</button>
        <button onclick="delete(' . $row->id . ')" class="btn btn-sm btn-danger">Delete</button>
    ';
})
```

## DataTables Configuration Options

### Basic Options:
```javascript
{
    processing: true,           // Show "Processing..." indicator
    serverSide: true,           // Enable server-side processing
    responsive: true,           // Enable responsive design
    stateSave: true,           // Save table state (pagination, sort)
    autoWidth: false,          // Disable automatic column width
}
```

### Buttons:
```javascript
{
    dom: 'Bfrtip',
    buttons: [
        'copy',      // Copy to clipboard
        'csv',       // Export to CSV
        'excel',     // Export to Excel
        'pdf',       // Export to PDF
        'print',     // Print view
        {
            text: 'Custom Button',
            action: function(e, dt, node, config) {
                // Custom action
            }
        }
    ]
}
```

### Pagination:
```javascript
{
    lengthMenu: [10, 25, 50, 100],     // Page size options
    pageLength: 25,                    // Default page size
    pagingType: 'full_numbers',        // Pagination style
}
```

### Ordering/Sorting:
```javascript
{
    order: [[0, 'desc']],              // Initial sort
    orderMulti: true,                  // Multi-column sorting
    columnDefs: [
        { orderable: false, targets: [0, 5] }  // Disable sorting on columns
    ]
}
```

### Search/Filter:
```javascript
{
    searching: true,                  // Enable search
    searchDelay: 500,                 // Delay before search
    regex: true,                      // Enable regex search
}
```

### Language:
```javascript
{
    language: {
        url: '//cdn.datatables.net/plug-ins/1.13.6/i18n/id.json'  // Indonesian
    }
    // Or custom language
    language: {
        search: "Cari:",
        lengthMenu: "Tampil _MENU_ data",
        info: "Menampilkan _START_ sampai _END_ dari _TOTAL_ data",
        paginate: {
            first: "Pertama",
            last: "Terakhir",
            next: "Selanjutnya",
            previous: "Sebelumnya"
        }
    }
}
```

### Column Definitions:
```javascript
{
    columns: [
        {
            data: 'field',
            name: 'db_column',
            orderable: true,
            searchable: true,
            visible: true,
            render: function(data, type, row) {
                return '<strong>' + data + '</strong>';
            }
        }
    ]
}
```

## Common Issues & Solutions

### Issue: "DataTables warning: table id=X - Invalid JSON response"
**Cause:** Server returning HTML instead of JSON
**Solution:**
- Check controller is returning `->make(true)`
- Verify route doesn't have web middleware conflict
- Check for PHP errors in response

### Issue: "CSRF token mismatch"
**Solution:**
```javascript
ajax: {
    url: '{{ route('data') }}',
    data: function(d) {
        d._token = '{{ csrf_token() }}';  // Add this
    }
}
```

### Issue: Columns not sorting
**Solution:**
```javascript
// In column definition
{ data: 'field', name: 'db_column', orderable: true }

// In controller, make sure column is added
->addColumn('field', function ($row) {
    return $row->field;
})
```

### Issue: Badges showing HTML as text
**Solution:**
```php
// In controller, add rawColumns
->rawColumns(['badge', 'actions'])
```

### Issue: Relations not loading (N+1 query problem)
**Solution:**
```php
// Use eager loading
$query = Model::with(['relation1', 'relation2']);
```

### Issue: Slow performance with large datasets
**Solutions:**
1. Add database indexes
2. Select only needed columns
3. Use eager loading
4. Enable query cache
5. Increase pagination size limits

## Performance Tips

### 1. Database Indexes:
```sql
ALTER TABLE your_table ADD INDEX idx_date (date_column);
ALTER TABLE your_table ADD INDEX idx_status (status_column);
```

### 2. Optimize Queries:
```php
// Bad - loads all columns
Model::all();

// Good - selects only needed columns
Model::select('id', 'name', 'date')->get();

// Better - with pagination and limits
Model::select('id', 'name', 'date')
    ->where('status', 'active')
    ->limit(100)
    ->get();
```

### 3. Eager Loading:
```php
// Bad - N+1 queries
$items = Model::all();
foreach ($items as $item) {
    echo $item->relation->name;  // Separate query for each
}

// Good - Single query with joins
$items = Model::with('relation')->get();
foreach ($items as $item) {
    echo $item->relation->name;  // No additional queries
}
```

### 4. Query Caching:
```bash
php artisan config:cache
php artisan route:cache
```

## Testing DataTables

### Manual Testing Checklist:
- [ ] Table loads with data
- [ ] Pagination works
- [ ] Column sorting works
- [ ] Search functionality works
- [ ] Export buttons work (Copy, CSV, Excel, PDF, Print)
- [ ] Responsive design on mobile
- [ ] No JavaScript errors in console
- [ ] Fast loading time (< 2 seconds)
- [ ] AJAX requests complete successfully

### Performance Testing:
```bash
# Create test data (1000+ records)
php artisan tinker
>>> for($i = 0; $i < 1000; $i++) {
...     Model::create([...]);
... }

# Test with browser DevTools
# 1. Open Network tab
# 2. Reload page
# 3. Check /data endpoint response time
# Should be < 500ms for good performance
```

## Advanced Features

### Custom AJAX Parameters:
```javascript
ajax: {
    url: '/data',
    type: 'POST',
    data: function(d) {
        d.custom_param = 'value';
        d.dates = $('#date_range').val();
    }
}
```

### Custom Rendering:
```javascript
columnDefs: [{
    targets: 0,
    render: function(data, type, row) {
        return '<a href="/view/' + row.id + '">' + data + '</a>';
    }
}]
```

### Row Callback:
```javascript
rowCallback: function(row, data, index) {
    if (data.status == 'urgent') {
        $(row).addClass('urgent-row');
    }
}
```

### Footer Callback:
```javascript
footerCallback: function(row, data, start, end, display) {
    var api = this.api();
    var total = api.column(3).data().reduce(function(a, b) {
        return a + b;
    }, 0);
    $(api.column(3).footer()).html('Total: ' + total);
}
```

### Init Complete:
```javascript
initComplete: function() {
    this.api().columns().every(function() {
        var column = this;
        // Add custom filter to each column
    });
}
```

## Resources

### Documentation:
- [DataTables Documentation](https://datatables.net/)
- [Laravel DataTables](https://yajrabox.com/docs/laravel-datatables)
- [DataTables Examples](https://datatables.net/examples/)

### Language Packs:
- [Indonesian](https://cdn.datatables.net/plug-ins/1.13.6/i18n/id.json)
- [All Languages](https://datatables.net/plug-ins/i18n/)

### Plugins:
- [Buttons](https://datatables.net/extensions/buttons/)
- [Responsive](https://datatables.net/extensions/responsive/)
- [Select](https://datatables.net/extensions/select/)
- [Editor](https://datatables.net/extensions/editor/)

---

**Quick Tips:**
- Always use `serverSide: true` for datasets > 1000 records
- Use `orderable: false` for action columns
- Use `searchable: false` for calculated columns
- Always include `->rawColumns()` for HTML content
- Use eager loading to prevent N+1 queries
- Add database indexes for frequently searched/sorted columns
- Test with realistic data volumes

**Need Help?**
- Check browser console for JavaScript errors
- Check Network tab for AJAX errors
- Check Laravel logs: `tail -f storage/logs/laravel.log`
- Verify routes: `php artisan route:list | grep data`
