Carto on Unveil ok

This commit is contained in:
Jérémy Munsch 2024-03-26 12:23:04 +01:00
parent 6cd2a87655
commit afad70924b
No known key found for this signature in database
GPG key ID: 18361AF3BFEC0FEC
17 changed files with 588 additions and 91 deletions

View file

@ -21,6 +21,7 @@ use App\Models\StaticPage;
use App\Models\Strip;
use App\Models\Testimonial;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Str;
class StaticPageController extends Controller
{
@ -80,18 +81,24 @@ class StaticPageController extends Controller
$historySection = $sectionModels->where('section', PageSectionEnum::unveil_history)->first();
$commitmentSection = $sectionModels->where('section', PageSectionEnum::unveil_commitments)->first();
// * Calcul Viewbox leaflet map.
$viewBox = (object)[
// @phpstan-ignore-next-line
'lat' => \round($siteModelList->sum(fn (Site $siteModel) =>
$siteModel->latitude) / $siteModelList->count(), 6),
// @phpstan-ignore-next-line
'lng' => \round($siteModelList->sum(fn (Site $siteModel) =>
$siteModel->longitude) / $siteModelList->count(), 6)
];
$viewBox = null;
$initialZoom = null;
// * Calcul Viewbox leaflet map ().
// Carte  page “on se dévoile” : Point central = Laval + rayon = 100 km 
/** @var \App\Models\Site|null $lavalSite */
// @phpstan-ignore-next-line
$lavalSite = $siteModelList->first(fn (Site $site) => Str::contains($site->name, 'Laval'));
if ($lavalSite) {
$viewBox = (object)[
'lat' => $lavalSite->latitude,
'lng' => $lavalSite->longitude
];
$initialZoom = 9;
}
return view('fo.pages.unveil', compact(
'viewBox',
'initialZoom',
'staticPageModel',
'sectionModels',
'historicalMilestoneModels',
@ -276,9 +283,17 @@ class StaticPageController extends Controller
$nextSiteModel = Site::query()->orderBy('order')->where('order', '>', $site->order)->first();
}
$viewBox = (object)[
'lat' => $site->latitude,
'lng' => $site->longitude
];
$initialZoom = 9;
return view('fo.pages.site', [
'siteModel' => $site,
'nextSiteModel' => $nextSiteModel
'nextSiteModel' => $nextSiteModel,
'viewBox' => $viewBox,
'initialZoom' => $initialZoom,
]);
}
}
}

View file

@ -80,7 +80,7 @@ class StoreSiteRequest extends FormRequest
];
return \array_merge(
$rules,
$this->pictureRules('logo', 300, 300, 300, 300, false),
$this->pictureRules('logo', 1000, 727, 1000, 727, false),
$this->pictureRules('picture_1', 1000, 562, 1000, 562, false),
$this->pictureRules('picture_2', 1000, 562, 1000, 562, true),
$this->pictureRules('picture_3', 1000, 562, 1000, 562, true),

View file

@ -16,6 +16,7 @@
"axlon/laravel-postal-code-validation": "^3.5",
"diglactic/laravel-breadcrumbs": "^8.0",
"guzzlehttp/guzzle": "^7.2",
"kwaadpepper/image-resizer": "^2.1",
"laravel/framework": "^10.0",
"laravel/tinker": "^2.8",
"laravel/ui": "^4.2",
@ -28,7 +29,7 @@
"fakerphp/faker": "^1.9.1",
"kitloong/laravel-migrations-generator": "^6.8",
"krlove/eloquent-model-generator": "dev-l10-compatibility",
"larastan/larastan": "^2.6",
"larastan/larastan": "^2.9",
"laravel-lang/common": "^4.0",
"laravel/pint": "^1.0",
"laravel/sail": "^1.18",

279
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "4bf7c1fe3b307c9b2251f4ebcfbd0cd4",
"content-hash": "1da5334945451015dfb5c5edc5c9b42f",
"packages": [
{
"name": "axlon/laravel-postal-code-validation",
@ -1422,6 +1422,158 @@
],
"time": "2023-12-03T19:50:20+00:00"
},
{
"name": "intervention/image",
"version": "2.7.2",
"source": {
"type": "git",
"url": "https://github.com/Intervention/image.git",
"reference": "04be355f8d6734c826045d02a1079ad658322dad"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Intervention/image/zipball/04be355f8d6734c826045d02a1079ad658322dad",
"reference": "04be355f8d6734c826045d02a1079ad658322dad",
"shasum": ""
},
"require": {
"ext-fileinfo": "*",
"guzzlehttp/psr7": "~1.1 || ^2.0",
"php": ">=5.4.0"
},
"require-dev": {
"mockery/mockery": "~0.9.2",
"phpunit/phpunit": "^4.8 || ^5.7 || ^7.5.15"
},
"suggest": {
"ext-gd": "to use GD library based image processing.",
"ext-imagick": "to use Imagick based image processing.",
"intervention/imagecache": "Caching extension for the Intervention Image library"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.4-dev"
},
"laravel": {
"providers": [
"Intervention\\Image\\ImageServiceProvider"
],
"aliases": {
"Image": "Intervention\\Image\\Facades\\Image"
}
}
},
"autoload": {
"psr-4": {
"Intervention\\Image\\": "src/Intervention/Image"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Oliver Vogel",
"email": "oliver@intervention.io",
"homepage": "https://intervention.io/"
}
],
"description": "Image handling and manipulation library with support for Laravel integration",
"homepage": "http://image.intervention.io/",
"keywords": [
"gd",
"image",
"imagick",
"laravel",
"thumbnail",
"watermark"
],
"support": {
"issues": "https://github.com/Intervention/image/issues",
"source": "https://github.com/Intervention/image/tree/2.7.2"
},
"funding": [
{
"url": "https://paypal.me/interventionio",
"type": "custom"
},
{
"url": "https://github.com/Intervention",
"type": "github"
}
],
"time": "2022-05-21T17:30:32+00:00"
},
{
"name": "intervention/imagecache",
"version": "2.6.0",
"source": {
"type": "git",
"url": "https://github.com/Intervention/imagecache.git",
"reference": "86136575a62d3634b51f196a998fce4a583b49bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Intervention/imagecache/zipball/86136575a62d3634b51f196a998fce4a583b49bb",
"reference": "86136575a62d3634b51f196a998fce4a583b49bb",
"shasum": ""
},
"require": {
"illuminate/cache": "^5.5|~6|~7|~8|~9|~10",
"illuminate/filesystem": "^5.5|~6|~7|~8|~9|~10",
"intervention/image": "~2.2",
"nesbot/carbon": "^2.39",
"opis/closure": "^3.5",
"php": "~7.2|~8"
},
"require-dev": {
"phpunit/phpunit": "^8.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Intervention\\Image\\": "src/Intervention/Image"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Oliver Vogel",
"email": "oliver@intervention.io",
"homepage": "http://intervention.io/"
}
],
"description": "Caching extension for the Intervention Image Class",
"homepage": "https://image.intervention.io",
"keywords": [
"cache",
"gd",
"image",
"imagick",
"laravel"
],
"support": {
"issues": "https://github.com/Intervention/imagecache/issues",
"source": "https://github.com/Intervention/imagecache/tree/2.6.0"
},
"funding": [
{
"url": "https://paypal.me/interventionio",
"type": "custom"
},
{
"url": "https://github.com/Intervention",
"type": "github"
}
],
"abandoned": true,
"time": "2023-02-25T19:40:47+00:00"
},
{
"name": "jean85/pretty-package-versions",
"version": "2.0.6",
@ -1481,6 +1633,66 @@
},
"time": "2024-03-08T09:58:59+00:00"
},
{
"name": "kwaadpepper/image-resizer",
"version": "2.1.0",
"source": {
"type": "git",
"url": "https://github.com/Kwaadpepper/image-resizer.git",
"reference": "2a14ad153b34916f437af50549bad47c018902df"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Kwaadpepper/image-resizer/zipball/2a14ad153b34916f437af50549bad47c018902df",
"reference": "2a14ad153b34916f437af50549bad47c018902df",
"shasum": ""
},
"require": {
"illuminate/support": "~10",
"intervention/image": "^2.7.2",
"intervention/imagecache": "^2.6",
"laravel/framework": "~10"
},
"require-dev": {
"slevomat/coding-standard": "^8.11"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Kwaadpepper\\ImageResizer\\ImageResizerServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Kwaadpepper\\ImageResizer\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jérémy Munsch",
"email": "github@jeremydev.ovh",
"homepage": "https://jeremydev.ovh"
}
],
"description": "Resize images on the fly and cache them",
"homepage": "https://github.com/kwaadpepper/image-resizer",
"keywords": [
"images",
"laravel",
"resize"
],
"support": {
"issues": "https://github.com/Kwaadpepper/image-resizer/issues",
"source": "https://github.com/Kwaadpepper/image-resizer/tree/2.1.0"
},
"time": "2023-06-08T12:07:24+00:00"
},
{
"name": "laravel/framework",
"version": "v10.48.3",
@ -2982,6 +3194,71 @@
],
"time": "2023-11-13T09:31:12+00:00"
},
{
"name": "opis/closure",
"version": "3.6.3",
"source": {
"type": "git",
"url": "https://github.com/opis/closure.git",
"reference": "3d81e4309d2a927abbe66df935f4bb60082805ad"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/opis/closure/zipball/3d81e4309d2a927abbe66df935f4bb60082805ad",
"reference": "3d81e4309d2a927abbe66df935f4bb60082805ad",
"shasum": ""
},
"require": {
"php": "^5.4 || ^7.0 || ^8.0"
},
"require-dev": {
"jeremeamia/superclosure": "^2.0",
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.6.x-dev"
}
},
"autoload": {
"files": [
"functions.php"
],
"psr-4": {
"Opis\\Closure\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marius Sarca",
"email": "marius.sarca@gmail.com"
},
{
"name": "Sorin Sarca",
"email": "sarca_sorin@hotmail.com"
}
],
"description": "A library that can be used to serialize closures (anonymous functions) and arbitrary objects.",
"homepage": "https://opis.io/closure",
"keywords": [
"anonymous functions",
"closure",
"function",
"serializable",
"serialization",
"serialize"
],
"support": {
"issues": "https://github.com/opis/closure/issues",
"source": "https://github.com/opis/closure/tree/3.6.3"
},
"time": "2022-01-27T09:35:39+00:00"
},
{
"name": "phpoption/phpoption",
"version": "1.9.2",

70
config/image-resizer.php Normal file
View file

@ -0,0 +1,70 @@
<?php
return [
/**
* The php image driver to use
* this can be 'imagick' or 'gd'
*/
'driver' => 'imagick',
/**
* The cache driver to use as defined
* in config/cache of your app
*/
'cache' => 'file',
/**
* The path where to store image in cache
*/
'cachePath' => 'cache/images',
/**
* Image cache life time
* This is given in minutes
* Here the cache for images is
* one hour
*/
'lifetime' => 60,
/**
* Format can specifiy to which format save the image
* JPEG PNG GIF TIF BMP ICO PSD WebP
* GD ✔️ ✔️ ✔️ - - - - ✔️ *
* Imagick ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ ✔️ *
* For WebP support GD driver must be used with PHP 5 >= 5.5.0 or PHP 7
* in order to use imagewebp(). If Imagick is used, it must be compiled
* with libwebp for WebP support.
* resize => will resize the image (boolean)
* fit => Combine cropping and resizing to format image in a smart way (boolean)
* keepRatio => will keep image ratio wile resizing (boolean)
* trim => boolean to trim the image using border color
* inCanvas => to make sure image boundarie is respected
* format => select tha wantd ouput form, yan can just convert images if you want
* example :
* 'small' => [
* 'height' => 500,
* 'width' => 250,
* 'inCanvas' => true,
* 'trim' => ['transparent', null, 10]
* ],
* 'smallWebp' => [
* 'height' => 500,
* 'width' => 250,
* 'inCanvas' => true,
* 'format' => 'webp'
* ],
* 'justconvertImage' => [
* 'format' => 'webp'
* ]
*/
'templates' => [
'cartoPicture' => [
'height' => 140,
'width' => 155,
'fit' => true,
'inCanvas' => true,
'trim' => ['transparent', null, 10],
'format' => 'webp',
]
]
];

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -25,7 +25,7 @@ class SiteSeeder extends Seeder
$site->logo = FileStorageHelper::storeFile(
new Site(),
new \SplFileInfo(\resource_path(
'../database/factories/assets/sites/default-picture-300x300.png'
'../database/factories/assets/sites/default-picture-1000x727.jpg'
))
);
$site->picture_1 = FileStorageHelper::storeFile(

View file

@ -176,3 +176,9 @@ $theme-colors: map.merge($theme-colors, $light-colors);
}
}
}
// .map-site-widget {
// img {
// width: 6rem;
// }
// }

View file

@ -18,7 +18,15 @@
.sites {
.embed-map {
min-height: 20rem;
min-height: 30rem;
@include media-breakpoint-up(sm) {
min-height: 35rem;
}
@include media-breakpoint-up(md) {
min-height: 40rem;
}
iframe {
width: 100%;

View file

@ -177,6 +177,27 @@ document.addEventListener("DOMContentLoaded", function () {
},
},
},
"swiper-sites-map": {
centeredSlides: true,
modules: [Keyboard],
grabCursor: true,
slidesPerView: 1,
spaceBetween: 20,
keyboard: {
enabled: true,
},
breakpoints: {
768: {
slidesPerView: 1.5,
},
992: {
slidesPerView: 1,
},
1200: {
slidesPerView: 1.3,
},
},
},
"swiper-sites-pictures": {
modules: [Navigation, Keyboard],
grabCursor: true,
@ -301,13 +322,8 @@ document.addEventListener("DOMContentLoaded", function () {
},
};
type SwiperSlider = {
element: HTMLElement;
swiper: Swiper;
};
const swiperVol = document.getElementsByClassName("swiper") as HTMLCollectionOf<HTMLElement>,
sliders: SwiperSlider[] = [];
const swiperVol = document.getElementsByClassName("swiper") as HTMLCollectionOf<HTMLElement>;
window.__SLIDERS = new Map<string,SwiperSlider>();
for (const htmlElt of swiperVol) {
if (!swiperConfig[htmlElt.id as keyof typeof swiperConfig]) {
@ -315,10 +331,12 @@ document.addEventListener("DOMContentLoaded", function () {
}
// @ts-ignore
const swiper = new Swiper(htmlElt, swiperConfig[htmlElt.id as keyof typeof swiperConfig]);
sliders.push({
element: htmlElt,
swiper: swiper,
});
window.__SLIDERS.set(
htmlElt.id,
{
element: htmlElt,
swiper: swiper,
});
if (swiper.el.id === "swiper-teams") {
const btnPlayPause = document.querySelector(".swiper-pagination-playpause");
btnPlayPause?.addEventListener("click", function () {

View file

@ -5,7 +5,7 @@
>
<div
ref="marker"
class="d-none marker-pin text-bg-white px-3 py-1 d-flex justify-content-center align-items-center f-barlow rounded-pill border border-1 border-primary"
class="d-none marker-pin bg-white text-primary px-3 py-1 d-flex justify-content-center align-items-center f-barlow rounded-pill border border-1 border-primary"
>
<img
class="marker-logo mx-1"
@ -13,25 +13,13 @@
alt=""
>
<span>
<span class="mx-1 marker-title text-primary fw-bold text-uppercase text-break" />
</span>
</div>
<div
ref="marker-pannel"
class="d-none"
>
<span class="h4 marker-title" />
<div class="marker-desc" />
<span class="marker-people">
<FontAwesomeIcon icon="fa-solid fa-users" />
<span class="mx-1 marker-title fw-bold text-uppercase text-break" />
</span>
</div>
</div>
</template>
<script lang="ts">
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import { DivIcon, Icon, Map, Marker, TileLayer, type LatLngExpression, type LatLngTuple } from "leaflet";
// @ts-ignore
import "overlapping-marker-spiderfier-leaflet";
@ -55,30 +43,32 @@ type Site = {
alt: string;
title: string;
},
divIcon: DivIcon
divIcon: DivIcon,
marker: Marker|null
};
export default defineComponent({
name: "LeafletMapVueComponent",
mixins: [trans],
components: {FontAwesomeIcon},
data(): {
wrapperClasses: string[];
map: Map;
oms: OverlappingMarkerSpiderfier;
initialPosition: LatLngExpression;
initialPosition: LatLngExpression | null;
initialZoom: number;
siteList: Array<Site>;
markerTextLength: number;
controlSliderId: string|null;
} {
return {
wrapperClasses:[],
map: {} as Map,
oms: {} as OverlappingMarkerSpiderfier,
initialPosition: [0, 0],
initialZoom: 3,
initialPosition: null,
initialZoom: 9,
siteList: [],
markerTextLength: 20
markerTextLength: 20,
controlSliderId: null
};
},
computed: {},
@ -86,7 +76,21 @@ export default defineComponent({
const json = String(this.$attrs.json ?? "{}"),
data = JSON.parse(json);
this.wrapperClasses = data.wrapperClasses ?? [];
this.initialPosition = [Number.parseFloat(data.coordinates.lat), Number.parseFloat(data.coordinates.lng)];
if(data.coordinates) {
this.initialPosition = [
Number.parseFloat(data.coordinates.lat),
Number.parseFloat(data.coordinates.lng)
];
}
if(data.initialZoom) {
this.initialZoom = data.initialZoom;
}
if(data.controlSliderId) {
this.controlSliderId = String(data.controlSliderId);
}
console.log(data);
this.parseSiteModelList(data.siteModelList);
@ -108,8 +112,12 @@ export default defineComponent({
(new TileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution: "&copy; <a href=\"http://www.openstreetmap.org/copyright\">OpenStreetMap</a>"
})).addTo(this.map as Map);
// * Auto set viewbox
(this.map as Map).fitBounds(this.siteList.map(site => Object.values(site.coords)) as LatLngTuple[]);
if(!this.initialPosition) {
// * Auto set viewbox
(this.map as Map).fitBounds(this.siteList.map(site => Object.values(site.coords)) as LatLngTuple[]);
} else {
(this.map as Map).setView(this.initialPosition, this.initialZoom);
}
// * Setup OMS
// @ts-ignore
this.oms = new OverlappingMarkerSpiderfier(this.map as Map, {
@ -130,14 +138,11 @@ export default defineComponent({
// ditto
spiralLengthFactor: 5,
});
this.oms.addListener("click", (marker: Marker) => {
console.log(marker);
});
this.oms.addListener("spiderfy", () => {
this.map.closePopup();
});
this.oms.addListener("click", this.selectedMarker);
this.oms.addListener("spiderfy", this.clearSelectedMarkers);
},
parseSiteModelList(siteModelList: LaravelModelList) {
const bodyFontSize = parseFloat(getComputedStyle(document.documentElement).fontSize);
siteModelList.forEach((site) => {
this.siteList.push({
name: String(site.name),
@ -152,6 +157,7 @@ export default defineComponent({
alt: String(site.logo_alt),
title: String(site.logo_title),
},
marker: null,
divIcon: new DivIcon({
className: "leaf-div-icon",
html: this.fetchNewMarkerElement(
@ -162,8 +168,7 @@ export default defineComponent({
title: String(site.logo_title),
}
),
iconSize: [30, 42],
iconAnchor: [15, 42]
iconSize: [10*bodyFontSize, 3*bodyFontSize],
})
});
});
@ -191,6 +196,7 @@ export default defineComponent({
this.map.addLayer(marker);
// @ts-ignore
this.oms.addMarker(marker);
site.marker = marker;
});
},
truncateString(str: string, limit: number, end: string = "..") {
@ -198,6 +204,37 @@ export default defineComponent({
return str;
}
return str.slice(0, limit) + end;
},
selectedMarker(marker: Marker) {
this.clearSelectedMarkers();
const siteIndex = this.siteList.findIndex(site => site!.marker!.options.title === marker.options.title);
if(siteIndex === -1) {
throw new Error("Could not fetch related Site");
}
const pin = marker.getElement()!.firstChild as HTMLElement | null;
if(!pin) {
throw new Error("Missing Marker Pin");
}
pin.classList.add("bg-primary", "text-white");
pin.classList.remove("bg-white", "text-primary");
if(this.controlSliderId) {
const slider = window.__SLIDERS.get(this.controlSliderId);
if(!slider) {
throw new Error(`Missing slider to control ${this.controlSliderId}`);
}
slider.swiper.slideTo(siteIndex);
}
},
clearSelectedMarkers() {
this.siteList.forEach(site => {
const pin = site.marker!.getElement()!.firstChild as HTMLElement | null;
if(!pin) {
throw new Error("Missing Marker Pin");
}
pin.classList.add("bg-white", "text-primary");
pin.classList.remove("bg-primary", "text-white");
});
}
},
});
@ -208,26 +245,29 @@ export default defineComponent({
</style>
<style lang="scss" scoped>
@import "bootstrap/scss/functions";
@import "bootstrap/scss/variables";
@import "bootstrap/scss/variables-dark";
@import "bootstrap/scss/maps";
@import "bootstrap/scss/mixins";
@import "bootstrap/scss/vendor/rfs";
.leafleat-wrapper-class {
.marker-pin {
@include rfs(10rem, min-width);
}
.marker-logo {
object-fit: contain;
height: auto;
@include rfs(2rem, width);
}
.marker-title {
@include rfs(0.8rem, font-size);
}
.leafleat-wrapper-class {
.marker-pin {
width: 10rem;
height: 3rem;
}
.marker-logo {
object-fit: contain;
height: auto;
width: 2rem;
}
.marker-title {
@include rfs(0.8rem, font-size);
overflow: hidden;
display: -webkit-box;
/* number of lines to show */
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
}
</style>

View file

@ -1,6 +1,7 @@
import CookieNotice from "@ldc-web/cookie-notice";
import type VueTagsInput from "@sipec/vue3-tags-input";
import { AxiosStatic } from "axios";
import type Swiper from "swiper";
export { };
// * Enum
@ -71,11 +72,17 @@ declare global {
type Enum = EnumInterface;
type SwiperSlider = {
element: HTMLElement;
swiper: Swiper;
};
interface Window {
CookieNotice: typeof CookieNotice;
axios: AxiosStatic;
Swal: Function;
vueDebug: boolean | undefined;
__SLIDERS: Map<string, SwiperSlider>,
__SYSTEM: {
_asset: Record<string, string>;
_locale: string;

View file

@ -593,11 +593,11 @@
'id' => 'siteLogo',
'name' => 'logo',
'width' => 1000,
'height' => 562,
'height' => 727,
'model' => $siteModel ?? null,
'helper' => __('crud.minicrud.dimensions_must_be', [
'widthpx' => '1000px',
'heightpx' => '562px',
'heightpx' => '727px',
]),
'required' => true,
'preview' => true,

View file

@ -14,7 +14,7 @@
</div>
<div class="col-12">
<div class="d-flex justify-content-between">
<a href="{{ route('fo.home.show') }}" title="{{ __('Retour à la page d\'accueil') }}">
<a href="{{ url()->previous() }}" title="{{ __('Retour à la page d\'accueil') }}">
<img class="arrow-left" src="{{ Vite::asset('resources/assets/images/misc/blue-arrow.svg') }}"
title="{{ __('Retour à la page d\'accueil') }}" alt="{{ __('Flèche vers la gauche') }}">
{{ __('Retour') }}

View file

@ -105,23 +105,17 @@
</div>
@endif
</div>
<div class="col-12 col-lg-6 order-lg-first d-flex justify-content-center">
<div class="col-12 col-lg-6 order-lg-first d-flex justify-content-center position-relative g-0">
@php
$data = [
'wrapperClasses' => 'rounded-3 embed-map w-100 my-3',
'coordinates' => [
'lat' => $viewBox->lat,
'lng' => $viewBox->lng,
],
'siteModelList' => $siteModelList,
];
$carto = ['siteModelList' => $siteModelList];
if (!empty($viewBox)) {
$carto = $carto + compact('viewBox');
}
if (!empty($initialZoom)) {
$carto['initialZoom'] = $initialZoom;
}
@endphp
<div class="leaflet-map-vue w-100" data-json='@json($data)'></div>
{{-- FIXME: Quelles coordonnées pour la map ? --}}
{{-- <iframe class="rounded-3 embed-map w-100 my-3"
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d10661.469000249905!2d-0.7577479264599797!3d48.083855231712434!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x4809013bc7a7e43f%3A0xe01d7907f663610d!2sSNV%20Laval!5e0!3m2!1sfr!2sfr!4v1709025460315!5m2!1sfr!2sfr"
title="{{ __('Carte de nos sites') }}" style="border:0;" allowfullscreen="" loading="lazy"
referrerpolicy="no-referrer-when-downgrade"></iframe> --}}
@include('fo.partials.carte', $carto)
</div>
</div>
</div>

View file

@ -0,0 +1,61 @@
{{-- Carte  page “on se dévoile” : Point central = Laval + rayon = 100 km  --}}
{{-- Carte  page “site ” : Point central =  le site  + rayon = 50 km  --}}
{{-- FIXME: USE COORDINATES TO CENTER MAP --}}
@php
$data = [
'wrapperClasses' => 'rounded-3 embed-map w-100 my-3',
'siteModelList' => $siteModelList,
'controlSliderId' => 'swiper-sites-map',
];
if (!empty($viewBox)) {
$data['coordinates'] = [
'lat' => $viewBox->lat,
'lng' => $viewBox->lng,
];
}
if (!empty($initialZoom)) {
$data['initialZoom'] = $initialZoom;
}
$colors = ['quint', 'secondary', 'sixt', 'quad'];
@endphp
<div class="leaflet-map-vue w-100 z-1" data-json='@json($data)'></div>
<div class="swiper w-100 z-2 swiper-sites-map position-absolute bottom-0 mb-4 px-2 pt-2" id="swiper-sites-map">
<div class="swiper-wrapper h-fit">
@foreach ($siteModelList as $index => $siteModel)
<div class="swiper-slide position-relative">
<div
class="d-flex map-site-widget justify-content-center align-items-stretch text-bg-white rounded-4 border-primary border-1 flex-row overflow-hidden border p-2">
<div class="d-flex align-items-center justify-content-center">
<img class="rounded-3" src="{{ asset(resize($siteModel->picture_1, 'cartoPicture')) }}"
title="{{ $siteModel->picture_1_title }}" alt="{{ $siteModel->picture_1_alt }}">
</div>
<div class="flex-grow-1 d-flex flex-column ps-3">
<div class="h4 text-uppercase fw-bold text-primary">{{ Str::limit($siteModel->name, 25, '...') }}</div>
<div class="ck-content text-primary py-1">{{ Str::limit(strip_tags($siteModel->description), 150, '...') }}
</div>
<div class="flex-grow-1 d-flex justify-content-between align-items-end mt-2 flex-row pb-2">
<span class="text-primary d-inline-block">
<i class="fa-solid fa-users me-2"></i>
<span>{{ $siteModel->employees }}</span>
</span>
<a class="text-bg-{{ $colors[$index % count($colors)] }} carto-link p-3"
href="{{ route('fo.sites.show', $siteModel) }}" alt="{{ __('Voir la page du site') }}">
<i class="fa fa-plus"></i>
</a>
</div>
</div>
</div>
</div>
@endforeach
@push('styles')
<style nonce="{{ $nonce }}">
.carto-link {
position: relative;
bottom: -1.1rem;
border-radius: 1rem 0 0 0;
right: -.5rem;
}
</style>
@endpush
</div>
</div>