├── .styleci.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── composer.json ├── config └── config.php ├── index.php ├── jsconfig.json ├── laravel-codegenerator.png ├── resources └── views │ ├── blade │ ├── Events │ │ └── ModelEvent.blade.php │ ├── Http │ │ ├── Controllers │ │ │ ├── API │ │ │ │ └── ModelController.blade.php │ │ │ └── ModelController.blade.php │ │ └── Requests │ │ │ └── ModelRequest.blade.php │ ├── Notifications │ │ └── ModelNotification.blade.php │ ├── database │ │ └── factories │ │ │ └── ModelFactory.blade.php │ ├── lang │ │ └── en │ │ │ └── Models.blade.php │ ├── routes.blade.txt │ ├── tests │ │ └── Feature │ │ │ └── Http │ │ │ └── Controllers │ │ │ ├── API │ │ │ └── ModelControllerTest.blade.php │ │ │ └── ModelControllerTest.blade.php │ └── views │ │ ├── create.blade.php │ │ ├── edit.blade.php │ │ ├── index.blade.php │ │ └── show.blade.php │ ├── inertia │ ├── Events │ │ └── ModelEvent.blade.php │ ├── Http │ │ ├── Controllers │ │ │ └── ModelController.blade.php │ │ └── Requests │ │ │ └── ModelRequest.blade.php │ ├── Notifications │ │ └── ModelNotification.blade.php │ ├── database │ │ └── factories │ │ │ └── ModelFactory.blade.php │ ├── lang │ │ └── en │ │ │ └── Models.blade.php │ ├── resources │ │ └── js │ │ │ ├── Components │ │ │ ├── CheckboxInput.vue │ │ │ ├── Container.vue │ │ │ ├── FlashAlert.vue │ │ │ ├── Pagination.vue │ │ │ ├── SelectInput.vue │ │ │ ├── TableBase.vue │ │ │ ├── TextInput.vue │ │ │ └── TextareaInput.vue │ │ │ └── Pages │ │ │ └── Models │ │ │ ├── Create.blade.vue │ │ │ ├── Edit.blade.vue │ │ │ └── Index.blade.vue │ └── routes.blade.txt │ ├── livewire │ ├── Http │ │ └── Index.blade.php │ └── views │ │ ├── edit.blade.php │ │ ├── index.blade.php │ │ ├── list.blade.php │ │ └── show.blade.php │ └── schema.blade.json └── src ├── CodeGenerator.php ├── Console └── GenerateCommand.php ├── Facades ├── CodeGenerator.php ├── CodeHelper.php └── ModelLoader.php ├── Helper.php ├── LaravelCodeGeneratorServiceProvider.php ├── ModelLoader.php ├── ModelRelation.php ├── RelationFinder.php ├── Structure ├── Column.php ├── Model.php └── Table.php ├── Template.php └── helpers.php /.styleci.yml: -------------------------------------------------------------------------------- 1 | preset: laravel 2 | 3 | disabled: 4 | - single_class_element_per_statement 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to `laravel-codegenerator` will be documented in this file 4 | 5 | ## 1.0.0 - 201X-XX-XX 6 | 7 | - initial release 8 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Contributions are **welcome** and will be fully **credited**. 4 | 5 | Please read and understand the contribution guide before creating an issue or pull request. 6 | 7 | ## Etiquette 8 | 9 | This project is open source, and as such, the maintainers give their free time to build and maintain the source code 10 | held within. They make the code freely available in the hope that it will be of use to other developers. It would be 11 | extremely unfair for them to suffer abuse or anger for their hard work. 12 | 13 | Please be considerate towards maintainers when raising issues or presenting pull requests. Let's show the 14 | world that developers are civilized and selfless people. 15 | 16 | It's the duty of the maintainer to ensure that all submissions to the project are of sufficient 17 | quality to benefit the project. Many developers have different skillsets, strengths, and weaknesses. Respect the maintainer's decision, and do not be upset or abusive if your submission is not used. 18 | 19 | ## Viability 20 | 21 | When requesting or submitting new features, first consider whether it might be useful to others. Open 22 | source projects are used by many developers, who may have entirely different needs to your own. Think about 23 | whether or not your feature is likely to be used by other users of the project. 24 | 25 | ## Procedure 26 | 27 | Before filing an issue: 28 | 29 | - Attempt to replicate the problem, to ensure that it wasn't a coincidental incident. 30 | - Check to make sure your feature suggestion isn't already present within the project. 31 | - Check the pull requests tab to ensure that the bug doesn't have a fix in progress. 32 | - Check the pull requests tab to ensure that the feature isn't already in progress. 33 | 34 | Before submitting a pull request: 35 | 36 | - Check the codebase to ensure that your feature doesn't already exist. 37 | - Check the pull requests to ensure that another person hasn't already submitted the feature or fix. 38 | 39 | ## Requirements 40 | 41 | If the project maintainer has any additional requirements, you will find them listed here. 42 | 43 | - **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](https://pear.php.net/package/PHP_CodeSniffer). 44 | 45 | - **Add tests!** - Your patch won't be accepted if it doesn't have tests. 46 | 47 | - **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. 48 | 49 | - **Consider our release cycle** - We try to follow [SemVer v2.0.0](https://semver.org/). Randomly breaking public APIs is not an option. 50 | 51 | - **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. 52 | 53 | - **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](https://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting. 54 | 55 | **Happy coding**! 56 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Victor Yoalli 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # ![Laravel Code Generator](laravel-codegenerator.png) 4 | 5 | ![GitHub release (latest by date)](https://img.shields.io/github/v/release/victoryoalli/laravel-code-generator) 6 | ![Packagist PHP Version Support](https://img.shields.io/packagist/php-v/victoryoalli/laravel-code-generator) 7 | [![GitHub forks](https://img.shields.io/github/forks/victoryoalli/laravel-code-generator)](https://github.com/victoryoalli/laravel-code-generator/network) 8 | [![GitHub stars](https://img.shields.io/github/stars/victoryoalli/laravel-code-generator)](https://github.com/victoryoalli/laravel-code-generator/stargazers) 9 | ![Packagist Downloads](https://img.shields.io/packagist/dt/victoryoalli/laravel-code-generator) 10 | 11 | 12 | Laravel Code Generator is a PHP Laravel Package that uses [Blade template](https://laravel.com/docs/8.x/blade) engine to generate code for you. 13 | 14 | The difference between other code generators is that this one will generate the code exactly as you want it to be, same design, same lines of code. 15 | 16 | ## Demo 17 | 18 | * [Video Tutorial Introduction (English) ](https://youtu.be/CgI7eixFexg) 19 | 20 | ## Installation 21 | 22 | Use composer to install Laravel Code Generator. 23 | 24 | ```bash 25 | composer require --dev victoryoalli/laravel-code-generator 26 | ``` 27 | 28 | ## Usage 29 | 30 | ### Single file generation 31 | ```php 32 | php artisan code:generate 'App\Models\User' -t 'schema' //prints to command line 33 | php artisan code:generate 'App\Models\User' -t 'schema' -o 'user-schema.json' 34 | ``` 35 | 36 | **Example Output** 37 | ```json 38 | { 39 | "name": "User", 40 | "complete_name": "App\\Models\\User", 41 | "table": { 42 | "name": "users", 43 | "columns": [ 44 | { 45 | "name": "id", 46 | "type": "BigInt", 47 | "length": "", 48 | "nullable": "", 49 | "autoincrement": "1", 50 | "default": "" 51 | }, 52 | { 53 | "name": "name", 54 | "type": "String", 55 | "length": "255", 56 | "nullable": "", 57 | "autoincrement": "", 58 | "default": "" 59 | }, 60 | { 61 | "name": "email", 62 | "type": "String", 63 | "length": "255", 64 | "nullable": "", 65 | "autoincrement": "", 66 | "default": "" 67 | }, 68 | { 69 | "name": "email_verified_at", 70 | "type": "DateTime", 71 | "length": "0", 72 | "nullable": "1", 73 | "autoincrement": "", 74 | "default": "" 75 | }, 76 | { 77 | "name": "password", 78 | "type": "String", 79 | "length": "255", 80 | "nullable": "", 81 | "autoincrement": "", 82 | "default": "" 83 | }, 84 | { 85 | "name": "remember_token", 86 | "type": "String", 87 | "length": "100", 88 | "nullable": "1", 89 | "autoincrement": "", 90 | "default": "" 91 | }, 92 | { 93 | "name": "created_at", 94 | "type": "DateTime", 95 | "length": "0", 96 | "nullable": "1", 97 | "autoincrement": "", 98 | "default": "" 99 | }, 100 | { 101 | "name": "updated_at", 102 | "type": "DateTime", 103 | "length": "0", 104 | "nullable": "1", 105 | "autoincrement": "", 106 | "default": "" 107 | } 108 | ] 109 | }, 110 | "relations": [] 111 | } 112 | ``` 113 | 114 | ### Multiple file generator 115 | 116 | First create a custom command like this example 117 | 118 | #### Create a Custom Command 119 | 120 | ```bash 121 | php artisan make:command CodeGeneratorCommand --command='code:generator' 122 | ``` 123 | 124 | #### Custom Command 125 | 126 | ```php 127 | option('force'); 171 | 172 | //Options 173 | $controller = $this->option('controller'); 174 | $routes = $this->option('routes'); 175 | $views = $this->option('views'); 176 | $api = $this->option('api'); 177 | $lang = $this->option('lang'); 178 | $factory = $this->option('factory'); 179 | $tests = $this->option('tests'); 180 | $auth = $this->option('auth'); 181 | $event = $this->option('event'); 182 | $notification = $this->option('notification'); 183 | $all = $this->option('all'); 184 | $livewire = $this->option('livewire'); 185 | $theme = $this->option('theme'); 186 | if ($all) { 187 | $lang = $controller = $routes = $views = $all; 188 | } 189 | $request = ($controller || $api); 190 | 191 | $options = compact(['factory', 'controller', 'routes', 'views', 'api', 'tests', 'auth', 'request', 'notification', 'event', 'lang','livewire']); 192 | $namespace = rtrim($this->option('namespace'), '\\'); 193 | $models = collect(explode(',', $this->argument('model'))); 194 | 195 | $models->each(function ($model) use ($namespace, $options, $theme, $force) { 196 | $model = "{$namespace}\\{$model}"; 197 | if (!$model) { 198 | return; 199 | } 200 | $m = ModelLoader::load($model); 201 | 202 | $this->generate($m, $options, $theme, $force); 203 | }); 204 | } 205 | 206 | public function generate(Model $m, $options, $theme, $force) 207 | { 208 | $option = (object) $options; 209 | $folder = str($m->name)->plural()->snake(); 210 | 211 | $this->info('🚀 Starting code generation'); 212 | $this->newLine(); 213 | if ($option->controller) { 214 | $this->printif('Web Controller', CodeGenerator::generate($m, $theme . '/Http/Controllers/ModelController', "app/Http/Controllers/{$m->name}Controller.php", $force, $options)); 215 | } 216 | if ($option->api) { 217 | $this->printif('API Controller', CodeGenerator::generate($m, $theme . '/Http/Controllers/API/ModelController', "app/Http/Controllers/API/{$m->name}Controller.php", $force, $options)); 218 | } 219 | if ($option->request) { 220 | $this->printif('Form Request', CodeGenerator::generate($m, $theme . '/Http/Requests/ModelRequest', "app/Http/Requests/{$m->name}Request.php", $force, $options)); 221 | } 222 | 223 | if ($option->views) { 224 | $this->printif('Index View', CodeGenerator::generate($m, $theme . '/views/index', "resources/views/{$folder}/index.blade.php", $force, $options)); 225 | $this->printif('Create View', CodeGenerator::generate($m, $theme . '/views/create', "resources/views/{$folder}/create.blade.php", $force, $options)); 226 | $this->printif('Show View', CodeGenerator::generate($m, $theme . '/views/show', "resources/views/{$folder}/show.blade.php", $force, $options)); 227 | $this->printif('Edit View', CodeGenerator::generate($m, $theme . '/views/edit', "resources/views/{$folder}/edit.blade.php", $force, $options)); 228 | } 229 | if ($option->lang) { 230 | $this->printif('Lang', CodeGenerator::generate($m, $theme . '/lang/en/Models', "resources/lang/en/{$folder}.php", $force, $options)); 231 | } 232 | if ($option->factory) { 233 | $this->printif('Factory ', CodeGenerator::generate($m, $theme . '/database/factories/ModelFactory', "database/factories/{$m->name}Factory.php", $force, $options)); 234 | } 235 | if ($option->tests) { 236 | $this->printif('Feature Test Controller', CodeGenerator::generate($m, $theme . '/tests/Feature/Http/Controllers/ModelControllerTest', "tests/Feature/Http/Controllers/{$m->name}ControllerTest.php", $force, $options)); 237 | if ($option->controller) { 238 | $this->printif('Feature Test Controller', CodeGenerator::generate($m, $theme . '/tests/Feature/Http/Controllers/ModelControllerTest', "tests/Feature/Http/Controllers/{$m->name}ControllerTest.php", $force, $options)); 239 | } 240 | if ($option->api) { 241 | $this->printif('Feature Test API Controller', CodeGenerator::generate($m, $theme . '/tests/Feature/Http/Controllers/API/ModelControllerTest', "tests/Feature/Http/Controllers/API/{$m->name}ControllerTest.php", $force, $options)); 242 | } 243 | } 244 | if ($option->notification) { 245 | $this->printif('Notification', CodeGenerator::generate($m, $theme . '/Notifications/ModelNotification', "app/Notifications/{$m->name}{$option->notification}.php", $force, $options)); 246 | } 247 | if ($option->event) { 248 | $this->printif('Event', CodeGenerator::generate($m, $theme . '/Events/ModelEvent', "app/Events/{$m->name}{$option->event}.php", $force, $options)); 249 | } 250 | if ($option->livewire) { 251 | $plural = str($m->name)->plural(); 252 | $this->printif('Livewire Component ', CodeGenerator::generate($m, "/livewire/Http/Index", "app/Http/Livewire/{$plural}/Index.php", $force, $options)); 253 | $this->printif('Livewire index view ', CodeGenerator::generate($m, "/livewire/views/index", "resources/views/livewire/{$folder}/index.blade.php", $force, $options)); 254 | $this->printif('Livewire list view ', CodeGenerator::generate($m, "/livewire/views/list", "resources/views/livewire/{$folder}/list.blade.php", $force, $options)); 255 | $this->printif('Livewire edit view ', CodeGenerator::generate($m, "/livewire/views/edit", "resources/views/livewire/{$folder}/edit.blade.php", $force, $options)); 256 | $this->printif('Livewire show view ', CodeGenerator::generate($m, "/livewire/views/show", "resources/views/livewire/{$folder}/show.blade.php", $force, $options)); 257 | } 258 | if ($option->routes) { 259 | $this->newLine(3); 260 | $this->line(''.CodeGenerator::generate($m, $theme . '/routes', null, $force, $options).''); 261 | } 262 | 263 | $this->newLine(); 264 | $this->info('🎉 Finished!'); 265 | } 266 | 267 | public function printif($type, $filename) 268 | { 269 | $text = empty($filename) ? ' ✖ '. $type . ' already exists ' : '' . $filename . ' created. '; 270 | $this->line($text); 271 | } 272 | } 273 | 274 | ``` 275 | 276 | #### Execute custom command 277 | ```bash 278 | php artisan code:generator 'App\User' -FA 279 | ``` 280 | 281 | ## Templates & Customization 282 | 283 | Templates are located at `resources/vendor/laravel-code-generator`. 284 | For example once you publish the views the file `schema.blade.json` will be located at the relative path is `resources/vendor/laravel-code-generator\schema.blade.json` . 285 | 286 | The path `resources/views/vendor/laravel-code-generator` is where you can create your own new templates, or customize the existing ones. 287 | 288 | #### Publish template views & Config 289 | 290 | You can publish : 291 | ```bash 292 | ## views at: resources/views/vendor/laravel-code-generator 293 | php artisan vendor:publish --provider="VictorYoalli\LaravelCodeGenerator\LaravelCodeGeneratorServiceProvider" --tag="views" 294 | ``` 295 | 296 | or the config file 297 | ```php 298 | ## config file: config/laravel-code-generator.php 299 | php artisan vendor:publish --provider="VictorYoalli\LaravelCodeGenerator\LaravelCodeGeneratorServiceProvider" --tag="config" 300 | ``` 301 | 302 | This is the contents of the published config file 303 | `config/laravel-code-generator.php`: 304 | 305 | By default you can use as templates files with following extensions, if you need to generate or use different files as templates you can add to the config file. 306 | 307 | ```php 308 | [ 323 | 'js', 324 | 'jsx', 325 | 'vue', 326 | 'html', 327 | 'txt', 328 | 'json', 329 | ] 330 | ]; 331 | ``` 332 | ## Structure 333 | * **Model** *(object)* 334 | * name *(string)* 335 | * table *(object)* 336 | * relations *(array)* 337 | * **Table** *(object)* 338 | * name *(string)* 339 | * columns *(array)* 340 | * **Column** *(object)* 341 | * name *(string)* 342 | * type *(string)* 343 | * length *(integer)* 344 | * nullable *(boolean)* 345 | * autoincrement *(boolean)* 346 | * default *(string)* 347 | * **Relations** *(array)* 348 | * name *(string)* 349 | * type *(string)* 350 | * local_key *(string)* 351 | * foreign_key *(string)* 352 | * model *(array)* 353 | 354 | #### Example 355 | ```php 356 | {!!code()->PHPSOL()!!} 357 | 358 | namespace App\Http\Controllers\API; 359 | 360 | use App\{{$model->name}}; 361 | use Illuminate\Http\Request; 362 | use App\Http\Controllers\Controller; 363 | 364 | class {{$model->name}}Controller extends Controller 365 | { 366 | /** 367 | * Display a listing of the resource. 368 | * 369 | * @return \Illuminate\Http\Response 370 | */ 371 | public function index() 372 | { 373 | return {{$model->name}}::all(); 374 | } 375 | 376 | /** 377 | * Store a newly created resource in storage. 378 | * 379 | * @param \Illuminate\Http\Request $request 380 | * @return \Illuminate\Http\Response 381 | */ 382 | public function store(Request $request) 383 | { 384 | $this->validate($request, [ 385 | @foreach($model->table->columns as $col) 386 | @if(!str($col->name)->matches('/_at$/') && !str($col->name)->matches('/^id$/')) 387 | @if(!$col->nullable) '{{$col->name}}' => 'required', 388 | @endif 389 | @endif 390 | @endforeach 391 | ]); 392 | 393 | ${{str($model->name)->camel()}} = {{$model->name}}::create($request->all()); 394 | 395 | return ${{str($model->name)->camel()}}; 396 | } 397 | 398 | ... 399 | } 400 | 401 | ``` 402 | 403 | #### Output Sample 404 | 405 | ```php 406 | validate($request, [ 435 | 'name' => 'required', 436 | 'email' => 'required', 437 | 'password' => 'required', 438 | 439 | ]); 440 | 441 | $user = User::create($request->all()); 442 | 443 | return $user; 444 | } 445 | 446 | ``` 447 | 448 | 449 | ## Helpers 450 | 451 | `PHPSOL()`: PHP Start Of Line 452 | 453 | ```php 454 | {!!code->PHPSOL()!!} 455 | ``` 456 | Will print 457 | ```php 458 | doubleCurlyOpen()}} 464 | ``` 465 | Will print: 466 | ```php 467 | {{ 468 | ``` 469 | 470 | 471 | `doubleCurlyClose()`: Closing Double Curly Braces 472 | ```php 473 | {{code()->doubleCurlyClose()}} 474 | ``` 475 | Will print: 476 | ```php 477 | }} 478 | ``` 479 | 480 | `tag('x-component-name')`: Closing Double Curly Braces 481 | ```php 482 | {{code()->tag('x-component-name')}} 483 | ``` 484 | Will print: 485 | ```php 486 | 487 | ``` 488 | 489 | 490 | 491 | 492 | ## CodeGenerator::generate Facade 493 | 494 | This is how you can use the Facade when you want to create your own Code Generator. 495 | 496 | ```php 497 | $filename = CodeGenerator::generate('App\Models\User', 'blade/show', "resources/views/{$folder}/show.blade.php", false); 498 | $generatedCodeString = CodeGenerator::generate($m, 'blade/routes' ); 499 | ``` 500 | 501 | 502 | 503 | ## Contributing 504 | Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. 505 | 506 | Please make sure to update tests as appropriate. 507 | 508 | ## License 509 | [MIT](https://choosealicense.com/licenses/mit/) 510 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "victoryoalli/laravel-code-generator", 3 | "description": "A PHP Package for Code Generation.", 4 | "type": "library", 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Victor Yoalli", 9 | "email": "victoryoalli@gmail.com" 10 | } 11 | ], 12 | "homepage": "https://github.com/victoryoalli/laravel-code-generator", 13 | "require": { 14 | "php": "^8.0", 15 | "illuminate/console": "^8.0|^9.0|^10.0", 16 | "illuminate/filesystem": "^8.0|^9.0|^10.0", 17 | "illuminate/support": "^8.0|^9.0|^10.0", 18 | "doctrine/dbal": "^2.9|^3.0", 19 | "spatie/laravel-ray": "^1.18" 20 | }, 21 | "require-dev": { 22 | "orchestra/testbench": "^7.0|^8.0", 23 | "victoryoalli/laravel-string-macros": "^1.0" 24 | }, 25 | "autoload": { 26 | "files": [ 27 | "src/helpers.php" 28 | ], 29 | "psr-4": { 30 | "VictorYoalli\\LaravelCodeGenerator\\": "src/" 31 | } 32 | }, 33 | "autoload-dev": { 34 | "psr-4": { 35 | "VictorYoalli\\LaravelCodeGenerator\\Tests\\": "tests" 36 | } 37 | }, 38 | "extra": { 39 | "laravel": { 40 | "providers": [ 41 | "VictorYoalli\\LaravelCodeGenerator\\LaravelCodeGeneratorServiceProvider" 42 | ], 43 | "aliases": { 44 | "CodeGenerator": "VictorYoalli\\LaravelCodeGenerator\\Facades\\CodeGenerator", 45 | "ModelLoader": "VictorYoalli\\LaravelCodeGenerator\\Facades\\ModelLoader", 46 | "CodeHelper": "VictorYoalli\\LaravelCodeGenerator\\Facades\\CodeHelper" 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /config/config.php: -------------------------------------------------------------------------------- 1 | [ 13 | 'js', 14 | 'jsx', 15 | 'vue', 16 | 'html', 17 | 'txt', 18 | 'json', 19 | ] 20 | ]; 21 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | handle(); 7 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "paths": { 5 | "@/*": [ 6 | "resources/js/*" 7 | ], 8 | "@Components/*": [ 9 | "resources/js/Components/*" 10 | ] 11 | } 12 | }, 13 | "exclude": [ 14 | "node_modules", 15 | "public" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /laravel-codegenerator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/victoryoalli/laravel-code-generator/184b17d329332cbc98f47efad8c311405190a56f/laravel-codegenerator.png -------------------------------------------------------------------------------- /resources/views/blade/Events/ModelEvent.blade.php: -------------------------------------------------------------------------------- 1 | {!!CodeHelper::PHPSOL()!!} 2 | 3 | namespace App\Events; 4 | 5 | use Illuminate\Broadcasting\Channel; 6 | use Illuminate\Broadcasting\InteractsWithSockets; 7 | use Illuminate\Broadcasting\PresenceChannel; 8 | use Illuminate\Broadcasting\PrivateChannel; 9 | use Illuminate\Contracts\Broadcasting\ShouldBroadcast; 10 | use Illuminate\Foundation\Events\Dispatchable; 11 | use Illuminate\Queue\SerializesModels; 12 | use {{$model->complete_name}}; 13 | 14 | class {{$model->name}}{{$options->event}} 15 | { 16 | use Dispatchable, InteractsWithSockets, SerializesModels; 17 | 18 | protected ${{str($model->name)->camel()}}; 19 | /** 20 | * Create a new event instance. 21 | * 22 | * @return void 23 | */ 24 | public function __construct({{$model->name}} ${{str($model->name)->camel()}}) 25 | { 26 | $this->{{str($model->name)->camel()}} = ${{str($model->name)->camel()}}; 27 | } 28 | 29 | /** 30 | * Get the channels the event should broadcast on. 31 | * 32 | * @return \Illuminate\Broadcasting\Channel|array 33 | */ 34 | public function broadcastOn() 35 | { 36 | return new PrivateChannel('channel-name'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /resources/views/blade/Http/Controllers/API/ModelController.blade.php: -------------------------------------------------------------------------------- 1 | {!! code()->PHPSOL() !!} 2 | 3 | namespace App\Http\Controllers\API; 4 | 5 | use Illuminate\Http\Request; 6 | use App\Http\Requests\{{$model->name}}Request; 7 | use App\Http\Controllers\Controller; 8 | @if($options->notification) 9 | use App\Notifications\{{$model->name}}{{$options->notification}}; 10 | @endif 11 | @if($options->event) 12 | use App\Events\{{$options->event}}; 13 | @endif 14 | use {{$model->complete_name}}; 15 | 16 | class {{$model->name}}Controller extends Controller 17 | { 18 | @if($options->auth) 19 | public function __construct() 20 | { 21 | //parent::__construct(); 22 | $this->middleware('auth:api'); 23 | } 24 | @endif 25 | 26 | 27 | public function index() 28 | { 29 | return {{$model->name}}::all(); 30 | } 31 | 32 | public function show(Request $request, {{$model->name}} ${{str($model->name)->snake()}}) 33 | { 34 | return ${{str($model->name)->snake()}}; 35 | } 36 | 37 | public function store({{$model->name}}Request $request) 38 | { 39 | $data = $request->validated(); 40 | ${{str($model->name)->snake()}} = {{$model->name}}::create($data); 41 | @if($options->notification) 42 | //auth()->user->notify(new {{$model->name}}{{$options->notification}}(${{str($model->name)->snake()}})); 43 | @endif 44 | @if($options->event) 45 | event(new {{$options->event}}(${{str($model->name)->snake()}})); 46 | @endif 47 | return ${{str($model->name)->snake()}}; 48 | } 49 | 50 | public function update({{$model->name}}Request $request, {{$model->name}} ${{str($model->name)->snake()}}) 51 | { 52 | $data = $request->validated(); 53 | ${{str($model->name)->snake()}}->fill($data); 54 | ${{str($model->name)->snake()}}->save(); 55 | 56 | return ${{str($model->name)->snake()}}; 57 | } 58 | 59 | public function destroy(Request $request, {{$model->name}} ${{str($model->name)->snake()}}) 60 | { 61 | ${{str($model->name)->snake()}}->delete(); 62 | return ${{str($model->name)->snake()}}; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /resources/views/blade/Http/Controllers/ModelController.blade.php: -------------------------------------------------------------------------------- 1 | {!! code()->PHPSOL() !!} 2 | 3 | namespace App\Http\Controllers; 4 | 5 | use Illuminate\Http\Request; 6 | use App\Http\Requests\{{$model->name}}Request; 7 | @if($options->notification) 8 | use App\Notifications\{{$model->name}}{{$options->notification}}; 9 | @endif 10 | @if($options->event) 11 | use App\Events\{{$options->event}}; 12 | @endif 13 | use {{$model->complete_name}}; 14 | 15 | 16 | class {{$model->name}}Controller extends Controller 17 | { 18 | @if($options->auth) 19 | public function __construct() 20 | { 21 | //parent::__construct(); 22 | $this->middleware('auth'); 23 | } 24 | @endif 25 | 26 | public function index() 27 | { 28 | ${{str($model->name)->snake()->plural()}} = {{$model->name}}::paginate(10); 29 | return view('{{str($model->name)->snake()->plural()}}.index', compact('{{str($model->name)->snake()->plural()}}')); 30 | } 31 | 32 | public function show(Request $request, {{$model->name}} ${{str($model->name)->snake()}}) 33 | { 34 | return view('{{str($model->name)->snake()->plural()}}.show', compact('{{str($model->name)->snake()}}')); 35 | } 36 | 37 | public function create() 38 | { 39 | return view('{{str($model->name)->snake()->plural()}}.create'); 40 | } 41 | 42 | public function store({{$model->name}}Request $request) 43 | { 44 | $data = $request->validated(); 45 | ${{str($model->name)->snake()}} = {{$model->name}}::create($data); 46 | @if($options->notification) 47 | //auth()->user->notify(new {{$model->name}}{{$options->notification}}(${{str($model->name)->snake()}})); 48 | @endif 49 | @if($options->event) 50 | event(new {{$options->event}}(${{str($model->name)->snake()}})); 51 | @endif 52 | return redirect()->route('{{str($model->name)->slug()->plural()}}.index')->with('status', '{{$model->name}} created!'); 53 | } 54 | 55 | public function edit(Request $request, {{$model->name}} ${{str($model->name)->snake()}}) 56 | { 57 | return view('{{str($model->name)->snake()->plural()}}.edit', compact('{{str($model->name)->snake()}}')); 58 | } 59 | 60 | public function update({{$model->name}}Request $request, {{$model->name}} ${{str($model->name)->snake()}}) 61 | { 62 | $data = $request->validated(); 63 | ${{str($model->name)->snake()}}->fill($data); 64 | ${{str($model->name)->snake()}}->save(); 65 | return redirect()->route('{{str($model->name)->slug()->plural()}}.index')->with('status', '{{$model->name}} updated!'); 66 | } 67 | 68 | public function destroy(Request $request, {{$model->name}} ${{str($model->name)->snake()}}) 69 | { 70 | ${{str($model->name)->snake()}}->delete(); 71 | return redirect()->route('{{str($model->name)->slug()->plural()}}.index')->with('status', '{{$model->name}} destroyed!'); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /resources/views/blade/Http/Requests/ModelRequest.blade.php: -------------------------------------------------------------------------------- 1 | {!! CodeHelper::PHPSOL() !!} 2 | 3 | namespace App\Http\Requests; 4 | 5 | use Illuminate\Foundation\Http\FormRequest; 6 | 7 | class {{$model->name}}Request extends FormRequest 8 | { 9 | /** 10 | * Determine if the user is authorized to make this request. 11 | * 12 | * @return bool 13 | */ 14 | public function authorize() 15 | { 16 | return true; 17 | } 18 | 19 | /** 20 | * Get the validation rules that apply to the request. 21 | * 22 | * @return array 23 | */ 24 | public function rules() 25 | { 26 | return [ 27 | @foreach($model->table->columns as $col) 28 | @if(!str($col->name)->matches('/^id$/') && !str($col->name)->matches('/created_at$/') && !str($col->name)->matches('/updated_at$/') && !str($col->name)->matches('/deleted_at$/')) 29 | @if(!$col->nullable) 30 | '{{$col->name}}' => [ 31 | 'required', 32 | ], 33 | @else 34 | '{{$col->name}}' => [ 35 | 'nullable', 36 | ], 37 | @endif 38 | @endif 39 | @endforeach 40 | ]; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /resources/views/blade/Notifications/ModelNotification.blade.php: -------------------------------------------------------------------------------- 1 | {!!code()->PHPSOL()!!} 2 | 3 | namespace App\Notifications; 4 | 5 | use Illuminate\Bus\Queueable; 6 | use Illuminate\Contracts\Queue\ShouldQueue; 7 | use Illuminate\Notifications\Messages\MailMessage; 8 | use Illuminate\Notifications\Notification; 9 | use {{$model->complete_name}}; 10 | 11 | class {{$model->name}}{{$options->notification}} extends Notification 12 | { 13 | use Queueable; 14 | 15 | protected ${{str($model->name)->camel()}}; 16 | /** 17 | * Create a new notification instance. 18 | * 19 | * @return void 20 | */ 21 | public function __construct({{$model->name}} ${{str($model->name)->camel()}}) 22 | { 23 | $this->${{str($model->name)->camel()}} = ${{str($model->name)->camel()}}; 24 | } 25 | 26 | /** 27 | * Get the notification's delivery channels. 28 | * 29 | * @param mixed $notifiable 30 | * @return array 31 | */ 32 | public function via($notifiable) 33 | { 34 | return ['mail']; 35 | } 36 | 37 | /** 38 | * Get the mail representation of the notification. 39 | * 40 | * @param mixed $notifiable 41 | * @return \Illuminate\Notifications\Messages\MailMessage 42 | */ 43 | public function toMail($notifiable) 44 | { 45 | return (new MailMessage($this->{{str($model->name)->camel()}})) 46 | ->line('The introduction to the notification.') 47 | ->action('Notification Action', url('/')) 48 | ->line('Thank you for using our application!'); 49 | } 50 | 51 | /** 52 | * Get the array representation of the notification. 53 | * 54 | * @param mixed $notifiable 55 | * @return array 56 | */ 57 | public function toArray($notifiable) 58 | { 59 | return [ 60 | // 61 | ]; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /resources/views/blade/database/factories/ModelFactory.blade.php: -------------------------------------------------------------------------------- 1 | {!!code()->PHPSOL()!!} 2 | 3 | namespace Database\Factories; 4 | 5 | use {{$model->complete_name}}; 6 | use Illuminate\Database\Eloquent\Factories\Factory; 7 | @foreach($model->relations as $rel) 8 | use {{$rel->model->complete_name}}; 9 | @endforeach 10 | 11 | @php 12 | $columns = collect($model->table->columns); 13 | $columns = $columns->filter(function($c){ 14 | return ($c->name != 'id' && $c->name != 'created_at' && $c->name != 'updated_at' && $c->name != 'deleted_at'); 15 | }); 16 | 17 | function fakerType($column){ 18 | if($column->type == 'String'){ 19 | if(str($column->name)->matches('/password/') ){ 20 | $result = 'bcrypt($this->faker->password)'; 21 | } 22 | elseif(str($column->name)->matches('/slug/') ){ 23 | $result = 'slug()'; 24 | } 25 | elseif(str($column->name)->matches('/email/') ){ 26 | $result = 'safeEmail()'; 27 | } 28 | elseif(str($column->name)->matches('/username/') ){ 29 | $result = 'userName()'; 30 | } 31 | elseif(str($column->name)->matches('/last.*name/') ){ 32 | $result = 'lastName()'; 33 | } 34 | elseif(str($column->name)->matches('/first.?name/') ){ 35 | $result = 'firstName()'; 36 | } 37 | elseif(str($column->name)->matches('/phone|mobile/') ){ 38 | $result = 'phoneNumber()'; 39 | } 40 | elseif(str($column->name)->matches('/photo/') ){ 41 | $result = "imageUrl(640,480,'people')"; 42 | } 43 | elseif(str($column->name)->matches('/name/') ){ 44 | $result = 'name()'; 45 | } 46 | elseif(str($column->name)->matches('/img.*url|image.*url/') ){ 47 | $result = 'imageUrl()'; 48 | } 49 | elseif(str($column->name)->matches('/image|img/') ){ 50 | $result = 'imageUrl()'; 51 | } 52 | elseif(str($column->name)->matches('/file|path/') ){ 53 | $result = 'file()'; 54 | } 55 | elseif(str($column->name)->matches('/url/') ){ 56 | $result = 'url'; 57 | } 58 | elseif(str($column->name)->matches('/domain/') ){ 59 | $result = 'domainName'; 60 | } 61 | elseif(str($column->name)->matches('/color/') ){ 62 | $result = 'hexcolor'; 63 | } 64 | elseif(str($column->name)->matches('/token/') ){ 65 | $result = 'md5'; 66 | } 67 | elseif($column->length > 255){ 68 | $result = 'sentence'; 69 | } 70 | else { 71 | $result = 'text()'; 72 | } 73 | } 74 | elseif($column->type == 'Text'){ 75 | $result = 'text(1024)'; 76 | } 77 | elseif($column->type == 'Boolean'){ 78 | $result = 'boolean'; 79 | } 80 | elseif($column->type == 'DateTime'){ 81 | $result = 'dateTime()'; 82 | } 83 | elseif($column->type == 'BigInt' && str($column->name)->matches('/_id$/')){ 84 | return str($column->name)->replace('_id','')->camel()->ucfirst().'::factory()->create()->id'; 85 | } 86 | elseif(str($column->type)->matches('/Int/')){ 87 | $result = 'randomDigit'; 88 | } 89 | elseif(str($column->type)->matches('/Float|Decimal/')){ 90 | $result = 'randomFloat()'; 91 | } 92 | else { 93 | $result = 'word'; 94 | } 95 | if($column->nullable){ 96 | $result = 'optional()->'.$result; 97 | 98 | } 99 | return '$this->faker->'.$result; 100 | } 101 | @endphp 102 | 103 | class {{$model->name}}Factory extends Factory 104 | { 105 | /** 106 | * The name of the factory's corresponding model. 107 | * 108 | * @var string 109 | */ 110 | protected $model = {{$model->name}}::class; 111 | 112 | /** 113 | * Define the model's default state. 114 | * 115 | * @return array 116 | */ 117 | public function definition() 118 | { 119 | return [ 120 | @foreach($columns as $column) 121 | '{{$column->name}}' => {!!fakerType($column)!!}, 122 | @endforeach 123 | @foreach($model->relations as $rel) 124 | //{{$rel->name}} {{$rel->type}} {{$rel->model->name}} {{$rel->local_key}} 125 | @endforeach 126 | ]; 127 | 128 | } 129 | } -------------------------------------------------------------------------------- /resources/views/blade/lang/en/Models.blade.php: -------------------------------------------------------------------------------- 1 | {!! code()->PHPSOL() !!} 2 | 3 | return [ 4 | 'singular' => '{{str($model->name)->human()->title()}}', 5 | 'plural' => '{{str($model->name)->plural()->human()->title()}}', 6 | //Fields 7 | @foreach($model->table->columns as $column) 8 | '{{str($column->name)->snake()}}' => '{{str($column->name)->human()->title()}}', 9 | @endforeach 10 | //Relations 11 | @foreach($model->relations as $rel) 12 | '{{str($rel->name)->snake()}}' => '{{str($rel->name)->human()->title()}}', 13 | @endforeach 14 | //Custom 15 | ]; -------------------------------------------------------------------------------- /resources/views/blade/routes.blade.txt: -------------------------------------------------------------------------------- 1 | # {{str($model->name)->title()}} Routes for web.php 2 | use App\Http\Controllers; 3 | 4 | Route::resource('{{str($model->name)->plural()->slug()}}', Controllers\{{$model->name}}Controller::class); 5 | 6 | #--------------------------------------------------# 7 | @if($options->livewire) 8 | # {{str($model->name)->title()}} Livewire Routes for web.php 9 | use App\Http\Livewire; 10 | 11 | Route::get('{{str($model->name)->snake()->plural()}}', Livewire\{{str($model->name)->plural()}}\Index::class); 12 | @endif 13 | 14 | #--------------------------------------------------# 15 | # {{str($model->name)->title()}} Routes for api.php 16 | use App\Http\Controllers\API; 17 | 18 | Route::apiResource('{{str($model->name)->plural()->slug()}}', API\{{$model->name}}Controller::class); -------------------------------------------------------------------------------- /resources/views/blade/tests/Feature/Http/Controllers/API/ModelControllerTest.blade.php: -------------------------------------------------------------------------------- 1 | {!!code()->PHPSOL()!!} 2 | 3 | namespace Tests\Feature\Http\API\Controllers; 4 | 5 | use Illuminate\Foundation\Testing\RefreshDatabase; 6 | use Tests\TestCase; 7 | use {{$model->complete_name}}; 8 | use {{$model->namespace}}\User; 9 | @if($options->auth) 10 | use Laravel\Passport\Passport; 11 | @endif 12 | 13 | class {{$model->name}}ControllerTest extends TestCase 14 | { 15 | use RefreshDatabase; 16 | 17 | /** 18 | * @test 19 | */ 20 | public function it_stores_{{str($model->name)->snake()}}_api() 21 | { 22 | @if($options->auth) 23 | Passport::actingAs(User::factory()->create(), ['api/{{str($model->name)->plural()->slug()}}']); 24 | @endif 25 | ${{str($model->name)->camel()}} = {{$model->name}}::factory()->make(); 26 | $data = ${{str($model->name)->camel()}}->attributesToArray(); 27 | $response = $this->json('POST','api/{{str($model->name)->plural()->slug()}}',$data); 28 | $response->assertStatus(201)->assertJson(['created_at'=>true]); 29 | } 30 | 31 | /** 32 | * @test 33 | */ 34 | public function it_updates_{{str($model->name)->snake()}}_api() 35 | { 36 | @if($options->auth) 37 | Passport::actingAs(User::factory()->create(), ['api/{{str($model->name)->plural()->slug()}}']); 38 | @endif 39 | ${{str($model->name)->camel()}} = {{$model->name}}::factory()->create(); 40 | $data = {{$model->name}}::factory()->make()->attributesToArray(); 41 | $response = $this->json('PUT','api/{{str($model->name)->plural()->slug()}}/'.${{str($model->name)->camel()}}->id,$data); 42 | $response->assertStatus(200)->assertJson(['updated_at'=>true]); 43 | } 44 | 45 | /** 46 | * @test 47 | */ 48 | public function it_destroys_{{str($model->name)->snake()}}_api() 49 | { 50 | @if($options->auth) 51 | Passport::actingAs(User::factory()->create(), ['api/{{str($model->name)->plural()->slug()}}']); 52 | @endif 53 | ${{str($model->name)->camel()}} = {{$model->name}}::factory()->create(); 54 | $response = $this->json('DELETE','api/{{str($model->name)->plural()->slug()}}/'.${{str($model->name)->camel()}}->id); 55 | $response->assertStatus(200)->assertJson(['deleted_at'=>true]); 56 | ${{str($model->name)->camel()}}->refresh(); 57 | @if(collect($model->table->columns)->contains('name','deleted_at')) 58 | $this->assertSoftDeleted('{{str($model->name)->plural()->snake()}}',['id' => ${{str($model->name)->camel()}}->id]); 59 | @else 60 | $this->assertDatabaseMissing('{{str($model->name)->plural()->snake()}}',['id' => ${{str($model->name)->camel()}}->id]); 61 | @endif 62 | 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /resources/views/blade/tests/Feature/Http/Controllers/ModelControllerTest.blade.php: -------------------------------------------------------------------------------- 1 | {!!code()->PHPSOL()!!} 2 | 3 | namespace Tests\Feature\Http\Controllers; 4 | 5 | use Illuminate\Foundation\Testing\RefreshDatabase; 6 | use Tests\TestCase; 7 | use {{$model->complete_name}}; 8 | @if($options->auth) 9 | use {{$model->namespace}}\User; 10 | @endif 11 | 12 | class {{$model->name}}ControllerTest extends TestCase 13 | { 14 | use RefreshDatabase; 15 | 16 | /** 17 | * @test 18 | */ 19 | public function it_stores_{{str($model->name)->snake()}}_and_redirects_web() 20 | { 21 | @if($options->auth) 22 | $user = User::factory()->create(); 23 | $response = $this->actingAs($user); 24 | @endif 25 | 26 | ${{str($model->name)->camel()}} = {{$model->name}}::factory()->make(); 27 | $data = ${{str($model->name)->camel()}}->attributesToArray(); 28 | $response = $this->post(route('{{str($model->name)->plural()->slug()}}.store'), $data); 29 | $response->assertRedirect(route('{{str($model->name)->plural()->slug()}}.index')); 30 | $response->assertSessionHas('status', '{{$model->name}} created!'); 31 | } 32 | 33 | /** 34 | * @test 35 | */ 36 | public function it_updates_{{str($model->name)->snake()}}_and_redirects_web() 37 | { 38 | @if($options->auth) 39 | $user = User::factory()->create(); 40 | $response = $this->actingAs($user); 41 | @endif 42 | ${{str($model->name)->camel()}} = {{$model->name}}::factory()->create(); 43 | $data = {{$model->name}}::factory()->make()->attributesToArray(); 44 | $response = $this->put(route('{{str($model->name)->slug()->plural()}}.update', ['{{str($model->name)->snake()}}' => ${{str($model->name)->camel()}}]), $data); 45 | $response->assertRedirect(route('{{str($model->name)->slug()->plural()}}.index')); 46 | $response->assertSessionHas('status', '{{$model->name}} updated!'); 47 | } 48 | 49 | /** 50 | * @test 51 | */ 52 | public function it_destroys_{{str($model->name)->snake()}}_and_redirects_web() 53 | { 54 | @if($options->auth) 55 | $user = User::factory()->create(); 56 | $response = $this->actingAs($user); 57 | @endif 58 | ${{str($model->name)->camel()}} = {{$model->name}}::factory()->create(); 59 | $response = $this->delete(route('{{str($model->name)->slug()->plural()}}.destroy', ['{{str($model->name)->snake()}}' => ${{str($model->name)->camel()}}])); 60 | $response->assertRedirect(route('{{str($model->name)->slug()->plural()}}.index')); 61 | $response->assertSessionHas('status', '{{$model->name}} destroyed!'); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /resources/views/blade/views/create.blade.php: -------------------------------------------------------------------------------- 1 | @if($options->auth) 2 | {!!code()->tag('x-app-layout')!!} 3 | @else 4 | {!!code()->tag('x-guest-layout')!!} 5 | @endif 6 | 7 |
8 |
9 |
10 |

{{str($model->name)->human()->title()}}

11 | @@if ($errors->any()) 12 |
    13 | @@foreach ($errors->all() as $error) 14 |
  • @{{ $error }}
  • 15 | @@endforeach 16 |
17 | @@endif 18 |
19 | 20 |
21 |
22 |
23 | 24 | @@csrf 25 | @foreach($model->relations as $rel) 26 | @if($rel->type === 'BelongsTo') 27 |
28 | 29 | 37 |
38 | @endif 39 | @endforeach 40 | 41 | @foreach($model->table->columns as $column) 42 | @if(!str($column->name)->matches('/id$/') && !str($column->name)->matches('/created_at$/') && !str($column->name)->matches('/updated_at$/') && !str($column->name)->matches('/deleted_at$/')) 43 |
44 | 45 | @if($column->type=='Text') 46 | 47 | @else 48 | type == 'String') 49 | type="text" 50 | maxlength="{{$column->length}}" 51 | @elseif(str($column->type)->matches('/Date/')) 52 | type="date" 53 | @elseif(str($column->type)->matches('/Int/')) 54 | type="number" 55 | @elseif(str($column->type)->matches('/Decimal|Float/')) 56 | type="number" 57 | step="0.01" 58 | @endif 59 | class="mt-1 focus:ring-blue-500 focus:border-blue-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded {{$column->type}}" 60 | @if(!$column->nullable) 61 | required="required" 62 | @endif 63 | > 64 | @endif 65 | @@if($errors->has('{{$column->name}}')) 66 |

{{code()->doubleCurlyOpen()}}$errors->first('{{$column->name}}'){{code()->doubleCurlyClose()}}

67 | @@endif 68 |
69 | @endif 70 | @endforeach 71 |
72 |
73 | Back 74 | 75 |
76 |
77 |
78 |
79 |
80 | @if($options->auth) 81 | {!!code()->tag('/x-app-layout')!!} 82 | @else 83 | {!!code()->tag('/x-guest-layout')!!} 84 | @endif -------------------------------------------------------------------------------- /resources/views/blade/views/edit.blade.php: -------------------------------------------------------------------------------- 1 | @if($options->auth) 2 | {!!code()->tag('x-app-layout')!!} 3 | @else 4 | {!!code()->tag('x-guest-layout')!!} 5 | @endif 6 | 7 |
8 |
9 |
10 |

{{str($model->name)->title()}} Edit

11 | @@if ($errors->any()) 12 |
    13 | @@foreach ($errors->all() as $error) 14 |
  • @{{ $error }}
  • 15 | @@endforeach 16 |
17 | @@endif 18 |
19 |
20 |
21 |
22 | 23 | @@csrf 24 | @@method('PUT') 25 | @foreach($model->relations as $rel) 26 | @if($rel->type === 'BelongsTo') 27 |
28 | 29 | 41 |
42 | @endif 43 | @endforeach 44 | 45 | 46 | @foreach($model->table->columns as $column) 47 | @if(!str($column->name)->matches('/id$/') && !str($column->name)->matches('/created_at$/') && !str($column->name)->matches('/updated_at$/') && !str($column->name)->matches('/deleted_at$/')) 48 |
49 | 50 | @if($column->type=='Text') 51 | 52 | @else 53 | type == 'String') 56 | type="text" 57 | maxlength="{{$column->length}}" 58 | @elseif(str($column->type)->matches('/Date/')) 59 | type="date" 60 | @elseif(str($column->type)->matches('/Int/')) 61 | type="number" 62 | @elseif(str($column->type)->matches('/Decimal|Float/')) 63 | type="number" 64 | step="0.01" 65 | @endif 66 | class="mt-1 focus:ring-blue-500 focus:border-blue-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded {{$column->type}}" 67 | @if(!$column->nullable) 68 | required="required" 69 | @endif 70 | value="{{code()->doubleCurlyOpen()}}old('{{$column->name}}',${{str($model->name)->snake()}}->{{$column->name}}){{code()->doubleCurlyClose()}}" 71 | > 72 | @endif 73 | @@if($errors->has('{{$column->name}}')) 74 |

{{code()->doubleCurlyOpen()}}$errors->first('{{$column->name}}'){{code()->doubleCurlyClose()}}

75 | @@endif 76 |
77 | @endif 78 | @endforeach 79 |
80 |
81 | Back 82 | 83 |
84 |
85 |
86 |
87 | @if($options->auth) 88 | {!!code()->tag('/x-app-layout')!!} 89 | @else 90 | {!!code()->tag('/x-guest-layout')!!} 91 | @endif -------------------------------------------------------------------------------- /resources/views/blade/views/index.blade.php: -------------------------------------------------------------------------------- 1 | @if($options->auth) 2 | {!!code()->tag('x-app-layout')!!} 3 | @else 4 | {!!code()->tag('x-guest-layout')!!} 5 | @endif 6 | 7 |
8 | @@if (session('status')) 9 |
10 |
11 | @{{ session('status') }} 12 |
13 |
14 | @@endif 15 |
16 |
17 |

{{str($model->name)->human()->title()->plural()}}

18 | {!!code()->tag('x-slot name="header"')!!} {{str($model->name)->human()->plural()->title()}} {!! code()->tag('/x-slot') !!} 19 |
20 | 23 | 24 |
25 | 26 | @@if(count(${{str($model->name)->snake()->plural()}})) 27 | 28 | 29 | 30 | @foreach($model->table->columns as $column) 31 | @if(!str($column->name)->matches('/id$/')&&!str($column->name)->matches('/_at$/')) 32 | 33 | @endif 34 | @endforeach 35 | 36 | 37 | @@endif 38 | 39 | @@forelse(${{str($model->name)->snake()->plural()}} as ${{str($model->name)->snake()}}) 40 | 41 | 55 | @foreach($model->table->columns as $column) 56 | @if(!str($column->name)->matches('/id$/')&&!str($column->name)->matches('/_at$/')) 57 | 58 | @endif 59 | @endforeach 60 | 61 | 62 | @@empty 63 |

