Merge branch 'backend'
This commit is contained in:
commit
068975d3b0
16
backend/app/Actions/CreateProductAction.php
Normal file
16
backend/app/Actions/CreateProductAction.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Actions;
|
||||||
|
|
||||||
|
use App\Data\UploadImageDTO;
|
||||||
|
|
||||||
|
final readonly class CreateProductAction
|
||||||
|
{
|
||||||
|
public function execute(UploadImageDTO $uploadImageDTO): void
|
||||||
|
{
|
||||||
|
$path = $uploadImageDTO->image->store('public/images');
|
||||||
|
$uploadImageDTO->product->images()->create([
|
||||||
|
'path' => $path,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
19
backend/app/Actions/GetAllProductCategory.php
Normal file
19
backend/app/Actions/GetAllProductCategory.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Actions;
|
||||||
|
|
||||||
|
use App\Data\ProductCategoryDTO;
|
||||||
|
use App\Models\ProductCategory;
|
||||||
|
|
||||||
|
final readonly class GetAllProductCategory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Execute the action.
|
||||||
|
*/
|
||||||
|
public function execute(): array
|
||||||
|
{
|
||||||
|
return ProductCategory::all(columns: ['id', 'name', 'slug'])
|
||||||
|
->map(fn ($category) => ProductCategoryDTO::fromModel($category))
|
||||||
|
->toArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
16
backend/app/Actions/UploadImageAction.php
Normal file
16
backend/app/Actions/UploadImageAction.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Actions;
|
||||||
|
|
||||||
|
use App\Data\UploadImageDTO;
|
||||||
|
|
||||||
|
final readonly class UploadImageAction
|
||||||
|
{
|
||||||
|
public function execute(UploadImageDTO $uploadImageDTO): void
|
||||||
|
{
|
||||||
|
$path = $uploadImageDTO->image->store('public/images');
|
||||||
|
$uploadImageDTO->product->images()->create([
|
||||||
|
'path' => $path,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
32
backend/app/Console/Commands/MakeActionCommand.php
Normal file
32
backend/app/Console/Commands/MakeActionCommand.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use Illuminate\Console\GeneratorCommand;
|
||||||
|
|
||||||
|
class MakeActionCommand extends GeneratorCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'make:action {name}';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Create a new action class';
|
||||||
|
|
||||||
|
protected function getStub(): string
|
||||||
|
{
|
||||||
|
return base_path('stubs/action.stub');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getDefaultNamespace($rootNamespace): string
|
||||||
|
{
|
||||||
|
return $rootNamespace.'\Actions';
|
||||||
|
}
|
||||||
|
}
|
||||||
36
backend/app/Data/ProductCategoryDTO.php
Normal file
36
backend/app/Data/ProductCategoryDTO.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Data;
|
||||||
|
|
||||||
|
use App\Contracts\OutputDataTransferObject;
|
||||||
|
use App\Models\ProductCategory;
|
||||||
|
|
||||||
|
final readonly class ProductCategoryDTO implements OutputDataTransferObject
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public int $id,
|
||||||
|
public string $name,
|
||||||
|
public string $slug,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function toArray(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => $this->id,
|
||||||
|
'name' => $this->name,
|
||||||
|
'slug' => $this->slug,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function fromModel(ProductCategory $category): self
|
||||||
|
{
|
||||||
|
return new self(
|
||||||
|
id: $category->id,
|
||||||
|
name: $category->name,
|
||||||
|
slug: $category->slug,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
53
backend/app/Data/ProductDTO.php
Normal file
53
backend/app/Data/ProductDTO.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Data;
|
||||||
|
|
||||||
|
use App\Contracts\OutputDataTransferObject;
|
||||||
|
use App\Models\Product;
|
||||||
|
use App\Models\ProductImage;
|
||||||
|
|
||||||
|
final readonly class ProductDTO implements OutputDataTransferObject
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param ProductImageDTO[] $productImages
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
public int $id,
|
||||||
|
public string $title,
|
||||||
|
public string $description,
|
||||||
|
public int $actualPrice,
|
||||||
|
public int $listPrice,
|
||||||
|
public ProductCategoryDTO $category,
|
||||||
|
public array $productImages,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function toArray(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => $this->id,
|
||||||
|
'title' => $this->title,
|
||||||
|
'description' => $this->description,
|
||||||
|
'actualPrice' => $this->actualPrice,
|
||||||
|
'listPrice' => $this->listPrice,
|
||||||
|
'category' => $this->category->toArray(),
|
||||||
|
'productImage' => array_map(fn (ProductImageDTO $productImage) => $productImage->toArray(),
|
||||||
|
$this->productImages),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function fromModel(Product $product): self
|
||||||
|
{
|
||||||
|
return new self(
|
||||||
|
id: $product->id,
|
||||||
|
title: $product->title,
|
||||||
|
description: $product->description,
|
||||||
|
actualPrice: $product->actual_price,
|
||||||
|
listPrice: $product->list_price,
|
||||||
|
category: ProductCategoryDTO::fromModel($product->category),
|
||||||
|
productImages: $product->images->map(fn (ProductImage $productImage) => ProductImageDTO::fromModel($productImage))->all(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
36
backend/app/Data/ProductImageDTO.php
Normal file
36
backend/app/Data/ProductImageDTO.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Data;
|
||||||
|
|
||||||
|
use App\Contracts\OutputDataTransferObject;
|
||||||
|
use App\Models\ProductImage;
|
||||||
|
|
||||||
|
final readonly class ProductImageDTO implements OutputDataTransferObject
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public ?int $id = null,
|
||||||
|
public ?string $path = null,
|
||||||
|
public ?int $productId = null,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function toArray(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id' => $this->id,
|
||||||
|
'path' => $this->path,
|
||||||
|
'productId' => $this->productId,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function fromModel(ProductImage $productImage): self
|
||||||
|
{
|
||||||
|
return new self(
|
||||||
|
$productImage->id,
|
||||||
|
$productImage->path,
|
||||||
|
$productImage->product_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
22
backend/app/Data/UploadImageDTO.php
Normal file
22
backend/app/Data/UploadImageDTO.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Data;
|
||||||
|
|
||||||
|
use App\Models\Product;
|
||||||
|
use Illuminate\Http\UploadedFile;
|
||||||
|
|
||||||
|
readonly class UploadImageDTO
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public UploadedFile $image,
|
||||||
|
public Product $product,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public static function fromRequest(array $data): self
|
||||||
|
{
|
||||||
|
return new self(
|
||||||
|
image: $data['image'],
|
||||||
|
product: Product::find($data['product_id']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -12,6 +12,7 @@ public function __construct(
|
|||||||
public string $email,
|
public string $email,
|
||||||
public string $mobileNumber,
|
public string $mobileNumber,
|
||||||
public string $city,
|
public string $city,
|
||||||
|
public string $role
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,6 +26,7 @@ public function toArray(): array
|
|||||||
'email' => $this->email,
|
'email' => $this->email,
|
||||||
'mobileNumber' => $this->mobileNumber,
|
'mobileNumber' => $this->mobileNumber,
|
||||||
'city' => $this->city,
|
'city' => $this->city,
|
||||||
|
'role' => $this->role,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
backend/app/Enums/UserRoles.php
Normal file
10
backend/app/Enums/UserRoles.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Enums;
|
||||||
|
|
||||||
|
enum UserRoles: string
|
||||||
|
{
|
||||||
|
case Admin = 'admin';
|
||||||
|
case Customer = 'customer';
|
||||||
|
case Broker = 'broker';
|
||||||
|
}
|
||||||
@ -40,7 +40,8 @@ public function show()
|
|||||||
name: $user->name,
|
name: $user->name,
|
||||||
email: $user->email,
|
email: $user->email,
|
||||||
mobileNumber: $user->mobile_number,
|
mobileNumber: $user->mobile_number,
|
||||||
city: $user->city
|
city: $user->city,
|
||||||
|
role: $user->role->value
|
||||||
);
|
);
|
||||||
|
|
||||||
return response()->json($userDto->toArray());
|
return response()->json($userDto->toArray());
|
||||||
|
|||||||
13
backend/app/Http/Controllers/ProductCategoryController.php
Normal file
13
backend/app/Http/Controllers/ProductCategoryController.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Actions\GetAllProductCategory;
|
||||||
|
|
||||||
|
class ProductCategoryController extends Controller
|
||||||
|
{
|
||||||
|
public function index(GetAllProductCategory $action)
|
||||||
|
{
|
||||||
|
return $action->execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
31
backend/app/Http/Controllers/ProductController.php
Normal file
31
backend/app/Http/Controllers/ProductController.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Data\ProductDTO;
|
||||||
|
use App\Http\Requests\CreateProductRequest;
|
||||||
|
use App\Http\Resources\ProductResource;
|
||||||
|
use App\Models\Product;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class ProductController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$paginator = Product::query()->with(['category:id,name,slug', 'images:id,path,product_id'])->paginate();
|
||||||
|
$paginatedDtos = $paginator->through(fn ($product) => ProductDTO::fromModel($product));
|
||||||
|
|
||||||
|
return ProductResource::collection($paginatedDtos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(CreateProductRequest $request)
|
||||||
|
{
|
||||||
|
return Product::create($request->validated());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show(Product $product) {}
|
||||||
|
|
||||||
|
public function update(Request $request, Product $product) {}
|
||||||
|
|
||||||
|
public function destroy(Product $product) {}
|
||||||
|
}
|
||||||
30
backend/app/Http/Controllers/ProductImagesController.php
Normal file
30
backend/app/Http/Controllers/ProductImagesController.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Actions\UploadImageAction;
|
||||||
|
use App\Data\UploadImageDTO;
|
||||||
|
use App\Http\Requests\UploadImageRequest;
|
||||||
|
use App\Models\ProductImages;
|
||||||
|
|
||||||
|
class ProductImagesController extends Controller
|
||||||
|
{
|
||||||
|
public function store(UploadImageRequest $request, UploadImageAction $action)
|
||||||
|
{
|
||||||
|
$action->execute(UploadImageDTO::fromRequest($request->validated()));
|
||||||
|
|
||||||
|
return response()->json(['message' => 'Image uploaded successfully']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show(ProductImages $productImages)
|
||||||
|
{
|
||||||
|
return $productImages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(ProductImages $productImages)
|
||||||
|
{
|
||||||
|
$productImages->delete();
|
||||||
|
|
||||||
|
return response()->json();
|
||||||
|
}
|
||||||
|
}
|
||||||
24
backend/app/Http/Requests/CreateProductRequest.php
Normal file
24
backend/app/Http/Requests/CreateProductRequest.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class CreateProductRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'title' => 'required|string|max:255',
|
||||||
|
'description' => 'required|string',
|
||||||
|
'product_category_id' => 'required|exists:product_categories,id',
|
||||||
|
'actual_price' => 'required|numeric|min:0',
|
||||||
|
'list_price' => 'required|numeric|min:0',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
29
backend/app/Http/Requests/UploadImageRequest.php
Normal file
29
backend/app/Http/Requests/UploadImageRequest.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UploadImageRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
|
||||||
|
'product_id' => 'required|exists:products,id',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
16
backend/app/Http/Resources/ProductCollection.php
Normal file
16
backend/app/Http/Resources/ProductCollection.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||||
|
|
||||||
|
class ProductCollection extends ResourceCollection
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'data' => $this->collection,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
18
backend/app/Http/Resources/ProductResource.php
Normal file
18
backend/app/Http/Resources/ProductResource.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources;
|
||||||
|
|
||||||
|
use App\Data\ProductDTO;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property ProductDTO $resource
|
||||||
|
*/
|
||||||
|
class ProductResource extends JsonResource
|
||||||
|
{
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return $this->resource->toArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
28
backend/app/Models/Product.php
Normal file
28
backend/app/Models/Product.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
|
||||||
|
class Product extends Model
|
||||||
|
{
|
||||||
|
protected $fillable = [
|
||||||
|
'title',
|
||||||
|
'actual_price',
|
||||||
|
'list_price',
|
||||||
|
'description',
|
||||||
|
'product_category_id',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function category(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(ProductCategory::class, 'product_category_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function images(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(ProductImage::class, 'product_id', 'id');
|
||||||
|
}
|
||||||
|
}
|
||||||
10
backend/app/Models/ProductCategory.php
Normal file
10
backend/app/Models/ProductCategory.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class ProductCategory extends Model
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
19
backend/app/Models/ProductImage.php
Normal file
19
backend/app/Models/ProductImage.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
|
||||||
|
class ProductImage extends Model
|
||||||
|
{
|
||||||
|
protected $fillable = [
|
||||||
|
'path',
|
||||||
|
'product_id',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function product(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Product::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,6 +3,7 @@
|
|||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||||
|
use App\Enums\UserRoles;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||||
use Illuminate\Notifications\Notifiable;
|
use Illuminate\Notifications\Notifiable;
|
||||||
@ -23,6 +24,7 @@ class User extends Authenticatable
|
|||||||
'password',
|
'password',
|
||||||
'city',
|
'city',
|
||||||
'mobile_number',
|
'mobile_number',
|
||||||
|
'role',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,6 +47,7 @@ protected function casts(): array
|
|||||||
return [
|
return [
|
||||||
'email_verified_at' => 'datetime',
|
'email_verified_at' => 'datetime',
|
||||||
'password' => 'hashed',
|
'password' => 'hashed',
|
||||||
|
'role' => UserRoles::class,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('product_categories', function (Blueprint $table) {
|
||||||
|
$table->id()->index();
|
||||||
|
$table->string('name')->unique();
|
||||||
|
$table->string('slug')->unique();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('product_categories');
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\ProductCategory;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('products', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('title');
|
||||||
|
$table->text('description');
|
||||||
|
$table->decimal('actual_price', 10, 2);
|
||||||
|
$table->decimal('list_price', 10, 2);
|
||||||
|
$table->foreignIdFor(ProductCategory::class)->index();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('products');
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\Product;
|
||||||
|
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('product_images', function (Blueprint $table) {
|
||||||
|
$table->id()->index();
|
||||||
|
$table->string('path');
|
||||||
|
$table->foreignIdFor(Product::class)->index();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('product_images');
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\UserRoles;
|
||||||
|
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::table('users', function (Blueprint $table) {
|
||||||
|
$table->enum('role', array_column(UserRoles::cases(), 'value'))->default(UserRoles::Customer->value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('role');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
28
backend/database/seeders/ProductCategorySeeder.php
Normal file
28
backend/database/seeders/ProductCategorySeeder.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use App\Models\ProductCategory;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
class ProductCategorySeeder extends Seeder
|
||||||
|
{
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
$names = [
|
||||||
|
'Electronics', 'Clothing', 'Home', 'Books',
|
||||||
|
'Sports', 'Toys', 'Health', 'Beauty', 'Automotive',
|
||||||
|
];
|
||||||
|
|
||||||
|
// Transform the flat names into an array of associative arrays
|
||||||
|
$categories = collect($names)->map(function ($name) {
|
||||||
|
return [
|
||||||
|
'name' => $name,
|
||||||
|
'slug' => Str::slug($name),
|
||||||
|
];
|
||||||
|
})->toArray();
|
||||||
|
|
||||||
|
ProductCategory::upsert($categories, ['name'], ['slug']);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use App\Http\Controllers\AuthenticatedUserController;
|
use App\Http\Controllers\AuthenticatedUserController;
|
||||||
|
use App\Http\Controllers\ProductCategoryController;
|
||||||
|
use App\Http\Controllers\ProductController;
|
||||||
|
use App\Http\Controllers\ProductImagesController;
|
||||||
use App\Http\Controllers\RegisteredUserController;
|
use App\Http\Controllers\RegisteredUserController;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
@ -11,4 +14,7 @@
|
|||||||
Route::middleware('auth:sanctum')->group(function () {
|
Route::middleware('auth:sanctum')->group(function () {
|
||||||
Route::get('/user', [AuthenticatedUserController::class, 'show']);
|
Route::get('/user', [AuthenticatedUserController::class, 'show']);
|
||||||
Route::post('/logout', [AuthenticatedUserController::class, 'destroy']);
|
Route::post('/logout', [AuthenticatedUserController::class, 'destroy']);
|
||||||
|
Route::post('/upload/images', action: [ProductImagesController::class, 'store']);
|
||||||
});
|
});
|
||||||
|
Route::get('/categories', [ProductCategoryController::class, 'index']);
|
||||||
|
Route::apiResource('products', ProductController::class);
|
||||||
|
|||||||
14
backend/stubs/action.stub
Normal file
14
backend/stubs/action.stub
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace {{ namespace }};
|
||||||
|
|
||||||
|
final readonly class {{ class }}
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Execute the action.
|
||||||
|
*/
|
||||||
|
public function execute()
|
||||||
|
{
|
||||||
|
// Your logic here
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user