fix contact page
This commit is contained in:
parent
87b2ca2368
commit
45ff265caf
21 changed files with 372 additions and 338 deletions
|
|
@ -5,8 +5,8 @@ namespace App\Http\Controllers\Fo;
|
|||
use App\Enums\StaticPageType;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Fo\ContactRequest;
|
||||
use App\Mail\SendContactForm;
|
||||
use App\Models\Explorerpage;
|
||||
use App\Mail\SendContactMail;
|
||||
use App\Models\Homepage;
|
||||
use App\Models\News;
|
||||
use App\Models\Range;
|
||||
|
|
@ -94,7 +94,7 @@ class StaticPageController extends Controller
|
|||
*/
|
||||
public function contactForm(ContactRequest $request): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
Mail::to(\config('mail.from.address'))->send(new SendContactForm($request->validated()));
|
||||
Mail::to(\config('mail.from.address'))->send(new SendContactMail((object)$request->validated()));
|
||||
|
||||
return redirect()->route('fo.contact.show')
|
||||
->with(
|
||||
|
|
|
|||
|
|
@ -90,6 +90,8 @@ class SecureHeaders
|
|||
'https://www.googletagmanager.com',
|
||||
'https://cdnjs.cloudflare.com',
|
||||
"$scheme://www.google-analytics.com",
|
||||
'https://www.google.com/recaptcha/',
|
||||
'https://www.gstatic.com/recaptcha/',
|
||||
// * VITE DEV
|
||||
config('app.debug') ? "https://{$host}:4443" : '',
|
||||
]) . ';'
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace App\Http\Requests\Fo;
|
|||
|
||||
use App\Enums\Contact\CivilityEnum;
|
||||
use App\Enums\Contact\ObjectEnum;
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
use App\Traits\Requests\HasPicture;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rules\Enum;
|
||||
|
|
@ -12,16 +13,6 @@ class ContactRequest extends FormRequest
|
|||
{
|
||||
use HasPicture;
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the data for validation.
|
||||
*
|
||||
|
|
@ -43,6 +34,8 @@ class ContactRequest extends FormRequest
|
|||
*/
|
||||
public function rules()
|
||||
{
|
||||
ToolboxHelper::validateRecaptcha($this, \config('services.google.recaptcha.version'));
|
||||
|
||||
$rules = [
|
||||
'civility' => ['sometimes', 'nullable', new Enum(CivilityEnum::class)],
|
||||
'last_name' => 'sometimes|nullable|string|between:3,255',
|
||||
|
|
@ -53,7 +46,7 @@ class ContactRequest extends FormRequest
|
|||
'address' => 'sometimes|nullable|string|between:3,255',
|
||||
'postal_code' => 'sometimes|nullable|numeric|min:0',
|
||||
'city' => 'sometimes|nullable|string|between:3,255',
|
||||
'object' => ['sometimes', 'nullable', new Enum(ObjectEnum::class)],
|
||||
'object' => ['required', new Enum(ObjectEnum::class)],
|
||||
'product_name' => [
|
||||
'nullable', 'string', 'between:3,255',
|
||||
// @phpcs:ignore Generic.Files.LineLength.TooLong
|
||||
|
|
@ -144,12 +137,21 @@ class ContactRequest extends FormRequest
|
|||
}
|
||||
}
|
||||
],
|
||||
'message' => 'sometimes|nullable|string|between:3,255',
|
||||
'message' => 'required|string|between:3,255',
|
||||
'accept_rules' => 'required|boolean',
|
||||
'send_data' => 'required|boolean',
|
||||
];
|
||||
|
||||
return \array_merge($rules, $this->pictureRules('file', 0, 0, 1920, 1080, true));
|
||||
return \array_merge($rules, $this->pictureRules(
|
||||
'file',
|
||||
0,
|
||||
0,
|
||||
1920,
|
||||
1080,
|
||||
3000,
|
||||
true,
|
||||
'product_name,product_date_limit,product_barcode,product_lot,product_date_consumption,product_location'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,208 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\Enums\Contact\CivilityEnum;
|
||||
use App\Enums\Contact\ObjectEnum;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class SendContactForm extends Mailable
|
||||
{
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* The civility.
|
||||
*
|
||||
* @var \App\Enums\Contact\CivilityEnum|null
|
||||
*/
|
||||
private $civility;
|
||||
|
||||
/**
|
||||
* The first name.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
private $first_name;
|
||||
|
||||
/**
|
||||
* The last name.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
private $last_name;
|
||||
|
||||
/**
|
||||
* The society.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
private $society;
|
||||
|
||||
/**
|
||||
* The email.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $email;
|
||||
|
||||
/**
|
||||
* The phone.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
private $phone;
|
||||
|
||||
/**
|
||||
* The address.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
private $address;
|
||||
|
||||
/**
|
||||
* The postal code.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
private $postal_code;
|
||||
|
||||
/**
|
||||
* The city.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
private $city;
|
||||
|
||||
/**
|
||||
* The object.
|
||||
*
|
||||
* @var \App\Enums\Contact\ObjectEnum|null
|
||||
*/
|
||||
private $object;
|
||||
|
||||
/**
|
||||
* The product name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $product_name;
|
||||
|
||||
/**
|
||||
* The product date limit.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $product_date_limit;
|
||||
|
||||
/**
|
||||
* The product barcode.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $product_barcode;
|
||||
|
||||
/**
|
||||
* The product lot.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $product_lot;
|
||||
|
||||
/**
|
||||
* The product date consumption.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $product_date_consumption;
|
||||
|
||||
/**
|
||||
* The product_location.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $product_location;
|
||||
|
||||
/**
|
||||
* The message.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
private $message;
|
||||
|
||||
/**
|
||||
* The file.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
private $file;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @param array $edition
|
||||
* @return void
|
||||
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
|
||||
*/
|
||||
public function __construct(array $edition)
|
||||
{
|
||||
// phpcs:enable
|
||||
$this->civility = (isset($edition['civility'])) ? CivilityEnum::make(intval($edition['civility']))->label() : null;
|
||||
$this->first_name = $edition['first_name'] ?? null;
|
||||
$this->last_name = $edition['last_name'] ?? null;
|
||||
$this->society = $edition['society'] ?? null;
|
||||
$this->email = $edition['email'];
|
||||
$this->phone = $edition['phone'] ?? null;
|
||||
$this->address = $edition['address'] ?? null;
|
||||
$this->postal_code = $edition['postal_code'] ?? null;
|
||||
$this->city = $edition['city'] ?? null;
|
||||
$this->object = (isset($edition['object'])) ? ObjectEnum::make(intval($edition['object']))->label() : null;
|
||||
$this->product_name = $edition['product_name'];
|
||||
$this->product_date_limit = $edition['product_date_limit'];
|
||||
$this->product_barcode = $edition['product_barcode'];
|
||||
$this->product_lot = $edition['product_lot'];
|
||||
$this->product_date_consumption = $edition['product_date_consumption'];
|
||||
$this->product_location = $edition['product_location'];
|
||||
$this->message = $edition['message'] ?? null;
|
||||
$this->file = $edition['file'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
$mail = $this->subject(\config('app.name') . ' - contact formulaire')
|
||||
->markdown('emails.send-contact-form')
|
||||
->with([
|
||||
'civility' => $this->civility,
|
||||
'first_name' => $this->first_name,
|
||||
'last_name' => $this->last_name,
|
||||
'society' => $this->society,
|
||||
'email' => $this->email,
|
||||
'phone' => $this->phone,
|
||||
'address' => $this->address,
|
||||
'postal_code' => $this->postal_code,
|
||||
'city' => $this->city,
|
||||
'object' => $this->object,
|
||||
'product_name' => $this->product_name,
|
||||
'product_date_limit' => $this->product_date_limit,
|
||||
'product_barcode' => $this->product_barcode,
|
||||
'product_lot' => $this->product_lot,
|
||||
'product_date_consumption' => $this->product_date_consumption,
|
||||
'product_location' => $this->product_location,
|
||||
'message' => $this->message,
|
||||
]);
|
||||
if (isset($this->file)) {
|
||||
$mail = $mail->attach($this->file->getRealPath(), [
|
||||
'as' => $this->file->getClientOriginalName(),
|
||||
'mime' => $this->file->getClientMimeType(),
|
||||
]);
|
||||
}
|
||||
return $mail;
|
||||
}
|
||||
}
|
||||
110
app/Mail/SendContactMail.php
Normal file
110
app/Mail/SendContactMail.php
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\Enums\Contact\ObjectEnum;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Address;
|
||||
use Illuminate\Mail\Mailables\Attachment;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
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)
|
||||
{
|
||||
$this->data = clone $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Envelope
|
||||
*/
|
||||
public function envelope(): \Illuminate\Mail\Mailables\Envelope
|
||||
{
|
||||
return new Envelope(
|
||||
from: new Address(
|
||||
$this->data->email,
|
||||
($this->data->first_name !== null || $this->data->last_name !== null) ?
|
||||
(($this->data->first_name ?? '') . " " . ($this->data->last_name ?? '')) :
|
||||
null
|
||||
),
|
||||
to: [new Address(config('mail.from.address'), config('mail.from.name'))],
|
||||
subject: sprintf('%s - %s', ObjectEnum::make($this->data->object)->label() ?? __('Nouveau message'), 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 integer $civility
|
||||
* @property string $last_name
|
||||
* @property string $first_name
|
||||
* @property string $society
|
||||
* @property string $email
|
||||
* @property string $phone
|
||||
* @property string $address
|
||||
* @property string $postal_code
|
||||
* @property boolean $city
|
||||
* @property integer $object
|
||||
* @property string $message
|
||||
* @property string $product_name
|
||||
* @property string $product_date_limit
|
||||
* @property string $product_barcode
|
||||
* @property string $product_lot
|
||||
* @property string $product_date_consumption
|
||||
* @property string $product_location
|
||||
* @property boolean $accept_rules
|
||||
* @property boolean $send_data
|
||||
* @property \Illuminate\Http\UploadedFile $file
|
||||
* @phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses
|
||||
*/
|
||||
class Contact extends \stdClass
|
||||
{
|
||||
}
|
||||
|
|
@ -26,10 +26,9 @@ class AppServiceProvider extends ServiceProvider
|
|||
App::singleton('clientIp', function () {
|
||||
if (config('app.env') === 'local') {
|
||||
return request()->getClientIp();
|
||||
} else {
|
||||
return request()->server('HTTP_X_FORWARDED_FOR') ??
|
||||
request()->getClientIp();
|
||||
}
|
||||
return request()->server('HTTP_X_FORWARDED_FOR') ??
|
||||
request()->getClientIp();
|
||||
});
|
||||
|
||||
// * LOCAL FORCE eg: for Carbon
|
||||
|
|
|
|||
|
|
@ -45,7 +45,9 @@ trait HasPicture
|
|||
* @param integer|null $minHeight
|
||||
* @param integer|null $maxWith
|
||||
* @param integer|null $maxHeight
|
||||
* @param integer|null $size
|
||||
* @param boolean $nullable
|
||||
* @param string|null $requiredWith
|
||||
* @return array
|
||||
*/
|
||||
public function pictureRules(
|
||||
|
|
@ -54,9 +56,11 @@ trait HasPicture
|
|||
?int $minHeight = null,
|
||||
?int $maxWith = null,
|
||||
?int $maxHeight = null,
|
||||
bool $nullable = false
|
||||
?int $size = null,
|
||||
bool $nullable = false,
|
||||
?string $requiredWith = null,
|
||||
): array {
|
||||
$sizes = (object)[
|
||||
$dimensions = (object)[
|
||||
'minWith' => $minWith ?? $this->minWith,
|
||||
'minHeight' => $minHeight ?? $this->minHeight,
|
||||
'maxWith' => $maxWith ?? $this->maxWith,
|
||||
|
|
@ -65,8 +69,10 @@ trait HasPicture
|
|||
return [
|
||||
$name => [
|
||||
!$nullable ? 'required' : 'nullable',
|
||||
function (string $attribute, $value, callable $fail) use ($sizes) {
|
||||
return ToolboxHelper::validatePicture($attribute, $value, $fail, $sizes);
|
||||
(strlen($requiredWith)) ? 'required_with:' . $requiredWith : '',
|
||||
($size) ? 'max:' . $size : '',
|
||||
function (string $attribute, $value, callable $fail) use ($dimensions) {
|
||||
return ToolboxHelper::validatePicture($attribute, $value, $fail, $dimensions);
|
||||
}
|
||||
]
|
||||
];
|
||||
|
|
|
|||
|
|
@ -31,4 +31,11 @@ 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
|
||||
]
|
||||
],
|
||||
];
|
||||
|
|
|
|||
2
package-lock.json
generated
2
package-lock.json
generated
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "agis",
|
||||
"name": "srcs",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
|
|
|||
BIN
resources/assets/images/global/btn-arrow-dark.png
Normal file
BIN
resources/assets/images/global/btn-arrow-dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 616 B |
9
resources/assets/images/global/checkbox-cross.svg
Normal file
9
resources/assets/images/global/checkbox-cross.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Calque_2" data-name="Calque 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23.38 22.17">
|
||||
<g id="Contact_survol" data-name="Contact / survol">
|
||||
<g>
|
||||
<polygon points="4.85 22.17 1.79 17.14 7.03 11.25 18.42 0 21.76 5.46 4.85 22.17"/>
|
||||
<polygon points="0 5.19 5.52 .62 11.08 6.3 23.38 16.55 18.27 20.4 0 5.19"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 397 B |
12
resources/lang/en/contact.php
Normal file
12
resources/lang/en/contact.php
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
// phpcs:disable Generic.Strings.UnnecessaryStringConcat.Found
|
||||
return [
|
||||
'acceptcgu' => "J’autorise AGIS à traiter mes données personnelles " .
|
||||
"conformément à la :startACharte de confidentialité:endA.",
|
||||
'senddata' => "I authorize AGIS to process my personal data in accordance " .
|
||||
"with the :startA Privacy Policy :endA.",
|
||||
'send' => 'Send'
|
||||
];
|
||||
12
resources/lang/fr/contact.php
Normal file
12
resources/lang/fr/contact.php
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
// phpcs:disable Generic.Strings.UnnecessaryStringConcat.Found
|
||||
return [
|
||||
'acceptcgu' => "J’autorise AGIS à traiter mes données personnelles " .
|
||||
"conformément à la :startACharte de confidentialité:endA.",
|
||||
'senddata' => "J'ai lu et j'accepte la politique de confidentialité " .
|
||||
"de ce site: :startA Voir nos mentions légales:endA.",
|
||||
'send' => 'Envoyer'
|
||||
];
|
||||
|
|
@ -6,6 +6,10 @@ img {
|
|||
max-width: 100%;
|
||||
}
|
||||
|
||||
.form-check-input[type="checkbox"]:checked {
|
||||
#{--bs-form-check-bg-image}: url("@/images/global/checkbox-cross.svg");
|
||||
}
|
||||
|
||||
.bg-agis-yellow {
|
||||
background-image: url('@/images/global/bg-yellow.svg');
|
||||
background-position: center;
|
||||
|
|
|
|||
|
|
@ -18,15 +18,11 @@
|
|||
}
|
||||
|
||||
&.active::after {
|
||||
background: url("@/images/global/btn-arrow-dark.png");
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
transform: rotate(270deg);
|
||||
}
|
||||
}
|
||||
|
||||
&-products-input {
|
||||
display: none;
|
||||
|
||||
&.active {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,35 +1,57 @@
|
|||
document.addEventListener("DOMContentLoaded", function () {
|
||||
// Select after animation
|
||||
const selects = document.querySelectorAll(".contact .select-form") as NodeListOf<HTMLFieldSetElement>;
|
||||
const contactPage = document.querySelector("section.contact");
|
||||
if (contactPage === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
document.body.addEventListener("click", function (event) {
|
||||
const target = event.target as Node | null;
|
||||
selects.forEach(select => {
|
||||
if(select.contains(target)){
|
||||
selectToggleArrowClass(select);
|
||||
// * Return string error.
|
||||
function getErrorString(fieldName: string) {
|
||||
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 {
|
||||
selectRemoveArrowClass(select);
|
||||
select.parentElement!.classList.remove("active");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function selectToggleArrowClass(select: HTMLFieldSetElement) {
|
||||
select.classList.toggle("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;
|
||||
if (contactProductsInput === null) {
|
||||
throw new Error(getErrorString(".contact-products-input"));
|
||||
}
|
||||
|
||||
function selectRemoveArrowClass(select: HTMLFieldSetElement) {
|
||||
select.classList.remove("active");
|
||||
if (selectObject === null) {
|
||||
throw new Error(getErrorString("select[name=\"object\"]"));
|
||||
}
|
||||
|
||||
// Show more input on specific option selected
|
||||
const selectObject = document.getElementsByName("object")[0] as unknown as HTMLSelectElement;
|
||||
selectObject.addEventListener("click", function () {
|
||||
const contactProductsInput = document.querySelector(".contact-products-input") as HTMLDivElement;
|
||||
if (Number(selectObject.value) === 1) {
|
||||
contactProductsInput.classList.remove("d-none");
|
||||
}
|
||||
selectObject.addEventListener("change", () => {
|
||||
if (Number(selectObject.value) === 1) {
|
||||
contactProductsInput.classList.add("active");
|
||||
}
|
||||
else {
|
||||
contactProductsInput.classList.remove("active");
|
||||
contactProductsInput.classList.remove("d-none");
|
||||
} else {
|
||||
contactProductsInput.classList.add("d-none");
|
||||
}
|
||||
});
|
||||
|
||||
// * Get filename.
|
||||
const inputFile = contactPage.querySelector("input[name=\"file\"]") as HTMLSelectElement | null;
|
||||
const renderFileName = contactPage.querySelector("#input-file-name") as HTMLParagraphElement | null;
|
||||
if (inputFile === null) {
|
||||
throw new Error(getErrorString("input[name=\"file\"]"));
|
||||
}
|
||||
if (renderFileName === null) {
|
||||
throw new Error(getErrorString("#input-file-name"));
|
||||
}
|
||||
inputFile.addEventListener("change", function () {
|
||||
renderFileName.textContent = this.value;
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,28 +1,41 @@
|
|||
@component('mail::message')
|
||||
# Bonjour,
|
||||
# Bonjour,
|
||||
|
||||
Voici un message depuis le formulaire de contact du site web {{ config('app.name') }} :
|
||||
## Voici un message envoyé depuis le formulaire de contact du site web {{ config('app.name') }} :
|
||||
|
||||
Information sur l'utilisateur:
|
||||
{{ __('validation.custom.civility') }}: {{ $civility }}
|
||||
{{ __('validation.attributes.first_name') }}: {{ $first_name }}
|
||||
{{ __('validation.attributes.last_name') }}: {{ $last_name }}
|
||||
{{ __('validation.custom.society') }}: {{ $society }}
|
||||
{{ __('validation.attributes.email') }}: {{ $email }}
|
||||
{{ __('validation.attributes.password') }}: {{ $phone }}
|
||||
{{ __('validation.attributes.address') }}: {{ $address }}
|
||||
{{ __('validation.attributes.postal_code') }}: {{ $postal_code }}
|
||||
{{ __('validation.attributes.city') }}: {{ $city }}
|
||||
{{ __('validation.custom.object') }}: {{ $object }}
|
||||
{{ __('validation.attributes.message') }}: {{ $message }}
|
||||
|
||||
Information sur le produit:
|
||||
{{ __('validation.custom.product_name') }}: {{ $product_name }}
|
||||
{{ __('validation.custom.product_date_limit') }}: {{ $product_date_limit }}
|
||||
{{ __('validation.custom.product_barcode') }}: {{ $product_barcode }}
|
||||
{{ __('validation.custom.product_lot') }}: {{ $product_lot }}
|
||||
{{ __('validation.custom.product_date_consumption') }}: {{ $product_date_consumption }}
|
||||
{{ __('validation.custom.product_location') }}: {{ $product_location }}
|
||||
|
||||
{{ config('app.name') }}.
|
||||
### Information sur l'utilisateur:
|
||||
@component('mail::panel')
|
||||
- **{{ __('validation.custom.civility') }}:** {{ \App\Enums\Contact\CivilityEnum::make($data->civility)->label() ?? '' }}
|
||||
- **{{ __('validation.attributes.first_name') }}:** {{ $data->first_name ?? '' }}
|
||||
- **{{ __('validation.attributes.last_name') }}:** {{ $data->last_name ?? '' }}
|
||||
- **{{ __('validation.custom.society') }}:** {{ $data->society ?? '' }}
|
||||
- **{{ __('validation.attributes.email') }}:** {{ $data->email }}
|
||||
- **{{ __('validation.attributes.phone') }}:** {{ $data->phone ?? '' }}
|
||||
- **{{ __('validation.attributes.address') }}:** {{ $data->address ?? '' }}
|
||||
- **{{ __('validation.attributes.postal_code') }}:** {{ $data->postal_code ?? '' }}
|
||||
- **{{ __('validation.attributes.city') }}:** {{ $data->city ?? '' }}
|
||||
- **{{ __('validation.custom.object') }}:** {{ \App\Enums\Contact\ObjectEnum::make($data->object)->label() }}
|
||||
- **{{ __('validation.attributes.message') }}:** {{ $data->message }}
|
||||
@endcomponent
|
||||
|
||||
@if(
|
||||
$data->product_name !== null ||
|
||||
$data->product_date_limit !== null ||
|
||||
$data->product_barcode !== null ||
|
||||
$data->product_lot !== null ||
|
||||
$data->product_date_consumption !== null ||
|
||||
$data->product_location !== null
|
||||
)
|
||||
### Information sur le produit:
|
||||
@component('mail::panel')
|
||||
- **{{ __('validation.custom.product_name') }}:** {{ $data->product_name ?? '' }}
|
||||
- **{{ __('validation.custom.product_date_limit') }}:** {{ $data->product_date_limit ?? '' }}
|
||||
- **{{ __('validation.custom.product_barcode') }}:** {{ $data->product_barcode ?? '' }}
|
||||
- **{{ __('validation.custom.product_lot') }}:** {{ $data->product_lot ?? '' }}
|
||||
- **{{ __('validation.custom.product_date_consumption') }}:** {{ $data->product_date_consumption ?? '' }}
|
||||
- **{{ __('validation.custom.product_location') }}:** {{ $data->product_location ?? '' }}
|
||||
@endcomponent
|
||||
@endif
|
||||
|
||||
L'équipe {{ config('app.name') }}
|
||||
@endcomponent
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form method="POST" action="{{ route('fo.contact.store') }}" enctype="multipart/form-data">
|
||||
<form id="contact-form" method="POST" action="{{ route('fo.contact.store') }}" enctype="multipart/form-data">
|
||||
@method('POST')
|
||||
@csrf
|
||||
<div class="bg-agis-yellow mb-md-5 pb-md-5 m-0 p-0">
|
||||
<div class="bg-agis-yellow mb-md-5 m-0 pb-5">
|
||||
<div class="container">
|
||||
<div class="position-relative px-md-0 mt-5 px-2 py-5">
|
||||
<p
|
||||
|
|
@ -39,7 +39,7 @@
|
|||
<option class="text-capitalize" disabled selected>{{ __('validation.custom.civility') }}</option>
|
||||
@foreach (\App\Enums\Contact\CivilityEnum::toArray() as $key => $enumObject)
|
||||
<option class="text-capitalize" value="{{ $enumObject->value }}"
|
||||
@if (old('civility') == $key) selected @endif>
|
||||
@if (intval(old('civility')) === $enumObject->value) selected @endif>
|
||||
{{ $enumObject->label }}
|
||||
</option>
|
||||
@endforeach
|
||||
|
|
@ -98,11 +98,11 @@
|
|||
<div class="col-12 col-md-6 p-0">
|
||||
<div class="ms-md-5 position-relative pt-md-0 h-100 pt-4">
|
||||
<fieldset class="select-form d-flex flex-column justify-content-end align-items-start h-100">
|
||||
<select class="form-control text-capitalize" name="object" role="button">
|
||||
<select class="form-control text-capitalize" name="object" role="button" required>
|
||||
<option class="text-capitalize" disabled selected>{{ __('validation.custom.object') }}</option>
|
||||
@foreach (\App\Enums\Contact\ObjectEnum::toArray() as $key => $enumObject)
|
||||
<option class="text-capitalize" value="{{ $enumObject->value }}"
|
||||
@if (old('object') === $key) selected @endif>
|
||||
@if (intval(old('object')) === $enumObject->value) selected @endif>
|
||||
{{ $enumObject->label }}
|
||||
</option>
|
||||
@endforeach
|
||||
|
|
@ -110,7 +110,7 @@
|
|||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
<div class="contact-products-input row mx-auto p-0">
|
||||
<div class="contact-products-input row d-none mx-auto p-0">
|
||||
<p class="highlight black m-0 mx-auto my-5 w-fit px-5 text-center text-white">
|
||||
{{ Str::of(__('pour pouvoir vous répondre nous avons besoin de quelques informations :'))->ucFirst()->value() }}
|
||||
</p>
|
||||
|
|
@ -171,15 +171,20 @@
|
|||
<div class="col-12 my-5 p-0">
|
||||
<fieldset class="row">
|
||||
<div class="col-12 col-md-6 pe-md-5">
|
||||
<label class="mt-1" for="file">
|
||||
<p class="mb-0 mt-1">
|
||||
{{ Str::of(__('souhaitez-vous joindre une photo ?'))->ucFirst()->value() }}
|
||||
</label>
|
||||
<span
|
||||
class="text-body-secondary">{{ Str::of(__('formats acceptés : jpg, png'))->ucFirst()->value() }}</span>
|
||||
</p>
|
||||
<span class="text-body-secondary">
|
||||
{{ Str::of(__('formats acceptés : jpg, png'))->ucFirst()->value() }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 ps-md-5">
|
||||
<input class="form-control" id ="file" name="file" type="file"
|
||||
value="{{ old('file') }}" role="button" accept="image/*">
|
||||
<label class="btn btn-primary w-100" for="file">
|
||||
{{ Str::of(__('ajouter un fichier'))->ucFirst()->value() }}
|
||||
</label>
|
||||
<input class="d-none" id ="file" name="file" type="file" value="{{ old('file') }}"
|
||||
role="button" accept="image/*">
|
||||
<p class="m-0" id="input-file-name"></p>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
|
@ -187,9 +192,9 @@
|
|||
<div class="col-12 mb-5 p-0">
|
||||
<fieldset class="d-flex flex-column justify-content-center align-items-start">
|
||||
<label class="mt-1" for="message">
|
||||
{{ Str::of(__('message'))->ucFirst()->value() }} :
|
||||
{{ Str::of(__('message'))->ucFirst()->value() }}* :
|
||||
</label>
|
||||
<textarea class="form-control" id="message" name="message" rows="6">{{ old('message') }}</textarea>
|
||||
<textarea class="form-control" id="message" name="message" rows="6" required>{{ old('message') }}</textarea>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="col-12 mb-1 p-0">
|
||||
|
|
@ -197,8 +202,12 @@
|
|||
<input class="form-check-input rounded-0 mt-2 p-3" id="accept_rules" name="accept_rules" type="checkbox"
|
||||
value="{{ old('accept_rules') }}" role="button" required>
|
||||
<label class="ms-2 mt-1" for="accept_rules" role="button">
|
||||
{{ Str::of(__('j\'ai lu et j\'accepte la politique de confidentialité de ce site.'))->ucFirst()->value() }} :
|
||||
<a href="{{ route('fo.legals.show') }}" target="_blank">{{ __('Voir nos mentions légales') }}</a>
|
||||
{!! nl2br(
|
||||
__('contact.acceptcgu', [
|
||||
'startA' => '<a href="' . route('fo.policies.show') . '">',
|
||||
'endA' => '</a>',
|
||||
]),
|
||||
) !!}
|
||||
</label>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
|
@ -207,19 +216,57 @@
|
|||
<input class="form-check-input rounded-0 mt-2 p-3" id="send_data" name="send_data" type="checkbox"
|
||||
value="{{ old('send_data') }}" role="button" required>
|
||||
<label class="ms-2 mt-1" for="send_data" role="button">
|
||||
{{ Str::of(__('j\'autorise Agis à enregistrer mes données à fin de traiter ma demande'))->ucFirst()->value() }} :
|
||||
{!! nl2br(
|
||||
__('contact.senddata', [
|
||||
'startA' => '<a href="' . route('fo.legals.show') . '">',
|
||||
'endA' => '</a>',
|
||||
]),
|
||||
) !!}
|
||||
</label>
|
||||
</fieldset>
|
||||
</div>
|
||||
<p>{{ __('*Champ obligatoire') }}</p>
|
||||
<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>
|
||||
</div>
|
||||
<button class="btn btn-primary d-none d-md-block w-100 text-capitalize" type="submit">{{ __('envoyer') }}</button>
|
||||
<button class="g-recaptcha btn btn-primary w-100 text-capitalize"
|
||||
data-sitekey="{{ config('services.google.recaptcha.public') }}"
|
||||
type="submit">{{ Str::ucfirst(__('contact.send')) }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-3">
|
||||
<button class="btn btn-primary d-block d-md-none w-100 mb-5 mt-3" type="submit">{{ __('envoyer') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</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('contact-form').inert = false;
|
||||
};
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
|
|
|
|||
56
resources/views/vendor/cn-cookies.blade.php
vendored
56
resources/views/vendor/cn-cookies.blade.php
vendored
|
|
@ -4,40 +4,38 @@
|
|||
$site_name = Str::ucfirst(config('app.name'));
|
||||
$logo_picture_url = Vite::asset('resources/assets/images/layout/logo.svg', 'build');
|
||||
$logo_alt_text = "Logo {$site_name}";
|
||||
// $confidentiality_page_url = route('page.confidentiality');
|
||||
// TODO : Changer qd la page existera
|
||||
$confidentiality_page_url = "#";
|
||||
$confidentiality_page_url = route('fo.policies.show');
|
||||
|
||||
$strings = (object)[
|
||||
'button_customize_cookies' => __('cookie-notice.button_customize_cookies'),
|
||||
'button_forbid' => __('cookie-notice.button_forbid'),
|
||||
'button_allow' => __('cookie-notice.button_allow'),
|
||||
'button_forbid_all' => Str::upper(__('cookie-notice.button_forbid_all')),
|
||||
'button_allow_all' => Str::upper(__('cookie-notice.button_allow_all')),
|
||||
'button_customize' => Str::upper(__('cookie-notice.button_customize')),
|
||||
'button_back' => Str::upper(__('cookie-notice.button_back')),
|
||||
'banner_title' => __('cookie-notice.banner_title', ['site_name' => $site_name]),
|
||||
'banner_text_open' => __('cookie-notice.banner_text_open', ['site_name' => $site_name]),
|
||||
'banner_text' => __('cookie-notice.banner_text'),
|
||||
'banner_details' => __('cookie-notice.banner_details'),
|
||||
'banner_details_link' => __('cookie-notice.banner_details_link'),
|
||||
'button_customize_cookies' => __('cookie-notice.button_customize_cookies'),
|
||||
'button_forbid' => __('cookie-notice.button_forbid'),
|
||||
'button_allow' => __('cookie-notice.button_allow'),
|
||||
'button_forbid_all' => Str::upper(__('cookie-notice.button_forbid_all')),
|
||||
'button_allow_all' => Str::upper(__('cookie-notice.button_allow_all')),
|
||||
'button_customize' => Str::upper(__('cookie-notice.button_customize')),
|
||||
'button_back' => Str::upper(__('cookie-notice.button_back')),
|
||||
'banner_title' => __('cookie-notice.banner_title', ['site_name' => $site_name]),
|
||||
'banner_text_open' => __('cookie-notice.banner_text_open', ['site_name' => $site_name]),
|
||||
'banner_text' => __('cookie-notice.banner_text'),
|
||||
'banner_details' => __('cookie-notice.banner_details'),
|
||||
'banner_details_link' => __('cookie-notice.banner_details_link'),
|
||||
'banner_details_link_title' => __('cookie-notice.banner_details_link_title'),
|
||||
'banner_more_details' => __('cookie-notice.banner_more_details'),
|
||||
'banner_less_details' => __('cookie-notice.banner_less_details'),
|
||||
'Panel_title' => __('cookie-notice.Panel_title'),
|
||||
'Panel_subtitle' => __('cookie-notice.Panel_subtitle'),
|
||||
'Panel_details' => __('cookie-notice.Panel_details'),
|
||||
'banner_more_details' => __('cookie-notice.banner_more_details'),
|
||||
'banner_less_details' => __('cookie-notice.banner_less_details'),
|
||||
'Panel_title' => __('cookie-notice.Panel_title'),
|
||||
'Panel_subtitle' => __('cookie-notice.Panel_subtitle'),
|
||||
'Panel_details' => __('cookie-notice.Panel_details'),
|
||||
];
|
||||
|
||||
$cookies = [];
|
||||
|
||||
// RECAPTCHA
|
||||
$cookies['recaptcha'] = [
|
||||
'name' => __('cookie-notice.custom.recaptcha.title'),
|
||||
'description' => __('cookie-notice.custom.recaptcha.description'),
|
||||
'link' => 'https://policies.google.com/privacy',
|
||||
'labelLink' => __('En savoir +'),
|
||||
'cookies' => ['NID', '__Secure-3PAPISID', '__Secure-3PSID', '__Secure-3PSIDCC']
|
||||
'name' => __('cookie-notice.custom.recaptcha.title'),
|
||||
'description' => __('cookie-notice.custom.recaptcha.description'),
|
||||
'link' => 'https://policies.google.com/privacy',
|
||||
'labelLink' => __('En savoir +'),
|
||||
'cookies' => ['NID', '__Secure-3PAPISID', '__Secure-3PSID', '__Secure-3PSIDCC']
|
||||
];
|
||||
|
||||
$cookies['recaptcha']['script'] = <<<SCRIPT
|
||||
|
|
@ -50,11 +48,11 @@ SCRIPT;
|
|||
|
||||
// MATOMO
|
||||
$cookies['matomo'] = [
|
||||
'name' => __('cookie-notice.custom.matomo.title'),
|
||||
'name' => __('cookie-notice.custom.matomo.title'),
|
||||
'description' => __('cookie-notice.custom.matomo.description'),
|
||||
'link' => 'https://fr.matomo.org/gdpr-analytics/',
|
||||
'labelLink' => __('En savoir +'),
|
||||
'cookies' => ['_pk']
|
||||
'link' => 'https://fr.matomo.org/gdpr-analytics/',
|
||||
'labelLink' => __('En savoir +'),
|
||||
'cookies' => ['_pk']
|
||||
];
|
||||
|
||||
$cookies['matomo']['script'] = <<<SCRIPT
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
@if (trim($slot) === 'Laravel')
|
||||
<img class="logo" src="https://laravel.com/img/notification-logo.png" alt="Laravel Logo">
|
||||
@else
|
||||
<img class="logo img-fluid" src="{{ Vite::asset('resources/assets/images/global/logo.png') }}" alt="{{ config('app.name') }}">
|
||||
<img class="img-fluid" src="{{ Vite::asset('resources/assets/images/global/logo.png') }}" alt="{{ config('app.name') }}">
|
||||
@endif
|
||||
</a>
|
||||
</td>
|
||||
|
|
|
|||
|
|
@ -10,8 +10,11 @@ Route::middleware(['throttle:credentials'])
|
|||
Route::get('/explorateur-et-gastronome', [StaticPageController::class, 'explorer'])->name('explorer');
|
||||
Route::view('/bs-demo', 'fo.pages.bs-demo')->name('bs-demo');
|
||||
|
||||
// * CONTACT
|
||||
Route::get('/contact', [StaticPageController::class, 'contact'])->name('contact.show');
|
||||
Route::post('/contact-form', [StaticPageController::class, 'contactForm'])->name('contact.store');
|
||||
|
||||
// * LEGALS
|
||||
Route::get('/mentions-legales', [StaticPageController::class, 'legals'])->name('legals.show');
|
||||
Route::get('/charte-de-confidentialite', [StaticPageController::class, 'policies'])->name('policies.show');
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue