feat: ✨ add tdf static pages
This commit is contained in:
parent
10fa9c0b43
commit
011884cf13
31 changed files with 1545 additions and 353 deletions
|
|
@ -8,20 +8,22 @@ enum InputType: int
|
|||
{
|
||||
use BaseEnum;
|
||||
|
||||
case boolean = 1;
|
||||
case dropdownArray = 2;
|
||||
case email = 3;
|
||||
case image = 4;
|
||||
case imageArray = 5;
|
||||
case labelArray = 6;
|
||||
case miniblocArray = 7;
|
||||
case number = 8;
|
||||
case selectEnum = 9;
|
||||
case password = 10;
|
||||
case string = 11;
|
||||
case text = 12;
|
||||
case url = 13;
|
||||
case videoVimeo = 14;
|
||||
case videoYoutube = 15;
|
||||
case video = 16;
|
||||
case boolean = 1;
|
||||
case dropdownArray = 2;
|
||||
case email = 3;
|
||||
case image = 4;
|
||||
case imageArray = 5;
|
||||
case labelArray = 6;
|
||||
case miniblocArray = 7;
|
||||
case number = 8;
|
||||
case selectEnum = 9;
|
||||
case password = 10;
|
||||
case string = 11;
|
||||
case text = 12;
|
||||
case url = 13;
|
||||
case videoVimeo = 14;
|
||||
case videoYoutube = 15;
|
||||
case video = 16;
|
||||
case slider = 17;
|
||||
case selectImageVideo = 18;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ enum StaticPageType: int
|
|||
case exitOutside = 23;
|
||||
case ouiCBon = 24;
|
||||
case ourFarms = 25;
|
||||
case tdf = 26;
|
||||
|
||||
/**
|
||||
* Optionnal labels definition.
|
||||
|
|
@ -64,7 +65,8 @@ enum StaticPageType: int
|
|||
self::rules->name => 'Règlement du jeu',
|
||||
self::exitOutside->name => 'Sortir à l\'extérieur',
|
||||
self::ouiCBon->name => 'Oui c\'est bon',
|
||||
self::ourFarms->name => 'Nos élevages'
|
||||
self::ourFarms->name => 'Nos élevages',
|
||||
self::tdf->name => 'Tour de France'
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -43,9 +43,19 @@ class StaticPageController extends Controller
|
|||
public function update(UpdateStaticPageRequest $request, StaticPage $static_page): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request, $static_page) {
|
||||
$validated = $request->validated();
|
||||
$data = $static_page->data;
|
||||
|
||||
foreach ($validated['data'] as $key => $input) {
|
||||
if (isset($input['value']) && is_array($input['value'])) {
|
||||
$data[$key]['value'] = $input['value'];
|
||||
}
|
||||
}
|
||||
|
||||
$static_page->data = $data;
|
||||
$static_page->fill(array_replace_recursive(
|
||||
$static_page->getFillableFields($static_page),
|
||||
$request->validated()
|
||||
$validated
|
||||
));
|
||||
|
||||
if ($static_page->saveOrFail()) {
|
||||
|
|
@ -73,7 +83,7 @@ class StaticPageController extends Controller
|
|||
->map(fn($page) => $page->data['common_section'] ?? null)
|
||||
->filter()
|
||||
->first();
|
||||
|
||||
|
||||
return view('bo.pages.static_pages.common_section.edit', [
|
||||
'commonSection' => $commonSection,
|
||||
]);
|
||||
|
|
@ -88,17 +98,17 @@ class StaticPageController extends Controller
|
|||
public function updateCommonSection(UpdateCommonSectionRequest $request): RedirectResponse
|
||||
{
|
||||
$pages = StaticPage::whereIn('type', StaticPageType::getBreedingValues())->get();
|
||||
|
||||
|
||||
try {
|
||||
DB::transaction(function () use ($pages, $request) {
|
||||
foreach ($pages as $page) {
|
||||
$data = $page->data ?? [];
|
||||
|
||||
|
||||
$data['common_section'] = [
|
||||
'title' => $request->validated('title'),
|
||||
'content' => $request->validated('content'),
|
||||
];
|
||||
|
||||
|
||||
$page->data = $data;
|
||||
$page->saveOrFail();
|
||||
}
|
||||
|
|
@ -110,7 +120,7 @@ class StaticPageController extends Controller
|
|||
->with('error', __('crud.messages.cannot_be_updated', [
|
||||
'model' => Str::ucfirst(__('validation.custom.common_section_part'))]));
|
||||
}
|
||||
|
||||
|
||||
return redirect()
|
||||
->route('bo.static_page.sections.edit')
|
||||
->with('success', __('crud.messages.has_been_updated', [
|
||||
|
|
|
|||
|
|
@ -141,4 +141,15 @@ class StaticPageController extends Controller
|
|||
$videoModels = Video::get6PublishedVideosOrderedWithProducts();
|
||||
return view('fo.pages.saga', compact('staticPageModel', 'videoModels'));
|
||||
}
|
||||
|
||||
/**
|
||||
* TDF page.
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function tdf(): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$staticPageModel = StaticPage::getCachedStaticPage(StaticPageType::tdf);
|
||||
return view('fo.pages.tdf', compact('staticPageModel'));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ namespace App\Http\Requests\Bo;
|
|||
use App\Enums\InputType;
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
abstract class UpdateMiniCrudRequest extends FormRequest
|
||||
|
|
@ -203,6 +204,36 @@ abstract class UpdateMiniCrudRequest extends FormRequest
|
|||
$rules = array_merge($rules, [
|
||||
"data.$iptName.value" => 'boolean'
|
||||
]);
|
||||
break;
|
||||
case InputType::slider->value:
|
||||
foreach ($input['columns'] as $column) {
|
||||
$columnId = $column['id'];
|
||||
$validation = $column['validation'] ?? '';
|
||||
|
||||
if (!empty($validation)) {
|
||||
$rules["data.$iptName.value.*.$columnId"] = $validation;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InputType::selectImageVideo->value:
|
||||
if (Arr::exists($this->input("data.$iptName.value"), 'picture')) {
|
||||
$rules = array_merge($rules, [
|
||||
"data.$iptName.value.picture" => "required|array",
|
||||
"data.$iptName.value.picture.path" => "required|image|mimes:png,jpg,jpeg|dimensions:width=620,height=348",
|
||||
"data.$iptName.value.picture.alt" => "required|string|between:3,255",
|
||||
"data.$iptName.value.picture.title" => "required|string|between:3,255",
|
||||
]);
|
||||
}
|
||||
|
||||
if (Arr::exists($this->input("data.$iptName.value"), 'video')) {
|
||||
$rules = array_merge($rules, [
|
||||
"data.$iptName.value.video" => "required|array",
|
||||
"data.$iptName.value.video.id" => "required|string",
|
||||
"data.$iptName.value.video.alt" => "required|string|between:3,255",
|
||||
"data.$iptName.value.video.title" => "required|string|between:3,255",
|
||||
]);
|
||||
}
|
||||
|
||||
break;
|
||||
} //end switch
|
||||
} //end foreach
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@ class ViewServiceProvider extends ServiceProvider
|
|||
['name' => 'exitOutsideStaticPageModel', 'value' => StaticPage::getCachedStaticPage(StaticPageType::exitOutside)],
|
||||
['name' => 'ouiCestBonStaticPageModel', 'value' => StaticPage::getCachedStaticPage(StaticPageType::ouiCBon)],
|
||||
['name' => 'ourFarmsStaticPageModel', 'value' => StaticPage::getCachedStaticPage(StaticPageType::ourFarms)],
|
||||
['name' => 'tdfStaticPageModel', 'value' => StaticPage::getCachedStaticPage(StaticPageType::tdf)],
|
||||
])->map(function ($array) {
|
||||
View::share($array['name'], (function () use ($array) {
|
||||
return $array['value'] ?: null;
|
||||
|
|
|
|||
|
|
@ -171,6 +171,20 @@ trait MiniCrudModel
|
|||
case InputType::url->value:
|
||||
ToolboxHelper::assertNoInternalBoUrls('content', $input['value']);
|
||||
break;
|
||||
case InputType::slider->value:
|
||||
if (!is_array($data[$o]['value'])) break;
|
||||
foreach ($data[$o]['value'] as $index => $item) {
|
||||
if (isset($item['picture']) && $item['picture'] instanceof \Illuminate\Http\UploadedFile) {
|
||||
$data[$o]['value'][$index]['picture'] = \preg_replace(
|
||||
'/^\/|^/',
|
||||
'',
|
||||
FileStorageHelper::storeFile($this, $item['picture'], true)
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InputType::selectImageVideo->value:
|
||||
break;
|
||||
default:
|
||||
throw new \ErrorException(sprintf(
|
||||
'Unknown input Type %s',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,612 @@
|
|||
<?php
|
||||
|
||||
use App\Enums\InputType;
|
||||
use App\Enums\StaticPageType;
|
||||
use App\Models\StaticPage;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// TDF
|
||||
$data = [
|
||||
'highlight_text' => [
|
||||
'label' => 'Texte de l\'encart',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'TOUR DE FRANCE 2025',
|
||||
'validate' => 'required|string|between:3,20',
|
||||
'required' => true
|
||||
],
|
||||
'banner_title' => [
|
||||
'label' => 'Titre de la bannière',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Le Gaulois en selle pour le tour de France',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'banner_picture' => [
|
||||
'label' => 'Logo de la bannière',
|
||||
'inputType' => 4,
|
||||
'dimensions' => [
|
||||
'width' => 100,
|
||||
'height' => 300
|
||||
],
|
||||
'alt' => 'Logo volaille officielle de Le Gaulois et le Tour de France',
|
||||
'title' => 'Logo volaille officielle de Le Gaulois et le Tour de France',
|
||||
'value' => '',
|
||||
'validate' => 'required',
|
||||
'required' => true
|
||||
],
|
||||
'banner_button_title' => [
|
||||
'label' => 'Titre du bouton n°1',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Le Gaulois et le Tour de France',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'banner_button_title_2' => [
|
||||
'label' => 'Titre du bouton n°2',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Au cœur de la caravane le Gaulois',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'banner_picture_author' => [
|
||||
'label' => 'Nom du photographe',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Crédit photo - ASO Aurélien Vialatte',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'play_title' => [
|
||||
'label' => 'Titre de la section n°2',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Jouez et tentez de gagner !',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'play_description' => [
|
||||
'label' => 'Description de la section n°2',
|
||||
'inputType' => InputType::text->value,
|
||||
'value' => '<p>Participez à notre jeu 100% gagnant Le Gaulois pendant le Tour de France 2025.</p>',
|
||||
'validate' => 'required|string|min:15',
|
||||
'required' => true
|
||||
],
|
||||
'play_picture' => [
|
||||
'label' => 'Logo de la section n°2',
|
||||
'inputType' => 4,
|
||||
'dimensions' => [
|
||||
'width' => 200,
|
||||
'height' => 125
|
||||
],
|
||||
'alt' => '100% Gagnant',
|
||||
'title' => '100% Gagnant',
|
||||
'value' => '',
|
||||
'validate' => 'required',
|
||||
'required' => true
|
||||
],
|
||||
'play_btn_text' => [
|
||||
'label' => 'Texte du bouton',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Je tente ma chance !',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'play_btn_url' => [
|
||||
'label' => 'Lien du bouton',
|
||||
'inputType' => InputType::url->value,
|
||||
"value" => "https://www.legauloistourdefrance.fr",
|
||||
"validate" => "required|string|url:http,https",
|
||||
'required' => true
|
||||
],
|
||||
'prize_title_1' => [
|
||||
'label' => 'Texte du lot n°1',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Ensembles TV + Home Cinema',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'prize_picture_1' => [
|
||||
'label' => 'Image du lot n°1',
|
||||
'inputType' => 4,
|
||||
'dimensions' => [
|
||||
'width' => 130,
|
||||
'height' => 100
|
||||
],
|
||||
'alt' => 'Ensemble TV-Home cinéma à gagner pendant le jeu TDF 100% gagnant Le Gaulois',
|
||||
'title' => '5 Ensembles TV-Home cinéma à gagner',
|
||||
'value' => '',
|
||||
'validate' => 'required',
|
||||
'required' => true
|
||||
],
|
||||
'prize_title_2' => [
|
||||
'label' => 'Texte du lot n°2',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Casques audios oreilles libres',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'prize_picture_2' => [
|
||||
'label' => 'Image du lot n°2',
|
||||
'inputType' => 4,
|
||||
'dimensions' => [
|
||||
'width' => 130,
|
||||
'height' => 100
|
||||
],
|
||||
'alt' => 'Casques audios oreilles libres à gagner pendant le jeu TDF 100% gagnant Le Gaulois',
|
||||
'title' => '40 Casques audios oreilles libres à gagner',
|
||||
'value' => '',
|
||||
'validate' => 'required',
|
||||
'required' => true
|
||||
],
|
||||
'prize_title_3' => [
|
||||
'label' => 'Texte du lot n°3',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Bons d\'achat',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'prize_picture_3' => [
|
||||
'label' => 'Image du lot n°3',
|
||||
'inputType' => 4,
|
||||
'dimensions' => [
|
||||
'width' => 130,
|
||||
'height' => 100
|
||||
],
|
||||
'alt' => 'Bons de réduction à gagner pendant le jeu TDF 100% gagnant Le Gaulois',
|
||||
'title' => 'Milliers de bons d\'achat à gagner',
|
||||
'value' => '',
|
||||
'validate' => 'required',
|
||||
'required' => true
|
||||
],
|
||||
"play_display_section" => [
|
||||
"label" => "Afficher la section n°2",
|
||||
"inputType" => InputType::boolean->value,
|
||||
"value" => true,
|
||||
"validate" => "required|boolean",
|
||||
'required' => true
|
||||
],
|
||||
'find_us_title' => [
|
||||
'label' => 'Titre de la section n°3',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Venez nous retrouver sur le parcours du Tour de France',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'find_us_description' => [
|
||||
'label' => 'Description de la section n°3',
|
||||
'inputType' => InputType::text->value,
|
||||
'value' => '<p>Participez à notre jeu 100% gagnant Le Gaulois pendant le Tour de France 2025.</p>',
|
||||
'validate' => 'required|string|min:15',
|
||||
'required' => true
|
||||
],
|
||||
'find_us_picture' => [
|
||||
'label' => 'Pictogramme de la section n°3',
|
||||
'inputType' => 4,
|
||||
'dimensions' => [
|
||||
'width' => 50,
|
||||
'height' => 70
|
||||
],
|
||||
'alt' => 'Point d\'exclamation',
|
||||
'title' => 'Point d\'exclamation',
|
||||
'value' => '',
|
||||
'validate' => 'required',
|
||||
'required' => true
|
||||
],
|
||||
'find_us_btn_text_1' => [
|
||||
'label' => 'Texte du bouton n°1',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Télécharger la pancarte',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'find_us_btn_url_1' => [
|
||||
'label' => 'Lien du bouton n°1',
|
||||
'inputType' => InputType::url->value,
|
||||
"value" => "https://www.legaulois.fr/tdf-downloads/Pancarte.pdf",
|
||||
"validate" => "required|string|url:http,https",
|
||||
'required' => true
|
||||
],
|
||||
'find_us_btn_text_2' => [
|
||||
'label' => 'Texte du bouton n°2',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Télécharger des coloriages',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'find_us_btn_url_2' => [
|
||||
'label' => 'Lien du bouton n°2',
|
||||
'inputType' => InputType::url->value,
|
||||
"value" => "https://www.legaulois.fr/tdf-downloads/COLORIAGE-Avril-2024.pdf",
|
||||
"validate" => "required|string|url:http,https",
|
||||
'required' => true
|
||||
],
|
||||
'find_us_picture_1' => [
|
||||
'label' => 'Image n°1 de la section n°3',
|
||||
'inputType' => 4,
|
||||
'dimensions' => [
|
||||
'width' => 300,
|
||||
'height' => 220
|
||||
],
|
||||
'alt' => 'Chars de la caravane Le Gaulois',
|
||||
'title' => 'Caravane Le Gaulois au mileu des supporters du Tour de France',
|
||||
'value' => '',
|
||||
'validate' => 'required',
|
||||
'required' => true
|
||||
],
|
||||
'find_us_picture_2' => [
|
||||
'label' => 'Image n°2 de la section n°3',
|
||||
'inputType' => 4,
|
||||
'dimensions' => [
|
||||
'width' => 300,
|
||||
'height' => 220
|
||||
],
|
||||
'alt' => 'Char Cuisson Express Le Gaulois',
|
||||
'title' => 'Char cocotte Cuisson Express traversant un pont lors d\'une étape du Tour de France',
|
||||
'value' => '',
|
||||
'validate' => 'required',
|
||||
'required' => true
|
||||
],
|
||||
'find_us_picture_author' => [
|
||||
'label' => 'Nom du photographe',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Crédit photo - ASO Aurélien Vialatte',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'tdf_title' => [
|
||||
'label' => 'Titre de la section n°4',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Le Gaulois et le Tour de France',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'tdf_subtitle_1' => [
|
||||
'label' => 'Sous-titre n°1 de la section n°4',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Plus de 10 années',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'tdf_subtitle_2' => [
|
||||
'label' => 'Sous-titre n°2 de la section n°4',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => ' de complicité avec le public',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'tdf_description' => [
|
||||
'label' => 'Description de la section n°4',
|
||||
'inputType' => InputType::text->value,
|
||||
'value' => '<p><strong>Les chars « Cocottes » sont devenus emblématiques de la caravane du Tour de France.</strong> <strong>Dix-huit caravaniers passionnés</strong>, dont huit femmes et dix hommes de tous âges et venus de différentes régions de France, auront l\'opportunité unique de piloter les mythiques « Cocottes » à travers le pays. Représentant <strong>la diversité et l\'esprit de partage</strong>, ces caravaniers formeront une <strong>véritable famille</strong> pendant toute la durée du Tour, <strong>unis par leur amour du sport et leur engagement envers Le Gaulois.</strong> <br> <br>Les huit chars Le Gaulois, représentant les produits phares de la marque, offrent au public l\'occasion de découvrir ou redécouvrir la diversité des produits proposés : <strong>Crousty Chicken, Oui c\'est Bon !, Cordon Bleu, Filets de Poulet Rôti, Blanc de Poulet Sortant à l\'Extérieur, et Le Filet de Poulet Tranché Cuisson Express</strong> seront à l\'honneur. Deux chars multiproduits, mettant en avant la diversité de la gamme, défileront également en tête de cortège avec à leur bord l\'animateur Arthur pour enflammer les foules gauloises. En fin de défilé, le char « Roule ma Poule » viendra clore le spectacle, un clin d\'œil toujours apprécié du public. <br><br> Les chars iront à la rencontre des Français pour distribuer plus de 600 000 goodies Le Gaulois dans une atmosphère joyeuse et conviviale. Cette année, la marque offrira des <strong>capes supporters, des magnets décapsuleurs, et des milliers de bons de réduction</strong> pour découvrir les produits Le Gaulois en magasin.</p>',
|
||||
'validate' => 'required|string|min:15',
|
||||
'required' => true
|
||||
],
|
||||
'tdf_media' => [
|
||||
'label' => 'Media de la section n°3',
|
||||
'inputType' => InputType::selectImageVideo->value,
|
||||
'value' => '',
|
||||
'validate' => 'required|array',
|
||||
'required' => true
|
||||
],
|
||||
'discover_title_1' => [
|
||||
'label' => 'Titre n°1 de la section n°5',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Découvrez',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'discover_title_2' => [
|
||||
'label' => 'Titre n°2 de la section n°5',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'nos chars "cocottes"',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'discover_items' => [
|
||||
'label' => 'Slider de la section n°5',
|
||||
'inputType' => InputType::slider->value,
|
||||
'value' => '',
|
||||
'validate' => 'required|array|between:2,10',
|
||||
'required' => true,
|
||||
'columns' => [
|
||||
[
|
||||
'id' => 'picture',
|
||||
'type' => 'picture',
|
||||
'placeholder' => Str::ucFirst(__('validation.custom.picture')),
|
||||
'validation' => 'required',
|
||||
'required' => true
|
||||
],
|
||||
[
|
||||
'id' => 'picture_alt',
|
||||
'type' => 'text',
|
||||
'placeholder' => Str::ucFirst(__('validation.custom.picture_alt')),
|
||||
'validation' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
[
|
||||
'id' => 'picture_title',
|
||||
'type' => 'text',
|
||||
'placeholder' => Str::ucFirst(__('validation.custom.picture_title')),
|
||||
'validation' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
[
|
||||
'id' => 'subtitle',
|
||||
'type' => 'text',
|
||||
'placeholder' => Str::ucFirst(__('validation.custom.subtitle')),
|
||||
'validation' => 'sometimes|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
[
|
||||
'id' => 'description',
|
||||
'type' => 'wysiwyg',
|
||||
'placeholder' => Str::ucFirst(__('validation.attributes.description')),
|
||||
'validation' => 'required|string|min:15',
|
||||
'required' => true
|
||||
],
|
||||
],
|
||||
'itemLimit' => [2, 10],
|
||||
'imageSizes' => [600, 450],
|
||||
],
|
||||
'heart_title' => [
|
||||
'label' => 'Titre de la section n°6',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Au cœur de la caravane Le Gaulois',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'heart_subtitle' => [
|
||||
'label' => 'Sous-titre de la section n°6',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Nos petites anecdotes',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'heart_picture' => [
|
||||
'label' => 'Image de fond de la section n°6',
|
||||
'inputType' => 4,
|
||||
'dimensions' => [
|
||||
'width' => 1020,
|
||||
'height' => 680
|
||||
],
|
||||
'alt' => 'Char \'La crousty mobile\' qui traverse un village français pendant le Tour de France',
|
||||
'title' => 'Char de la caravane Le Gaulois',
|
||||
'value' => '',
|
||||
'validate' => 'required',
|
||||
'required' => true
|
||||
],
|
||||
'heart_picture_author' => [
|
||||
'label' => 'Nom du photographe',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Crédit photo - ASO Aurélien Vialatte',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'fun_facts_title_1' => [
|
||||
'label' => 'Titre de l\'anecdote n°1',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'La caravane par tous les temps !',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'fun_facts_description_1' => [
|
||||
'label' => 'Description de l\'anecdote n°1',
|
||||
'inputType' => InputType::text->value,
|
||||
'value' => '<p>Le 26 juillet 2019, lors de l\'étape Saint-Jean-de-Maurienne et Tignes, les chars terminent leur parade quand un orage de grêle s\'invite et entraîne une coulée de boue qui bloque la route et l\'accès aux cyclistes. L\'organisation décide l\'arrêt de l\'étape et marquera l\'histoire du Tour de France.</p>',
|
||||
'validate' => 'required|string|min:15',
|
||||
'required' => true
|
||||
],
|
||||
'fun_facts_picture_1' => [
|
||||
'label' => 'Pictogramme de l\'anecdote n°1',
|
||||
'inputType' => 4,
|
||||
'dimensions' => [
|
||||
'width' => 80,
|
||||
'height' => 80
|
||||
],
|
||||
'alt' => 'Pictogramme d\'un soleil pour les anecdoctes météo sur le Tour de France',
|
||||
'title' => 'Pictogramme d\'un soleil',
|
||||
'value' => '',
|
||||
'validate' => 'required',
|
||||
'required' => true
|
||||
],
|
||||
'fun_facts_title_2' => [
|
||||
'label' => 'Titre de l\'anecdote n°2',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'La transmission d\'une passion entre Père & Fils !',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'fun_facts_description_2' => [
|
||||
'label' => 'Description de l\'anecdote n°2',
|
||||
'inputType' => InputType::text->value,
|
||||
'value' => '<p>Avec plus de 10 tours de France à son actif, Jean-Marie a transmis sa passion à son fils. Léo assure : « Sur le Tour, nous sommes collègues, mais il y a toujours cette fierté personnelle de partager ces moments ensemble sur les routes de France. ».</p>',
|
||||
'validate' => 'required|string|min:15',
|
||||
'required' => true
|
||||
],
|
||||
'fun_facts_picture_2' => [
|
||||
'label' => 'Pictogramme de l\'anecdote n°2',
|
||||
'inputType' => 4,
|
||||
'dimensions' => [
|
||||
'width' => 80,
|
||||
'height' => 80
|
||||
],
|
||||
'alt' => 'Pictogramme d\'une tête d\'enfant pour les liens de parenté au sein de l\'équipe des caravaniers',
|
||||
'title' => 'Pictogramme d\'un enfant',
|
||||
'value' => '',
|
||||
'validate' => 'required',
|
||||
'required' => true
|
||||
],
|
||||
'fun_facts_title_3' => [
|
||||
'label' => 'Titre de l\'anecdote n°3',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Histoire de poulet',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'fun_facts_description_3' => [
|
||||
'label' => 'Description de l\'anecdote n°3',
|
||||
'inputType' => InputType::text->value,
|
||||
'value' => '<p>Avec un sens de l\'humour aguerri, Cocotte rencontre <a href="https://www.youtube.com/watch?v=reI-Z8UE3lM" target="_blank">un sympathique collègue</a> au détour d\'un passage dans un village sur les routes du Tour de France.</p>',
|
||||
'validate' => 'required|string|min:15',
|
||||
'required' => true
|
||||
],
|
||||
'fun_facts_picture_3' => [
|
||||
'label' => 'Pictogramme de l\'anecdote n°3',
|
||||
'inputType' => 4,
|
||||
'dimensions' => [
|
||||
'width' => 80,
|
||||
'height' => 80
|
||||
],
|
||||
'alt' => 'Pictogramme d\'un poulet policier pour les histoires poulets-policiers pendants le Tour de France',
|
||||
'title' => 'Pictogramme d\'un poulet policier',
|
||||
'value' => '',
|
||||
'validate' => 'required',
|
||||
'required' => true
|
||||
],
|
||||
'fun_facts_title_4' => [
|
||||
'label' => 'Titre de l\'anecdote n°4',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Un pompier en tant que chauffeur d\'un char Le Gaulois !',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'fun_facts_description_4' => [
|
||||
'label' => 'Description de l\'anecdote n°4',
|
||||
'inputType' => InputType::text->value,
|
||||
'value' => '<p>Nicolas, pompier engagé, a procédé à une intervention de secours pour une jeune caravanière Le Gaulois. Depuis, Nicolas, rebaptisé Pimpon Le Gaulois, sillonne toujours les routes de France à bord d\'un char Cocotte.</p>',
|
||||
'validate' => 'required|string|min:15',
|
||||
'required' => true
|
||||
],
|
||||
'fun_facts_picture_4' => [
|
||||
'label' => 'Pictogramme de l\'anecdote n°4',
|
||||
'inputType' => 4,
|
||||
'dimensions' => [
|
||||
'width' => 80,
|
||||
'height' => 80
|
||||
],
|
||||
'alt' => 'Pictogramme d\'une sirène d\'alarme pour les anecdoctes insolites pendant le Tour de France',
|
||||
'title' => 'Pictorgramme d\'une alarme',
|
||||
'value' => '',
|
||||
'validate' => 'required',
|
||||
'required' => true
|
||||
],
|
||||
'testimonials_title' => [
|
||||
'label' => 'Titre de la section n°7',
|
||||
'inputType' => InputType::string->value,
|
||||
'value' => 'Les témoignages des caravaniers',
|
||||
'validate' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
'testimonials_items' => [
|
||||
'label' => 'Slider de la section n°7',
|
||||
'inputType' => InputType::slider->value,
|
||||
'value' => '',
|
||||
'validate' => 'required|array|between:2,6',
|
||||
'required' => true,
|
||||
'columns' => [
|
||||
[
|
||||
'id' => 'picture',
|
||||
'type' => 'picture',
|
||||
'placeholder' => Str::ucFirst(__('validation.custom.picture')),
|
||||
'validation' => 'required',
|
||||
'required' => true
|
||||
],
|
||||
[
|
||||
'id' => 'picture_alt',
|
||||
'type' => 'text',
|
||||
'placeholder' => Str::ucFirst(__('validation.custom.picture_alt')),
|
||||
'validation' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
[
|
||||
'id' => 'picture_title',
|
||||
'type' => 'text',
|
||||
'placeholder' => Str::ucFirst(__('validation.custom.picture_title')),
|
||||
'validation' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
[
|
||||
'id' => 'picture_author',
|
||||
'type' => 'text',
|
||||
'placeholder' => Str::ucFirst(__('validation.custom.picture_author')),
|
||||
'validation' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
[
|
||||
'id' => 'title',
|
||||
'type' => 'text',
|
||||
'placeholder' => Str::ucFirst(__('validation.attributes.title')),
|
||||
'validation' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
[
|
||||
'id' => 'subtitle',
|
||||
'type' => 'text',
|
||||
'placeholder' => Str::ucFirst(__('validation.custom.subtitle')),
|
||||
'validation' => 'nullable|string|between:3,255',
|
||||
'required' => false
|
||||
],
|
||||
[
|
||||
'id' => 'description',
|
||||
'type' => 'wysiwyg',
|
||||
'placeholder' => Str::ucFirst(__('validation.attributes.description')),
|
||||
'validation' => 'required|string|min:15',
|
||||
'required' => true
|
||||
],
|
||||
[
|
||||
'id' => 'subtitle_2',
|
||||
'type' => 'text',
|
||||
'placeholder' => Str::ucFirst(__('validation.custom.subtitle')),
|
||||
'validation' => 'required|string|between:3,255',
|
||||
'required' => true
|
||||
],
|
||||
[
|
||||
'id' => 'description_2',
|
||||
'type' => 'wysiwyg',
|
||||
'placeholder' => Str::ucFirst(__('validation.attributes.description')),
|
||||
'validation' => 'required|string|min:15',
|
||||
'required' => true
|
||||
],
|
||||
],
|
||||
'itemLimit' => [2, 6],
|
||||
'imageSizes' => [500, 333],
|
||||
],
|
||||
];
|
||||
|
||||
$staticPage = StaticPage::where('type', StaticPageType::tdf)->first();
|
||||
if ($staticPage) {
|
||||
$staticPage->data = $data;
|
||||
$staticPage->saveQuietly();
|
||||
} else {
|
||||
StaticPage::query()->forceCreateQuietly(
|
||||
[
|
||||
'type' => StaticPageType::tdf->value(),
|
||||
'seo_title' => 'Le Gaulois | Volaille officielle du Tour de France',
|
||||
'seo_description' => 'Immergez-vous dans l\'ambiance du Tour de France avec Le Gaulois. Découvrez le jeu concours, les photos, anecdotes et témoignages de notre équipe.',
|
||||
'title' => 'Le Gaulois Le sponsor du Tour de France',
|
||||
'slug' => 'tour-de-france',
|
||||
'data' => $data
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('static_pages', function () {
|
||||
$staticPage = StaticPage::query()->where('type', StaticPageType::tdf)->first();
|
||||
$staticPage->data = [];
|
||||
$staticPage->saveQuietly();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -72,6 +72,10 @@ return [
|
|||
'picture_title_label' => 'Title attribute of the image',
|
||||
'picture_alt_helper' => 'Must describe your image for search engines and blind people (5 to 6 words).',
|
||||
'picture_alt_label' => 'Alt attribute of the image',
|
||||
'video_title_helper' => 'Useful for users, displayed by moving the mouse over the video',
|
||||
'video_title_label' => 'Title attribute of the video',
|
||||
'video_alt_helper' => 'Must describe your video for search engines and blind people (5 to 6 words).',
|
||||
'video_alt_label' => 'Alt attribute of the video',
|
||||
'text_warning' => 'Proofread your content before publishing it',
|
||||
],
|
||||
|
||||
|
|
|
|||
|
|
@ -328,6 +328,12 @@ return [
|
|||
'salt' => 'salt',
|
||||
],
|
||||
'breeding_section_card' => 'Common breeding section',
|
||||
'common_section_part' => 'common section'
|
||||
'common_section_part' => 'common section',
|
||||
'picture' => 'image',
|
||||
'picture_author' => 'image author',
|
||||
'picture_alt' => 'image alternative text',
|
||||
'picture_title' => 'image title',
|
||||
'video_alt' => 'video alternative text',
|
||||
'video_title' => 'video title',
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -76,6 +76,11 @@ return [
|
|||
'picture_alt_helper' => 'Doit décrire votre image pour les moteurs de recherche et
|
||||
les personnes malvoyantes (5 à 6 mots).',
|
||||
'picture_alt_label' => 'Attribut Alt de l\'image',
|
||||
'video_title_helper' => 'Utile pour les utilisateurs, s\'affiche en passant la souris sur la vidéo.',
|
||||
'video_title_label' => 'Attribut du titre de la vidéo',
|
||||
'video_alt_helper' => 'Doit décrire votre vidéo pour les moteurs de recherche et
|
||||
les personnes malvoyantes (5 à 6 mots).',
|
||||
'video_alt_label' => 'Attribut Alt de la vidéo',
|
||||
'text_warning' => 'Relisez votre contenu avant de le publier.',
|
||||
],
|
||||
|
||||
|
|
|
|||
|
|
@ -346,6 +346,12 @@ return [
|
|||
'salt' => 'sel',
|
||||
],
|
||||
'breeding_section_card' => 'section commune des élevages',
|
||||
'common_section_part' => 'section commune'
|
||||
'common_section_part' => 'section commune',
|
||||
'picture' => 'image',
|
||||
'picture_author' => 'auteur de l\'image',
|
||||
'picture_alt' => 'texte alternatif de l\'image',
|
||||
'picture_title' => 'titre de l\'image',
|
||||
'video_alt' => 'texte alternatif de la vidéo',
|
||||
'video_title' => 'titre de la vidéo',
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -52,3 +52,11 @@
|
|||
.form-control::file-selector-button {
|
||||
font-family: #{$btn-font-family} !important;
|
||||
}
|
||||
|
||||
.mt-16 {
|
||||
margin-top: 4rem;
|
||||
}
|
||||
|
||||
.mt-24 {
|
||||
margin-top: 6.25rem;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
// ASSETS
|
||||
/// <reference types="vite/client" />
|
||||
import.meta.glob(["./../../assets/images/**"]);
|
||||
import { initMediaSelector } from "./utilities/media-selector";
|
||||
|
||||
// UTILITIES
|
||||
import "./utilities/bootstrap";
|
||||
import "./utilities/fontawesome";
|
||||
import "./utilities/vue-bo";
|
||||
window.initMediaSelector = initMediaSelector;
|
||||
|
||||
// MODULES
|
||||
import "./../modules/sweetalert";
|
||||
|
|
|
|||
285
resources/ts/bo/components/SliderComponent.vue
Normal file
285
resources/ts/bo/components/SliderComponent.vue
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
<template>
|
||||
<div
|
||||
:class="`slider-component slider-${inputParameters.name}`"
|
||||
ref="slider"
|
||||
>
|
||||
<div
|
||||
v-if="itemParameters.list.length > 0"
|
||||
>
|
||||
<div
|
||||
class="border rounded-3 p-3 mb-3"
|
||||
v-for="(item, itemIndex) of itemParameters.list"
|
||||
:key="itemIndex"
|
||||
>
|
||||
<div
|
||||
class="d-flex justify-content-between align-items-center"
|
||||
>
|
||||
<legend class="w-fit me-2 mb-0">
|
||||
Slide n°{{ itemIndex + 1 }}
|
||||
</legend>
|
||||
<div
|
||||
v-if="buttonsDisplayParameters.remove"
|
||||
class="align-bottom"
|
||||
>
|
||||
<button
|
||||
@click.stop.prevent="removeLine(itemIndex)"
|
||||
class="btn btn-sm btn-danger"
|
||||
:title="trans.methods.__('Supprimer la ligne')"
|
||||
data-bs-toggle="tooltip"
|
||||
>
|
||||
<i class="fa-solid fa-trash" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="row"
|
||||
>
|
||||
<div
|
||||
class="col-6 mb-3"
|
||||
v-for="(column, columnIndex) of itemParameters.columns"
|
||||
:key="columnIndex"
|
||||
>
|
||||
<label class="py-2">
|
||||
<b>{{ column.placeholder + (column.required ? '*' : '') }}</b>
|
||||
</label>
|
||||
<div
|
||||
v-if="itemParameters.columns[columnIndex].type == 'wysiwyg'"
|
||||
:class="(getErrorMessage(itemIndex, column.id) !== null) ? 'is-invalid' : ''"
|
||||
>
|
||||
<CkEditorComponent
|
||||
:name="`data[${inputParameters.name}][value][${String(itemIndex)}][${column.id}]`"
|
||||
:placeholder="itemParameters.columns[columnIndex].placeholder"
|
||||
:dbtext="String(item[column.id as keyof typeof item] ?? '')"
|
||||
:required="true"
|
||||
:errors="allErrors"
|
||||
:editor-config="itemParameters.wysiwygConfig"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="itemParameters.columns[columnIndex].type == 'picture'"
|
||||
:class="(getErrorMessage(itemIndex, column.id) !== null) ? 'is-invalid' : ''"
|
||||
>
|
||||
<ImageInputComponent
|
||||
:id="'picture-input-' + inputParameters.name + '-' + column.id + '-' + itemIndex"
|
||||
:required="itemParameters.columns[columnIndex].required"
|
||||
:show-labels="true"
|
||||
:name="`data[${inputParameters.name}][value][${String(itemIndex)}][${column.id}]`"
|
||||
:helper="trans.methods.__('crud.minicrud.dimensions_must_be', {
|
||||
widthpx: (itemParameters.imageSizes[0] ?? String(500)) + 'px',
|
||||
heightpx: (itemParameters.imageSizes[1] ?? String(500)) + 'px',
|
||||
})"
|
||||
:width="itemParameters.imageSizes[0] ?? 500"
|
||||
:height="itemParameters.imageSizes[1] ?? 500"
|
||||
:value="item[column.id as keyof typeof item] ? String(item[column.id as keyof typeof item]) : undefined"
|
||||
:preview="false"
|
||||
:browse-event="false"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-else
|
||||
>
|
||||
<WordCounter
|
||||
:id="'text-input-' + inputParameters.name + '-' + column.id + '-' + itemIndex"
|
||||
class="ck-word-count"
|
||||
/>
|
||||
<input
|
||||
:id="'text-input-' + inputParameters.name + '-' + column.id + '-' + itemIndex"
|
||||
:class="['form-control', (getErrorMessage(itemIndex, column.id) !== null) ? 'is-invalid' : '']"
|
||||
:name="`data[${inputParameters.name}][value][${String(itemIndex)}][${column.id}]`"
|
||||
:type="itemParameters.columns[columnIndex].type"
|
||||
v-model="item[column.id as keyof typeof item]"
|
||||
:placeholder="itemParameters.columns[columnIndex].placeholder"
|
||||
:required="itemParameters.columns[columnIndex].required"
|
||||
>
|
||||
</div>
|
||||
<small class="text-danger m-0">
|
||||
{{ getErrorMessage(itemIndex, column.id) }}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<p>{{ trans.methods.__("Aucun élément renseigné(s).") }}</p>
|
||||
</div>
|
||||
<div
|
||||
v-if="buttonsDisplayParameters.add"
|
||||
class="text-center mt-1"
|
||||
>
|
||||
<button
|
||||
@click.prevent="addLine"
|
||||
class="btn btn-sm btn-primary"
|
||||
type="button"
|
||||
:title="trans.methods.__('Ajouter une ligne')"
|
||||
data-bs-toggle="tooltip"
|
||||
>
|
||||
<i class="fa-solid fa-plus" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, defineOptions, onMounted, reactive, ref, useAttrs } from "vue";
|
||||
import parseLaravelErrorMessages from "./../../modules/parseLaravelErrorMessages";
|
||||
import trans from "./../../modules/trans";
|
||||
import { Tooltips } from "./../../modules/bsTooltips";
|
||||
import CkEditorComponent from "./CkEditorComponent.vue";
|
||||
import ImageInputComponent from "./ImageInputComponent.vue";
|
||||
import WordCounter from "./WordCounterComponent.vue";
|
||||
|
||||
defineOptions({
|
||||
name: "SliderComponent"
|
||||
});
|
||||
|
||||
// * ATTRIBUTES
|
||||
const attrs = useAttrs();
|
||||
|
||||
// * REFS
|
||||
const slider = ref<HTMLDivElement|null>(null);
|
||||
|
||||
// * DATA
|
||||
const tooltips = ref<Tooltips | null>(null);
|
||||
const allErrors = ref<LaravelValidationErrors>({});
|
||||
|
||||
interface Column {
|
||||
id: string;
|
||||
type: "picture" | "text" | "wysiwyg";
|
||||
placeholder: string;
|
||||
validation: string;
|
||||
required: boolean;
|
||||
}
|
||||
|
||||
/** Input parameters. */
|
||||
const inputParameters = reactive<{
|
||||
id: string,
|
||||
name: string,
|
||||
}>({
|
||||
id: "string",
|
||||
name: "",
|
||||
});
|
||||
|
||||
/** Item parameters. */
|
||||
const itemParameters = reactive<{
|
||||
list: Array<Object>,
|
||||
columns: Array<Column>,
|
||||
limits: Array<number>,
|
||||
wysiwygConfig: string,
|
||||
imageSizes: Array<number>,
|
||||
}>({
|
||||
list: [{}],
|
||||
columns: [],
|
||||
limits: [0, 0],
|
||||
wysiwygConfig: "",
|
||||
imageSizes: [500, 500],
|
||||
});
|
||||
|
||||
/** Buttons parameters. */
|
||||
const buttonsDisplayParameters = reactive<{
|
||||
add: boolean,
|
||||
remove: boolean,
|
||||
}>({
|
||||
add: true,
|
||||
remove: true,
|
||||
});
|
||||
|
||||
// * COMPUTED
|
||||
const isUsedWithProps = computed<boolean>(() => attrs.json === undefined);
|
||||
|
||||
// * LIFECYCLE
|
||||
onMounted(() => {
|
||||
const json = String(attrs.json ?? "{}"),
|
||||
data = JSON.parse(json);
|
||||
if (!isUsedWithProps.value) {
|
||||
/** Input parameters. */
|
||||
inputParameters.name = data.inputName;
|
||||
/** Item parameters. */
|
||||
itemParameters.list = Array.isArray(data.itemList) ? data.itemList : [];
|
||||
itemParameters.columns = data.columns;
|
||||
itemParameters.limits = data.itemLimit;
|
||||
itemParameters.wysiwygConfig = data.wysiwygConfig;
|
||||
itemParameters.imageSizes = data.imageSizes;
|
||||
/** Global parameters */
|
||||
allErrors.value = data.errors;
|
||||
}
|
||||
setDefaultLines();
|
||||
checkLengthList();
|
||||
initTooltips();
|
||||
});
|
||||
|
||||
// * METHODS
|
||||
|
||||
/**
|
||||
* Set default line(s)
|
||||
* according to the minimum limit defined.
|
||||
*/
|
||||
function setDefaultLines(): void {
|
||||
while (itemParameters.list.length < itemParameters.limits[0]) {
|
||||
addLine();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new line to the <table>,
|
||||
* add a new element to the array,
|
||||
* show remove line button.
|
||||
*/
|
||||
function addLine(): void {
|
||||
itemParameters.list.push({});
|
||||
if (buttonsDisplayParameters.remove == false) {
|
||||
buttonsDisplayParameters.remove = true;
|
||||
}
|
||||
checkLengthList();
|
||||
tooltips.value?.closeBootstrapTooltip();
|
||||
initTooltips();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a specific line from the <table>,
|
||||
* remove a specific element to the array,
|
||||
* show adding line button.
|
||||
*/
|
||||
function removeLine(itemIndex: number): void {
|
||||
itemParameters.list.splice(itemIndex, 1);
|
||||
if (buttonsDisplayParameters.add == false) {
|
||||
buttonsDisplayParameters.add = true;
|
||||
}
|
||||
checkLengthList();
|
||||
tooltips.value?.closeBootstrapTooltip();
|
||||
initTooltips();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the length of the list,
|
||||
* update variables accordingly.
|
||||
*/
|
||||
function checkLengthList(): void {
|
||||
/** Length minimum */
|
||||
if (itemParameters.list.length <= itemParameters.limits[0]) {
|
||||
buttonsDisplayParameters.remove = false;
|
||||
}
|
||||
/** Length maximum */
|
||||
if (itemParameters.list.length >= itemParameters.limits[1]) {
|
||||
buttonsDisplayParameters.add = false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Return error message or null. */
|
||||
function getErrorMessage(itemIndex: number, column: string): string|null {
|
||||
return parseLaravelErrorMessages.methods.parseValidationInput(
|
||||
`${inputParameters.name}.${String(itemIndex)}.${column}`,
|
||||
allErrors.value
|
||||
);
|
||||
}
|
||||
|
||||
/** Initialise all tooltips in the component. */
|
||||
function initTooltips(): void {
|
||||
setTimeout(() => {
|
||||
tooltips.value = Tooltips.make({
|
||||
type: "dom",
|
||||
elements: slider.value!.querySelectorAll("[data-bs-toggle=\"tooltip\"]")
|
||||
});
|
||||
}, 500);
|
||||
}
|
||||
</script>
|
||||
|
|
@ -85,7 +85,10 @@ import {
|
|||
faUndoAlt,
|
||||
faUserTie,
|
||||
faUtensils,
|
||||
faWandMagic
|
||||
faWandMagic,
|
||||
faBicycle,
|
||||
faChevronDown,
|
||||
faChevronUp
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
config.autoReplaceSvg = false;
|
||||
|
|
@ -175,5 +178,8 @@ library.add(faComments);
|
|||
library.add(faRug);
|
||||
library.add(faBasketShopping);
|
||||
library.add(faArrowTurnUp);
|
||||
library.add(faBicycle);
|
||||
library.add(faChevronDown);
|
||||
library.add(faChevronUp);
|
||||
|
||||
dom.watch();
|
||||
|
|
|
|||
49
resources/ts/bo/utilities/media-selector.ts
Normal file
49
resources/ts/bo/utilities/media-selector.ts
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
export function initMediaSelector(id: string) {
|
||||
const container = document.getElementById(`${id}Section`);
|
||||
if (container === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const mediaVideo = document.getElementById("mediaSelectorVideo") as HTMLInputElement,
|
||||
mediaImage = document.getElementById("mediaSelectorImage") as HTMLInputElement,
|
||||
mediaEmpty = document.getElementById("mediaSelectorEmpty") as HTMLInputElement;
|
||||
|
||||
mediaVideo?.addEventListener("change", function() {
|
||||
hideFormPart(`.${id}Picture`);
|
||||
showFormPart(`.${id}Video`);
|
||||
hideFormPart(`.${id}None`);
|
||||
});
|
||||
|
||||
mediaImage?.addEventListener("change", function() {
|
||||
hideFormPart(`.${id}Video`);
|
||||
showFormPart(`.${id}Picture`);
|
||||
hideFormPart(`.${id}None`);
|
||||
});
|
||||
|
||||
mediaEmpty?.addEventListener("change", function() {
|
||||
hideFormPart(`.${id}Video`);
|
||||
hideFormPart(`.${id}Picture`);
|
||||
showFormPart(`.${id}None`);
|
||||
});
|
||||
}
|
||||
|
||||
function hideFormPart(id: string) {
|
||||
const parts = document.querySelectorAll(id);
|
||||
parts.forEach(partToHide => {
|
||||
partToHide.classList.add("d-none");
|
||||
const inputs = partToHide.querySelectorAll("input");
|
||||
for (const input of inputs) {
|
||||
input.disabled = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
function showFormPart(id: string) {
|
||||
const parts = document.querySelectorAll(id);
|
||||
parts.forEach(partToShow => {
|
||||
partToShow.classList.remove("d-none");
|
||||
const inputs = partToShow.querySelectorAll("input");
|
||||
for (const input of inputs) {
|
||||
input.disabled = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
2
resources/ts/index.d.ts
vendored
2
resources/ts/index.d.ts
vendored
|
|
@ -5,6 +5,7 @@ import { AxiosStatic } from "axios";
|
|||
import type Swiper from "swiper";
|
||||
import type { DepStatus as DepStatusEnum } from "./club/enums";
|
||||
import type { MenuNodeInterface } from "./types/models/MenuNode";
|
||||
import { initMediaSelector } from "./bo/utilities/media-selector";
|
||||
|
||||
// * Enum
|
||||
interface EnumInterface {
|
||||
|
|
@ -141,6 +142,7 @@ declare global {
|
|||
Swal: Function;
|
||||
shop: ClubShop;
|
||||
vueDebug: boolean | undefined;
|
||||
initMediaSelector: initMediaSelector;
|
||||
__SLIDERS: Map<string, SwiperSlider>,
|
||||
__SYSTEM: {
|
||||
_asset: Record<string, string>;
|
||||
|
|
|
|||
|
|
@ -1176,7 +1176,7 @@
|
|||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
{{-- PAGE SORTIR-A-L-EXTERIEUR --}}
|
||||
@if (isset($exitOutsideStaticPageModel))
|
||||
@if (isset($exitOutsideStaticPageModel))
|
||||
<li>
|
||||
<a href="{{ route('bo.static_pages.edit', $exitOutsideStaticPageModel) }}" @class([
|
||||
'dropdown-item px-3 py-2',
|
||||
|
|
@ -1195,14 +1195,14 @@
|
|||
</li>
|
||||
@endif
|
||||
{{-- OUI-C-BON --}}
|
||||
@if (isset($ouiCestBonStaticPageModel))
|
||||
@if (isset($ouiCestBonStaticPageModel))
|
||||
<li>
|
||||
<a href="{{ route('bo.static_pages.edit', $ouiCestBonStaticPageModel ) }}" @class([
|
||||
'dropdown-item px-3 py-2',
|
||||
'fw-bold text-bg-secondary' =>
|
||||
url()->current() ===
|
||||
route('bo.static_pages.edit', $ouiCestBonStaticPageModel),
|
||||
|
||||
|
||||
])>
|
||||
<i @class([
|
||||
'fa-solid fa-file fa-fw fa-fw',
|
||||
|
|
@ -1242,6 +1242,25 @@
|
|||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{{-- TDF PAGE --}}
|
||||
@if (isset($tdfStaticPageModel))
|
||||
<a data-bs-toggle="tooltip" href="{{ route('bo.static_pages.edit', $tdfStaticPageModel) }}"
|
||||
title="{{ __('crud.helpers.update_model', ['model' => $tdfStaticPageModel->type->label()]) }}" role="button"
|
||||
@class([
|
||||
'btn btn-primary w-100 text-start mt-1',
|
||||
'fw-bold active' =>
|
||||
url()->current() ===
|
||||
route('bo.static_pages.edit', $tdfStaticPageModel->type->value()),
|
||||
])>
|
||||
<i @class([
|
||||
'fa-solid fa-bicycle fa-fw',
|
||||
'fa-lg' =>
|
||||
url()->current() ===
|
||||
route('bo.static_pages.edit', $tdfStaticPageModel->type->value()),
|
||||
])></i>
|
||||
{{ $tdfStaticPageModel->type->label() }}
|
||||
</a>
|
||||
@endif
|
||||
<hr>
|
||||
{{-- CONTACT --}}
|
||||
@if(isset($contactStaticPageModel))
|
||||
|
|
|
|||
|
|
@ -246,6 +246,58 @@
|
|||
</div>
|
||||
@break
|
||||
|
||||
@case(intval(\App\Enums\InputType::selectImageVideo->value))
|
||||
<div class="minicrud-input col-12 mb-3">
|
||||
<fieldset class="border p-3">
|
||||
<legend>{{ $input['label'] }}*</legend>
|
||||
<div class="row mb-3">
|
||||
<div class="col-12">
|
||||
@include('bo.partials.inputs.media-selector', [
|
||||
'id' => Str::camel($k),
|
||||
'name' => $k,
|
||||
'value' => old("data.{$k}.value", $input['value'] ?? null),
|
||||
'required' => isset($input['required']) ? !empty($input['required']) : true,
|
||||
'model' => $model ?? null,
|
||||
'helper' =>
|
||||
__('crud.minicrud.text_warning') .
|
||||
'. ' .
|
||||
__('validation.min.string', [
|
||||
'attribute' => $input['label'],
|
||||
'min' => 3,
|
||||
]),
|
||||
])
|
||||
@include('modules.input-error', [
|
||||
'inputName' => "data.{$k}.value",
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
@break
|
||||
|
||||
@case(intval(\App\Enums\InputType::slider->value))
|
||||
<div class="minicrud-input col-12 mb-3">
|
||||
<fieldset class="h-100 border p-3">
|
||||
<legend>{{ $input['label'] }}*</legend>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
@include('bo.partials.inputs.slider', [
|
||||
'id' => Str::camel($k),
|
||||
'name' => $k,
|
||||
'value' => old("data.{$k}.value", $input['value'] ?? null),
|
||||
'model' => $model ?? null,
|
||||
'columns' => $input['columns'],
|
||||
'itemLimit' => $input['itemLimit'],
|
||||
'imageSizes' => $input['imageSizes'],
|
||||
'required' => isset($input['required']) ? !empty($input['required']) : true,
|
||||
'helper' => '',
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
@break
|
||||
|
||||
@default
|
||||
@php throw new Exception('Input type not handled'); @endphp
|
||||
@endswitch
|
||||
|
|
|
|||
163
resources/views/bo/partials/inputs/media-selector.blade.php
Normal file
163
resources/views/bo/partials/inputs/media-selector.blade.php
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
<div id="{{ sprintf("%sSection", $id)}}" class="row">
|
||||
{{-- BUTTONS SELECTOR --}}
|
||||
<div class="col-12 col-md-6 mb-3">
|
||||
<div class="input-group justify-content-center align-items-center h-100">
|
||||
<input class="btn-check" id="mediaSelectorVideo" name="mediaSelector" type="radio" autocomplete="off"
|
||||
@checked(isset($model->data[$name]['value']['video']))>
|
||||
<label class="btn btn-secondary rounded-start" for="mediaSelectorVideo">{{ __('Vidéo') }}</label>
|
||||
<input class="btn-check" id="mediaSelectorImage" name="mediaSelector" type="radio" autocomplete="off"
|
||||
@checked(isset($model->data[$name]['value']['picture']))>
|
||||
<label class="btn btn-secondary" for="mediaSelectorImage">{{ __('Image') }}</label>
|
||||
@if (!$required)
|
||||
<input class="btn-check" id="mediaSelectorEmpty" name="mediaSelector" type="radio" autocomplete="off"
|
||||
@checked(!$required && empty($model->data[$name]['value']['video']) && empty($model->data[$name]['value']['picture']))>
|
||||
<label class="btn btn-secondary" for="mediaSelectorEmpty">{{ __('Rien') }}</label>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- HIDDEN EMPTY MEDIA INPUT --}}
|
||||
<input name="value[]" value="" hidden>
|
||||
|
||||
{{-- VIDEO --}}
|
||||
<div @class([
|
||||
sprintf('%sVideo', $id) . ' col-12 col-md-6 mb-3',
|
||||
'd-none' => empty($model->data[$name]['value']['video']),
|
||||
])>
|
||||
{{-- VIDEO ID --}}
|
||||
@include('bo.partials.inputs.varchar', [
|
||||
'id' => sprintf("%sVideoId", $id),
|
||||
'label' => Str::ucFirst(__('validation.custom.video_id')),
|
||||
'hasWordCounter' => true,
|
||||
'name' => "data[$name][value][video][id]",
|
||||
'required' => true,
|
||||
'disabled' => empty($model->data[$name]['value']['video']),
|
||||
'value' => $model->data[$name]['value']['video']['id'] ?? null,
|
||||
'helper' => Str::ucFirst(__('validation.custom.video_id')),
|
||||
'placeholder' => Str::ucFirst(__('validation.custom.video_id')),
|
||||
])
|
||||
</div>
|
||||
{{-- VIDEO_ALT --}}
|
||||
<div @class([
|
||||
sprintf('%sVideo', $id) . ' col-12 col-md-6 mb-3',
|
||||
'd-none' => empty($model->data[$name]['value']['video']),
|
||||
])>
|
||||
@include('bo.partials.inputs.varchar', [
|
||||
'id' => sprintf("%sVideoAlt", $id),
|
||||
'label' => Str::ucFirst(__('validation.custom.video_alt')),
|
||||
'hasWordCounter' => true,
|
||||
'name' => "data[$name][value][video][alt]",
|
||||
'required' => true,
|
||||
'model' => $model ?? null,
|
||||
'disabled' => empty($model->data[$name]['value']['video']['alt']),
|
||||
'value' => $model->data[$name]['value']['video']['alt'] ?? '',
|
||||
'helper' => __('crud.minicrud.video_alt_helper') . ' ' . __('validation.between.string', [
|
||||
'attribute' => Str::ucFirst(__('validation.custom.video_alt')),
|
||||
'min' => 6,
|
||||
'max' => 255
|
||||
]),
|
||||
'placeholder' => Str::ucFirst(__('validation.custom.video_alt')),
|
||||
])
|
||||
</div>
|
||||
{{-- VIDEO_TITLE --}}
|
||||
<div @class([
|
||||
sprintf('%sVideo', $id) . ' col-12 col-md-6 mb-3',
|
||||
'd-none' => empty($model->data[$name]['value']['video']),
|
||||
])>
|
||||
@include('bo.partials.inputs.varchar', [
|
||||
'id' => sprintf("%sVideoTitle", $id),
|
||||
'label' => Str::ucFirst(__('validation.custom.video_title')),
|
||||
'hasWordCounter' => true,
|
||||
'name' => "data[$name][value][video][title]",
|
||||
'required' => true,
|
||||
'model' => $model ?? null,
|
||||
'disabled' => empty($model->data[$name]['value']['video']['title']),
|
||||
'value' => $model->data[$name]['value']['video']['title'] ?? '',
|
||||
'helper' => __('crud.minicrud.video_title_helper') . ' ' . __('validation.between.string', [
|
||||
'attribute' => Str::ucFirst(__('validation.custom.video_title')),
|
||||
'min' => 6,
|
||||
'max' => 255
|
||||
]),
|
||||
'placeholder' => Str::ucFirst(__('validation.custom.video_title')),
|
||||
])
|
||||
</div>
|
||||
{{-- PICTURE --}}
|
||||
<div @class([
|
||||
sprintf('%sPicture', $id) . ' col-12 col-md-6 mb-3',
|
||||
'd-none' => empty($model->data[$name]['value']['picture']),
|
||||
])>
|
||||
@include('bo.partials.inputs.varchar-picture', [
|
||||
'id' => sprintf("%sPicture", $id),
|
||||
'name' => "data[$name][value][picture][path]",
|
||||
'width' => 500,
|
||||
'height' => 500,
|
||||
'model' => $model ?? null,
|
||||
'value' => $model->data[$name]['value']['picture']['path'] ?? null,
|
||||
'helper' => __('crud.minicrud.dimensions_must_be', [
|
||||
'width' => 500,
|
||||
'height' => 500,
|
||||
]),
|
||||
'required' => true,
|
||||
'preview' => false,
|
||||
])
|
||||
</div>
|
||||
{{-- PICTURE_ALT --}}
|
||||
<div @class([
|
||||
sprintf('%sPicture', $id) . ' col-12 col-md-6 mb-3',
|
||||
'd-none' => empty($model->data[$name]['value']['picture']),
|
||||
])>
|
||||
@include('bo.partials.inputs.varchar', [
|
||||
'id' => sprintf("%sPictureAlt", $id),
|
||||
'label' => Str::ucFirst(__('validation.custom.picture_alt')),
|
||||
'hasWordCounter' => true,
|
||||
'name' => "data[$name][value][picture][alt]",
|
||||
'required' => true,
|
||||
'model' => $model ?? null,
|
||||
'disabled' => empty($model->data[$name]['value']['picture']['alt']),
|
||||
'value' => $model->data[$name]['value']['picture']['alt'] ?? '',
|
||||
'helper' => __('crud.minicrud.picture_alt_helper') . ' ' . __('validation.between.string', [
|
||||
'attribute' => Str::ucFirst(__('validation.custom.picture_alt')),
|
||||
'min' => 6,
|
||||
'max' => 255
|
||||
]),
|
||||
'placeholder' => Str::ucFirst(__('validation.custom.picture_alt')),
|
||||
])
|
||||
</div>
|
||||
{{-- PICTURE_TITLE --}}
|
||||
<div @class([
|
||||
sprintf('%sPicture', $id) . ' col-12 col-md-6 mb-3',
|
||||
'd-none' => empty($model->data[$name]['value']['picture']),
|
||||
])>
|
||||
@include('bo.partials.inputs.varchar', [
|
||||
'id' => sprintf("%sPictureTitle", $id),
|
||||
'label' => Str::ucFirst(__('validation.custom.picture_title')),
|
||||
'hasWordCounter' => true,
|
||||
'name' => "data[$name][value][picture][title]",
|
||||
'required' => true,
|
||||
'model' => $model ?? null,
|
||||
'disabled' => empty($model->data[$name]['value']['picture']['title']),
|
||||
'value' => $model->data[$name]['value']['picture']['title'] ?? '',
|
||||
'helper' => __('crud.minicrud.picture_title_helper') . ' ' . __('validation.between.string', [
|
||||
'attribute' => Str::ucFirst(__('validation.custom.picture_title')),
|
||||
'min' => 6,
|
||||
'max' => 255
|
||||
]),
|
||||
'placeholder' => Str::ucFirst(__('validation.custom.picture_title')),
|
||||
])
|
||||
</div>
|
||||
{{-- NOTHING SELECTED --}}
|
||||
<div @class([
|
||||
sprintf('%sNone', $id) . ' col-12 col-md-6',
|
||||
'd-none' => !empty($model->data[$name]['value']['picture']) || !empty($model->data[$name]['value']['video']),
|
||||
])>
|
||||
<p class="text-center text-body-secondary m-0">{{ __('Aucun média n\'est sélectionné') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script nonce="{{ $nonce }}">
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
initMediaSelector("{{ $id }}");
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
18
resources/views/bo/partials/inputs/slider.blade.php
Normal file
18
resources/views/bo/partials/inputs/slider.blade.php
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
@php
|
||||
$data = [
|
||||
'itemList' => old($name, $value ?? []) ?? [],
|
||||
'columns' => $columns,
|
||||
'itemLimit' => $itemLimit ?? [],
|
||||
'inputName' => $name,
|
||||
'imageSizes' => $imageSizes ?? [],
|
||||
'wysiwygConfig' => $wysiwygConfig ?? 'basic',
|
||||
'header' => $header ?? false,
|
||||
'errors' => $errors->getBag('default')->getMessages() ?? [],
|
||||
];
|
||||
@endphp
|
||||
<div class="slider" data-json='@json($data)'></div>
|
||||
@include('modules.input-error', [
|
||||
'inputName' => $name,
|
||||
'helperId' => "{$id}Help",
|
||||
'helper' => $helper,
|
||||
])
|
||||
|
|
@ -1,62 +1,74 @@
|
|||
@php
|
||||
$anecdotes = [
|
||||
[
|
||||
'picto_url' => Vite::asset('resources/assets/images/page-tdf/caravane/Picto-soleil-jaune-météo.svg'),
|
||||
'picto_alt' => 'Pictogramme d\'un soleil pour les anecdoctes météo sur le Tour de France',
|
||||
'picto_title' => 'Pictogramme d\'un soleil',
|
||||
'title' => 'La caravane par tous les temps !',
|
||||
'content' =>
|
||||
'Le 26 juillet 2019, lors de l\'étape Saint-Jean-de-Maurienne et Tignes, les chars terminent leur parade quand un orage de grêle s\'invite et entraîne une coulée de boue qui bloque la route et l’accès aux cyclistes. L’organisation décide l\'arrêt de l’étape et marquera l’histoire du Tour de France.',
|
||||
'picto_url' => asset($model->data['fun_facts_picture_1']['value']),
|
||||
'picto_alt' => $model->data['fun_facts_picture_1']['alt'],
|
||||
'picto_title' => $model->data['fun_facts_picture_1']['title'],
|
||||
'title' => $model->data['fun_facts_title_1']['value'],
|
||||
'content' => $model->data['fun_facts_description_1']['value'],
|
||||
],
|
||||
[
|
||||
'picto_url' => Vite::asset('resources/assets/images/page-tdf/caravane/Picto-enfant-brun-famille.svg'),
|
||||
'picto_alt' => 'Pictogramme d\'une tête d\'enfant pour les liens de parenté au sein de l\'équipe des caravaniers',
|
||||
'picto_title' => 'Pictogramme d\'un enfant',
|
||||
'title' => 'La transmission d’une passion entre Père & Fils !',
|
||||
'content' =>
|
||||
'Avec plus de 10 tours de France à son actif, Jean-Marie a transmis sa passion à son fils. Léo assure : « Sur le Tour, nous sommes collègues, mais il y a toujours cette fierté personnelle de partager ces moments ensemble sur les routes de France. ».',
|
||||
'picto_url' => asset($model->data['fun_facts_picture_2']['value']),
|
||||
'picto_alt' => $model->data['fun_facts_picture_2']['alt'],
|
||||
'picto_title' => $model->data['fun_facts_picture_2']['title'],
|
||||
'title' => $model->data['fun_facts_title_2']['value'],
|
||||
'content' => $model->data['fun_facts_description_2']['value'],
|
||||
],
|
||||
[
|
||||
'picto_url' => Vite::asset('resources/assets/images/page-tdf/caravane/Picto-poulet-policier-bleu.svg'),
|
||||
'picto_alt' => 'Pictogramme d\'un poulet policier pour les histoires poulets-policiers pendants le Tour de France',
|
||||
'picto_title' => 'Pictogramme d\'un poulet policier',
|
||||
'title' => 'Histoire de poulet',
|
||||
'content' =>
|
||||
'Avec un sens de l’humour aguerri, Cocotte rencontre <a href="https://www.youtube.com/watch?v=reI-Z8UE3lM" target="_blank">un sympathique collègue</a> au détour d’un passage dans un village sur les routes du Tour de France.',
|
||||
'picto_url' => asset($model->data['fun_facts_picture_3']['value']),
|
||||
'picto_alt' => $model->data['fun_facts_picture_3']['alt'],
|
||||
'picto_title' => $model->data['fun_facts_picture_3']['title'],
|
||||
'title' => $model->data['fun_facts_title_3']['value'],
|
||||
'content' => $model->data['fun_facts_description_3']['value'],
|
||||
],
|
||||
[
|
||||
'picto_url' => Vite::asset('resources/assets/images/page-tdf/caravane/Picto-sirène-pompier-rouge.svg'),
|
||||
'picto_alt' => 'Pictogramme d\'une sirène d\'alarme pour les anecdoctes insolites pendant le Tour de France',
|
||||
'picto_title' => 'Pictorgramme d\'une alarme',
|
||||
'title' => 'Un pompier en tant que chauffeur d’un char Le Gaulois !',
|
||||
'content' =>
|
||||
'Nicolas, pompier engagé, a procédé à une intervention de secours pour une jeune caravanière Le Gaulois. Depuis, Nicolas, rebaptisé Pimpon Le Gaulois, sillonne toujours les routes de France à bord d\'un char Cocotte.',
|
||||
'picto_url' => asset($model->data['fun_facts_picture_4']['value']),
|
||||
'picto_alt' => $model->data['fun_facts_picture_4']['alt'],
|
||||
'picto_title' => $model->data['fun_facts_picture_4']['title'],
|
||||
'title' => $model->data['fun_facts_title_4']['value'],
|
||||
'content' => $model->data['fun_facts_description_4']['value'],
|
||||
],
|
||||
];
|
||||
@endphp
|
||||
<section id="au-coeur-de-la-caravane">
|
||||
<h2 class="fw-bold text-uppercase mb-md-5 mb-0 text-center">Au cœur de la caravane Le Gaulois</h2>
|
||||
<h2 class="fw-bold text-uppercase mb-md-5 mb-0 text-center">
|
||||
{{ $model->data['heart_title']['value'] }}
|
||||
</h2>
|
||||
<div class="position-relative line-border-large">
|
||||
<div class="position-absolute left-100 w-100 d-none d-md-block start-0 z-0">
|
||||
<img class="img-fluid w-100 h-auto" src="{{ Vite::asset('resources/assets/images/page-tdf/caravane/TDF2033-caravaniers.jpg') }}"
|
||||
title="Char de la caravane Le Gaulois" alt="Char 'La crousty mobile' qui traverse un village français pendant le Tour de France" />
|
||||
<img
|
||||
class="img-fluid w-100 h-auto"
|
||||
src="{{ asset($model->data['heart_picture']['value']) }}"
|
||||
title="{{ $model->data['heart_picture']['title'] }}"
|
||||
alt="{{ $model->data['heart_picture']['alt'] }}"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="position-relative z-1 anecdote-container container">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-lg-7">
|
||||
<div class="rounded-3 position-relative line-border-medium bg-white p-4 shadow">
|
||||
<h4 class="fw-bold fs-2 text-uppercase mb-5 text-center">Nos petites anecdotes</h4>
|
||||
<div class="">
|
||||
<h4 class="fw-bold fs-2 text-uppercase mb-5 text-center">
|
||||
{{ $model->data['heart_subtitle']['value'] }}
|
||||
</h4>
|
||||
<div>
|
||||
@foreach ($anecdotes as $a)
|
||||
<div class="row mb-3">
|
||||
<div class="col-3 d-flex flex-column justify-content-center">
|
||||
<img class="w-50 mx-auto mb-2" src="{{ $a['picto_url'] }}" title="{{ $a['picto_title'] }}"
|
||||
alt="{{ $a['picto_alt'] }}">
|
||||
<img
|
||||
class="w-50 mx-auto mb-2"
|
||||
src="{{ $a['picto_url'] }}"
|
||||
title="{{ $a['picto_title'] }}"
|
||||
alt="{{ $a['picto_alt'] }}"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-9">
|
||||
<div class="fw-bold text-uppercase fs-6 text-start">{{ $a['title'] }}</div>
|
||||
<p class="f-bakerie-rough fs-4 fw-normal">{!! $a['content'] !!}</p>
|
||||
<div class="fw-bold text-uppercase fs-6 text-start">
|
||||
{!! clean($a['title']) !!}
|
||||
</div>
|
||||
<div class="f-bakerie-rough fs-4 fw-normal">
|
||||
{!! clean($a['content']) !!}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
|
|
@ -68,5 +80,5 @@
|
|||
</div>
|
||||
</section>
|
||||
<div class="ms-md-5 mt-4 d-none d-md-block">
|
||||
<small>Crédit photo - ASO Aurélien Vialatte</small>
|
||||
<small>{{ $model->data['heart_picture_author']['value'] }}</small>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,74 +1,5 @@
|
|||
@php
|
||||
$sliders = [
|
||||
[
|
||||
'img' => Vite::asset('resources/assets/images/page-tdf/chars-slider/Char-cocotte-roule-ma-poule-Le-Gaulois.png'),
|
||||
'alt' =>
|
||||
'"Char" La cocotte multiproduits" avec les packagings du filet de canard, du poulet à la mexicaine et des gésiers de volaille Le Gaulois',
|
||||
'title_img' => '"Char" La cocotte multiproduits" Le Gaulois',
|
||||
'title' => 'La Cocotte multiproduits',
|
||||
'content' =>
|
||||
"Variée et savoureuse, la Cocotte mutiproduits présente les incontournables de votre frigo, pour toute la famille et pour toute l'année. Et vous, quel est votre produit préféré Le Gaulois ?",
|
||||
],
|
||||
[
|
||||
'img' => Vite::asset('resources/assets/images/page-tdf/chars-slider/Char-cocotte-cordon-bleu-Le-Gaulois.png'),
|
||||
'alt' => 'Char "La cocotte panée"avec le packaging du cordon bleu de poulet Le Gaulois',
|
||||
'title_img' => 'Char "La cocotte panée" Le Gaulois',
|
||||
'title' => 'La Cocotte Panée',
|
||||
'content' =>
|
||||
'Moelleuse, croustillante et fondante, la Cocotte Panée arpente les régions françaises à la découverte du nouveau Cordon Bleu culinaire ! Quel sera le nouveau chef cuisinier du Tour de France ?',
|
||||
],
|
||||
[
|
||||
'img' => Vite::asset('resources/assets/images/page-tdf/chars-slider/Char-cocotte-crousty-chicken-Le-Gaulois.png'),
|
||||
'alt' => 'Char "La crousty mobile" avec une box de crousty chicken Le Gaulois',
|
||||
'title_img' => 'Char "La crousty mobile" Le Gaulois',
|
||||
'title' => 'La Crousty Mobile',
|
||||
'content' =>
|
||||
'Généreuse et gourmande, la Crousty Mobile saura vous régaler ! Et vous, à quelle occasion mangeriez-vous les Crousty Chicken ?',
|
||||
],
|
||||
[
|
||||
'img' => Vite::asset('resources/assets/images/page-tdf/chars-slider/Char-cocotte-cuisson-express-poulet-Le-Gaulois.png'),
|
||||
'alt' => 'Char "La cocotte express"avec le packaging du filet de poulet tranché Cuisson Express Le Gaulois',
|
||||
'title_img' => 'Char "La cocotte express" Le Gaulois',
|
||||
'title' => 'La Cocotte Express',
|
||||
'content' =>
|
||||
'Rapide à cuisiner, la Cocotte Express est dans la course ! Battra-t\'elle suffisamment des ailes pour décrocher le maillot jaune ?',
|
||||
],
|
||||
[
|
||||
'img' => Vite::asset(
|
||||
'resources/assets/images/page-tdf/chars-slider/Char-cocotte-blanc-poulet-sortant à l\'extérieur-Le-Gaulois.png',
|
||||
),
|
||||
'alt' => 'Char " La cocotte Sortant à l\'Extérieur" avec le packaging du blanc de poulet sortant à l\'extérieur Le Gaulois',
|
||||
'title_img' => 'Char " La cocotte Sortant à l\'Extérieur" Le Gaulois',
|
||||
'title' => 'La Cocotte Sortant à l\'extérieur',
|
||||
'content' =>
|
||||
'Sortant à l\'extérieur, la Cocotte profite de la lumière et de la nature pour observer nos plus belles régions de France. Selon vous, quelle est la meilleure étape du Tour ?',
|
||||
],
|
||||
[
|
||||
'img' => Vite::asset('resources/assets/images/page-tdf/chars-slider/Char-cocotte-filet-poulet-rôti-Le-Gaulois.png'),
|
||||
'alt' => 'Char "La cocotte rôtie"avec le packaging du filet de poulet rôti Le Gaulois',
|
||||
'title_img' => 'Char " La cocotte rôtie" Le Gaulois',
|
||||
'title' => 'La Cocotte Rôtie',
|
||||
'content' =>
|
||||
"Prête à consommer chaud ou froid, la Cocotte rôtie profite du Tour de France pour renforcer son bronzage. Et oui, c'est ça le secret du poulet rôti Le Gaulois !",
|
||||
],
|
||||
[
|
||||
'img' => Vite::asset('resources/assets/images/page-tdf/chars-slider/Char-cocotte-multiproduits-Le-Gaulois.png'),
|
||||
'alt' =>
|
||||
'Char " La cocotte roule ma poule" avec les packagings du poulet fumé, des brochettes de dinde, du crousty chicken et de la belle escalope Le Gaulois',
|
||||
'title_img' => 'Char " La cocotte roule ma poule" Le Gaulois',
|
||||
'title' => 'La Cocotte Roule ma poule',
|
||||
'content' =>
|
||||
'Sain et gourmand, le panier plaisir défile les étapes du Tour de France pour vous accompagner à mieux manger. Et vous, quelle est votre produit préféré Le Gaulois ?',
|
||||
],
|
||||
[
|
||||
'img' => Vite::asset('resources/assets/images/page-tdf/chars-slider/Char-cocotte-filet-poulet-Oui c\'est bon-Le-Gaulois.png'),
|
||||
'alt' => 'Char "La cocotte Oui c\'est Bon"avec le packaging du filet de poulet Oui c\'est Bon Le Gaulois',
|
||||
'title_img' => 'Char "La cocotte Oui c\'est Bon" Le Gaulois',
|
||||
'title' => 'La Cocotte Oui c\'est Bon',
|
||||
'content' =>
|
||||
'Tendre et de qualité, la Cocotte Oui c\'est Bon s\'adapte à tous les repas du quotidien, pour les petits et les grands ! Alors avez-vous retrouvé votre éleveur grâce à la traçabilité ?',
|
||||
],
|
||||
];
|
||||
$sliders = $model->data['discover_items']['value'];
|
||||
@endphp
|
||||
|
||||
<section class="position-relative bg-white-wood">
|
||||
|
|
@ -76,9 +7,8 @@
|
|||
<div class="row align-items-center justify-content-center">
|
||||
<div class="col-md-5"></div>
|
||||
<div class="col-md-4">
|
||||
<h2 class="fw-bold text-uppercase mb-4">Découvrez <span class="text-danger">nos
|
||||
chars</span>
|
||||
<span class="text-danger">"cocottes"</span>
|
||||
<h2 class="fw-bold text-uppercase mb-4">{{ $model->data['discover_title_1']['value'] }}
|
||||
<span class="text-danger">{{ $model->data['discover_title_2']['value'] }}</span>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -90,13 +20,15 @@
|
|||
<div class="swiper-slide">
|
||||
<div class="row align-items-center justify-content-center">
|
||||
<div class="col-md-6 text-center">
|
||||
<img class="img-fluid mb-3 increase-width" src="{{ $slide['img'] }}" title="{{ $slide['title_img'] }}"
|
||||
alt="{{ $slide['alt'] }}">
|
||||
<img class="img-fluid mb-3 increase-width" src="{{ asset($slide['picture']) }}" title="{{ $slide['picture_title'] }}"
|
||||
alt="{{ $slide['picture_alt'] }}">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="rounded-3 line-border-small bg-white p-4">
|
||||
<h4 class="text-uppercase text-danger mb-2">{{ $slide['title'] }}</h4>
|
||||
<p class="mb-0">{{ $slide['content'] }}</p>
|
||||
<h4 class="text-uppercase text-danger mb-2">{{ $slide['subtitle'] }}</h4>
|
||||
<div>
|
||||
{!! clean($slide['description']) !!}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,93 +1,112 @@
|
|||
<section class="bg-white-wood-big-reverse jeu-concours-section position-relative">
|
||||
<div class="d-flex justify-content-center jeu-concours-section-height container">
|
||||
<div @class([
|
||||
'd-flex justify-content-center jeu-concours-section-height container',
|
||||
'mt-16' => !$model->data['play_display_section']['value']
|
||||
])>
|
||||
<div class="row g-4 align-items-center">
|
||||
<div class="col-12 col-md-6">
|
||||
<div class="position-relative">
|
||||
<div class="d-flex justify-content-end w-100">
|
||||
<div class="position-relative game-100-percent-image-wrapper z-2">
|
||||
<img src="{{ Vite::asset('resources/assets/images/page-tdf/jeux-TDF-100% gagnant.svg') }}" alt="100% Gagnant">
|
||||
@if ($model->data['play_display_section']['value'])
|
||||
<div class="col-12 col-md-6">
|
||||
<div class="position-relative">
|
||||
<div class="d-flex justify-content-end w-100">
|
||||
<div class="position-relative game-100-percent-image-wrapper z-2">
|
||||
<img
|
||||
src="{{ asset($model->data['play_picture']['value']) }}"
|
||||
alt="{{ $model->data['play_picture']['alt'] }}"
|
||||
title="{{ $model->data['play_picture']['title'] }}"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-100 rounded-3 line-border-medium position-relative z-1 bg-white p-5 shadow">
|
||||
<h3 class="fw-bold text-uppercase mb-2">Jouez et tentez de gagner !</h3>
|
||||
<p class="mb-3">Participez à notre <a class="text-decoration-underline"
|
||||
href="https://www.legauloistourdefrance.fr/reglement" target="_blank"><strong>jeu 100% gagnant
|
||||
</strong></a> Le Gaulois pendant le
|
||||
Tour de France 2025.</p>
|
||||
<a class="btn btn-danger text-uppercase mb-4" href="https://www.legauloistourdefrance.fr" target="_blank">Je tente
|
||||
ma chance
|
||||
!</a>
|
||||
<div class="row text-center">
|
||||
<div class="col-4">
|
||||
<img class="images-100-percent mb-1"
|
||||
src="{{ Vite::asset('resources/assets/images/page-tdf/TV-home-cinéma.png') }}"
|
||||
title="5 Ensembles TV-Home cinéma à gagner"
|
||||
alt="Ensemble TV-Home cinéma à gagner pendant le jeu TDF 100% gagnant Le Gaulois">
|
||||
<div class="fw-bold text-uppercase">Ensembles TV + Home Cinema</div>
|
||||
<div class="w-100 rounded-3 line-border-medium position-relative z-1 bg-white p-5 shadow">
|
||||
<h3 class="fw-bold text-uppercase mb-2">{{ $model->data['play_title']['value'] }}</h3>
|
||||
<div class="mb-3">
|
||||
{!! clean($model->data['play_description']['value']) !!}
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<img class="images-100-percent mb-1"
|
||||
src="{{ Vite::asset('resources/assets/images/page-tdf/Casque-audios-oreilles-libres.png') }}"
|
||||
title="40 Casques audios oreilles libres à gagner"
|
||||
alt="Casques audios oreilles libres à gagner pendant le jeu TDF 100% gagnant Le Gaulois">
|
||||
<div class="fw-bold text-uppercase">casques audios oreilles libres</div>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<img class="images-100-percent mb-1"
|
||||
src="{{ Vite::asset('resources/assets/images/page-tdf/Bons-d-achat.png') }}"
|
||||
title="Milliers de bons d'achat à gagner"
|
||||
alt=" Bons de réduction à gagner pendant le jeu TDF 100% gagnant Le Gaulois">
|
||||
<div class="fw-bold text-uppercase">Bons d'achat</div>
|
||||
<a class="btn btn-danger text-uppercase mb-4" href="{{ $model->data['play_btn_url']['value'] }}" target="_blank">
|
||||
{{ $model->data['play_btn_text']['value'] }}
|
||||
</a>
|
||||
<div class="row text-center">
|
||||
<div class="col-4">
|
||||
<img class="images-100-percent mb-1"
|
||||
src="{{ asset($model->data['prize_picture_1']['value']) }}"
|
||||
title="{{ $model->data['prize_picture_1']['title'] }}"
|
||||
alt="{{ $model->data['prize_picture_1']['alt'] }}">
|
||||
<div class="fw-bold text-uppercase">{{ $model->data['prize_title_1']['value'] }}</div>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<img class="images-100-percent mb-1"
|
||||
src="{{ asset($model->data['prize_picture_2']['value']) }}"
|
||||
title="{{ $model->data['prize_picture_2']['title'] }}"
|
||||
alt="{{ $model->data['prize_picture_2']['alt'] }}">
|
||||
<div class="fw-bold text-uppercase">{{ $model->data['prize_title_2']['value'] }}</div>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<img class="images-100-percent mb-1"
|
||||
src="{{ asset($model->data['prize_picture_3']['value']) }}"
|
||||
title="{{ $model->data['prize_picture_3']['title'] }}"
|
||||
alt="{{ $model->data['prize_picture_3']['alt'] }}">
|
||||
<div class="fw-bold text-uppercase">{{ $model->data['prize_title_3']['value'] }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 d-flex flex-column position-relative" id="come-section">
|
||||
<div class="ms-md-5 position-relative z-2 bg-white shadow" id="come">
|
||||
@endif
|
||||
<div class="col-12 col-md-6 d-flex flex-column position-relative mx-auto" id="come-section">
|
||||
<div @class([
|
||||
'position-relative z-2 bg-white shadow',
|
||||
'ms-md-5' => $model->data['play_display_section']['value']
|
||||
]) id="come">
|
||||
<div class="d-flex align-items-center mb-2">
|
||||
<div class="point-exclamation me-3">
|
||||
<img src="{{ Vite::asset('resources/assets/images/page-tdf/point-exclamation.svg') }}"
|
||||
title="Point d'exclamation" alt="Point d'exclamation">
|
||||
<img
|
||||
src="{{ asset($model->data['find_us_picture']['value']) }}"
|
||||
title="{{ $model->data['find_us_picture']['title'] }}"
|
||||
alt="{{ $model->data['find_us_picture']['alt'] }}"
|
||||
/>
|
||||
</div>
|
||||
<span class="fw-bold text-uppercase fs-4">Venez nous retrouver sur le parcours du Tour de France</span>
|
||||
<span class="fw-bold text-uppercase fs-4">{{ $model->data['find_us_title']['value'] }}</span>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
{!! $model->data['find_us_description']['value'] !!}
|
||||
</div>
|
||||
<p class="mb-2"><b>Télécharger notre pancarte et retrouver nous sur la route du tour de France !</b></p>
|
||||
<p class="mb-3">Le Tour de France est un rendez-vous immanquable qui marque le début de la pause estivale. Venez
|
||||
nous rejoindre au bord des routes avec votre <strong>pancarte Cocotte Le Gaulois !</strong> Lorsque l’animateur du
|
||||
char
|
||||
d’ouverture de la caravane, Arthur, et ses acolytes caravaniers et caravanières vous repèrent, ils vous
|
||||
enverront des petits cadeaux.</p>
|
||||
<p><strong>Petit conseil :</strong> En agitant fièrement votre pancarte, vous augmenterez vos chances de recevoir
|
||||
des cadeaux !</p>
|
||||
<div class="d-flex flex-wrap gap-3">
|
||||
<a class="btn btn-secondary" href="{{ asset('tdf-downloads/Pancarte.pdf') }}" download>
|
||||
<a class="btn btn-secondary" href="{{ $model->data['find_us_btn_url_1']['value'] }}" download>
|
||||
<i class="fa-solid fa-arrow-down"></i>
|
||||
<span>Télécharger la pancarte</span>
|
||||
<span>{{ $model->data['find_us_btn_text_1']['value'] }}</span>
|
||||
</a>
|
||||
<a class="btn btn-light border" href="{{ asset('tdf-downloads/COLORIAGE - Avril 2024.pdf') }}" target="_blank">
|
||||
<a class="btn btn-light border" href="{{ $model->data['find_us_btn_url_2']['value'] }}" target="_blank">
|
||||
<i class="fa-solid fa-arrow-down"></i>
|
||||
<span>Télécharger des coloriages</span>
|
||||
<span>{{ $model->data['find_us_btn_text_2']['value'] }}</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-none d-md-block img-1-wrapper line-border-small position-absolute z-1 bg-white p-2">
|
||||
<div class="line-border-small">
|
||||
<img class="img-fluid" src="{{ Vite::asset('resources/assets/images/page-tdf/char.jpg') }}"
|
||||
title="Caravane Le Gaulois au mileu des supporters du Tour de France" alt="Chars de la caravane Le Gaulois">
|
||||
<img
|
||||
class="img-fluid"
|
||||
src="{{ asset($model->data['find_us_picture_1']['value']) }}"
|
||||
title="{{ $model->data['find_us_picture_1']['title'] }}"
|
||||
alt="{{ $model->data['find_us_picture_1']['alt'] }}"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-none d-md-block img-2-wrapper line-border-small position-absolute z-1 bg-white p-2">
|
||||
<div class="line-border-small">
|
||||
<img class="img-fluid" src="{{ Vite::asset('resources/assets/images/page-tdf/char-cuisson-express.jpg') }}"
|
||||
title="Char cocotte Cuisson Express traversant un pont lors d'une étape du Tour de France"
|
||||
alt="Char Cuisson Express Le Gaulois">
|
||||
<img
|
||||
class="img-fluid"
|
||||
src="{{ asset($model->data['find_us_picture_2']['value']) }}"
|
||||
title="{{ $model->data['find_us_picture_2']['title'] }}"
|
||||
alt="{{ $model->data['find_us_picture_2']['alt'] }}"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-lg-flex d-none justify-content-end w-75">
|
||||
<div @class([
|
||||
'd-lg-flex d-none justify-content-end w-75',
|
||||
'mt-24' => !$model->data['play_display_section']['value']
|
||||
])>
|
||||
<div class="d-flex justify-content-center w-25">
|
||||
<small>Crédit photo - ASO Aurélien Vialatte</small>
|
||||
<small>{{ $model->data['find_us_picture_author']['value'] }}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,39 +2,29 @@
|
|||
<div class="position-relative d-flex flex-column justify-content-center hero-section container pb-5 pt-5">
|
||||
<div class="row justify-content-center pt-5">
|
||||
<div class="col-12 col-lg-10 rounded-3 position-relative line-border-medium bg-white p-5 shadow">
|
||||
<span class="badge bg-warning fs-5 mb-2 p-2 text-white">TOUR DE FRANCE 2025</span>
|
||||
<div class="text-muted small mb-2">Accueil / Le Gaulois Le sponsor du Tour de France</div>
|
||||
<span class="badge bg-warning fs-5 mb-2 p-2 text-white">{{ $model->data['highlight_text']['value'] }}</span>
|
||||
<div class="text-muted small mb-2">{{ $model->subtitle }}</div>
|
||||
<div class="d-flex mb-1">
|
||||
<h1 class="fw-bold text-uppercase fs-1">Le Gaulois en selle pour le tour de
|
||||
France</h1>
|
||||
<h1 class="fw-bold text-uppercase fs-1">{{ $model->data['banner_title']['value'] }}</h1>
|
||||
</div>
|
||||
<div class="d-flex justify-content-around align-items-center mb-1">
|
||||
<p class="w-md-75 mb-3 w-100">
|
||||
Depuis 2015, Le Gaulois est fier d’être <strong>la volaille officielle du Tour de France</strong>. Un évènement
|
||||
populaire marquant le début de la pause estivale qui s’adresse à tous les Français, un rendez-vous immanquable pour des
|
||||
milliers de passionnés aux bords des routes ou devant leur télévision. <strong>La convivialité, le partage et la bonne
|
||||
humeur</strong>
|
||||
sont au rendez-vous et c’est ce <strong>bon vivre à la française</strong> que la caravane Le Gaulois véhicule en
|
||||
sillonnant les routes de
|
||||
France chaque année. Des milliers de cadeaux sont distribués pour ravir les petits comme les plus grands. La
|
||||
participation à cet évènement est également l’occasion de réaffirmer auprès du public, <strong>l’engagement sur
|
||||
l’origine 100%
|
||||
française des volailles Le Gaulois !</strong>
|
||||
</p>
|
||||
<div class="w-md-75 mb-3 w-100">
|
||||
{!! clean($model->content) !!}
|
||||
</div>
|
||||
<div class="d-flex align-items-center logo-tdf">
|
||||
<img src="{{ Vite::asset('resources/assets/images/page-tdf/logo-gaulois-tdf.jpg') }}"
|
||||
title="Logo volaille officielle de Le Gaulois et le Tour de France"
|
||||
alt="Logo volaille officielle de Le Gaulois et le Tour de France">
|
||||
<img src="{{ asset($model->data['banner_picture']['value']) }}"
|
||||
title="{{ $model->data['banner_picture']['title'] }}"
|
||||
alt="{{ $model->data['banner_picture']['alt'] }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex justify-content-center flex-wrap gap-3">
|
||||
<a class="btn btn-tertiary" href="#le-gaulois-et-le-tour-de-france">Le Gaulois et le Tour de France</a>
|
||||
<a class="btn btn-tertiary" href="#au-coeur-de-la-caravane">Au cœur de la caravane le Gaulois</a>
|
||||
<a class="btn btn-tertiary" href="#le-gaulois-et-le-tour-de-france">{{ $model->data['banner_button_title']['value'] }}</a>
|
||||
<a class="btn btn-tertiary" href="#au-coeur-de-la-caravane">{{ $model->data['banner_button_title_2']['value'] }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<div class="ms-md-5 mt-4 d-none d-md-block">
|
||||
<small>Crédit photo - ASO Aurélien Vialatte</small>
|
||||
<small>{{ $model->data['find_us_picture_author']['value'] }}</small>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,45 +1,48 @@
|
|||
<section class="bg-light pb-5" id="le-gaulois-et-le-tour-de-france">
|
||||
<div class="container">
|
||||
<h2 class="fw-bold text-uppercase mb-5 text-center">Le Gaulois et le Tour de France</h2>
|
||||
<h2 class="fw-bold text-uppercase mb-5 text-center">{{ $model->data['tdf_title']['value'] }}</h2>
|
||||
<div class="row align-items-center">
|
||||
<div class="col-md-6">
|
||||
<h3 class="fw-bold mb-4">Plus de 10 années <span class="text-danger"> de complicité avec le
|
||||
public</span>
|
||||
<h3 class="fw-bold mb-4">
|
||||
{{ $model->data['tdf_subtitle_1']['value'] }}
|
||||
<span class="text-danger">{{ $model->data['tdf_subtitle_2']['value'] }}</span>
|
||||
</h3>
|
||||
<p class="fs-5"><strong>Les chars « Cocottes » sont devenus emblématiques de la caravane du Tour de France.</strong>
|
||||
<strong>Dix-huit
|
||||
caravaniers passionnés</strong>,
|
||||
dont huit femmes et dix hommes de tous âges et venus de différentes régions de France, auront l’opportunité unique
|
||||
de piloter les mythiques « Cocottes » à travers le pays. Représentant <strong>la diversité et l’esprit de
|
||||
partage</strong>, ces
|
||||
caravaniers formeront une <strong>véritable famille</strong> pendant toute la durée du Tour, <strong>unis par leur
|
||||
amour du sport et leur
|
||||
engagement envers Le Gaulois.</strong> <br /> <br />
|
||||
Les huit chars Le Gaulois, représentant les produits phares de la marque, offrent au public l'occasion de découvrir
|
||||
ou redécouvrir la diversité des produits proposés : <strong>Crousty Chicken, Oui c’est Bon !, Cordon Bleu, Filets de
|
||||
Poulet
|
||||
Rôti, Blanc de Poulet Sortant à l’Extérieur, et Le Filet de Poulet Tranché Cuisson Express</strong> seront à
|
||||
l’honneur. Deux
|
||||
chars multiproduits, mettant en avant la diversité de la gamme, défileront également en tête de cortège avec à leur
|
||||
bord l’animateur Arthur pour enflammer les foules gauloises. En fin de défilé, le char « Roule ma Poule » viendra
|
||||
clore le spectacle, un clin d’œil toujours apprécié du public. <br /><br />
|
||||
Les chars iront à la rencontre des Français pour distribuer plus de 600 000 goodies Le Gaulois dans une atmosphère
|
||||
joyeuse et conviviale. Cette année, la marque offrira des <strong>capes supporters, des magnets décapsuleurs, et des
|
||||
milliers de bons de réduction</strong> pour découvrir les produits Le Gaulois en magasin.
|
||||
</p>
|
||||
<div class="fs-5">
|
||||
{!! clean($model->data['tdf_description']['value']) !!}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 text-center">
|
||||
<div class="position-relative bg-white p-2 shadow">
|
||||
<div class="ratio ratio-16x9 position-relative d-inline-block line-border-small w-100">
|
||||
@if (\App\Rules\IsValidYoutubeId::validates('hY0WPbkf4Ow'))
|
||||
<div class="video-inlaid h-100" type="youtube"
|
||||
href="https://www.youtube.com/embed/hY0WPbkf4Ow?autoplay=0&loop=1">
|
||||
<a class="cn-cookie-link" id="youtube-warning" href="" rel="nofollow">
|
||||
<strong class="text-underline text-bold text-normal text-danger">
|
||||
{{ __('cookie-notice.custom.youtube.warning') }}
|
||||
</strong>
|
||||
</a>
|
||||
</div>
|
||||
@if (!empty($model->data['tdf_media']['value']['video']))
|
||||
@php
|
||||
$videoId = $model->data['tdf_media']['value']['video']['id'];
|
||||
@endphp
|
||||
@if (\App\Rules\IsValidYoutubeId::validates($videoId))
|
||||
<div class="video-inlaid h-100" type="youtube"
|
||||
href="{{ sprintf("https://www.youtube.com/embed/%s?autoplay=0&loop=1", $videoId) }}">
|
||||
<a class="cn-cookie-link" id="youtube-warning" href="" rel="nofollow">
|
||||
<strong class="text-underline text-bold text-normal text-danger">
|
||||
{{ __('cookie-notice.custom.youtube.warning') }}
|
||||
</strong>
|
||||
</a>
|
||||
</div>
|
||||
@elseif (\App\Rules\IsValidVimeoId::validates($videoId))
|
||||
<div class="video-inlaid h-100" type="vimeo"
|
||||
href="{{ sprintf("https://player.vimeo.com/video/%s", $videoId) }}">
|
||||
<a class="cn-cookie-link" id="vimeo-warning" href="" rel="nofollow">
|
||||
<strong class="text-underline text-bold text-normal text-danger">
|
||||
{{ __('cookie-notice.custom.vimeo.warning') }}
|
||||
</strong>
|
||||
</a>
|
||||
</div>
|
||||
@endif
|
||||
@else
|
||||
<img
|
||||
src="{{ asset($model->data['tdf_media']['value']['picture']['path']) }}"
|
||||
alt="{{ $model->data['tdf_media']['value']['picture']['alt'] }}"
|
||||
title="{{ $model->data['tdf_media']['value']['picture']['title'] }}"
|
||||
/>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,78 +1,15 @@
|
|||
@php
|
||||
$slides = [
|
||||
[
|
||||
'name' => 'Nicolas',
|
||||
'alias' => 'Pimpom',
|
||||
'sign' => 'L\'ambianceur',
|
||||
'anecdote' =>
|
||||
'Nous cherchions un cri de guerre pour se motiver pour les étapes. Après avoir trouvé celui-ci, je ne sais pas pourquoi j’ai conclu par un cri de coq ! Résultat : il est resté jusqu\'à la fin du tour et même plus, il est passé au JT 19/20 sur France 3 Rhône-Alpes Auvergne.',
|
||||
'adventure' =>
|
||||
'Cette année 2023, je l’avoue, ce fût le meilleur de tous, grâce à une équipe hyper soudée, bosseuse et jamais fatiguée.',
|
||||
'img_url' => Vite::asset(
|
||||
'resources/assets/images/page-tdf/testimonials/Nicolas-Joly-caravanier-Le-Gaulois-Etienne-Coudret.jpg',
|
||||
),
|
||||
'img_alt' => 'Photo de Nicolas en tenue de caravanier Le Gaulois',
|
||||
'img_title' => 'Nicolas Joly caravanier Le Gaulois',
|
||||
'advice' =>
|
||||
'Etre à 200% du matin au soir, avoir le sourire en permanence et surtout ne pas avoir peur d’aller vers les autres !',
|
||||
'credit' => 'Crédit photo - Etienne Coudret',
|
||||
],
|
||||
[
|
||||
'name' => 'Mylène',
|
||||
'alias' => null,
|
||||
'sign' => 'Le boute-en-train',
|
||||
'anecdote' => "
|
||||
Dans mes meilleurs moments de cette année, il y a le moment de convivialité entre nous sur le parking de l’hôtel après avoir terminé le rechargement des cadeaux pour l’étape du lendemain. Nous avons mis la musique sur une enceinte et nous avons fait la chenille sur le parking. Tout le monde s’est pris au jeu et c’était vraiment un bon moment de rigolade. Il faut savoir que la chenille était notre danse de l’année avec les caravaniers Le Gaulois, on a lancé des chenilles un peu partout et même à une fête de village.",
|
||||
'adventure' =>
|
||||
'Faire partie de la caravane du Tour de France est avant tout une aventure humaine inoubliable. On y fait la rencontre de personnes toutes différentes mais avec la même envie de travailler dans la bonne humeur pendant 3 semaines de folie ! Le retour à la réalité a d’ailleurs été assez compliqué quand j’ai quitté les copains de la caravane Le Gaulois pour rentrer chez moi.',
|
||||
'img_url' => Vite::asset('resources/assets/images/page-tdf/testimonials/Mylène-Cornillet-caravaniere-Le-Gaulois.jpeg'),
|
||||
'img_alt' => 'Photo de Mylène sur un char Cocotte Le Gaulois',
|
||||
'img_title' => 'Mylène Cornillet caravanière Le Gaulois',
|
||||
'advice' =>
|
||||
'Je dirais que si c’est vraiment une expérience que l’on a envie de vivre, il faut persévérer et ne pas s’arrêter au premier refus. Il faut aussi se démarquer des autres candidats qui sont souvent très nombreux avec un CV qui attire le regard ou une lettre de motivation qui sort du lot. Mais le plus important, c’est surtout d’être authentique et de montrer sa véritable personnalité !',
|
||||
'credit' => 'Crédit photo - ASO Aurélien Vialatte',
|
||||
],
|
||||
[
|
||||
'name' => 'Thierry',
|
||||
'alias' => 'Titi',
|
||||
'sign' => 'Le sage',
|
||||
'anecdote' => "
|
||||
Sur une étape du Tour féminin, ma coéquipière est photographiée à proximité de Marion ROUSSE et elle ne la reconnait pas !! A l'arrivée du Tour féminin, je m'aperçois que j'ai fait tout le Tour avec mon accréditation du Tour de France masculin (signé Titi).",
|
||||
'adventure' =>
|
||||
'C\'est une chance de pouvoir vivre cet événement exceptionnel de l\'intérieur avec une équipe conviviale, soudée et sympathique.',
|
||||
'img_url' => Vite::asset(
|
||||
'resources/assets/images/page-tdf/testimonials/Thierry-Gilles-caravanier-Le-Gaulois-Etienne-Coudret.jpg',
|
||||
),
|
||||
'img_alt' => 'Photo de Thierry sur le parking des chars Le Gaulois',
|
||||
'img_title' => 'Thierry Gilles caravanier Le Gaulois',
|
||||
'advice' =>
|
||||
'Même si vous n\'y participez qu\'une seule fois, profitez de vivre ce moment exceptionnel tout en suivant attentivement les directives de l\'encadrement.',
|
||||
'credit' => 'Crédit photo - Etienne Coudret',
|
||||
],
|
||||
[
|
||||
'name' => 'Justine',
|
||||
'alias' => 'Ça percute !',
|
||||
'sign' => 'La floflo de Florence Foresti',
|
||||
'anecdote' => "
|
||||
Comme scène marquante, je dirais le nombre de spectateurs sur la route nous regardant comme des « stars ». Je n'ai pas de scène drôle en particulier dans ma tête, mais tous les soirs au « cul du camion » comme nous le disons, un débrief avec rigolade et humour est organisé avec toute l'équipe.",
|
||||
'adventure' => 'Une expérience INOUBLIABLE, INCROYABLE, MAGIQUE, MAGNIFIQUE',
|
||||
'img_url' => Vite::asset(
|
||||
'resources/assets/images/page-tdf/testimonials/Justine-Le-Guillou-caravanière-Le-Gaulois-A.S.O-Aurélien-Vialatte.jpg',
|
||||
),
|
||||
'img_alt' => 'Photo de Justine entourée de l\'équipe des caravaniers Le Gaulois',
|
||||
'img_title' => 'Justine Le Guillou caravanière Le Gaulois',
|
||||
'advice' => 'D’être soi-même, profiter pleinement de son aventure, d’être dynamique et avoir l’esprit d’équipe.',
|
||||
'credit' => 'Crédit photo - ASO Aurélien Vialatte',
|
||||
],
|
||||
];
|
||||
$slides = $model->data['testimonials_items']['value'];
|
||||
@endphp
|
||||
<section class="position-relative bg-white-wood-big-reverse pt-lg-5 pt-1" id="testimonial-section">
|
||||
<div class="container-fluid">
|
||||
<h2 class="fw-bold text-uppercase mb-5 text-center">Les témoignages des caravaniers</h2>
|
||||
<h2 class="fw-bold text-uppercase mb-5 text-center">
|
||||
{{ $model->data['testimonials_title']['value'] }}
|
||||
</h2>
|
||||
<div class="d-flex justify-content-center mb-5 flex-wrap gap-4" id="swiper-anecdote-tdf-badges">
|
||||
@foreach ($slides as $index => $slide)
|
||||
<button class="btn text-uppercase fs-5 fw-medium text-secondary px-4 py-1 shadow-none" data-slide-index="{{ $index }}">
|
||||
{{ $slide['name'] }}
|
||||
{{ $slide['title'] }}
|
||||
</button>
|
||||
@endforeach
|
||||
</div>
|
||||
|
|
@ -86,42 +23,34 @@
|
|||
<div class="row align-items-center mb-4">
|
||||
<div class="col-md-5">
|
||||
<div class="position-relative line-border-small bg-white p-2">
|
||||
<img class="img-fluid position-relative line-border-small w-100" src="{{ $slide['img_url'] }}"
|
||||
title="{{ $slide['img_title'] }}" alt="{{ $slide['img_alt'] }}">
|
||||
<img class="img-fluid position-relative line-border-small w-100" src="{{ asset($slide['picture']) }}"
|
||||
title="{{ $slide['picture_title'] }}" alt="{{ $slide['picture_alt'] }}">
|
||||
</div>
|
||||
<div class="ms-md-5 mt-lg-4 mt-0 mb-4 mb-lg-0">
|
||||
<small>{{ $slide['credit'] }}</small>
|
||||
<small>{{ $slide['picture_author'] }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="d-flex align-items-end gap-2">
|
||||
<h5 class="fs-2 text-uppercase fw-semibold">{{ $slide['name'] }}</h5>
|
||||
@if (!empty($slide['alias']))
|
||||
<div class="fs-3 text-muted f-bakerie-rough mb-2">alias {{ $slide['alias'] }}</div>
|
||||
<h5 class="fs-2 text-uppercase fw-semibold">{{ $slide['title'] }}</h5>
|
||||
@if (!empty($slide['subtitle']))
|
||||
<div class="fs-3 text-muted f-bakerie-rough mb-2">{{ $slide['subtitle'] }}</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="fs-5">
|
||||
<p><span class="text-uppercase"><b>Son signe distinctif</b></span> : {{ $slide['sign'] }}</p>
|
||||
|
||||
<div>
|
||||
<p class="text-uppercase"><b>Son anecdote du Tour de France</b> :</p>
|
||||
<p>{{ $slide['anecdote'] }}</p>
|
||||
</div>
|
||||
{!! clean($slide['description']) !!}
|
||||
</div>
|
||||
|
||||
<p class="text-uppercase fs-5 fw-bold">{{ _('Son aventure Le Gaulois') }}</p>
|
||||
<p class="fs-5">{{ $slide['adventure'] }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rounded-3 position-relative line-border-large bg-white p-5">
|
||||
<div>
|
||||
<p class="text-uppercase">
|
||||
<strong>Le conseil de <span class="mb-0 bg-secondary px-3 py-1 text-white">
|
||||
{{ $slide['name'] }}</span></strong>
|
||||
<strong>{{ $slide['subtitle_2'] }} <span class="mb-0 bg-secondary px-3 py-1 text-white">
|
||||
{{ $slide['title'] }}</span></strong>
|
||||
<br />
|
||||
<br />
|
||||
</p>
|
||||
{{ $slide['advice'] }}
|
||||
{!! clean($slide['description_2']) !!}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,16 @@
|
|||
@extends('fo.layout')
|
||||
@extends('fo.layout', ['brParam' => $staticPageModel])
|
||||
|
||||
@section('title', 'Le Gaulois | Volaille officielle du Tour de France')
|
||||
@section('description', 'Immergez-vous dans l\'ambiance du Tour de France avec Le Gaulois. Découvrez le jeu concours, les photos, anecdotes
|
||||
et témoignages de notre équipe.')
|
||||
@section('title', $staticPageModel->seo_title)
|
||||
@section('description', $staticPageModel->seo_description)
|
||||
@section('bg-offset', true)
|
||||
|
||||
@section('content')
|
||||
<div id="tdf">
|
||||
<x-fo.page-tdf.hero />
|
||||
<x-fo.page-tdf.game />
|
||||
<x-fo.page-tdf.ten-years />
|
||||
<x-fo.page-tdf.char-slider />
|
||||
<x-fo.page-tdf.au-coeur-de-la-caravane />
|
||||
<x-fo.page-tdf.testimonials />
|
||||
<x-fo.page-tdf.hero :model="$staticPageModel" />
|
||||
<x-fo.page-tdf.game :model="$staticPageModel" />
|
||||
<x-fo.page-tdf.ten-years :model="$staticPageModel" />
|
||||
<x-fo.page-tdf.char-slider :model="$staticPageModel" />
|
||||
<x-fo.page-tdf.au-coeur-de-la-caravane :model="$staticPageModel" />
|
||||
<x-fo.page-tdf.testimonials :model="$staticPageModel" />
|
||||
</div>
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -185,5 +185,5 @@ Route::middleware(['throttle:web'])->name('fo.')->group(function () {
|
|||
->name('ratings.store');
|
||||
|
||||
// * OTHERS
|
||||
Route::view('/tour-de-france', 'fo.pages.tdf')->name('tdf');
|
||||
Route::get('/tour-de-france', [StaticPageController::class, 'tdf'])->name('tdf');
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue