Merge branch 'trunk'

This commit is contained in:
Jérémy Munsch 2024-04-19 09:27:55 +02:00
commit 0bfbb6d44d
No known key found for this signature in database
GPG key ID: 18361AF3BFEC0FEC
51 changed files with 5636 additions and 12051 deletions

2
.dockerignore Normal file
View file

@ -0,0 +1,2 @@
.git
*.md

View file

@ -31,16 +31,18 @@ MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"
MAIL_LIST_SERVICEWEB=
MAIL_LIST_CONTACTFORM=
ANALYTICS_GOOGLE_ID=
# Matomo
MATOMO_SITE_ID=
# Google Recaptcha
GOOGLE_RECAPTCHA_PUBLIC=
GOOGLE_RECAPTCHA_PRIVATE=
GOOGLE_RECAPTCHA_VERSION=
LDC_WEB_API_KEY="MY_KEY"
LDC_STATUS_CHECKER_API_KEY="MY_KEY"
LDC_STATUS_CHECKER_UUID="UUID_PROJECT"
## LDCWEB ADMIN SECURE
LDC_WEB_API_KEY=
# Sentry
SENTRY_LARAVEL_DSN=

1
.gitignore vendored
View file

@ -14,3 +14,4 @@ npm-debug.log
yarn-error.log
/.idea
auth.json
.npmrc

View file

@ -1,74 +1,23 @@
include:
- project: "ldc-web/shared-ci"
ref: "main"
file: "lint/lint7.3.yml"
- project: "ldc-web/shared-ci"
ref: "main"
file: "security/security7.3.yml"
- project: "ldc-web/shared-ci"
ref: "main"
file: "build/build7.3.yml"
- project: "ldc-web/shared-ci"
ref: "main"
file: "test/test.yml"
- project: "ldc-web/shared-ci"
ref: "main"
file: "deploy/deploy.yml"
stages:
- Security
- CodingStandards
- Builds
composer-security:
stage: Security
image: $CI_REGISTRY/service-web-lab/ldc-web-images-docker/ldcweb-qa:php7.3-1.0
script:
- local-php-security-checker --format=json --path=./composer.lock > composer-security-checker-report.json
artifacts:
when: on_failure
expose_as: 'composer-security-checker'
paths:
- composer-security-checker-report.json
allow_failure: true
needs: []
npm-security:
stage: Security
image: node:17.9.1
before_script:
- npm install --location=global audit-ci@^6
script:
- audit-ci -p npm -o json > npm-security-checker-report.json
artifacts:
when: on_failure
expose_as: 'npm-security-checker'
paths:
- npm-security-checker-report.json
allow_failure: true
needs: []
phpcs:
stage: CodingStandards
image: $CI_REGISTRY/service-web-lab/ldc-web-images-docker/ldcweb-qa:php7.3-1.0
before_script:
- composer config gitlab-token.gitlab.com $CI_DEPLOY_USER $CI_DEPLOY_PASSWORD
- composer install
cache:
paths:
- vendor/
script:
- vendor/bin/phpcs --report=junit --report-file=phpcs-report.xml
artifacts:
when: on_failure
expose_as: 'phpcs'
paths:
- phpcs-report.xml
reports:
junit: phpcs-report.xml
allow_failure: false
needs:
- composer-security
- npm-security
front-build:
stage: Builds
image: node:17.9.1
before_script:
- npm install
cache:
paths:
- node_modules/
script:
- npm run prod > front-build-report.json
artifacts:
when: on_failure
expose_as: 'front-build-report'
paths:
- front-build-report.json
allow_failure: false
needs:
- phpcs
- lint
- security
- build
- test
- deploy

30
.vscode/settings.json vendored
View file

@ -1,21 +1,23 @@
{
"workbench.colorCustomizations": {
"activityBar.activeBackground": "#fccf1d",
"activityBar.activeBackground": "#e2bd2b",
"activityBar.activeBorder": "#222f5c",
"activityBar.background": "#fccf1d",
"activityBar.foreground": "#222f5c",
"activityBar.inactiveForeground": "#222f5c99",
"activityBarBadge.background": "#ff0400",
"activityBarBadge.foreground": "#ffffff",
"sash.hoverBorder": "#fccf1d",
"activityBar.background": "#e2bd2b",
"activityBar.foreground": "#15202b",
"activityBar.inactiveForeground": "#15202b99",
"activityBarBadge.background": "#138c74",
"activityBarBadge.foreground": "#e7e7e7",
"sash.hoverBorder": "#e2bd2b",
"statusBar.background": "#c19f1a",
"statusBar.foreground": "#222f5c",
"statusBarItem.hoverBackground": "#ff0400",
"statusBar.foreground": "#15202b",
"statusBarItem.hoverBackground": "#947a14",
"statusBarItem.remoteBackground": "#c19f1a",
"statusBarItem.remoteForeground": "#222f5c",
"statusBarItem.remoteForeground": "#15202b",
"titleBar.activeBackground": "#c19f1a",
"titleBar.activeForeground": "#222f5c",
"titleBar.inactiveBackground": "#fccf1d99",
"titleBar.inactiveForeground": "#222f5c99"
}
"titleBar.activeForeground": "#15202b",
"titleBar.inactiveBackground": "#c19f1a99",
"titleBar.inactiveForeground": "#15202b99",
"commandCenter.border": "#15202b99"
},
"peacock.remoteColor": "#c19f1a"
}

5
Dockerfile Normal file
View file

@ -0,0 +1,5 @@
FROM registry.s-web.fr/ldc-web/projets/ldc-web-images-docker/ldcweb-production-7.3:latest
COPY --chown=www-data:www-data . /app/srcs
USER root
RUN chmod -R 755 /app/srcs/storage
USER www-data

View file

@ -1,48 +0,0 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Hash;
use App\Models\User;
class AdminCreate extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'admin:create';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Create Admin User';
/**
* Execute the console command.
*
* @return integer
*/
public function handle()
{
$role = 0;
$name = $this->ask('Name ?');
$email = $this->ask('Email ?');
$password = $this->secret('What is the password?');
$user = new User([
'name' => $name,
'email' => $email,
'role' => $role,
'password' => Hash::make($password)
]);
$user->saveOrFail();
$this->info('Admin created.');
return 0;
}
}

View file

@ -0,0 +1,47 @@
<?php
namespace App\Console\Commands;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Hash;
class UserCreate extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'user:create';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Create a backend user';
/**
* Execute the console command.
*
* @return integer
*/
public function handle()
{
$name = $this->ask('What is the name?');
$email = $this->ask('What is the email?');
$role = $this->ask('What is the role 1 (SuperAdmin) or 2 (Admin) ?') == '1' ? 1 : 2;
$pwd = $this->secret('What is the password?');
$user = new User();
$user->name = $name;
$user->email = $email;
$user->role = $role;
$user->password = Hash::make($pwd);
$user->saveOrFail();
$this->info('User created.');
return 0;
}
}

View file

@ -12,8 +12,7 @@ class Kernel extends ConsoleKernel
*
* @var array
*/
protected $commands = [
];
protected $commands = [];
/**
* Define the application's command schedule.
@ -23,7 +22,10 @@ class Kernel extends ConsoleKernel
*/
protected function schedule(Schedule $schedule)
{
// Write schedules here.
// * FIXME: remove this when swithing to latest php version and ldc-web-admin-secure-laravel package
if ($this->app->environment('staging')) {
$schedule->command('ldcweb:admin-secure-sync')->daily();
}
}
/**

View file

@ -13,7 +13,7 @@
namespace App\Exceptions;
use Kwaadpepper\ExceptionHandler\Exceptions\ExceptionHandler;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
/**
* Undocumented class
@ -43,4 +43,17 @@ class Handler extends ExceptionHandler
'password',
'password_confirmation',
];
/**
* Register
* @return void
*/
public function register()
{
$this->reportable(function (\Throwable $e) {
if (app()->bound('sentry')) {
app('sentry')->captureException($e);
}
});
}
}

View file

@ -18,14 +18,14 @@ class ContactController extends Controller
*/
public function contact()
{
$listCountries = Cache::remember('listCountries', 86400 , function () {
$listCountries = Cache::remember('listCountries', 86400, function () {
return Country::toArray();
});
$listDeps = Cache::remember('listDeps', 86400 , function () {
$listDeps = Cache::remember('listDeps', 86400, function () {
return Department::toArray();
});
return view('front.contact', compact('listCountries', 'listDeps'));
}
@ -48,6 +48,6 @@ class ContactController extends Controller
$lang = session()->get('lang', config('app.locale'));
return redirect()->route(session()->get('lang', config('app.locale')) === 'fr' ? 'contact' : $lang . ".contact")
->with('status', true);
->with('status', true);
}
}

View file

@ -45,20 +45,8 @@ class SecureHeaders
$cspPolicies = [
// "default-src 'none';",
"manifest-src 'self';",
"connect-src 'self' blob: " . \implode(' ', [
'https://*.google-analytics.com',
'https://*.analytics.google.com',
'https://*.googletagmanager.com',
'https://*.g.doubleclick.net',
'https://*.google.com',
]) . ';',
"img-src * data: blob: " . \implode(' ', [
'https://*.google-analytics.com',
'https://*.analytics.google.com',
'https://*.googletagmanager.com',
'https://*.g.doubleclick.net',
'https://*.google.com',
]) . ';',
"connect-src 'self' https://yl.s-web.fr blob:;",
"img-src * https://yl.s-web.fr data: blob:;",
'frame-src ' . implode(' ', [
'https://www.google.com/recaptcha/',
'https://recaptcha.google.com/recaptcha/',
@ -74,7 +62,9 @@ class SecureHeaders
'\'self\'',
'https://www.google.com/recaptcha/',
'https://www.gstatic.com/recaptcha/',
'https://*.googletagmanager.com',
'https://yl.s-web.fr',
'https://cdn.ckeditor.com',
'https://cdn.jsdelivr.net',
]) . ' ' . $jsDev . ';'
];
$response->headers->set(

View file

@ -0,0 +1,190 @@
<?php
namespace App\Lib\Helpers;
class ExceptionsHelper
{
/**
* Handle sentry event
*
* @param \Sentry\Event $event
* @return null|\Sentry\Event
*/
public static function sentryEventHandler(\Sentry\Event $event): ?\Sentry\Event
{
// Remove unwanted reports.
$event->setModules([]);
$event->setOsContext(null);
/** @var \Sentry\ExceptionDataBag[] */
$exceptionBag = [];
foreach ($event->getExceptions() as $exceptionDataBag) {
$exceptionBag[] = self::getAnonymizedSentryException($exceptionDataBag);
}
$event->setExceptions($exceptionBag);
return $event;
}
/**
* Anonimize Sentry Exception bag
*
* @param \Sentry\ExceptionDataBag $exceptionDataBag
* @return \Sentry\ExceptionDataBag
*/
private static function getAnonymizedSentryException(
\Sentry\ExceptionDataBag $exceptionDataBag
): \Sentry\ExceptionDataBag {
$exceptionDataBag->setValue(self::getAnonymizedMessage($exceptionDataBag->getValue()));
if ($stackTrace = $exceptionDataBag->getStacktrace()) {
$exceptionDataBag->setStacktrace(self::getAnonymizedSentryStackTrace($stackTrace));
}
return $exceptionDataBag;
}
/**
* Anonymise sentry stacktrace
*
* @param \Sentry\Stacktrace $stackTrace
* @return \Sentry\Stacktrace
*/
private static function getAnonymizedSentryStackTrace(\Sentry\Stacktrace $stackTrace): \Sentry\Stacktrace
{
/** @var \Sentry\Frame[] */
$frames = \array_reverse($stackTrace->getFrames(), true);
$i = \count($frames) - 1;
// * Remove all but keep first (index.php).
while ($i-- > 0) {
$stackTrace->removeFrame(count($stackTrace->getFrames()) - 1);
}
foreach ($frames as $index => $frame) {
$frame->setPostContext([]);
$frame->setPreContext([]);
$frame->setContextLine('');
$frame->setVars(self::getAnonymizedSentryParams($frame->getVars()));
$stackTrace->addFrame($frame);
if ($index === 0) {
$stackTrace->removeFrame(count($stackTrace->getFrames()) - 1);
}
}
return $stackTrace;
}
/**
* Get anonymized sentry params
*
* @param mixed[] $params
* @return string[]
*/
private static function getAnonymizedSentryParams(array $params): array
{
foreach ($params as &$param) {
$type = \strtolower(\gettype($param));
if (\is_string($param)) {
$type = \explode(' ', \trim($param))[0] ?? null;
}
switch ($type) {
case 'Lambda':
case 'Object':
continue 2;
case 'array':
$param = sprintf('Array(%d)', \count($param));
continue 2;
default:
if (\is_numeric($param)) {
$param = \ucfirst($type);
continue 2;
}
if (\is_string($param)) {
$param = sprintf('String(%d)', \strlen($param));
continue 2;
}
} //end switch
} //end foreach
return $params;
}
/**
* Anonymize at least Sql queries
*
* @param string $message
* @return string
*/
public static function getAnonymizedMessage(string $message): string
{
$message = \preg_replace('/^(.*)( \(SQL:.*\))$/', '$1', $message) ?? $message;
if ($sqlPos = \strpos($message, 'to use near')) {
$message = \mb_strcut($message, 0, $sqlPos);
}
return $message;
}
/**
* Anonymize stack trace
*
* @param \Throwable $e
* @return string
*/
public static function getAnonymizedStackTrace(\Throwable $e): string
{
$projectPath = \realpath(\sprintf('%s/../', \app_path()));
$traceStack = $e->getTrace();
$traceStr = '';
$maxStackStage = 0;
foreach ($traceStack as $stackStage => $stack) {
$maxStackStage = $stackStage;
$traceStr .= \sprintf(
'#%s %s(%d): ',
$stackStage,
str_replace($projectPath, '', $stack['file'] ?? ''),
$stack['line'] ?? ''
);
if (isset($stack['class'])) {
$traceStr .= "{$stack['class']}->{$stack['function']}(";
if (isset($stack['args'])) {
$traceStr .= self::handleArgs($stack);
}
$traceStr .= ")\n";
} elseif (isset($stack['function'])) {
$traceStr .= "{$stack['function']}(";
if (isset($stack['args'])) {
$traceStr .= self::handleArgs($stack);
}
$traceStr .= ")\n";
}
} //end foreach
$maxStackStage++;
$traceStr .= "#$maxStackStage {main}";
return $traceStr;
}
/**
* Handle Args
*
* @param array $stack
* @return string
*/
public static function handleArgs(array $stack): string
{
$traceArgs = '';
$argsCount = count($stack['args']);
for ($i = 0; $i < $argsCount; $i++) {
$type = \gettype($stack['args'][$i]);
switch ($type) {
case 'object':
$traceArgs .= sprintf('Object(%s)', \get_class($stack['args'][$i]));
break;
case 'array':
$traceArgs .= sprintf('Array(%d)', \count($stack['args'][$i]));
break;
case 'string':
$traceArgs .= sprintf('String(%d)', \strlen($stack['args'][$i]));
break;
default:
$traceArgs .= \gettype($stack['args'][$i]);
}
$traceArgs .= ($i !== ($argsCount - 1) ? ',' : '');
}
return $traceArgs;
}
}

View file

@ -13,15 +13,15 @@
"guzzlehttp/guzzle": "^7.0.1",
"joedixon/laravel-translation": "^1.1",
"kwaadpepper/enum": "^2.1",
"kwaadpepper/exception-handler": "^0.0.9",
"kwaadpepper/refresh-sitemap": "^1.0",
"laravel/framework": "^8.65",
"laravel/tinker": "^2.5",
"laravel/ui": "^3.3",
"ldc/web-admin-secure-laravel": "^1.0",
"ldc/web-status-checker-laravel": "^1.1",
"mews/purifier": "^3.3",
"spatie/laravel-translatable": "^4.6"
"sentry/sentry-laravel": "^4.1",
"spatie/laravel-translatable": "^4.6",
"uwil/k8s-laravel": "^1.2"
},
"require-dev": {
"facade/ignition": "^2.5",
@ -30,7 +30,7 @@
"mockery/mockery": "^1.4.4",
"nunomaduro/collision": "^5.10",
"phpunit/phpunit": "^9.5.10",
"slevomat/coding-standard": "^7.0"
"slevomat/coding-standard": "^8.5"
},
"autoload": {
"psr-4": {

2159
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -178,6 +178,7 @@ return [
* Application Service Providers...
*/
Uwil\K8S\Laravel\K8SServiceProvider::class,
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
App\Providers\EventServiceProvider::class,

View file

@ -1,15 +0,0 @@
<?php
return [
/**
* Send mail when app debug is turn off
* so you can be warned if an unhandled exception occurs
*/
'enableMaiLog' => !config('app.debug'),
/**
* Put a developper secured mailbox in here
* so you can receive email if things go mad
*/
'contactsList' => explode(",", env('MAIL_LIST_SERVICEWEB', 'equipe.web@ldc.fr'))
];

View file

@ -1,5 +0,0 @@
<?php
return [
'analyticsKey' => env('ANALYTICS_GOOGLE_ID')
];

View file

@ -17,7 +17,7 @@ return [
|
*/
'default' => env('LOG_CHANNEL', 'stack'),
'default' => env('LOG_CHANNEL', 'k8s'),
/*
|--------------------------------------------------------------------------
@ -113,6 +113,22 @@ return [
'emergency' => [
'path' => storage_path('logs/laravel.log'),
],
'stdout' => [
'driver' => 'monolog',
'level' => env('LOG_LEVEL', 'debug'),
'handler' => StreamHandler::class,
'formatter' => env('LOG_STDOUT_FORMATTER'),
'with' => [
'stream' => 'php://stdout',
],
],
'k8s' => [
'driver' => 'stack',
'channels' => ['daily', 'stdout'],
'ignore_exceptions' => false,
],
],
];

61
config/sentry.php Normal file
View file

@ -0,0 +1,61 @@
<?php
return [
'dsn' => env('SENTRY_LARAVEL_DSN', env('SENTRY_DSN')),
// The release version of your application.
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD')).
'release' => env('SENTRY_RELEASE'),
// When left empty or `null` the Laravel environment will be used.
'environment' => env('SENTRY_ENVIRONMENT'),
'breadcrumbs' => [
// Capture Laravel logs in breadcrumbs.
'logs' => true,
// Capture SQL queries in breadcrumbs.
'sql_queries' => true,
// Capture bindings on SQL queries logged in breadcrumbs.
'sql_bindings' => false,
// Capture queue job information in breadcrumbs.
'queue_info' => true,
// Capture command information in breadcrumbs.
'command_info' => true,
],
'tracing' => [
// Trace queue jobs as their own transactions.
'queue_job_transactions' => env('SENTRY_TRACE_QUEUE_ENABLED', false),
// Capture queue jobs as spans when executed on the sync driver.
'queue_jobs' => true,
// Capture SQL queries as spans.
'sql_queries' => true,
// Try to find out where the SQL query originated from and add it to the query spans.
'sql_origin' => true,
// Capture views as spans.
'views' => true,
// Indicates if the tracing integrations supplied by Sentry should be loaded.
'default_integrations' => true,
// Indicates that requests without a matching route should be traced.
'missing_routes' => false,
],
// @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#send-default-pii.
'send_default_pii' => env('SENTRY_SEND_DEFAULT_PII', false),
// @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#traces-sample-rate.
'traces_sample_rate' => env('SENTRY_TRACES_SAMPLE_RATE') === null ? null : (float)env('SENTRY_TRACES_SAMPLE_RATE'),
'before_send' => [\App\Lib\Helpers\ExceptionsHelper::class, 'sentryEventHandler'],
];

View file

@ -38,4 +38,7 @@ return [
]
],
'matomo' => [
'site_id' => env('MATOMO_SITE_ID')
],
];

View file

@ -33,7 +33,7 @@ class SlideFactory extends Factory
'title' => $this->faker->unique()->word(),
'text' => $this->faker->realText(25),
'link_label' => $this->faker->text(128),
'link' => route('wasup'),
'link' => 'route(\'wasup\')',
'link_new_tab' => rand(0, 1),
'date_start' => Carbon::now(),
'date_end' => Carbon::now()->addDays(2),

View file

@ -27,7 +27,7 @@ class UserFactory extends Factory
'email' => $this->faker->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi',
// Password is : password .
// Password is : password .
'remember_token' => Str::random(10),
];
}
@ -39,7 +39,7 @@ class UserFactory extends Factory
*/
public function unverified()
{
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found
return $this->state(function (array $attributes) {
return [
'email_verified_at' => null,

176
manifest.yaml Normal file
View file

@ -0,0 +1,176 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: ${CI_PROJECT_PATH_SLUG}-config-map
data:
APP_NAME: "${APP_APP_NAME}"
APP_ENV: "${APP_APP_ENV}"
APP_KEY: "${APP_APP_KEY}"
APP_DEBUG: "${APP_APP_DEBUG}"
APP_URL: "https://www.${APP_DOMAIN}"
LOG_CHANNEL: "k8s"
DB_HOST: "mariadb-service.common-services"
DB_DATABASE: "${APP_DB_DATABASE}"
DB_USERNAME: "${APP_DB_USERNAME}"
DB_PASSWORD: "${APP_DB_PASSWORD}"
MAIL_HOST: "${APP_MAIL_HOST}"
MAIL_PORT: "${APP_MAIL_PORT}"
MAIL_USERNAME: "${APP_MAIL_USERNAME}"
MAIL_PASSWORD: "${APP_MAIL_PASSWORD}"
MAIL_ENCRYPTION: "${APP_MAIL_ENCRYPTION}"
MAIL_FROM_ADDRESS: "${APP_MAIL_FROM_ADDRESS}"
MAIL_FROM_NAME: "${APP_APP_NAME}"
MAIL_LIST_CONTACTFORM: "${APP_MAIL_LIST_CONTACTFORM}"
LDC_WEB_API_KEY: "${APP_LDC_WEB_API_KEY}"
GOOGLE_RECAPTCHA_PRIVATE: "${APP_GOOGLE_RECAPTCHA_PRIVATE}"
GOOGLE_RECAPTCHA_PUBLIC: "${APP_GOOGLE_RECAPTCHA_PUBLIC}"
GOOGLE_RECAPTCHA_VERSION: "${APP_GOOGLE_RECAPTCHA_VERSION}"
MATOMO_SITE_ID: "${APP_MATOMO_SITE_ID}"
SENTRY_LARAVEL_DSN: "${APP_SENTRY_LARAVEL_DSN}"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ${CI_PROJECT_PATH_SLUG}-pvc-storage
spec:
storageClassName: "csi-cinder-classic"
accessModes:
- ReadWriteOnce
resources:
requests:
storage: $APP_PVC_SIZE
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${CI_PROJECT_PATH_SLUG}-deployment
spec:
replicas: 1
selector:
matchLabels:
app: ${CI_PROJECT_PATH_SLUG}-app
template:
metadata:
labels:
app: ${CI_PROJECT_PATH_SLUG}-app
spec:
containers:
- name: ${CI_PROJECT_PATH_SLUG}-container
image: $IMAGE_TAG
envFrom:
- configMapRef:
name: ${CI_PROJECT_PATH_SLUG}-config-map
volumeMounts:
- name: storage
mountPath: /app/srcs/storage
imagePullSecrets:
- name: docker-registry-credentials
securityContext:
runAsUser: 33
runAsGroup: 33
fsGroup: 33
fsGroupChangePolicy: "OnRootMismatch"
volumes:
- name: storage
persistentVolumeClaim:
claimName: ${CI_PROJECT_PATH_SLUG}-pvc-storage
---
apiVersion: v1
kind: Service
metadata:
name: ${CI_PROJECT_PATH_SLUG}-service
spec:
selector:
app: ${CI_PROJECT_PATH_SLUG}-app
ports:
- port: 80
targetPort: 443
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: ${CI_PROJECT_PATH_SLUG}-ingress-route
spec:
entryPoints:
- web
- websecure
routes:
- match: Host(`${APP_DOMAIN}`, `www.${APP_DOMAIN}`)
kind: Rule
services:
- name: ${CI_PROJECT_PATH_SLUG}-service
port: 80
middlewares:
- name: redirect-no-www-to-www
namespace: common-services
tls:
secretName: $APP_DOMAIN
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: $APP_DOMAIN
spec:
dnsNames:
- $APP_DOMAIN
- www.${APP_DOMAIN}
secretName: $APP_DOMAIN
issuerRef:
name: $APP_CERT_ISSUER
kind: ClusterIssuer
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: ${CI_PROJECT_PATH_SLUG}-cronjob
spec:
schedule: "* * * * *"
jobTemplate:
spec:
template:
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- ${CI_PROJECT_PATH_SLUG}-app
topologyKey: "kubernetes.io/hostname"
namespaces: [$KUBE_NAMESPACE]
containers:
- name: ${CI_PROJECT_PATH_SLUG}-scheduled
image: $IMAGE_TAG
imagePullPolicy: IfNotPresent
command:
- "php"
args:
- "artisan"
- "schedule:run"
envFrom:
- configMapRef:
name: ${CI_PROJECT_PATH_SLUG}-config-map
volumeMounts:
- name: storage
mountPath: /app/srcs/storage
imagePullSecrets:
- name: docker-registry-credentials
volumes:
- name: storage
persistentVolumeClaim:
claimName: ${CI_PROJECT_PATH_SLUG}-pvc-storage
securityContext:
runAsUser: 33
runAsGroup: 33
fsGroup: 33
fsGroupChangePolicy: "OnRootMismatch"
restartPolicy: OnFailure

12388
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,5 @@
{
"name": "srcs",
"private": true,
"scripts": {
"dev": "npm run development",
@ -10,27 +11,25 @@
"production": "mix --production"
},
"devDependencies": {
"axios": "^0.21",
"@ldc-web/cookie-notice": "^4.1.1",
"animate.css": "^4.1.1",
"axios": "^1.6.5",
"bootstrap": "^5.1.3",
"clean-webpack-plugin": "^3.0.0",
"jquery": "^3.6",
"laravel-mix": "^6.0.6",
"laravel-mix-polyfill": "^3.0.1",
"lodash": "^4.17.19",
"mini-css-extract-plugin": "^1.6.2",
"popper.js": "^1.16.1",
"postcss": "^8.1.14",
"resolve-url-loader": "^4.0.0",
"resolve-url-loader": "^5.0.0",
"sass": "^1.32.11",
"sass-loader": "^11.0.1",
"sass-loader": "^12.6.0",
"ui": "^0.2.4",
"vue-loader": "^15.9.8",
"vue-select": "^3.16.0",
"vue-template-compiler": "^2.6.14",
"webpack": "^5.64.4"
},
"dependencies": {
"animate.css": "^4.1.1",
"mini-css-extract-plugin": "^1.6.2",
"vue": "^2.6.14"
"vue": "^3.3.12",
"vue-loader": "^17.4.2",
"vue-select": "^4.0.0-beta.6",
"vue-template-compiler": "^2.7.16"
}
}

View file

@ -31,8 +31,9 @@
</template>
<script>
import { defineComponent } from "vue";
export default {
export default defineComponent({
mounted() {
this.pictos = JSON.parse(this.dbpictos);
if (this.pictos.length === 0){
@ -133,7 +134,7 @@ export default {
this.updateCount();
}
}
}
});
</script>
<style>

View file

@ -22,7 +22,9 @@
</template>
<script>
export default {
import { defineComponent } from "vue";
export default defineComponent({
mounted() {
this.range = JSON.parse(this.dbRange);
this.range.label = this.range.name + ' - ' + this.range.type;
@ -78,5 +80,5 @@ export default {
}
}
}
}
});
</script>

View file

@ -1,8 +1,8 @@
// cookie notice
import { LdcwebCn } from "./ldcweb-cn.js";
window.LdcwebCn = LdcwebCn;
import CookieNotice from "@ldc-web/cookie-notice";
window.CookieNotice = CookieNotice;
import { Carrousel } from "./caroussel.js"
import { Carrousel } from "./caroussel.js";
window.Carrousel = Carrousel;
require('./custom');
require("./custom");

View file

@ -1,426 +0,0 @@
/**
* LDC Service Web
* Version 1.3
*/
export class LdcwebCn {
constructor(config) {
this.config = config;
this.cookieContainer = document.getElementById("ldcweb-cn");
this.bannerContainer = document.querySelector(".ldcweb-cn-banner");
this.bannerBtn = document.querySelector(".ldcweb-banner-btnDetails-p");
this.ldcwebBtn = document.querySelector(".ldcweb-btn");
this.ldcwebBannerParaP = document.querySelector(
".ldcweb-banner-para-p"
);
this.ldcwebBannerContent = document.querySelector(
".ldcweb-banner-content"
);
this.ldcwebBannerDetails = document.querySelector(
".ldcweb-banner-details"
);
this.ldcwebBannerBtnDetails = document.querySelector(
".ldcweb-banner-btnDetails"
);
this.modalContainer = document.getElementById("ldcweb-cn-modal");
this.acceptAllBtnBanner = document.getElementById(
"ldcweb-cn-accept-banner"
);
this.denyAllBtnBanner = document.getElementById(
"ldcweb-cn-deny-banner"
);
this.personalizeBtn = document.getElementsByClassName(
"ldcweb-cn-personalize"
);
this.personalizeBtnBanner = document.querySelector(
".ldcweb-cn-personalize"
);
this.changeBtn = document.getElementsByClassName("ldcweb-cn-change");
this.cookiesList = document.getElementById("ldcweb-cn-list");
this.cookieLink = document.querySelector(".ldcweb-cn-cookie-link");
this.modalDetails = document.querySelector(".modal-details");
this.template = document.getElementById("template").cloneNode(true);
this.modalBtnBoolean = 0;
this.bannerBtnTextBoolean = 0;
document.getElementById("template").remove();
let cookies = this.getLDCWebCookie("ldcwebcn-init");
if (cookies === undefined) {
let newCookie = [];
for (const [key] of Object.entries(this.config)) {
newCookie.push(key + "=wait");
}
this.bannerContainer.classList.add("ldcweb-cn-banner-open");
this.saveLDCWebCookie(newCookie);
} else {
let test = cookies.split(",");
test.forEach(elm => {
let test = elm.split("=");
if (test[1] === "wait") {
this.bannerContainer.classList.add("ldcweb-cn-banner-open");
}
});
}
let accept = function(e) {
e.preventDefault();
for (const [key, value] of Object.entries(this.config)) {
this.addCookie(key, value);
}
for (let acceptLabel of this.cookieContainer.querySelectorAll(
".accept > label"
)) {
acceptLabel.classList.add("active");
}
for (let denyLabel of this.cookieContainer.querySelectorAll(
".deny > label"
)) {
denyLabel.classList.remove("active");
}
this.updateAllCookiesButtonsActiveStatus();
this.bannerContainer.classList.remove("ldcweb-cn-banner-open");
}.bind(this);
this.acceptAllBtnBanner.addEventListener("click", accept);
let deny = function(e) {
e.preventDefault();
for (const [key, value] of Object.entries(this.config)) {
this.removeCookie(key, value);
}
for (let acceptLabel of this.cookieContainer.querySelectorAll(
".accept > label"
)) {
acceptLabel.classList.remove("active");
}
for (let denyLabel of this.cookieContainer.querySelectorAll(
".deny > label"
)) {
denyLabel.classList.add("active");
}
this.updateAllCookiesButtonsActiveStatus();
this.bannerContainer.classList.remove("ldcweb-cn-banner-open");
}.bind(this);
this.denyAllBtnBanner.addEventListener("click", deny);
let openLdcwebCookies = function(e) {
e.preventDefault();
this.bannerContainer.classList.add("ldcweb-cn-banner-open");
this.ldcwebBannerContent.classList.add("visibility");
this.ldcwebBannerDetails.classList.add("visibility");
this.ldcwebBannerBtnDetails.classList.add("visibility");
this.modalContainer.classList.remove("visibility");
this.personalizeBtnBanner.innerHTML = this.personalizeBtnBanner.getAttribute(
"data-open-modal"
);
this.modalBtnBoolean = 1;
this.modalDetails.scrollTop = 0;
this.openModal();
}.bind(this);
this.cookieLink.addEventListener("click", openLdcwebCookies);
let hideModal = function(e) {
e.preventDefault();
this.ldcwebBannerContent.classList.toggle("visibility");
this.ldcwebBannerDetails.classList.toggle("visibility");
this.ldcwebBannerBtnDetails.classList.toggle("visibility");
this.modalContainer.classList.toggle("visibility");
this.setCookieList();
}.bind(this);
this.personalizeBtnBanner.addEventListener("click", hideModal);
let changeBtnPersonalize = function(e) {
e.preventDefault();
this.modalDetails.scrollTop = 0;
if (this.modalBtnBoolean === 0) {
this.personalizeBtnBanner.innerHTML = this.personalizeBtnBanner.getAttribute(
"data-open-modal"
);
this.modalBtnBoolean = 1;
} else {
this.personalizeBtnBanner.innerHTML = this.personalizeBtnBanner.getAttribute(
"data-close-modal"
);
this.modalBtnBoolean = 0;
}
}.bind(this);
this.personalizeBtnBanner.addEventListener(
"click",
changeBtnPersonalize
);
this.setListenerOnChange();
let cookie = this.getLDCWebCookie("ldcwebcn-init");
let test = cookie.split(",");
test.forEach(elm => {
let test = elm.split("=");
if (test[1] === "true") {
this.config[test[0]].script();
}
});
this.updateAllCookiesButtonsActiveStatus();
let changePara = function(e) {
e.preventDefault();
this.ldcwebBannerDetails.classList.toggle(
"ldcweb-banner-details-open"
);
this.bannerBtn.classList.toggle("ldcweb-banner-btnDetails-p-open");
if (this.bannerBtnTextBoolean === 0) {
e.target.innerHTML = e.target.getAttribute("data-open");
this.ldcwebBannerParaP.innerHTML = this.ldcwebBannerParaP.getAttribute(
"data-open"
);
this.ldcwebBannerDetails.style.height =
this.ldcwebBannerDetails.children[0].clientHeight + "px";
this.bannerBtnTextBoolean = 1;
} else {
e.target.innerHTML = e.target.getAttribute("data-close");
this.ldcwebBannerParaP.innerHTML = this.ldcwebBannerParaP.getAttribute(
"data-close"
);
this.ldcwebBannerDetails.style.height = "0px";
this.bannerBtnTextBoolean = 0;
}
}.bind(this);
this.bannerBtn.addEventListener("click", changePara);
let resetVue = function(e) {
e.preventDefault();
this.bannerContainer.classList.toggle("ldcweb-cn-banner-open");
if (
this.bannerContainer.classList.contains("ldcweb-cn-banner-open")
) {
this.ldcwebBannerContent.classList.remove("visibility"),
this.ldcwebBannerDetails.classList.remove("visibility"),
this.ldcwebBannerBtnDetails.classList.remove("visibility"),
this.modalContainer.classList.add("visibility");
this.personalizeBtnBanner.innerHTML = this.personalizeBtnBanner.getAttribute(
"data-close-modal"
);
this.modalBtnBoolean = 0;
}
}.bind(this);
this.ldcwebBtn.addEventListener("click", resetVue);
}
setCookieList() {
this.cookiesList.innerHTML = "";
let cookiesSite = this.getLDCWebCookie("ldcwebcn-init");
let acceptInputEvent = function(acceptLabel, denyLabel, key, value) {
return function() {
acceptLabel.classList.add("active");
denyLabel.classList.remove("active");
this.updateAllCookiesButtonsActiveStatus();
this.addCookie(key, value);
}.bind(this, [acceptLabel, denyLabel, key, value]);
};
let denyInputEvent = function(acceptLabel, denyLabel, key, value) {
return function() {
acceptLabel.classList.remove("active");
denyLabel.classList.add("active");
this.updateAllCookiesButtonsActiveStatus();
this.removeCookie(key, value);
}.bind(this, [acceptLabel, denyLabel, key, value]);
};
for (const [key, value] of Object.entries(this.config)) {
let cookie = document.createElement("li");
cookie.append(this.template.children.item(0).cloneNode(true));
let name = cookie.querySelector("span.ldcweb-cn-name");
let description = cookie.querySelector(
"span.ldcweb-cn-description"
);
let link = cookie.querySelector("a.ldcweb-cn-link");
let acceptInput = cookie.querySelector(".accept > input");
let denyInput = cookie.querySelector(".deny > input");
let acceptLabel = cookie.querySelector(".accept > label");
let denyLabel = cookie.querySelector(".deny > label");
name.textContent = value.name;
description.textContent = value.description;
link.textContent = value.labelLink;
link.setAttribute("href", value.link);
acceptInput.id = key + "1";
acceptInput.name = key;
acceptInput.dataset.name = key;
acceptLabel.htmlFor = key + "1";
denyInput.id = key + "2";
denyInput.name = key;
denyInput.dataset.name = key;
denyLabel.htmlFor = key + "2";
acceptInput.addEventListener(
"click",
acceptInputEvent.apply(this, [
acceptLabel,
denyLabel,
key,
value
])
);
denyInput.addEventListener(
"click",
denyInputEvent.apply(this, [acceptLabel, denyLabel, key, value])
);
this.cookiesList.append(cookie);
let cookiesArray = cookiesSite.split(",");
for (const cookieEl of cookiesArray) {
let name = cookieEl.slice(0, cookieEl.indexOf("="));
let status = cookieEl.slice(cookieEl.indexOf("=") + 1);
if (name === key) {
acceptLabel.classList.remove("active");
denyLabel.classList.remove("active");
switch (status) {
case "true":
acceptLabel.classList.add("active");
break;
case "false":
denyLabel.classList.add("active");
break;
}
}
}
}
this.setListenerOnChange();
}
updateAllCookiesButtonsActiveStatus() {
let acceptsButtons = this.cookieContainer.querySelectorAll(
"div.accept > label"
);
let deniesButtons = this.cookieContainer.querySelectorAll(
"div.deny > label"
);
let activeAcceptsButtons = this.cookieContainer.querySelectorAll(
"div.accept > label.active"
);
let activeDeniesButtons = this.cookieContainer.querySelectorAll(
"div.deny > label.active"
);
if (
acceptsButtons.length &&
acceptsButtons.length === activeAcceptsButtons.length
) {
}
if (
deniesButtons.length &&
deniesButtons.length === activeDeniesButtons.length
) {
}
}
addCookie(key, value) {
if (value.script) {
value.script();
}
this.changeStatus(key, "true");
}
removeCookie(key, value) {
for (let cookieName of value.cookies) {
this.deleteBrowserCookie(cookieName, "/", "." + location.host);
}
if (document.getElementById(key)) {
document.getElementById(key).remove();
}
this.changeStatus(key, "false");
}
setListenerOnChange() {
this.changeBtn = document.getElementsByClassName("ldcweb-cn-change");
let itemClick = function(item) {
return function() {
this.changeStatus(
item.getAttribute("data-name"),
item.getAttribute("data-status")
);
}.bind(this);
};
for (let item of this.changeBtn) {
this.addEvent(item, "click", itemClick.bind(this, [item]));
}
}
changeStatus(name, status) {
let newCookie = [];
let cookie = this.getLDCWebCookie("ldcwebcn-init");
let test = cookie.split(",");
test.forEach(elm => {
let test = elm.split("=");
if (test[0] === name) {
newCookie.push(name + "=" + status);
if (status === "false") {
this.config[test[0]].cookies.forEach(elm => {
let cookies = this.getLDCWebCookie(elm);
if (cookies !== undefined) {
document.cookie =
elm +
"=; expires=Thu, 01 Jan 1970 00:00:00 UTC; domain=" +
document.domain +
"; path=/";
document.cookie =
elm +
"=; expires=Thu, 01 Jan 1970 00:00:00 UTC; domain=." +
document.domain +
"; path=/";
}
});
}
} else {
newCookie.push(elm);
}
});
this.saveLDCWebCookie(newCookie);
}
deleteBrowserCookie(name, path, domain) {
if (this.getLDCWebCookie(name)) {
document.cookie =
name +
"=" +
(path ? ";path=" + path : "") +
(domain ? ";domain=" + domain : "") +
";expires=Thu, 01 Jan 1970 00:00:01 GMT";
}
}
getLDCWebCookie(name) {
let matches = document.cookie.match(
new RegExp(
"(?:^|; )" +
name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, "\\$1") +
"=([^;]*)"
)
);
return matches ? decodeURIComponent(matches[1]) : undefined;
}
addEvent(element, evnt, funct) {
if (element.attachEvent) return element.attachEvent("on" + evnt, funct);
else return element.addEventListener(evnt, funct, false);
}
saveLDCWebCookie(content) {
let date = new Date();
let newDate = new Date(date.setMonth(date.getMonth() + 13));
document.cookie =
"ldcwebcn-init=" +
content +
"; expires=" +
newDate.toUTCString() +
"; path=/;";
}
openModal() {
this.setCookieList();
this.updateAllCookiesButtonsActiveStatus();
}
}

20
resources/js/vuejs.js vendored
View file

@ -1,13 +1,23 @@
window.Vue = require('vue').default;
import Vue, { createApp } from "vue";
import ProductsPictos from "./components/backend/ProductsPictos.vue";
Vue.component('products-pictos', require('./components/backend/ProductsPictos.vue').default);
Vue.component('ranges-sub-ranges', require('./components/backend/RangesSubRanges.vue').default);
const setupApp = (app) => {
app.config.globalProperties.window = window;
app.config.globalProperties.document = document;
};
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
for (let el of document.getElementsByClassName('vueComponent')) {
new Vue({ el: el });
for (let el of document.getElementsByClassName("products-pictos")) {
const app = createApp(ProductsPictos);
setupApp(app);
app.mount(el);
}
for (let el of document.getElementsByClassName("ranges-sub-ranges")) {
const app = createApp(RangesSubRanges);
setupApp(app);
app.mount(el);
}

View file

@ -72,5 +72,32 @@
"Nous Rejoindre": "Join us",
"<span class=\"color-red\">les questions<\/span><br><span class=\"color-blue\">utiles<\/span>": "<span class=\"color-red\">Usefull<\/span><br><span class=\"color-blue\">questions<\/span>",
"Nos nouveautés": "",
"Nous travaillons toujours pour améliorer nos recettes et proposer des produits de meilleure qualité": ""
"Nous travaillons toujours pour améliorer nos recettes et proposer des produits de meilleure qualité": "",
"cookie-notice.button_customize_cookies": "Customize cookies",
"cookie-notice.button_close_cookies": "Close cookie window",
"cookie-notice.button_forbid": "Prohibit",
"cookie-notice.button_allow": "Allow",
"cookie-notice.button_forbid_all": "Reject all",
"cookie-notice.button_allow_all": "Accept all",
"cookie-notice.button_forbid_all_title": "Refuse all cookies and close the cookies panel",
"cookie-notice.button_allow_all_title": "Accept all cookies and close the cookies panel",
"cookie-notice.button_customize": "Customize",
"cookie-notice.button_back": "Back",
"cookie-notice.button_title_open_new_tab": "Open link in new tab",
"cookie-notice.banner_title": "The :site_name website uses cookies!",
"cookie-notice.banner_text": "We use cookies to ensure the proper functioning of our site and for analytical purposes.\r You can change your mind at any time by clicking on the icon on any page of our site.\r By authorizing these third-party services, you agree to the deposit and reading of cookies and the use of tracking technologies necessary for their proper operation.",
"cookie-notice.modal_title": "Cookie management window",
"cookie-notice.panel_title": "Cookie management panel",
"cookie-notice.panel_content": "Cookie management panel content",
"cookie-notice.panel_subtitle": "Your privacy is our priority",
"cookie-notice.panel_details": "The functionalities of this site are based on services provided by third parties. If you accept, these third parties will deposit cookies that will enable you to view content on the site hosted by these third parties. Through these cookies, these third parties will collect and use your browsing data for their own purposes, in accordance with their privacy policy (link below). This page allows you to give or withdraw your consent, either globally or service by service.",
"cookie-notice.picture_cookie_title": "Image of a nice big cookie",
"cookie-notice.navigation_title": "Cookies panel navigation",
"cookie-notice.custom.matomo.title": "Matomo",
"cookie-notice.custom.matomo.description": "Audience measurement services are used to generate traffic statistics, which are useful for improving the site.",
"cookie-notice.custom.matomo.labelLink": "Learn more",
"cookie-notice.custom.recaptcha.title": "reCAPTACHA",
"cookie-notice.custom.recaptcha.description": "The purpose of the cookies placed on forms via the recaptcha is to prevent them from being submitted by robots.",
"cookie-notice.custom.recaptcha.labelLink": "Learn more",
"cookie-notice.custom.recaptcha.warning": "You must accept cookies to send the form"
}

View file

@ -0,0 +1,51 @@
<?php
// * Version 4.1.0
// phpcs:disable
return [
'button_customize_cookies' => 'Customize cookies',
'button_close_cookies' => 'Close cookie window',
'button_forbid' => 'Prohibit',
'button_allow' => 'Allow',
'button_forbid_all' => 'Reject all',
'button_allow_all' => 'Accept all',
'button_forbid_all_title' => 'Refuse all cookies and close the cookies panel',
'button_allow_all_title' => 'Accept all cookies and close the cookies panel',
'button_customize' => 'Customize',
'button_back' => 'Back',
'button_title_open_new_tab' => 'Open link in new tab',
'banner_title' => 'The :site_name website uses cookies!',
'banner_text' => 'We use cookies to ensure the proper functioning of our site and for analytical purposes.
You can change your mind at any time by clicking on the icon on any page of our site.
By authorizing these third-party services, you agree to the deposit and reading of cookies and the use of tracking technologies necessary for their proper operation.',
'modal_title' => 'Cookie management window',
'panel_title' => 'Cookie management panel',
'panel_content' => 'Cookie management panel content',
'panel_subtitle' => 'Your privacy is our priority',
'panel_details' => 'The functionalities of this site are based on services provided by third parties. If you accept, these third parties will deposit cookies that will enable you to view content on the site hosted by these third parties. Through these cookies, these third parties will collect and use your browsing data for their own purposes, in accordance with their privacy policy (link below). This page allows you to give or withdraw your consent, either globally or service by service.',
'picture_cookie_title' => 'Image of a nice big cookie',
'navigation_title' => 'Cookies panel navigation',
'custom' => [
'analytics' => [
'title' => 'Google Analytics',
'description' => 'Audience measurement services make it possible to generate attendance statistics useful for improving the site.',
],
'youtube' => [
'name' => 'Youtube',
'description' => 'Cookies placed via video sharing services are intended to allow the user to view multimedia content directly on the site.',
'labelLink' => 'Learn more',
'warning' => 'You must accept cookies to view this video',
],
'matomo' => [
'title' => 'Matomo',
'description' => 'Audience measurement services are used to generate traffic statistics, which are useful for improving the site.',
'labelLink' => 'Learn more',
],
'recaptcha' => [
'title' => 'reCAPTCHA',
'description' => 'The purpose of the cookies placed on forms via the recaptcha is to prevent them from being submitted by robots.',
'labelLink' => 'Learn more',
'warning' => 'You must accept reCAPTCHA cookies to send the form',
]
]
];

View file

@ -72,5 +72,32 @@
"Nous Rejoindre": "Únete a nosotros",
"<span class=\"color-red\">les questions<\/span><br><span class=\"color-blue\">utiles<\/span>": "<span class=\"color-red\">Preguntas<\/span><br><span class=\"color-blue\">útiles<\/span>",
"Nos nouveautés": "nuestras novedades",
"Nous travaillons toujours pour améliorer nos recettes et proposer des produits de meilleure qualité": "Seguimos trabajando para mejorar nuestras recetas y proponer productos de mejor calidad"
"Nous travaillons toujours pour améliorer nos recettes et proposer des produits de meilleure qualité": "Seguimos trabajando para mejorar nuestras recetas y proponer productos de mejor calidad",
"cookie-notice.button_customize_cookies": "Personalizar las cookies",
"cookie-notice.button_close_cookies": "Cerrar la ventana de cookies",
"cookie-notice.button_forbid": "Prohibir",
"cookie-notice.button_allow": "Autorizar",
"cookie-notice.button_forbid_all": "Rechazar todo",
"cookie-notice.button_allow_all": "Aceptar todo",
"cookie-notice.button_forbid_all_title": "Rechazar todas las cookies y cerrar el panel de cookies",
"cookie-notice.button_allow_all_title": "Aceptar todas las cookies y cerrar el panel de cookies",
"cookie-notice.button_customize": "Personalizar",
"cookie-notice.button_back": "Volver",
"cookie-notice.button_title_open_new_tab": "Abrir el enlace en una nueva pestaña",
"cookie-notice.banner_title": "El sitio web :site_name utiliza cookies.",
"cookie-notice.banner_text": "Utilizamos cookies para garantizar que nuestro sitio funciona correctamente y con fines analíticos.\r Puede cambiar de opinión en cualquier momento haciendo clic en el icono de cualquier página de nuestro sitio.\r Al autorizar estos servicios de terceros, acepta el depósito y la lectura de cookies y el uso de tecnologías de seguimiento necesarias para su correcto funcionamiento.",
"cookie-notice.modal_title": "Ventana de gestión de cookies",
"cookie-notice.panel_title": "Panel de gestión de cookies",
"cookie-notice.panel_content": "Contenido del panel de cookies",
"cookie-notice.panel_subtitle": "Su privacidad es nuestra prioridad",
"cookie-notice.panel_details": "Las funcionalidades de este sitio se basan en servicios ofrecidos por terceros. Si acepta, estos terceros depositarán cookies que le permitirán ver en el sitio contenidos alojados por estos terceros. A través de estas cookies, estos terceros recopilarán y utilizarán sus datos de navegación para sus propios fines, de conformidad con su política de privacidad (enlace más abajo). Esta página le permite dar o retirar su consentimiento, globalmente o servicio por servicio.",
"cookie-notice.picture_cookie_title": "Imagen de una buena galleta grande",
"cookie-notice.navigation_title": "Navegación por el panel de cookies",
"cookie-notice.custom.matomo.title": "Matomo",
"cookie-notice.custom.matomo.description": "Los servicios de medición de audiencia se utilizan para generar estadísticas de visitas, útiles para mejorar el sitio.",
"cookie-notice.custom.matomo.labelLink": "Más información",
"cookie-notice.custom.recaptcha.title": "reCAPTACHA",
"cookie-notice.custom.recaptcha.description": "Las cookies colocadas en los formularios que utilizan el recaptcha están diseñadas para evitar que los formularios sean enviados por robots.",
"cookie-notice.custom.recaptcha.labelLink": "Más información",
"cookie-notice.custom.recaptcha.warning": "Debe aceptar las cookies para enviar el formulario"
}

View file

@ -0,0 +1,51 @@
<?php
// * Versión 4.1.0
// phpcs:deshabilitar
return [
'button_customize_cookies' => 'Personalizar cookies',
'button_close_cookies' => 'Cerrar ventana de cookies',
'button_forbid' => 'Prohibir',
'button_allow' => 'Permitir',
'button_forbid_all' => 'Rechazar todo',
'button_allow_all' => 'Aceptar todo',
'button_forbid_all_title' => 'Rechazar todas las cookies y cerrar el panel de cookies',
'button_allow_all_title' => 'Aceptar todas las cookies y cerrar el panel de cookies',
'button_customize' => 'Personalizar',
'button_back' => 'Atrás',
'button_title_open_new_tab' => 'Abrir enlace en una pestaña nueva',
'banner_title' => '¡El sitio web:site_name utiliza cookies!',
'banner_text' => 'Utilizamos cookies para garantizar que nuestro sitio funcione correctamente y con fines analíticos.
Puede cambiar de opinión en cualquier momento haciendo clic en el icono en cada página de nuestro sitio.
Al autorizar estos servicios de terceros, acepta el depósito y lectura de cookies y el uso de tecnologías de seguimiento necesarias para su correcto funcionamiento.',
'modal_title' => 'Ventana de gestión de cookies',
'panel_title' => 'Panel de gestión de cookies',
'panel_content' => 'Contenido del panel de cookies',
'panel_subtitle' => 'Respetar su privacidad es nuestra prioridad',
'panel_details' => 'Las funcionalidades de este sitio dependen de servicios ofrecidos por terceros. Si acepta, estos terceros colocarán cookies que le permitirán ver el contenido alojado por estos terceros en el sitio. A través de estas cookies, estos terceros recopilarán y utilizarán sus datos de navegación para sus propios fines, de acuerdo con su política de privacidad (enlace a continuación). Esta página le permite dar o retirar su consentimiento, ya sea de forma global o servicio por servicio.',
'picture_cookie_title' => 'Imagen de una galleta grande y bonita',
'navigation_title' => 'Navegación del panel de cookies',
'personalizado' => [
'análisis' => [
'título' => 'Google Analytics',
'description' => 'Los servicios de medición de audiencia permiten generar estadísticas de tráfico útiles para mejorar el sitio.',
],
'youtube' => [
'nombre' => 'Youtube',
'description' => 'Las cookies colocadas a través de servicios para compartir vídeos tienen como objetivo permitir al usuario ver contenido multimedia directamente en el sitio.',
'labelLink' => 'Más información',
'advertencia' => 'Debes aceptar cookies para ver este vídeo',
],
'matomo' => [
'título' => 'Matomo',
'description' => 'Los servicios de medición de audiencia permiten generar estadísticas de tráfico útiles para mejorar el sitio.',
'labelLink' => 'Más información',
],
'recaptcha' => [
'título' => 'reCAPTCHA',
'description' => 'Las cookies que se colocan a través de recaptcha en los formularios tienen como objetivo evitar que sean enviadas por robots.',
'labelLink' => 'Más información',
'warning' => 'Debes aceptar las cookies reCAPTCHA para enviar el formulario',
]
]
];

View file

@ -72,5 +72,32 @@
"Nous Rejoindre": "",
"<span class=\"color-red\">les questions<\/span><br><span class=\"color-blue\">utiles<\/span>": "<span class=\"color-red\">les questions<\/span><br><span class=\"color-blue\">utiles<\/span>",
"Nos nouveautés": "Produits à la une",
"Nous travaillons toujours pour améliorer nos recettes et proposer des produits de meilleure qualité": "Ne ratez aucune de nos nouveautés"
"Nous travaillons toujours pour améliorer nos recettes et proposer des produits de meilleure qualité": "Ne ratez aucune de nos nouveautés",
"cookie-notice.button_customize_cookies": "Personnaliser les cookies",
"cookie-notice.button_close_cookies": "Fermer la fenêtre des cookies",
"cookie-notice.button_forbid": "Interdire",
"cookie-notice.button_allow": "Autoriser",
"cookie-notice.button_forbid_all": "Tout refuser",
"cookie-notice.button_allow_all": "Tout accepter",
"cookie-notice.button_forbid_all_title": "Refuser tous les cookies et fermer le panneau des cookies",
"cookie-notice.button_allow_all_title": "Accepter tous les cookies et fermer le panneau des cookies",
"cookie-notice.button_customize": "Personnaliser",
"cookie-notice.button_back": "Retour",
"cookie-notice.button_title_open_new_tab": "Ouvrir le lien dans un nouvel onglet",
"cookie-notice.banner_title": "Le site internet :site_name utilise des cookies !",
"cookie-notice.banner_text": "Nous utilisons des cookies pour nous assurer du bon fonctionnement de notre site et à des fins analytiques.\r Vous pouvez changer d'avis à tout moment en cliquant sur l'icône présente sur chaque page de notre site.\r En autorisant ces services tiers, vous acceptez le dépôt et la lecture de cookies et l'utilisation de technologies de suivi nécessaires à leur bon fonctionnement.",
"cookie-notice.modal_title": "Fenêtre de gestion de cookies",
"cookie-notice.panel_title": "Panneau de gestion des cookies",
"cookie-notice.panel_content": "Contenu du panneau des cookies",
"cookie-notice.panel_subtitle": "Le respect de votre vie privée est notre priorité",
"cookie-notice.panel_details": "Les fonctionnalités de ce site s'appuient sur des services proposés par des tiers. Si vous acceptez, ces tiers déposeront des cookies qui vous permettront de visualiser sur le site du contenu hébergé par ces tiers. Via ces cookies, ces tiers collecteront et utiliseront vos données de navigation pour des finalités qui leur sont propres, conformément à leur politique de confidentialité (lien ci-dessous). Cette page vous permet de donner ou de retirer votre consentement, soit globalement soit service par service.",
"cookie-notice.picture_cookie_title": "Image d'un bon gros cookie",
"cookie-notice.navigation_title": "Navigation du panneau des cookies",
"cookie-notice.custom.matomo.title": "Matomo",
"cookie-notice.custom.matomo.description": "Les services de mesure d’audience permettent de générer des statistiques de fréquentation utiles à l’amélioration du site.",
"cookie-notice.custom.matomo.labelLink": "En apprendre plus",
"cookie-notice.custom.recaptcha.title": "reCAPTACHA",
"cookie-notice.custom.recaptcha.description": "Les cookies qui sont déposés via le recaptcha sur les formulaires ont pour finalité d’empêcher que ceux-ci ne soient soumis par des robots.",
"cookie-notice.custom.recaptcha.labelLink": "En apprendre plus",
"cookie-notice.custom.recaptcha.warning": "Vous devez accepter les cookies pour envoyer le formulaire"
}

View file

@ -0,0 +1,51 @@
<?php
// * Version 4.1.0
// phpcs:disable
return [
'button_customize_cookies' => 'Personnaliser les cookies',
'button_close_cookies' => 'Fermer la fenêtre des cookies',
'button_forbid' => 'Interdire',
'button_allow' => 'Autoriser',
'button_forbid_all' => 'Tout refuser',
'button_allow_all' => 'Tout accepter',
'button_forbid_all_title' => 'Refuser tous les cookies et fermer le panneau des cookies',
'button_allow_all_title' => 'Accepter tous les cookies et fermer le panneau des cookies',
'button_customize' => 'Personnaliser',
'button_back' => 'Retour',
'button_title_open_new_tab' => 'Ouvrir le lien dans un nouvel onglet',
'banner_title' => 'Le site internet :site_name utilise des cookies !',
'banner_text' => 'Nous utilisons des cookies pour nous assurer du bon fonctionnement de notre site et à des fins analytiques.
Vous pouvez changer d’avis à tout moment en cliquant sur l’icône présente sur chaque page de notre site.
En autorisant ces services tiers, vous acceptez le dépôt et la lecture de cookies et l’utilisation de technologies de suivi nécessaires à leur bon fonctionnement.',
'modal_title' => 'Fenêtre de gestion de cookies',
'panel_title' => 'Panneau de gestion des cookies',
'panel_content' => 'Contenu du panneau des cookies',
'panel_subtitle' => 'Le respect de votre vie privée est notre priorité',
'panel_details' => 'Les fonctionnalités de ce site s’appuient sur des services proposés par des tiers. Si vous acceptez, ces tiers déposeront des cookies qui vous permettront de visualiser sur le site du contenu hébergé par ces tiers. Via ces cookies, ces tiers collecteront et utiliseront vos données de navigation pour des finalités qui leur sont propres, conformément à leur politique de confidentialité (lien ci-dessous). Cette page vous permet de donner ou de retirer votre consentement, soit globalement soit service par service.',
'picture_cookie_title' => 'Image d’un bon gros cookie',
'navigation_title' => 'Navigation du panneau des cookies',
'custom' => [
'analytics' => [
'title' => 'Google Analytics',
'description' => 'Les services de mesure d’audience permettent de générer des statistiques de fréquentation utiles à l’amélioration du site.',
],
'youtube' => [
'name' => 'Youtube',
'description' => 'Les cookies placés via les services de partage de vidéos sont destinés à permettre à l’utilisateur de visionner des contenus multimédias directement sur le site.',
'labelLink' => 'En apprendre plus',
'warning' => 'Vous devez accepter les cookies pour visionner cette vidéo',
],
'matomo' => [
'title' => 'Matomo',
'description' => 'Les services de mesure d’audience permettent de générer des statistiques de fréquentation utiles à l’amélioration du site.',
'labelLink' => 'En apprendre plus',
],
'recaptcha' => [
'title' => 'reCAPTCHA',
'description' => 'Les cookies qui sont déposés via le recaptcha sur les formulaires ont pour finalité d’empêcher que ceux-ci ne soient soumis par des robots.',
'labelLink' => 'En apprendre plus',
'warning' => 'Vous devez accepter les cookies reCAPTCHA pour envoyer le formulaire',
]
]
];

View file

@ -2,4 +2,4 @@
@import "layouts/backend/top_nav";
@import "vue-select/src/scss/vue-select.scss";
@import "vue-select/dist/vue-select.css";

View file

@ -28,6 +28,28 @@
}
}
.form-result_confirm {
background-color: #D1E7DD;
border: 1px solid #badbcc;
color: #0f5132;
border-radius: 0.375rem;
padding: 1rem;
margin: 1rem 0;
width: 100%;
text-align: center;
}
.form-result_error {
background-color: #f8d7da;
border: 1px solid #f5c2c7;
color: #842029;
border-radius: 0.375rem;
padding: 1rem;
margin: 1rem 0;
width: 100%;
text-align: center;
}
#products,
#values {
display: flex;

View file

@ -21,3 +21,16 @@ $fontcocon-regular: "cocon-regular", arial, sans-serif;
$fontbarlow-regular: "barlow-regular", arial, sans-serif;
$fontbarlow-bold: "barlow-bold", arial, sans-serif;
// * COOKIE NOTICE
// * Global
$ck-primary-color: $color-dark !default;
$ck-secondary-color: $color-second !default;
$ck-background-color: $color-main !default;
$ck-shadow-color: 0 0.5rem 1rem rgb(0 0 0 / 35%) !default;
$ck-title-font: "barlow-bold", arial, sans-serif !default;
$ck-title-size: 40px !default;
$ck-accept-color: #33aa33 !default;
$ck-deny-color: #aa3333 !default;
// * Buttons
$cn-button-bg-color: $color-main !default;

View file

@ -27,4 +27,4 @@
@import "timeline";
@import "custom";
@import "cookies-ldc";
@import "~@ldc-web/cookie-notice";

View file

@ -1,502 +0,0 @@
/* DEBUT DU PARAMETRAGE */
/* - Choix des FONTS */
/* - Changement des couleurs et des polices */
:root {
/* PARTIE A RENSEIGNER */
--primary-color: #0c1417;
--secondary-color: #ff0400;
--background-color: #fccf1d;
--shadow-color: 0 0.5rem 1rem rgb(0 0 0 / 35%);
--title-font: "barlow-bold", arial, sans-serif;
--title-size: 40px;
--text-font: "Barlow", sans-serif;
--text-size: 14px;
--accept-color: #33aa33;
--deny-color: #aa3333;
/* Position et animation des cookies */
--ldcweb-cn-position-left: 20px; /* Distance par rapport à la gauche de la fenêtre */
--ldcweb-cn-position-right: auto; /* Distance par rapport à la droite de la fenêtre */
--ldcweb-cn-animation-left: 0; /* Position gauche de base des cookies */
--ldcweb-cn-animation-right: auto; /* Position droite de base des cookies */
--ldcweb-cn-position-bottom: 20px; /* Distance par rapport au bas de la fenêtre */
--ldcweb-cn-z-index: 200;
/* PARTIE A RENSEIGNER FACULTATIF */
/* FENETRE D'ACCUEIL */
--ck-bg-color: var(--background-color);
/* Title settings */
--ck-w1-bgcolor-title: var(--background-color);
--ck-w1-font-family-title: var(--title-font);
--ck-w1-font-size-title: var(--title-size);
--ck-w1-color-title: var(--secondary-color);
/* Text settings */
--ck-w1-font-family-txt: var(--text-font);
--ck-w1-font-size-txt: var(--text-size);
--ck-w1-color-txt: var(--primary-color);
--ck-w1-color-href-hover: var(--secondary-color);
/* Button settings */
--ck-w1-color-btn: var(--secondary-color);
--ck-w1-color-btn-hover: var(--secondary-color);
--ck-w1-font-family-btn-txt: var(--text-font);
--ck-w1-font-size-btn-txt: var(--text-size);
--ck-w1-color-btn-txt: #ffffff;
--ck-w1-color-btn-txt-hover: #ffffff;
--ck-w1-color-btn-border: transparent;
--ck-w1-color-btn-border-hover: transparent;
/* FENETRE DE PERSONNALISATION */
--ck-bg-color-modal-wrapper: #ffffff;
/* Title settings */
--ck-w2-bgcolor-title: var(--background-color);
--ck-w2-font-family-title: var(--title-font);
--ck-w2-font-size-title: var(--title-size);
--ck-w2-color-title: var(--secondary-color);
/* Text settings */
--ck-w2-font-family-txt: var(--text-font);
--ck-w2-font-size-txt: var(--text-size);
--ck-w2-color-txt: var(--primary-color);
--ck-w2-color-href-hover: #000000;
/* Accept/Deny btn settings */
--ck-color-accept: #808080;
--ck-color-accept-hover: var(--accept-color);
--ck-color-deny: #808080;
--ck-color-deny-hover: var(--deny-color);
--ck-color-txt: #ffffff;
--ck-color-txt-hover: #ffffff;
/* Cookies list settings */
--ck-bgcolor-list: #e4e4e4;
--ck-font-family-list: var(--text-font);
--ck-font-size-list: var(--text-size);
--ck-color-list: #000000;
--ck-color-title: var(--secondary-color);
/* Scroll bar */
--ck-scroll-bgcolor: var(--primary-color);
--ck-scroll-barcolor: var(--secondary-color);
}
/* FIN DU PARAMETRAGE */
/* MOBILE FIRST */
#template {
display: none;
}
* {
box-sizing: border-box;
}
#ldcweb-cn.open-banner .ldcweb-cn-banner {
display: flex;
}
#ldcweb-cn.open-banner,
#ldcweb-cn.open-modal {
display: flex;
}
#ldcweb-cn p,
#ldcweb-cn a {
font-family: var(--ck-w1-font-family-txt);
font-size: var(--ck-w1-font-size-txt);
color: var(--ck-w1-color-txt);
}
#ldcweb-cn a {
text-decoration: underline;
transition: 0s;
}
#ldcweb-cn a::before {
content: none;
}
.ldcweb-cn-cookie-link {
cursor: pointer;
}
#ldcweb-cn .ldcweb-cn-banner,
#ldcweb-cn-modal .modal-wrapper {
overflow: auto;
display: flex;
flex-direction: column;
align-items: center;
}
#ldcweb-cn .ldcweb-cn-banner {
padding: 0;
margin: 0;
padding-top: 20px;
background-color: var(--ck-bg-color);
flex-direction: column;
justify-content: flex-end;
position: fixed;
left: var(--ldcweb-cn-animation-left);
right: var(--ldcweb-cn-animation-right);
bottom: calc(var(--ldcweb-cn-position-bottom) + 60px);
width: 475px;
height: auto;
max-height: 80vh;
border-radius: 10px;
z-index: var(--ldcweb-cn-z-index);
line-height: initial;
overflow: hidden;
box-shadow: var(--shadow-color);
user-select: none;
opacity: 0;
visibility: hidden;
transition: 0.3s;
}
#ldcweb-cn .ldcweb-cn-banner-open {
left: var(--ldcweb-cn-position-left);
right: var(--ldcweb-cn-position-right);
opacity: 1;
visibility: visible;
}
.ldcweb-banner-content,
.ldcweb-banner-details {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
padding: 0px 20px 0px 20px;
}
.ldcweb-banner-details {
height: 0;
transition: 0.3s;
text-align: justify;
overflow: hidden;
align-items: flex-start;
}
.ldcweb-banner-details-open {
margin-bottom: 6px;
}
#ldcweb-cn .ldcweb-banner-img {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: auto;
width: 150px;
padding-right: 20px;
}
#ldcweb-cn .ldcweb-banner-img img {
width: 100%;
}
#ldcweb-cn .ldcweb-banner-text {
flex: 2;
}
#ldcweb-cn .ldcweb-banner-title {
line-height: 0.9;
padding-bottom: 1rem;
}
#ldcweb-cn .ldcweb-banner-title p {
font-family: var(--ck-w1-font-family-title);
font-size: var(--ck-w1-font-size-title);
font-weight: bold;
color: var(--ck-w1-color-title);
text-align: left;
}
#ldcweb-cn .ldcweb-banner-para-p {
text-align: justify;
margin-bottom: 6px;
}
#ldcweb-cn .ldcweb-banner-btnDetails {
width: 100%;
margin: 0 0 20px 0;
}
#ldcweb-cn .ldcweb-banner-btnDetails-p {
cursor: pointer;
color: var(--secondary-color);
width: fit-content;
margin: 0 auto;
text-align: center;
}
#ldcweb-cn .ldcweb-banner-btns {
flex: 1;
display: flex;
flex-direction: row;
width: 100%;
cursor: pointer;
}
#ldcweb-cn .ldcweb-banner-btns .ldcweb-banner-btn-flex {
width: 66.5%;
border-top: 1px solid grey;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
text-align: center;
}
.ldcweb-banner-btn-personalize {
width: 33.5%;
border-top: 1px solid gray;
}
#ldcweb-cn .ldcweb-banner-btns .ldcweb-banner-btn-flex div {
width: 50%;
}
.ldcweb-banner-btn-accept {
border-left: 1px solid gray;
border-right: 1px solid gray;
}
#ldcweb-cn .ldcweb-banner-btns .ldcweb-banner-btn-flex .ldcweb-cn-accept {
font-weight: bolder;
color: var(--secondary-color);
}
#ldcweb-cn .ldcweb-banner-btns .ldcweb-banner-btns-btn {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
width: 100%;
height: 50px;
background-color: var(--background-color);
text-decoration: none;
font-family: var(--ck-w1-font-family-btn-txt);
font-size: var(--ck-w1-font-size-btn-txt);
color: var(--primary-color);
}
#ldcweb-cn .ldcweb-banner-btns .ldcweb-banner-btns-btn:hover {
color: var(--ck-w1-color-btn-txt-hover);
background-color: var(--ck-w1-color-btn-hover);
}
.ldcweb-btn {
position: fixed;
left: var(--ldcweb-cn-position-left);
right: var(--ldcweb-cn-position-right);
bottom: var(--ldcweb-cn-position-bottom);
z-index: var(--ldcweb-cn-z-index);
background-color: white;
padding: 8px;
border-radius: 100%;
cursor: pointer;
box-shadow: var(--shadow-color);
width: 50px;
height: 50px;
}
.ldcweb-btn-icon path {
fill: var(--secondary-color);
}
.ldcweb-btn-icon circle {
fill: var(--secondary-color);
}
.visibility {
display: none !important;
}
/* MODAL */
#ldcweb-cn-modal {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
z-index: 200;
opacity: 1;
}
#ldcweb-cn-modal .modal-wrapper {
position: relative;
max-height: 100vh;
}
#ldcweb-cn-modal .modal-wrapper > div:not(:first-of-type) {
width: 100%;
align-items: flex-end;
}
#ldcweb-cn-modal .modal-title {
padding: 0px 20px 0px 20px;
}
#ldcweb-cn-modal .modal-title * {
text-align: justify;
margin: 0;
}
#ldcweb-cn-modal .modal-title .description,
#ldcweb-cn-modal .modal-btns {
display: flex;
flex-direction: column;
align-items: center;
font-weight: normal;
line-height: initial;
}
#ldcweb-cn-modal .modal-title .description,
#ldcweb-cn-modal .modal-btns p,
#ldcweb-cn-modal .modal-btns a,
#ldcweb-cn-modal .modal-title > .subTitle {
font-family: var(--ck-w2-font-family-txt);
font-size: var(--ck-w2-font-size-txt);
color: var(--ck-w2-color-txt);
}
/* TITLE */
#ldcweb-cn-modal .modal-title .title {
font-family: var(--ck-w2-font-family-title);
font-size: var(--ck-w2-font-size-title);
font-weight: bold;
color: var(--ck-w2-color-title);
}
#ldcweb-cn-modal .modal-title > .subTitle {
color: var(--ck-w2-color-title);
margin-bottom: 6px;
}
#ldcweb-cn-modal .modal-title .title,
#ldcweb-cn-modal .modal-title > .subTitle {
text-align: center;
}
#ldcweb-cn-modal .modal-title a {
width: fit-content;
}
/* DETAILS */
#ldcweb-cn-modal .modal-details {
width: 100%;
height: 153px;
overflow-y: auto;
margin: 6px 0;
}
#ldcweb-cn-modal .modal-details ul {
display: flex;
flex-direction: column;
padding: 0 20px;
list-style: none;
}
#ldcweb-cn-modal .modal-details li > div {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
margin: 10px 0;
padding: 10px 20px;
border-radius: 20px;
border: 1px solid var(--ck-bgcolor-list);
}
#ldcweb-cn-modal .modal-details li span,
#ldcweb-cn-modal .modal-details li a,
#ldcweb-cn-modal .modal-details li label {
font-family: var(--ck-font-family-list);
font-size: var(--ck-font-size-list);
color: var(--ck-color-list);
}
#ldcweb-cn-modal .modal-details .ldcweb-cn-name {
color: var(--ck-color-title);
}
#ldcweb-cn-modal .modal-details .ldcweb-cn-infos {
display: flex;
flex-direction: column;
flex: 1;
width: 100%;
}
#ldcweb-cn-modal .modal-details .ldcweb-cn-infos span:first-of-type {
font-size: var(--ck-w1-font-size-title);
font-weight: bold;
font-family: var(--ck-w1-font-family-title);
}
#ldcweb-cn-modal .modal-details .ldcweb-cn-infos .ldcweb-cn-description {
color: var(--ck-w2-color-txt);
}
#ldcweb-cn-modal .modal-details .ldcweb-cn-infos a {
width: fit-content;
}
#ldcweb-cn-modal .modal-details .ldcweb-cn-buttons {
display: flex;
justify-content: space-around;
width: 200px;
margin-top: 6px;
}
#ldcweb-cn-modal .modal-details .ldcweb-cn-buttons div:first-of-type,
#ldcweb-cn-modal .modal-details .ldcweb-cn-buttons div:last-of-type {
transition: all 0.3s;
}
#ldcweb-cn-modal .modal-details .ldcweb-cn-buttons div:first-of-type {
background: var(--ck-color-accept);
}
#ldcweb-cn-modal .modal-details .ldcweb-cn-buttons div:last-of-type {
background: var(--ck-color-deny);
}
#ldcweb-cn-modal .modal-details .ldcweb-cn-buttons div {
display: table;
text-align: center;
margin: 0.5em;
}
#ldcweb-cn-modal
.modal-details
.ldcweb-cn-buttons
div:first-of-type
input:checked
~ label,
#ldcweb-cn-modal
.modal-details
.ldcweb-cn-buttons
div:first-of-type
input
~ label.active {
background-color: var(--ck-color-deny-hover);
}
#ldcweb-cn-modal
.modal-details
.ldcweb-cn-buttons
div:last-of-type
input:checked
~ label,
#ldcweb-cn-modal
.modal-details
.ldcweb-cn-buttons
div:last-of-type
input
~ label.active {
background-color: var(--ck-color-accept-hover);
}
#ldcweb-cn-modal .modal-details .ldcweb-cn-buttons input {
display: none;
}
#ldcweb-cn-modal .modal-details .ldcweb-cn-buttons label {
width: 100px;
display: block;
color: var(--ck-color-txt);
transition: color 0.3s;
padding: 6px 20px;
cursor: pointer;
}
/* MEDIA QUERIES */
@media (max-width: 535px) {
.ldcweb-banner-content,
#ldcweb-cn .ldcweb-banner-btns {
flex-direction: column;
}
#ldcweb-cn .ldcweb-banner-btns .ldcweb-banner-btn-flex,
#ldcweb-cn .ldcweb-banner-btns .ldcweb-banner-btn-personalize {
width: 100%;
}
#ldcweb-cn
.ldcweb-banner-btns
.ldcweb-banner-btn-flex
.ldcweb-banner-btn-deny,
#ldcweb-cn
.ldcweb-banner-btns
.ldcweb-banner-btn-flex
.ldcweb-banner-btn-accept {
width: 50%;
}
.ldcweb-banner-btn-accept {
border-left: 1px solid gray;
border-right: none;
}
#ldcweb-cn .ldcweb-cn-banner {
left: 0;
bottom: 0;
}
#ldcweb-cn .ldcweb-cn-banner {
width: 100%;
max-height: 100vh;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.ldcweb-banner-details-open {
height: 0;
}
#ldcweb-cn .ldcweb-banner-title p {
text-align: center;
}
#ldcweb-cn .ldcweb-banner-img {
padding: 0 0 20px 0;
}
}

View file

@ -1,61 +1,64 @@
<div class="forms-group">
<div class="form-group">
<label for="title">{{ __('Titre') }} *</label>
<input type="text" id="title" name="title" class="form-control" placeholder="{{ __('Titre') }} *" value="{{ old('title', $text->title ?? '') }}" required>
@include('back.modules.input-error', ['inputName'=>'title'])
<input class="form-control" id="title" name="title" type="text" value="{{ old('title', $text->title ?? '') }}"
placeholder="{{ __('Titre') }} *" required>
@include('back.modules.input-error', ['inputName' => 'title'])
</div>
<div class="form-group">
<div class="form-group">
<label for="text">{{ __('Texte') }} *</label>
<textarea class="form-control" placeholder="{{ __('Texte') }}" id="text" name="text" style="height: 150px;">{{ old('commentaire', $text->text ?? '') }}</textarea>
@include('back.modules.input-error', ['inputName'=>'text'])
<textarea class="form-control" id="text" name="text" style="height: 150px;" placeholder="{{ __('Texte') }}">{{ old('commentaire', $text->text ?? '') }}</textarea>
@include('back.modules.input-error', ['inputName' => 'text'])
</div>
</div>
@push('scripts')
<script type="text/javascript">
var editorConfig = {
removePlugins: ["Image", "ImageCaption", "ImageStyle", "ImageToolbar", "ImageUpload"],
toolbar: ['heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', '|', 'blockQuote', 'insertTable', '|', 'undo', 'redo'],
heading: {
options: [{
model: 'paragraph',
title: 'Paragraph',
class: 'ck-heading_paragraph'
<script type="text/javascript" nonce="{{ $nonce }}">
var editorConfig = {
removePlugins: ["Image", "ImageCaption", "ImageStyle", "ImageToolbar", "ImageUpload"],
toolbar: ['heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', '|', 'blockQuote', 'insertTable', '|',
'undo', 'redo'
],
heading: {
options: [{
model: 'paragraph',
title: 'Paragraph',
class: 'ck-heading_paragraph'
},
{
model: 'heading1',
view: 'h1',
title: 'Heading 1',
class: 'ck-heading_heading1'
},
{
model: 'heading2',
view: 'h2',
title: 'Heading 2',
class: 'ck-heading_heading2'
},
{
model: 'heading3',
view: 'h3',
title: 'Heading 3',
class: 'ck-heading_heading3'
},
{
model: 'heading4',
view: 'h4',
title: 'Heading 4',
class: 'ck-heading_heading4'
}
]
},
{
model: 'heading1',
view: 'h1',
title: 'Heading 1',
class: 'ck-heading_heading1'
},
{
model: 'heading2',
view: 'h2',
title: 'Heading 2',
class: 'ck-heading_heading2'
},
{
model: 'heading3',
view: 'h3',
title: 'Heading 3',
class: 'ck-heading_heading3'
},
{
model: 'heading4',
view: 'h4',
title: 'Heading 4',
class: 'ck-heading_heading4'
table: {
contentToolbar: ['tableColumn', 'tableRow', 'mergeTableCells']
}
]
},
table: {
contentToolbar: ['tableColumn', 'tableRow', 'mergeTableCells']
}
};
ClassicEditor
.create(document.querySelector('#text'), editorConfig)
.catch(error => {
console.error(error);
});
</script>
@endpush
};
ClassicEditor
.create(document.querySelector('#text'), editorConfig)
.catch(error => {
console.error(error);
});
</script>
@endpush

View file

@ -1,258 +1,306 @@
@extends('layouts.frontend')
@section('title', __('Nous contacter'))
@section('description', __("Découvrez DOUX, des produits de volailles françaises."))
@section('description', __('Découvrez DOUX, des produits de volailles françaises.'))
@section('content')
<section class="jumbotron">
<p class="maintitle ttu animate__animated fadeIn animate__slow">{{ __('Nous contacter') }}</p>
<img class="img-zoom" src="{{ asset('assets/images/contact.jpg') }}" alt="Nous contacter">
<div class="banner">
<svg id="Calque_1" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1919.76 59.99">
<section class="jumbotron">
<p class="maintitle ttu animate__animated fadeIn animate__slow">{{ __('Nous contacter') }}</p>
<img class="img-zoom" src="{{ asset('assets/images/contact.jpg') }}" alt="Nous contacter">
<div class="banner">
<svg id="Calque_1" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1919.76 59.99">
<defs>
<style>
.cls-1 {
fill: #ffffff;
}
.cls-2 {
fill: transparent;
}
</style>
</defs>
<path class="cls-1"
d="M1919.67,58c-.42.62,1,2.12-1,2-1.17-.07-2.34,0-3.5,0H0V55c3-.06,6,.08,9-.22,28.32-2.84,56.61-6,85-8.6q59.19-5.38,118.44-10c46.65-3.58,93.32-7,140-9.88,49.7-3.05,99.43-5.85,149.18-7.9,68.4-2.81,136.83-5,205.26-7.06,38.63-1.14,77.28-1.58,115.92-1.94,78.47-.74,156.93-.9,235.39.32,37.81.59,75.62,1.2,113.42,2.09q64.44,1.5,128.85,4,76.89,2.85,153.71,6.91,63.36,3.32,126.66,7.44,43.86,2.85,87.7,6,33.13,2.4,66.22,5.17,38.82,3.23,77.61,6.72c20.06,1.79,40.11,3.73,60.16,5.6Z" />
<path class="cls-2"
d="M1919.67,58l-47.21-4.36c-20-1.87-40.1-3.81-60.16-5.6q-38.79-3.47-77.61-6.72-33.09-2.74-66.22-5.17-43.83-3.18-87.7-6-63.3-4.11-126.66-7.44-76.83-4-153.71-6.91-64.41-2.4-128.85-4c-37.8-.89-75.61-1.5-113.42-2.09-78.46-1.22-156.92-1.06-235.39-.32-38.64.36-77.29.8-115.92,1.94-68.43,2-136.86,4.25-205.26,7.06-49.75,2-99.48,4.85-149.18,7.9-46.7,2.87-93.37,6.3-140,9.88q-59.27,4.54-118.44,10c-28.35,2.58-56.64,5.76-85,8.6-3,.3-6,.16-9,.22V0H1919.67Z" />
</svg>
</div>
</section>
<div class="contact-page has-bckg--grey is-flex horizontal-center container">
<svg class="p-abs" id="picto-localisation" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 171 236">
<defs>
<style>
.cls-1 {
fill: #ffffff;
}
.cls-2 {
fill: transparent;
fill-rule: evenodd;
}
</style>
</defs>
<path class="cls-1" d="M1919.67,58c-.42.62,1,2.12-1,2-1.17-.07-2.34,0-3.5,0H0V55c3-.06,6,.08,9-.22,28.32-2.84,56.61-6,85-8.6q59.19-5.38,118.44-10c46.65-3.58,93.32-7,140-9.88,49.7-3.05,99.43-5.85,149.18-7.9,68.4-2.81,136.83-5,205.26-7.06,38.63-1.14,77.28-1.58,115.92-1.94,78.47-.74,156.93-.9,235.39.32,37.81.59,75.62,1.2,113.42,2.09q64.44,1.5,128.85,4,76.89,2.85,153.71,6.91,63.36,3.32,126.66,7.44,43.86,2.85,87.7,6,33.13,2.4,66.22,5.17,38.82,3.23,77.61,6.72c20.06,1.79,40.11,3.73,60.16,5.6Z" />
<path class="cls-2" d="M1919.67,58l-47.21-4.36c-20-1.87-40.1-3.81-60.16-5.6q-38.79-3.47-77.61-6.72-33.09-2.74-66.22-5.17-43.83-3.18-87.7-6-63.3-4.11-126.66-7.44-76.83-4-153.71-6.91-64.41-2.4-128.85-4c-37.8-.89-75.61-1.5-113.42-2.09-78.46-1.22-156.92-1.06-235.39-.32-38.64.36-77.29.8-115.92,1.94-68.43,2-136.86,4.25-205.26,7.06-49.75,2-99.48,4.85-149.18,7.9-46.7,2.87-93.37,6.3-140,9.88q-59.27,4.54-118.44,10c-28.35,2.58-56.64,5.76-85,8.6-3,.3-6,.16-9,.22V0H1919.67Z" />
<path class="cls-1"
d="M85,236C60,197,0,131,0,85A84.93,84.93,0,0,1,85,0c48,0,86,38,86,85C171,131,111,197,85,236ZM85,43c24,0,43,19,43,42a42.68,42.68,0,0,1-43,43c-23,0-42-19-42-43A42.25,42.25,0,0,1,85,43Z" />
</svg>
<p>
<strong>{{ __('Adresse') }}</strong><br /><br />
DOUX FARMOR<br />
450 Route de Rosporden<br />
Le Grand Guelen<br />
29000 QUIMPER, France
</p>
</div>
</section>
<div class="container contact-page has-bckg--grey is-flex horizontal-center">
<svg id="picto-localisation" class="p-abs" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 171 236"><defs>
<style>.cls-1{fill-rule:evenodd;}</style>
</defs><path class="cls-1" d="M85,236C60,197,0,131,0,85A84.93,84.93,0,0,1,85,0c48,0,86,38,86,85C171,131,111,197,85,236ZM85,43c24,0,43,19,43,42a42.68,42.68,0,0,1-43,43c-23,0-42-19-42-43A42.25,42.25,0,0,1,85,43Z"/>
</svg>
<p>
<strong>{{ __('Adresse') }}</strong><br /><br />
DOUX FARMOR<br />
450 Route de Rosporden<br />
Le Grand Guelen<br />
29000 QUIMPER, France
</p>
</div>
<div class="container">
<div class="wrapper">
<div class="breadcrumb is-flex">
<a href="{{ route($routeprefixer . 'home') }}" class="link">{{ __('Accueil') }}</a>
</div>
<div class="header-title sectiontitle align-center p-rel">
<h2 class="punchline-module__title align-center animate__animated fadeInUp animate__slow">{!! __('Une question ? Une idée ? Un conseil ?<br>Des informations sur nos produits ?') !!}</h2>
</div>
<p class="align-center">{!! __('N\'hésitez-pas à nous contacter en renseignant le formulaire ci-dessous.<br>Nous traiterons votre demande avec la plus grande attention dans les meilleurs délais.') !!}</p>
@if(session()->has('status'))
<div class="form-result form-result_confirm">
<div class="form-result__title title title_small">{{ __('Votre message a bien été envoyé !') }}</div>
<div class="form-result__text">{{ __('Nos services mettent tout en oeuvre pour y répondre au plus vite.') }}</div>
</div>
@endif
<form id="contact-form" action="{{route($routeprefixer . 'contact.submit')}}" method="post" class="form contact__form" enctype="multipart/form-data">
@csrf
@if ($errors->any())
@foreach ($errors->all() as $error)
<div class="field__error">{{ $error }}</div>
@endforeach
<div class="container">
<div class="wrapper">
<div class="breadcrumb is-flex">
<a class="link" href="{{ route($routeprefixer . 'home') }}">{{ __('Accueil') }}</a>
</div>
<div class="header-title sectiontitle align-center p-rel">
<h2 class="punchline-module__title align-center animate__animated fadeInUp animate__slow">{!! __('Une question ? Une idée ? Un conseil ?<br>Des informations sur nos produits ?') !!}</h2>
</div>
<p class="align-center">{!! __(
'N\'hésitez-pas à nous contacter en renseignant le formulaire ci-dessous.<br>Nous traiterons votre demande avec la plus grande attention dans les meilleurs délais.',
) !!}</p>
@if (session()->has('status'))
<div class="form-result form-result_confirm">
<div class="form-result__title title title_small">{{ __('Votre message a bien été envoyé !') }}</div>
<div class="form-result__text">{{ __('Nos services mettent tout en oeuvre pour y répondre au plus vite.') }}</div>
</div>
@endif
<fieldset>
<legend>{{ __('Vos coordonnées') }} :</legend>
<form class="form contact__form" id="contact-form" action="{{ route($routeprefixer . 'contact.submit') }}" method="post"
enctype="multipart/form-data">
@csrf
@if ($errors->any())
@foreach ($errors->all() as $error)
<div class="form-result_error">{{ $error }}</div>
@endforeach
@endif
<fieldset>
<legend>{{ __('Vos coordonnées') }} :</legend>
<label class="radio-label">{{ __('Monsieur') }}
<input type="radio" checked="checked" name="civilite" value="monsieur" @if (old('civilite') === "monsieur" ) checked @endif>
<span class="checkmark"></span>
</label>
<label class="radio-label">{{ __('Madame') }}
<input type="radio" name="civilite" value="madame" @if (old('civilite') === "madame" ) checked @endif>
<span class="checkmark"></span>
</label>
<label class="radio-label">{{ __('Monsieur') }}
<input name="civilite" type="radio" value="monsieur" checked="checked"
@if (old('civilite') === 'monsieur') checked @endif>
<span class="checkmark"></span>
</label>
<label class="radio-label">{{ __('Madame') }}
<input name="civilite" type="radio" value="madame" @if (old('civilite') === 'madame') checked @endif>
<span class="checkmark"></span>
</label>
<div class="form-row">
<div class="form-group">
<label for="name">{{ __('Nom') }}* : </label>
<input type="text" name="name" id="name" minlength="2" required value="{{old('name')}}">
<div class="form-row">
<div class="form-group">
<label for="name">{{ __('Nom') }}* : </label>
<input id="name" name="name" type="text" value="{{ old('name') }}" minlength="2" required>
</div>
<div class="form-group">
<label for="lastname">{{ __('Prénom') }}* : </label>
<input id="lastname" name="lastname" type="text" value="{{ old('lastname') }}" minlength="2" required>
</div>
</div>
<div class="form-group">
<label for="lastname">{{ __('Prénom') }}* : </label>
<input type="text" name="lastname" id="lastname" minlength="2" value="{{ old('lastname') }}" required>
<div class="form-row">
<div class="form-group">
<label for="address">{{ __('Adresse') }}* : </label>
<input id="address" name="address" type="text" value="{{ old('address') }}" maxlength="255"
autocomplete="street-address" required>
</div>
<div class="form-group">
<label for="postcode">{{ __('Code postal') }}* : </label>
<input id="postcode" name="postcode" type="text" value="{{ old('postcode') }}" minlength="1" maxlength="99000"
autocomplete="postal-code" required>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="city">{{ __('Ville') }}* : </label>
<input id="city" name="city" type="text" value="{{ old('city') }}" maxlength="255"
autocomplete="address-level2" required>
</div>
<div class="form-group">
<label for="phone">{{ __('Téléphone') }}* : </label>
<input id="phone" name="phone" type="number" value="{{ old('phone') }}" min="1" max="9999999999"
autocomplete="tel" required>
</div>
<div class="form-group">
<label for="email">{{ __('Email') }}* : </label>
<input id="email" name="email" type="mail" value="{{ old('email') }}"
pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$" autocomplete="email" required>
</div>
</div>
<div class="form-row">
<div class="country">
<select class="changeLength" id="country" name="country" maxlength="255" required>
<option value="" @if (!old('country')) selected @endif>{{ __('Sélectionnez un pays') }} *
</option>
@foreach ($listCountries as $country)
<option value="{{ $country->value }}" @if (old('country') == $country->value) selected @endif>
{{ __($country->label) }}</option>
@endforeach
</select>
</div>
<div class="drom">
<select class="changeLength" id="departement" name="departement" maxlength="255">
<option value="" @if (!old('departement')) selected @endif>
{{ __('Sélectionnez un département') }} *</option>
@foreach ($listDeps as $departement)
<option value="{{ $departement->value }}" @if (old('departement') === $departement->value) selected @endif>
{{ __($departement->label) }}</option>
@endforeach
</select>
</div>
</div>
</fieldset>
<fieldset>
<legend>{{ __('Préciser votre demande') }} :</legend>
<div class="ck-button">
<label>
<input class="consoRecla" name="topic" type="radio" value="Réclamation"
@if (old('topic') == 'Réclamation') checked @endif><span>{{ __('Réclamation produit') }}</span>
</label>
<label>
<input class="otherRecla" name="topic" type="radio" value="La marque"
@if (old('topic') == 'La marque') checked @endif><span>{{ __('La marque') }}</span>
</label>
<label>
<input class="otherRecla" name="topic" type="radio" value="Contact Commercial"
@if (old('topic') == 'Contact Commercial') checked @endif><span>{{ __('Contact commercial') }}</span>
</label>
<label>
<input class="otherRecla" name="topic" type="radio" value="Autre"
@if (old('topic') == 'Autre') checked @endif><span>{{ __('Autre demande') }}</span>
</label>
</div>
<div class="form-row recla_field">
<div class="form-group">
<label for="address">{{ __('Nom du produit') }}* : </label>
<input id="product_name" name="product_name" type="text" value="{{ old('product_name') }}">
</div>
<div class="form-group">
<label for="barcode">{{ __('Code barre') }}* : </label>
<input id="barcode" name="barcode" type="number" value="{{ old('barcode') }}">
</div>
</div>
<div class="form-row recla_field">
<div class="form-group">
<label for="shop">{{ __("Lieu d'achat") }}* : </label>
<input id="shop" name="shop" type="text" value="{{ old('shop') }}">
</div>
<div class="form-group">
<label for="lot">{{ __('Numéro de lot') }}* : </label>
<input id="lot" name="lot" type="number" value="{{ old('lot') }}">
</div>
</div>
<div class="form-row recla_field">
<div class="form-group">
<label for="limit_date">{{ __('Date Limite de Consommation') }}* : </label>
<input id="limit_date" name="limit_date" type="date" value="{{ old('limit_date') }}">
</div>
<div class="form-group">
<label for="consumption_date">{{ __('Date de consommation') }}* : </label>
<input id="consumption_date" name="consumption_date" type="date" value="{{ old('consumption_date') }}">
</div>
</div>
<div>
<label for="message">{{ __('Message') }}* : </label>
<textarea id="message" name="message" cols="30" rows="10">{{ old('message') }}</textarea>
</div>
<div>
<input id="file" name="file" type="file" @if ('topic' == 'Réclamation') required @endif>
<label id="lblFile" for="file"></label>
</div>
</fieldset>
<p class="is-small">{!! __('rgpd.contact.disclaimer', ['PRIVROUTE' => route($routeprefixer . 'policy')]) !!}</P>
<div class="is-small">
<input id="rgpd" name="rgpd" type="checkbox" required>
<label for="rgpd">{{ __('rgpd.contact.acceptcgu') }}</label>
</div>
<div class="form-row">
<div class="form-group">
<label for="address">{{ __('Adresse') }}* : </label>
<input type="text" name="address" id="address" maxlength="255" value="{{ old('address') }}" autocomplete="street-address" required>
</div>
<div class="form-group">
<label for="postcode">{{ __('Code postal') }}* : </label>
<input type="text" name="postcode" id="postcode" minlength="1" maxlength="99000" value="{{ old('postcode') }}" autocomplete="postal-code" required>
</div>
<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="form-row">
<div class="form-group">
<label for="city">{{ __('Ville') }}* : </label>
<input type="text" name="city" id="city" maxlength="255" value="{{ old('city') }}" autocomplete="address-level2" required>
</div>
<div class="form-group">
<label for="phone">{{ __('Téléphone') }}* : </label>
<input type="number" name="phone" id="phone" min="1" max="9999999999" value="{{ old('phone') }}" autocomplete="tel" required>
</div>
<div class="form-group">
<label for="email">{{ __('Email') }}* : </label>
<input type="mail" name="email" id="email" pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$" value="{{ old('email') }}" autocomplete="email" required>
</div>
<div class="align-center">
<div class="g-recaptcha" data-sitekey="{{ config('services.google.recaptcha.public') }}"></div>
<input type="submit" value="Envoyer">
</div>
<div class="form-row">
<div class="country">
<select id="country" class="changeLength" maxlength="255" name="country" required>
<option value="" @if(!old('country')) selected @endif>{{ __('Sélectionnez un pays') }} *</option>
@foreach($listCountries as $country)
<option value="{{ $country->value }}" @if(old('country') == $country->value) selected @endif>{{ __($country->label) }}</option>
@endforeach
</select>
</div>
<div class="drom">
<select id="departement" class="changeLength" maxlength="255" name="departement">
<option value="" @if(!old('departement')) selected @endif>{{ __('Sélectionnez un département') }} *</option>
@foreach ($listDeps as $departement)
<option value="{{ $departement->value }}" @if(old('departement') === $departement->value) selected @endif>{{ __($departement->label) }}</option>
@endforeach
</select>
</div>
</div>
</fieldset>
<fieldset>
<legend>{{ __('Préciser votre demande') }} :</legend>
<div class="ck-button">
<label>
<input class="consoRecla" type="radio" value="Réclamation" name="topic" @if (old('topic')=="Réclamation") checked @endif><span>{{ __('Réclamation produit') }}</span>
</label>
<label>
<input class="otherRecla" type="radio" value="La marque" name="topic" @if (old('topic')=="La marque") checked @endif><span>{{ __('La marque') }}</span>
</label>
<label>
<input class="otherRecla" type="radio" value="Contact Commercial" name="topic" @if (old('topic')=="Contact Commercial") checked @endif><span>{{ __('Contact commercial') }}</span>
</label>
<label>
<input class="otherRecla" type="radio" value="Autre" name="topic" @if (old('topic')=="Autre") checked @endif><span>{{ __('Autre demande') }}</span>
</label>
</div>
<div class="form-row recla_field">
<div class="form-group">
<label for="address">{{ __('Nom du produit') }}* : </label>
<input type="text" name="product_name" id="product_name" value="{{ old('product_name') }}">
</div>
<div class="form-group">
<label for="barcode">{{ __('Code barre') }}* : </label>
<input type="number" name="barcode" id="barcode" value="{{ old('barcode') }}">
</div>
</div>
<div class="form-row recla_field">
<div class="form-group">
<label for="shop">{{ __("Lieu d'achat") }}* : </label>
<input type="text" name="shop" id="shop" value="{{ old('shop') }}">
</div>
<div class="form-group">
<label for="lot">{{ __('Numéro de lot') }}* : </label>
<input type="number" name="lot" id="lot" value="{{ old('lot') }}">
</div>
</div>
<div class="form-row recla_field">
<div class="form-group">
<label for="limit_date">{{ __('Date Limite de Consommation') }}* : </label>
<input type="date" name="limit_date" id="limit_date" value="{{ old('limit_date') }}">
</div>
<div class="form-group">
<label for="consumption_date">{{ __('Date de consommation') }}* : </label>
<input type="date" name="consumption_date" id="consumption_date" value="{{ old('consumption_date') }}">
</div>
</div>
<div>
<label for="message">{{ __('Message') }}* : </label>
<textarea name="message" id="message" cols="30" rows="10">{{ old('message') }}</textarea>
</div>
<div>
<input type="file" name="file" id="file" @if ('topic'=="Réclamation" ) required @endif>
<label for="file" id="lblFile"></label>
</div>
</fieldset>
<p class="is-small">{!! __('rgpd.contact.disclaimer', ['PRIVROUTE' => route($routeprefixer . 'policy')]) !!}</P>
<div class="is-small">
<input type="checkbox" name="rgpd" id="rgpd" required>
<label for="rgpd">{{ __('rgpd.contact.acceptcgu') }}</label>
</div>
<div class="align-center">
<div class="g-recaptcha" data-sitekey="{{ config('services.google.recaptcha.public') }}"></div>
<input type="submit" value="Envoyer">
</div>
</form>
</form>
</div>
</div>
</div>
@endsection
@push('scripts')
<script nonce="{{ $nonce }}">
function showReclaFields() {
var collection = document.getElementsByClassName('recla_field');
for(let elem of collection) {
elem.style.display = 'flex';
<script nonce="{{ $nonce }}">
function showReclaFields() {
var collection = document.getElementsByClassName('recla_field');
for (let elem of collection) {
elem.style.display = 'flex';
}
document.getElementById('lblFile').innerHTML = 'Photo de l\'emballage*';
document.getElementById('file').required = true;
}
document.getElementById('lblFile').innerHTML = 'Photo de l\'emballage*';
document.getElementById('file').required = true;
}
function hideReclaFields() {
var collection = document.getElementsByClassName('recla_field');
for(let elem of collection) {
elem.style.display = 'none';
function hideReclaFields() {
var collection = document.getElementsByClassName('recla_field');
for (let elem of collection) {
elem.style.display = 'none';
}
document.getElementById('lblFile').innerHTML = 'Insérer une pièce jointe';
document.getElementById('file').required = false;
}
document.getElementById('lblFile').innerHTML = 'Insérer une pièce jointe';
document.getElementById('file').required = false;
}
function showDromField() {
const countryList = document.getElementById('country');
const departmentList = document.getElementById('departement');
if (countryList.value=='{{ \App\Enums\Country::france()->value }}') {
departmentList.style.display = 'initial';
departmentList.required = true;
} else {
departmentList.style.display = 'none';
departmentList.required = false;
function showDromField() {
const countryList = document.getElementById('country');
const departmentList = document.getElementById('departement');
if (countryList.value == '{{ \App\Enums\Country::france()->value }}') {
departmentList.style.display = 'initial';
departmentList.required = true;
} else {
departmentList.style.display = 'none';
departmentList.required = false;
}
}
}
document.addEventListener('DOMContentLoaded', function () {
hideReclaFields();
showDromField();
@if (old('topic')=="Réclamation")
showReclaFields();
@endif
document.getElementById('country').addEventListener('change', showDromField)
});
</script>
document.addEventListener('DOMContentLoaded', function() {
hideReclaFields();
showDromField();
@if (old('topic') == 'Réclamation')
showReclaFields();
@endif
document.getElementById('country').addEventListener('change', showDromField)
});
</script>
<script nonce="{{ $nonce }}">
window.__LDC_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';
s.parentNode.insertBefore(g, s)
}(document, 'script'));
};
<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;
};
});
function onSubmit(token) {
document.getElementById("contact-form").submit();
}
</script>
function onSubmit(token) {
document.getElementById("contact-form").submit();
}
</script>
@endpush

View file

@ -12,7 +12,7 @@
<main>
@yield('content')
</main>
@include('layouts.frontend.cookie')
@include('vendor.cn-cookies')
@include('layouts.frontend.app-footer')
</div>

View file

@ -1,9 +1,16 @@
<footer>
<div class="footer-widgets is-flex p-rel">
<div class="footer-widgets__content wrapper is-flex p-abs @if (Route::current()->getName() == 'food') white-color @endif">
<svg id="picto-localisation" class="p-abs" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 171 236"><defs>
<style>.cls-1{fill-rule:evenodd;}</style>
</defs><path class="cls-1" d="M85,236C60,197,0,131,0,85A84.93,84.93,0,0,1,85,0c48,0,86,38,86,85C171,131,111,197,85,236ZM85,43c24,0,43,19,43,42a42.68,42.68,0,0,1-43,43c-23,0-42-19-42-43A42.25,42.25,0,0,1,85,43Z"/>
<svg class="p-abs" id="picto-localisation" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 171 236">
<defs>
<style>
.cls-1 {
fill-rule: evenodd;
}
</style>
</defs>
<path class="cls-1"
d="M85,236C60,197,0,131,0,85A84.93,84.93,0,0,1,85,0c48,0,86,38,86,85C171,131,111,197,85,236ZM85,43c24,0,43,19,43,42a42.68,42.68,0,0,1-43,43c-23,0-42-19-42-43A42.25,42.25,0,0,1,85,43Z" />
</svg>
<p>
DOUX FARMOR<br />
@ -13,26 +20,32 @@
</p>
</div>
@switch (Route::current()->getName())
@case('wasup')
<img src="{{ asset('assets/images/footer_marque.jpg') }}" alt="{{ __('Cuisiner en famille') }}" />
@break
@case('product')
<img src="{{ asset('assets/images/footer_product.jpg') }}" alt="{{ __('Poulet rôti') }}" />
@break
@case('products')
<img src="{{ asset('assets/images/footer_products.jpg') }}" alt="{{ __('Poulet rôti') }}" />
@break
@case('gammes')
<img src="{{ asset('assets/images/footer_gammes.jpg') }}" alt="{{ __('Grignottes de poulet') }}" />
@break
@case('news')
<img src="{{ asset('assets/images/footer_news.jpg') }}" alt="{{ __('Poulet rôti') }}" />
@break
@case('food')
<img src="{{ asset('assets/images/footer_food.jpg') }}" alt="{{ __('Cuisine de chef') }}" />
@break
@default
<img src="{{ asset('assets/images/footer_home.jpg') }}" alt="{{ __('Suggestion de poulet frit') }}" />
@case('wasup')
<img src="{{ asset('assets/images/footer_marque.jpg') }}" alt="{{ __('Cuisiner en famille') }}" />
@break
@case('product')
<img src="{{ asset('assets/images/footer_product.jpg') }}" alt="{{ __('Poulet rôti') }}" />
@break
@case('products')
<img src="{{ asset('assets/images/footer_products.jpg') }}" alt="{{ __('Poulet rôti') }}" />
@break
@case('gammes')
<img src="{{ asset('assets/images/footer_gammes.jpg') }}" alt="{{ __('Grignottes de poulet') }}" />
@break
@case('news')
<img src="{{ asset('assets/images/footer_news.jpg') }}" alt="{{ __('Poulet rôti') }}" />
@break
@case('food')
<img src="{{ asset('assets/images/footer_food.jpg') }}" alt="{{ __('Cuisine de chef') }}" />
@break
@default
<img src="{{ asset('assets/images/footer_home.jpg') }}" alt="{{ __('Suggestion de poulet frit') }}" />
@endswitch
<div class="banner footer">
<svg id="Calque_1" data-name="Calque 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1919.76 59.99">
@ -47,20 +60,22 @@
}
</style>
</defs>
<path class="cls-1" d="M1919.67,58c-.42.62,1,2.12-1,2-1.17-.07-2.34,0-3.5,0H0V55c3-.06,6,.08,9-.22,28.32-2.84,56.61-6,85-8.6q59.19-5.38,118.44-10c46.65-3.58,93.32-7,140-9.88,49.7-3.05,99.43-5.85,149.18-7.9,68.4-2.81,136.83-5,205.26-7.06,38.63-1.14,77.28-1.58,115.92-1.94,78.47-.74,156.93-.9,235.39.32,37.81.59,75.62,1.2,113.42,2.09q64.44,1.5,128.85,4,76.89,2.85,153.71,6.91,63.36,3.32,126.66,7.44,43.86,2.85,87.7,6,33.13,2.4,66.22,5.17,38.82,3.23,77.61,6.72c20.06,1.79,40.11,3.73,60.16,5.6Z" />
<path class="cls-2" d="M1919.67,58l-47.21-4.36c-20-1.87-40.1-3.81-60.16-5.6q-38.79-3.47-77.61-6.72-33.09-2.74-66.22-5.17-43.83-3.18-87.7-6-63.3-4.11-126.66-7.44-76.83-4-153.71-6.91-64.41-2.4-128.85-4c-37.8-.89-75.61-1.5-113.42-2.09-78.46-1.22-156.92-1.06-235.39-.32-38.64.36-77.29.8-115.92,1.94-68.43,2-136.86,4.25-205.26,7.06-49.75,2-99.48,4.85-149.18,7.9-46.7,2.87-93.37,6.3-140,9.88q-59.27,4.54-118.44,10c-28.35,2.58-56.64,5.76-85,8.6-3,.3-6,.16-9,.22V0H1919.67Z" />
<path class="cls-1"
d="M1919.67,58c-.42.62,1,2.12-1,2-1.17-.07-2.34,0-3.5,0H0V55c3-.06,6,.08,9-.22,28.32-2.84,56.61-6,85-8.6q59.19-5.38,118.44-10c46.65-3.58,93.32-7,140-9.88,49.7-3.05,99.43-5.85,149.18-7.9,68.4-2.81,136.83-5,205.26-7.06,38.63-1.14,77.28-1.58,115.92-1.94,78.47-.74,156.93-.9,235.39.32,37.81.59,75.62,1.2,113.42,2.09q64.44,1.5,128.85,4,76.89,2.85,153.71,6.91,63.36,3.32,126.66,7.44,43.86,2.85,87.7,6,33.13,2.4,66.22,5.17,38.82,3.23,77.61,6.72c20.06,1.79,40.11,3.73,60.16,5.6Z" />
<path class="cls-2"
d="M1919.67,58l-47.21-4.36c-20-1.87-40.1-3.81-60.16-5.6q-38.79-3.47-77.61-6.72-33.09-2.74-66.22-5.17-43.83-3.18-87.7-6-63.3-4.11-126.66-7.44-76.83-4-153.71-6.91-64.41-2.4-128.85-4c-37.8-.89-75.61-1.5-113.42-2.09-78.46-1.22-156.92-1.06-235.39-.32-38.64.36-77.29.8-115.92,1.94-68.43,2-136.86,4.25-205.26,7.06-49.75,2-99.48,4.85-149.18,7.9-46.7,2.87-93.37,6.3-140,9.88q-59.27,4.54-118.44,10c-28.35,2.58-56.64,5.76-85,8.6-3,.3-6,.16-9,.22V0H1919.67Z" />
</svg>
</div>
</div>
<div class="container footer-content align-center @if (strpos(Route::current()->getName(), 'food') !== false) blue-bg @endif">
<div class="footer-content align-center @if (strpos(Route::current()->getName(), 'food') !== false) blue-bg @endif container">
<ul>
<li><a href="{{ route($routeprefixer . 'cgu') }}">{{ __('Mentions légales') }}</a></li>
<li><a href="{{ route($routeprefixer . 'policy') }}">{{ __('Charte de confidentialité') }}</a></li>
{{--<li><a href="{{ route($routeprefixer . 'site-map') }}">{{ __('Plan du site') }}</a></li>--}}
{{-- <li><a href="{{ route($routeprefixer . 'site-map') }}">{{ __('Plan du site') }}</a></li> --}}
<li><a href="https://recrutement.ldc.fr/fr/annonces?brands=593" target="_blank">{{ __('Nous Rejoindre') }}</a></li>
<li><a href="{{ route($routeprefixer . 'contact') }}">{{ __('Contact') }}</a></li>
<li><a href="#cookies" class="ldcweb-cn-cookie-link">{{ __('Gestion des cookies') }}</a></li>
<li><a class="cn-cookie-link" href="#cookies">{{ __('Gestion des cookies') }}</a></li>
</ul>
<span>© 2022 DOUX</span>

View file

@ -1,130 +0,0 @@
<div id="ldcweb-cn">
<a class="ldcweb-btn" title="Personnaliser les cookies">
<svg class="ldcweb-btn-icon" viewBox="0 0 28 28" xmlns="http://www.w3.org/2000/svg">
<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" />
</svg>
</a>
<div id="ldcweb-banner" class="ldcweb-cn-banner">
<div class="ldcweb-banner-content">
<div class="ldcweb-banner-img">
<img src="{{ asset('assets/images/logo-doux.png') }}" alt="{{ __('Doux') }}" />
</div>
<div class="ldcweb-banner-text">
<div class="ldcweb-banner-title">
<p aria-level="h1">{{ __('rgpd.banner.title') }}</p>
</div>
<p class="ldcweb-banner-para-p" data-open="{{ __('rgpd.banner.desc.introopen') }}" data-close="{{ __('rgpd.banner.desc.introclose') }}">
{!! __('rgpd.banner.desc.introclose') !!}
</p>
</div>
</div>
<div class="ldcweb-banner-details">
<p>{!! __('rgpd.banner.desc.more', ['PRIVROUTE' => route($routeprefixer . 'policy')]) !!}</p>
</div>
<div class="ldcweb-banner-btnDetails">
<p class="ldcweb-banner-btnDetails-p" data-open="{{ __('rgpd.banner.lessdetails') }}" data-close="{{ __('rgpd.banner.moredetails') }}">{{ __('rgpd.banner.moredetails') }}</p>
</div>
<div id="ldcweb-cn-modal" class="visibility">
<div class="modal-wrapper">
<div class="modal-title">
<p class="title" aria-level="h2">{{ __('rgpd.manage.title') }}</p>
<p class="subTitle">{{ __('rgpd.manage.subtitle') }}</p>
<p class="description">{!! __('rgpd.manage.explain') !!}</p>
</div>
<div class="modal-details">
<ul id="ldcweb-cn-list">
</ul>
<div id="template">
<div>
<div class="ldcweb-cn-infos">
<span class="ldcweb-cn-name">Google Analytics (universal)</span>
<span class="ldcweb-cn-description">Ce service peut déposer 8 cookies.</span>
<a class="ldcweb-cn-link" href="#">En savoir plus</a>
</div>
<div class="ldcweb-cn-buttons">
<div class="deny" id="deny-btn">
<input type="radio" id="analytics2" name="analytics" data-name="analytics"
data-status="false">
<label for="analytics2">{{ __('rgpd.cookie.deny') }}</label>
</div>
<div class="accept" id="accept-btn">
<input type="radio" id="analytics1" name="analytics" data-name="analytics"
data-status="true">
<label for="analytics1">{{ __('rgpd.cookie.allow') }}</label>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="ldcweb-banner-btns">
<div class="ldcweb-banner-btn-flex">
<div class="ldcweb-banner-btn-deny">
<a id="ldcweb-cn-deny-banner" class="ldcweb-banner-btns-btn ldcweb-cn-deny">{{ __('rgpd.cookies.denyall') }}</a>
</div>
<div class="ldcweb-banner-btn-accept">
<a id="ldcweb-cn-accept-banner" class="ldcweb-banner-btns-btn ldcweb-cn-accept">{{ __('rgpd.cookies.allowall') }}</a>
</div>
</div>
<div class="ldcweb-banner-btn-personalize">
<a class="ldcweb-banner-btns-btn ldcweb-cn-personalize" data-open-modal="{{ __('rgpd.cookies.return') }}"
data-close-modal="{{ __('rgpd.cookies.personalize') }}">{{ __('rgpd.cookies.personalize') }}</a>
</div>
</div>
</div>
</div>
@push('scripts')
<script nonce="{{ $nonce }}">
window.LDCWebCN = new LdcwebCn({
'analytics': {
'name': "{!! __('rgpd.analytics.title') !!}",
'description': "{!! __('rgpd.analytics.desc') !!}",
'link': 'https://support.google.com/analytics/answer/6004245',
'cookies': ['_ga', '_gat_gtag_{{ str_replace('-', '_', config('google.analyticsKey')) }}',
'_gid'
],
'script': function() {
(function(d, t) {
var g = d.createElement(t),
s = d.getElementsByTagName(t)[0];
g.src =
'https://www.googletagmanager.com/gtag/js?id={{ config('google.analyticsKey') }}';
s.parentNode.insertBefore(g, s)
}(document, 'script'));
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', '{{ config('google.analyticsKey') }}');
}
},
'recaptcha': {
'name': "API - reCAPTACHA",
'description': 'Les cookies qui sont déposés via le recaptcha sur les formulaires ont pour finalité d\'empêcher que ceux-ci ne soient soumis par des robots.',
'link': 'https://policies.google.com/privacy',
'labelLink': 'En savoir plus',
'cookies': ['NID', '__Secure-3PAPISID', '__Secure-3PSID', '__Secure-3PSIDCC'],
'script': function() {
if (window.__LDC_CN_Recaptcha) {
window.__LDC_CN_Recaptcha();
}
}
},
});
</script>
@endpush

View file

@ -0,0 +1,111 @@
{{-- blade-formatter-disable --}}
@php
$site_name = Str::ucfirst(config('app.name'));
$logo_picture_url = asset('assets/images/logo-doux.png');
$logo_title_text = __('Logo du site :name', ['name' => $site_name]);
$logo_alt_text = __('Logo :name', ['name' => $site_name]);
$strings = (object)[
'modal_title' => __('cookie-notice.modal_title'),
'button_customize_cookies' => __('cookie-notice.button_customize_cookies'),
'button_close_cookies' => __('cookie-notice.button_close_cookies'),
'button_title_open_new_tab' => __('cookie-notice.button_title_open_new_tab'),
'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_forbid_all_title' => __('cookie-notice.button_forbid_all_title'),
'button_allow_all_title' => __('cookie-notice.button_allow_all_title'),
'button_back' => Str::upper(__('cookie-notice.button_back')),
'banner_title' => __('cookie-notice.banner_title', ['site_name' => $site_name]),
'banner_text' => __('cookie-notice.banner_text'),
'panel_title' => __('cookie-notice.panel_title'),
'panel_content' => __('cookie-notice.panel_content'),
'panel_subtitle' => __('cookie-notice.panel_subtitle'),
'panel_details' => __('cookie-notice.panel_details'),
'picture_cookie_title' => __('cookie-notice.picture_cookie_title'),
'navigation_title' => __('cookie-notice.navigation_title'),
];
$cookies = [];
// RECAPTCHA
$cookies['recaptcha'] = [
'name' => __('cookie-notice.custom.recaptcha.title'),
'description' => __('cookie-notice.custom.recaptcha.description'),
'link' => 'https://policies.google.com/privacy',
'labelLink' => __('cookie-notice.custom.recaptcha.labelLink'),
'cookies' => ['NID', '__Secure-3PAPISID', '__Secure-3PSID', '__Secure-3PSIDCC']
];
$cookies['recaptcha']['script'] = <<<SCRIPT
function () {
if (window.__CN_Recaptcha) {
window.__CN_Recaptcha();
}
}
SCRIPT;
// MATOMO
$cookies['matomo'] = [
'name' => __('cookie-notice.custom.matomo.title'),
'description' => __('cookie-notice.custom.matomo.description'),
'link' => 'https://fr.matomo.org/gdpr-analytics/',
'labelLink' => __('cookie-notice.custom.matomo.labelLink'),
'cookies' => ['_pk']
];
$cookies['matomo']['script'] = <<<SCRIPT
function () {
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//yl.s-web.fr/";
_paq.push(['setTrackerUrl', u+'rainbow']);
_paq.push(['setSiteId', '
SCRIPT;
$cookies['matomo']['script'] .= config("services.matomo.site_id");
$cookies['matomo']['script'] .= <<<SCRIPT
']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'unicorn'; s.parentNode.insertBefore(g,s);
})();
}
SCRIPT;
@endphp
{{-- INCLUDE TEMPLATE --}}
@include('vendor.cookie-notice-templates.standard', compact(
'site_name', 'logo_picture_url', 'logo_alt_text',
'logo_title_text', 'strings'
))
@push('scripts')
<script nonce="{{ $nonce ?? '' }}">
document.addEventListener('DOMContentLoaded', function () {
window.WebCookieNotice = {};
@foreach($cookies as $index_name => $cookie)
window.WebCookieNotice['{{ $index_name }}'] = {};
window.WebCookieNotice['{{ $index_name }}'].tmp = {};
// SCRIPT
window.WebCookieNotice['{{ $index_name }}'].tmp.script = {!! strip_tags($cookie['script']) !!};
@php unset($cookie['script']); @endphp
// FALLBACK
@if(isset($cookie['fallback']))
window.WebCookieNotice['{{ $index_name }}'].tmp.fallback = {!! strip_tags($cookie['fallback']) !!};
@php unset($cookie['fallback']); @endphp
@endif
window.WebCookieNotice['{{ $index_name }}'].conf = @json($cookie);
window.WebCookieNotice['{{ $index_name }}'].conf.script = window.WebCookieNotice['{{ $index_name }}'].tmp.script;
window.WebCookieNotice['{{ $index_name }}'].conf.fallback = window.WebCookieNotice['{{ $index_name }}'].tmp.fallback;
window.WebCookieNotice['{{ $index_name }}'] = window.WebCookieNotice['{{ $index_name }}'].conf;
@endforeach
window.WebCookieNotice = new window.CookieNotice(window.WebCookieNotice);
});
</script>
@endpush

View file

@ -0,0 +1,82 @@
<div id="cn-wrapper" title="{{ $strings->modal_title }}" role="alertdialog" tabindex="-1">
<button id="cn-cookie-btn" title="{{ $strings->button_customize_cookies }}">
{{-- COOKIE SVG --}}
<svg viewBox="0 0 28 28" xmlns="http://www.w3.org/2000/svg">
<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" />
</svg>
</button>
{{-- BANNER --}}
<div id="cn-banner" tabindex="-1">
<div class="cn-modal-top-line">
<button id="cn-close-modal" title="{{ $strings->button_close_cookies }}">X</button>
</div>
{{-- CONTENT VIEW --}}
<div class="cn-content" title="{{ $strings->panel_content }}" tabindex="0">
{{-- 1ST PAGE BANNER --}}
<div class="cn-banner-content">
<div class="cn-banner-img">
<img src="{{ $logo_picture_url }}" title="{{ $logo_title_text }}" alt="{{ $logo_alt_text }}">
</div>
<div class="cn-banner-text">
<div class="cn-banner-title">
<span>{!! nl2br(e($strings->banner_title)) !!}</span>
</div>
<div class="cn-banner-para-p">
<p>{!! nl2br(e($strings->banner_text)) !!}</p>
</div>
</div>
</div>
{{-- 2ND PAGE CUSTOMIZE PANEL --}}
<div class="cn-modal-container d-none">
<p class="cn-modal-title" aria-level="h2">{{ $strings->panel_title }}</p>
<p class="cn-modal-subtitle">{!! nl2br(e($strings->panel_subtitle)) !!}</p>
<p class="cn-modal-description">{!! nl2br(e($strings->panel_details)) !!}</p>
<div class="cn-modal-wrapper">
{{-- COOKIES LIST --}}
<ul id="cn-modal-list"></ul>
</div>
</div>
</div>
{{-- NAV BAR --}}
<div class="cn-nav" title="{{ $strings->navigation_title }}" role="navigation">
<button class="cn-banner-btn cn-deny" id="cn-deny-banner"
title="{{ $strings->button_forbid_all_title }}">{{ $strings->button_forbid_all }}</button>
<button class="cn-banner-btn cn-accept" id="cn-accept-banner"
title="{{ $strings->button_allow_all_title }}">{{ $strings->button_allow_all }}</button>
<button class="cn-banner-btn cn-custom" id="cn-settings-banner" data-open-modal="{{ $strings->button_back }}"
data-close-modal="{{ $strings->button_customize }}">{{ $strings->button_customize }}</button>
</div>
{{-- COOKIE LIST LI TEMPLATE --}}
<div id="cn-li-template">
<div class="cn-cookie-wrapper">
<div class="cn-cookie-infos">
<span class="cn-cookie-name">#name</span>
<span class="cn-cookie-description">#description</span>
<a class="cn-cookie-link" title="{{ $strings->button_title_open_new_tab }}" target="blank">#link</a>
</div>
<div class="cn-cookie-buttons">
<div class="deny">
<input id="" name="" data-name="" data-status="false" type="radio">
<label for="" role="button" tabindex="0">{{ $strings->button_forbid }}</label>
</div>
<div class="accept">
<input id="" name="" data-name="" data-status="true" type="radio">
<label for="" role="button" tabindex="0">{{ $strings->button_allow }}</label>
</div>
</div>
</div>
</div>
</div>
</div>

