mirror of
https://github.com/robonen/metr.git
synced 2026-03-20 02:44:42 +00:00
Offer filters and user feedback
This commit is contained in:
18
backend/app/Filters/Filterable.php
Normal file
18
backend/app/Filters/Filterable.php
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filters;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
|
||||||
|
trait Filterable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||||
|
* @param \App\Filters\QueryFilter $filters
|
||||||
|
* @return \Illuminate\Database\Eloquent\Builder
|
||||||
|
*/
|
||||||
|
public function scopeFilter(Builder $builder, QueryFilter $filters): Builder
|
||||||
|
{
|
||||||
|
return $filters->apply($builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
57
backend/app/Filters/OfferFilter.php
Normal file
57
backend/app/Filters/OfferFilter.php
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filters;
|
||||||
|
|
||||||
|
use App\Enums\OrderTypesEnum;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
|
||||||
|
class OfferFilter extends QueryFilter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param string $type
|
||||||
|
* @return \Illuminate\Database\Eloquent\Builder
|
||||||
|
*/
|
||||||
|
protected function type(string $type): Builder
|
||||||
|
{
|
||||||
|
if (OrderTypesEnum::tryFrom($type) !== null)
|
||||||
|
return $this->builder->where('type', $type);
|
||||||
|
|
||||||
|
return $this->builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $rooms
|
||||||
|
* @return \Illuminate\Database\Eloquent\Builder
|
||||||
|
*/
|
||||||
|
protected function rooms(int $rooms): Builder
|
||||||
|
{
|
||||||
|
if ($rooms >= 1)
|
||||||
|
return $this->builder->where('rooms', '>=', $rooms);
|
||||||
|
|
||||||
|
return $this->builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $price
|
||||||
|
* @return \Illuminate\Database\Eloquent\Builder
|
||||||
|
*/
|
||||||
|
protected function startPrice(int $price): Builder
|
||||||
|
{
|
||||||
|
if ($price >= 0)
|
||||||
|
return $this->builder->where('price', '>=', $price);
|
||||||
|
|
||||||
|
return $this->builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $price
|
||||||
|
* @return \Illuminate\Database\Eloquent\Builder
|
||||||
|
*/
|
||||||
|
protected function endPrice(int $price): Builder
|
||||||
|
{
|
||||||
|
if ($price >= 0)
|
||||||
|
return $this->builder->where('price', '<=', $price);
|
||||||
|
|
||||||
|
return $this->builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
46
backend/app/Filters/QueryFilter.php
Normal file
46
backend/app/Filters/QueryFilter.php
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filters;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
abstract class QueryFilter
|
||||||
|
{
|
||||||
|
protected Request $request;
|
||||||
|
|
||||||
|
protected Builder $builder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
*/
|
||||||
|
public function __construct(Request $request)
|
||||||
|
{
|
||||||
|
$this->request = $request;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \Illuminate\Database\Eloquent\Builder $builder
|
||||||
|
* @return \Illuminate\Database\Eloquent\Builder
|
||||||
|
*/
|
||||||
|
public function apply(Builder $builder): Builder
|
||||||
|
{
|
||||||
|
$this->builder = $builder;
|
||||||
|
|
||||||
|
foreach ($this->filters() as $name => $value) {
|
||||||
|
if (method_exists($this, $name)) {
|
||||||
|
call_user_func_array([$this, $name], array_filter([$value]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array|string|null
|
||||||
|
*/
|
||||||
|
private function filters(): array|string|null
|
||||||
|
{
|
||||||
|
return $this->request->query();
|
||||||
|
}
|
||||||
|
}
|
||||||
69
backend/app/Http/Controllers/FeedbackController.php
Normal file
69
backend/app/Http/Controllers/FeedbackController.php
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Requests\StoreFeedbackRequest;
|
||||||
|
use App\Http\Requests\UpdateFeedbackRequest;
|
||||||
|
use App\Http\Resources\FeedbackResource;
|
||||||
|
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||||
|
|
||||||
|
class FeedbackController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\Resources\Json\AnonymousResourceCollection
|
||||||
|
*/
|
||||||
|
public function index(): AnonymousResourceCollection
|
||||||
|
{
|
||||||
|
return FeedbackResource::collection(auth()->user()->feedback()->get());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
* @return \App\Http\Resources\FeedbackResource
|
||||||
|
*/
|
||||||
|
public function show(int $id): FeedbackResource
|
||||||
|
{
|
||||||
|
$feedback = auth()->user()->feedback()->findOrFail($id);
|
||||||
|
return new FeedbackResource($feedback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*
|
||||||
|
* @param \App\Http\Requests\StoreFeedbackRequest $request
|
||||||
|
* @return \App\Http\Resources\FeedbackResource
|
||||||
|
*/
|
||||||
|
public function store(StoreFeedbackRequest $request): FeedbackResource
|
||||||
|
{
|
||||||
|
$feedback = auth()->user()->feedback()->create($request->validated());
|
||||||
|
return new FeedbackResource($feedback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*
|
||||||
|
* @param \App\Http\Requests\UpdateFeedbackRequest $request
|
||||||
|
* @param int $id
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function update(UpdateFeedbackRequest $request, int $id): void
|
||||||
|
{
|
||||||
|
$feedback = auth()->user()->feedback()->findOrFail($id);
|
||||||
|
$feedback->update($request->validated());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*
|
||||||
|
* @param int $id
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function destroy(int $id): void
|
||||||
|
{
|
||||||
|
auth()->user()->feedback()->findOrFail($id)->delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Filters\OfferFilter;
|
||||||
use App\Http\Requests\StoreOfferRequest;
|
use App\Http\Requests\StoreOfferRequest;
|
||||||
use App\Http\Requests\UpdateOfferRequest;
|
use App\Http\Requests\UpdateOfferRequest;
|
||||||
use App\Http\Resources\OfferResource;
|
use App\Http\Resources\OfferResource;
|
||||||
@@ -15,9 +16,9 @@ class OfferController extends Controller
|
|||||||
*
|
*
|
||||||
* @return \Illuminate\Http\Resources\Json\AnonymousResourceCollection
|
* @return \Illuminate\Http\Resources\Json\AnonymousResourceCollection
|
||||||
*/
|
*/
|
||||||
public function index(): AnonymousResourceCollection
|
public function index(OfferFilter $filters): AnonymousResourceCollection
|
||||||
{
|
{
|
||||||
return OfferResource::collection(Offer::all());
|
return OfferResource::collection(Offer::filter($filters)->get());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
19
backend/app/Http/Requests/StoreFeedbackRequest.php
Normal file
19
backend/app/Http/Requests/StoreFeedbackRequest.php
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
class StoreFeedbackRequest extends BaseRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'comment' => ['required', 'string', 'max:2000'],
|
||||||
|
'rating' => ['required', 'numeric', 'min:1', 'max:5'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
19
backend/app/Http/Requests/UpdateFeedbackRequest.php
Normal file
19
backend/app/Http/Requests/UpdateFeedbackRequest.php
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
class UpdateFeedbackRequest extends BaseRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'comment' => ['string', 'max:2000'],
|
||||||
|
'rating' => ['numeric', 'min:1', 'max:5'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
19
backend/app/Http/Resources/FeedbackResource.php
Normal file
19
backend/app/Http/Resources/FeedbackResource.php
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class FeedbackResource extends JsonResource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transform the resource into an array.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
|
||||||
|
*/
|
||||||
|
public function toArray($request)
|
||||||
|
{
|
||||||
|
return parent::toArray($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,4 +19,13 @@ class Feedback extends Model
|
|||||||
'comment',
|
'comment',
|
||||||
'rating',
|
'rating',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that should be cast.
|
||||||
|
*
|
||||||
|
* @var array<string, string>
|
||||||
|
*/
|
||||||
|
protected $casts = [
|
||||||
|
'rating' => 'integer',
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,13 @@
|
|||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use App\Enums\OrderTypesEnum;
|
use App\Enums\OrderTypesEnum;
|
||||||
|
use App\Filters\Filterable;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
class Offer extends Model
|
class Offer extends Model
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory, Filterable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that are mass assignable.
|
* The attributes that are mass assignable.
|
||||||
|
|||||||
@@ -34,4 +34,9 @@ class User extends Authenticatable
|
|||||||
protected $hidden = [
|
protected $hidden = [
|
||||||
'password',
|
'password',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public function feedback()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Feedback::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,6 @@ return [
|
|||||||
|
|
||||||
'max_age' => 0,
|
'max_age' => 0,
|
||||||
|
|
||||||
'supports_credentials' => false,
|
'supports_credentials' => true,
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
use App\Http\Controllers\Auth\LoginController;
|
use App\Http\Controllers\Auth\LoginController;
|
||||||
use App\Http\Controllers\Auth\LogoutController;
|
use App\Http\Controllers\Auth\LogoutController;
|
||||||
use App\Http\Controllers\Auth\RegistrationController;
|
use App\Http\Controllers\Auth\RegistrationController;
|
||||||
|
use App\Http\Controllers\FeedbackController;
|
||||||
use App\Http\Controllers\OfferController;
|
use App\Http\Controllers\OfferController;
|
||||||
use App\Http\Controllers\OrderController;
|
use App\Http\Controllers\OrderController;
|
||||||
use App\Http\Controllers\UserController;
|
use App\Http\Controllers\UserController;
|
||||||
@@ -32,16 +33,14 @@ Route::prefix('auth')->group(function() {
|
|||||||
|
|
||||||
Route::middleware('auth:sanctum')->group(function() {
|
Route::middleware('auth:sanctum')->group(function() {
|
||||||
|
|
||||||
Route::prefix('user')->group(function() {
|
Route::apiResource('orders', OrderController::class);
|
||||||
|
|
||||||
|
Route::prefix('users')->group(function() {
|
||||||
Route::get('', [UserController::class, 'index']);
|
Route::get('', [UserController::class, 'index']);
|
||||||
Route::put('', [UserController::class, 'update']);
|
Route::put('', [UserController::class, 'update']);
|
||||||
|
Route::apiResource('feedback', FeedbackController::class);
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::apiResource('orders', OrderController::class);
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::apiResource('offers', OfferController::class);
|
Route::apiResource('offers', OfferController::class);
|
||||||
|
|
||||||
// TODO: На главной странице 6 самых дорогих квартир
|
|
||||||
// TODO: Последние добавленные квартиры + фильтры
|
|
||||||
|
|||||||
Reference in New Issue
Block a user