Compare commits
1 commit
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d83281f6a6 |
20 changed files with 507 additions and 74 deletions
45
app/Http/Controllers/Fo/NewsController.php
Normal file
45
app/Http/Controllers/Fo/NewsController.php
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Fo;
|
||||||
|
|
||||||
|
use App\Enums\StaticPageType;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\News;
|
||||||
|
use App\Models\Range;
|
||||||
|
use App\Models\StaticPage;
|
||||||
|
|
||||||
|
class NewsController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display the homepage.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\View
|
||||||
|
*/
|
||||||
|
public function index(): \Illuminate\Contracts\View\View
|
||||||
|
{
|
||||||
|
$staticPageModel = StaticPage::query()
|
||||||
|
->where('type', StaticPageType::news)
|
||||||
|
->firstOrFail();
|
||||||
|
$rangeModelList = Range::query()->limit(3)->inRandomOrder()->get();
|
||||||
|
|
||||||
|
$newsModelList = News::query()->get();
|
||||||
|
return view('fo.pages.news.index', compact(
|
||||||
|
'staticPageModel',
|
||||||
|
'newsModelList',
|
||||||
|
'rangeModelList'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a specific resource.
|
||||||
|
*
|
||||||
|
* @param \App\Models\News $frontNews
|
||||||
|
* @return \Illuminate\Contracts\View\View
|
||||||
|
*/
|
||||||
|
public function show(News $frontNews): \Illuminate\Contracts\View\View
|
||||||
|
{
|
||||||
|
return view('fo.pages.news.show', [
|
||||||
|
'newsModel' => $frontNews
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -42,6 +42,9 @@ class StoreNewsRequest extends FormRequest
|
||||||
public function rules(): array
|
public function rules(): array
|
||||||
{
|
{
|
||||||
$rules = [
|
$rules = [
|
||||||
|
'seo_title' => 'required|between:45,70',
|
||||||
|
'seo_description' => 'required|between:50,160',
|
||||||
|
'title' => 'required|string|between:3,100',
|
||||||
'text' => [
|
'text' => [
|
||||||
'required',
|
'required',
|
||||||
'string',
|
'string',
|
||||||
|
|
@ -78,6 +81,9 @@ class StoreNewsRequest extends FormRequest
|
||||||
public function attributes(): array
|
public function attributes(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
'seo_title' => trans('validation.custom.seo_title'),
|
||||||
|
'seo_description' => trans('validation.custom.seo_description'),
|
||||||
|
'title' => trans('validation.attributes.title'),
|
||||||
'text' => trans('validation.attributes.text'),
|
'text' => trans('validation.attributes.text'),
|
||||||
'picture_alt' => trans('validation.custom.picture_alt'),
|
'picture_alt' => trans('validation.custom.picture_alt'),
|
||||||
'picture_title' => trans('validation.custom.picture_title'),
|
'picture_title' => trans('validation.custom.picture_title'),
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,17 @@
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use App\Lib\Helpers\FileStorageHelper;
|
use App\Lib\Helpers\FileStorageHelper;
|
||||||
|
use App\Lib\Helpers\ToolboxHelper;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @property string $seo_title Utilisé pour la balise title de la page.
|
||||||
|
* @property string $seo_description Utilisé pour la balise meta description
|
||||||
|
* de la page.
|
||||||
|
* @property string $title Titre de la news.
|
||||||
|
* @property string $slug Slug à partir du titre de la news.
|
||||||
* @property string $picture Path de l'image (308px * 223px).
|
* @property string $picture Path de l'image (308px * 223px).
|
||||||
* @property string $picture_alt Attribut alt de l'image.
|
* @property string $picture_alt Attribut alt de l'image.
|
||||||
* @property string $picture_title Attribut title de l'image.
|
* @property string $picture_title Attribut title de l'image.
|
||||||
|
|
@ -27,6 +34,10 @@ class News extends Model
|
||||||
* @var array<int, string>
|
* @var array<int, string>
|
||||||
*/
|
*/
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
'seo_title',
|
||||||
|
'seo_description',
|
||||||
|
'title',
|
||||||
|
'slug',
|
||||||
'picture',
|
'picture',
|
||||||
'picture_alt',
|
'picture_alt',
|
||||||
'picture_title',
|
'picture_title',
|
||||||
|
|
@ -79,10 +90,30 @@ class News extends Model
|
||||||
*/
|
*/
|
||||||
private static function manageFields(self $model): void
|
private static function manageFields(self $model): void
|
||||||
{
|
{
|
||||||
|
// * ASSERTIONS
|
||||||
|
self::assertFieldIsUnique('title', $model->title, $model->id);
|
||||||
|
self::assertFieldIsUnique('slug', Str::slug($model->title), $model->id);
|
||||||
|
|
||||||
|
// * TRANSFORMATIONS
|
||||||
|
$model->title = Str::slug($model->title);
|
||||||
self::makeStatusSense($model);
|
self::makeStatusSense($model);
|
||||||
$model->picture = FileStorageHelper::storeFile($model, $model->picture, true);
|
$model->picture = FileStorageHelper::storeFile($model, $model->picture, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts using validation that the field is unique.
|
||||||
|
*
|
||||||
|
* @param string $nameField
|
||||||
|
* @param string $valueField
|
||||||
|
* @param integer|null $id
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private static function assertFieldIsUnique(string $nameField, string $valueField, ?int $id = null): void
|
||||||
|
{
|
||||||
|
$table = (new self())->getTable();
|
||||||
|
ToolboxHelper::assertFieldIsUnique($table, $nameField, $valueField, $id);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adjusts model status using current status and publish dates
|
* Adjusts model status using current status and publish dates
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ class Product extends Model
|
||||||
self::assertFieldIsUnique('slug', Str::slug($model->label), $model->id);
|
self::assertFieldIsUnique('slug', Str::slug($model->label), $model->id);
|
||||||
|
|
||||||
// * TRANSFORMATIONS
|
// * TRANSFORMATIONS
|
||||||
self::setSlug($model, $model->label);
|
$model->label = Str::slug($model->label);
|
||||||
$model->picture = FileStorageHelper::storeFile($model, $model->picture, true);
|
$model->picture = FileStorageHelper::storeFile($model, $model->picture, true);
|
||||||
$model->picture_thumbnail = FileStorageHelper::storeFile($model, $model->picture_thumbnail, true);
|
$model->picture_thumbnail = FileStorageHelper::storeFile($model, $model->picture_thumbnail, true);
|
||||||
}
|
}
|
||||||
|
|
@ -145,19 +145,6 @@ class Product extends Model
|
||||||
ToolboxHelper::assertFieldIsUnique($table, $nameField, $valueField, $id);
|
ToolboxHelper::assertFieldIsUnique($table, $nameField, $valueField, $id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the slug.
|
|
||||||
*
|
|
||||||
* @param self $model
|
|
||||||
* @param string $original
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
private static function setSlug(self $model, string $original): void
|
|
||||||
{
|
|
||||||
$model->slug = Str::slug($original);
|
|
||||||
}
|
|
||||||
|
|
||||||
// * RELATIONS
|
// * RELATIONS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ class RouteServiceProvider extends ServiceProvider
|
||||||
->group(base_path('routes/web-fo.php'));
|
->group(base_path('routes/web-fo.php'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Route::bind('frontNews', fn ($value) => News::query()->where('slug', $value)->firstOrFail());
|
||||||
Route::model('user', User::class);
|
Route::model('user', User::class);
|
||||||
Route::model('picto', Picto::class);
|
Route::model('picto', Picto::class);
|
||||||
Route::model('range', Range::class);
|
Route::model('range', Range::class);
|
||||||
|
|
|
||||||
62
database/migrations/2023_12_22_154506_update_news_table.php
Normal file
62
database/migrations/2023_12_22_154506_update_news_table.php
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
$news = DB::table('news')->get();
|
||||||
|
Schema::table('news', function (Blueprint $table) {
|
||||||
|
$table->string('seo_title')->after('id')
|
||||||
|
->comment('Utilisé pour la balise title de la page produit');
|
||||||
|
$table->string('seo_description')->after('seo_title')
|
||||||
|
->comment('Utilisé pour la balise meta description de la page produit');
|
||||||
|
$table->string('title')->after('seo_description')
|
||||||
|
->comment('Titre de la news');
|
||||||
|
$table->string('slug')->after('title')
|
||||||
|
->comment('Slug à partir du titre de la news');
|
||||||
|
$table->text('text')->change()
|
||||||
|
->comment('WYSIWYG - Texte de l\'actualité.');
|
||||||
|
});
|
||||||
|
$news->each(function (object $news) {
|
||||||
|
$title = fake()->unique()->jobTitle;
|
||||||
|
DB::table('news')->where('id', $news->id)
|
||||||
|
->update([
|
||||||
|
'seo_title' => fake()->words(3, true),
|
||||||
|
'seo_description' => fake()->words(7, true),
|
||||||
|
'title' => $title,
|
||||||
|
'slug' => Str::slug($title),
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
Schema::table('news', function (Blueprint $table) {
|
||||||
|
$table->unique('slug');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('news', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('seo_title');
|
||||||
|
$table->dropColumn('seo_description');
|
||||||
|
$table->dropColumn('title');
|
||||||
|
$table->dropColumn('slug');
|
||||||
|
$table->text('text')->change()
|
||||||
|
->comment('WYSIWYG - Texte de l\'actualité. Max 80 mots.');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
BIN
resources/assets/images/news/news-bg.jpg
Normal file
BIN
resources/assets/images/news/news-bg.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 86 KiB |
|
|
@ -12,7 +12,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// N'as rien à faire ici !!
|
// N'as rien à faire ici !!
|
||||||
.products, .history, .news {
|
.products, .history {
|
||||||
h1, h2 {
|
h1, h2 {
|
||||||
&::after {
|
&::after {
|
||||||
display: block;
|
display: block;
|
||||||
|
|
@ -39,3 +39,7 @@
|
||||||
opacity: 1 !important;
|
opacity: 1 !important;
|
||||||
visibility: visible !important;
|
visibility: visible !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.color-primary {
|
||||||
|
color: $color-primary !important;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
@import './pages/product';
|
@import './pages/product';
|
||||||
@import './pages/ranges';
|
@import './pages/ranges';
|
||||||
@import './pages/range';
|
@import './pages/range';
|
||||||
|
@import './pages/news-index';
|
||||||
|
|
||||||
// * PARTIALS
|
// * PARTIALS
|
||||||
@import './partials/news-section';
|
@import './partials/news-section';
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
.historypage {
|
.historypage,.newspage {
|
||||||
.ourproducts {
|
.ourproducts {
|
||||||
&::before {
|
&::before {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
@ -129,7 +129,7 @@
|
||||||
// X:::::X X:::::XL::::::::::::::::::::::L
|
// X:::::X X:::::XL::::::::::::::::::::::L
|
||||||
// XXXXXXX XXXXXXXLLLLLLLLLLLLLLLLLLLLLLLL
|
// XXXXXXX XXXXXXXLLLLLLLLLLLLLLLLLLLLLLLL
|
||||||
@include media-breakpoint-up(xl) {
|
@include media-breakpoint-up(xl) {
|
||||||
.historypage {
|
.historypage,.newspage {
|
||||||
.ourproducts {
|
.ourproducts {
|
||||||
.seagull {
|
.seagull {
|
||||||
top: 2.5rem;
|
top: 2.5rem;
|
||||||
|
|
|
||||||
28
resources/sass/fo/pages/_news-index.scss
Normal file
28
resources/sass/fo/pages/_news-index.scss
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
.newspage {
|
||||||
|
#swiper-news-index {
|
||||||
|
clip-path: inset(-2rem -50vw 0 0);
|
||||||
|
|
||||||
|
// .swiper-slide {
|
||||||
|
// max-width: 22rem;
|
||||||
|
// }
|
||||||
|
|
||||||
|
.swiper-button-prev-custom, .swiper-button-next-custom {
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-news::after {
|
||||||
|
position: relative;
|
||||||
|
top: -0.5rem;
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 1rem;
|
||||||
|
background-image: url('@/images/global/underline-yellow.svg');
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 3rem;
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -47,6 +47,26 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||||
}
|
}
|
||||||
// SWIPER
|
// SWIPER
|
||||||
const swiperConfig = {
|
const swiperConfig = {
|
||||||
|
"swiper-news-index": {
|
||||||
|
modules: [Navigation],
|
||||||
|
grabCursor: true,
|
||||||
|
slidesPerView: 1,
|
||||||
|
navigation: {
|
||||||
|
nextEl: ".swiper-button-next-custom",
|
||||||
|
prevEl: ".swiper-button-prev-custom",
|
||||||
|
},
|
||||||
|
breakpoints: {
|
||||||
|
500: {
|
||||||
|
slidesPerView: 2,
|
||||||
|
},
|
||||||
|
768: {
|
||||||
|
slidesPerView: 3,
|
||||||
|
},
|
||||||
|
1200: {
|
||||||
|
slidesPerView: 4,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
"swiper-news": {
|
"swiper-news": {
|
||||||
modules: [Navigation],
|
modules: [Navigation],
|
||||||
grabCursor: true,
|
grabCursor: true,
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,103 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{{-- TEXT --}}
|
{{-- SEO --}}
|
||||||
<div class="col-12 col-md-6 mb-3">
|
<div class="col-12 pb-3">
|
||||||
<fieldset class="h-100 border p-3">
|
<fieldset class="h-100 border p-3">
|
||||||
<legend>{{ Str::ucfirst(__('validation.attributes.text')) }}</legend>
|
<legend>{{ Str::ucfirst(__('validation.custom.seo')) }}</legend>
|
||||||
<div class="row">
|
<div class="row mb-3">
|
||||||
<div class="col-12">
|
{{-- SEO_TITLE --}}
|
||||||
|
<div class="col-12 col-md-6 m-md-0 mb-3">
|
||||||
@include('bo.partials.inputs.varchar', [
|
@include('bo.partials.inputs.varchar', [
|
||||||
'id' => 'newsText',
|
'id' => 'newsSeoTitle',
|
||||||
'label' => __(':field :inter:model', [
|
'label' => __(':field :inter:model', [
|
||||||
'field' => Str::ucfirst(__('validation.attributes.text')),
|
'field' => Str::ucfirst(__('validation.custom.seo_title')),
|
||||||
'inter' => __('validation.custom.of_the.vowel'),
|
'inter' => __('validation.custom.of_the.male'),
|
||||||
'model' => __('models.classes.news'),
|
'model' => __('models.classes.news'),
|
||||||
]),
|
]),
|
||||||
'hasWordCounter' => true,
|
'hasWordCounter' => true,
|
||||||
'name' => 'text',
|
'name' => 'seo_title',
|
||||||
'required' => true,
|
'required' => true,
|
||||||
'model' => $newsModel ?? null,
|
'model' => $newsModel ?? null,
|
||||||
'helper' => __('validation.string', [
|
'helper' => sprintf(
|
||||||
|
'%s %s',
|
||||||
|
__('crud.helpers.seo_title'),
|
||||||
|
__('validation.between.string', [
|
||||||
'attribute' => __(':field :inter:model', [
|
'attribute' => __(':field :inter:model', [
|
||||||
'field' => Str::ucfirst(__('validation.attributes.text')),
|
'field' => __('validation.custom.seo_title'),
|
||||||
'inter' => __('validation.custom.of_the.vowel'),
|
'inter' => __('validation.custom.of_the.female'),
|
||||||
'model' => __('models.classes.news'),
|
'model' => __('models.classes.news'),
|
||||||
]),
|
]),
|
||||||
|
'min' => 45,
|
||||||
|
'max' => 70,
|
||||||
|
])),
|
||||||
|
'placeholder' => __(':field :inter:model', [
|
||||||
|
'field' => Str::ucfirst(__('validation.custom.seo_title')),
|
||||||
|
'inter' => __('validation.custom.of_the.male'),
|
||||||
|
'model' => __('models.classes.news'),
|
||||||
]),
|
]),
|
||||||
'placeholder' => Str::ucfirst(__('validation.attributes.text')),
|
])
|
||||||
|
</div>
|
||||||
|
{{-- SEO_DESCRIPTION --}}
|
||||||
|
<div class="col-12 col-md-6 m-md-0 mb-3">
|
||||||
|
@include('bo.partials.inputs.varchar-multiline', [
|
||||||
|
'id' => 'newsSeoDescription',
|
||||||
|
'label' => __(':field :inter:model', [
|
||||||
|
'field' => Str::ucfirst(__('validation.custom.seo_description')),
|
||||||
|
'inter' => __('validation.custom.of_the.male'),
|
||||||
|
'model' => __('models.classes.news'),
|
||||||
|
]),
|
||||||
|
'hasWordCounter' => true,
|
||||||
|
'name' => 'seo_description',
|
||||||
|
'required' => true,
|
||||||
|
'model' => $newsModel ?? null,
|
||||||
|
'helper' => sprintf(
|
||||||
|
'%s %s',
|
||||||
|
__('crud.helpers.seo_description'),
|
||||||
|
__('validation.between.string', [
|
||||||
|
'attribute' => __(':field :inter:model', [
|
||||||
|
'field' => __('validation.custom.seo_description'),
|
||||||
|
'inter' => __('validation.custom.of_the.female'),
|
||||||
|
'model' => __('models.classes.news'),
|
||||||
|
]),
|
||||||
|
'min' => 50,
|
||||||
|
'max' => 160,
|
||||||
|
])),
|
||||||
|
'placeholder' => __(':field :inter:model', [
|
||||||
|
'field' => Str::ucfirst(__('validation.custom.seo_description')),
|
||||||
|
'inter' => __('validation.custom.of_the.male'),
|
||||||
|
'model' => __('models.classes.news'),
|
||||||
|
]),
|
||||||
|
])
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
{{-- TITLE --}}
|
||||||
|
<div class="col-12 col-md-6 mb-3">
|
||||||
|
<fieldset class="h-100 border p-3">
|
||||||
|
<legend>{{ Str::ucfirst(__('validation.attributes.title')) }}</legend>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
@include('bo.partials.inputs.varchar', [
|
||||||
|
'id' => 'newsTitle',
|
||||||
|
'label' => __(':field :inter:model', [
|
||||||
|
'field' => Str::ucfirst(__('validation.attributes.title')),
|
||||||
|
'inter' => __('validation.custom.of_the.male'),
|
||||||
|
'model' => __('models.classes.news'),
|
||||||
|
]),
|
||||||
|
'hasWordCounter' => true,
|
||||||
|
'name' => 'title',
|
||||||
|
'required' => true,
|
||||||
|
'model' => $newsModel ?? null,
|
||||||
|
'helper' => __('validation.between.string', [
|
||||||
|
'attribute' => __(':field :inter:model', [
|
||||||
|
'field' => __('validation.attributes.title'),
|
||||||
|
'inter' => __('validation.custom.of_the.male'),
|
||||||
|
'model' => __('models.classes.news'),
|
||||||
|
]),
|
||||||
|
'min' => 3,
|
||||||
|
'max' => 100,
|
||||||
|
]),
|
||||||
|
'placeholder' => __('Un titre clair et concis'),
|
||||||
])
|
])
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -103,6 +177,28 @@
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
|
{{-- TEXT --}}
|
||||||
|
<div class="col-12 mb-3">
|
||||||
|
<fieldset class="border p-3">
|
||||||
|
<legend>{{ Str::ucfirst(__('validation.attributes.text')) }}</legend>
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col-12">
|
||||||
|
@include('bo.partials.inputs.text-html', [
|
||||||
|
'id' => 'newsDescription',
|
||||||
|
'label' => __(':field :inter:model', [
|
||||||
|
'field' => Str::ucfirst(__('validation.attributes.text')),
|
||||||
|
'inter' => __('validation.custom.of_the.male'),
|
||||||
|
'model' => __('models.classes.news'),
|
||||||
|
]),
|
||||||
|
'name' => 'text',
|
||||||
|
'model' => $newsModel ?? null,
|
||||||
|
'required' => true,
|
||||||
|
'helper' => __('crud.minicrud.text_warning'),
|
||||||
|
])
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
{{-- PUBLISHED --}}
|
{{-- PUBLISHED --}}
|
||||||
<div class="col-12 col-md-6 mb-3">
|
<div class="col-12 col-md-6 mb-3">
|
||||||
<fieldset class="h-100 border p-3">
|
<fieldset class="h-100 border p-3">
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
'url' => route('fo.ranges.index'),
|
'url' => route('fo.ranges.index'),
|
||||||
'text' => __('Nos produits'),
|
'text' => __('Nos produits'),
|
||||||
'title' => __('Nos produits'),
|
'title' => __('Nos produits'),
|
||||||
'is_active' => request()->routeIs('fo.ranges.index'),
|
'is_active' => request()->routeIs('fo.ranges.*'),
|
||||||
'sub_menu_list' => $ranges,
|
'sub_menu_list' => $ranges,
|
||||||
])
|
])
|
||||||
</li>
|
</li>
|
||||||
|
|
@ -42,6 +42,14 @@
|
||||||
'is_active' => request()->routeIs('fo.commitments.show'),
|
'is_active' => request()->routeIs('fo.commitments.show'),
|
||||||
])
|
])
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
@include('fo.layouts.nav-link', [
|
||||||
|
'url' => route('fo.news.index'),
|
||||||
|
'text' => __('Nos actualités'),
|
||||||
|
'title' => __('Nos actualités'),
|
||||||
|
'is_active' => request()->routeIs('fo.news.*'),
|
||||||
|
])
|
||||||
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
@include('fo.layouts.nav-link', [
|
@include('fo.layouts.nav-link', [
|
||||||
'url' => route('fo.klub.home'),
|
'url' => route('fo.klub.home'),
|
||||||
|
|
|
||||||
|
|
@ -63,39 +63,7 @@
|
||||||
<div class="historical-milestones-slider" data-json='@json($data)'></div>
|
<div class="historical-milestones-slider" data-json='@json($data)'></div>
|
||||||
</section>
|
</section>
|
||||||
{{-- OUR PRODUCTS --}}
|
{{-- OUR PRODUCTS --}}
|
||||||
<section class="ourproducts position-relative">
|
@include('fo.partials.our-products', ['rangeModels' => $rangeModels])
|
||||||
<div class="bg-tertiary px-0 pt-5">
|
|
||||||
<div class="container">
|
|
||||||
<div class="row">
|
|
||||||
<h2 class="col fs-1 text-primary text-center">{{ __('Découvrez nos produits') }}</h2>
|
|
||||||
</div>
|
|
||||||
<div class="position-relative d-flex flex-column flex-xl-row justify-content-center">
|
|
||||||
@foreach ($rangeModels as $key => $rangeModel)
|
|
||||||
<div class="d-flex flex-column justify-content-center align-items-center mx-md-1 mx-lg-2 mx-xxl-4 m-0">
|
|
||||||
<div class="position-relative py-3 text-center">
|
|
||||||
<img class="rounded-circle w-100 h-auto" src="{{ asset($rangeModel->picture_ambiance) }}"
|
|
||||||
title="{{ $rangeModel->picture_ambiance_title }}" alt="{{ $rangeModel->picture_ambiance_alt }}">
|
|
||||||
<img class="ourproducts-ellipse position-absolute translate-middle start-50 top-50 h-auto"
|
|
||||||
alt="cercle fin de couleur blanc"
|
|
||||||
@if ($key % 2) src="{{ Vite::asset('resources/assets/images/global/ellipse_white.png') }}"
|
|
||||||
@else
|
|
||||||
src="{{ Vite::asset('resources/assets/images/global/ellipse_blue.png') }}" @endif>
|
|
||||||
</div>
|
|
||||||
<a class="ourproducts-btn btn @if ($key % 2) btn-white btn-rotate-right @else btn-primary btn-rotate-left @endif fs-4 my-2 px-4"
|
|
||||||
href="{{ route('fo.ranges.show', $rangeModel->slug) }}"
|
|
||||||
title="{{ __('Voir les produits de la gamme') }} {{ $rangeModel->label }}">
|
|
||||||
{{ Str::limit(__($rangeModel->label), 30) }}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
@endforeach
|
|
||||||
</div>
|
|
||||||
<div class="d-none d-xl-block seagull-column me-4">
|
|
||||||
<img class="img-fluid position-absolute end-0" id="seagulls-scroll" data-offset="16"
|
|
||||||
src="{{ Vite::asset('resources/assets/images/global/mouettes.svg') }}" alt="{{ __('Ombre de mouettes') }}">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
{{-- NEWS --}}
|
{{-- NEWS --}}
|
||||||
@include('fo.partials.news-section')
|
@include('fo.partials.news-section')
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
95
resources/views/fo/pages/news/index.blade.php
Normal file
95
resources/views/fo/pages/news/index.blade.php
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
@extends('fo.layout')
|
||||||
|
|
||||||
|
@section('title', $staticPageModel->seo_title)
|
||||||
|
@section('description', $staticPageModel->seo_description)
|
||||||
|
@section('breadcrumb',
|
||||||
|
request()->route()->getName())
|
||||||
|
|
||||||
|
@section('main-bg-class', 'has-banner newspage')
|
||||||
|
|
||||||
|
{{-- @section('banner')
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col g-0">
|
||||||
|
<img class="img-fluid banner-picture object-fit-cover w-100" src="{{ Vite::asset('resources/assets/images/news/news-bg.jpg') }}"
|
||||||
|
alt="{{ __('Bannière de la page actualités') }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection --}}
|
||||||
|
|
||||||
|
@section('banner')
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row position-relative bulle-banner">
|
||||||
|
<div class="col-12 g-0">
|
||||||
|
<img class="img-fluid banner-picture object-fit-cover w-100 h-100 z-n1 position-relative"
|
||||||
|
src="{{ Vite::asset('resources/assets/images/news/news-bg.jpg') }}" alt="{{ __('Bannière de la page nos engagements') }}">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Nos Engagements header (mobile hide) --}}
|
||||||
|
<div class="col-12 d-none d-xl-block position-absolute translate-middle-y col-6 g-0 top-50 start-0">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-7 col-xx-6 div-bulle px-5 py-3">
|
||||||
|
<div class="p-5">
|
||||||
|
<div class="text-center">
|
||||||
|
<h1 class="fs-1 f-intro-head-h-base text-primary text-center">{{ $staticPageModel->title }}</h1>
|
||||||
|
<img class="img-fluid flex-shrink-1 mb-3 flex-grow-0"
|
||||||
|
src="{{ Vite::asset('resources/assets/images/global/underline-yellow.svg') }}"
|
||||||
|
alt="{{ __('Trait souligné') }}">
|
||||||
|
</div>
|
||||||
|
<div class="ck-content">{!! clean($staticPageModel->content) !!}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<section class="bg-light-top-tear container-fluid mt-0 pb-5">
|
||||||
|
<div class="row justify-content-center pt-5">
|
||||||
|
<div class="col-12 col-lg-10 g-0">
|
||||||
|
{{-- SWIPER NEWS --}}
|
||||||
|
<div class="swiper" id="swiper-news-index">
|
||||||
|
<div class="swiper-wrapper">
|
||||||
|
@foreach ($newsModelList as $newsModel)
|
||||||
|
<div class="swiper-slide">
|
||||||
|
<div class="card rounded-5 mx-3">
|
||||||
|
<img class="card-img-top rounded-top-5" src="{{ asset($newsModel->picture) }}"
|
||||||
|
title="{{ $newsModel->picture_title }}" alt="{{ $newsModel->picture_alt }}">
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="card-text">
|
||||||
|
{{ Str::limit(strip_tags($newsModel->text), 150, '...') }}
|
||||||
|
</p>
|
||||||
|
<a class="link-primary fs-5 link-news text-decoration-none d-block fw-bold text-center"
|
||||||
|
href="{{ route('fo.news.show', $newsModel) }}"
|
||||||
|
title="{{ __('Aller sur la page d\'actualité :name', ['name' => $newsModel->picture_title]) }}">
|
||||||
|
{{ __('En savoir plus') }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-start mx-5 mt-4">
|
||||||
|
<div class="swiper-button swiper-button-prev-custom mx-3">
|
||||||
|
<button class="btn btn-light color-primary" data-bs-toggle="tooltip" title="{{ __('Voir les news precentes') }}">
|
||||||
|
<i class="fa-solid fa-chevron-left"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="swiper-button swiper-button-next-custom mx-3">
|
||||||
|
<button class="btn btn-light color-primary" data-bs-toggle="tooltip" title="{{ __('Voir les news suivantes') }}">
|
||||||
|
<i class="fa-solid fa-chevron-right"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{{-- OUR PRODUCTS --}}
|
||||||
|
@include('fo.partials.our-products', ['rangeModels' => $rangeModelList])
|
||||||
|
@endsection
|
||||||
42
resources/views/fo/pages/news/show.blade.php
Normal file
42
resources/views/fo/pages/news/show.blade.php
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
@extends('fo.layout')
|
||||||
|
|
||||||
|
@section('title', __($newsModel->seo_title))
|
||||||
|
@section('description', __($newsModel->seo_description))
|
||||||
|
@section('breadcrumb',
|
||||||
|
request()->route()->getName())
|
||||||
|
|
||||||
|
@section('main-bg-class', 'has-banner newspage-show')
|
||||||
|
|
||||||
|
@section('banner')
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col g-0">
|
||||||
|
<img class="img-fluid banner-picture object-fit-cover w-100" src="{{ Vite::asset('resources/assets/images/news/news-bg.jpg') }}"
|
||||||
|
alt="{{ __('Bannière de la page actualités') }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="bg-light-top-tear container-fluid mt-0 pb-5">
|
||||||
|
<div class="col-12 mb-3 text-center">
|
||||||
|
<h1 class="fs-1 f-intro-head-h-base text-primary">
|
||||||
|
{{ $newsModel->title }}
|
||||||
|
</h1>
|
||||||
|
<img class="img-fluid mb-3" src="{{ Vite::asset('resources/assets/images/global/underline-yellow.svg') }}"
|
||||||
|
alt="{{ __('Trait souligné') }}">
|
||||||
|
</div>
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col text-center">
|
||||||
|
<img class="img-fluid" src="{{ asset($newsModel->picture) }}" title="{{ $newsModel->picture_title }}"
|
||||||
|
alt="{{ $newsModel->picture_alt }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row justify-content-center mb-5">
|
||||||
|
<div class="col-md-11 col-lg-9 ck-content">
|
||||||
|
{!! clean($newsModel->text) !!}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
@ -7,9 +7,10 @@
|
||||||
<p>
|
<p>
|
||||||
{{ __('Découvrez les dernières actualités croustillantes de Tre Galette ! Retrouvez tous nos événements très bretons, nos idées de recette et nos conseils très gourmands. Un voyage gourmand en Bretagne vous attend ! ') }}
|
{{ __('Découvrez les dernières actualités croustillantes de Tre Galette ! Retrouvez tous nos événements très bretons, nos idées de recette et nos conseils très gourmands. Un voyage gourmand en Bretagne vous attend ! ') }}
|
||||||
</p>
|
</p>
|
||||||
{{-- TODO: Changer le lien quand la page actualité index sera faite. --}}
|
<a class="btn btn-tertiary btn-rotate-left fs-2 px-4" href="{{ route('fo.news.index') }}"
|
||||||
<a class="btn btn-tertiary btn-rotate-left fs-2 px-4" href="#CHANGEME"
|
title="{{ __('Se rendre sur la page Nos actualités') }}">
|
||||||
title="{{ __('Nos actualités') }}">{{ __('Nos actualités') }}</a>
|
{{ __('Nos actualités') }}
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-lg-8">
|
<div class="col-12 col-lg-8">
|
||||||
{{-- SWIPER NEWS --}}
|
{{-- SWIPER NEWS --}}
|
||||||
|
|
@ -25,7 +26,7 @@
|
||||||
title="{{ $news->picture_title }}" alt="{{ $news->picture_alt }}">
|
title="{{ $news->picture_title }}" alt="{{ $news->picture_alt }}">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<p class="card-text">
|
<p class="card-text">
|
||||||
{{ $news->text }}
|
{{ Str::limit(strip_tags($news->text), 150, '...') }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
33
resources/views/fo/partials/our-products.blade.php
Normal file
33
resources/views/fo/partials/our-products.blade.php
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
<section class="ourproducts position-relative">
|
||||||
|
<div class="bg-tertiary px-0 pt-5">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<h2 class="col fs-1 text-primary text-center">{{ __('Découvrez nos produits') }}</h2>
|
||||||
|
</div>
|
||||||
|
<div class="position-relative d-flex flex-column flex-xl-row justify-content-center">
|
||||||
|
@foreach ($rangeModels as $key => $rangeModel)
|
||||||
|
<div class="d-flex flex-column justify-content-center align-items-center mx-md-1 mx-lg-2 mx-xxl-4 m-0">
|
||||||
|
<div class="position-relative py-3 text-center">
|
||||||
|
<img class="rounded-circle w-100 h-auto" src="{{ asset($rangeModel->picture_ambiance) }}"
|
||||||
|
title="{{ $rangeModel->picture_ambiance_title }}" alt="{{ $rangeModel->picture_ambiance_alt }}">
|
||||||
|
<img class="ourproducts-ellipse position-absolute translate-middle start-50 top-50 h-auto"
|
||||||
|
alt="cercle fin de couleur blanc"
|
||||||
|
@if ($key % 2) src="{{ Vite::asset('resources/assets/images/global/ellipse_white.png') }}"
|
||||||
|
@else
|
||||||
|
src="{{ Vite::asset('resources/assets/images/global/ellipse_blue.png') }}" @endif>
|
||||||
|
</div>
|
||||||
|
<a class="ourproducts-btn btn @if ($key % 2) btn-white btn-rotate-right @else btn-primary btn-rotate-left @endif fs-4 my-2 px-4"
|
||||||
|
href="{{ route('fo.ranges.show', $rangeModel->slug) }}"
|
||||||
|
title="{{ __('Voir les produits de la gamme') }} {{ $rangeModel->label }}">
|
||||||
|
{{ Str::limit(__($rangeModel->label), 30) }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
<div class="d-none d-xl-block seagull-column me-4">
|
||||||
|
<img class="img-fluid position-absolute end-0" id="seagulls-scroll" data-offset="16"
|
||||||
|
src="{{ Vite::asset('resources/assets/images/global/mouettes.svg') }}" alt="{{ __('Ombre de mouettes') }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Http\Controllers\Fo\NewsController;
|
||||||
use App\Http\Controllers\Fo\ContactController;
|
use App\Http\Controllers\Fo\ContactController;
|
||||||
use App\Http\Controllers\Fo\HomeController;
|
use App\Http\Controllers\Fo\HomeController;
|
||||||
use App\Http\Controllers\Fo\Klub\CustomerController;
|
use App\Http\Controllers\Fo\Klub\CustomerController;
|
||||||
|
|
@ -55,6 +56,10 @@ Route::middleware(['throttle:credentials'])->name('fo.')->group(function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// * NEWS
|
||||||
|
Route::get('/actualites', [NewsController::class, 'index'])->name('news.index');
|
||||||
|
Route::get('/actualites/{frontNews:slug}', [NewsController::class, 'show'])->name('news.show');
|
||||||
|
|
||||||
// * RANGES
|
// * RANGES
|
||||||
Route::get('/gammes', [RangeController::class, 'index'])->name('ranges.index');
|
Route::get('/gammes', [RangeController::class, 'index'])->name('ranges.index');
|
||||||
Route::get('/gamme/{slug}', [RangeController::class, 'show'])->name('ranges.show');
|
Route::get('/gamme/{slug}', [RangeController::class, 'show'])->name('ranges.show');
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue