From 074320d79c67ee053b2b38059e21a8a65431276f Mon Sep 17 00:00:00 2001 From: Corentin Huet Date: Fri, 6 Mar 2026 10:47:07 +0100 Subject: [PATCH 1/3] fix: :bug: resolve various bugs following re7 feedback --- app/Http/Controllers/Bo/AisleController.php | 43 ++++++++++++++- .../Bo/Aisles/UpdateAisleOrderRequest.php | 54 +++++++++++++++++++ .../Requests/Bo/Brands/StoreBrandRequest.php | 2 +- .../Bo/Networks/StoreNetworkRequest.php | 1 + app/Models/Aisle.php | 26 +++++++++ app/Models/Network.php | 1 + ...2026_03_06_113426_alter_networks_table.php | 30 +++++++++++ .../2026_03_06_125234_alter_aisles_table.php | 37 +++++++++++++ resources/sass/fo/fo.scss | 1 + resources/sass/fo/pages/_networks.scss | 30 +++++++++++ resources/ts/bo/utilities/fontawesome.ts | 4 +- resources/ts/fo/base/common.ts | 2 +- .../change-model-order-select.blade.php | 22 ++++++++ .../bo/pages/aisles/index-list.blade.php | 26 +++++++-- .../views/bo/pages/aisles/index.blade.php | 36 ++++++++++--- .../views/bo/pages/networks/form.blade.php | 29 ++++++++++ .../views/fo/pages/networks/show.blade.php | 41 ++++++++++---- .../views/fo/pages/produce/show.blade.php | 3 ++ .../partials/networks/slider-card.blade.php | 2 +- routes/web-bo.php | 6 ++- 20 files changed, 370 insertions(+), 26 deletions(-) create mode 100644 app/Http/Requests/Bo/Aisles/UpdateAisleOrderRequest.php create mode 100644 database/migrations/2026_03_06_113426_alter_networks_table.php create mode 100644 database/migrations/2026_03_06_125234_alter_aisles_table.php create mode 100644 resources/sass/fo/pages/_networks.scss create mode 100644 resources/views/bo/modules/change-model-order-select.blade.php diff --git a/app/Http/Controllers/Bo/AisleController.php b/app/Http/Controllers/Bo/AisleController.php index 21d7193..d5ea7ed 100644 --- a/app/Http/Controllers/Bo/AisleController.php +++ b/app/Http/Controllers/Bo/AisleController.php @@ -4,10 +4,11 @@ namespace App\Http\Controllers\Bo; use App\Http\Controllers\Controller; use App\Http\Requests\Bo\Aisles\StoreAisleRequest; +use App\Http\Requests\Bo\Aisles\UpdateAisleOrderRequest; use App\Http\Requests\Bo\Aisles\UpdateAisleRequest; -use App\Models\Logo; use App\Models\Aisle; use App\Models\Network; +use App\Traits\Controllers\ChangesModelOrder; use App\Traits\Controllers\UpdateModelPublished; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; @@ -15,6 +16,7 @@ use Illuminate\Support\Str; class AisleController extends Controller { + use ChangesModelOrder; use UpdateModelPublished; /** @@ -35,6 +37,13 @@ class AisleController extends Controller { /** @var \Illuminate\Database\Eloquent\Builder $aisleModels */ $aisleModels = Aisle::query()->with('network'); + $networkModels = Network::query()->where('published', true)->get(); + + $selectedNetwork = intval($request->network); + + $aisleModels = $aisleModels->when($selectedNetwork, function ($query) use ($selectedNetwork) { + $query->where('network_id', $selectedNetwork); + }); /** @var string $search Search field */ $search = $request->input('search'); @@ -56,7 +65,7 @@ class AisleController extends Controller /** Custom pagination */ $aisleModels = $this->paginate($aisleModels); - return view('bo.pages.aisles.index', compact('aisleModels', 'search', 'searchFields')); + return view('bo.pages.aisles.index', compact('aisleModels', 'networkModels', 'selectedNetwork', 'search', 'searchFields')); } @@ -174,4 +183,34 @@ class AisleController extends Controller { return $this->create($aisle->replicate()); } + + /** + * Update ticket priority. + * + * @param \App\Http\Requests\Bo\Aisles\UpdateAisleOrderRequest $request + * @param \App\Models\Aisle $aisle + * @return void + */ + public function changeCustomOrder(UpdateAisleOrderRequest $request, Aisle $aisle) + { + $newOrder = $request->validated('order'); + + return DB::transaction(function () use ($aisle, $newOrder) { + // Update all tickets who will be moved with this priority update. + $request = Aisle::query() + ->where('network_id', $aisle->network_id) + ->whereNot('id', $aisle->id) + ->whereBetween('order', [min($aisle->order, $newOrder), max($aisle->order, $newOrder)]); + $aisle->order < $newOrder ? $request->decrement('order', 1) : $request->increment('order', 1); + + // Update the aisle. + $aisle->order = $newOrder; + if (!$aisle->saveOrFail()) { + return back()->with('error', trans('crud.messages.order_not_changed')); + }; + + return redirect()->back()->with('success', trans('crud.messages.order_changed')); + }); + } + } diff --git a/app/Http/Requests/Bo/Aisles/UpdateAisleOrderRequest.php b/app/Http/Requests/Bo/Aisles/UpdateAisleOrderRequest.php new file mode 100644 index 0000000..991f9d7 --- /dev/null +++ b/app/Http/Requests/Bo/Aisles/UpdateAisleOrderRequest.php @@ -0,0 +1,54 @@ +check(); + } + + /** + * Prepare the data for validation. + * + * @return void + */ + protected function prepareForValidation(): void + { + $this->aisle = $this->route('aisle'); + $this->max = Aisle::query()->where('network_id', $this->aisle->network_id)->max('order'); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules(): array + { + return [ + 'order' => [ + 'required', + 'integer', + 'min:1', + sprintf('max:%s', $this->max), + function ($attribute, $value, $fail) { + if ($this->aisle && intval($value) === $this->aisle->order) { + $fail("La valeur de {$attribute} doit être différente de la valeur actuelle."); + } + }, + ], + ]; + } +} diff --git a/app/Http/Requests/Bo/Brands/StoreBrandRequest.php b/app/Http/Requests/Bo/Brands/StoreBrandRequest.php index 9a47751..37b9891 100644 --- a/app/Http/Requests/Bo/Brands/StoreBrandRequest.php +++ b/app/Http/Requests/Bo/Brands/StoreBrandRequest.php @@ -45,7 +45,7 @@ class StoreBrandRequest extends FormRequest 'text' => [ 'required', 'string', - new WysiwygLength(3, 255), + new WysiwygLength(3, 500), ], 'picture_alt' => 'required|string|between:3,255', 'picture_title' => 'required|string|between:3,255', diff --git a/app/Http/Requests/Bo/Networks/StoreNetworkRequest.php b/app/Http/Requests/Bo/Networks/StoreNetworkRequest.php index 40d6d01..1d12848 100644 --- a/app/Http/Requests/Bo/Networks/StoreNetworkRequest.php +++ b/app/Http/Requests/Bo/Networks/StoreNetworkRequest.php @@ -47,6 +47,7 @@ class StoreNetworkRequest extends FormRequest 'subtitle' => 'required|string|between:3,255', 'picture_alt' => 'required|string|between:3,255', 'picture_title' => 'required|string|between:3,255', + 'button_text' => 'required|string|between:3,255', 'published' => 'required|boolean', ]; diff --git a/app/Models/Aisle.php b/app/Models/Aisle.php index 1221356..82ed110 100644 --- a/app/Models/Aisle.php +++ b/app/Models/Aisle.php @@ -27,6 +27,7 @@ class Aisle extends Model 'picture_title', 'published', 'network_id', + 'order', ]; /** @@ -46,6 +47,7 @@ class Aisle extends Model protected static function booted(): void { static::creating(function (self $model) { + self::setOrder($model); self::manageFields($model); }); static::updating(function (self $model) { @@ -59,6 +61,7 @@ class Aisle extends Model }); static::deleted(function (self $model) { FileStorageHelper::removeFile($model, 'picture'); + self::setOrder($model, true); }); } @@ -78,6 +81,29 @@ class Aisle extends Model $model->picture = FileStorageHelper::storeFile($model, $model->picture, true); } + /** + * Set order after the last element of the list. + * + * @param self $model + * @param boolean $isDeletion + * @return void + */ + private static function setOrder(self $model, bool $isDeletion = false): void + { + $maxOrder = \intval(self::query()->where('network_id', $model->network_id)->max('order')); + + if ($isDeletion) { + $request = Aisle::query() + ->where('network_id', $model->network_id) + ->whereNot('id', $model->id) + ->whereBetween('order', [$model->order, $maxOrder]); + $request->decrement('order', 1); + return; + } + + $model->order = $maxOrder + 1; + } + /** * Check if the limit of published models is reached. * diff --git a/app/Models/Network.php b/app/Models/Network.php index 3fd0c6e..95ae75c 100644 --- a/app/Models/Network.php +++ b/app/Models/Network.php @@ -30,6 +30,7 @@ class Network extends Model 'picture', 'picture_alt', 'picture_title', + 'button_text', 'order', 'published', ]; diff --git a/database/migrations/2026_03_06_113426_alter_networks_table.php b/database/migrations/2026_03_06_113426_alter_networks_table.php new file mode 100644 index 0000000..b4a7c47 --- /dev/null +++ b/database/migrations/2026_03_06_113426_alter_networks_table.php @@ -0,0 +1,30 @@ +string('button_text')->default('On produit')->comment('Button text')->after('picture_title'); + $table->dropUnique(['order']); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('networks', function (Blueprint $table) { + $table->unique('order'); + $table->dropColumn('button_text'); + }); + } +}; diff --git a/database/migrations/2026_03_06_125234_alter_aisles_table.php b/database/migrations/2026_03_06_125234_alter_aisles_table.php new file mode 100644 index 0000000..a1063b0 --- /dev/null +++ b/database/migrations/2026_03_06_125234_alter_aisles_table.php @@ -0,0 +1,37 @@ +integer('order')->comment('Position of the aisles')->after('network_id'); + }); + + Network::query()->with('aisles')->get()->map(function ($network) { + $network->aisles->map(function ($aisle, $aisleIndex) { + $aisle->order = $aisleIndex + 1; + $aisle->saveQuietly(); + }); + }); + + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('aisles', function (Blueprint $table) { + $table->dropColumn('order'); + }); + } +}; diff --git a/resources/sass/fo/fo.scss b/resources/sass/fo/fo.scss index a3b749f..6546a50 100644 --- a/resources/sass/fo/fo.scss +++ b/resources/sass/fo/fo.scss @@ -24,6 +24,7 @@ @import "./pages/unveil"; @import "./pages/news"; @import "./pages/hire"; +@import "./pages/networks"; // * PARTIALS @import "./partials/slider"; diff --git a/resources/sass/fo/pages/_networks.scss b/resources/sass/fo/pages/_networks.scss new file mode 100644 index 0000000..51060ad --- /dev/null +++ b/resources/sass/fo/pages/_networks.scss @@ -0,0 +1,30 @@ +@use "sass:color"; + +.swiper-networks { + .swiper-networks-pagination { + bottom: 2rem; + left: 5%; + + @include media-breakpoint-up(lg) { + top: auto; + bottom: .5rem; + left: 0; + width: 100%; + } + } + + .swiper-pagination-bullet { + width: 3rem; + max-width: 10rem; + height: .5rem; + background-color: color.adjust($color-dark, $alpha: -0.8); + + &:hover { + cursor: pointer; + } + } + + .swiper-pagination-bullet-active { + background-color: $color-primary; + } +} diff --git a/resources/ts/bo/utilities/fontawesome.ts b/resources/ts/bo/utilities/fontawesome.ts index a07fa0a..7db27b6 100644 --- a/resources/ts/bo/utilities/fontawesome.ts +++ b/resources/ts/bo/utilities/fontawesome.ts @@ -41,7 +41,8 @@ import { faTrash, faUndoAlt, faWandMagic, - faXmark + faXmark, + faChevronDown, } from "@fortawesome/free-solid-svg-icons"; config.autoReplaceSvg = false; @@ -88,5 +89,6 @@ library.add(faChevronRight); library.add(faCircleXmark); library.add(faCircleNotch); library.add(faSliders); +library.add(faChevronDown); dom.watch(); diff --git a/resources/ts/fo/base/common.ts b/resources/ts/fo/base/common.ts index 4d26a9a..1e2a948 100644 --- a/resources/ts/fo/base/common.ts +++ b/resources/ts/fo/base/common.ts @@ -53,7 +53,7 @@ document.addEventListener("DOMContentLoaded", function () { slidesPerView: 1, loop: true, autoplay: { - delay: 3000, + delay: 20000, disableOnInteraction: false, }, pagination: { diff --git a/resources/views/bo/modules/change-model-order-select.blade.php b/resources/views/bo/modules/change-model-order-select.blade.php new file mode 100644 index 0000000..5ebb4bb --- /dev/null +++ b/resources/views/bo/modules/change-model-order-select.blade.php @@ -0,0 +1,22 @@ + +
+ {{ $model->order ?? '' }} + + +
+ diff --git a/resources/views/bo/pages/aisles/index-list.blade.php b/resources/views/bo/pages/aisles/index-list.blade.php index 64500fa..af4342e 100644 --- a/resources/views/bo/pages/aisles/index-list.blade.php +++ b/resources/views/bo/pages/aisles/index-list.blade.php @@ -1,18 +1,38 @@ @if (count($aisleModels) > 0) - @include('bo.modules.table-col-sorter', [ - 'cols' => [ + @php + $cols = []; + + if (request()->network) { + $cols = array_merge($cols, [ + 'order' => Str::ucfirst(__('validation.custom.order')), + ]); + } + + $cols = array_merge($cols, [ 'name' => Str::ucfirst(__('validation.attributes.name')), 'network_id' => Str::ucfirst(trans_choice('models.classes.network', 1)), 'published' => Str::ucfirst(__('validation.custom.activated')), 'updated_at' => Str::ucfirst(__('validation.attributes.updated_at')), - ], + ]); + @endphp + + @include('bo.modules.table-col-sorter', [ + $cols ]) @foreach ($aisleModels as $aisleModel) + @php + $routeName = request()->route()->getName(); + @endphp + @if (request()->network && empty(request()->search) && Session::get("$routeName.sort_col") === 'order') + @include('bo.modules.change-model-order-select', [ + 'model' => $aisleModel, + ]) + @endif @include('bo.modules.change-published-status', [ diff --git a/resources/views/bo/pages/aisles/index.blade.php b/resources/views/bo/pages/aisles/index.blade.php index 986b46b..748e9d6 100644 --- a/resources/views/bo/pages/aisles/index.blade.php +++ b/resources/views/bo/pages/aisles/index.blade.php @@ -6,15 +6,37 @@ @section('content')
@include('modules.breadcrumbs.breadcrumb-body') - @can('create', \App\Models\Aisle::class) - - - - @endcan +
+
+ + @push('scripts') + + @endpush + @can('create', \App\Models\Aisle::class) + + + + @endcan +
+ +
@include('bo.modules.search-bar') -
+
@include('bo.pages.aisles.index-list')
{{ $aisleModels->links() }} diff --git a/resources/views/bo/pages/networks/form.blade.php b/resources/views/bo/pages/networks/form.blade.php index 9877f3f..ed51d80 100644 --- a/resources/views/bo/pages/networks/form.blade.php +++ b/resources/views/bo/pages/networks/form.blade.php @@ -252,6 +252,35 @@
+ {{-- BUTTON_TEXT --}} +
+ @include('bo.partials.inputs.varchar', [ + 'id' => 'networkButtonText', + 'label' => __(':field :inter:model', [ + 'field' => Str::ucfirst(__('validation.custom.button_label')), + 'inter' => __('validation.custom.of_the.male'), + 'model' => trans_choice('models.classes.network', 1), + ]), + 'hasWordCounter' => true, + 'name' => 'button_text', + 'required' => true, + 'model' => $networkModel ?? null, + 'helper' => __('validation.between.string', [ + 'attribute' => __(':field :inter:model', [ + 'field' => __('validation.custom.button'), + 'inter' => __('validation.custom.of_the.male'), + 'model' => trans_choice('models.classes.network', 1), + ]), + 'min' => 3, + 'max' => 255, + ]), + 'placeholder' => __(':field :inter:model', [ + 'field' => Str::ucfirst(__('validation.custom.button_label')), + 'inter' => __('validation.custom.of_the.male'), + 'model' => trans_choice('models.classes.network', 1), + ]), + ]) +

{{ __('validation.custom.required_fields') }}

diff --git a/resources/views/fo/pages/networks/show.blade.php b/resources/views/fo/pages/networks/show.blade.php index 3731769..35cd42a 100644 --- a/resources/views/fo/pages/networks/show.blade.php +++ b/resources/views/fo/pages/networks/show.blade.php @@ -24,7 +24,10 @@ {{-- AISLES --}} - @foreach ($networkModel->aisles as $aisleModel) + @php + $aisleModels = $networkModel->aisles->where('published', true); + @endphp + @foreach ($aisleModels as $aisleModel)
@@ -40,21 +43,31 @@
- @foreach($aisleModel->brands as $brandModel) + @php + $brandModels = $aisleModel->brands->where('published', true); + @endphp + @foreach($brandModels as $brandModel)
$loop->even ])> - + @if ($brandModel->link) + + {{ $brandModel->picture_alt }} + + @else {{ $brandModel->picture_alt }} - + @endif
- @foreach ($networkModels as $networkModel) + @foreach ($networkModels as $network)
@include('fo.partials.networks.slider-card', [ - 'networkModel' => $networkModel + 'networkModel' => $network ])
@endforeach @@ -104,4 +117,14 @@
+
+ +
@endsection diff --git a/resources/views/fo/pages/produce/show.blade.php b/resources/views/fo/pages/produce/show.blade.php index e505b67..e721ad8 100644 --- a/resources/views/fo/pages/produce/show.blade.php +++ b/resources/views/fo/pages/produce/show.blade.php @@ -150,6 +150,9 @@ @endforeach +
+
diff --git a/resources/views/bo/pages/aisles/index.blade.php b/resources/views/bo/pages/aisles/index.blade.php index 748e9d6..22a7477 100644 --- a/resources/views/bo/pages/aisles/index.blade.php +++ b/resources/views/bo/pages/aisles/index.blade.php @@ -13,7 +13,7 @@ Tous les rayons @foreach ($networkModels as $networkModel) - @endforeach From 860cbe272b87e1109b248dac158fc253ef5ab569 Mon Sep 17 00:00:00 2001 From: Corentin Huet Date: Fri, 13 Mar 2026 15:46:34 +0100 Subject: [PATCH 3/3] fix: :rotating_light: resolve phpcs and phpstan errors --- app/Http/Requests/Bo/UpdateOrderRequest.php | 4 ++-- app/Traits/Controllers/UpdateModelOrder.php | 5 ++++- app/Traits/Models/Orderable.php | 7 +++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/app/Http/Requests/Bo/UpdateOrderRequest.php b/app/Http/Requests/Bo/UpdateOrderRequest.php index 9a7fe87..cc998fb 100644 --- a/app/Http/Requests/Bo/UpdateOrderRequest.php +++ b/app/Http/Requests/Bo/UpdateOrderRequest.php @@ -12,8 +12,7 @@ class UpdateOrderRequest extends FormRequest * * @var Model $orderable */ - - private Model $orderableModel; + private Model $orderableModel; /** * Determine if the user is authorized to make this request. @@ -50,6 +49,7 @@ class UpdateOrderRequest extends FormRequest 'min:1', sprintf('max:%s', $this->orderableModel->max('order')), function ($attribute, $value, $fail) { + /** @phpstan-ignore-next-line */ if ($this->orderableModel && intval($value) === $this->orderableModel->order) { $fail("La valeur de {$attribute} doit être différente de la valeur actuelle."); } diff --git a/app/Traits/Controllers/UpdateModelOrder.php b/app/Traits/Controllers/UpdateModelOrder.php index 05973b9..3a283a5 100644 --- a/app/Traits/Controllers/UpdateModelOrder.php +++ b/app/Traits/Controllers/UpdateModelOrder.php @@ -13,7 +13,7 @@ trait UpdateModelOrder * Updates the model order and shifts affected siblings accordingly * * @param UpdateOrderRequest $request - * @param Model $model + * @param Model $model * @return \Illuminate\Http\RedirectResponse */ public function changeCustomOrder(UpdateOrderRequest $request, Model $model): \Illuminate\Http\RedirectResponse @@ -21,16 +21,19 @@ trait UpdateModelOrder $newOrder = $request->validated('order'); return DB::transaction(function () use ($model, $newOrder): RedirectResponse { + /** @phpstan-ignore-next-line */ $groupField = $model->getOrderGroupField(); $query = $model::query() ->whereKeyNot($model) + /** @phpstan-ignore-next-line */ ->whereBetween('order', [min($model->order, $newOrder), max($model->order, $newOrder)]); if ($groupField) { $query->where($groupField, $model->{$groupField}); } + /** @phpstan-ignore-next-line */ $model->order < $newOrder ? $query->decrement('order', 1) : $query->increment('order', 1); $model->order = $newOrder; diff --git a/app/Traits/Models/Orderable.php b/app/Traits/Models/Orderable.php index 6f6a0a3..b060503 100644 --- a/app/Traits/Models/Orderable.php +++ b/app/Traits/Models/Orderable.php @@ -20,12 +20,13 @@ trait Orderable /** * Set order after the last element of the list. * - * @param Model $model - * @param bool $isDeletion + * @param Model $model + * @param boolean $isDeletion * @return void */ public static function setOrder(Model $model, bool $isDeletion = false): void { + /** @phpstan-ignore-next-line */ $groupField = $model->getOrderGroupField(); $maxOrderQuery = $model::query(); @@ -38,6 +39,7 @@ trait Orderable if ($isDeletion) { $query = $model::query() ->whereKeyNot($model) + /** @phpstan-ignore-next-line */ ->whereBetween('order', [$model->order, $maxOrder]); if ($groupField) { @@ -48,6 +50,7 @@ trait Orderable return; } + /** @phpstan-ignore-next-line */ $model->order = $maxOrder + 1; } }
{{ $aisleModel->name }} {{ $aisleModel->network->name }} {{ $aisleModel->name }}