Add CLAUDE.md - AI agent instructions for module development
Created comprehensive anti-hallucination documentation: - EXACT file templates with full code examples - Precise naming conventions (PascalCase, snake_case, kebab-case) - Step-by-step module creation checklist - Common mistakes to avoid section - Filament form/table component reference - Debugging commands and troubleshooting - Updated AI_CONTEXT.md and README.md to reference CLAUDE.md
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
# AI Assistant Context
|
||||
|
||||
> **🚨 CRITICAL: For detailed module development instructions, see [CLAUDE.md](CLAUDE.md)**
|
||||
> That document contains EXACT file templates, naming conventions, and step-by-step instructions.
|
||||
|
||||
This document provides context for AI coding assistants working on projects built with this template.
|
||||
|
||||
## Template Overview
|
||||
@@ -331,6 +334,7 @@ make restore file=... # Restore database
|
||||
|
||||
## Documentation Links
|
||||
|
||||
- **[CLAUDE.md](CLAUDE.md)** - 🚨 **AI AGENTS: START HERE** - Exact module templates
|
||||
- [GETTING_STARTED.md](GETTING_STARTED.md) - Setup walkthrough
|
||||
- [README.md](README.md) - Overview
|
||||
- [docs/modules.md](docs/modules.md) - Module system
|
||||
|
||||
779
CLAUDE.md
Normal file
779
CLAUDE.md
Normal file
@@ -0,0 +1,779 @@
|
||||
# AI Agent Instructions for Laravel Module Development
|
||||
|
||||
> **CRITICAL**: This document provides EXACT specifications for building modules in this Laravel template.
|
||||
> Follow these instructions PRECISELY. Do NOT deviate, guess, or improvise.
|
||||
> When in doubt, READ THE EXISTING CODE before making changes.
|
||||
|
||||
---
|
||||
|
||||
## 🚨 BEFORE YOU START - MANDATORY STEPS
|
||||
|
||||
### 1. Always Check Existing Patterns First
|
||||
```bash
|
||||
# List existing modules to see patterns
|
||||
ls -la src/app/Modules/
|
||||
|
||||
# Read an existing module's structure
|
||||
find src/app/Modules/[ExistingModule]/ -type f -name "*.php"
|
||||
```
|
||||
|
||||
### 2. Always Check Logs After Errors
|
||||
```bash
|
||||
docker-compose exec app tail -n 100 storage/logs/laravel.log
|
||||
```
|
||||
|
||||
### 3. Never Guess at Solutions
|
||||
- If you encounter an error, READ the full stack trace
|
||||
- Find the EXACT file and line number causing the issue
|
||||
- Understand what the code is trying to do before fixing
|
||||
|
||||
---
|
||||
|
||||
## 📁 PROJECT STRUCTURE - EXACT PATHS
|
||||
|
||||
```
|
||||
Laravel-Docker-Dev-Template/
|
||||
├── src/ # ← ALL Laravel code goes here
|
||||
│ ├── app/
|
||||
│ │ ├── Filament/
|
||||
│ │ │ ├── Pages/
|
||||
│ │ │ │ └── Settings.php # Site settings page
|
||||
│ │ │ └── Resources/ # Core Filament resources
|
||||
│ │ │ ├── UserResource.php
|
||||
│ │ │ ├── RoleResource.php
|
||||
│ │ │ └── PermissionResource.php
|
||||
│ │ ├── Http/
|
||||
│ │ │ ├── Controllers/
|
||||
│ │ │ └── Middleware/
|
||||
│ │ ├── Models/
|
||||
│ │ │ ├── User.php
|
||||
│ │ │ └── Setting.php
|
||||
│ │ ├── Modules/ # ← ALL modules go here
|
||||
│ │ │ └── [ModuleName]/ # ← Each module is a folder
|
||||
│ │ ├── Providers/
|
||||
│ │ │ └── AppServiceProvider.php
|
||||
│ │ └── Traits/
|
||||
│ │ └── ModuleAuditable.php
|
||||
│ ├── bootstrap/
|
||||
│ │ └── app.php # Middleware registration
|
||||
│ ├── config/
|
||||
│ ├── database/
|
||||
│ │ ├── migrations/
|
||||
│ │ └── seeders/
|
||||
│ │ ├── DatabaseSeeder.php
|
||||
│ │ └── RolePermissionSeeder.php
|
||||
│ ├── resources/
|
||||
│ │ └── views/
|
||||
│ │ ├── layouts/
|
||||
│ │ │ ├── app.blade.php # Authenticated layout
|
||||
│ │ │ └── guest.blade.php # Guest layout
|
||||
│ │ └── components/
|
||||
│ └── routes/
|
||||
│ ├── web.php
|
||||
│ ├── api.php
|
||||
│ └── auth.php
|
||||
├── docker-compose.yml
|
||||
├── setup.bat # Windows setup
|
||||
└── setup.sh # Linux/Mac setup
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 MODULE STRUCTURE - EXACT SPECIFICATION
|
||||
|
||||
When creating a module named `[ModuleName]` (e.g., `StockManagement`):
|
||||
|
||||
```
|
||||
src/app/Modules/[ModuleName]/
|
||||
├── Config/
|
||||
│ └── [module_name].php # snake_case filename
|
||||
├── Database/
|
||||
│ ├── Migrations/
|
||||
│ │ └── YYYY_MM_DD_HHMMSS_create_[table_name]_table.php
|
||||
│ └── Seeders/
|
||||
│ └── [ModuleName]Seeder.php
|
||||
├── Filament/
|
||||
│ └── Resources/
|
||||
│ ├── [ModelName]Resource.php
|
||||
│ └── [ModelName]Resource/
|
||||
│ └── Pages/
|
||||
│ ├── List[ModelName]s.php
|
||||
│ ├── Create[ModelName].php
|
||||
│ └── Edit[ModelName].php
|
||||
├── Http/
|
||||
│ ├── Controllers/
|
||||
│ │ └── [ModuleName]Controller.php
|
||||
│ ├── Middleware/
|
||||
│ └── Requests/
|
||||
│ └── [ModelName]Request.php
|
||||
├── Models/
|
||||
│ └── [ModelName].php
|
||||
├── Policies/
|
||||
│ └── [ModelName]Policy.php
|
||||
├── Services/
|
||||
│ └── [ModelName]Service.php
|
||||
├── Routes/
|
||||
│ ├── web.php
|
||||
│ └── api.php
|
||||
├── Resources/
|
||||
│ └── views/
|
||||
│ ├── index.blade.php
|
||||
│ └── layouts/
|
||||
│ └── module.blade.php
|
||||
├── Permissions.php
|
||||
└── [ModuleName]ServiceProvider.php
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 EXACT FILE TEMPLATES
|
||||
|
||||
### 1. Service Provider (REQUIRED)
|
||||
|
||||
**File**: `src/app/Modules/[ModuleName]/[ModuleName]ServiceProvider.php`
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Modules\[ModuleName];
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
class [ModuleName]ServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function register(): void
|
||||
{
|
||||
$this->mergeConfigFrom(
|
||||
__DIR__ . '/Config/[module_name].php',
|
||||
'[module_name]'
|
||||
);
|
||||
}
|
||||
|
||||
public function boot(): void
|
||||
{
|
||||
$this->loadMigrationsFrom(__DIR__ . '/Database/Migrations');
|
||||
$this->loadViewsFrom(__DIR__ . '/Resources/views', '[module-slug]');
|
||||
|
||||
$this->registerRoutes();
|
||||
}
|
||||
|
||||
protected function registerRoutes(): void
|
||||
{
|
||||
Route::middleware(['web', 'auth'])
|
||||
->prefix('[module-slug]')
|
||||
->name('[module-slug].')
|
||||
->group(__DIR__ . '/Routes/web.php');
|
||||
|
||||
if (file_exists(__DIR__ . '/Routes/api.php')) {
|
||||
Route::middleware(['api', 'auth:sanctum'])
|
||||
->prefix('api/[module-slug]')
|
||||
->name('api.[module-slug].')
|
||||
->group(__DIR__ . '/Routes/api.php');
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**NAMING RULES**:
|
||||
- `[ModuleName]` = PascalCase (e.g., `StockManagement`)
|
||||
- `[module_name]` = snake_case (e.g., `stock_management`)
|
||||
- `[module-slug]` = kebab-case (e.g., `stock-management`)
|
||||
|
||||
### 2. Config File (REQUIRED)
|
||||
|
||||
**File**: `src/app/Modules/[ModuleName]/Config/[module_name].php`
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
return [
|
||||
'name' => '[Module Display Name]',
|
||||
'slug' => '[module-slug]',
|
||||
'version' => '1.0.0',
|
||||
|
||||
'audit' => [
|
||||
'enabled' => true,
|
||||
'strategy' => 'all', // 'all', 'include', 'exclude', 'none'
|
||||
'include' => [],
|
||||
'exclude' => [],
|
||||
],
|
||||
];
|
||||
```
|
||||
|
||||
### 3. Model (REQUIRED for data modules)
|
||||
|
||||
**File**: `src/app/Modules/[ModuleName]/Models/[ModelName].php`
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Modules\[ModuleName]\Models;
|
||||
|
||||
use App\Traits\ModuleAuditable;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use OwenIt\Auditing\Contracts\Auditable;
|
||||
|
||||
class [ModelName] extends Model implements Auditable
|
||||
{
|
||||
use HasFactory, ModuleAuditable;
|
||||
|
||||
protected $fillable = [
|
||||
// List ALL fields that can be mass-assigned
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
// Type casts for fields
|
||||
];
|
||||
|
||||
// Define relationships here
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Migration (REQUIRED for data modules)
|
||||
|
||||
**File**: `src/app/Modules/[ModuleName]/Database/Migrations/YYYY_MM_DD_HHMMSS_create_[table_name]_table.php`
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('[table_name]', function (Blueprint $table) {
|
||||
$table->id();
|
||||
// Define ALL columns here
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('[table_name]');
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### 5. Permissions (REQUIRED)
|
||||
|
||||
**File**: `src/app/Modules/[ModuleName]/Permissions.php`
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
return [
|
||||
'[module_name].view' => 'View [Module Name]',
|
||||
'[module_name].create' => 'Create [Module Name] records',
|
||||
'[module_name].edit' => 'Edit [Module Name] records',
|
||||
'[module_name].delete' => 'Delete [Module Name] records',
|
||||
];
|
||||
```
|
||||
|
||||
### 6. Filament Resource (REQUIRED for admin)
|
||||
|
||||
**File**: `src/app/Modules/[ModuleName]/Filament/Resources/[ModelName]Resource.php`
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Modules\[ModuleName]\Filament\Resources;
|
||||
|
||||
use App\Modules\[ModuleName]\Filament\Resources\[ModelName]Resource\Pages;
|
||||
use App\Modules\[ModuleName]\Models\[ModelName];
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class [ModelName]Resource extends Resource
|
||||
{
|
||||
protected static ?string $model = [ModelName]::class;
|
||||
|
||||
protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';
|
||||
|
||||
protected static ?string $navigationGroup = '[Module Display Name]';
|
||||
|
||||
protected static ?int $navigationSort = 1;
|
||||
|
||||
public static function canAccess(): bool
|
||||
{
|
||||
return auth()->user()?->can('[module_name].view') ?? false;
|
||||
}
|
||||
|
||||
public static function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->schema([
|
||||
Forms\Components\Section::make('[Model Name] Details')
|
||||
->schema([
|
||||
// Add form fields here
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
// Add table columns here
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->actions([
|
||||
Tables\Actions\EditAction::make(),
|
||||
Tables\Actions\DeleteAction::make(),
|
||||
])
|
||||
->bulkActions([
|
||||
Tables\Actions\BulkActionGroup::make([
|
||||
Tables\Actions\DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => Pages\List[ModelName]s::route('/'),
|
||||
'create' => Pages\Create[ModelName]::route('/create'),
|
||||
'edit' => Pages\Edit[ModelName]::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 7. Filament Resource Pages (REQUIRED)
|
||||
|
||||
**File**: `src/app/Modules/[ModuleName]/Filament/Resources/[ModelName]Resource/Pages/List[ModelName]s.php`
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Modules\[ModuleName]\Filament\Resources\[ModelName]Resource\Pages;
|
||||
|
||||
use App\Modules\[ModuleName]\Filament\Resources\[ModelName]Resource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
|
||||
class List[ModelName]s extends ListRecords
|
||||
{
|
||||
protected static string $resource = [ModelName]Resource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\CreateAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**File**: `src/app/Modules/[ModuleName]/Filament/Resources/[ModelName]Resource/Pages/Create[ModelName].php`
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Modules\[ModuleName]\Filament\Resources\[ModelName]Resource\Pages;
|
||||
|
||||
use App\Modules\[ModuleName]\Filament\Resources\[ModelName]Resource;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
|
||||
class Create[ModelName] extends CreateRecord
|
||||
{
|
||||
protected static string $resource = [ModelName]Resource::class;
|
||||
}
|
||||
```
|
||||
|
||||
**File**: `src/app/Modules/[ModuleName]/Filament/Resources/[ModelName]Resource/Pages/Edit[ModelName].php`
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Modules\[ModuleName]\Filament\Resources\[ModelName]Resource\Pages;
|
||||
|
||||
use App\Modules\[ModuleName]\Filament\Resources\[ModelName]Resource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
|
||||
class Edit[ModelName] extends EditRecord
|
||||
{
|
||||
protected static string $resource = [ModelName]Resource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\DeleteAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 8. Routes (REQUIRED)
|
||||
|
||||
**File**: `src/app/Modules/[ModuleName]/Routes/web.php`
|
||||
```php
|
||||
<?php
|
||||
|
||||
use App\Modules\[ModuleName]\Http\Controllers\[ModuleName]Controller;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::get('/', [[ModuleName]Controller::class, 'index'])->name('index');
|
||||
```
|
||||
|
||||
**File**: `src/app/Modules/[ModuleName]/Routes/api.php` (if API needed)
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::middleware('auth:sanctum')->group(function () {
|
||||
// API routes here
|
||||
});
|
||||
```
|
||||
|
||||
### 9. Controller (REQUIRED)
|
||||
|
||||
**File**: `src/app/Modules/[ModuleName]/Http/Controllers/[ModuleName]Controller.php`
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Modules\[ModuleName]\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class [ModuleName]Controller extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$this->authorize('[module_name].view');
|
||||
|
||||
return view('[module-slug]::index');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 10. Index View (REQUIRED)
|
||||
|
||||
**File**: `src/app/Modules/[ModuleName]/Resources/views/index.blade.php`
|
||||
```blade
|
||||
<x-app-layout>
|
||||
<x-slot name="header">
|
||||
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
|
||||
{{ __('[Module Display Name]') }}
|
||||
</h2>
|
||||
</x-slot>
|
||||
|
||||
<div class="py-12">
|
||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
||||
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
|
||||
<div class="p-6 text-gray-900 dark:text-gray-100">
|
||||
{{ __('[Module Display Name] content goes here.') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ MODULE REGISTRATION
|
||||
|
||||
After creating all files, register the module in `src/config/app.php` providers array:
|
||||
|
||||
```php
|
||||
'providers' => ServiceProvider::defaultProviders()->merge([
|
||||
// ...existing providers...
|
||||
App\Modules\[ModuleName]\[ModuleName]ServiceProvider::class,
|
||||
])->toArray(),
|
||||
```
|
||||
|
||||
Or add to `src/bootstrap/providers.php`:
|
||||
```php
|
||||
return [
|
||||
App\Providers\AppServiceProvider::class,
|
||||
// ...existing providers...
|
||||
App\Modules\[ModuleName]\[ModuleName]ServiceProvider::class,
|
||||
];
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 AFTER MODULE CREATION - REQUIRED COMMANDS
|
||||
|
||||
```bash
|
||||
# 1. Run migrations
|
||||
docker-compose exec app php artisan migrate
|
||||
|
||||
# 2. Clear all caches
|
||||
docker-compose exec app php artisan optimize:clear
|
||||
|
||||
# 3. Seed permissions (if using permissions)
|
||||
docker-compose exec app php artisan db:seed --class=RolePermissionSeeder
|
||||
|
||||
# 4. Reset permission cache
|
||||
docker-compose exec app php artisan permission:cache-reset
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ COMMON MISTAKES TO AVOID
|
||||
|
||||
### 1. Wrong Namespace
|
||||
❌ `namespace App\Modules\StockManagement\Models;`
|
||||
✅ `namespace App\Modules\StockManagement\Models;`
|
||||
|
||||
The namespace MUST match the folder structure EXACTLY.
|
||||
|
||||
### 2. Wrong View Namespace
|
||||
❌ `return view('stockmanagement::index');`
|
||||
❌ `return view('StockManagement::index');`
|
||||
✅ `return view('stock-management::index');`
|
||||
|
||||
View namespace is ALWAYS kebab-case.
|
||||
|
||||
### 3. Wrong Permission Names
|
||||
❌ `'StockManagement.view'`
|
||||
❌ `'stock-management.view'`
|
||||
✅ `'stock_management.view'`
|
||||
|
||||
Permissions are ALWAYS snake_case.
|
||||
|
||||
### 4. Forgetting to Register Provider
|
||||
The module WILL NOT LOAD if you forget to add its ServiceProvider.
|
||||
|
||||
### 5. Wrong Import Paths
|
||||
❌ `use App\Models\Product;`
|
||||
✅ `use App\Modules\StockManagement\Models\Product;`
|
||||
|
||||
Module models are in the MODULE namespace, not the core App namespace.
|
||||
|
||||
### 6. Missing Fillable Array
|
||||
❌ Empty `$fillable` array causes mass-assignment errors
|
||||
✅ List ALL fields that should be mass-assignable
|
||||
|
||||
### 7. Forgetting to Run Migrations
|
||||
Always run `php artisan migrate` after creating migrations.
|
||||
|
||||
---
|
||||
|
||||
## 🎨 FILAMENT FORM FIELD REFERENCE
|
||||
|
||||
```php
|
||||
// Text
|
||||
Forms\Components\TextInput::make('name')
|
||||
->required()
|
||||
->maxLength(255);
|
||||
|
||||
// Email
|
||||
Forms\Components\TextInput::make('email')
|
||||
->email()
|
||||
->required();
|
||||
|
||||
// Password
|
||||
Forms\Components\TextInput::make('password')
|
||||
->password()
|
||||
->required();
|
||||
|
||||
// Textarea
|
||||
Forms\Components\Textarea::make('description')
|
||||
->rows(3);
|
||||
|
||||
// Select
|
||||
Forms\Components\Select::make('status')
|
||||
->options([
|
||||
'active' => 'Active',
|
||||
'inactive' => 'Inactive',
|
||||
])
|
||||
->required();
|
||||
|
||||
// Checkbox
|
||||
Forms\Components\Toggle::make('is_active')
|
||||
->default(true);
|
||||
|
||||
// Date
|
||||
Forms\Components\DatePicker::make('date');
|
||||
|
||||
// DateTime
|
||||
Forms\Components\DateTimePicker::make('published_at');
|
||||
|
||||
// Number
|
||||
Forms\Components\TextInput::make('price')
|
||||
->numeric()
|
||||
->prefix('$');
|
||||
|
||||
// File Upload
|
||||
Forms\Components\FileUpload::make('image')
|
||||
->image()
|
||||
->directory('uploads');
|
||||
|
||||
// Relationship Select
|
||||
Forms\Components\Select::make('category_id')
|
||||
->relationship('category', 'name')
|
||||
->searchable()
|
||||
->preload();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 FILAMENT TABLE COLUMN REFERENCE
|
||||
|
||||
```php
|
||||
// Text
|
||||
Tables\Columns\TextColumn::make('name')
|
||||
->searchable()
|
||||
->sortable();
|
||||
|
||||
// Badge
|
||||
Tables\Columns\TextColumn::make('status')
|
||||
->badge()
|
||||
->color(fn (string $state): string => match ($state) {
|
||||
'active' => 'success',
|
||||
'inactive' => 'danger',
|
||||
default => 'gray',
|
||||
});
|
||||
|
||||
// Boolean Icon
|
||||
Tables\Columns\IconColumn::make('is_active')
|
||||
->boolean();
|
||||
|
||||
// Image
|
||||
Tables\Columns\ImageColumn::make('avatar')
|
||||
->circular();
|
||||
|
||||
// Date
|
||||
Tables\Columns\TextColumn::make('created_at')
|
||||
->dateTime()
|
||||
->sortable();
|
||||
|
||||
// Money
|
||||
Tables\Columns\TextColumn::make('price')
|
||||
->money('USD');
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔐 EXISTING CORE RESOURCES
|
||||
|
||||
### User Management (already exists in template)
|
||||
- `src/app/Filament/Resources/UserResource.php` - User CRUD with role assignment
|
||||
- `src/app/Filament/Resources/RoleResource.php` - Role CRUD with permissions
|
||||
- `src/app/Filament/Resources/PermissionResource.php` - Permission CRUD
|
||||
|
||||
### Settings (already exists)
|
||||
- `src/app/Filament/Pages/Settings.php` - Site settings (name, logo, colors, registration toggle)
|
||||
- `src/app/Models/Setting.php` - Settings model with get/set helpers
|
||||
|
||||
### Authentication (pre-installed)
|
||||
- Laravel Breeze with Blade templates
|
||||
- Login: `/login`
|
||||
- Register: `/register` (controlled by enable_registration setting)
|
||||
- Admin: `/admin`
|
||||
|
||||
---
|
||||
|
||||
## 🧪 TESTING MODULES
|
||||
|
||||
Create tests in `src/tests/Feature/Modules/[ModuleName]/`:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Modules\[ModuleName];
|
||||
|
||||
use App\Models\User;
|
||||
use App\Modules\[ModuleName]\Models\[ModelName];
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class [ModelName]Test extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_user_can_view_[model_name]s(): void
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
$user->givePermissionTo('[module_name].view');
|
||||
|
||||
$this->actingAs($user)
|
||||
->get('/[module-slug]')
|
||||
->assertStatus(200);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 CHECKLIST FOR NEW MODULES
|
||||
|
||||
Before considering a module complete:
|
||||
|
||||
- [ ] ServiceProvider created and registered
|
||||
- [ ] Config file created
|
||||
- [ ] Model created with fillable and casts
|
||||
- [ ] Migration created and run
|
||||
- [ ] Permissions.php created
|
||||
- [ ] Filament Resource created with all pages
|
||||
- [ ] Controller created
|
||||
- [ ] Routes (web.php and optionally api.php) created
|
||||
- [ ] Index view created
|
||||
- [ ] `php artisan migrate` run
|
||||
- [ ] `php artisan optimize:clear` run
|
||||
- [ ] `php artisan db:seed --class=RolePermissionSeeder` run
|
||||
- [ ] Module accessible at `/[module-slug]`
|
||||
- [ ] Admin panel shows module in navigation
|
||||
- [ ] CRUD operations work in admin
|
||||
|
||||
---
|
||||
|
||||
## 🆘 DEBUGGING
|
||||
|
||||
### Module Not Loading
|
||||
```bash
|
||||
# Check if provider is registered
|
||||
docker-compose exec app php artisan about
|
||||
|
||||
# Clear everything
|
||||
docker-compose exec app php artisan optimize:clear
|
||||
```
|
||||
|
||||
### Filament Resource Not Showing
|
||||
```bash
|
||||
# Clear Filament cache
|
||||
docker-compose exec app php artisan filament:cache-components
|
||||
|
||||
# Check canAccess() method returns true
|
||||
# Check user has required permission
|
||||
```
|
||||
|
||||
### Permission Denied
|
||||
```bash
|
||||
# Reset permission cache
|
||||
docker-compose exec app php artisan permission:cache-reset
|
||||
|
||||
# Verify permissions exist
|
||||
docker-compose exec app php artisan tinker
|
||||
>>> \Spatie\Permission\Models\Permission::pluck('name');
|
||||
```
|
||||
|
||||
### View Not Found
|
||||
```bash
|
||||
# Verify view namespace (must be kebab-case)
|
||||
# Check file exists in Resources/views/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Remember**: When in doubt, look at existing code in the codebase. The patterns are already established - follow them exactly.
|
||||
@@ -4,7 +4,8 @@ A comprehensive Laravel development environment with Docker for local developmen
|
||||
|
||||
> **New here?** Start with [GETTING_STARTED.md](GETTING_STARTED.md) for a step-by-step setup guide.
|
||||
>
|
||||
> **AI Assistant?** See [AI_CONTEXT.md](AI_CONTEXT.md) for project context and conventions.
|
||||
> **AI Assistant?** See [CLAUDE.md](CLAUDE.md) for EXACT module templates and step-by-step instructions.
|
||||
> Also see [AI_CONTEXT.md](AI_CONTEXT.md) for project context and conventions.
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
|
||||
Reference in New Issue
Block a user