diff --git a/.ai/mcp/mcp.json b/.ai/mcp/mcp.json new file mode 100644 index 0000000..e69de29 diff --git a/.gitignore b/.gitignore index 9efe7dc..7353c22 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,8 @@ yarn-error.log testem.log /typings __screenshots__/ +*.cache +.php-cs-fixer.dist.php # System files .DS_Store diff --git a/backend/app/Http/Controllers/FavouriteProductController.php b/backend/app/Http/Controllers/FavouriteProductController.php new file mode 100644 index 0000000..80e2467 --- /dev/null +++ b/backend/app/Http/Controllers/FavouriteProductController.php @@ -0,0 +1,35 @@ +user(); + + $changes = $user->favoriteProducts()->toggle($product); + + // If changes has any item, that means a product has been attached. + $isFavorite = count($changes['attached']) > 0; + + return response()->json([ + 'message' => $isFavorite ? 'Product added to favorites' : 'Product removed from favorites', + 'isFavorite' => $isFavorite, + ]); + } +} diff --git a/backend/app/Http/Resources/FavouriteProductResource.php b/backend/app/Http/Resources/FavouriteProductResource.php new file mode 100644 index 0000000..4ad6a80 --- /dev/null +++ b/backend/app/Http/Resources/FavouriteProductResource.php @@ -0,0 +1,23 @@ + $this->id, + 'created_at' => $this->created_at, + 'updated_at' => $this->updated_at, + + 'user_id' => $this->user_id, + 'product_id' => $this->product_id, + ]; + } +} diff --git a/backend/app/Models/User.php b/backend/app/Models/User.php index eb74b44..a0ab8b4 100644 --- a/backend/app/Models/User.php +++ b/backend/app/Models/User.php @@ -11,7 +11,9 @@ class User extends Authenticatable { /** @use HasFactory<\Database\Factories\UserFactory> */ - use HasFactory, Notifiable; + use HasFactory; + + use Notifiable; /** * The attributes that are mass assignable. @@ -50,4 +52,14 @@ protected function casts(): array 'role' => UserRoles::class, ]; } + + public function favoriteProducts() + { + return $this->belongsToMany(Product::class, 'favorite_products', 'user_id', 'product_id'); + } + + public function hasFavorited(Product $product): bool + { + return $this->favoriteProducts()->where('product_id', $product->id)->exists(); + } } diff --git a/backend/database/migrations/2026_03_02_133303_create_favourite_products_table.php b/backend/database/migrations/2026_03_02_133303_create_favourite_products_table.php new file mode 100644 index 0000000..0975051 --- /dev/null +++ b/backend/database/migrations/2026_03_02_133303_create_favourite_products_table.php @@ -0,0 +1,26 @@ +id(); + $table->foreignIdFor(User::class); + $table->foreignIdFor(Product::class); + $table->timestamps(); + $table->unique(['user_id', 'product_id']); + }); + } + + public function down(): void + { + Schema::dropIfExists('favorite_products'); + } +}; diff --git a/backend/routes/api.php b/backend/routes/api.php index 5d8329d..311580f 100644 --- a/backend/routes/api.php +++ b/backend/routes/api.php @@ -1,6 +1,7 @@