Merge branch 'develop' into trunk

This commit is contained in:
Noah Lancien 2026-04-09 08:59:24 +02:00
commit 44ca6a3055
26 changed files with 450 additions and 32 deletions

View file

@ -7,9 +7,11 @@ use App\Enums\TagTypeEnum;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\Advice\StoreAdviceRequest;
use App\Http\Requests\Bo\Advice\UpdateAdviceRequest;
use App\Http\Requests\Bo\UpdateOrderRequest;
use App\Models\Advice;
use App\Models\Product;
use App\Models\Tag;
use App\Traits\Controllers\ManagesOrder;
use App\Traits\Controllers\UpdateModelPublished;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Http\Request;
@ -20,6 +22,7 @@ use Illuminate\Support\Str;
class AdviceController extends Controller
{
use UpdateModelPublished;
use ManagesOrder;
/**
* Display a listing of the resource.

View file

@ -7,6 +7,7 @@ use App\Http\Requests\Bo\BrigadeSections\UpdateBrigadeSectionsRequest;
use App\Models\BrigadeSection;
use App\Traits\Controllers\ChangesModelOrder;
use App\Traits\Controllers\UpdateModelPublished;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Uwil\Laravel\Common\Controllers\Controller;
@ -69,7 +70,7 @@ class BrigadeSectionController extends Controller
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\Bo\BrigadeSections\StoreBrigadeSectionRequest $request
* @param \App\Http\Requests\Bo\BrigadeSections\StoreBrigadeSectionsRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(StoreBrigadeSectionsRequest $request): \Illuminate\Http\RedirectResponse
@ -111,7 +112,7 @@ class BrigadeSectionController extends Controller
* @param \App\Models\BrigadeSection $brigadeSection
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateBrigadeSectionsRequest $request, BrigadeSection $brigadeSection): \Illuminate\Http\RedirectResponse
public function update(UpdateBrigadeSectionsRequest $request, BrigadeSection $brigadeSection): RedirectResponse
{
return DB::transaction(function () use ($request, $brigadeSection) {
$brigadeSection->fill($request->validated());

View file

@ -6,6 +6,7 @@ use App\Enums\TagTypeEnum;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\Products\StoreProductRequest;
use App\Http\Requests\Bo\Products\UpdateProductRequest;
use App\Http\Requests\Bo\UpdateOrderRequest;
use App\Lib\Helpers\FileStorageHelper;
use App\Models\Product;
use App\Models\Range;
@ -13,6 +14,7 @@ use App\Models\Subrange;
use App\Models\Tag;
use App\Traits\Controllers\UpdateModelPublished;
use App\Traits\Controllers\ChangesModelOrder;
use App\Traits\Controllers\ManagesOrder;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
@ -21,6 +23,7 @@ class ProductController extends Controller
{
use ChangesModelOrder;
use UpdateModelPublished;
use ManagesOrder;
/**
* Display a listing of the resource.

View file

@ -7,6 +7,8 @@ use App\Http\Controllers\Controller;
use App\Http\Requests\Fo\Contact\ContactRequest;
use App\Mail\ContactFormMail;
use App\Models\StaticPage;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Session;
use LDC\LDCCRM\Exceptions\ApiErrorException;
@ -35,6 +37,14 @@ class ContactController extends Controller
*/
public function contactSubmit(ContactRequest $request): \Illuminate\Http\RedirectResponse
{
$recipients = config('mail.contactsList.contactform');
if (empty($recipients)) {
Log::warning('Aucun destinataire configuré pour le formulaire de contact.');
return back()
->withErrors(['global' => __('Une erreur est survenue, veuillez réessayer plus tard.')])
->withInput();
}
$redirection = back()->with('success', trans(
'Votre message a bien été envoyé, merci de votre intérêt, nous répondrons dans les meilleurs délais.'
));
@ -57,14 +67,32 @@ class ContactController extends Controller
}
} //end if
foreach (config('mail.contactsList.contactform') as $recipient) {
foreach ($recipients as $recipient) {
Mail::to($recipient)->send(new ContactFormMail($request));
}
Session::forget('saveProductInBasket');
Session::forget('contact_draft');
Session::flash('matomo_generate_lead');
return $redirection;
}
/**
* Save data form as draft
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function saveDraft(Request $request): \Illuminate\Http\JsonResponse
{
$request->session()->put('contact_draft', $request->only([
'firstname', 'lastname', 'email', 'phone',
'activity', 'society', 'postcode', 'city',
'message', 'callTime', 'opt_in',
]));
return response()->json(['success' => true]);
}
}

View file

@ -0,0 +1,72 @@
<?php
namespace App\Http\Requests\Bo;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Http\FormRequest;
class UpdateOrderRequest extends FormRequest
{
/**
* Attribute model needed.
*
* @var Model $orderable
*/
private Model $orderable;
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return auth('backend')->check();
}
/**
* Prepare the data for validation.
*
* @return void
*/
protected function prepareForValidation(): void
{
$this->orderable = collect($this->route()->parameters())
->first(fn($param) => $param instanceof Model);
$groupField = $this->orderable->getOrderGroupField();
if ($groupField) {
$this->orderable::query()->where($groupField, $this->orderable->{$groupField});
}
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules(): array
{
return [
'priority_order' => [
'required',
'integer',
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
function ($attribute, $value, $fail) {
if ($this->orderable && intval($value) < 1) {
$fail(trans('validation.custom.min_priority'));
}
},
sprintf('max:%s', $this->orderable->max('priority_order')),
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
function ($attribute, $value, $fail) {
if ($this->orderable && intval($value) === $this->orderable->priority_order) {
$fail(trans('validation.custom.same_priority'));
}
},
],
];
}
}

View file

@ -6,6 +6,7 @@ use App\Enums\Advices\AdviceTypeEnum;
use App\Enums\Advices\AdviceDifficultyEnum;
use App\Lib\Helpers\FileStorageHelper;
use App\Lib\Helpers\ToolboxHelper;
use App\Traits\Models\Orderable;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
@ -46,6 +47,7 @@ use Uwil\Laravel\Redirections\Traits\IsRedirectable;
* @property integer|null $preparation_time Time of preparation.
* @property \App\Enums\Advices\AdviceDifficultyEnum|null $difficulty Difficulty.
* @property boolean $published Status.
* @property integer $priority_order Priority Order.
* @property-read \Illuminate\Support\Carbon $created_at Created date.
* @property-read \Illuminate\Support\Carbon $updated_at Updated date.
*
@ -65,6 +67,7 @@ class Advice extends Authenticatable implements SeoInterface, Sitemapable, Redir
use HasFactory;
use SeoTrait;
use IsRedirectable;
use Orderable;
/**
* The attributes that are mass assignable.
@ -95,7 +98,8 @@ class Advice extends Authenticatable implements SeoInterface, Sitemapable, Redir
'cooking_time',
'preparation_time',
'difficulty',
'published'
'published',
'priority_order'
];
/**
@ -119,6 +123,7 @@ class Advice extends Authenticatable implements SeoInterface, Sitemapable, Redir
{
static::creating(function (self $model) {
self::manageFields($model);
self::bootOrderable($model);
});
static::updating(function (self $model) {
self::manageFields($model);
@ -133,6 +138,7 @@ class Advice extends Authenticatable implements SeoInterface, Sitemapable, Redir
FileStorageHelper::removeFile($model, 'picture');
FileStorageHelper::removeFile($model, 'sticker');
FileStorageHelper::removeFile($model, 'sticker_sm');
self::setOrder($model);
});
}
@ -375,4 +381,15 @@ class Advice extends Authenticatable implements SeoInterface, Sitemapable, Redir
$params = ['publishedAdvice' => $model];
return SitemapHelper::generateUrl($route, $params, $model);
}
/**
* Group ordering by type.
*
* @return string
*/
public function getOrderGroupField(): string
{
return 'type';
}
}

View file

