add contact page (listen) + mail
This commit is contained in:
parent
5aff3c64ed
commit
c358bd37f7
32 changed files with 1469 additions and 227 deletions
|
|
@ -60,3 +60,9 @@ VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
|||
|
||||
# Sentry
|
||||
SENTRY_LARAVEL_DSN=
|
||||
|
||||
# MAILS
|
||||
MAIL_CONTACT_REMARK="equipe.web@ldc.fr"
|
||||
MAIL_CONTACT_SPONSORING="equipe.web@ldc.fr"
|
||||
MAIL_CONTACT_SERVICE="equipe.web@ldc.fr"
|
||||
MAIL_CONTACT_OTHER="equipe.web@ldc.fr"
|
||||
|
|
|
|||
27
app/Enums/Listen/ObjectEnum.php
Normal file
27
app/Enums/Listen/ObjectEnum.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums\Listen;
|
||||
|
||||
use App\Traits\Enums\BaseEnum;
|
||||
|
||||
enum ObjectEnum: int
|
||||
{
|
||||
use BaseEnum;
|
||||
|
||||
case remark = 1;
|
||||
case sponsoring = 2;
|
||||
case service = 3;
|
||||
case other = 4;
|
||||
|
||||
/**
|
||||
* Optionnal labels definition.
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
*/
|
||||
private const LABELS = [
|
||||
self::remark->name => 'Contact Commercial ou remarque sur nos produits',
|
||||
self::sponsoring->name => 'Demande de partenariat ou sponsoring',
|
||||
self::service->name => 'Proposition de service au fournisseur',
|
||||
self::other->name => 'Autre demande',
|
||||
];
|
||||
}
|
||||
|
|
@ -2,12 +2,21 @@
|
|||
|
||||
namespace App\Http\Controllers\Fo;
|
||||
|
||||
use App\Enums\Listen\ObjectEnum;
|
||||
use App\Enums\Slides\SliderTypeEnum;
|
||||
use App\Enums\StaticPageType;
|
||||
use App\Enums\Testimonials\TypeEnum;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Fo\ListenFormRequest;
|
||||
use App\Mail\SendConfirmationMail;
|
||||
use App\Mail\SendContactMail;
|
||||
use App\Models\HistoricalMilestone;
|
||||
use App\Models\Section;
|
||||
use App\Models\Site;
|
||||
use App\Models\Slide;
|
||||
use App\Models\StaticPage;
|
||||
use App\Models\Testimonial;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
class StaticPageController extends Controller
|
||||
{
|
||||
|
|
@ -25,6 +34,102 @@ class StaticPageController extends Controller
|
|||
->get();
|
||||
$siteModel = Site::query()->first();
|
||||
|
||||
return view('fo.pages.unveil', compact('staticPageModel', 'sectionModels', 'historicalMilestoneModels', 'siteModel'));
|
||||
return view('fo.pages.unveil', compact(
|
||||
'staticPageModel',
|
||||
'sectionModels',
|
||||
'historicalMilestoneModels',
|
||||
'siteModel'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the 'commitments' page.
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function commit(): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$staticPageModel = StaticPage::query()->where('type', StaticPageType::we_commit)->first();
|
||||
$sectionModels = Section::query()->where('page_id', $staticPageModel->id)->get();
|
||||
$slideModels = Slide::query()
|
||||
->whereIn('slider', [SliderTypeEnum::better_life->value, SliderTypeEnum::respect_earth->value])
|
||||
->get();
|
||||
$testimonialModels = Testimonial::query()
|
||||
->whereIn('type', [
|
||||
TypeEnum::breeding->value,
|
||||
TypeEnum::better_life->value,
|
||||
TypeEnum::respect_earth->value,
|
||||
TypeEnum::feed->value,
|
||||
TypeEnum::volena->value,
|
||||
])
|
||||
->get();
|
||||
|
||||
return view('fo.pages.commitments', compact(
|
||||
'staticPageModel',
|
||||
'sectionModels',
|
||||
'slideModels',
|
||||
'testimonialModels'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the 'legals' page.
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function legals(): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$staticPageModel = StaticPage::query()->where('type', StaticPageType::legals)->first();
|
||||
|
||||
return view('fo.pages.legals', compact(
|
||||
'staticPageModel',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the 'confidentiality' page.
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function confidentiality(): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$staticPageModel = StaticPage::query()->where('type', StaticPageType::confidentiality)->first();
|
||||
|
||||
return view('fo.pages.confidentiality', compact(
|
||||
'staticPageModel',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the 'we_listen' page.
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function listen(): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$staticPageModel = StaticPage::query()->where('type', StaticPageType::we_listen)->first();
|
||||
|
||||
return view('fo.pages.listen', compact(
|
||||
'staticPageModel',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send listen form data.
|
||||
*
|
||||
* @param \App\Http\Requests\Fo\ListenFormRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function listenForm(ListenFormRequest $request): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
Mail::to(config('mail.contact.' . ObjectEnum::make(intval($request->validated()['object']))->name()))
|
||||
->send(new SendContactMail((object)$request->validated()));
|
||||
Mail::to($request->validated()['email'])->send(new SendConfirmationMail((object)$request->validated()));
|
||||
|
||||
return redirect()->route('fo.listen')
|
||||
->with('success', trans(
|
||||
'Bonjour, votre message a bien été transmis, nous vous en remercions. Cordialement, l’équipe :appName.',
|
||||
['appName' => config('app.name')]
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
114
app/Http/Requests/Fo/ListenFormRequest.php
Normal file
114
app/Http/Requests/Fo/ListenFormRequest.php
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Fo;
|
||||
|
||||
use App\Enums\Country;
|
||||
use App\Enums\Listen\ObjectEnum;
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
use App\Traits\Requests\HasPicture;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rules\Enum;
|
||||
|
||||
class ListenFormRequest extends FormRequest
|
||||
{
|
||||
use HasPicture;
|
||||
|
||||
/**
|
||||
* Prepare the data for validation.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function prepareForValidation()
|
||||
{
|
||||
$this->merge([
|
||||
'country' => $this->post('country') == null ? $this->post('country') : null,
|
||||
'accept_rules' => $this->boolean('accept_rules'),
|
||||
'send_data' => $this->boolean('send_data'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
ToolboxHelper::validateRecaptcha($this, \config('services.google.recaptcha.version'));
|
||||
$rules = [
|
||||
'first_name' => 'present|nullable|string|between:3,100',
|
||||
'last_name' => 'required|string|between:3,100',
|
||||
'society' => 'present|nullable|string|between:3,255',
|
||||
'email' => 'required|email:rfc,strict,dns,spoof,filter|max:255',
|
||||
'phone' => 'present|nullable|phone:FR|max:25',
|
||||
'postal_code' => 'present|nullable|postal_code:FR|max:25',
|
||||
'city' => 'present|nullable|string|between:3,20',
|
||||
'country' => ['present', 'nullable', new Enum(Country::class)],
|
||||
'address' => 'present|nullable|string|between:3,255',
|
||||
'object' => ['required', new Enum(ObjectEnum::class)],
|
||||
'message' => 'required|min:20|max:35656',
|
||||
'accept_rules' => 'required|boolean',
|
||||
'send_data' => 'required|boolean',
|
||||
];
|
||||
if (
|
||||
isset(request()->file) and
|
||||
(request()->file->getClientMimeType() === "image/jpeg" ||
|
||||
request()->file->getClientMimeType() === "image/png")
|
||||
) {
|
||||
$rules = \array_merge($rules, $this->pictureRules(
|
||||
'file',
|
||||
0,
|
||||
0,
|
||||
1920,
|
||||
1080,
|
||||
true,
|
||||
3000,
|
||||
));
|
||||
} elseif (isset(request()->file) and (request()->file->getClientMimeType() === "application/pdf")) {
|
||||
$rules = \array_merge($rules, [
|
||||
//phpcs:ignore Generic.Files.LineLength.TooLong
|
||||
'file' => 'present|nullable|mimes:pdf'
|
||||
]);
|
||||
} elseif (
|
||||
isset(request()->file) and
|
||||
(request()->file->getClientMimeType() !== "application/pdf") and
|
||||
(request()->file->getClientMimeType() !== "image/jpeg") and
|
||||
(request()->file->getClientMimeType() !== "image/png")
|
||||
) {
|
||||
$rules = \array_merge($rules, [
|
||||
'file' => [
|
||||
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
|
||||
function ($attribute, $value, $fail) {
|
||||
$fail(\trans('Le format du fichier doit être .jpg, .png ou .pdf'));
|
||||
}
|
||||
],
|
||||
]);
|
||||
} //end if
|
||||
return $rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get custom attributes for validator errors.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function attributes(): array
|
||||
{
|
||||
return [
|
||||
'first_name' => trans('validation.attributes.first_name'),
|
||||
'last_name' => trans('validation.attributes.last_name'),
|
||||
'society' => trans('validation.attributes.society'),
|
||||
'email' => trans('validation.attributes.email'),
|
||||
'phone' => trans('validation.attributes.phone'),
|
||||
'postal_code' => trans('validation.attributes.postal_code'),
|
||||
'city' => trans('validation.attributes.city'),
|
||||
'country' => trans('validation.attributes.country'),
|
||||
'address' => trans('validation.attributes.address'),
|
||||
'object' => trans('validation.attributes.object'),
|
||||
'message' => trans('validation.attributes.message'),
|
||||
'file' => trans('validation.attributes.file'),
|
||||
'accept_rules' => trans('validation.attributes.custom.accept_rules'),
|
||||
'send_data' => trans('validation.attributes.custom.send_data'),
|
||||
];
|
||||
}
|
||||
}
|
||||
115
app/Mail/SendConfirmationMail.php
Normal file
115
app/Mail/SendConfirmationMail.php
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Mail\Markdown;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Blade;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class SendConfirmationMail extends Mailable
|
||||
{
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var \App\Mail\Contact
|
||||
*/
|
||||
private \stdClass $data;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @param \stdClass $data
|
||||
* @return void
|
||||
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
|
||||
*/
|
||||
public function __construct(\stdClass $data)
|
||||
{
|
||||
// @phpstan-ignore-next-line
|
||||
$this->data = clone $data;
|
||||
$this->sanitizeStringInputs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes user message
|
||||
*
|
||||
* ! This is not recursive !
|
||||
* * Prevent xss injection via markdown interpretation.
|
||||
*
|
||||
* La solution devrai etre de filtrer en sortie, mais il n'est pas possible de
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function sanitizeStringInputs(): void
|
||||
{
|
||||
// @phpstan-ignore-next-line
|
||||
$this->data = (object)Arr::map((array)$this->data, function ($el) {
|
||||
if (is_string($el)) {
|
||||
$el = \htmlspecialchars(\strip_tags(Blade::render(
|
||||
(string)Markdown::parse($el)
|
||||
)));
|
||||
$el = Str::of($el)->replaceMatches(
|
||||
'/[^\p{L}0-9\n\s\@\.\:\-\_\?\!\;\(\)\+\-\/\\\=]+/us',
|
||||
''
|
||||
)->trim()->wordWrap(75, "\n", true)->toString();
|
||||
}
|
||||
return $el;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Envelope
|
||||
*/
|
||||
public function envelope(): \Illuminate\Mail\Mailables\Envelope
|
||||
{
|
||||
return new Envelope(
|
||||
subject: sprintf(
|
||||
'%s - %s',
|
||||
trans('Confirmation d\'envoi'),
|
||||
config('app.name')
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Content
|
||||
*/
|
||||
public function content(): \Illuminate\Mail\Mailables\Content
|
||||
{
|
||||
return new Content(
|
||||
markdown: 'emails.send-confirmation-form',
|
||||
with: ['data' => $this->data],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @property \App\Enums\Contact\ObjectEnum $type
|
||||
* @property string|null $first_name
|
||||
* @property string $last_name
|
||||
* @property string|null $phone
|
||||
* @property string $email
|
||||
* @property string|null $address
|
||||
* @property string|null $city
|
||||
* @property string|null $postal_code
|
||||
* @property string $message
|
||||
* @property boolean $terms
|
||||
* @property \Illuminate\Http\UploadedFile|null $file
|
||||
* @property \App\Models\Product|null $product
|
||||
* @property \Carbon\Carbon|null $expiration_date
|
||||
* @property integer|null $batch_number
|
||||
* @phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses
|
||||
*/
|
||||
class ContactConfirmation extends \stdClass
|
||||
{
|
||||
}
|
||||
133
app/Mail/SendContactMail.php
Normal file
133
app/Mail/SendContactMail.php
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\Enums\Listen\ObjectEnum;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Attachment;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Mail\Markdown;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Blade;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class SendContactMail extends Mailable
|
||||
{
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var \App\Mail\Contact
|
||||
*/
|
||||
private \stdClass $data;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @param \stdClass $data
|
||||
* @return void
|
||||
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
|
||||
*/
|
||||
public function __construct(\stdClass $data)
|
||||
{
|
||||
// @phpstan-ignore-next-line
|
||||
$this->data = clone $data;
|
||||
$this->sanitizeStringInputs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes user message
|
||||
*
|
||||
* ! This is not recursive !
|
||||
* * Prevent xss injection via markdown interpretation.
|
||||
*
|
||||
* La solution devrai etre de filtrer en sortie, mais il n'est pas possible de
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function sanitizeStringInputs(): void
|
||||
{
|
||||
// @phpstan-ignore-next-line
|
||||
$this->data = (object)Arr::map((array)$this->data, function ($el) {
|
||||
if (is_string($el)) {
|
||||
$el = \htmlspecialchars(\strip_tags(Blade::render(
|
||||
(string)Markdown::parse($el)
|
||||
)));
|
||||
$el = Str::of($el)->replaceMatches(
|
||||
'/[^\p{L}0-9\n\s\@\.\:\-\_\?\!\;\(\)\+\-\/\\\=]+/us',
|
||||
''
|
||||
)->trim()->wordWrap(75, "\n", true)->toString();
|
||||
}
|
||||
return $el;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Envelope
|
||||
*/
|
||||
public function envelope(): \Illuminate\Mail\Mailables\Envelope
|
||||
{
|
||||
return new Envelope(
|
||||
subject: sprintf(
|
||||
'%s - %s',
|
||||
ObjectEnum::make($this->data->object)->label(),
|
||||
config('app.name')
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Content
|
||||
*/
|
||||
public function content(): \Illuminate\Mail\Mailables\Content
|
||||
{
|
||||
return new Content(
|
||||
markdown: 'emails.send-contact-form',
|
||||
with: ['data' => $this->data],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attachments for the message.
|
||||
*
|
||||
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
|
||||
*/
|
||||
public function attachments(): array
|
||||
{
|
||||
$attachments = [];
|
||||
if (isset($this->data->file)) {
|
||||
$attachments[] = Attachment::fromPath($this->data->file->getRealPath())
|
||||
->as($this->data->file->getClientOriginalName())
|
||||
->withMime($this->data->file->getClientMimeType());
|
||||
}
|
||||
return $attachments;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @property \App\Enums\Contact\ObjectEnum $type
|
||||
* @property string|null $first_name
|
||||
* @property string $last_name
|
||||
* @property string|null $phone
|
||||
* @property string $email
|
||||
* @property string|null $address
|
||||
* @property string|null $city
|
||||
* @property string|null $postal_code
|
||||
* @property string $message
|
||||
* @property boolean $terms
|
||||
* @property \Illuminate\Http\UploadedFile|null $file
|
||||
* @property \App\Models\Product|null $product
|
||||
* @property \Carbon\Carbon|null $expiration_date
|
||||
* @property integer|null $batch_number
|
||||
* @phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses
|
||||
*/
|
||||
class Contact extends \stdClass
|
||||
{
|
||||
}
|
||||
|
|
@ -12,13 +12,15 @@
|
|||
],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^8.3",
|
||||
"php": "^8.2",
|
||||
"axlon/laravel-postal-code-validation": "^3.5",
|
||||
"diglactic/laravel-breadcrumbs": "^8.0",
|
||||
"guzzlehttp/guzzle": "^7.2",
|
||||
"laravel/framework": "^10.0",
|
||||
"laravel/tinker": "^2.8",
|
||||
"laravel/ui": "^4.2",
|
||||
"mews/purifier": "^3.4",
|
||||
"propaganistas/laravel-phone": "^5.1",
|
||||
"sentry/sentry-laravel": "*",
|
||||
"uwil/k8s-laravel": "^1.2"
|
||||
},
|
||||
|
|
|
|||
658
composer.lock
generated
658
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -118,4 +118,10 @@ return [
|
|||
],
|
||||
],
|
||||
|
||||
'contact' => [
|
||||
'remark' => env('MAIL_CONTACT_REMARK', 'hello@example.com'),
|
||||
'sponsoring' => env('MAIL_CONTACT_SPONSORING', 'hello@example.com'),
|
||||
'service' => env('MAIL_CONTACT_SERVICE', 'hello@example.com'),
|
||||
'other' => env('MAIL_CONTACT_OTHER', 'hello@example.com'),
|
||||
]
|
||||
];
|
||||
|
|
|
|||
|
|
@ -31,4 +31,15 @@ return [
|
|||
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
||||
],
|
||||
|
||||
'google' => [
|
||||
'recaptcha' => [
|
||||
'public' => env('GOOGLE_RECAPTCHA_PUBLIC'),
|
||||
'private' => env('GOOGLE_RECAPTCHA_PRIVATE'),
|
||||
'version' => env('GOOGLE_RECAPTCHA_VERSION', "3") === "3" ? true : false
|
||||
]
|
||||
],
|
||||
|
||||
'matomo' => [
|
||||
'site_id' => env('MATOMO_SITE_ID')
|
||||
]
|
||||
];
|
||||
|
|
|
|||
|
|
@ -18,19 +18,6 @@ class StaticPageSeeder extends Seeder
|
|||
{
|
||||
try {
|
||||
StaticPage::unsetEventDispatcher();
|
||||
StaticPage::query()->updateOrCreate(
|
||||
[
|
||||
'type' => StaticPageType::contact,
|
||||
],
|
||||
[
|
||||
'seo_title' => 'Seo title pour la page contactez nous',
|
||||
'seo_description' => 'Seo description pour la page contactez nous',
|
||||
'title' => 'Contactez-nous',
|
||||
'slug' => Str::slug('Contactez-nous'),
|
||||
'type' => StaticPageType::contact,
|
||||
'content' => \clean(\fake()->randomHtml(6, 7)),
|
||||
]
|
||||
);
|
||||
StaticPage::query()->updateOrCreate(
|
||||
[
|
||||
'type' => StaticPageType::legals,
|
||||
|
|
|
|||
4
resources/assets/images/others/joindre-fichier.svg
Normal file
4
resources/assets/images/others/joindre-fichier.svg
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="11" height="12" viewBox="0 0 11 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0.836914" y="12" width="1.2435" height="9.32623" rx="0.621749" transform="rotate(-90 0.836914 12)" fill="#103251"/>
|
||||
<path d="M6.12167 9.13476L6.12167 2.18982L9.1558 5.22396C9.39828 5.46644 9.7962 5.46644 10.0387 5.22396C10.2812 4.98148 10.2812 4.58977 10.0387 4.34729L5.94136 0.249969C5.8252 0.133545 5.66749 0.0681161 5.50303 0.0681161C5.33857 0.068116 5.18086 0.133544 5.0647 0.249968L0.961158 4.34107C0.718676 4.58356 0.718676 4.97526 0.961157 5.21774C1.20364 5.46022 1.59534 5.46022 1.83782 5.21774L4.87817 2.18982L4.87817 9.13475C4.87817 9.47672 5.15796 9.7565 5.49992 9.7565C5.84188 9.7565 6.12167 9.47672 6.12167 9.13476Z" fill="#103251"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 759 B |
|
|
@ -217,7 +217,13 @@ return [
|
|||
'updated_at' => 'mis à jour à',
|
||||
'username' => 'nom d\'utilisateur',
|
||||
'year' => 'année',
|
||||
'custom' => [
|
||||
'accept_rules' => 'acceptation du traitement des données',
|
||||
'send_data' => 'acceptation de la politique de confidentialité'
|
||||
]
|
||||
],
|
||||
'youtube_id' => ':attribute doit être un ID de vidéo Youtube valide',
|
||||
'vimeo_id' => ':attribute doit être un ID de vidéo Vimeo valide',
|
||||
'custom' => [
|
||||
'of_the' => [
|
||||
'male' => 'du ',
|
||||
|
|
@ -283,5 +289,8 @@ return [
|
|||
optimal dans les moteurs de recherche (balise <title>).',
|
||||
'seo_description' => 'Doit décrire précisément le contenu de la page (balise <meta> description).',
|
||||
'required_fields' => '* Champs obligatoires',
|
||||
'society' => 'entreprise',
|
||||
'object' => 'objet',
|
||||
'message' => 'message',
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -20,4 +20,5 @@
|
|||
@import "./pages/homepage";
|
||||
@import "./pages/unveil";
|
||||
@import "./pages/site";
|
||||
@import "./pages/contact";
|
||||
|
||||
|
|
|
|||
80
resources/sass/fo/pages/_contact.scss
Normal file
80
resources/sass/fo/pages/_contact.scss
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
#listen {
|
||||
.btn-outline-primary {
|
||||
text-transform: initial;
|
||||
}
|
||||
|
||||
#wrapper-listen-form {
|
||||
@include media-breakpoint-up(md) {
|
||||
background-color: rgb(var(--bs-eight-rgb));
|
||||
}
|
||||
}
|
||||
|
||||
#listen-form {
|
||||
@include media-breakpoint-up(md) {
|
||||
background-color: rgb(var(--bs-seven-rgb));
|
||||
}
|
||||
|
||||
.form-control {
|
||||
@include media-breakpoint-up(md) {
|
||||
/* stylelint-disable-next-line color-function-notation */
|
||||
box-shadow: inset 0 -1px rgba(var(--bs-tertiary-rgb), 60%);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
@include media-breakpoint-up(md) {
|
||||
/* stylelint-disable-next-line color-function-notation */
|
||||
box-shadow: inset 0 -1px rgba(var(--bs-tertiary-rgb), 100%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* stylelint-disable-next-line selector-no-qualifying-type */
|
||||
.form-floating > input.form-control, select {
|
||||
height: 56px;
|
||||
}
|
||||
|
||||
/* stylelint-disable-next-line selector-no-qualifying-type */
|
||||
.form-floating > input.form-control:focus ~ label::after,
|
||||
.form-floating > input.form-control:not(:placeholder-shown) ~ label::after {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
.listen-message {
|
||||
@include media-breakpoint-up(md) {
|
||||
background-color: rgb(var(--bs-white-rgb));
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(xl) {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#contact-file-icon {
|
||||
display: block;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
background-image: url("@/images/others/joindre-fichier.svg");
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ck-content p {
|
||||
@include media-breakpoint-up(xl) {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.badge-logo {
|
||||
width: 6rem;
|
||||
height: 6rem;
|
||||
background-image: url("@/images/footer/volena-logo.svg");
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 80%;
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,8 @@ $tertiary: $color-tertiary;
|
|||
$quad: $color-quad;
|
||||
$quint: $color-quint;
|
||||
$sixt: $color-sixt;
|
||||
$seven: $color-seven;
|
||||
$eight: $color-eight;
|
||||
$success: $color-success;
|
||||
$info: $color-info;
|
||||
$warning: $color-warning;
|
||||
|
|
@ -33,6 +35,8 @@ $custom-theme-colors: map.merge($theme-colors,
|
|||
'quad': $quad,
|
||||
'quint': $quint,
|
||||
'sixt': $sixt,
|
||||
'seven': $seven,
|
||||
'eight': $eight,
|
||||
));
|
||||
$theme-colors: map.merge($theme-colors, $custom-theme-colors);
|
||||
$theme-colors-rgb: map-loop($theme-colors, to-rgb, '$value');
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ $color-tertiary: #23628a;
|
|||
$color-quad: #d36738;
|
||||
$color-quint: #4c764b;
|
||||
$color-sixt: #b94c73;
|
||||
$color-seven: #C3DFE9;
|
||||
$color-eight: #EDF9FD;
|
||||
|
||||
// * BACKGROUNDS COLORS
|
||||
$bg-body: $color-white;
|
||||
|
|
|
|||
4
resources/sass/fo/vendor/_cookie-notice.scss
vendored
4
resources/sass/fo/vendor/_cookie-notice.scss
vendored
|
|
@ -1 +1,5 @@
|
|||
$ck-background-color: $bg-body;
|
||||
$ck-btn-background-color: $bg-body;
|
||||
$ck-title-font: $font-default-family-base;
|
||||
|
||||
@import "@ldc-web/cookie-notice";
|
||||
|
|
|
|||
14
resources/views/emails/send-confirmation-form.blade.php
Normal file
14
resources/views/emails/send-confirmation-form.blade.php
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{{-- blade-formatter-disable --}}
|
||||
@component('mail::message')
|
||||
# {{ __('Bonjour,') }}
|
||||
|
||||
{{ __('Nous avons bien reçu votre demande.') }}
|
||||
|
||||
{{ __('Nous vous remercions de l\'attention que vous nous portez.') }}
|
||||
|
||||
{{ __('Nous vous répondrons dans les meilleurs délais.') }}
|
||||
|
||||
{{ __('Cordialement,') }}
|
||||
|
||||
{{ __('L\'équipe :appName.', ['appName' => config('app.name')]) }}
|
||||
@endcomponent
|
||||
35
resources/views/emails/send-contact-form.blade.php
Normal file
35
resources/views/emails/send-contact-form.blade.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
{{-- blade-formatter-disable --}}
|
||||
@component('mail::message')
|
||||
# {{ __('Message contact :') }}
|
||||
|
||||
{{ __('Voici un message envoyé depuis :siteName :', ['siteName' => config('app.name')]) }}
|
||||
|
||||
{{ __('Expéditeur :') }} @if ($data->first_name) __{{ $data->first_name }}__ @endif __{{ $data->last_name }}__
|
||||
|
||||
{{ __('E-mail :') }} __{{ $data->email }}__
|
||||
|
||||
@if ($data->phone)
|
||||
{{ __('Téléphone :') }} __{{ $data->phone }}__
|
||||
@endif
|
||||
|
||||
@if ($data->address)
|
||||
{{ __('Adresse :') }} __{{ $data->address }}__
|
||||
@endif
|
||||
|
||||
@if ($data->city)
|
||||
{{ __('Ville :') }} __{{ $data->city }}__
|
||||
@endif
|
||||
|
||||
@if ($data->postal_code)
|
||||
{{ __('Code postal :') }} __{{ $data->postal_code }}__
|
||||
@endif
|
||||
|
||||
{{ __('Message :') }}
|
||||
@component('mail::panel')
|
||||
```
|
||||
{{ $data->message }}
|
||||
```
|
||||
@endcomponent
|
||||
|
||||
{{ config('app.name') }}.
|
||||
@endcomponent
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
<main class="@yield('bg-color') pt-2">
|
||||
<div class="container-fluid">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col col-md-6">
|
||||
<div class="col-12 col-md-10 col-xl-6">
|
||||
@include('modules.flash-messages')
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@
|
|||
</li>
|
||||
<li class="list-inline-item"><span @class($separatorClassList)>{{ $separator }}</span></li>
|
||||
<li class="list-inline-item">
|
||||
<a href="FIXME:#cookier" title="{{ __('Ouvrir le panneau de Gestion des cookies') }}" @class($linkClassList)>
|
||||
<a class="cn-cookie-link link-primary" href="#" title="{{ __('Ouvrir le panneau de Gestion des cookies') }}"
|
||||
@class($linkClassList)>
|
||||
{{ __('Gestion des cookies') }}
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
<div class="col text-center">
|
||||
<span>©{{ __('Voléna') }}</span>
|
||||
<span>-</span>
|
||||
<span>2023</span>
|
||||
<span>{{ date('Y') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row pb-5">
|
||||
|
|
|
|||
|
|
@ -65,8 +65,8 @@
|
|||
</li>
|
||||
<li class="nav-item mb-1">
|
||||
@php $activePage = false; @endphp
|
||||
<a class="nav-link @if ($activePage) active @endif" data-bs-toggle="tooltip" href="#FIXME:route"
|
||||
title="{{ __('Aller sur la page On vous écoute') }}"
|
||||
<a class="nav-link @if ($activePage) active @endif" data-bs-toggle="tooltip"
|
||||
href="{{ route('fo.listen') }}" title="{{ __('Aller sur la page On vous écoute') }}"
|
||||
@if ($activePage) aria-current="page" @endif>
|
||||
{{ __('On vous écoute') }}
|
||||
</a>
|
||||
|
|
|
|||
301
resources/views/fo/pages/listen.blade.php
Normal file
301
resources/views/fo/pages/listen.blade.php
Normal file
|
|
@ -0,0 +1,301 @@
|
|||
@extends('fo.layout')
|
||||
|
||||
@section('title', $staticPageModel->seo_title)
|
||||
@section('description', $staticPageModel->seo_description)
|
||||
@section('breadcrumb', request()->route()->getName())
|
||||
|
||||
@section('banner')
|
||||
@include('fo.layouts.banner', [
|
||||
'h1' => __($staticPageModel->title),
|
||||
'asset' => Vite::asset('resources/assets/images/banners/home_reworked.jpg'),
|
||||
'title' => __('Paysage d\'un champs de blé au soleil couchant avec une lisière en fond de tableau'),
|
||||
'alt' => __('Image de fond'),
|
||||
'displayArrow' => true,
|
||||
])
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<section class="container mb-5" id="listen">
|
||||
<div class="d-none d-lg-block my-5 p-5 text-center">
|
||||
<a class="btn btn-outline-primary rounded-pill border-primary border shadow-none"
|
||||
href="#FIXME: url page 'on embauche' section 'on se retrouve'">
|
||||
{{ __('Je suis candidat') }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="rounded-5 p-md-4" id="wrapper-listen-form">
|
||||
<div class="row m-md-0 p-md-4 my-5 py-5">
|
||||
<div class="col-12 col-lg-4 text-lg-start text-center">
|
||||
<h2 class="h2 fw-bold text-primary m-0">{{ $staticPageModel->title }}</h2>
|
||||
</div>
|
||||
<div class="d-lg-none col-12 text-center">
|
||||
<a class="btn btn-outline-primary rounded-pill border-primary text-lowercase my-3 border shadow-none"
|
||||
href="#FIXME: url page 'on embauche' section 'on se retrouve'">
|
||||
{{ __('Je suis candidat') }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-12 col-lg-6 text-lg-start d-lg-flex align-items-end justify-content-center text-center">
|
||||
@if ($staticPageModel->content)
|
||||
<div class="ck-content text-primary">
|
||||
{!! clean($staticPageModel->content) !!}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-12 col-lg-2 d-none d-lg-flex justify-content-center align-items-center">
|
||||
<div class="badge-logo bg-primary rounded-pill"></div>
|
||||
</div>
|
||||
</div>
|
||||
<form class="rounded-4 p-md-3 p-xl-5 p-0" id="listen-form" method="POST" action="{{ route('fo.listen.send') }}"
|
||||
enctype="multipart/form-data">
|
||||
@method('POST')
|
||||
@csrf
|
||||
<div class="position-relative row w-100 gx-0 gx-md-4 mx-auto">
|
||||
<div class="col-12 col-md-6 col-xl-4">
|
||||
<div class="row">
|
||||
<fieldset class="col-12 form-floating mb-3" inert="true">
|
||||
<input class="form-control bg-transparent" id="contactSociety" name="society" type="text"
|
||||
value="{{ old('society') }}" placeholder="{{ Str::of(__('validation.custom.society'))->ucFirst() }}">
|
||||
<label for="contactSociety">{{ Str::of(__('validation.custom.society'))->ucFirst() }}</label>
|
||||
@foreach ($errors->get('society') as $message)
|
||||
<div class="invalid-feedback d-block">{{ $message }}</div>
|
||||
@endforeach
|
||||
</fieldset>
|
||||
<fieldset class="col-12 form-floating mb-3" inert="true">
|
||||
<input class="form-control bg-transparent" id="contactFirstname" name="first_name" type="text"
|
||||
value="{{ old('first_name') }}"
|
||||
placeholder="{{ Str::of(__('validation.attributes.first_name'))->ucFirst() }}">
|
||||
<label for="contactFirstname">{{ Str::of(__('validation.attributes.first_name'))->ucFirst() }}</label>
|
||||
@foreach ($errors->get('first_name') as $message)
|
||||
<div class="invalid-feedback d-block">{{ $message }}</div>
|
||||
@endforeach
|
||||
</fieldset>
|
||||
<fieldset class="col-12 form-floating mb-3" inert="true">
|
||||
<input class="form-control bg-transparent" id="contactLastname" name="last_name" type="text"
|
||||
value="{{ old('last_name') }}"
|
||||
placeholder="{{ Str::of(__('validation.attributes.last_name'))->ucFirst() }}" required>
|
||||
<label for="contactLastname">{{ Str::of(__('validation.attributes.last_name'))->ucFirst() }}*</label>
|
||||
@foreach ($errors->get('last_name') as $message)
|
||||
<div class="invalid-feedback d-block">{{ $message }}</div>
|
||||
@endforeach
|
||||
</fieldset>
|
||||
<fieldset class="col-12 form-floating mb-3" inert="true">
|
||||
<input class="form-control bg-transparent" id="contactEmail" name="email" type="text"
|
||||
value="{{ old('email') }}" required
|
||||
placeholder="{{ Str::of(__('validation.attributes.email'))->ucFirst() }}">
|
||||
<label for="contactEmail">{{ Str::of(__('validation.attributes.email'))->ucFirst() }}*</label>
|
||||
@foreach ($errors->get('email') as $message)
|
||||
<div class="invalid-feedback d-block">{{ $message }}</div>
|
||||
@endforeach
|
||||
</fieldset>
|
||||
<fieldset class="col-12 form-floating mb-3" inert="true">
|
||||
<input class="form-control bg-transparent" id="contactPhone" name="phone" type="number"
|
||||
value="{{ old('phone') }}" placeholder="{{ Str::of(__('validation.attributes.phone'))->ucFirst() }}">
|
||||
<label for="contactPhone">{{ Str::of(__('validation.attributes.phone'))->ucFirst() }}</label>
|
||||
@foreach ($errors->get('phone') as $message)
|
||||
<div class="invalid-feedback d-block">{{ $message }}</div>
|
||||
@endforeach
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 col-xl-4">
|
||||
<div class="row">
|
||||
<fieldset class="col-12" inert="true">
|
||||
<div class="row">
|
||||
<div class="col-6 col-md-12 form-floating mb-3">
|
||||
<input class="form-control bg-transparent" id="contactPostalcode" name="postal_code" type="number"
|
||||
value="{{ old('postal_code') }}"
|
||||
placeholder="{{ Str::of(__('validation.attributes.postal_code'))->ucFirst() }}">
|
||||
<label
|
||||
for="contactPostalcode">{{ Str::of(__('validation.attributes.postal_code'))->ucFirst() }}</label>
|
||||
@foreach ($errors->get('postal_code') as $message)
|
||||
<div class="invalid-feedback d-block">{{ $message }}</div>
|
||||
@endforeach
|
||||
</div>
|
||||
<div class="col-6 col-md-12 form-floating mb-3">
|
||||
<input class="form-control bg-transparent" id="contactCity" name="city" type="text"
|
||||
value="{{ old('city') }}"
|
||||
placeholder="{{ Str::of(__('validation.attributes.city'))->ucFirst() }}">
|
||||
<label for="contactCity">{{ Str::of(__('validation.attributes.city'))->ucFirst()->value() }}</label>
|
||||
@foreach ($errors->get('city') as $message)
|
||||
<div class="invalid-feedback d-block">{{ $message }}</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="col-12 mb-3" inert="true">
|
||||
<select class="form-control bg-transparent px-2" id="contactCountry" name="country">
|
||||
<option value="null" selected>
|
||||
{{ __('Sélectionner un :entity', ['entity' => __('validation.attributes.country')]) }}
|
||||
</option>
|
||||
@foreach (\App\Enums\Country::validShippingCountries() as $key => $country)
|
||||
<option class="my-2" value="{{ $country->value() }}"
|
||||
@if (old('country') == $country->value()) selected @endif>
|
||||
{{ \App\Enums\Country::make($country->value)->label() }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@foreach ($errors->get('country') as $message)
|
||||
<div class="invalid-feedback d-block">{{ $message }}</div>
|
||||
@endforeach
|
||||
</fieldset>
|
||||
<fieldset class="col-12 form-floating mb-3" inert="true">
|
||||
<input class="form-control bg-transparent" id="contactAddress" name="address" type="text"
|
||||
value="{{ old('address') }}"
|
||||
placeholder="{{ Str::of(__('validation.attributes.address'))->ucFirst() }}">
|
||||
<label for="contactAddress">{{ Str::of(__('validation.attributes.address'))->ucFirst() }}</label>
|
||||
@foreach ($errors->get('address') as $message)
|
||||
<div class="invalid-feedback d-block">{{ $message }}</div>
|
||||
@endforeach
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
<fieldset class="col-12 col-xl-4 listen-message rounded-4 p-md-4 d-flex justify-content-center align-items-center p-0">
|
||||
<div class="row">
|
||||
<div class="col-12 form-floating mb-3" inert="true">
|
||||
<select class="form-control bg-transparent px-2" id="contactObject" name="object">
|
||||
<option value="null" selected>
|
||||
{{ __('Sélectionner un :entity de mail*', ['entity' => __('validation.custom.object')]) }}
|
||||
</option>
|
||||
<option value="0">{{ __('Recutement') }}</option>
|
||||
@foreach (\App\Enums\Listen\ObjectEnum::toArray() as $key => $object)
|
||||
<option class="my-2" value="{{ $object->value }}"
|
||||
@if (old('object') == $object->value) selected @endif>
|
||||
{{ $object->label }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@push('scripts')
|
||||
<script nonce="{{ $nonce }}">
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const selectObject = document.getElementById('contactObject')
|
||||
selectObject.addEventListener('change', (event) => {
|
||||
if (selectObject.value == 0) {
|
||||
window.open('https://www.odwebp.svc.ms/embed?smkt=fr-fr', '_blank');
|
||||
selectObject.value = null;
|
||||
}
|
||||
})
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@foreach ($errors->get('object') as $message)
|
||||
<div class="invalid-feedback d-block">{{ $message }}</div>
|
||||
@endforeach
|
||||
</div>
|
||||
<div class="col-12 form-floating mb-3" inert="true">
|
||||
<textarea class="form-control bg-transparent" id="contactMessage" name="message" rows="6" placeholder="Leave a comment here"
|
||||
required>{{ old('message') }}</textarea>
|
||||
<label class="ms-2" for="contactMessage">
|
||||
{{ Str::of(__('validation.custom.message'))->ucFirst()->value() }}*
|
||||
</label>
|
||||
@foreach ($errors->get('message') as $message)
|
||||
<div class="invalid-feedback d-block">{{ $message }}</div>
|
||||
@endforeach
|
||||
</div>
|
||||
<div class="col-12 mb-1">
|
||||
<label class="btn btn-light w-100 test d-flex justify-content-between text-start shadow-none"
|
||||
for="contact-file">
|
||||
{{ Str::of(__('joindre un fichier'))->ucFirst()->value() }}*
|
||||
<span id="contact-file-icon"></span>
|
||||
</label>
|
||||
<input class="d-none" id="contact-file" name="file" type="file" value="{{ old('file') }}"
|
||||
role="button" accept=".jpg,.jpeg,.png,.pdf">
|
||||
@foreach ($errors->get('file') as $message)
|
||||
<div class="invalid-feedback d-block">{{ $message }}</div>
|
||||
@endforeach
|
||||
</div>
|
||||
<div class="col-12 pe-md-5 m-xl-0 mb-2">
|
||||
<span class="text-body-secondary">
|
||||
{{ Str::of(__('formats acceptés: jpg,jpeg,png,pdf'))->ucFirst()->value() }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
{{-- Don't remove next empty div, use for placement --}}
|
||||
<div class="d-none d-lg-block col-12 col-xl-4 visibility-hidden"></div>
|
||||
<div class="col-12 col-xl-4 py-xl-0 py-4">
|
||||
<div class="row">
|
||||
<fieldset class="col-12 d-flex justify-content-start align-items-start align-items-md-center mb-1 flex-row"
|
||||
inert="true">
|
||||
<input class="form-check-input mt-2 p-2" id="accept_rules" name="accept_rules" type="checkbox"
|
||||
role="button" @if (old('accept_rules')) checked @endif required>
|
||||
<label class="ms-2 mt-1" for="accept_rules" role="button">
|
||||
{!! nl2br(
|
||||
__('J’autorise :appName à traiter mes données personnelles conformément à la :startAPolitique de confidentialité:endA.', [
|
||||
'appName' => config('app.name'),
|
||||
'startA' => '<a href="' . route('fo.confidentiality') . '">',
|
||||
'startA' => '<a href="' . route('fo.confidentiality') . '">',
|
||||
'endA' => '</a>',
|
||||
]),
|
||||
) !!}
|
||||
</label>
|
||||
@foreach ($errors->get('accept_rules') as $message)
|
||||
<div class="invalid-feedback d-block">{{ $message }}</div>
|
||||
@endforeach
|
||||
</fieldset>
|
||||
<fieldset class="col-12 d-flex justify-content-start align-items-start align-items-md-center mb-1 flex-row"
|
||||
inert="true">
|
||||
<input class="form-check-input mt-2 p-2" id="send_data" name="send_data" type="checkbox" role="button"
|
||||
@if (old('send_data')) checked @endif required>
|
||||
<label class="ms-2 mt-1" for="send_data" role="button">
|
||||
{!! nl2br(
|
||||
__('J\'ai lu et j\'accepte la politique de confidentialité de ce site: :startA Voir nos mentions légales et CGU:endA.', [
|
||||
'startA' => '<a href="' . route('fo.legals') . '">',
|
||||
'endA' => '</a>',
|
||||
]),
|
||||
) !!}
|
||||
</label>
|
||||
@foreach ($errors->get('send_data') as $message)
|
||||
<div class="invalid-feedback d-block">{{ $message }}</div>
|
||||
@endforeach
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-xl-4">
|
||||
<a class="cn-cookie-link" id="recaptcha-warning" href="" rel="nofollow">
|
||||
<strong class="text-underline text-bold text-normal text-danger">
|
||||
{{ __('cookie-notice.custom.recaptcha.warning') }}
|
||||
</strong>
|
||||
</a>
|
||||
<div class="d-flex flex-column justify-content-center align-items-center">
|
||||
<div id="r_captcha"></div>
|
||||
@if ($errors->has('g-recaptcha-response'))
|
||||
<div class="mb-6">
|
||||
<span class="text-danger">{{ $errors->first('g-recaptcha-response') }}</span>
|
||||
</div>
|
||||
@endif
|
||||
<p>{{ __('*Champ obligatoire') }}</p>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<button class="g-recaptcha btn btn-primary rounded-pill text-capitalize"
|
||||
data-sitekey="{{ config('services.google.recaptcha.public') }}" type="submit"
|
||||
inert="true">{{ Str::ucfirst(__('Envoyer')) }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script nonce="{{ $nonce }}">
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
window.__CN_Recaptcha = function() {
|
||||
(function(d, t) {
|
||||
let g = d.createElement(t),
|
||||
s = d.getElementsByTagName(t)[0];
|
||||
g.src = 'https://www.google.com/recaptcha/api.js?render=explicit&onload=__CN_Recaptcha_Loaded';
|
||||
s.parentNode.insertBefore(g, s)
|
||||
}(document, 'script'));
|
||||
};
|
||||
window.__CN_Recaptcha_Loaded = function() {
|
||||
grecaptcha.render('r_captcha', {
|
||||
'sitekey': '{{ config('services.google.recaptcha.public') }}'
|
||||
});
|
||||
document.getElementById('recaptcha-warning').remove();
|
||||
document.getElementById('listen-form').querySelectorAll('[inert="true"]').forEach(element => {
|
||||
element.inert = false;
|
||||
});
|
||||
};
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
2
resources/views/vendor/cn-cookies.blade.php
vendored
2
resources/views/vendor/cn-cookies.blade.php
vendored
|
|
@ -2,7 +2,7 @@
|
|||
@php
|
||||
|
||||
$site_name = Str::ucfirst(config('app.name'));
|
||||
$logo_picture_url = Vite::asset('resources/assets/images/logo.png');
|
||||
$logo_picture_url = Vite::asset('resources/assets/images/header/volena-logo.svg');
|
||||
$logo_title_text = __('Logo du site :name', ['name' => $site_name]);
|
||||
$logo_alt_text = __('Logo :name', ['name' => $site_name]);
|
||||
|
||||
|
|
|
|||
|
|
@ -5,15 +5,15 @@
|
|||
<title>{{ $strings->picture_cookie_title }}</title>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M14.0001 2.93383C14.0001 4.16622 14.6159 5.25477 15.5567 5.90849C15.3526 6.46423 15.2412 7.06473 15.2412 7.69126C15.2412 10.5472 17.5564 12.8624 20.4123 12.8624C21.0807 12.8624 21.7195 12.7356 22.3059 12.5047C22.9456 13.527 24.0817 14.2069 25.3766 14.2069C26.1872 14.2069 26.9357 13.9404 27.539 13.4903C27.5453 13.6594 27.5484 13.8294 27.5484 14C27.5484 21.4826 21.4826 27.5484 14 27.5484C6.51748 27.5484 0.45166 21.4826 0.45166 14C0.45166 6.51748 6.51748 0.45166 14 0.45166C14.3209 0.45166 14.6391 0.462811 14.9543 0.484747C14.3618 1.12929 14.0001 1.98931 14.0001 2.93383ZM21.2176 2.53212C21.2195 2.54914 21.2213 2.56619 21.2229 2.58328C21.2569 2.58864 21.2909 2.59433 21.3247 2.60035C21.2891 2.57745 21.2534 2.5547 21.2176 2.53212ZM25.5171 6.86104C25.523 6.89745 25.5285 6.93399 25.5336 6.97066C25.5512 6.97141 25.5687 6.97228 25.5861 6.97328C25.5633 6.93574 25.5403 6.89833 25.5171 6.86104ZM12.5247 2.09283C12.4748 2.38291 12.4487 2.68118 12.4487 2.98553C12.4487 4.33316 12.9591 5.56158 13.7972 6.48802C13.7266 6.87842 13.6898 7.28054 13.6898 7.69126C13.6898 11.404 16.6996 14.4137 20.4123 14.4137C20.8725 14.4137 21.3219 14.3675 21.7562 14.2794C22.689 15.1941 23.9669 15.7582 25.3766 15.7582C25.5439 15.7582 25.7094 15.7503 25.8726 15.7347C25.0321 21.5385 20.0368 25.9971 14.0001 25.9971C7.37431 25.9971 2.00305 20.6258 2.00305 14.0001C2.00305 7.87378 6.59498 2.82 12.5247 2.09283Z"
|
||||
fill="#FF4E4E" />
|
||||
<circle cx="7.58784" cy="12.8624" r="1.96503" fill="#FF4E4E" />
|
||||
<circle cx="8.82887" cy="19.2745" r="1.3445" fill="#FF4E4E" />
|
||||
<circle cx="13.6897" cy="14.5171" r="1.03423" fill="#FF4E4E" />
|
||||
<circle cx="11.4144" cy="7.48439" r="0.930805" fill="#FF4E4E" />
|
||||
<circle cx="17.5164" cy="20.3089" r="1.86161" fill="#FF4E4E" />
|
||||
<circle cx="21.3432" cy="6.7604" r="0.930805" fill="#FF4E4E" />
|
||||
<circle cx="22.1706" cy="1.89958" r="1.44792" fill="#FF4E4E" />
|
||||
<circle cx="26.8245" cy="8.31185" r="0.72396" fill="#FF4E4E" />
|
||||
fill="#0e2b45" />
|
||||
<circle cx="7.58784" cy="12.8624" r="1.96503" fill="#0e2b45" />
|
||||
<circle cx="8.82887" cy="19.2745" r="1.3445" fill="#0e2b45" />
|
||||
<circle cx="13.6897" cy="14.5171" r="1.03423" fill="#0e2b45" />
|
||||
<circle cx="11.4144" cy="7.48439" r="0.930805" fill="#0e2b45" />
|
||||
<circle cx="17.5164" cy="20.3089" r="1.86161" fill="#0e2b45" />
|
||||
<circle cx="21.3432" cy="6.7604" r="0.930805" fill="#0e2b45" />
|
||||
<circle cx="22.1706" cy="1.89958" r="1.44792" fill="#0e2b45" />
|
||||
<circle cx="26.8245" cy="8.31185" r="0.72396" fill="#0e2b45" />
|
||||
</svg>
|
||||
</button>
|
||||
{{-- BANNER --}}
|
||||
|
|
|
|||
|
|
@ -2,11 +2,10 @@
|
|||
<td class="header">
|
||||
<a href="{{ $url }}" style="display: inline-block;">
|
||||
@if (trim($slot) === 'Laravel')
|
||||
<img src="https://laravel.com/img/notification-logo.png" class="logo" alt="Laravel Logo">
|
||||
<img class="logo" src="https://laravel.com/img/notification-logo.png" alt="Laravel Logo">
|
||||
@else
|
||||
{{-- FIXME: Personaliser ca --}}
|
||||
<img src="{{ Vite::asset('resources/assets/images/logo.png') }}" class="logo img-fluid" alt="{{ config('app.name') }}">
|
||||
{{ $slot }}
|
||||
<img class="logo img-fluid" src="{{ Vite::asset('resources/assets/images/header/volena-logo.svg') }}"
|
||||
alt="{{ config('app.name') }}">
|
||||
@endif
|
||||
</a>
|
||||
</td>
|
||||
|
|
|
|||
|
|
@ -13,8 +13,14 @@ Route::middleware(['throttle:credentials'])->name('fo.')->group(function () {
|
|||
|
||||
Route::get('/', [HomeController::class, 'index'])->name('homepage');
|
||||
Route::get('/on-se-devoile', [StaticPageController::class, 'unveil'])->name('unveil');
|
||||
Route::get('/on-sengage', [StaticPageController::class, 'commit'])->name('commit');
|
||||
Route::get('/on-vous-ecoute', [StaticPageController::class, 'listen'])->name('listen');
|
||||
Route::get('/mentions-legales', [StaticPageController::class, 'listen'])->name('legals');
|
||||
Route::get('/charte-de-confidentialite', [StaticPageController::class, 'listen'])->name('confidentiality');
|
||||
Route::get('/sites/{site:slug}', [SiteController::class, 'show'])->name('sites.show');
|
||||
|
||||
Route::post('/on-vous-ecoute-formulaire', [StaticPageController::class, 'listenForm'])->name('listen.send');
|
||||
|
||||
// * Iframe cookies
|
||||
Route::get('/frame/{frame}', function (string $frame) {
|
||||
return view('fo.modules.frame', ['frame' => $frame]);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,9 @@ const purgePlugin = purge({
|
|||
/^cropper-/, /^offcanvas-/, /^tooltip/, /^bs-tooltip/, /^data-popper/, /.*\[data-popper-placement].*/,
|
||||
/^bs-popover/, /^popover/,
|
||||
// Vue
|
||||
/-(leave|enter|appear)(|-(to|from|active))$/, /^(?!(|.*?:)cursor-move).+-move$/, /^router-link(|-exact)-active$/, /data-v-.*/
|
||||
/-(leave|enter|appear)(|-(to|from|active))$/, /^(?!(|.*?:)cursor-move).+-move$/, /^router-link(|-exact)-active$/, /data-v-.*/,
|
||||
// Cookies
|
||||
/^cn-.*/
|
||||
],
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue