From 8caaff989ced53a1a61ca683d69b1d3e5bc72f1c Mon Sep 17 00:00:00 2001 From: Alexis Gousseau Date: Tue, 5 Aug 2025 12:32:21 +0200 Subject: [PATCH] feat: :sparkles: adding a field to associate brands with users --- app/Http/Controllers/Bo/UserController.php | 10 +- .../Requests/Bo/Users/StoreUserRequest.php | 39 ++++---- .../Requests/Bo/Users/UpdateUserRequest.php | 23 ++--- app/Models/Brand.php | 2 +- app/Models/User.php | 2 +- resources/views/bo/pages/users/form.blade.php | 94 +++++++++---------- 6 files changed, 82 insertions(+), 88 deletions(-) diff --git a/app/Http/Controllers/Bo/UserController.php b/app/Http/Controllers/Bo/UserController.php index 72f632e..28f3722 100644 --- a/app/Http/Controllers/Bo/UserController.php +++ b/app/Http/Controllers/Bo/UserController.php @@ -5,11 +5,13 @@ namespace App\Http\Controllers\Bo; use App\Http\Controllers\Controller; use App\Http\Requests\Bo\Users\StoreUserRequest; use App\Http\Requests\Bo\Users\UpdateUserRequest; +use App\Models\Brand; use App\Models\User; use App\Traits\Controllers\UpdateModelPublished; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; +use Uwil\LaravelCommon\Helpers\CollectionHelper; class UserController extends Controller { @@ -72,7 +74,8 @@ class UserController extends Controller */ public function create(User $user): \Illuminate\Contracts\View\View { - return view('bo.pages.users.create', ['userModel' => $user]); + $brandModels = CollectionHelper::paginate(Brand::getUserAssociatedBrands(), $this->jsonItemPerPagination); + return view('bo.pages.users.create', ['userModel' => $user, 'brandModels' => $brandModels]); } /** @@ -88,6 +91,7 @@ class UserController extends Controller $user->fill($request->validated()); if ($user->saveOrFail()) { + $user->brands()->sync(collect($request->validated()['brand_id'])->pluck('id')->toArray()); return redirect()->route('bo.users.edit', $user) ->with('success', __('crud.messages.has_been_created', [ 'model' => Str::ucfirst(__('models.classes.user')) @@ -108,7 +112,8 @@ class UserController extends Controller */ public function edit(User $user): \Illuminate\Contracts\View\View { - return view('bo.pages.users.edit', ['userModel' => $user]); + $brandModels = CollectionHelper::paginate(Brand::getUserAssociatedBrands(), $this->jsonItemPerPagination); + return view('bo.pages.users.edit', ['userModel' => $user, 'brandModels' => $brandModels]); } /** @@ -124,6 +129,7 @@ class UserController extends Controller $user->fill($request->validated()); if ($user->saveOrFail()) { + $user->brands()->sync(collect($request->validated()['brand_id'])->pluck('id')->toArray()); return redirect()->route('bo.users.edit', $user) ->with('success', __('crud.messages.has_been_updated', [ 'model' => Str::ucfirst(__('models.classes.user')) diff --git a/app/Http/Requests/Bo/Users/StoreUserRequest.php b/app/Http/Requests/Bo/Users/StoreUserRequest.php index 26dccdc..4c0388f 100644 --- a/app/Http/Requests/Bo/Users/StoreUserRequest.php +++ b/app/Http/Requests/Bo/Users/StoreUserRequest.php @@ -5,7 +5,6 @@ namespace App\Http\Requests\Bo\Users; use App\Enums\Users\RoleEnum; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Validation\Rules\Enum; -use Illuminate\Validation\Rules\Password; class StoreUserRequest extends FormRequest { @@ -27,7 +26,8 @@ class StoreUserRequest extends FormRequest protected function prepareForValidation(): void { $this->merge([ - 'published' => $this->published ? true : false + 'published' => $this->input('published') ? true : false, + 'brand_id' => $this->input('brand_id') ?: [], ]); } @@ -39,19 +39,14 @@ class StoreUserRequest extends FormRequest public function rules(): array { return [ - 'first_name' => 'required|string|min:3|max:255', - 'last_name' => 'required|string|min:3|max:255', - 'email' => 'required|email:rfc,strict,dns,spoof,filter|unique:users,email', - 'password' => [ - 'required', 'required_with:password_confirmation', 'confirmed', 'max:255', Password::min(8) - ->letters() - ->mixedCase() - ->numbers() - ->symbols() - ->uncompromised() - ], - 'role' => ['required', new Enum(RoleEnum::class)], - 'published' => 'required|boolean', + 'first_name' => 'required|string|min:3|max:255', + 'last_name' => 'required|string|min:3|max:255', + 'email' => 'required|email:rfc,strict,dns,spoof,filter|unique:users,email', + 'role' => ['required', new Enum(RoleEnum::class)], + 'published' => 'required|boolean', + 'brand_id' => 'present|array', + 'brand_id.*' => 'sometimes|nullable|array', + 'brand_id.*.id' => 'sometimes|nullable|numeric|exists:brands,id', ]; } @@ -63,12 +58,14 @@ class StoreUserRequest extends FormRequest public function attributes(): array { return [ - 'first_name' => trans('validation.attributes.first_name'), - 'last_name' => trans('validation.attributes.last_name'), - 'email' => trans('validation.attributes.email'), - 'password' => trans('validation.attributes.password'), - 'role' => trans('validation.attributes.role'), - 'published' => trans('validation.custom.publication') + 'first_name' => trans('validation.attributes.first_name'), + 'last_name' => trans('validation.attributes.last_name'), + 'email' => trans('validation.attributes.email'), + 'role' => trans('validation.attributes.role'), + 'published' => trans('validation.custom.publication'), + 'brand_id' => trans('models.classes.brands'), + 'brand_id.*' => trans('models.classes.brands'), + 'brand_id.*.id' => trans('models.classes.brands'), ]; } } diff --git a/app/Http/Requests/Bo/Users/UpdateUserRequest.php b/app/Http/Requests/Bo/Users/UpdateUserRequest.php index 1b4dc56..afe7844 100644 --- a/app/Http/Requests/Bo/Users/UpdateUserRequest.php +++ b/app/Http/Requests/Bo/Users/UpdateUserRequest.php @@ -2,8 +2,6 @@ namespace App\Http\Requests\Bo\Users; -use Illuminate\Validation\Rules\Password; - class UpdateUserRequest extends StoreUserRequest { /** @@ -14,11 +12,8 @@ class UpdateUserRequest extends StoreUserRequest protected function prepareForValidation(): void { $this->merge([ - 'published' => $this->published ? true : false, - 'password' => $this->password ? $this->password : $this->route('user')->password, - 'password_confirmation' => $this->password_confirmation ? - $this->password_confirmation : - $this->route('user')->password + 'published' => $this->input('published') ? true : false, + 'brand_id' => $this->input('brand_id') ?: [], ]); } @@ -29,19 +24,15 @@ class UpdateUserRequest extends StoreUserRequest */ public function rules(): array { + /** @var \App\Models\User $userModel */ + $userModel = request()->route()->parameter('user'); + return array_merge(parent::rules(), [ 'email' => [ 'required', + 'string', 'email:rfc,strict,dns,spoof,filter', - 'unique:users,email,' . $this->route('user')->id . ',id', - ], - 'password' => [ - 'required', 'required_with:password_confirmation', 'confirmed', 'max:255', Password::min(8) - ->letters() - ->mixedCase() - ->numbers() - ->symbols() - ->uncompromised() + 'unique:users,email,' . $userModel->getKey(), ], ]); } diff --git a/app/Models/Brand.php b/app/Models/Brand.php index 4c1931e..e90ecdc 100644 --- a/app/Models/Brand.php +++ b/app/Models/Brand.php @@ -212,7 +212,7 @@ class Brand extends Model */ public function users(): \Illuminate\Database\Eloquent\Relations\BelongsToMany { - return $this->belongsToMany(User::class, 'brand_users'); + return $this->belongsToMany(Brand::class, 'brand_users', 'brand_id', 'user_id'); } /** diff --git a/app/Models/User.php b/app/Models/User.php index 60c9523..5eea455 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -122,6 +122,6 @@ class User extends Authenticatable */ public function brands(): \Illuminate\Database\Eloquent\Relations\BelongsToMany { - return $this->belongsToMany(Brand::class, 'brand_users'); + return $this->belongsToMany(Brand::class, 'brand_users', 'user_id', 'brand_id'); } } diff --git a/resources/views/bo/pages/users/form.blade.php b/resources/views/bo/pages/users/form.blade.php index d222edb..f35dc55 100644 --- a/resources/views/bo/pages/users/form.blade.php +++ b/resources/views/bo/pages/users/form.blade.php @@ -90,39 +90,6 @@ - {{-- PASSWORD --}} -
-
- {{ __('Mot de passe') }} -
-
- @include('bo.partials.inputs.varchar-password', [ - 'id' => 'userPassword', - 'label' => __('Mot de passe de l\':model', ['model' => __('models.classes.user')]), - 'name' => 'password', - 'hasWordCounter' => true, - 'required' => !$userModel->exists, - 'model' => null, - 'helper' => __( - 'Doît respecter certaines contraintes (8 caractères minimum, lettres, chiffres, caractères spéciaux).'), - ]) -
-
- @include('bo.partials.inputs.varchar-password', [ - 'id' => 'userPassword_confirmation', - 'label' => __('Confirmation du mot de passe de l\':model', [ - 'model' => __('models.classes.user'), - ]), - 'name' => 'password_confirmation', - 'hasWordCounter' => true, - 'required' => !$userModel->exists, - 'model' => null, - 'helper' => __('Doît correspondre au mot de passe saisi précédemment.'), - ]) -
-
-
-
{{-- STATUS --}}
@@ -140,6 +107,36 @@
+ {{-- BRAND --}} +
+
+ {{ str(__('models.classes.brands'))->ucfirst() }} +
+ @include('bo.partials.inputs.search-belongs-to-dropdown', [ + 'id' => 'questionBrand', + 'label' => __(':model associées', [ + 'model' => str(__('models.classes.brands'))->ucfirst(), + ]), + 'name' => 'brand_id', + 'relation' => 'brands', + 'model' => $userModel, + 'targetClass' => 'App\Models\Brand', + 'modelListPaginate' => $brandModels ?? [], + 'constructedRoute' => route('bo.brands.json-paginate'), + 'fieldName' => 'name', + 'multiple' => true, + 'required' => true, + 'disabled' => false, + 'placeholder' => __('Rechercher une :model', [ + 'model' => str(__('models.classes.brands'))->singular(), + ]), + 'helper' => __('Sélectionner des :model qui seront associées parmis la liste.', [ + 'model' => __('models.classes.brands'), + ]), + ]) +
+
+

{{ __('* Champs obligatoires') }}

@@ -151,23 +148,26 @@ @endpush