@ -106,7 +106,7 @@ class BrigadeSection extends Model
* @param self $model
* @param boolean $isDeletion
* @return void
* @throws \Illuminate\Validation\ValidationException
* @throws \Illuminate\Validation\ValidationException Returns if fails.
*/
private static function assertLimitPublishedSections(self $model, bool $isDeletion = false)
{

View file

@ -13,6 +13,7 @@ use App\Lib\Helpers\FileStorageHelper;
use Illuminate\Database\Eloquent\Model;
use Spatie\Sitemap\Contracts\Sitemapable;
use App\Enums\Products\ProductSpeciesEnum;
use App\Traits\Models\Orderable;
use Uwil\SitemapGenerator\Lib\SitemapHelper;
use Uwil\Seo\Laravel\Interfaces\SeoInterface;
use Uwil\Laravel\Redirections\Traits\IsRedirectable;
@ -42,6 +43,7 @@ use Uwil\Laravel\Redirections\Interfaces\RedirectableInterface;
* @property boolean $is_egalim Is egalim or not.
* @property boolean $published Status.
* @property integer $order Order.
* @property integer $priority_order Priority Order.
* @property-read \Illuminate\Support\Carbon $created_at Created date.
* @property-read \Illuminate\Support\Carbon $updated_at Updated date.
*
@ -56,6 +58,7 @@ class Product extends Model implements SeoInterface, Sitemapable, RedirectableIn
use HasFactory;
use SeoTrait;
use IsRedirectable;
use Orderable;
/**
* The attributes that are mass assignable.
@ -83,7 +86,8 @@ class Product extends Model implements SeoInterface, Sitemapable, RedirectableIn
'is_vip',
'is_egalim',
'order',
'published'
'published',
'priority_order',
];
/**
@ -113,7 +117,7 @@ class Product extends Model implements SeoInterface, Sitemapable, RedirectableIn
// * EVENT CLOSURES.
static::creating(function (self $model) {
self::manageFields($model);
$model->order = \intval(self::query()->max('order')) + 1;
self::bootOrderable($model);
});
static::updating(function (self $model) {
self::manageFields($model);
@ -131,6 +135,7 @@ class Product extends Model implements SeoInterface, Sitemapable, RedirectableIn
$model,
!is_array($model->getOriginal('slider_pictures')) ? [] : $model->getOriginal('slider_pictures'),
);
self::setOrder($model);
});
}

View file

@ -0,0 +1,55 @@
<?php
namespace App\Traits\Controllers;
use App\Http\Requests\Bo\UpdateOrderRequest;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\RedirectResponse;
trait ManagesOrder
{
/**
* Updates the order of a model and reorders all impacted elements.
*
* Shifts by +1 or -1 all elements located between the old
* and new position of the model, then assigns the new position
* to the target model. The whole operation runs inside a
* database transaction to ensure data consistency.
*
* @param UpdateOrderRequest $request The validated request containing the 'priority' field.
* @param Model $model The model to reorder (must use the Orderable trait).
* @return RedirectResponse
*
* @throws \Throwable Returns if save fail.
*/
public function changeOrderPriority(UpdateOrderRequest $request, Model $model): RedirectResponse
{
$newPriority = (int) $request->validated('priority_order');
return DB::transaction(function () use ($model, $newPriority): RedirectResponse {
$query = $model::query()
->whereKeyNot($model)
->whereBetween('priority_order', [
min($model->priority_order, $newPriority),
max($model->priority_order, $newPriority),
]);
$groupField = $model->getOrderGroupField();
if ($groupField) {
$query->where($groupField, $model->{$groupField});
}
$model->priority_order < $newPriority
? $query->decrement('priority_order', 1)
: $query->increment('priority_order', 1);
$model->priority_order = $newPriority;
$model->saveOrFail();
return redirect()->back()->with('success', trans('crud.messages.order_changed'));
});
}
}

View file

@ -0,0 +1,61 @@
<?php
namespace App\Traits\Models;
use Illuminate\Database\Eloquent\Model;
trait Orderable
{
/**
* Returns the grouping field used for ordering.
* Returns null if the order is global
*
* @return string|null
*/
public function getOrderGroupField(): ?string
{
return null;
}
/**
* shifts down by 1 all elements positioned after the delete.
*
* @param Model $model
* @return void
*/
public static function setOrder(Model $model): void
{
$groupField = $model->getOrderGroupField();
$query = $model::query()->where('priority_order', '>', $model->priority_order);
if ($groupField) {
$query->where($groupField, $model->{$groupField});
}
$query->each(function (Model $item): void {
$item->priority_order -= 1;
$item->saveOrFail();
});
}
/**
* Assigns the next order value on creation.
*
* @return void
*/
public static function bootOrderable(): void
{
static::creating(function (Model $model): void {
if (!$model->priority_order) {
$groupField = $model->getOrderGroupField();
$query = static::query();
if ($groupField) {
$query->where($groupField, $model->{$groupField});
}
$model->priority_order = ($query->max('priority_order') ?? 0) + 1;
}
});
}
}