No {{str($model->name)->title()->plural()}}

64 | @@endforelse 65 | 66 |
 {{str($column->name)->human()->title()}}
42 | 50 | 54 | {{code()->doubleCurlyOpen()}}${{str($model->name)->snake()}}->{{$column->name}}{{code()->doubleCurlyClose()}}
67 |
68 |
69 | {{code()->doubleCurlyOpen()}} ${{str($model->name)->plural->snake()}}->links() {{code()->doubleCurlyClose()}} 70 |
71 |
72 | 73 |
74 | @if($options->auth) 75 | {!!code()->tag('/x-app-layout')!!} 76 | @else 77 | {!!code()->tag('/x-guest-layout')!!} 78 | @endif -------------------------------------------------------------------------------- /resources/views/blade/views/show.blade.php: -------------------------------------------------------------------------------- 1 | @if($options->auth) 2 | {!!code()->tag('x-app-layout')!!} 3 | @else 4 | {!!code()->tag('x-guest-layout')!!} 5 | @endif 6 | 7 |
8 |
9 |
10 |

{{str($model->name)->human()->title()}}

11 | @@if ($errors->any()) 12 |
    13 | @@foreach ($errors->all() as $error) 14 |
  • @{{ $error }}
  • 15 | @@endforeach 16 |
