add news.index + news.show pages

This commit is contained in:
Alexis Gousseau 2023-11-06 16:05:48 +01:00
parent 705aa7c522
commit bdbbb9ff9a
23 changed files with 698 additions and 36 deletions

View 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);
}
}

View file

@ -167,7 +167,6 @@ trait BaseEnum
return $this->value;
}
// * CACHE
/**

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.1 KiB

View 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

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.8 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.5 KiB

View file

@ -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;
}

View file

@ -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;
}

View file

@ -24,3 +24,4 @@
@import './pages/product';
@import './pages/about-us';
@import './pages/convictions';
@import './pages/news';

View file

@ -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 {

View 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;
}
}
}

View file

@ -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,

View 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>

View file

@ -1,6 +0,0 @@
declare module "*.vue" {
import type { DefineComponent } from "vue";
const component: DefineComponent<{}, {}, any>;
// @ts-ignore
export default component;
}

View file

@ -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>

View file

@ -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>

View file

@ -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"

View file

@ -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>

View 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>

View 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

View 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

View file

@ -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>

View file

@ -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');
});