View file

@ -120,6 +120,6 @@ return [
*/
'contactsList' => [
'contactform' => explode(',', env('MAIL_LIST_CONTACTFORM') ?? ''),
'contactform' => array_filter(explode(',', env('MAIL_LIST_CONTACTFORM', '') ?? '')),
]
];

View file

@ -44,7 +44,8 @@ class SlideFactory extends Factory
'picture_alt' => $picture_alt,
'picture_title' => $picture_title,
'picture_thumbnail_alt' => $picture_alt,
'picture_thumbnail_title' => $picture_title
'picture_thumbnail_title' => $picture_title,
'published' => $this->faker->boolean(),
];
}
}

View file

@ -0,0 +1,38 @@
<?php
use App\Models\Product;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('products', function (Blueprint $table) {
$table->unsignedInteger('priority_order')->comment('Ordre de priorite')->default(0)->after('order');
});
$order = 1;
Product::query()
->orderBy('order')
->each(function (Product $product) use (&$order) {
$product->priority_order = $order++;
$product->saveOrFail();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('products', function (Blueprint $table) {
$table->dropColumn('priority_order');
});
}
};

View file

@ -0,0 +1,43 @@
<?php
use App\Enums\Advices\AdviceTypeEnum;
use App\Models\Advice;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('advice', function (Blueprint $table) {
$table->unsignedInteger('priority_order')->comment('Ordre de priorite')->default(0)->after('published');
});
// loop through all types and in each type we order
Advice::query()->select('type')->pluck('type')
->each(function (AdviceTypeEnum $type) {
$order = 1;
Advice::query()
->where('type', $type)
->orderBy('created_at')
->each(function (Advice $advice) use (&$order) {
$advice->priority_order = $order++;
$advice->saveOrFail();
});
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('advice', function (Blueprint $table) {
$table->dropColumn('priority_order');
});
}
};

View file

@ -21,7 +21,7 @@ class ExpertiseProductSeeder extends Seeder
ExpertiseProduct::factory(rand(0, 3))->make()->each(
// @phpstan-ignore-next-line
function (ExpertiseProduct $expertiseProduct) use ($enum) {
$expertiseProduct->page = $enum;
$expertiseProduct->page = ExpertiseProductPageEnum::make($enum->value);
$expertiseProduct->saveQuietly();
}
);

View file

@ -141,5 +141,10 @@ return [
'seo_title' => 'SEO title',
'seo_description' => 'SEO description',
'type' => 'type',
'new_priority' => 'New priority',
'priority' => 'priority',
'same_priority' => 'the priority value must be different from the current value.',
'min_priority' => 'the priority value must be greater than 0.'
],
];

View file

@ -151,7 +151,11 @@ return [
'seo_title' => 'titre SEO',
'seo_description' => 'description SEO',
'type' => 'type',
'url' => 'Le champ :field doit être une URL valide.'
'url' => 'Le champ :field doit être une URL valide.',
'new_priority' => 'Nouvelle priorité',
'priority' => 'priorité',
'same_priority' => 'La valeur de priorité doit être différente de la valeur actuelle.',
'min_priority' => 'La valeur de priorité doit être supérieure à 0.'
],
'attributes' => [
'advantages' => 'Avantages',

View file

@ -37,6 +37,7 @@ import {
faTrash,
faUndoAlt,
faWandMagic,
faChevronDown
} from "@fortawesome/free-solid-svg-icons";
config.autoReplaceSvg = false;
@ -72,7 +73,7 @@ library.add(faListUl);
library.add(faCircleCheck);
library.add(faCircleExclamation);
library.add(faCircleInfo);
library.add(faChevronDown);
// Front
library.add(faChevronLeft);
library.add(faChevronRight);

View file

@ -19,3 +19,6 @@ window.CookieNotice = CookieNotice;
import "./base/common";
import "./base/matomo";
// TS script
import "./pages/contact"

View file

@ -0,0 +1,30 @@
document.addEventListener('DOMContentLoaded', () => {
const plusButton = document.querySelector<HTMLAnchorElement>('.btn-plus-wrapper');
const form = document.getElementById('contact-form') as HTMLFormElement | null;
const csrfToken = document.querySelector<HTMLMetaElement>('meta[name="csrf-token"]')?.content;
const saveDraftUrl = form?.dataset.saveDraftUrl;
if (!plusButton || !form || !csrfToken || !saveDraftUrl) {
return;
}
plusButton.addEventListener('click', (e) => {
e.preventDefault();
const href = plusButton.href;
const formData = new FormData(form);
const data = Object.fromEntries(formData.entries());
fetch(saveDraftUrl, {
method: 'POST',
headers: {
'X-CSRF-TOKEN': csrfToken,
'Content-Type': 'application/json',
'Accept': 'application/json',
},
body: JSON.stringify(data),
}).finally(() => {
window.location.href = href;
});
});
});

View file

@ -0,0 +1,21 @@
<td class="text-center align-middle">
<div class="d-flex justify-content-center align-items-center">
<b class="mx-3">{{ $value ?? '' }}</b>
<div class="dropdown">
<button class="btn btn-secondary" type="button" data-bs-toggle="dropdown" aria-expanded="false">
<i class="fa-solid fa-chevron-down"></i>
</button>
<div class="dropdown-menu">
<form class="px-4 py-3" action="{{ $route }}" method="POST" novalidate>
@csrf
@method('PATCH')
<div class="mb-3">
<label for="priority-{{ $model->getKey() }}" class="form-label">{{ __('validation.custom.new_priority') }}</label>
<input type="number" class="form-input" id="priority-{{ $model->getKey() }}" placeholder="1" name="priority_order" min="1">
</div>
<button type="submit" class="btn btn-primary">{{ _('Sauvegarder') }}</button>
</form>
</div>
</div>
</div>
</td>

View file

@ -22,6 +22,7 @@
<thead>
@include('bo.modules.table-col-sorter', [
'cols' => [
'priority_order' => Str::ucfirst(__('validation.custom.priority')),
'title' => __('validation.attributes.title'),
'picture' => __('validation.attributes.picture'),
'published' => __('validation.attributes.published'),
@ -32,6 +33,11 @@
<tbody>
@foreach ($adviceModels as $adviceModel)
<tr class="border-bottom">
@include('bo.modules.change-model-order-select', [
'model' => $adviceModel,
'value' => $adviceModel->priority_order,
'route' => route('bo.advice.change-priority', $adviceModel)
])
<td class="text-center align-middle">{{ $adviceModel->title }}</td>
<td class="text-center align-middle">
@if($adviceModel->picture)
@ -46,10 +52,8 @@
'model' => $adviceModel,
])
<td class="text-center align-middle"><span class="badge bg-secondary">{{ $adviceModel->updated_at }}</span></td>
@php
$routeName = request()->route()->getName();
@endphp
@if (empty(request()->search) && Session::get("$routeName.sort_col") === 'order')
@if (empty(request()->search) && request()->range)
@php $routeName = request()->route()->getName(); @endphp
@include('bo.modules.change-model-order', [
'routeName' => 'advice',
'models' => $adviceModels,

View file

@ -33,6 +33,7 @@
$cols = [];
$routeName = request()->route()->getName();
$cols = array_merge($cols, [
'priority_order' => Str::ucfirst(__('validation.custom.priority')),
'label' => Str::ucfirst(__('validation.attributes.label')),
'species' => Str::ucfirst(__('validation.attributes.species')),
'picture' => Str::ucfirst(__('validation.attributes.picture')),
@ -46,12 +47,17 @@
}
@endphp
@include('bo.modules.table-col-sorter', [
'cols' => $cols,
'cols' => $cols,
])
</thead>
<tbody>
@foreach ($productModels as $productModel)
<tr class="border-bottom">
@include('bo.modules.change-model-order-select', [
'model' => $productModel,
'value' => $productModel->priority_order,
'route' => route('bo.products.change-priority', $productModel)
])
<td class="text-center align-middle">{{ $productModel->label }}</td>
<td class="text-center align-middle">{{ $productModel->species->label() }}</td>
<td class="text-center align-middle">

View file

@ -1,3 +1,7 @@
@php
$draft = Session::get('contact_draft', []);
$val = fn(string $key) => old($key, $draft[$key] ?? '');
@endphp
@extends('fo.layout', ['page' => 'contact'])
@section('title', $staticPageModel->seo_title)
@ -29,27 +33,27 @@
</div>
<div class="contact-wrapper position-relative bg-ardoise-radial pt-sm-4 pt-4">
<form class="form-contact" id="contact-form" action="{{ route('fo.contact.submit') }}" method="post"
inert="true">
inert="true" data-save-draft-url="{{ route('fo.contact.save-draft') }}">
@csrf
<div class="row wrapper-sm justify-content-center">
<div class="col-12 col-sm-6 d-flex justify-content-center justify-content-sm-end flex-wrap">
<input class="form-control black-square mb-3 p-3" id="firstname" name="firstname" type="text"
value="{{ old('firstname') }}" placeholder="{{ __('Prénom') }}">
value="{{ $val('firstname') }}" placeholder="{{ __('Prénom') }}">
@include('fo.modules.input-error', ['inputName' => 'firstname'])
</div>
<div class="col-12 col-sm-6 d-flex justify-content-center justify-content-sm-start flex-wrap">
<input class="form-control black-square mb-3 p-3" id="lastname" name="lastname" type="text"
value="{{ old('lastname') }}" placeholder="{{ __('Nom *') }}" required>
value="{{ $val('lastname') }}" placeholder="{{ __('Nom *') }}" required>
@include('fo.modules.input-error', ['inputName' => 'lastname'])
</div>
<div class="col-12 col-sm-6 d-flex justify-content-center justify-content-sm-start flex-wrap">
<input class="form-control black-square mb-3 p-3" id="email" name="email" type="email"
value="{{ old('email') }}" placeholder="{{ __('Adresse e-mail *') }}" required>
value="{{ $val('email') }}" placeholder="{{ __('Adresse e-mail *') }}" required>
@include('fo.modules.input-error', ['inputName' => 'email'])
</div>
<div class="col-12 col-sm-6 d-flex justify-content-center justify-content-sm-start flex-wrap">
<input class="form-control black-square mb-3 p-3" id="phone" name="phone" type="text"
value="{{ old('phone') }}" placeholder="{{ __('N° de téléphone *') }}" required>
value="{{ $val('phone') }}" placeholder="{{ __('N° de téléphone *') }}" required>
@include('fo.modules.input-error', ['inputName' => 'phone'])
</div>
<div class="col-12 col-sm-6 d-flex justify-content-center justify-content-sm-start flex-wrap">
@ -57,28 +61,28 @@
name="activity" role="button">
{{ __('Votre activité') }} *
<option class="option-activity-item disabled p-3 px-3"
@if (!old('activity')) selected @endif disabled>
@if (!old('activity') && empty($draft['activity'])) selected @endif disabled>
{{ __('Votre activité') }} *</option>
@foreach (\App\Enums\Contact\ContactActivityEnum::toArray() as $key => $activity)
<option class="option-activity-item px-3" value="{{ $activity->value }}"
@if (old('activity') == $activity->value) selected @endif>{{ $activity->label }}</option>
@if (old('activity',$draft['activity'] ?? '') == $activity->value) selected @endif>{{ $activity->label }}</option>
@endforeach
</select>
@include('fo.modules.input-error', ['inputName' => 'activity'])
</div>
<div class="col-12 col-sm-6 d-flex justify-content-center justify-content-sm-start flex-wrap">
<input class="form-control black-square mb-3 p-3" id="society" name="society" type="text"
value="{{ old('society') }}" placeholder="{{ __('Société') }}">
value="{{ $val('society') }}" placeholder="{{ __('Société') }}">
@include('fo.modules.input-error', ['inputName' => 'society'])
</div>
<div class="col-12 col-sm-6 d-flex justify-content-center justify-content-sm-start flex-wrap">
<input class="form-control black-square mb-3 p-3" id="postcode" name="postcode" type="text"
value="{{ old('postcode') }}" placeholder="{{ __('Code postal') }}">
value="{{ $val('postcode') }}" placeholder="{{ __('Code postal') }}">
@include('fo.modules.input-error', ['inputName' => 'postcode'])
</div>
<div class="col-12 col-sm-6 d-flex justify-content-center justify-content-sm-start flex-wrap">
<input class="form-control black-square mb-3 p-3" id="city" name="city" type="text"
value="{{ old('city') }}" placeholder="{{ __('Ville') }}">
value="{{ $val('city') }}" placeholder="{{ __('Ville') }}">
@include('fo.modules.input-error', ['inputName' => 'city'])
</div>
</div>
@ -87,7 +91,7 @@
<div class="col">
@include('fo.modules.input-error', ['inputName' => 'message'])
<textarea class="form-control black-square mb-3 p-3" id="message" name="message" cols="30" rows="6"
placeholder="{{ __('Votre message') }} ({{ __('min. 20 caractères.') }}) *" required>{{ old('message') }}</textarea>
placeholder="{{ __('Votre message') }} ({{ __('min. 20 caractères.') }}) *" required>{{ $val('message') }}</textarea>
</div>
</div>
<div class="row wrapper-sm mb-3">
@ -115,7 +119,7 @@
<div class="col">
<input class="input-radio-contact d-none" id="call-time-{{ Str::slug($contactTime->value) }}"
name="callTime" type="radio" value="{{ $contactTime->value }}"
@if (old('callTime') == $contactTime->value) checked @endif>
@if (old('callTime', $draft['callTime'] ?? '') == $contactTime->value) checked @endif>
<label class="label-time-contact butn-cinq position-relative w-100 m-0"
for="call-time-{{ Str::slug($contactTime->value) }}">
{{ $contactTime->label }}
@ -128,7 +132,7 @@
<div class="col col-md-8 lh-sm px-0 py-2">
<div class="form-check text-start">
<input class="form-check-input @if ($errors->has('opt_in')) is-invalid @endif me-1" id="check-optin"
name="opt_in" type="checkbox" @checked(old('opt_in'))>
name="opt_in" type="checkbox" @checked(old('opt_in', $draft['opt_in'] ?? false))>
<label class="form-check-label w-fit" for="check-optin" role="button">
{{ __('Je souhaite m’inscrire à la newsletter') }} {{ Config::get('theme.site_name') }}
</label>
@ -206,5 +210,6 @@
window.WebCookieNotice.acceptCookie('recaptcha');
});
});
</script>
@endpush
@endpush

View file

@ -61,6 +61,12 @@ Route::prefix('bo')
])->where('direction', 'up|down')->name('products.change-order');
Route::post('/products/{product}/change-published', [ProductController::class, 'changePublished'])
->name('products.change-published');
Route::patch('/products/{product}/change-priority', [ProductController::class, 'changeOrderPriority'])
->name('products.change-priority');
Route::patch('/products/{product}/change-order/{direction}', [
BrigadeSectionController::class,
'changeOrder'
])->where('direction', 'up|down')->name('products.change-order');
// * NEWS
Route::resource('news', NewsController::class)->except(['show'])
@ -83,6 +89,8 @@ Route::prefix('bo')
Route::get('advice/{type}/create', [AdviceController::class, 'create'])->name('advice.create');
Route::post('/advice/{advice}/change-published', [AdviceController::class, 'changePublished'])
->name('advice.change-published');
Route::patch('/advice/{advice}/change-priority', [AdviceController::class, 'changeOrderPriority'])
->name('advice.change-priority');
// * EXPERTISE PRODUITS VIP
Route::resource('vips', ExpertiseProductController::class)->except(['show']);
@ -95,7 +103,10 @@ Route::prefix('bo')
Route::resource('brigade_sections', BrigadeSectionController::class)->except(['show'])
->withoutMiddleware('htmlsanitize')
->middleware('htmlsanitize:content');
Route::post('/brigade_sections/{brigade_section}/change-published', [BrigadeSectionController::class, 'changePublished'])
Route::post(
'/brigade_sections/{brigade_section}/change-published',
[BrigadeSectionController::class, 'changePublished']
)
->name('brigade_sections.change-published');
Route::patch('/brigade_sections/{brigade_section}/change-order/{direction}', [
BrigadeSectionController::class,

View file

@ -144,6 +144,7 @@ Route::name('fo.')
Route::get('/', [ContactController::class, 'index'])->name('show');
Route::post('/mail', [ContactController::class, 'contactSubmit'])->name('submit');
});
Route::post('contactez-nous/save-draft', [ContactController::class, 'saveDraft'])->name('contact.save-draft');
Route::get('/restauration-sociale', [ActivitiesController::class, 'sociale'])->name('group');
Route::get('/restauration-commerciale', [ActivitiesController::class, 'commerciale'])->name('trade');