17 | @@endif 18 |
19 |
20 |
21 |
22 | @foreach($model->relations as $rel) 23 | @if($rel->type === 'BelongsTo') 24 |
25 | 26 | @@foreach((\{{$rel->model->complete_name}}::all() ?? [] ) as ${{$rel->name}}) 27 | @@if(${{str($model->name)->snake()}}->{{$rel->local_key}} == ${{$rel->name}}->id) 28 | 29 | {{code()->doubleCurlyOpen()}}${{$rel->name}}->{{collect($rel->model->table->columns)->filter(fn($col,$key) => ($col->type == 'String') )->map(function($col){ return $col->name;})->first()}}{{code()->doubleCurlyClose()}} 30 | 31 | @@endif 32 | @@endforeach 33 | 34 |
35 | @endif 36 | @endforeach 37 | 38 | @foreach($model->table->columns as $column) 39 | @if(!str($column->name)->matches('/id$/') && !str($column->name)->matches('/created_at$/') && !str($column->name)->matches('/updated_at$/') && !str($column->name)->matches('/deleted_at$/')) 40 |
41 | 42 | @if(str($column->type)->matches('/Text/')) 43 | 44 | @else 45 | type == 'String') 46 | type="text" 47 | maxlength="{{$column->length}}" 48 | @elseif(str($column->type)->matches('/Date/')) 49 | type="date" 50 | @elseif(str($column->type)->matches('/Int/')) 51 | type="number" 52 | @elseif(str($column->type)->matches('/Decimal|Float/')) 53 | type="number" 54 | step="0.01" 55 | @endif 56 | class="mt-1 block w-full sm:text-sm border-transparent focus:ring-transparent focus:outline-none focus:border-transparent rounded {{$column->type}}" 57 | @if(!$column->nullable) 58 | required="required" 59 | @endif 60 | value="{{code()->doubleCurlyOpen()}}old('{{$column->name}}',${{str($model->name)->snake()}}->{{$column->name}}){{code()->doubleCurlyClose()}}" 61 | > 62 | @endif 63 | @@if($errors->has('{{$column->name}}')) 64 |

{{code()->doubleCurlyOpen()}}$errors->first('{{$column->name}}'){{code()->doubleCurlyClose()}}

65 | @@endif 66 |
67 | @endif 68 | @endforeach 69 |
70 | 74 |
75 |
76 |
77 | 78 |
79 | @foreach($model->relations as $rel) 80 | @if($rel->type === 'HasMany') 81 |

{{str($rel->name)->human()->title()}} ({{code()->doubleCurlyOpen()}}${{str($model->name)->camel()}}->{{str($rel->model->name)->snake()->plural()}}->count(){{code()->doubleCurlyClose()}})

82 | 83 | 84 | 85 | 86 | @foreach($rel->model->table->columns as $column) 87 | @if($column->type === 'String' || $column->type === 'Text') 88 | 89 | @endif 90 | @endforeach 91 | 92 | 93 | 94 | @@foreach(${{str($model->name)->camel()}}->{{str($rel->name)->snake()}} as ${{str($rel->name)->singular()}}) 95 | 96 | 110 | @foreach($rel->model->table->columns as $column) 111 | @if($column->type === 'String' || $column->type === 'Text') 112 | 113 | @endif 114 | @endforeach 115 | 116 | 117 | @@endforeach 118 | 119 |
  {{str($column->name)->human()->title()}}
97 | 105 | 109 | {{code()->doubleCurlyOpen()}} ${{str($rel->model->name)->camel()}}->{{$column->name}}{{code()->doubleCurlyClose()}}
120 | @endif 121 | @endforeach 122 |
123 | 124 | @if($options->auth) 125 | {!!code()->tag('/x-app-layout')!!} 126 | @else 127 | {!!code()->tag('/x-guest-layout')!!} 128 | @endif -------------------------------------------------------------------------------- /resources/views/inertia/Events/ModelEvent.blade.php: -------------------------------------------------------------------------------- 1 | {!!CodeHelper::PHPSOL()!!} 2 | 3 | namespace App\Events; 4 | 5 | use Illuminate\Broadcasting\Channel; 6 | use Illuminate\Broadcasting\InteractsWithSockets; 7 | use Illuminate\Broadcasting\PresenceChannel; 8 | use Illuminate\Broadcasting\PrivateChannel; 9 | use Illuminate\Contracts\Broadcasting\ShouldBroadcast; 10 | use Illuminate\Foundation\Events\Dispatchable; 11 | use Illuminate\Queue\SerializesModels; 12 | use {{$model->complete_name}}; 13 | 14 | class {{$model->name}}{{$options->event}} 15 | { 16 | use Dispatchable, InteractsWithSockets, SerializesModels; 17 | 18 | protected ${{str($model->name)->camel()}}; 19 | /** 20 | * Create a new event instance. 21 | * 22 | * @return void 23 | */ 24 | public function __construct({{$model->name}} ${{str($model->name)->camel()}}) 25 | { 26 | $this->{{str($model->name)->camel()}} = ${{str($model->name)->camel()}}; 27 | } 28 | 29 | /** 30 | * Get the channels the event should broadcast on. 31 | * 32 | * @return \Illuminate\Broadcasting\Channel|array 33 | */ 34 | public function broadcastOn() 35 | { 36 | return new PrivateChannel('channel-name'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /resources/views/inertia/Http/Controllers/ModelController.blade.php: -------------------------------------------------------------------------------- 1 | {!! code()->PHPSOL() !!} 2 | 3 | namespace App\Http\Controllers; 4 | 5 | use {{$model->complete_name}}; 6 | use Illuminate\Http\Request; 7 | use App\Http\Requests\{{$model->name}}Request; 8 | use Illuminate\Support\Facades\Redirect; 9 | use Inertia\Inertia; 10 | @if($options->notification) 11 | use App\Notifications\{{$model->name}}{{$options->notification}}; 12 | @endif 13 | @if($options->event) 14 | use App\Events\{{$options->event}}; 15 | @endif 16 | 17 | class {{$model->name}}Controller extends Controller 18 | { 19 | @if($options->auth) 20 | public function __construct() 21 | { 22 | $this->middleware('auth'); 23 | } 24 | @endif 25 | 26 | public function index() 27 | { 28 | return Inertia::render('{{str($model->name)->plural()}}/Index', ['{{str($model->name)->snake()->plural()}}'=>{{$model->name}}::paginate(25)]); 29 | } 30 | 31 | public function create() 32 | { 33 | return Inertia::render('{{str($model->name)->plural()}}/Create'); 34 | } 35 | 36 | public function store({{$model->name}}Request $request) 37 | { 38 | $data = $request->validated(); 39 | ${{str($model->name)->snake()}} = {{$model->name}}::create($data); 40 | 41 | @if($options->notification) 42 | //auth()->user->notify(new {{$model->name}}{{$options->notification}}(${{str($model->name)->snake()}})); 43 | @endif 44 | @if($options->event) 45 | event(new {{$options->event}}(${{str($model->name)->snake()}})); 46 | @endif 47 | 48 | return Redirect::route('{{str($model->name)->snake()->slug()->plural()}}.index')->with('status', '{{str($model->name)->human()}} created!'); 49 | } 50 | 51 | public function edit(Request $request, {{$model->name}} ${{str($model->name)->snake()}}) 52 | { 53 | @php 54 | $rels = collect($model->relations)->filter(function($rel){ return $rel->type === 'HasMany'; }); 55 | $rels_names = $rels->pluck('name'); 56 | $relations = $rels->map(function($rel){ return "'".$rel->name."' => $".$rel->name; })->implode(', '); 57 | @endphp 58 | @foreach($rels_names as $name) 59 | ${{$name}} = {{$model->name}}::find(${{str($model->name)->snake()}}->id)->{{$name}}()->paginate(25); 60 | @endforeach 61 | 62 | return Inertia::render('{{str($model->name)->plural()}}/Edit', ['{{str($model->name)->snake()}}'=>${{str($model->name)->snake()}}, {!!$relations!!}]); 63 | } 64 | 65 | public function update({{$model->name}}Request $request, {{$model->name}} ${{str($model->name)->snake()}}) 66 | { 67 | $data = $request->validated(); 68 | ${{str($model->name)->snake()}}->fill($data); 69 | ${{str($model->name)->snake()}}->save(); 70 | 71 | return Redirect::route('{{str($model->name)->snake()->slug()->plural()}}.index')->with('status', '{{str($model->name)->human()}} updated!'); 72 | } 73 | 74 | public function destroy(Request $request, {{$model->name}} ${{str($model->name)->snake()}}) 75 | { 76 | ${{str($model->name)->snake()}}->delete(); 77 | 78 | return Redirect::route('{{str($model->name)->snake()->slug()->plural()}}.index')->with('status', '{{str($model->name)->human()}} deleted!'); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /resources/views/inertia/Http/Requests/ModelRequest.blade.php: -------------------------------------------------------------------------------- 1 | {!! CodeHelper::PHPSOL() !!} 2 | 3 | namespace App\Http\Requests; 4 | 5 | use Illuminate\Foundation\Http\FormRequest; 6 | 7 | class {{$model->name}}Request extends FormRequest 8 | { 9 | /** 10 | * Determine if the user is authorized to make this request. 11 | * 12 | * @return bool 13 | */ 14 | public function authorize() 15 | { 16 | return true; 17 | } 18 | 19 | /** 20 | * Get the validation rules that apply to the request. 21 | * 22 | * @return array 23 | */ 24 | public function rules() 25 | { 26 | return [ 27 | @foreach($model->table->columns as $col) 28 | @if(!str($col->name)->matches('/^id$/') && !str($col->name)->matches('/created_at$/') && !str($col->name)->matches('/updated_at$/') && !str($col->name)->matches('/deleted_at$/')) 29 | @if(!$col->nullable) 30 | '{{$col->name}}' => [ 31 | 'required', 32 | ], 33 | @else 34 | '{{$col->name}}' => [ 35 | 'nullable', 36 | ], 37 | @endif 38 | @endif 39 | @endforeach 40 | ]; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /resources/views/inertia/Notifications/ModelNotification.blade.php: -------------------------------------------------------------------------------- 1 | {!!code()->PHPSOL()!!} 2 | 3 | namespace App\Notifications; 4 | 5 | use Illuminate\Bus\Queueable; 6 | use Illuminate\Contracts\Queue\ShouldQueue; 7 | use Illuminate\Notifications\Messages\MailMessage; 8 | use Illuminate\Notifications\Notification; 9 | use {{$model->complete_name}}; 10 | 11 | class {{$model->name}}{{$options->notification}} extends Notification 12 | { 13 | use Queueable; 14 | 15 | protected ${{str($model->name)->camel()}}; 16 | /** 17 | * Create a new notification instance. 18 | * 19 | * @return void 20 | */ 21 | public function __construct({{$model->name}} ${{str($model->name)->camel()}}) 22 | { 23 | $this->${{str($model->name)->camel()}} = ${{str($model->name)->camel()}}; 24 | } 25 | 26 | /** 27 | * Get the notification's delivery channels. 28 | * 29 | * @param mixed $notifiable 30 | * @return array 31 | */ 32 | public function via($notifiable) 33 | { 34 | return ['mail']; 35 | } 36 | 37 | /** 38 | * Get the mail representation of the notification. 39 | * 40 | * @param mixed $notifiable 41 | * @return \Illuminate\Notifications\Messages\MailMessage 42 | */ 43 | public function toMail($notifiable) 44 | { 45 | return (new MailMessage($this->{{str($model->name)->camel()}})) 46 | ->line('The introduction to the notification.') 47 | ->action('Notification Action', url('/')) 48 | ->line('Thank you for using our application!'); 49 | } 50 | 51 | /** 52 | * Get the array representation of the notification. 53 | * 54 | * @param mixed $notifiable 55 | * @return array 56 | */ 57 | public function toArray($notifiable) 58 | { 59 | return [ 60 | // 61 | ]; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /resources/views/inertia/database/factories/ModelFactory.blade.php: -------------------------------------------------------------------------------- 1 | {!!code()->PHPSOL()!!} 2 | 3 | namespace Database\Factories; 4 | 5 | use {{$model->complete_name}}; 6 | use Illuminate\Database\Eloquent\Factories\Factory; 7 | @foreach($model->relations as $rel) 8 | use {{$rel->model->complete_name}}; 9 | @endforeach 10 | 11 | @php 12 | $columns = collect($model->table->columns); 13 | $columns = $columns->filter(function($c){ 14 | return ($c->name != 'id' && $c->name != 'created_at' && $c->name != 'updated_at' && $c->name != 'deleted_at'); 15 | }); 16 | 17 | function fakerType($column){ 18 | if($column->type == 'String'){ 19 | if(str($column->name)->matches('/password/') ){ 20 | $result = 'bcrypt($this->faker->password)'; 21 | } 22 | elseif(str($column->name)->matches('/slug/') ){ 23 | $result = 'slug()'; 24 | } 25 | elseif(str($column->name)->matches('/email/') ){ 26 | $result = 'safeEmail()'; 27 | } 28 | elseif(str($column->name)->matches('/username/') ){ 29 | $result = 'userName()'; 30 | } 31 | elseif(str($column->name)->matches('/last.*name/') ){ 32 | $result = 'lastName()'; 33 | } 34 | elseif(str($column->name)->matches('/first.?name/') ){ 35 | $result = 'firstName()'; 36 | } 37 | elseif(str($column->name)->matches('/phone|mobile/') ){ 38 | $result = 'phoneNumber()'; 39 | } 40 | elseif(str($column->name)->matches('/photo/') ){ 41 | $result = "imageUrl(640,480,'people')"; 42 | } 43 | elseif(str($column->name)->matches('/name/') ){ 44 | $result = 'name()'; 45 | } 46 | elseif(str($column->name)->matches('/img.*url|image.*url/') ){ 47 | $result = 'imageUrl()'; 48 | } 49 | elseif(str($column->name)->matches('/image|img/') ){ 50 | $result = 'imageUrl()'; 51 | } 52 | elseif(str($column->name)->matches('/file|path/') ){ 53 | $result = 'file()'; 54 | } 55 | elseif(str($column->name)->matches('/url/') ){ 56 | $result = 'url'; 57 | } 58 | elseif(str($column->name)->matches('/domain/') ){ 59 | $result = 'domainName'; 60 | } 61 | elseif(str($column->name)->matches('/color/') ){ 62 | $result = 'hexcolor'; 63 | } 64 | elseif(str($column->name)->matches('/token/') ){ 65 | $result = 'md5'; 66 | } 67 | elseif($column->length > 255){ 68 | $result = 'sentence'; 69 | } 70 | else { 71 | $result = 'text()'; 72 | } 73 | } 74 | elseif($column->type == 'Text'){ 75 | $result = 'text(1024)'; 76 | } 77 | elseif($column->type == 'Boolean'){ 78 | $result = 'boolean'; 79 | } 80 | elseif($column->type == 'DateTime'){ 81 | $result = 'dateTime()'; 82 | } 83 | elseif($column->type == 'BigInt' && str($column->name)->matches('/_id$/')){ 84 | return str($column->name)->replace('_id','')->camel()->ucfirst().'::factory()->create()->id'; 85 | } 86 | elseif(str($column->type)->matches('/Int/')){ 87 | $result = 'randomDigit'; 88 | } 89 | elseif(str($column->type)->matches('/Float|Decimal/')){ 90 | $result = 'randomFloat()'; 91 | } 92 | else { 93 | $result = 'word'; 94 | } 95 | if($column->nullable){ 96 | $result = 'optional()->'.$result; 97 | 98 | } 99 | return '$this->faker->'.$result; 100 | } 101 | @endphp 102 | 103 | class {{$model->name}}Factory extends Factory 104 | { 105 | /** 106 | * The name of the factory's corresponding model. 107 | * 108 | * @var string 109 | */ 110 | protected $model = {{$model->name}}::class; 111 | 112 | /** 113 | * Define the model's default state. 114 | * 115 | * @return array 116 | */ 117 | public function definition() 118 | { 119 | return [ 120 | @foreach($columns as $column) 121 | '{{$column->name}}' => {!!fakerType($column)!!}, 122 | @endforeach 123 | @foreach($model->relations as $rel) 124 | //{{$rel->name}} {{$rel->type}} {{$rel->model->name}} {{$rel->local_key}} 125 | @endforeach 126 | ]; 127 | 128 | } 129 | } -------------------------------------------------------------------------------- /resources/views/inertia/lang/en/Models.blade.php: -------------------------------------------------------------------------------- 1 | {!! code()->PHPSOL() !!} 2 | 3 | return [ 4 | 'singular' => '{{str($model->name)->human()->title()}}', 5 | 'plural' => '{{str($model->name)->plural()->human()->title()}}', 6 | //Fields 7 | @foreach($model->table->columns as $column) 8 | '{{str($column->name)->snake()}}' => '{{str($column->name)->human()->title()}}', 9 | @endforeach 10 | //Relations 11 | @foreach($model->relations as $rel) 12 | '{{str($rel->name)->snake()}}' => '{{str($rel->name)->human()->title()}}', 13 | @endforeach 14 | //Custom 15 | ]; -------------------------------------------------------------------------------- /resources/views/inertia/resources/js/Components/CheckboxInput.vue: -------------------------------------------------------------------------------- 1 | 15 | 33 | -------------------------------------------------------------------------------- /resources/views/inertia/resources/js/Components/Container.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /resources/views/inertia/resources/js/Components/FlashAlert.vue: -------------------------------------------------------------------------------- 1 | 36 | 37 | 54 | -------------------------------------------------------------------------------- /resources/views/inertia/resources/js/Components/Pagination.vue: -------------------------------------------------------------------------------- 1 | 39 | 40 | 48 | -------------------------------------------------------------------------------- /resources/views/inertia/resources/js/Components/SelectInput.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 32 | -------------------------------------------------------------------------------- /resources/views/inertia/resources/js/Components/TableBase.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 49 | -------------------------------------------------------------------------------- /resources/views/inertia/resources/js/Components/TextInput.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 44 | -------------------------------------------------------------------------------- /resources/views/inertia/resources/js/Components/TextareaInput.vue: -------------------------------------------------------------------------------- 1 |