diff --git a/README.md b/README.md index 80163f2..692b05c 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,8 @@ A comprehensive Laravel development environment with Docker for local developmen │ ├── laravel-setup.md # Laravel setup guide │ ├── filament-admin.md # Admin panel docs │ ├── modules.md # Modular architecture guide +│ ├── module-generator.md # Admin UI module generator +│ ├── menu-management.md # Frontend menu system │ ├── audit-trail.md # Audit trail docs │ ├── site-settings.md # Appearance settings │ ├── testing.md # Pest testing guide diff --git a/docs/module-generator.md b/docs/module-generator.md new file mode 100644 index 0000000..30d07b7 --- /dev/null +++ b/docs/module-generator.md @@ -0,0 +1,173 @@ +# Module Generator (Admin UI) + +A visual tool for creating module skeletons through the Filament admin panel. + +> **Development Only**: This tool is only available when `APP_ENV=local`. + +## Access + +Navigate to: **Admin Panel → Development → Module Generator** + +URL: `/admin/module-generator` + +## Features + +- **Visual Form**: Create modules without command line +- **Auto Git Branch**: Optionally creates `module/{name}` branch and commits files +- **Skeleton Only**: Maximum flexibility - creates structure, you add the models +- **Instant Feedback**: Shows generation logs and next steps + +## What Gets Created + +``` +app/Modules/{ModuleName}/ +├── Config/{module_name}.php # Module configuration +├── Database/ +│ ├── Migrations/ # Empty, add your migrations +│ └── Seeders/ # Empty, add your seeders +├── Filament/Resources/ # Empty, add Filament resources +├── Http/ +│ ├── Controllers/{ModuleName}Controller.php +│ ├── Middleware/ # Empty +│ └── Requests/ # Empty +├── Models/ # Empty, add your models +├── Policies/ # Empty, add policies +├── Services/ # Empty, add services +├── Routes/ +│ ├── web.php # Basic index route +│ └── api.php # If API option selected +├── Resources/views/ +│ └── index.blade.php # Starter view +├── Permissions.php # CRUD permissions +├── {ModuleName}ServiceProvider.php # Auto-registered +└── README.md # Module documentation +``` + +## Form Options + +| Field | Description | +|-------|-------------| +| **Module Name** | PascalCase name (e.g., `Accounting`, `Inventory`) | +| **Description** | Brief description for README and config | +| **Create Git Branch** | Auto-create `module/{name}` branch and commit | +| **Include API Routes** | Add `Routes/api.php` with Sanctum auth | + +## Git Integration + +When "Create Git Branch" is enabled: + +1. **Checks** for uncommitted changes (fails if dirty) +2. **Creates** branch `module/{module-name}` +3. **Generates** all module files +4. **Commits** with message `feat: Add {ModuleName} module skeleton` +5. **Shows** push command: `git push -u origin module/{name}` + +### Requirements + +- Working directory must be clean (no uncommitted changes) +- Git must be installed in the container +- Repository must be initialized + +## After Generation + +1. **Run migrations** (if you add any): + ```bash + php artisan migrate + ``` + +2. **Seed permissions**: + ```bash + php artisan db:seed --class=RolePermissionSeeder + ``` + +3. **Clear caches**: + ```bash + php artisan optimize:clear + ``` + +4. **Push branch** (if Git was used): + ```bash + git push -u origin module/{name} + ``` + +## Adding Models + +After generating the skeleton, add models manually: + +```php +// app/Modules/Accounting/Models/Invoice.php +environment('local'); + } + + public static function shouldRegisterNavigation(): bool + { + return app()->environment('local'); + } + + public function mount(): void + { + $this->form->fill([ + 'create_git_branch' => true, + 'include_api' => false, + ]); + + $this->loadModules(); + } + + public function loadModules(): void + { + $discovery = new ModuleDiscoveryService(); + $this->modules = $discovery->discoverModules(); + $this->summary = $discovery->getModuleSummary(); + } + + public function toggleModule(string $moduleName): void + { + $this->expandedModule = $this->expandedModule === $moduleName ? null : $moduleName; + } + + public function form(Form $form): Form + { + return $form + ->schema([ + Section::make('Module Details') + ->description('Create a new module skeleton with all the necessary folders and files.') + ->schema([ + TextInput::make('name') + ->label('Module Name') + ->placeholder('e.g., Accounting, Inventory, HumanResources') + ->helperText('Use PascalCase. This will create app/Modules/YourModuleName/') + ->required() + ->maxLength(50) + ->rules(['regex:/^[A-Z][a-zA-Z0-9]*$/']) + ->validationMessages([ + 'regex' => 'Module name must be PascalCase (start with uppercase, letters and numbers only).', + ]) + ->live(onBlur: true) + ->afterStateUpdated(fn ($state, callable $set) => + $set('name', Str::studly($state)) + ), + + Textarea::make('description') + ->label('Description') + ->placeholder('Brief description of what this module does...') + ->rows(2) + ->maxLength(255), + ]), + + Section::make('Options') + ->schema([ + Toggle::make('create_git_branch') + ->label('Create Git Branch') + ->helperText('Automatically create and checkout a new branch: module/{module-name}') + ->default(true), + + Toggle::make('include_api') + ->label('Include API Routes') + ->helperText('Add Routes/api.php with Sanctum authentication') + ->default(false), + ]) + ->columns(2), + + Section::make('What Will Be Created') + ->schema([ + \Filament\Forms\Components\Placeholder::make('structure') + ->label('') + ->content(fn () => new \Illuminate\Support\HtmlString(' +
+ This is your new module. Start building by adding models, controllers, and views. +
+ +app/Modules/{$this->studlyName}/Models/app/Modules/{$this->studlyName}/Database/Migrations/app/Modules/{$this->studlyName}/Filament/Resources/app/Modules/{$this->studlyName}/Routes/web.phpNo modules registered yet. Create your first module below!
+No models
+ @endif +No views
+ @endif +No Filament resources
+ @endif +No web routes parsed
+ @endif +No migrations
+ @endif +No permissions
+ @endif +{{ $result['module_name'] }}
+ {{ $result['module_path'] }}
+ {{ $result['branch'] }}
+ $1', e($step)) !!}{{ $result['message'] }}
+ + @if(!empty($result['logs'])) +