feat: ✨ add desired location in joins us formulary #84

This commit is contained in:
Alexis Gousseau 2025-06-16 12:14:39 +02:00
parent 6bca2d4a13
commit 4656dd598e
12 changed files with 109 additions and 57 deletions

View file

@ -0,0 +1,27 @@
<?php
namespace App\Enums;
use App\Traits\Enums\BaseEnum;
enum DesiredLocation: int
{
use BaseEnum;
case avignon = 1;
case herbignac = 2;
case tarare = 3;
case none = 4;
/**
* Optionnal labels definition.
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::avignon->name => 'Avignon',
self::herbignac->name => 'Herbignac',
self::tarare->name => 'Tarare',
self::none->name => 'Indifférent',
];
}

View file

@ -28,7 +28,7 @@ class StaticPageController extends Controller
* @param \App\Models\StaticPage $aboutUsPage
* @return \Illuminate\Contracts\View\View
*/
public function aboutUs(StaticPage $aboutUsPage)
public function aboutUs(StaticPage $aboutUsPage): \Illuminate\Contracts\View\View
{
$aboutUsPage = StaticPage::query()->where('type', StaticPageType::aboutus)
->get();
@ -41,7 +41,7 @@ class StaticPageController extends Controller
* @param \App\Models\StaticPage $legalPage
* @return \Illuminate\Contracts\View\View
*/
public function legals(StaticPage $legalPage)
public function legals(StaticPage $legalPage): \Illuminate\Contracts\View\View
{
$legalPage = StaticPage::query()->where('type', StaticPageType::legals)->get();
return view('fo.pages.legals', ['staticPageModel' => $legalPage[0]]);
@ -53,7 +53,7 @@ class StaticPageController extends Controller
* @param \App\Models\StaticPage $policiesPage
* @return \Illuminate\Contracts\View\View
*/
public function policies(StaticPage $policiesPage)
public function policies(StaticPage $policiesPage): \Illuminate\Contracts\View\View
{
$policiesPage = StaticPage::query()->where('type', StaticPageType::confidentiality)->get();
return view('fo.pages.legals', ['staticPageModel' => $policiesPage[0]]);

View file

@ -2,8 +2,10 @@
namespace App\Http\Requests\Fo;
use App\Enums\DesiredLocation;
use App\Lib\Helpers\ToolboxHelper;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\Enum;
class JoinusRequest extends FormRequest
{
@ -12,17 +14,18 @@ class JoinusRequest extends FormRequest
*
* @return array
*/
public function rules()
public function rules(): array
{
ToolboxHelper::validateRecaptcha($this, \config('services.google.recaptcha.version'));
return [
'last_name' => 'required|string|between:3,255',
'first_name' => 'required|string|between:3,255',
'email' => 'required|email:rfc,strict,dns,spoof,filter|max:255',
'phone' => 'required|numeric|min:0',
'message' => 'required|string|between:3,500',
"file" => "sometimes|nullable|mimes:pdf|max:10000"
'last_name' => 'required|string|between:3,255',
'first_name' => 'required|string|between:3,255',
'email' => 'required|email:rfc,strict,dns,spoof,filter|max:255',
'phone' => 'required|numeric|min:0',
'desired_location' => ['required', new Enum(DesiredLocation::class)],
'message' => 'required|string|between:3,500',
"file" => "sometimes|nullable|mimes:pdf|max:10000"
];
}
@ -34,12 +37,13 @@ class JoinusRequest 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'),
'phone' => trans('validation.attributes.phone'),
'message' => trans('validation.attributes.message'),
'file' => trans('validation.attributes.file'),
'first_name' => trans('validation.attributes.first_name'),
'last_name' => trans('validation.attributes.last_name'),
'email' => trans('validation.attributes.email'),
'phone' => trans('validation.attributes.phone'),
'desired_location' => trans('validation.custom.desired_location'),
'message' => trans('validation.attributes.message'),
'file' => trans('validation.attributes.file'),
];
}
}

View file

@ -2,6 +2,7 @@
namespace App\Mail;
use App\Enums\DesiredLocation;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Attachment;
@ -27,7 +28,8 @@ class SendJoinusMail extends Mailable
*/
public function __construct(\stdClass $data)
{
$this->data = clone $data;
$data->desired_location = DesiredLocation::make($data->desired_location)->label();
$this->data = clone $data;
}
/**
@ -77,6 +79,7 @@ class SendJoinusMail extends Mailable
* @property string $first_name
* @property string $email
* @property string $phone
* @property \App\Enums\DesiredLocation $desired_location
* @property string $message
* @property \Illuminate\Http\UploadedFile $file
* @phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses

View file

@ -246,6 +246,7 @@ return [
'key_together_2' => 'key number for "live together" 2',
'key_together_3' => 'key number for "live together" 3',
'key_together_4' => 'key number for "live together" 4',
'desired_location' => 'desired location',
'model' => 'target element',
'nutritionnal_values' => 'nutritionnal values',
'object' => 'object',

View file

@ -248,6 +248,7 @@ return [
'key_together_2' => 'Chiffre clé "vivre ensemble" 2',
'key_together_3' => 'Chiffre clé "vivre ensemble" 3',
'key_together_4' => 'Chiffre clé "vivre ensemble" 4',
'desired_location' => 'localisation souhaitée',
'model' => 'élément ciblé',
'nutritionnal_values' => 'valeurs nutritionnelles',
'object' => 'objet',

View file

@ -146,6 +146,33 @@ a {
}
}
.select-form {
&::after {
position: absolute;
right: 1rem;
bottom: 0.3rem;
display: block;
width: 2rem;
height: 2rem;
background: url("@/images/global/btn-arrow.png");
background-position: center;
background-repeat: no-repeat;
background-size: 100% 100%;
content: "";
pointer-events: none;
transform: rotate(180deg);
transition: 0.1s ease-in-out;
}
&.active::after {
background: url("@/images/global/btn-arrow-dark.png");
background-position: center;
background-repeat: no-repeat;
background-size: 100% 100%;
transform: rotate(270deg);
}
}
// XXXXXXX XXXXXXXLLLLLLLLLLL
// X:::::X X:::::XL:::::::::L
// X:::::X X:::::XL:::::::::L

View file

@ -4,31 +4,4 @@
max-width: 55rem;
}
}
.select-form {
&::after {
position: absolute;
right: 1rem;
bottom: 0.3rem;
display: block;
width: 2rem;
height: 2rem;
background: url("@/images/global/btn-arrow.png");
background-position: center;
background-repeat: no-repeat;
background-size: 100% 100%;
content: "";
pointer-events: none;
transform: rotate(180deg);
transition: 0.1s ease-in-out;
}
&.active::after {
background: url("@/images/global/btn-arrow-dark.png");
background-position: center;
background-repeat: no-repeat;
background-size: 100% 100%;
transform: rotate(270deg);
}
}
}

View file

@ -136,4 +136,18 @@ document.addEventListener("DOMContentLoaded", function () {
});
});
// * Toggle la dropdown Arrow du select.
if (document.querySelector("section.contact") || document.querySelector("section.joinus")) {
const contactFormSelectList = document.querySelectorAll("select") as NodeListOf<HTMLSelectElement>;
document.body.addEventListener("click", function (e: MouseEvent) {
const target = e.target as HTMLElement | null;
contactFormSelectList.forEach(select => {
if (select.contains(target)) {
select.parentElement!.classList.toggle("active");
} else {
select.parentElement!.classList.remove("active");
}
});
});
}
});

View file

@ -9,19 +9,6 @@ document.addEventListener("DOMContentLoaded", function () {
return `Élement du dom ${fieldName} inexistant.`;
}
// * Toggle la dropdown Arrow du select.
const contactFormSelectList = contactPage.querySelectorAll("select") as NodeListOf<HTMLSelectElement>;
document.body.addEventListener("click", function (e: MouseEvent) {
const target = e.target as HTMLElement | null;
contactFormSelectList.forEach(select => {
if (select.contains(target)) {
select.parentElement!.classList.toggle("active");
} else {
select.parentElement!.classList.remove("active");
}
});
});
// * Show more input on specific option selected.
const selectObject = contactPage.querySelector("select[name=\"object\"]") as HTMLSelectElement | null;
const contactProductsInput = contactPage.querySelector(".contact-products-input") as HTMLDivElement | null;

View file

@ -10,6 +10,7 @@
- **{{ __('validation.attributes.last_name') }}:** {{ $data->last_name ?? '' }}
- **{{ __('validation.attributes.email') }}:** {{ $data->email }}
- **{{ __('validation.attributes.phone') }}:** {{ $data->phone ?? '' }}
- **{{ __('validation.custom.desired_location') }}:** {{ $data->desired_location }}
- **{{ __('validation.attributes.message') }}:** {{ $data->message }}
@endcomponent

View file

@ -201,6 +201,20 @@
</label>
<input class="form-control" id="phone" name="phone" value="{{ old('phone') }}" required>
</fieldset>
<fieldset class="select-form position-relative mb-3">
<label for="desired_location">
{{ Str::of(__('validation.custom.desired_location'))->ucFirst()->value() }}*&nbsp;:
</label>
<select class="form-control" name="desired_location" role="button">
<option disabled selected>{{ __('validation.custom.desired_location') }}</option>
@foreach (\App\Enums\DesiredLocation::toArray() as $key => $enumObject)
<option value="{{ $enumObject->value }}"
@if (intval(old('desired_location')) === $enumObject->value) selected @endif>
{{ $enumObject->label }}
</option>
@endforeach
</select>
</fieldset>
<fieldset class="row mb-xl-0 mb-3">
<div class="col-12 col-xl-5 d-flex align-items-center">
<p class="m-0">{{ __('Pièce jointe') }}&nbsp;:</p>