View file

@ -114,58 +114,60 @@ Route::prefix('bo')
}
);
$langs = ['en', 'es', ''];
if (!app()->runningInConsole()) {
$langs = ['en', 'es', ''];
foreach ($langs as $lang) {
Route::middleware(['front-end-globals'])
->prefix($lang)
->name($lang == '' ? '' : $lang . '.')
->group(
function () use ($lang) {
Route::get('/', [ControllersHomeController::class, 'index'])->name('home');
foreach ($langs as $lang) {
Route::middleware(['front-end-globals'])
->prefix($lang)
->name($lang == '' ? '' : $lang . '.')
->group(
function () use ($lang) {
Route::get('/', [ControllersHomeController::class, 'index'])->name('home');
Route::get(
'/' . Str::slug(Lang::get('urls.marque', [], $lang)),
[ControllersMarqueController::class, 'index']
)->name('wasup');
Route::get(
'/' . Str::slug(Lang::get('urls.gammes', [], $lang)),
[ControllersGammesController::class, 'index']
)->name('gammes.index');
Route::get(
'/' . Str::slug(Lang::get('urls.gamme', [], $lang)) . '/{gammeSlug:slug}',
[ControllersGammesController::class, 'show']
)->name('gammes.show');
Route::get(
'/' . Str::slug(Lang::get('urls.produit', [], $lang)) . '/{gammeSlug:slug}/{productSlug:slug}',
[ControllersProductsController::class, 'show']
)->name('product.show');
Route::get(
'/' . Str::slug(Lang::get('urls.news', [], $lang)),
[ControllersNewsController::class, 'index']
)->name('news');
Route::get(
'/' . Str::slug(Lang::get('urls.food-service', [], $lang)),
[ControllersFoodServiceController::class, 'index']
)->name('food');
Route::get(
'/' . Str::slug(Lang::get('urls.legals', [], $lang)),
[ControllersLegalsController::class, 'index']
)->name('cgu');
Route::get(
'/' . Str::slug(Lang::get('urls.policy', [], $lang)),
[ControllersPolicyController::class, 'index']
)->name('policy');
Route::get(
'/' . Str::slug(Lang::get('urls.search', [], $lang)),
[ControllersProductsController::class, 'search']
)->name('search');
// Classic.
Route::get(
'/' . Str::slug(Lang::get('urls.contact', [], $lang)),
[ControllersContactController::class, 'contact']
)->name('contact');
Route::post('/contact', [ControllersContactController::class, 'contactSubmit'])->name('contact.submit');
}
);
}//end foreach
Route::get(
'/' . Str::slug(Lang::get('urls.marque', [], $lang)),
[ControllersMarqueController::class, 'index']
)->name('wasup');
Route::get(
'/' . Str::slug(Lang::get('urls.gammes', [], $lang)),
[ControllersGammesController::class, 'index']
)->name('gammes.index');
Route::get(
'/' . Str::slug(Lang::get('urls.gamme', [], $lang)) . '/{gammeSlug:slug}',
[ControllersGammesController::class, 'show']
)->name('gammes.show');
Route::get(
'/' . Str::slug(Lang::get('urls.produit', [], $lang)) . '/{gammeSlug:slug}/{productSlug:slug}',
[ControllersProductsController::class, 'show']
)->name('product.show');
Route::get(
'/' . Str::slug(Lang::get('urls.news', [], $lang)),
[ControllersNewsController::class, 'index']
)->name('news');
Route::get(
'/' . Str::slug(Lang::get('urls.food-service', [], $lang)),
[ControllersFoodServiceController::class, 'index']
)->name('food');
Route::get(
'/' . Str::slug(Lang::get('urls.legals', [], $lang)),
[ControllersLegalsController::class, 'index']
)->name('cgu');
Route::get(
'/' . Str::slug(Lang::get('urls.policy', [], $lang)),
[ControllersPolicyController::class, 'index']
)->name('policy');
Route::get(
'/' . Str::slug(Lang::get('urls.search', [], $lang)),
[ControllersProductsController::class, 'search']
)->name('search');
// Classic.
Route::get(
'/' . Str::slug(Lang::get('urls.contact', [], $lang)),
[ControllersContactController::class, 'contact']
)->name('contact');
Route::post('/contact', [ControllersContactController::class, 'contactSubmit'])->name('contact.submit');
}
);
}//end foreach
}//end if

0
storage/app/public/.gitignore vendored Normal file → Executable file
View file