From fe2e5d316c0317f4d34c4fd6fc7ab6e8e79ed306 Mon Sep 17 00:00:00 2001 From: robonen Date: Sun, 29 May 2022 04:21:56 +0700 Subject: [PATCH] Offer filters and user feedback --- backend/app/Filters/Filterable.php | 18 +++++ backend/app/Filters/OfferFilter.php | 57 +++++++++++++++ backend/app/Filters/QueryFilter.php | 46 +++++++++++++ .../Http/Controllers/FeedbackController.php | 69 +++++++++++++++++++ .../app/Http/Controllers/OfferController.php | 5 +- .../Http/Requests/StoreFeedbackRequest.php | 19 +++++ .../Http/Requests/UpdateFeedbackRequest.php | 19 +++++ .../app/Http/Resources/FeedbackResource.php | 19 +++++ backend/app/Models/Feedback.php | 9 +++ backend/app/Models/Offer.php | 3 +- backend/app/Models/User.php | 5 ++ backend/config/cors.php | 2 +- backend/routes/api.php | 11 ++- 13 files changed, 272 insertions(+), 10 deletions(-) create mode 100644 backend/app/Filters/Filterable.php create mode 100644 backend/app/Filters/OfferFilter.php create mode 100644 backend/app/Filters/QueryFilter.php create mode 100644 backend/app/Http/Controllers/FeedbackController.php create mode 100644 backend/app/Http/Requests/StoreFeedbackRequest.php create mode 100644 backend/app/Http/Requests/UpdateFeedbackRequest.php create mode 100644 backend/app/Http/Resources/FeedbackResource.php diff --git a/backend/app/Filters/Filterable.php b/backend/app/Filters/Filterable.php new file mode 100644 index 0000000..cf7d5af --- /dev/null +++ b/backend/app/Filters/Filterable.php @@ -0,0 +1,18 @@ +apply($builder); + } +} diff --git a/backend/app/Filters/OfferFilter.php b/backend/app/Filters/OfferFilter.php new file mode 100644 index 0000000..3b03f1c --- /dev/null +++ b/backend/app/Filters/OfferFilter.php @@ -0,0 +1,57 @@ +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; + } +} diff --git a/backend/app/Filters/QueryFilter.php b/backend/app/Filters/QueryFilter.php new file mode 100644 index 0000000..f55ad87 --- /dev/null +++ b/backend/app/Filters/QueryFilter.php @@ -0,0 +1,46 @@ +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(); + } +} diff --git a/backend/app/Http/Controllers/FeedbackController.php b/backend/app/Http/Controllers/FeedbackController.php new file mode 100644 index 0000000..1cf93d8 --- /dev/null +++ b/backend/app/Http/Controllers/FeedbackController.php @@ -0,0 +1,69 @@ +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(); + } +} diff --git a/backend/app/Http/Controllers/OfferController.php b/backend/app/Http/Controllers/OfferController.php index 7ab8e53..915494f 100644 --- a/backend/app/Http/Controllers/OfferController.php +++ b/backend/app/Http/Controllers/OfferController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers; +use App\Filters\OfferFilter; use App\Http\Requests\StoreOfferRequest; use App\Http\Requests\UpdateOfferRequest; use App\Http\Resources\OfferResource; @@ -15,9 +16,9 @@ class OfferController extends Controller * * @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()); } /** diff --git a/backend/app/Http/Requests/StoreFeedbackRequest.php b/backend/app/Http/Requests/StoreFeedbackRequest.php new file mode 100644 index 0000000..abbf80e --- /dev/null +++ b/backend/app/Http/Requests/StoreFeedbackRequest.php @@ -0,0 +1,19 @@ + + */ + public function rules() + { + return [ + 'comment' => ['required', 'string', 'max:2000'], + 'rating' => ['required', 'numeric', 'min:1', 'max:5'], + ]; + } +} diff --git a/backend/app/Http/Requests/UpdateFeedbackRequest.php b/backend/app/Http/Requests/UpdateFeedbackRequest.php new file mode 100644 index 0000000..3b1a355 --- /dev/null +++ b/backend/app/Http/Requests/UpdateFeedbackRequest.php @@ -0,0 +1,19 @@ + + */ + public function rules() + { + return [ + 'comment' => ['string', 'max:2000'], + 'rating' => ['numeric', 'min:1', 'max:5'], + ]; + } +} diff --git a/backend/app/Http/Resources/FeedbackResource.php b/backend/app/Http/Resources/FeedbackResource.php new file mode 100644 index 0000000..6fb29be --- /dev/null +++ b/backend/app/Http/Resources/FeedbackResource.php @@ -0,0 +1,19 @@ + + */ + protected $casts = [ + 'rating' => 'integer', + ]; } diff --git a/backend/app/Models/Offer.php b/backend/app/Models/Offer.php index edb7327..d345902 100644 --- a/backend/app/Models/Offer.php +++ b/backend/app/Models/Offer.php @@ -3,12 +3,13 @@ namespace App\Models; use App\Enums\OrderTypesEnum; +use App\Filters\Filterable; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Offer extends Model { - use HasFactory; + use HasFactory, Filterable; /** * The attributes that are mass assignable. diff --git a/backend/app/Models/User.php b/backend/app/Models/User.php index 0dd1542..3088a5e 100644 --- a/backend/app/Models/User.php +++ b/backend/app/Models/User.php @@ -34,4 +34,9 @@ class User extends Authenticatable protected $hidden = [ 'password', ]; + + public function feedback() + { + return $this->hasMany(Feedback::class); + } } diff --git a/backend/config/cors.php b/backend/config/cors.php index 8a39e6d..94f07be 100644 --- a/backend/config/cors.php +++ b/backend/config/cors.php @@ -29,6 +29,6 @@ return [ 'max_age' => 0, - 'supports_credentials' => false, + 'supports_credentials' => true, ]; diff --git a/backend/routes/api.php b/backend/routes/api.php index 42ae39e..c4c0c45 100644 --- a/backend/routes/api.php +++ b/backend/routes/api.php @@ -3,6 +3,7 @@ use App\Http\Controllers\Auth\LoginController; use App\Http\Controllers\Auth\LogoutController; use App\Http\Controllers\Auth\RegistrationController; +use App\Http\Controllers\FeedbackController; use App\Http\Controllers\OfferController; use App\Http\Controllers\OrderController; use App\Http\Controllers\UserController; @@ -32,16 +33,14 @@ Route::prefix('auth')->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::put('', [UserController::class, 'update']); + Route::apiResource('feedback', FeedbackController::class); }); - Route::apiResource('orders', OrderController::class); - }); Route::apiResource('offers', OfferController::class); - -// TODO: На главной странице 6 самых дорогих квартир -// TODO: Последние добавленные квартиры + фильтры