phases 8
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
return ['name' => 'Products'];
|
||||
@@ -0,0 +1,10 @@
|
||||
<?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('products', function (Blueprint $table): void { $table->id(); $table->string('name'); $table->boolean('is_active')->default(true); $table->timestamps(); }); }
|
||||
public function down(): void { Schema::dropIfExists('products'); }
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Products\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\View\View;
|
||||
use Modules\Products\Http\Requests\StoreProductRequest;
|
||||
use Modules\Products\Models\Product;
|
||||
|
||||
final class ProductController
|
||||
{
|
||||
public function index(): View
|
||||
{
|
||||
return view('products::admin.products.index', ['records' => Product::query()->latest()->paginate()]);
|
||||
}
|
||||
|
||||
public function store(StoreProductRequest $request): RedirectResponse
|
||||
{
|
||||
Product::query()->create($request->validated());
|
||||
return back()->with('status', 'Product created.');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Products\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
final class StoreProductRequest extends FormRequest
|
||||
{
|
||||
public function authorize(): bool { return $this->user() !== null; }
|
||||
public function rules(): array { return ['name' => ['required', 'string', 'max:255'], 'is_active' => ['sometimes', 'boolean']]; }
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Products\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
final class Product extends Model
|
||||
{
|
||||
protected $guarded = [];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return ['is_active' => 'boolean'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Products\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
final class ProductsServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function register(): void
|
||||
{
|
||||
$this->app->register(RouteServiceProvider::class);
|
||||
$this->mergeConfigFrom(module_path('Products', 'Config/config.php'), 'products');
|
||||
}
|
||||
|
||||
public function boot(): void
|
||||
{
|
||||
$this->loadMigrationsFrom(module_path('Products', 'Database/Migrations'));
|
||||
$this->loadViewsFrom(module_path('Products', 'Resources/views'), 'products');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Products\Providers;
|
||||
|
||||
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
final class RouteServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function boot(): void
|
||||
{
|
||||
Route::middleware('web')->group(module_path('Products', 'Routes/web.php'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<form method="POST">@csrf<flux:input name="name" :label="__('Name')" required /><flux:button type="submit" variant="primary">{{ __('Save Product') }}</flux:button></form>
|
||||
@@ -0,0 +1,3 @@
|
||||
<x-layouts.app :title="__('Product')">
|
||||
<div class="space-y-6"><h1 class="text-2xl font-semibold">Product</h1>@foreach ($records as $record)<div>{{ $record->name }}</div>@endforeach{{ $records->links() }}</div>
|
||||
</x-layouts.app>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::middleware(['web', 'auth'])->prefix('administration/products')->name('administration.products.')->group(function (): void {
|
||||
// Register module routes here.
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
use Modules\Products\Models\Product;
|
||||
|
||||
it('can create a Product', function (): void { expect(Product::query()->create(['name' => 'Example']))->toBeInstanceOf(Product::class); });
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
it('boots the Products module', function (): void {
|
||||
expect(app()->providerIsLoaded(Modules\Products\Providers\ProductsServiceProvider::class))->toBeTrue();
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "Products",
|
||||
"alias": "products",
|
||||
"version": "1.0.0",
|
||||
"description": "Products module.",
|
||||
"keywords": [
|
||||
"products"
|
||||
],
|
||||
"priority": 100,
|
||||
"providers": [
|
||||
"Modules\\Products\\Providers\\ProductsServiceProvider"
|
||||
],
|
||||
"aliases": {},
|
||||
"files": [],
|
||||
"requires": [
|
||||
"Core",
|
||||
"Administration"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
# Corporate Theme
|
||||
|
||||
Generated by `php artisan theme:make corporate`.
|
||||
@@ -0,0 +1 @@
|
||||
:root { --theme-radius: 0.5rem; }
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "Corporate",
|
||||
"slug": "corporate",
|
||||
"version": "1.0.0",
|
||||
"parent": "common"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<x-layouts.app><main><h1>{{ config('app.name') }}</h1></main></x-layouts.app>
|
||||
@@ -0,0 +1 @@
|
||||
<!DOCTYPE html><html lang="{{ str_replace('_', '-', app()->getLocale()) }}"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>{{ $title ?? config('app.name') }}</title>@vite(['resources/css/app.css', 'resources/js/app.js'])</head><body>{{ $slot }}</body></html>
|
||||
Reference in New Issue
Block a user