add news.index + news.show pages
This commit is contained in:
parent
705aa7c522
commit
bdbbb9ff9a
23 changed files with 698 additions and 36 deletions
66
app/Http/Controllers/Fo/NewsController.php
Normal file
66
app/Http/Controllers/Fo/NewsController.php
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Fo;
|
||||
|
||||
use App\Enums\StaticPageType;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
use App\Models\News;
|
||||
use App\Models\StaticPage;
|
||||
use Illuminate\Contracts\Database\Query\Builder;
|
||||
|
||||
class NewsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(): \Illuminate\Contracts\View\View
|
||||
{
|
||||
/** @var \App\Models\StaticPage $staticPageModel */
|
||||
$staticPageModel = StaticPage::query()->where('type', StaticPageType::news)->firstOrFail();
|
||||
|
||||
/** @var \App\Models\News $newsModels */
|
||||
$newsModels = News::query()->where('published', true)->orderBy('publish_at', 'desc')->get();
|
||||
return view('fo.pages.news.index', \compact('staticPageModel', 'newsModels'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a news articles
|
||||
*
|
||||
* @param string $slug
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function show(string $slug): \Illuminate\Contracts\View\View
|
||||
{
|
||||
/** @var \App\Models\News $newsModel */
|
||||
$newsModel = News::query()
|
||||
->where('published', true)
|
||||
->where('slug', $slug)
|
||||
->firstOrFail();
|
||||
return view('fo.pages.news.show', \compact('newsModel'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get filtered news.
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function newsFiltered(): \Illuminate\Http\JsonResponse
|
||||
{
|
||||
$categoryId = ToolboxHelper::getValidatedEnum(
|
||||
0,
|
||||
'category',
|
||||
'\App\Enums\News\CategoryEnum',
|
||||
);
|
||||
$newsModels = News::query()
|
||||
->where('published', true)
|
||||
->when($categoryId != 0, function (Builder $query) use ($categoryId) {
|
||||
$query->where('category', $categoryId);
|
||||
})
|
||||
->orderBy('publish_at', 'desc')
|
||||
->get();
|
||||
return response()->json($newsModels);
|
||||
}
|
||||
}
|
||||
|
|
@ -167,7 +167,6 @@ trait BaseEnum
|
|||
return $this->value;
|
||||
}
|
||||
|
||||
|
||||
// * CACHE
|
||||
|
||||
/**
|
||||
|
|
|
|||
13
resources/assets/images/global/bg-grey-desktop.svg
Normal file
13
resources/assets/images/global/bg-grey-desktop.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 6.1 KiB |
14
resources/assets/images/socials/facebook-white-logo.svg
Normal file
14
resources/assets/images/socials/facebook-white-logo.svg
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Calque_2" data-name="Calque 2"
|
||||
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 35.69 35.69">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
stroke-width: 0px;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="UNE_ACTU" data-name="UNE ACTU">
|
||||
<path class="cls-1" d="m35.46,24.22c-.08-.08.16-.13,0-.19.22-.17-.23-.34.06-.49-.16-.12.08-.29,0-.46-.24-.08.07-.2-.1-.29.21-.25-.18-.51.06-.73.09-.16-.2-.3.06-.44l-.15-.61c.09-.05.11-.1.05-.17.17-.08.12-.24.06-.34.07-.04.05-.09-.05-.12.08-.16.08-.35,0-.51.08-.36.09-.86.01-1.21.28-.32-.09-.6.11-.9-.17-.14-.11-.35-.05-.51-.28-.07.09-.17-.1-.27.37-.14-.28-.28.06-.41-.32-.12.24-.19.06-.34-.2-.28.09-.65-.15-.95.15-.2-.05-.4,0-.59.1-.23.05-.56.07-.8-.04-.17.1-.42-.11-.58.35-.1.02-.27.12-.41-.28-.09.09-.21-.11-.32.18-.12.13-.32.06-.46-.12.05-.25.05-.37,0,.02.06-.14.14-.16.2l-.02-2.5s.02.03.05.05l.16-.02c.09.03.12.08.1.12-.05.04-.17.02-.26.02.12.04.47.12.36.24-.44.08.2.2-.16.29-.13-.03-.1-.09-.1-.15h-.1c.02.18-.12.41.31.49-.13.09-.36.09-.26.22.03.04.18.04.26.07-.28.1.13.26-.27.32-.05.21-.24.61.47.61.08-.41-.1-.77.12-1.14-.33-.21.2-.41-.05-.63-.36-.09.02-.23-.11-.36.18-.13.13-.34.06-.49.03-.11.21-.25,0-.34.18-.16-.11-.35.06-.48,0-.46-.19-.93-.04-1.39-.18-.16.09-.3-.1-.44.24-.06-.05-.14.11-.22-.04-.05-.14-.02-.21-.03-.18.06-.03.14-.05.22-.05.03-.13.04-.21.05.1.15.22.28.26.44-.21.1.21.26-.16.31l.21.08c.03.07-.04.13-.16.17-.05,0-.13,0-.16-.02-.01.12-.21.24-.06.37-.09.11.15.26,0,.39-.07.11.33.08.21.2-.03.01-.05.03-.1.02.09.13-.21.24.05.34l.05-.02c.07,0,.17-.02.21.02-.14.07-.13.19-.37.22l.05.02c.04.08-.04.2-.16.29l-.06-7.85.13.61c-.11.12-.03.29-.06.39l.22-.02c.08.04.21.08.16.14-.66.27-.3.73-.33,1.12.1.02.15-.03.22-.05.14,0,.14.08.21.12.18-.24-.11-.49.06-.73.2-.15-.06-.33-.05-.51.18-.18.12-.44.06-.63.17-.21.17-.5,0-.71.2-.15-.17-.32.11-.46-.22-.15.28-.22.12-.39,0-.11-.2-.18-.21-.29-.18-.03-.42-.03-.63-.02v-.03h-.11c.11,0,.22,0,.32,0l-.05-.1c.1-.06.22-.09.39-.07-.73-.04-1.59-.16-2.29,0-.38-.1-.87-.01-1.29,0l-.05-.03c-.17-.03-.47-.06-.61.02-.23-.15-.41.07-.72,0-.41-.16-1.08-.02-1.62-.03-.16-.08-.5-.16-.67-.03-.56.08-1.09.05-1.68.02-.6-.03-1.43.07-2.06,0-.26,0-.67.02-.95-.03-.28.11-.66.06-.94,0-.35.09-.74-.08-1.06.05-.54-.15-1.05.05-1.62.02-.42-.08-1.02-.04-1.45.02-.49.02-1.13-.1-1.62,0-.68-.02-1.35.02-2.07-.03-.37.04-.86-.09-1.23.02-.07,0-.18.02-.22-.03-.32-.04-.76-.05-1.01.07-.27-.11-.57.01-.89-.05-.61.13-1.23-.03-1.85-.05-1.34.06-2.79.08-4.13.07-.32.14-.71-.05-1.06.05-.64-.06-1.2,0-1.84-.06-.31.08-.57-.02-.9.05-.32-.14-.59.09-.95.05l.28.23-.02,1.32c-.13-.01-.29,0-.42,0-.23.23-.23.53-.22.78-.28.07.09.17-.11.24.5.25-.5.53.37.68-.15.05-.27.12-.22.22.04.14-.1.37.1.51-.08.26-.08.56,0,.83.01.26-.04.5.04.78-.05.02-.08.06-.16.05.13.26,0,.47.04.75.35.06-.01.17.1.27-.2.11-.07.27-.11.41.33.12-.12.3.1.46-.28.15.09.33-.06.49.2.13-.17.27.11.39-.28.12.21.29-.12.41.09.13,0,.23.11.36-.22.12.21.26-.17.34.13.2-.06.37.16.56-.03.06.06.14-.11.17.28.07-.09.19.11.24-.22.31-.04.72-.17,1.02.1.08.16.2.16.27-.07.09.1.13.16.2-.41.05.14.23-.32.22l.1.1c-.16.19-.16.47,0,.66-.1.41-.05.87-.07,1.26.2.11-.17.24.11.34-.27.14.29.25,0,.37-.09.01-.11-.03-.16-.05-.01.07.01.14.1.2.01.15-.28.34.05.46-.06.24-.12.47-.17.71.16.19-.08.4,0,.58-.47.13.19.29.21.44-.1.04-.09.14-.27.12l.05.24c-.08.16.4.3,0,.44-.01.06,0,.14.16.14l-.16.07s.06.06.05.1c-.16.27.07.56,0,.83-.45.13.45.26-.16.37,0,.05-.03.11.1.14.01.1.2.2.05.29.16.21-.1.46.1.68-.27.08.04.14.1.22-.34.14.21.35-.11.51-.52.07.14.26.05.41-.53.18.13.45-.17.7.31.21-.18.49.21.68.01.05-.01.09-.11.12-.18.2.11.42-.06.59.14.14-.06.35.16.49.07.05.12.16-.05.19-.05,0-.14,0-.16-.02,0,.14.2.23.21.37-.14.07-.2.15-.22.24.33.14-.2.26.05.41-.32.22.16.44,0,.66-.09.15.36.07.32.22-.47.1-.23.37-.21.53.38.18-.28.28-.06.49.35.13-.3.19,0,.34-.32.12.15.21,0,.36-.21.3.16.66-.12.97.37.14-.06.34.16.51-.18.15.11.29-.06.44.31.17-.21.32.05.51-.24.17.23.29,0,.46.18.1-.13.28.05.39.21.11-.21.34.16.43v.02c-.35.04-.04.13,0,.23v.03s0,.02,0,.03c-.04.04-.14.02-.21.02-.15.34.27.71-.01,1.05-.05.09.14.15,0,.22.16.15-.09.28,0,.44.01.07.25.09.21.17-.34.13-.02.37-.27.51.18.07.17.16.14.26-.03.01-.04.04-.02.07,0,0,0,.02-.01.02-.16.08-.1.16-.01.24h.87s0,0,0-.01l13.72-.04v-13.1h-4.26v-4.93h4.26v-3.63c0-4.22,2.57-6.51,6.34-6.51,1.8,0,3.35.13,3.8.19v4.41h-2.61c-2.05,0-2.44.97-2.44,2.4v3.15h4.88l-.64,4.93h-4.24v13.12c.52,0,1.07-.01,1.55.03.55-.12,1.16,0,1.73,0,.37-.12.79,0,1.17,0,.28,0,.63,0,.84,0,1-.08,1.98.04,3.01,0,.15.12.33-.02.56.03.97.06,1.98,0,3.01.06.14,0,.32-.01.39,0,.42-.04.84-.03,1.26-.01,0,.09.69.1.65.02.28,0,.56,0,.82-.05.2.06.1.1.04.15-.16.04.57.06.52-.02.04-.07-.04-.21-.04-.21-.02-.1-.04-.18-.08-.23-.07.04-.16.07-.27.08v-.27s0,0,0,0c0,0,0,0,0,0v-.4s.04-.02.06-.03c.24.16-.04.43.21.56.08-.22.08-.49,0-.71l.11-.07c-.12-.15.02-.26-.1-.41.2-.1-.17-.21.11-.29.12-.19-.22-.36-.05-.51-.14-.11.04-.23.06-.34-.1-.16-.01-.28-.1-.44.15-.31-.03-.68-.04-1.02.04-.17.17-.33,0-.49-.04-.25.19-.51.11-.8-.23-.07-.05-.17-.1-.24.17-.17.12-.42.06-.61l.05-.02c-.17-.38.13-.76-.04-1.14.01-.18-.03-.47.06-.63-.04-.17.1-.42-.1-.58.2-.31.07-.76.12-1.1-.1-.14.1-.33-.05-.49-.02-.16.03-.3.16-.44.01-.08-.04-.23.06-.32-.26-.04-.08-.17-.21-.24Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.1 KiB |
25
resources/assets/images/socials/instagram-white-logo.svg
Normal file
25
resources/assets/images/socials/instagram-white-logo.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 6.8 KiB |
24
resources/assets/images/socials/linkedin-white-logo.svg
Normal file
24
resources/assets/images/socials/linkedin-white-logo.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 6.5 KiB |
|
|
@ -72,7 +72,7 @@ img { max-width: 100%; }
|
|||
}
|
||||
|
||||
.highlight.yellow {
|
||||
@include button-shape(#ffcb52);
|
||||
@include button-shape($color-secondary);
|
||||
}
|
||||
|
||||
.highlight.maroon {
|
||||
|
|
@ -89,6 +89,20 @@ img { max-width: 100%; }
|
|||
}
|
||||
}
|
||||
|
||||
.social-icon {
|
||||
width: 4rem;
|
||||
padding: 0 1rem;
|
||||
|
||||
&:hover {
|
||||
fill: $color-white;
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
width: 2.2rem;
|
||||
padding:0;
|
||||
}
|
||||
}
|
||||
|
||||
.rotate-180 {
|
||||
rotate: 180deg;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,20 +117,6 @@
|
|||
letter-spacing: .1rem;
|
||||
}
|
||||
|
||||
.social-icon {
|
||||
width: 4rem;
|
||||
padding: 0 1rem;
|
||||
|
||||
&:hover {
|
||||
fill: $color-white;
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
width: 2.2rem;
|
||||
padding:0;
|
||||
}
|
||||
}
|
||||
|
||||
a,span {
|
||||
font-family: 'Readex Pro', sans-serif !important;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,3 +24,4 @@
|
|||
@import './pages/product';
|
||||
@import './pages/about-us';
|
||||
@import './pages/convictions';
|
||||
@import './pages/news';
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
.news .swiper-news,
|
||||
.news .swiper-homepage-news,
|
||||
.ranges .swiper-ranges {
|
||||
.swiper-button {
|
||||
&-prev,
|
||||
|
|
@ -218,7 +218,7 @@
|
|||
}
|
||||
|
||||
.news {
|
||||
.swiper-news {
|
||||
.swiper-homepage-news {
|
||||
border: 5px solid transparent;
|
||||
|
||||
.swiper-slide {
|
||||
|
|
|
|||
56
resources/sass/fo/pages/_news.scss
Normal file
56
resources/sass/fo/pages/_news.scss
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
.news {
|
||||
.fs-news {
|
||||
font-size: calc(1.375rem + 3.2vw)
|
||||
}
|
||||
|
||||
.swiper-button {
|
||||
&-prev,
|
||||
&-next { width: 3rem; }
|
||||
|
||||
&-next { rotate: 180deg; }
|
||||
|
||||
&-disabled { opacity: .5; }
|
||||
}
|
||||
|
||||
.swiper-slide {
|
||||
&-content {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
&-news-container{
|
||||
background-image: url('@/images/global/bg-white-desktop.png');
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&-category-arrow{
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
rotate: 180deg;
|
||||
}
|
||||
|
||||
&-show-w-85{
|
||||
width: 85%;
|
||||
}
|
||||
}
|
||||
|
||||
.news-single {
|
||||
&-img.bg-agis-white {
|
||||
background-position: bottom;
|
||||
background-size: 100% 85%;
|
||||
}
|
||||
|
||||
&-title {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
.news-single {
|
||||
&-title {
|
||||
width: fit-content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -72,7 +72,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||
}
|
||||
// SWIPER
|
||||
const swiperConfig = {
|
||||
"swiper-news": {
|
||||
"swiper-homepage-news": {
|
||||
modules: [Navigation],
|
||||
grabCursor: true,
|
||||
slidesPerView: 1,
|
||||
|
|
@ -87,6 +87,26 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||
},
|
||||
},
|
||||
},
|
||||
"swiper-news": {
|
||||
modules: [Navigation],
|
||||
grabCursor: true,
|
||||
slidesPerView: 1,
|
||||
spaceBetween: 60,
|
||||
keyboard: {
|
||||
enabled: true
|
||||
},
|
||||
// Navigation arrows
|
||||
navigation: {
|
||||
nextEl: ".swiper-button-next",
|
||||
prevEl: ".swiper-button-prev",
|
||||
},
|
||||
breakpoints: {
|
||||
// when window width is >= 1200px
|
||||
1200: {
|
||||
slidesPerView: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
"swiper-ranges": {
|
||||
modules: [Navigation],
|
||||
grabCursor: true,
|
||||
|
|
|
|||
323
resources/ts/fo/components/NewsListComponent.vue
Normal file
323
resources/ts/fo/components/NewsListComponent.vue
Normal file
|
|
@ -0,0 +1,323 @@
|
|||
<template>
|
||||
<div class="news-list container">
|
||||
<div class="row pt-5">
|
||||
<div class="col-12 col-lg-6">
|
||||
<div class="ranges-title w-100 w-lg-fit">
|
||||
<span class="divide d-block w-100 mt-xl-3 my-2" />
|
||||
<h1 class="f-sheldon text-uppercase text-lg-start my-3 text-center">
|
||||
{{ __('nos actualités') }}
|
||||
</h1>
|
||||
<span class="divide d-block w-100 mt-xl-3 my-2" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-lg-6">
|
||||
<div class="d-flex align-items-center h-100 w-100 justify-content-end">
|
||||
<fieldset class="select-form position-relative my-3 my-lg-0">
|
||||
<select
|
||||
class="form-control highlight yellow"
|
||||
role="button"
|
||||
@change="updateNews($event)"
|
||||
:disabled="intLoading"
|
||||
>
|
||||
<option
|
||||
value="0"
|
||||
selected
|
||||
>
|
||||
{{ __('Toutes catégories') }}
|
||||
</option>
|
||||
<option
|
||||
v-for="(categoryEnum, categoryEnumIndex) in categoryEnums"
|
||||
:key="categoryEnumIndex"
|
||||
:value="categoryEnum.value"
|
||||
>
|
||||
{{ categoryEnum.label }}
|
||||
</option>
|
||||
</select>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="news-slider d-block d-lg-none bg-agis-white pb-5">
|
||||
<div class="swiper swiper-news overflow-hidden">
|
||||
<div class="swiper-wrapper">
|
||||
<div
|
||||
class="swiper-slide swiper-slide-content"
|
||||
v-for="(news, id) in newsModels"
|
||||
:key="id"
|
||||
>
|
||||
<div class="swiper-slide-news-container">
|
||||
<div class="mx-auto p-4">
|
||||
<img
|
||||
class="card-img-top"
|
||||
:src="(news.picture_thumbnail as string)"
|
||||
:alt="(news.picture_thumbnail_alt as string)"
|
||||
:title="(news.picture_thumbnail_title as string)"
|
||||
>
|
||||
<div class="card-body">
|
||||
<p class="card-text m-0">
|
||||
{{ new Date(news.publish_at as string).toLocaleDateString() }}
|
||||
</p>
|
||||
<p class="card-text m-0">
|
||||
{{ news.title }}
|
||||
</p>
|
||||
<a
|
||||
class="card-text m-0"
|
||||
:href="showNews(news.slug as string)"
|
||||
>
|
||||
{{ __('> Lire la suite') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex justify-content-around">
|
||||
<div class="swiper-button-prev mx-3">
|
||||
<img
|
||||
src="@/images/global/btn-arrow.png"
|
||||
title="{{ __('Navigation du slider (gauche)') }}"
|
||||
alt="{{ __('flèche vers la gauche') }}"
|
||||
>
|
||||
</div>
|
||||
<div class="swiper-button-next mx-3">
|
||||
<img
|
||||
src="@/images/global/btn-arrow.png"
|
||||
title="{{ __('Navigation du slider (droite)') }}"
|
||||
alt="{{ __('flèche vers la droite') }}"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-none d-lg-flex flex-wrap justify-content-between my-4">
|
||||
<div
|
||||
v-for="(news, id) in newsModels"
|
||||
:key="id"
|
||||
class="cards-container"
|
||||
>
|
||||
<div class="bg-agis-white d-flex flex-column p-4">
|
||||
<div class="text-center">
|
||||
<img
|
||||
class="img-fluid w-auto"
|
||||
:src="(news.picture_thumbnail as string)"
|
||||
:alt="(news.picture_thumbnail_alt as string)"
|
||||
:title="(news.picture_thumbnail_title as string)"
|
||||
>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="card-text m-0">
|
||||
{{ new Date(news.publish_at as string).toLocaleDateString() }}
|
||||
</p>
|
||||
<p class="card-text m-0">
|
||||
{{ news.title }}
|
||||
</p>
|
||||
<a
|
||||
class="card-text m-0"
|
||||
:href="showNews(news.slug as string)"
|
||||
>
|
||||
{{ __('> Lire la suite') }}
|
||||
</a>
|
||||
<template
|
||||
v-for="(categoryEnum, categoryEnumIndex) in categoryEnums"
|
||||
:key="categoryEnumIndex"
|
||||
>
|
||||
<p
|
||||
class="card-text m-0"
|
||||
v-if="news.category === categoryEnum.value"
|
||||
>
|
||||
{{ categoryEnum.label }}
|
||||
</p>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Swiper from "swiper";
|
||||
import { Navigation } from "swiper/modules";
|
||||
import { defineComponent } from "vue";
|
||||
import parseLaravelErrorMessages from "./../../modules/parseLaravelErrorMessages";
|
||||
import route from "./../../modules/route";
|
||||
import trans from "./../../modules/trans";
|
||||
|
||||
export default defineComponent({
|
||||
name: "NewsListComponent",
|
||||
mixins: [trans, route, parseLaravelErrorMessages],
|
||||
data(): {
|
||||
newsModels: LaravelModelList;
|
||||
newsFilteredRoute: string;
|
||||
categoryEnums: {
|
||||
label: string,
|
||||
name: string,
|
||||
value: number,
|
||||
}[];
|
||||
selectedValue: number,
|
||||
swiper: Swiper|null,
|
||||
intLoading: boolean,
|
||||
} {
|
||||
return {
|
||||
newsModels: [],
|
||||
newsFilteredRoute: "",
|
||||
categoryEnums: [],
|
||||
selectedValue: 0,
|
||||
swiper: null,
|
||||
intLoading: false,
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
mounted() {
|
||||
const json = String(this.$attrs.json ?? "{}"),
|
||||
data = JSON.parse(json);
|
||||
this.newsModels = data.newsModels;
|
||||
this.categoryEnums = data.categoryEnums;
|
||||
this.initSelect();
|
||||
this.initSwiper();
|
||||
},
|
||||
methods: {
|
||||
showNews (slug: string): string {
|
||||
const route = this.route("fo.news.show", {
|
||||
SLUG: slug,
|
||||
});
|
||||
if (!route) {
|
||||
throw new Error("Undefined route fo.news.show");
|
||||
}
|
||||
return route;
|
||||
},
|
||||
formatDate (formDate: string | Date) {
|
||||
const date = new Date(formDate);
|
||||
return date.toLocaleDateString;
|
||||
},
|
||||
initSelect() {
|
||||
// * Toggle la dropdown Arrow du select.
|
||||
const contactFormSelectList = document.querySelectorAll(".news-list select") as NodeListOf<HTMLSelectElement>;
|
||||
document.body.addEventListener("click", function (e: MouseEvent) {
|
||||
const target = e.target as HTMLElement | null;
|
||||
contactFormSelectList.forEach(select => {
|
||||
if (select.contains(target)) {
|
||||
select.parentElement!.classList.toggle("active");
|
||||
} else {
|
||||
select.parentElement!.classList.remove("active");
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
/** Init news slider */
|
||||
initSwiper() {
|
||||
this.swiper = new Swiper(".swiper-news", {
|
||||
modules: [Navigation],
|
||||
grabCursor: true,
|
||||
slidesPerView: 1,
|
||||
spaceBetween: 20,
|
||||
navigation: {
|
||||
nextEl: ".swiper-button-next",
|
||||
prevEl: ".swiper-button-prev",
|
||||
},
|
||||
});
|
||||
},
|
||||
/** Get selected value */
|
||||
getSelectedValue(e: Event): number {
|
||||
let target = e.target as HTMLSelectElement | null;
|
||||
return Number(target?.value);
|
||||
},
|
||||
/** Get filtered news route */
|
||||
getFilteredNewsRoute(): string {
|
||||
const route = this.route("fo.news.filtered");
|
||||
if (!route) {
|
||||
throw new Error("Undefined route fo.news.filtered");
|
||||
}
|
||||
return route + "?category=" + this.selectedValue;
|
||||
},
|
||||
/** Get filtered news */
|
||||
getFilteredNews() {
|
||||
window.axios
|
||||
.get(this.newsFilteredRoute)
|
||||
.then((reponse) => {
|
||||
this.newsModels = reponse.data;
|
||||
this.$nextTick(() => {
|
||||
this.swiper?.update();
|
||||
this.intLoading = false;
|
||||
});
|
||||
})
|
||||
.catch(this.ajaxErrorHandler);
|
||||
},
|
||||
/** Return error message after the ajax call */
|
||||
ajaxErrorHandler(e: any) {
|
||||
this.intLoading = false;
|
||||
let message = this.__("Une erreur est survenue");
|
||||
if (e.response.status === 422) {
|
||||
message =
|
||||
this.parseValidationErrors(
|
||||
e.response?.data?.errors ?? {}
|
||||
) || message;
|
||||
if (window.vueDebug) {
|
||||
console.warn(e.response.data.errors);
|
||||
}
|
||||
} else if (e.response.status === 419) {
|
||||
// * CSRF TOKEN MISMATCH (On ne pourrais plus faire d'appels AJAX sans recharger la page)
|
||||
console.log(this.__("Votre session a expiré, la page va être rechargée"));
|
||||
setTimeout(() => window.location.reload(), 2000);
|
||||
} else if (e.response.status === 403) {
|
||||
// * Access denied
|
||||
console.log(this.__("Vous n'êtes pas autorisé a effectuer cette action"));
|
||||
setTimeout(() => window.location.reload(), 2000);
|
||||
} else {
|
||||
if (window.vueDebug) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
console.log(message);
|
||||
},
|
||||
/** Update news with filtered news */
|
||||
updateNews(e: Event) {
|
||||
this.intLoading = true;
|
||||
this.selectedValue = this.getSelectedValue(e);
|
||||
this.newsFilteredRoute = this.getFilteredNewsRoute();
|
||||
this.getFilteredNews();
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "./../../../../node_modules/bootstrap/scss/functions";
|
||||
@import "./../../../../node_modules/bootstrap/scss/variables";
|
||||
@import "./../../../../node_modules/bootstrap/scss/mixins";
|
||||
.news-list {
|
||||
.select-form {
|
||||
width: 100%;
|
||||
@include media-breakpoint-up(lg) {
|
||||
width: 20rem;
|
||||
}
|
||||
&::after {
|
||||
position: absolute;
|
||||
right: 1rem;
|
||||
bottom: 0.3rem;
|
||||
display: block;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
background: url("@/images/global/btn-arrow.png");
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
content: "";
|
||||
pointer-events: none;
|
||||
transform: rotate(180deg);
|
||||
transition: 0.1s ease-in-out;
|
||||
}
|
||||
|
||||
&.active::after {
|
||||
background: url("@/images/global/btn-arrow-dark.png");
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
transform: rotate(270deg);
|
||||
}
|
||||
}
|
||||
.cards-container{
|
||||
max-width: 314px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
6
resources/ts/fo/components/shims-vue.d.ts
vendored
6
resources/ts/fo/components/shims-vue.d.ts
vendored
|
|
@ -1,6 +0,0 @@
|
|||
declare module "*.vue" {
|
||||
import type { DefineComponent } from "vue";
|
||||
const component: DefineComponent<{}, {}, any>;
|
||||
// @ts-ignore
|
||||
export default component;
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
@include('fo.layouts.footer')
|
||||
@stack('scripts-constants')
|
||||
@include('vendor.cn-cookies')
|
||||
@include('modules.script-constants')
|
||||
@include('modules.script-routes')
|
||||
@vite(['resources/ts/fo/fo.ts'])
|
||||
@stack('scripts')
|
||||
</body>
|
||||
|
|
|
|||
|
|
@ -77,8 +77,8 @@
|
|||
</ul>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-uppercase @if (request()->routeIs('CHANGEME')) active @endif py-1" data-bs-toggle="tooltip"
|
||||
href="#" title="{{ __('Actualités') }}">
|
||||
<a class="nav-link text-uppercase @if (request()->routeIs('fo.news.*')) active @endif py-1" data-bs-toggle="tooltip"
|
||||
href="{{ route('fo.news.index') }}" title="{{ __('Actualités') }}">
|
||||
{{ __('Actualités') }}
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@
|
|||
href="{{ route('fo.aboutus.show') }}" title="{{ __('Nous connaitre') }}">
|
||||
{{ __('Nous connaitre') }}
|
||||
</a>
|
||||
<a class="nav-link display-5 fw-bold text-uppercase @if (request()->routeIs('CHANGEME')) active @endif" data-bs-toggle="tooltip"
|
||||
href="#" title="{{ __('Nos actualités') }}">
|
||||
<a class="nav-link display-5 fw-bold text-uppercase @if (request()->routeIs('fo.news.*')) active @endif" data-bs-toggle="tooltip"
|
||||
href="{{ route('fo.news.index') }}" title="{{ __('Nos actualités') }}">
|
||||
{{ __('Nos actualités') }}
|
||||
</a>
|
||||
<a class="nav-link display-5 fw-bold text-uppercase @if (request()->routeIs('fo.joinus.show')) active @endif" data-bs-toggle="tooltip"
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@
|
|||
<div class="position-relative w-100 h-100"></div>
|
||||
</div>
|
||||
<h2 class="text-uppercase fs-1 f-sheldon mx-auto w-fit bg-white px-4 text-center">{{ __('Nos actus') }}</h2>
|
||||
<div class="swiper swiper-news p-xl-4 pt-xl-0 pb-xl-5 mt-4 overflow-hidden p-0" id="swiper-news">
|
||||
<div class="swiper swiper-homepage-news p-xl-4 pt-xl-0 pb-xl-5 mt-4 overflow-hidden p-0" id="swiper-homepage-news">
|
||||
<div class="swiper-wrapper">
|
||||
@foreach ($newsModels as $key => $newsModel)
|
||||
<div class="swiper-slide">
|
||||
|
|
@ -96,7 +96,7 @@
|
|||
<img src="{{ Vite::asset('resources/assets/images/homepage/news.png') }}"
|
||||
title="{{ __('Représentation d\'un recette') }}" alt="{{ __('cocotte minute') }}">
|
||||
<div class="d-flex flex-column justify-content-start align-items-start mt-2">
|
||||
<a class="btn btn-secondary" href="#">{{ __('> Voir toutes nos actus') }}</a>
|
||||
<a class="btn btn-secondary" href="{{ route('fo.news.index') }}">{{ __('> Voir toutes nos actus') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
39
resources/views/fo/pages/news/cards.blade.php
Normal file
39
resources/views/fo/pages/news/cards.blade.php
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<div class="swiper-slide d-md-block d-lg-none">
|
||||
<div class="swiper-slide-news-container mx-auto mb-4">
|
||||
<div class="swiper-slide-content d-flex flex-column justify-content-center align-items-center mx-auto p-4">
|
||||
<img src="{{ asset($newsModel->picture_thumbnail) }}" title="{{ $newsModel->picture_thumbnail_title }}"
|
||||
alt="{{ $newsModel->picture_thumbnail_alt }}">
|
||||
<div
|
||||
class="d-flex flex-column justify-content-start align-items-start w-75 @if ($key % 2) mb-3 @else mt-3 @endif">
|
||||
<p class="f-readex-pro m-0">
|
||||
{{ \Carbon\Carbon::parse($newsModel->publish_at)->locale('fr_FR')->isoFormat('D MMM Y') }}</p>
|
||||
<p class="m-0 text-start">{{ $newsModel->title }}</p>
|
||||
<a href="{{ route('fo.news.show', $newsModel->slug) }}">{{ __('> Lire la suite') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex justify-content-evenly align-items-center d-lg-none w-100 flex-row pb-3">
|
||||
<div class="swiper-button-prev rounded-circle" role="button">
|
||||
<img src="{{ Vite::asset('resources/assets/images/global/btn-arrow.png') }}"
|
||||
title="{{ __('Navigation du slider (gauche)') }}" alt="{{ __('flèche vers la gauche') }}">
|
||||
</div>
|
||||
<div class="swiper-button-next rounded-circle" role="button">
|
||||
<img src="{{ Vite::asset('resources/assets/images/global/btn-arrow.png') }}"
|
||||
title="{{ __('Navigation du slider (droite)') }}" alt="{{ __('flèche vers la droite') }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-3 card-container d-none d-lg-block m-4">
|
||||
<div class="d-flex @if ($key % 2 === 1) flex-column-reverse @else flex-column @endif m-4">
|
||||
<div class="text-center">
|
||||
<img class="img-fluid w-auto" src="{{ $newsModel->picture_thumbnail }}" title="{{ $newsModel->picture_thumbnail_title }}"
|
||||
alt="{{ $newsModel->picture_thumbnail_alt }}" />
|
||||
</div>
|
||||
<div class="">
|
||||
<p>{{ \Carbon\Carbon::parse($newsModel->publish_at)->locale('fr_FR')->isoFormat('D MMM Y') }}</p>
|
||||
<h6>{{ $newsModel->title }}</h6>
|
||||
<a href="{{ route('fo.news.show', $newsModel->slug) }}">{{ __('> Lire la suite') }}</a>
|
||||
<p>{{ $newsModel->category->label() }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
18
resources/views/fo/pages/news/index.blade.php
Normal file
18
resources/views/fo/pages/news/index.blade.php
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
@extends('fo.layout')
|
||||
|
||||
@section('title', $staticPageModel->seo_title ?? __('Accueil'))
|
||||
@section('description', $staticPageModel->seo_description ?? __('Description site'))
|
||||
@section('breadcrumb',
|
||||
request()->route()->getName())
|
||||
|
||||
@section('content')
|
||||
<section class="news position-relative bg-agis-grey pb-5">
|
||||
@php
|
||||
$data = [
|
||||
'newsModels' => $newsModels,
|
||||
'categoryEnums' => \App\Enums\News\CategoryEnum::toArray(),
|
||||
];
|
||||
@endphp
|
||||
<div class="news-list" data-json='@json($data)'></div>
|
||||
</section>
|
||||
@endsection
|
||||
58
resources/views/fo/pages/news/show.blade.php
Normal file
58
resources/views/fo/pages/news/show.blade.php
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
@extends('fo.layout')
|
||||
|
||||
@section('title', $newsModel->seo_title ?? __('Actualités'))
|
||||
@section('description', $newsModel->seo_description ?? __('Les actualités de la marque'))
|
||||
@section('breadcrumb',
|
||||
request()->route()->getName())
|
||||
|
||||
@section('content')
|
||||
<section class="news-single mx-auto mb-5">
|
||||
<div class="row container mx-auto">
|
||||
<div class="col-12">
|
||||
<a class="btn btn-secondary" href="{{ route('fo.news.index') }}">{{ __('< Retour aux actualités') }}</a>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<h1 class="news-single-title f-sheldon text-uppercase lh-sm my-3 text-center">
|
||||
<span class="divide d-block w-100 mt-xl-3 my-2"></span>
|
||||
{{ $newsModel->title }}
|
||||
<span class="divide d-block w-100 mt-xl-3 my-2"></span>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<p class="f-readex-pro mb-0">
|
||||
{{ \Carbon\Carbon::parse($newsModel->publish_at)->locale('fr_FR')->isoFormat('D MMM Y') }}</p>
|
||||
<p class="fs-3 mb-3">{{ __($newsModel->category->label()) }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<article class="bg-agis-grey pt-5">
|
||||
<div class="container">
|
||||
<div class="mx-auto text-center">
|
||||
<div class="news-single-img bg-agis-white p-lg-5 p-md-4 mx-auto w-fit p-3 pt-0">
|
||||
<img class="" src="{{ asset($newsModel->picture) }}" title="{{ Str::of($newsModel->picture_title)->ucFirst() }}"
|
||||
alt="{{ Str::of($newsModel->picture_alt)->ucFirst() }}">
|
||||
</div>
|
||||
<div class="mx-auto mt-3">
|
||||
<p class="fs-7 fw-semibold text-start">{{ $newsModel->subtitle }}</p>
|
||||
<br>
|
||||
{!! clean($newsModel->content) !!}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row pb-5">
|
||||
<div class="col text-center">
|
||||
<p class="fs-3 mt-5">{{ __('Partager sur') }}</p>
|
||||
<a class="text-decoration-none" href="#FIXME:Change this" title="{{ __('Nous suivre sur Instagram') }}"
|
||||
target="_blank">
|
||||
@include('fo.partials.social-svg-instagram')
|
||||
</a>
|
||||
<a class="text-decoration-none" href="#FIXME:Change this" title="{{ __('Nous suivre sur Facebook') }}" target="_blank">
|
||||
@include('fo.partials.social-svg-facebook')
|
||||
</a>
|
||||
<a class="text-decoration-none" href="#FIXME:Change this" title="{{ __('Nous suivre sur Linkedin') }}" target="_blank">
|
||||
@include('fo.partials.social-svg-linkedin')
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
@endsection
|
||||
|
|
@ -1,6 +1,12 @@
|
|||
@include('modules.script-constants')
|
||||
<script @if(isset($nonce)) nonce="{{ $nonce }}" @endif>
|
||||
if (!window.__SYSTEM._routes) {
|
||||
window.__SYSTEM._routes = {};
|
||||
}
|
||||
<script @if (isset($nonce)) nonce="{{ $nonce }}" @endif>
|
||||
if (!window.__SYSTEM._routes) {
|
||||
window.__SYSTEM._routes = {};
|
||||
}
|
||||
window.__SYSTEM._routes.fo = {
|
||||
news: {
|
||||
filtered: "{{ route('fo.news.filtered') }}",
|
||||
show: "{{ route('fo.news.show', ['slug' => 'SLUG']) }}"
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use App\Http\Controllers\Fo\RangeController;
|
||||
use App\Http\Controllers\Fo\ProductController;
|
||||
use App\Http\Controllers\Fo\NewsController;
|
||||
use App\Http\Controllers\Fo\StaticPageController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
|
|
@ -33,4 +34,9 @@ Route::middleware(['throttle:credentials'])
|
|||
|
||||
Route::get('/mentions-legales', [StaticPageController::class, 'legals'])->name('legals.show');
|
||||
Route::get('/charte-de-confidentialite', [StaticPageController::class, 'policies'])->name('policies.show');
|
||||
|
||||
// * NEWS.
|
||||
Route::get('/news', [NewsController::class, 'index'])->name('news.index');
|
||||
Route::get('/news/filtered', [NewsController::class, 'newsFiltered'])->name('news.filtered');
|
||||
Route::get('/news/{slug}', [NewsController::class, 'show'])->name('news.show');
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue