generated from gitea_admin/default
Compare commits
9 Commits
329b43e07c
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| bc6ad43ea5 | |||
| b0352c963c | |||
| db365010e9 | |||
| d35d174918 | |||
| 71aae090e2 | |||
| 35be3e4ee3 | |||
| 8dd7cbbb06 | |||
| 35d326ab03 | |||
| c258a436a0 |
227
README.md
227
README.md
@@ -3,16 +3,30 @@
|
||||
- VueJS 3.5
|
||||
|
||||
# Dev du site en local
|
||||
# NUXT
|
||||
## NUXT
|
||||
Démarrer NUXT
|
||||
- npm run dev
|
||||
- URL : http://localhost:3000/
|
||||
|
||||
# Variables d'environnement
|
||||
Elles sont **définies** dans `ecosystem.config.cjs` (PM2) et **consommées** dans `nuxt.config.js` via `runtimeConfig`.
|
||||
|
||||
Exemples de variables :
|
||||
- `NUXT_PUBLIC_STRAPI_URL`
|
||||
- `NUXT_PUBLIC_SAISON`
|
||||
- `NUXT_STRAPI_TOKEN`
|
||||
|
||||
Utilisation dans le code :
|
||||
- `runtimeConfig.public.saison`
|
||||
- `runtimeConfig.public.strapiUrl`
|
||||
|
||||
Après modification de `ecosystem.config.cjs` :
|
||||
- `pm2 reload ecosystem.config.cjs --only wondif_vue`
|
||||
|
||||
# Site de développement
|
||||
## URL
|
||||
https://2025.orchestre-ile.com/
|
||||
|
||||
# TODO
|
||||
## Serveur web
|
||||
Créer un vrai /security.txt (ou /.well-known/security.txt) au lieu de le renvoyer en 404.
|
||||
dans le fichier de conf NGINX /etc/nginx/sites-available$ sudo nano wondif_2025
|
||||
@@ -41,9 +55,10 @@ git push origin main
|
||||
cd /var/www/wondif_vue
|
||||
|
||||
git pull origin main # récupère le dernier code
|
||||
npm ci # installe / met à jour les dépendances
|
||||
npm ci # installe / met à jour les dépendances (à exécuter uniquement si nouvelle dépendances installées dans package json)
|
||||
npm run build # rebuild Nuxt
|
||||
pm2 restart wondif_vue # redémarre le process
|
||||
pm2 reload ecosystem.config.cjs --only wondif_vue # redémarre le process avec les nouvelles variables d'environnement de ecosystem
|
||||
|
||||
|
||||
# STRAPI
|
||||
## URL de PROD
|
||||
@@ -108,6 +123,16 @@ populate[liens_youtube_concert]=true
|
||||
| A| B| C|
|
||||
|
||||
|
||||
API pour avoir la page Les Missions
|
||||
https://bo.orchestre-ile.com/api/mission?locale=fr-FR&populate=image_illustration_header
|
||||
https://bo.orchestre-ile.com/api/mission?locale=fr-FR&populate=*
|
||||
|
||||
|
||||
## SAISIE DU CONTENU
|
||||
### slug
|
||||
- concert
|
||||
- mettre le nom du concert avec la date
|
||||
|
||||
# CSS
|
||||
## LAYOUT
|
||||
|
||||
@@ -153,6 +178,30 @@ Array.from(document.querySelectorAll('body > *')).forEach(el => {
|
||||
});
|
||||
|
||||
|
||||
|
||||
@media (max-width: 980px) {
|
||||
.decalage_gauche {
|
||||
margin-left: -23px;
|
||||
}
|
||||
}
|
||||
|
||||
01_siick_smol_girlfriend_5m50.mp3
|
||||
02_siick_lunar_blast 213_5m13.wav
|
||||
03_siick_crystal_cavern_5m24.wav
|
||||
|
||||
|
||||
01_leon_romanens_8m49_stereo.wav
|
||||
02_marie_pierre_8m57_stereo.wav
|
||||
03_siick_7m23_stereo.wav
|
||||
04_celine_espuna_4m34_stereo.wav
|
||||
06_walid_nouh_6m44_stereo.wav
|
||||
08_codimp_7m43_stereo.wav
|
||||
05_adrien_bourmault_7m53_stereo.wav
|
||||
07_rafael_muniz_3m15_stereo.wav
|
||||
|
||||
|
||||
|
||||
debian@vps-48ebe2d9:~$ history
|
||||
1 sudo nano ~/.bashrc
|
||||
2 exit
|
||||
3 ll
|
||||
@@ -804,4 +853,172 @@ Array.from(document.querySelectorAll('body > *')).forEach(el => {
|
||||
649 SELECT NOW() AS now_local, UTC_TIMESTAMP() AS now_utc, TIMEDIFF(NOW(), UTC_TIMESTAMP()) AS diff;
|
||||
650 show databeses
|
||||
651 show databeses;
|
||||
652 history
|
||||
652 history
|
||||
653 mysql -u root -p
|
||||
654 pm2 list
|
||||
655 pm2 describe strapi_wondif
|
||||
656 TZ=Europe/Paris pm2 restart strapi_wondif --update-env
|
||||
657 pm2 describe strapi_wondif
|
||||
658 ll
|
||||
659 cd src
|
||||
660 ll
|
||||
661 cd admin/
|
||||
662 ll
|
||||
663 mv app.example.js app.js
|
||||
664 ll
|
||||
665 sudo nano app.js
|
||||
666 more app.js
|
||||
667 cd ..
|
||||
668 ll
|
||||
669 NODE_ENV=production npm run build
|
||||
670 pm2 list
|
||||
671 pm2 restart strapi_wondif
|
||||
672 pm2 list
|
||||
673 ll
|
||||
674 more jsconfig.json
|
||||
675 ll
|
||||
676 cd config/
|
||||
677 ll
|
||||
678 cd ..
|
||||
679 ll
|
||||
680 cd build/
|
||||
681 ll
|
||||
682 cd ..
|
||||
683 ll
|
||||
684 sudo nano
|
||||
685 ll
|
||||
686 more ecosystem.config.js
|
||||
687 pm2 list
|
||||
688 pm2 strapi_wondif stop
|
||||
689 pm2 stop strapi_wondif
|
||||
690 pm2 start ecosystem.config.js
|
||||
691 pm2 list
|
||||
692 pm2 env 0 | grep -E '^TZ=|^NODE_ENV='
|
||||
693 ll
|
||||
694 rm ecosystem.config.js
|
||||
695 pm2 list
|
||||
696 pm2 stop strapi_wondif
|
||||
697 pm2 restart strapi_wondif
|
||||
698 pm2 stop strapi_wondif
|
||||
699 sudo nano
|
||||
700 ll
|
||||
701 pm2 list
|
||||
702 sudo nano eco
|
||||
703 sudo nano ecosystem.config.js
|
||||
704 pm2 start ecosystem.config.js
|
||||
705 pm2 describe strapi_wondif2
|
||||
706 pm2 stop strapi_wondif2
|
||||
707 pm2 delete strapi_wondif2
|
||||
708 rm ecosystem.config.js
|
||||
709 pm2 reload strapi_wondif
|
||||
710 pm2 list
|
||||
711 cd /etc/nginx
|
||||
712 ll
|
||||
713 cd sites-available
|
||||
714 ll
|
||||
715 more wondif_media
|
||||
716 ll
|
||||
717 sudo nano wondif_media
|
||||
718 nginx -t
|
||||
719 sudo nginx -t
|
||||
720 sudo nginx -s reload
|
||||
721 systemctl restart nginx
|
||||
722 cd www
|
||||
723 www
|
||||
724 ll
|
||||
725 cd wondif_vue/
|
||||
726 ll
|
||||
727 git pull origin main
|
||||
728 npm ci
|
||||
729 ll
|
||||
730 cd app
|
||||
731 ll
|
||||
732 cd pages/
|
||||
733 ll
|
||||
734 cd concerts/
|
||||
735 ll
|
||||
736 www
|
||||
737 cd wondif_vue/
|
||||
738 ll
|
||||
739 npm run build
|
||||
740 pm2 list
|
||||
741 pm2 restart wondif_vue
|
||||
742 pm2 logs wondif_vue --lines 100
|
||||
743 ll
|
||||
744 sudo nano .env
|
||||
745 pm2 logs strapi_wondif --lines 100
|
||||
746 pm2 show wondif_vue
|
||||
747 pm2 env 1
|
||||
748 sudo nano .env
|
||||
749 ll
|
||||
750 sudo nano .env
|
||||
751 pm2 show wondif_vue
|
||||
752 ll
|
||||
753 more package.json
|
||||
754 pm2 restart wondif_vue
|
||||
755 pm2 show wondif_vue
|
||||
756 pm2 env 1
|
||||
757 ll
|
||||
758 sudo nano v
|
||||
759 sudo nano nuxt.config.js
|
||||
760 npm run build
|
||||
761 pm2 restart wondif_vue
|
||||
762 pm2 env 1
|
||||
763 git pull origin main
|
||||
764 git reset --hard HEAD
|
||||
765 git pull origin main
|
||||
766 pm2 list
|
||||
767 pm2 env 1
|
||||
768 pm2 env 2
|
||||
769 pm2 env 1
|
||||
770 www
|
||||
771 ll
|
||||
772 cd wondif_vue/
|
||||
773 ll
|
||||
774 more package.json
|
||||
775 ll
|
||||
776 more nuxt.config.js
|
||||
777 ll
|
||||
778 git pull origin main
|
||||
779 npm run build
|
||||
780 pm2 restart wondif_vue
|
||||
781 more nuxt.config.js
|
||||
782 more package.json
|
||||
783 more .env
|
||||
784 git pull origin main
|
||||
785 ll
|
||||
786 npm run build
|
||||
787 pm2 list
|
||||
788 pm2 delete wondif_vue
|
||||
789 pm2 start ecosystem.config.cjs
|
||||
790 pm2 save
|
||||
791 pm2 env wondif_vue
|
||||
792 pm2 env 1
|
||||
793 pm2 reload wondif_vue --update-env
|
||||
794 pm2 list
|
||||
795 pm2 env 1
|
||||
796 pm2 env 3
|
||||
797 more .env
|
||||
798 git pull origin main
|
||||
799 npm run build
|
||||
800 pm2 reload wondif_vue --update-env
|
||||
801 www
|
||||
802 ll
|
||||
803 cd wondif_vue/
|
||||
804 ll
|
||||
805 more .env
|
||||
806 ll
|
||||
807 rm .env
|
||||
808 ll
|
||||
809 npm run build
|
||||
810 pm2 reload wondif_vue --update-env
|
||||
811 history
|
||||
812 www
|
||||
813 ll
|
||||
814 cd strapi_wondif/
|
||||
815 ll
|
||||
816 NODE_ENV=production npm run build
|
||||
817 pm2 list
|
||||
818 pm2 restart strapi_wondif
|
||||
819 pm2 list
|
||||
820 history
|
||||
|
||||
BIN
app/assets/img/illustrations/orchestre_1.jpg
Normal file
BIN
app/assets/img/illustrations/orchestre_1.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 176 KiB |
BIN
app/assets/img/illustrations/orchestre_2.webp
Normal file
BIN
app/assets/img/illustrations/orchestre_2.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 113 KiB |
@@ -13,4 +13,10 @@
|
||||
margin: 0;
|
||||
object-fit: cover;
|
||||
//filter: contrast(0.8);
|
||||
}
|
||||
|
||||
.img_placeholder {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
@@ -48,7 +48,7 @@
|
||||
padding-right: 16px;
|
||||
padding-bottom: 5px;
|
||||
text-align: left;
|
||||
background-color: rgba(255, 255, 255, 0.95);
|
||||
background-color: var(--c-surface);
|
||||
border-radius: 3px;
|
||||
|
||||
.header_nav_topbar_submenu_item {
|
||||
@@ -64,6 +64,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header_nav_lang {
|
||||
display: flex;
|
||||
font-family: 'brandontext_medium';
|
||||
@@ -105,7 +106,8 @@
|
||||
|
||||
}
|
||||
.header_nav_logo {
|
||||
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
@include media_queries.media_min(tablet_700) {
|
||||
margin-top: -7px;
|
||||
}
|
||||
@@ -167,6 +169,19 @@
|
||||
|
||||
//font-family: 'brandontext_regular';
|
||||
font-family: var(--font-roboto);
|
||||
// wght Graisse
|
||||
// YTLC Hauteur miniscule
|
||||
// YTUC Hauteur majuscule
|
||||
// YTAS Hauteur des hampes ascendantes
|
||||
// YTDE Hauteur des hampes descendantes
|
||||
// wdth largeur horizontale des lettres
|
||||
font-variation-settings:
|
||||
"wdth" 41,
|
||||
"wght" 662,
|
||||
"YTLC" 570,
|
||||
"YTUC" 760,
|
||||
"YTAS" 794,
|
||||
"YTDE" -275;
|
||||
|
||||
@include media_queries.media_min(tablet_600) {
|
||||
font-size: 18px;
|
||||
@@ -204,6 +219,11 @@
|
||||
|
||||
list-style: none;
|
||||
|
||||
@media (min-width: 728px) and (max-width: 795px) {
|
||||
.decalage_gauche {
|
||||
margin-left: -73px;
|
||||
}
|
||||
}
|
||||
|
||||
&:nth-child(5) {
|
||||
margin-right: 10px;
|
||||
@@ -243,25 +263,27 @@
|
||||
/* Pour l'effet de transition */
|
||||
opacity: 0;
|
||||
transition: visibility 0.2s,opacity 0.2s cubic-bezier(0.4, 0, 1, 1);
|
||||
padding-top: 10px;
|
||||
padding-left: 20px;
|
||||
padding-right: 7px;
|
||||
padding-top: 17px;
|
||||
padding-left: 27px;
|
||||
padding-right: 12px;
|
||||
padding-bottom: 10px;
|
||||
text-align: left;
|
||||
background-color: rgba(255, 255, 255, 0.97);
|
||||
background-color: var(--c-surface);
|
||||
border-radius: 3px;
|
||||
|
||||
.header_nav_sub_menu_item {
|
||||
list-style: circle;
|
||||
//font-family: 'brandontext_regular';
|
||||
font-family: var(--font-roboto);
|
||||
font-variation-settings:
|
||||
"wdth" 41, "wght" 552, "YTLC" 570, "YTUC" 760, "YTAS" 794, "YTDE" -275;
|
||||
@media (min-width: 0px) {
|
||||
font-size: 16px;
|
||||
}
|
||||
@media (min-width: 900px) {
|
||||
font-size: 18px;
|
||||
}
|
||||
padding-bottom: 4px;
|
||||
padding-bottom: 7px;
|
||||
&:hover {
|
||||
a {
|
||||
color: var(--c-brand_rouge);
|
||||
@@ -389,17 +411,17 @@
|
||||
|
||||
&.is-open {
|
||||
.burger_line:nth-child(1) {
|
||||
top: 8px;
|
||||
transform: rotate(45deg);
|
||||
top: 8px;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.burger_line:nth-child(2) {
|
||||
opacity: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.burger_line:nth-child(3) {
|
||||
top: 8px;
|
||||
transform: rotate(-45deg);
|
||||
top: 8px;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -415,6 +437,13 @@
|
||||
margin-top: 47px;
|
||||
|
||||
font-family: var(--font-roboto);
|
||||
font-variation-settings:
|
||||
"wdth" 41,
|
||||
"wght" 662,
|
||||
"YTLC" 570,
|
||||
"YTUC" 760,
|
||||
"YTAS" 794,
|
||||
"YTDE" -275;
|
||||
|
||||
padding-bottom: 10px;
|
||||
padding-right: 10px;
|
||||
@@ -444,6 +473,7 @@
|
||||
|
||||
|
||||
&.is-open {
|
||||
border-bottom: none !important;
|
||||
.header_drawer_sub_menu {
|
||||
display: block;
|
||||
visibility: visible;
|
||||
@@ -481,6 +511,8 @@
|
||||
list-style: none;
|
||||
//font-family: 'brandontext_regular';
|
||||
font-family: var(--font-roboto);
|
||||
font-variation-settings:
|
||||
"wdth" 41, "wght" 552, "YTLC" 570, "YTUC" 760, "YTAS" 794, "YTDE" -275;
|
||||
font-size: 18px;
|
||||
padding-bottom: 4px;
|
||||
list-style: circle;
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
}
|
||||
@media (min-width: 500px) {
|
||||
.banniere_pros_wp {
|
||||
grid-template-columns: 150px 270px 40px 40px;
|
||||
grid-template-columns: 150px 250px 35px 35px;
|
||||
grid-template-rows: auto;
|
||||
//justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div v-if="items.length > 1" aria-label="Fil d’Ariane" class="breadcrumb">
|
||||
<ul class="breadcrumb__list">
|
||||
<li v-for="(item, i) in items" :key="item.to" class="breadcrumb__item">
|
||||
<NuxtLink v-if="i < items.length - 1" :to="item.to">
|
||||
<NuxtLink v-if="i < items.length - 1 && !item.noLink" :to="item.to">
|
||||
<img
|
||||
v-if="i === 0"
|
||||
src="/img/icones/house-grey.svg"
|
||||
@@ -32,6 +32,27 @@
|
||||
professionnels: "Professionnels"
|
||||
}
|
||||
|
||||
function resolveTo(part, index, parts, acc) {
|
||||
if (part === 'concerts') {
|
||||
const next = parts[index + 1] || ''
|
||||
if (next.startsWith('concert-')) {
|
||||
const from = typeof route.query.from === 'string' ? route.query.from : ''
|
||||
if (from === 'agenda') return '/concerts/agenda'
|
||||
if (from === 'saison') return '/concerts/saison'
|
||||
if (from === 'jeune-public') return '/concerts/jeune-public'
|
||||
}
|
||||
}
|
||||
if (part === 'orchestre') {
|
||||
const next = parts[index + 1] || ''
|
||||
if (next.startsWith('artiste-') || next.startsWith('artisteinvitee-') || next.startsWith('artistesinvitees-')) {
|
||||
const from = typeof route.query.from === 'string' ? route.query.from : ''
|
||||
if (from === 'musiciens') return '/orchestre/musiciens'
|
||||
if (from === 'artistesinvitees') return '/orchestre/artistesinvitees'
|
||||
}
|
||||
}
|
||||
return acc
|
||||
}
|
||||
|
||||
function humanize(segment) {
|
||||
return segment
|
||||
.replace(/-/g, ' ')
|
||||
@@ -41,6 +62,7 @@
|
||||
const items = computed(() => {
|
||||
const parts = route.path.split('/').filter(Boolean)
|
||||
const crumbs = [{ to: '/', label: 'Accueil' }]
|
||||
const from = typeof route.query.from === 'string' ? route.query.from : ''
|
||||
|
||||
let acc = ''
|
||||
parts.forEach((part, index) => {
|
||||
@@ -50,7 +72,35 @@
|
||||
? props.currentLabel
|
||||
: (labelMap[part] || humanize(decodeURIComponent(part)))
|
||||
|
||||
crumbs.push({ to: acc, label })
|
||||
const noLink = part === 'orchestre' || part === 'concerts'
|
||||
crumbs.push({ to: resolveTo(part, index, parts, acc), label, noLink })
|
||||
|
||||
if (part === 'concerts') {
|
||||
const next = parts[index + 1] || ''
|
||||
if (next.startsWith('concert-')) {
|
||||
if (from === 'agenda') {
|
||||
crumbs.push({ to: '/concerts/agenda', label: 'Agenda' })
|
||||
}
|
||||
if (from === 'saison') {
|
||||
crumbs.push({ to: '/concerts/saison', label: 'Saison' })
|
||||
}
|
||||
if (from === 'jeune-public') {
|
||||
crumbs.push({ to: '/concerts/jeune-public', label: 'Jeune public' })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (part === 'orchestre') {
|
||||
const next = parts[index + 1] || ''
|
||||
if (next.startsWith('artiste-') || next.startsWith('artisteinvitee-')) {
|
||||
if (from === 'musiciens') {
|
||||
crumbs.push({ to: '/orchestre/musiciens', label: 'Les musiciens' })
|
||||
}
|
||||
if (from === 'artistesinvitees') {
|
||||
crumbs.push({ to: '/orchestre/artistesinvitees', label: 'Les artistes invités' })
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return crumbs
|
||||
@@ -68,13 +118,13 @@
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
@media (min-width: 0px) {
|
||||
padding-left: 20px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
padding-left: 20px;
|
||||
padding-left: 0px;
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
padding-left: 20px;
|
||||
padding-left: 0px;
|
||||
}
|
||||
}
|
||||
.breadcrumb__list {
|
||||
|
||||
@@ -16,12 +16,24 @@
|
||||
</div>
|
||||
|
||||
<!-- Hint icon (micro affordance) -->
|
||||
<div v-if="showHint" class="hc__hint" aria-hidden="true">
|
||||
<button
|
||||
v-if="showHint"
|
||||
type="button"
|
||||
class="hc__hint"
|
||||
aria-label="Défiler vers la droite"
|
||||
@click="scrollByHint(1)"
|
||||
>
|
||||
<span class="hc__hint-icon">{{ hintIcon }}</span>
|
||||
</div>
|
||||
<div v-if="showHint" class="hc__hint--left" aria-hidden="true">
|
||||
</button>
|
||||
<button
|
||||
v-if="showHint"
|
||||
type="button"
|
||||
class="hc__hint--left"
|
||||
aria-label="Défiler vers la gauche"
|
||||
@click="scrollByHint(-1)"
|
||||
>
|
||||
<span class="hc__hint-icon">{{ hintIcon }}</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<!-- Scroller -->
|
||||
<div
|
||||
@@ -103,6 +115,14 @@
|
||||
t = setTimeout(() => {}, 80)
|
||||
}
|
||||
|
||||
const scrollByHint = (direction) => {
|
||||
const el = scroller.value
|
||||
if (!el) return
|
||||
|
||||
const distance = Math.max(140, Math.round(el.clientWidth * 0.8))
|
||||
el.scrollBy({ left: distance * direction, behavior: 'smooth' })
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
const el = scroller.value
|
||||
if (!el) return
|
||||
@@ -187,7 +207,11 @@
|
||||
|
||||
/* Hint icon */
|
||||
.hc__hint {
|
||||
pointer-events: none;
|
||||
pointer-events: auto;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
appearance: none;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 50%;
|
||||
@@ -204,7 +228,11 @@
|
||||
z-index: 2;
|
||||
}
|
||||
.hc__hint--left {
|
||||
pointer-events: none;
|
||||
pointer-events: auto;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
appearance: none;
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 50%;
|
||||
@@ -300,4 +328,4 @@
|
||||
opacity: 0.55;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
<!-- Actions -->
|
||||
<div class="concert-card__actions">
|
||||
<DsButtonArrow :to="`/concerts/${id}`" variant="secondary">
|
||||
<DsButtonArrow :to="`/concerts/concert-${id}`" variant="secondary">
|
||||
Découvrir
|
||||
</DsButtonArrow>
|
||||
</div>
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
defineProps({
|
||||
id: { type: [String, Number], required: true },
|
||||
title: { type: String, required: true },
|
||||
lieu: { type: String, required: true },
|
||||
lieu: { type: String, default: '' },
|
||||
dateISO: { type: String, required: true }, // ex: "2026-01-15T20:00:00+01:00"
|
||||
dateLabel: { type: String, required: true }, // ex: "Jeu. 15 jan. 2026 — 20h"
|
||||
description: { type: String, default: '' },
|
||||
@@ -86,4 +86,4 @@
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -135,6 +135,7 @@
|
||||
//règle spécifique après la règle générale
|
||||
.concert-card-list.concert-card-list--highlight-first > .concert-card:first-child {
|
||||
flex: 2 1 480px;
|
||||
min-width: 500px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,9 +40,9 @@
|
||||
margin-left: -11px;
|
||||
}
|
||||
.img_ticket_mob {
|
||||
max-height: 37px;
|
||||
margin-top: 9px;
|
||||
margin-left: -11px;
|
||||
max-height: 31px;
|
||||
margin-top: 10px;
|
||||
// margin-left: -11px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
<li class="header_nav_sub_menu_item"><NuxtLink to="/orchestre/missions">Nos missions</NuxtLink></li>
|
||||
<li class="header_nav_sub_menu_item"><NuxtLink to="/orchestre/direction">Direction musicale</NuxtLink></li>
|
||||
<li class="header_nav_sub_menu_item"><NuxtLink to="/orchestre/musiciens">Les musiciens</NuxtLink></li>
|
||||
<li class="header_nav_sub_menu_item"><NuxtLink to="/orchestre/artistes-invitees">Les artistes invités</NuxtLink></li>
|
||||
<li class="header_nav_sub_menu_item"><NuxtLink to="/orchestre/artistesinvitees">Les artistes invités</NuxtLink></li>
|
||||
<li class="header_nav_sub_menu_item"><NuxtLink to="/orchestre/discographie">Discographie</NuxtLink></li>
|
||||
<li class="header_nav_sub_menu_item"><NuxtLink to="/orchestre/partenaires">Nos partenaires</NuxtLink></li>
|
||||
<li class="header_nav_sub_menu_item"><NuxtLink to="/mecenat/soutenir">Nous soutenir</NuxtLink></li>
|
||||
@@ -57,7 +57,7 @@
|
||||
</li>
|
||||
|
||||
<li class="header_nav_item" :class="{ 'is-active': isMediation }">
|
||||
Éducation et médiation
|
||||
Action culturelle
|
||||
<ul class="header_nav_sub_menu">
|
||||
<li class="header_nav_sub_menu_item"><NuxtLink to="/mediation/petite-enfance">Petite enfance</NuxtLink></li>
|
||||
<li class="header_nav_sub_menu_item"><NuxtLink to="/mediation/scolaires">Scolaires</NuxtLink></li>
|
||||
@@ -70,7 +70,7 @@
|
||||
|
||||
<li class="header_nav_item" :class="{ 'is-active': isMecenat }">
|
||||
Mécénat
|
||||
<ul class="header_nav_sub_menu">
|
||||
<ul class="header_nav_sub_menu decalage_gauche">
|
||||
<li class="header_nav_sub_menu_item"><NuxtLink to="/mecenat/soutenir">Nous soutenir</NuxtLink></li>
|
||||
<li class="header_nav_sub_menu_item"><NuxtLink to="/mecenat/entreprises">Entreprises</NuxtLink></li>
|
||||
<li class="header_nav_sub_menu_item"><NuxtLink to="/mecenat/projets">Les projets</NuxtLink></li>
|
||||
@@ -166,7 +166,7 @@
|
||||
<li class="header_drawer_sub_menu_item"><NuxtLink to="/orchestre/missions">Nos missions</NuxtLink></li>
|
||||
<li class="header_drawer_sub_menu_item"><NuxtLink to="/orchestre/direction">Direction musicale</NuxtLink></li>
|
||||
<li class="header_drawer_sub_menu_item"><NuxtLink to="/orchestre/musiciens">Les musiciens</NuxtLink></li>
|
||||
<li class="header_drawer_sub_menu_item"><NuxtLink to="/orchestre/artistes-invitees">Les artistes invités</NuxtLink></li>
|
||||
<li class="header_drawer_sub_menu_item"><NuxtLink to="/orchestre/artistesinvitees">Les artistes invités</NuxtLink></li>
|
||||
<li class="header_drawer_sub_menu_item"><NuxtLink to="/orchestre/discographie">Discographie</NuxtLink></li>
|
||||
<li class="header_drawer_sub_menu_item"><NuxtLink to="/orchestre/partenaires">Nos partenaires</NuxtLink></li>
|
||||
<li class="header_drawer_sub_menu_item"><NuxtLink to="/mecenat/soutenir">Nous soutenir</NuxtLink></li>
|
||||
@@ -193,7 +193,7 @@
|
||||
:class="{ 'is-open': activeDrawer === 'education' }"
|
||||
@click="toggleDrawer('education')"
|
||||
>
|
||||
Éducation et médiation
|
||||
Action culturelle
|
||||
<ul class="header_drawer_sub_menu">
|
||||
<li class="header_drawer_sub_menu_item"><NuxtLink to="/mediation/petite-enfance">Petite enfance</NuxtLink></li>
|
||||
<li class="header_drawer_sub_menu_item"><NuxtLink to="/mediation/scolaires">Scolaires</NuxtLink></li>
|
||||
@@ -280,7 +280,7 @@
|
||||
route.path.startsWith('/concerts')
|
||||
)
|
||||
|
||||
// Éducation et médiation
|
||||
// Action culturelle
|
||||
const isMediation = computed(() =>
|
||||
route.path.startsWith('/mediation')
|
||||
)
|
||||
|
||||
161
app/components/section/Decalage.vue
Normal file
161
app/components/section/Decalage.vue
Normal file
@@ -0,0 +1,161 @@
|
||||
<template>
|
||||
<div class="decalage_cont"
|
||||
:class="[
|
||||
`decalage_cont--${position}`
|
||||
]"
|
||||
>
|
||||
<div class="decalage"
|
||||
:class="[
|
||||
`decalage--${tone}`,
|
||||
`decalage--${position}`
|
||||
]"
|
||||
>
|
||||
<div class="decalage_inner">
|
||||
<DsHeading v-if="$slots.title" :tone="titleTone" as="h2" textcase="uppercase">
|
||||
<slot name="title" />
|
||||
</DsHeading>
|
||||
<slot />
|
||||
<div v-if="$slots.button" class="decalage_button">
|
||||
<slot name="button" />
|
||||
</div>
|
||||
<div v-if="ensavoirplusTarget" class="decalage_button">
|
||||
<DsButton :textColor="buttonTone" :borderColor="buttonTone" @click="toggleTarget(ensavoirplusTarget)">En savoir +</DsButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import DsHeading from '@root/design-system/primitives/DsHeading.vue'
|
||||
import DsText from '@root/design-system/primitives/DsText.vue'
|
||||
import DsButton from '@root/design-system/primitives/DsButton.vue'
|
||||
|
||||
defineProps({
|
||||
tone: { type: String, default: 'default' },
|
||||
titleTone: { type: String, default: 'default' },
|
||||
buttonTone: { type: String, default: 'default' },
|
||||
position: { type: String, default: 'left' },
|
||||
ensavoirplusTarget: { type: String, default: '' }
|
||||
})
|
||||
|
||||
function toggleTarget(ensavoirplusTarget) {
|
||||
document.getElementById(ensavoirplusTarget).classList.toggle("decalage_ensavoirplus--hidden");
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
.decalage_cont {
|
||||
margin-bottom: 70px;
|
||||
display: flex;
|
||||
|
||||
&--left {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
&--right {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.decalage {
|
||||
padding-top: 50px;
|
||||
padding-bottom: 50px;
|
||||
display: flex;
|
||||
|
||||
@media (min-width: 0px) and (max-width: 700px) {
|
||||
width: 89vw;
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
width: 67vw;
|
||||
}
|
||||
@media (min-width: 800px) {
|
||||
width: 60vw;
|
||||
}
|
||||
|
||||
/* tons = arrière-plan section */
|
||||
&--default { background: transparent; }
|
||||
&--brand { background: var(--c-brand_rouge);}
|
||||
&--dark { background: var(--c-backgroud-black); }
|
||||
&--brandreverse { background: var(--c-backgroud-brandreverse); }
|
||||
&--jaune { background: var(--c-background-jaune); }
|
||||
|
||||
/* position = arrière-plan section */
|
||||
&--right {
|
||||
|
||||
.decalage_inner {
|
||||
padding-right: 20px;
|
||||
padding-left: 50px;
|
||||
|
||||
@media (max-width: 599px) {
|
||||
padding-right: 15px;
|
||||
padding-left: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&--left {
|
||||
justify-content: flex-end;
|
||||
|
||||
.decalage_inner {
|
||||
padding-right: 50px;
|
||||
padding-left: 20px;
|
||||
|
||||
@media (max-width: 599px) {
|
||||
padding-right: 40px;
|
||||
padding-left: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.decalage_inner {
|
||||
|
||||
@media (min-width: 0px) {
|
||||
width: 100%;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
width: calc(290px + 39vw);
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
width: calc(330px + 17vw);
|
||||
}
|
||||
@media (min-width: 800px) {
|
||||
width: calc(330px + 17vw);
|
||||
}
|
||||
@media (min-width: 900px) {
|
||||
width: 600px;
|
||||
}
|
||||
@media (min-width: 1000px) {
|
||||
width: 600px;
|
||||
}
|
||||
@media (min-width: 1100px) {
|
||||
width: 600px;
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
width: 600px;
|
||||
}
|
||||
@media (min-width: 1300px) {
|
||||
width: 600px;
|
||||
}
|
||||
@media (min-width: 1400px) {
|
||||
width: 600px;
|
||||
}
|
||||
@media (min-width: 1500px) {
|
||||
width: 600px;
|
||||
}
|
||||
}
|
||||
|
||||
.decalage_button {
|
||||
margin-top: 10px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.decalage_ensavoirplus--hidden {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
@@ -27,8 +27,6 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
tone: { type: String, default: 'default' }, // default / brand / muted / dark…
|
||||
padded_size: { type: String, default: '' }, // none | sm | md | lg
|
||||
@@ -39,7 +37,6 @@
|
||||
position : { type: String, default: '' },
|
||||
overflow : { type: String, default: '' }
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@@ -56,6 +53,10 @@
|
||||
&--brand { background: var(--c-brand_rouge);}
|
||||
&--dark { background: var(--c-backgroud-black); }
|
||||
&--brandreverse { background: var(--c-backgroud-brandreverse); }
|
||||
&--jaune { background: var(--c-background-jaune); }
|
||||
&--bleu { background: var(--c-background-bleu); }
|
||||
&--rouge45 { background: var(--c-brand_rouge45); }
|
||||
&--rouge-weak { background: var(--c-brand_rouge-weak); }
|
||||
|
||||
// padding en haut et en bas
|
||||
&--padded {
|
||||
@@ -68,7 +69,6 @@
|
||||
padding-bottom: 120px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
|
||||
@media (min-width: 0px) {
|
||||
max-width: 100%;
|
||||
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
max-width: 580px;
|
||||
|
||||
@@ -102,16 +102,17 @@
|
||||
font-family: var(--font-roboto);
|
||||
|
||||
&--p {
|
||||
|
||||
font-weight: var(--fw-light);
|
||||
font-size: 17px;
|
||||
line-height: 22px;
|
||||
margin-bottom: 5px;
|
||||
text-align: justify;
|
||||
}
|
||||
h1 {
|
||||
padding-bottom: 10px;
|
||||
font-weight: var(--fw-bold);
|
||||
font-size: 30px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
h2 {
|
||||
padding-bottom: 7px;
|
||||
|
||||
96
app/composables/useArtistesInvitees_asuppr.js
Normal file
96
app/composables/useArtistesInvitees_asuppr.js
Normal file
@@ -0,0 +1,96 @@
|
||||
export function useArtistesInvitees(options = {}) {
|
||||
const queryString = computed(() => {
|
||||
const locale = unref(options.locale) ?? "fr-FR"
|
||||
const sort = unref(options.sort) ?? null
|
||||
const populate = unref(options.populate) ?? null
|
||||
const filters = unref(options.filters) ?? null
|
||||
|
||||
const query = new URLSearchParams()
|
||||
query.set("locale", locale)
|
||||
if (sort) {
|
||||
query.set("sort[0]", sort)
|
||||
}
|
||||
if (populate && typeof populate === "object") {
|
||||
appendPopulate(query, populate)
|
||||
}
|
||||
if (filters && typeof filters === "object") {
|
||||
appendFilters(query, filters)
|
||||
}
|
||||
|
||||
return query.toString()
|
||||
})
|
||||
|
||||
const { data, pending, error, refresh } = useFetch(
|
||||
() => `/api/__strapi__/artistesinvitees?${queryString.value}`,
|
||||
{
|
||||
server: true,
|
||||
key: () => `artistesinvitees:${queryString.value}`,
|
||||
watch: [queryString],
|
||||
}
|
||||
)
|
||||
|
||||
const artistesinvitees = computed(() => {
|
||||
let list = (data.value?.data || []).map(normalizeArtiste)
|
||||
|
||||
const limit = unref(options.limit)
|
||||
if (typeof limit === "number") {
|
||||
list = list.slice(0, Math.max(0, limit))
|
||||
}
|
||||
|
||||
return list
|
||||
})
|
||||
|
||||
return {
|
||||
artistesinvitees,
|
||||
concerts: artistesinvitees,
|
||||
pending,
|
||||
error,
|
||||
refresh,
|
||||
}
|
||||
}
|
||||
|
||||
function appendPopulate(query, populate, prefix = "populate") {
|
||||
Object.entries(populate).forEach(([key, value]) => {
|
||||
if (value === true) {
|
||||
query.set(`${prefix}[${key}]`, "true")
|
||||
return
|
||||
}
|
||||
if (value && typeof value === "object") {
|
||||
const entries = Object.entries(value)
|
||||
const allTrue = entries.length > 0 && entries.every(([, v]) => v === true)
|
||||
if (allTrue) {
|
||||
const list = entries.map(([k]) => k).join(",")
|
||||
query.set(`${prefix}[${key}][populate]`, list)
|
||||
return
|
||||
}
|
||||
appendPopulate(query, value, `${prefix}[${key}][populate]`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function appendFilters(query, filters, prefix = "filters") {
|
||||
Object.entries(filters).forEach(([key, value]) => {
|
||||
if (value === null || value === undefined) return
|
||||
if (typeof value !== "object") {
|
||||
query.set(`${prefix}[${key}]`, String(value))
|
||||
return
|
||||
}
|
||||
Object.entries(value).forEach(([k, v]) => {
|
||||
if (v === null || v === undefined) return
|
||||
if (typeof v !== "object") {
|
||||
query.set(`${prefix}[${key}][${k}]`, String(v))
|
||||
return
|
||||
}
|
||||
appendFilters(query, v, `${prefix}[${key}][${k}]`)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function normalizeArtiste(item) {
|
||||
const a = item.attributes || item || {}
|
||||
|
||||
return {
|
||||
id: item.id,
|
||||
...a,
|
||||
}
|
||||
}
|
||||
96
app/composables/useArtistes_asuppr.js
Normal file
96
app/composables/useArtistes_asuppr.js
Normal file
@@ -0,0 +1,96 @@
|
||||
export function useArtistes(options = {}) {
|
||||
const queryString = computed(() => {
|
||||
const locale = unref(options.locale) ?? "fr-FR"
|
||||
const sort = unref(options.sort) ?? null
|
||||
const populate = unref(options.populate) ?? null
|
||||
const filters = unref(options.filters) ?? null
|
||||
|
||||
const query = new URLSearchParams()
|
||||
query.set("locale", locale)
|
||||
if (sort) {
|
||||
query.set("sort[0]", sort)
|
||||
}
|
||||
if (populate && typeof populate === "object") {
|
||||
appendPopulate(query, populate)
|
||||
}
|
||||
if (filters && typeof filters === "object") {
|
||||
appendFilters(query, filters)
|
||||
}
|
||||
|
||||
return query.toString()
|
||||
})
|
||||
|
||||
const { data, pending, error, refresh } = useFetch(
|
||||
() => `/api/__strapi__/artistes?${queryString.value}`,
|
||||
{
|
||||
server: true,
|
||||
key: () => `artistes:${queryString.value}`,
|
||||
watch: [queryString],
|
||||
}
|
||||
)
|
||||
|
||||
const artistes = computed(() => {
|
||||
let list = (data.value?.data || []).map(normalizeArtiste)
|
||||
|
||||
const limit = unref(options.limit)
|
||||
if (typeof limit === "number") {
|
||||
list = list.slice(0, Math.max(0, limit))
|
||||
}
|
||||
|
||||
return list
|
||||
})
|
||||
|
||||
return {
|
||||
artistes,
|
||||
concerts: artistes,
|
||||
pending,
|
||||
error,
|
||||
refresh,
|
||||
}
|
||||
}
|
||||
|
||||
function appendPopulate(query, populate, prefix = "populate") {
|
||||
Object.entries(populate).forEach(([key, value]) => {
|
||||
if (value === true) {
|
||||
query.set(`${prefix}[${key}]`, "true")
|
||||
return
|
||||
}
|
||||
if (value && typeof value === "object") {
|
||||
const entries = Object.entries(value)
|
||||
const allTrue = entries.length > 0 && entries.every(([, v]) => v === true)
|
||||
if (allTrue) {
|
||||
const list = entries.map(([k]) => k).join(",")
|
||||
query.set(`${prefix}[${key}][populate]`, list)
|
||||
return
|
||||
}
|
||||
appendPopulate(query, value, `${prefix}[${key}][populate]`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function appendFilters(query, filters, prefix = "filters") {
|
||||
Object.entries(filters).forEach(([key, value]) => {
|
||||
if (value === null || value === undefined) return
|
||||
if (typeof value !== "object") {
|
||||
query.set(`${prefix}[${key}]`, String(value))
|
||||
return
|
||||
}
|
||||
Object.entries(value).forEach(([k, v]) => {
|
||||
if (v === null || v === undefined) return
|
||||
if (typeof v !== "object") {
|
||||
query.set(`${prefix}[${key}][${k}]`, String(v))
|
||||
return
|
||||
}
|
||||
appendFilters(query, v, `${prefix}[${key}][${k}]`)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function normalizeArtiste(item) {
|
||||
const a = item.attributes || item || {}
|
||||
|
||||
return {
|
||||
id: item.id,
|
||||
...a,
|
||||
}
|
||||
}
|
||||
101
app/composables/useStrapi.js
Normal file
101
app/composables/useStrapi.js
Normal file
@@ -0,0 +1,101 @@
|
||||
export function useStrapi(endpoint, options = {}) {
|
||||
const queryString = computed(() => {
|
||||
const locale = unref(options.locale) ?? "fr-FR"
|
||||
const sort = unref(options.sort) ?? null
|
||||
const populate = unref(options.populate) ?? null
|
||||
const filters = unref(options.filters) ?? null
|
||||
|
||||
const query = new URLSearchParams()
|
||||
query.set("locale", locale)
|
||||
if (sort) {
|
||||
query.set("sort[0]", sort)
|
||||
}
|
||||
if (populate && typeof populate === "object") {
|
||||
appendPopulate(query, populate)
|
||||
}
|
||||
if (filters && typeof filters === "object") {
|
||||
appendFilters(query, filters)
|
||||
}
|
||||
|
||||
return query.toString()
|
||||
})
|
||||
|
||||
const { data, pending, error, refresh } = useFetch(
|
||||
() => `${endpoint}?${queryString.value}`,
|
||||
{
|
||||
server: true,
|
||||
key: () => `${endpoint}:${queryString.value}`,
|
||||
watch: [queryString],
|
||||
}
|
||||
)
|
||||
|
||||
const items = computed(() => {
|
||||
const raw = data.value?.data
|
||||
let list = []
|
||||
if (Array.isArray(raw)) {
|
||||
list = raw.map(normalizeStrapiItem)
|
||||
} else if (raw && typeof raw === "object") {
|
||||
list = [normalizeStrapiItem(raw)]
|
||||
}
|
||||
|
||||
const limit = unref(options.limit)
|
||||
if (typeof limit === "number") {
|
||||
list = list.slice(0, Math.max(0, limit))
|
||||
}
|
||||
|
||||
return list
|
||||
})
|
||||
|
||||
return {
|
||||
items,
|
||||
pending,
|
||||
error,
|
||||
refresh,
|
||||
}
|
||||
}
|
||||
|
||||
function appendPopulate(query, populate, prefix = "populate") {
|
||||
Object.entries(populate).forEach(([key, value]) => {
|
||||
if (value === true) {
|
||||
query.set(`${prefix}[${key}]`, "true")
|
||||
return
|
||||
}
|
||||
if (value && typeof value === "object") {
|
||||
const entries = Object.entries(value)
|
||||
const allTrue = entries.length > 0 && entries.every(([, v]) => v === true)
|
||||
if (allTrue) {
|
||||
const list = entries.map(([k]) => k).join(",")
|
||||
query.set(`${prefix}[${key}][populate]`, list)
|
||||
return
|
||||
}
|
||||
appendPopulate(query, value, `${prefix}[${key}][populate]`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function appendFilters(query, filters, prefix = "filters") {
|
||||
Object.entries(filters).forEach(([key, value]) => {
|
||||
if (value === null || value === undefined) return
|
||||
if (typeof value !== "object") {
|
||||
query.set(`${prefix}[${key}]`, String(value))
|
||||
return
|
||||
}
|
||||
Object.entries(value).forEach(([k, v]) => {
|
||||
if (v === null || v === undefined) return
|
||||
if (typeof v !== "object") {
|
||||
query.set(`${prefix}[${key}][${k}]`, String(v))
|
||||
return
|
||||
}
|
||||
appendFilters(query, v, `${prefix}[${key}][${k}]`)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function normalizeStrapiItem(item) {
|
||||
const a = item.attributes || item || {}
|
||||
|
||||
return {
|
||||
id: item.id,
|
||||
...a,
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
LES CONCERTS À VENIR
|
||||
</SectionTitle>
|
||||
</PageSection>
|
||||
<PageSection padded_size="md" content-size="default" class="">
|
||||
<PageSection padded_size="md" content-size="default" class="remonter_concert_list">
|
||||
<ConcertCardList :highlight-first="false" :limit-cards-on-breakpoint="false">
|
||||
<ConcertCard
|
||||
v-for="c in concerts"
|
||||
@@ -20,7 +20,7 @@
|
||||
:description="c.resume_concert"
|
||||
:imageUrl="c.image_illustration_concert?.url"
|
||||
:imageAlt="c.image_illustration_concert?.alternativeText"
|
||||
:href="`${c.slug_concert}`"
|
||||
:href="`concert-${c.slug_concert}?from=agenda`"
|
||||
/>
|
||||
</ConcertCardList>
|
||||
</PageSection>
|
||||
@@ -32,6 +32,7 @@
|
||||
<script setup>
|
||||
|
||||
import { onMounted } from "vue"
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
import { formatDateLong } from "@/utils/dateFormat.js"
|
||||
|
||||
const { concerts, refresh } = useConcerts({
|
||||
@@ -55,7 +56,7 @@
|
||||
filters: {
|
||||
saison_concert: {
|
||||
nom_saison: {
|
||||
$eq: "2025/2026",
|
||||
$eq: String(runtimeConfig.public.saison),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
:alt="illustration.alternativeText || concert?.titre_concert || ''"
|
||||
ratio="3-4"
|
||||
/>
|
||||
<div v-else class="img_placeholder" aria-hidden="true" />
|
||||
</div>
|
||||
<div class="fiche_header_bandeau"></div>
|
||||
<div class="fiche_header_infos">
|
||||
@@ -167,14 +168,12 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="description_wp">
|
||||
<section v-if="concert.description_concert" class="description_wp">
|
||||
<StrapiBlocksConvert :blocks="concert?.description_concert" />
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
<section class="img-gallery_wp">
|
||||
<div v-if="imagesConcert.length" class="img-gallery">
|
||||
<section v-if="imagesConcert.length" class="img-gallery_wp">
|
||||
<div class="img-gallery">
|
||||
<DsMedia
|
||||
v-for="img in imagesConcert"
|
||||
:key="img.id || img.url"
|
||||
@@ -184,8 +183,8 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="youtube_wp">
|
||||
<div v-if="youtubeEmbeds.length" class="youtube-list">
|
||||
<section v-if="youtubeEmbeds.length" class="youtube_wp">
|
||||
<div class="youtube-list">
|
||||
<div v-for="v in youtubeEmbeds" :key="v.id" class="youtube-item">
|
||||
<iframe
|
||||
:src="v.src"
|
||||
@@ -208,9 +207,8 @@
|
||||
import DsMedia from '@root/design-system/primitives/DsMedia.vue'
|
||||
import DsHeading from '@root/design-system/primitives/DsHeading.vue'
|
||||
import DsText from '@root/design-system/primitives/DsText.vue'
|
||||
import DsButton from '@root/design-system/primitives/DsButton.vue'
|
||||
const route = useRoute()
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// RÉCUPÉRATION DU CONTENU
|
||||
@@ -656,7 +654,10 @@
|
||||
margin-bottom: 70px;
|
||||
padding-top: 50px;
|
||||
padding-right: 30px;
|
||||
padding-left: 40px;
|
||||
padding-left: 50px;
|
||||
@media (max-width: 599px) {
|
||||
padding-left: 40px;
|
||||
}
|
||||
padding-bottom: 50px;
|
||||
|
||||
/* DÉCALAGE DU BLOC VERS LA DROITE */
|
||||
@@ -715,7 +716,7 @@
|
||||
column-gap: 30px;
|
||||
row-gap: 30px;
|
||||
padding-bottom: 70px;
|
||||
@media (min-width: 0px) and (max-width: 500px) {
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
padding-left: 20px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
@@ -1,13 +1,94 @@
|
||||
<template>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<PageSection tone="jaune" content-size="default">
|
||||
<SectionTitle tone="invert" pad="md">
|
||||
LA SAISON 2025/2026 POUR LES JEUNES
|
||||
</SectionTitle>
|
||||
</PageSection>
|
||||
<PageSection padded_size="md" content-size="default" class="remonter_concert_list">
|
||||
<ConcertCardList :highlight-first="false" :limit-cards-on-breakpoint="false">
|
||||
<ConcertCard
|
||||
v-for="c in concerts"
|
||||
:key="c.id"
|
||||
:id="c.slug_concert"
|
||||
:title="c.titre_concert"
|
||||
:dateISO="c.representation_concert?.[0]?.date_debut_representation"
|
||||
:dateLabel="formatDateLong(c.representation_concert?.[0]?.date_debut_representation)"
|
||||
:lieu="c.representation_concert?.[0]?.lieu_representation?.nom_lieu"
|
||||
:adresse_lieu="c.representation_concert?.[0]?.lieu_representation?.nom_lieu"
|
||||
:description="c.resume_concert"
|
||||
:imageUrl="c.image_illustration_concert?.url"
|
||||
:imageAlt="c.image_illustration_concert?.alternativeText"
|
||||
:href="`concert-${c.slug_concert}?from=jeune-public`"
|
||||
/>
|
||||
</ConcertCardList>
|
||||
</PageSection>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
|
||||
<script setup>
|
||||
|
||||
import { onMounted } from "vue"
|
||||
import { formatDateLong } from "@/utils/dateFormat.js"
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
|
||||
const { concerts, refresh } = useConcerts({
|
||||
locale: "fr-FR",
|
||||
populate: {
|
||||
saison_concert: true,
|
||||
genre_concert: true,
|
||||
type_audience_concert: true,
|
||||
direction_ondif_concert: { postes_artiste_ondif: true },
|
||||
direction_invite_concert: { postes_artiste_invite: true },
|
||||
artistes_ondif_concert: { postes_artiste_ondif: true },
|
||||
artistes_invite_concert: { postes_artiste_invite: true },
|
||||
image_illustration_concert: true,
|
||||
images_concert: true,
|
||||
videos_concert: true,
|
||||
audios_concert: true,
|
||||
programme_concert: true,
|
||||
representation_concert: { lieu_representation: true },
|
||||
liens_youtube_concert: true,
|
||||
},
|
||||
filters: {
|
||||
$and: [
|
||||
{
|
||||
saison_concert: {
|
||||
nom_saison: {
|
||||
$eq: String(runtimeConfig.public.saison),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
$or: [
|
||||
{
|
||||
genre_concert: {
|
||||
nom_genre: {
|
||||
$eq: "Jeune public",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type_audience_concert: {
|
||||
nom_audience: {
|
||||
$eq: "Jeune public",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
upcomingOnly: false,
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
if (!concerts.value?.length) {
|
||||
refresh()
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -6,7 +6,7 @@
|
||||
SAISON 2025/2026
|
||||
</SectionTitle>
|
||||
</PageSection>
|
||||
<PageSection padded_size="md" content-size="default" class="">
|
||||
<PageSection padded_size="md" content-size="default" class="remonter_concert_list">
|
||||
<ConcertCardList :highlight-first="false" :limit-cards-on-breakpoint="false">
|
||||
<ConcertCard
|
||||
v-for="c in concerts"
|
||||
@@ -20,7 +20,7 @@
|
||||
:description="c.resume_concert"
|
||||
:imageUrl="c.image_illustration_concert?.url"
|
||||
:imageAlt="c.image_illustration_concert?.alternativeText"
|
||||
:href="`${c.slug_concert}`"
|
||||
:href="`concert-${c.slug_concert}?from=saison`"
|
||||
/>
|
||||
</ConcertCardList>
|
||||
</PageSection>
|
||||
@@ -32,6 +32,7 @@
|
||||
<script setup>
|
||||
|
||||
import { onMounted } from "vue"
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
import { formatDateLong } from "@/utils/dateFormat.js"
|
||||
|
||||
const { concerts, refresh } = useConcerts({
|
||||
@@ -55,8 +56,8 @@
|
||||
filters: {
|
||||
saison_concert: {
|
||||
nom_saison: {
|
||||
$eq: "2025/2026",
|
||||
},
|
||||
$eq: String(runtimeConfig.public.saison),
|
||||
},
|
||||
},
|
||||
},
|
||||
upcomingOnly: false,
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
<div>
|
||||
|
||||
<!-- ================== -->
|
||||
<!-- Fond noir -->
|
||||
<!-- PROCHAIN CONCERTS -->
|
||||
<!-- ================== -->
|
||||
|
||||
<!-- Fond noir -->
|
||||
<PageSection tone="dark" content-size="default">
|
||||
<SectionTitle tone="invert" pad="md">
|
||||
CONCERTS À VENIR …
|
||||
</SectionTitle>
|
||||
</PageSection>
|
||||
|
||||
<!-- ================== -->
|
||||
<!-- Listes des prochains conncerts -->
|
||||
<!-- ================== -->
|
||||
<PageSection padded_size="md" content-size="default" class="remonter_concert_list">
|
||||
<ConcertCardList>
|
||||
<ConcertCard
|
||||
@@ -26,18 +26,43 @@
|
||||
:description="c.resume_concert"
|
||||
:imageUrl="c.image_illustration_concert?.url"
|
||||
:imageAlt="c.image_illustration_concert?.alternativeText"
|
||||
:href="`/concerts/${c.slug_concert}`"
|
||||
:href="`/concerts/concert-${c.slug_concert}?from=agenda`"
|
||||
/>
|
||||
</ConcertCardList>
|
||||
</PageSection>
|
||||
|
||||
|
||||
<PageSection tone="dark" padded_size="md" content-size="default" padb="xs" class="theme_tao photo_orchestre_wp remonter_bloc_dessous">
|
||||
<SectionContent>
|
||||
<SectionTitle tone="invert" pad="xs">
|
||||
L’ORCHESTRE NATIONAL D'ÎLE-DE-FRANCE
|
||||
</SectionTitle>
|
||||
|
||||
<DsMedia :src="orchestre_img" alt="L'Orchestre" class="photo_orchestre_img"/>
|
||||
|
||||
</SectionContent>
|
||||
|
||||
<SectionContent pad="xs" class="photo_orchestre_cta">
|
||||
<DsButtonArrow to="/" variant="invert">
|
||||
Découvrir les musiciens
|
||||
</DsButtonArrow>
|
||||
</SectionContent>
|
||||
|
||||
</PageSection>
|
||||
|
||||
<!-- ================== -->
|
||||
<!-- Carte Île-De-France Partout et pour tous -->
|
||||
<!-- PARTOUT ET POUR TOUS -->
|
||||
<!-- ================== -->
|
||||
<PageSection padded_size="md" class="theme_ppt_wp">
|
||||
<SectionContent class="theme_ppt">
|
||||
<!-- PHOTO DE L'ORCHETSRE -->
|
||||
<!-- <DsMedia :src="orchestre_img" alt="L'Orchestre" class="theme_ppt--img"/> -->
|
||||
<!-- PHOTO DE LA CARTE IDF -->
|
||||
<DsMedia :src="ppt_img" alt="Carte Île-De-France" class="theme_ppt--img"/>
|
||||
<!-- Avec couleur rouge par dessus -->
|
||||
<SectionContent tone="brand_rouge45" pad="" class="theme_ppt--content">
|
||||
<!-- Sans couleur rouge par dessus -->
|
||||
<!-- <SectionContent tone="" pad="" class="theme_ppt--content"> -->
|
||||
<SectionTitle tone="invert" pad="xs">
|
||||
PARTOUT ET POUR TOUS
|
||||
</SectionTitle>
|
||||
@@ -45,6 +70,7 @@
|
||||
<DsText tone="invert" size="lg" class="theme_ppt--txt" >
|
||||
Les 95 musiciennes et musiciens proposent chaque saison plus de 120 concerts dans des salles et théâtres, des lieux culturels et des espaces atypiques de la région francilienne. Porté par une forte mission territoriale, l’orchestre s’engage à rendre la musique symphonique accessible à toutes et tous, en la faisant vivre au plus près des habitants grâce notamment à des actions culturelles, pédagogiques et participatives au cœur du territoire.
|
||||
</DsText>
|
||||
<!-- UN CTA / LIEN SUR L'IMAGE -->
|
||||
<DsButtonArrow to="/" variant="invert">
|
||||
Carte des événements
|
||||
</DsButtonArrow>
|
||||
@@ -52,6 +78,15 @@
|
||||
</SectionContent>
|
||||
</SectionContent>
|
||||
</PageSection>
|
||||
|
||||
<!-- CARTES PARTOUT ET POUR TOUS -->
|
||||
<PageSection padded_size="md" class="theme_ppt_wp">
|
||||
<SectionContent class="theme_ppt">
|
||||
<SquareCardBlocTextList >
|
||||
|
||||
</SquareCardBlocTextList>
|
||||
</SectionContent>
|
||||
</PageSection>
|
||||
|
||||
<!-- ================== -->
|
||||
<!-- Tous à l'Orchestre -->
|
||||
@@ -78,11 +113,11 @@
|
||||
<PageSection padded_size="md">
|
||||
<SectionContent>
|
||||
<SectionTitle tone="" pad="xs">
|
||||
LES DERNIÈRES ACTUALITÉS
|
||||
ACTUALITÉS
|
||||
</SectionTitle>
|
||||
</SectionContent>
|
||||
<SquareCardList >
|
||||
<SquareCard
|
||||
<SquareCardBlocTextList >
|
||||
<SquareCardBlocText
|
||||
v-for="actuscard in actuscards"
|
||||
:key="actuscard.id"
|
||||
:id="actuscard.id"
|
||||
@@ -91,8 +126,8 @@
|
||||
:title="actuscard.title"
|
||||
:description="actuscard.description"
|
||||
:url="actuscard.url"
|
||||
></SquareCard>
|
||||
</SquareCardList>
|
||||
></SquareCardBlocText>
|
||||
</SquareCardBlocTextList>
|
||||
</PageSection>
|
||||
|
||||
<!-- ================== -->
|
||||
@@ -145,6 +180,8 @@
|
||||
|
||||
<script setup>
|
||||
import { onMounted, computed } from 'vue'
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
const config = useAppConfig()
|
||||
import { clientLog } from '~/utils/clientLog'
|
||||
import { formatDateLong } from "@/utils/dateFormat.js"
|
||||
import SectionContent from '../components/section/SectionContent.vue'
|
||||
@@ -153,23 +190,24 @@
|
||||
import DsMedia from '@root/design-system/primitives/DsMedia.vue'
|
||||
import DsButton from '@root/design-system/primitives/DsButton.vue'
|
||||
import DsButtonArrow from '@root/design-system/primitives/DsButtonArrow.vue'
|
||||
import orchestre_img from '@/assets/img/illustrations/orchestre_1.jpg'
|
||||
import ppt_img from '@/assets/img/illustrations/map_idf.jpg'
|
||||
import DsCard from '@root/design-system/components/DsCard.vue'
|
||||
|
||||
// Layout utilisé
|
||||
definePageMeta({ layout: 'default' })
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
|
||||
const STRAPI_URL = runtimeConfig.public.strapiUrl
|
||||
|
||||
// Config app (pour SEO)
|
||||
const config = useAppConfig()
|
||||
|
||||
useSeoMeta({
|
||||
title: config.title
|
||||
})
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
console.log("Bienvenue : ",appConfig.title)
|
||||
|
||||
console.log("Bienvenue : ",config.title)
|
||||
|
||||
|
||||
//--------------------
|
||||
// DONNÉES POUR LES CONCERTS À VENIR …
|
||||
@@ -184,7 +222,7 @@
|
||||
filters: {
|
||||
saison_concert: {
|
||||
nom_saison: {
|
||||
$eq: "2025/2026",
|
||||
$eq: String(runtimeConfig.public.saison),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -264,182 +302,209 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.remonter_concert_list {
|
||||
transform: translateY(-170px);
|
||||
}
|
||||
|
||||
.theme_ppt_wp {
|
||||
margin-bottom: 50px;
|
||||
// parce que le bloc du dessus à un transform: translateY(-170px); alors cela laisse un espace vide que l'on comble avec ce margin-top négatif
|
||||
margin-top: -170px;
|
||||
}
|
||||
.theme_ppt {
|
||||
display: grid;
|
||||
|
||||
&--img {
|
||||
grid-row: 1;
|
||||
grid-column: 1;
|
||||
.remonter_concert_list {
|
||||
transform: translateY(-170px);
|
||||
}
|
||||
.remonter_bloc_dessous {
|
||||
// parce que le bloc du dessus à un transform: translateY(-170px); alors cela laisse un espace vide que l'on comble avec ce margin-top négatif
|
||||
margin-top: -170px;
|
||||
}
|
||||
&--content {
|
||||
grid-row: 1;
|
||||
grid-column: 1;
|
||||
display: grid;
|
||||
align-items: center;
|
||||
|
||||
}
|
||||
&--description {
|
||||
max-width: 800px;
|
||||
align-self: self-start;
|
||||
// margin-top: 35px;
|
||||
}
|
||||
&--txt {
|
||||
margin-bottom: 35px;
|
||||
}
|
||||
}
|
||||
|
||||
.theme_tao {
|
||||
margin-bottom: 50px;
|
||||
|
||||
&--description {
|
||||
max-width: 800px;
|
||||
|
||||
}
|
||||
&--txt {
|
||||
margin-bottom: 35px;
|
||||
}
|
||||
&--filters {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
column-gap: 10px;
|
||||
row-gap: 14px;
|
||||
|
||||
}
|
||||
&--cardlist {
|
||||
margin-top: 20px;
|
||||
.photo_orchestre_wp {
|
||||
|
||||
&--card {
|
||||
background-color: var(--c-surface);
|
||||
border-radius: 10px;
|
||||
//padding: 50px;
|
||||
padding: clamp(18px, 2.4vw, 32px);
|
||||
.photo_orchestre_img {
|
||||
.page-section--inner--default {
|
||||
max-width: calc(+500px)
|
||||
}
|
||||
img {
|
||||
border-radius: 50px;
|
||||
max-height: 660px;
|
||||
}
|
||||
}
|
||||
.photo_orchestre_cta {
|
||||
padding-top: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//========================
|
||||
// PARTOUT ET POUR TOUS
|
||||
//========================
|
||||
|
||||
.theme_ppt_wp {
|
||||
margin-bottom: 50px;
|
||||
|
||||
}
|
||||
.theme_ppt {
|
||||
display: grid;
|
||||
|
||||
&--img {
|
||||
grid-row: 1;
|
||||
grid-column: 1;
|
||||
max-height: 400px;
|
||||
}
|
||||
&--content {
|
||||
grid-row: 1;
|
||||
grid-column: 1;
|
||||
display: grid;
|
||||
align-items: center;
|
||||
|
||||
}
|
||||
&--description {
|
||||
max-width: 800px;
|
||||
align-self: self-start;
|
||||
// margin-top: 35px;
|
||||
}
|
||||
&--txt {
|
||||
margin-bottom: 35px;
|
||||
}
|
||||
}
|
||||
|
||||
//========================
|
||||
// TOUS A L'ORCHESTRE
|
||||
//========================
|
||||
.theme_tao {
|
||||
margin-bottom: 50px;
|
||||
|
||||
&--description {
|
||||
max-width: 800px;
|
||||
|
||||
}
|
||||
&--txt {
|
||||
margin-bottom: 35px;
|
||||
}
|
||||
&--filters {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
column-gap: 10px;
|
||||
row-gap: 14px;
|
||||
|
||||
}
|
||||
&--cardlist {
|
||||
margin-top: 20px;
|
||||
|
||||
&--wp {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
&--img {
|
||||
max-width: 280px;
|
||||
overflow: hidden;
|
||||
img {
|
||||
max-height: 280px;
|
||||
&--card {
|
||||
background-color: var(--c-surface);
|
||||
border-radius: 10px;
|
||||
//padding: 50px;
|
||||
padding: clamp(18px, 2.4vw, 32px);
|
||||
|
||||
&--wp {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
@media (min-width: 400px) {
|
||||
&--img {
|
||||
max-width: 280px;
|
||||
overflow: hidden;
|
||||
img {
|
||||
max-height: 350px;
|
||||
max-height: 280px;
|
||||
}
|
||||
@media (min-width: 400px) {
|
||||
img {
|
||||
max-height: 350px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
&--content {
|
||||
max-width: 320px;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
}
|
||||
&--content {
|
||||
max-width: 320px;
|
||||
padding-top: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&--card {
|
||||
/* base: mobile-first */
|
||||
width: clamp(260px, 81vw, 360px);
|
||||
}
|
||||
@media (min-width: 400px) {
|
||||
&--card {
|
||||
width: clamp(260px, 80vw, 360px);
|
||||
/* base: mobile-first */
|
||||
width: clamp(260px, 81vw, 360px);
|
||||
}
|
||||
}
|
||||
@media (min-width: 500px) {
|
||||
&--card {
|
||||
width: clamp(280px, 63vw, 460px);
|
||||
@media (min-width: 400px) {
|
||||
&--card {
|
||||
width: clamp(260px, 80vw, 360px);
|
||||
}
|
||||
}
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
&--card {
|
||||
width: clamp(280px, 60vw, 460px);
|
||||
@media (min-width: 500px) {
|
||||
&--card {
|
||||
width: clamp(280px, 63vw, 460px);
|
||||
}
|
||||
}
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
&--card {
|
||||
width: clamp(320px, 33vw, 520px);
|
||||
@media (min-width: 700px) {
|
||||
&--card {
|
||||
width: clamp(280px, 60vw, 460px);
|
||||
}
|
||||
}
|
||||
}
|
||||
@media (min-width: 1440px) {
|
||||
&--card {
|
||||
width: clamp(360px, 28vw, 560px);
|
||||
@media (min-width: 1024px) {
|
||||
&--card {
|
||||
width: clamp(320px, 33vw, 520px);
|
||||
}
|
||||
}
|
||||
@media (min-width: 1440px) {
|
||||
&--card {
|
||||
width: clamp(360px, 28vw, 560px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.theme_mag {
|
||||
|
||||
|
||||
@media (max-width: 499px) {
|
||||
min-height: 650px;
|
||||
}
|
||||
@media (min-width: 500px) {
|
||||
min-height: 650px;
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
min-height: 650px;
|
||||
}
|
||||
@media (min-width: 900px) {
|
||||
min-height: 650px;
|
||||
}
|
||||
@media (min-width: 1100px) {
|
||||
min-height: 650px;
|
||||
}
|
||||
@media (min-width: 1300px) {
|
||||
min-height: 650px;
|
||||
}
|
||||
@media (min-width: 1500px) {
|
||||
min-height: 650px;
|
||||
}
|
||||
|
||||
.decoration--mag {
|
||||
position: absolute;
|
||||
top: -20px;
|
||||
//========================
|
||||
// MAGAZINE
|
||||
//========================
|
||||
.theme_mag {
|
||||
|
||||
|
||||
@media (max-width: 499px) {
|
||||
right: -150px;
|
||||
min-height: 650px;
|
||||
}
|
||||
@media (min-width: 500px) {
|
||||
right: -120px;
|
||||
min-height: 650px;
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
right: -100px;
|
||||
min-height: 650px;
|
||||
}
|
||||
@media (min-width: 900px) {
|
||||
right: -100px;
|
||||
min-height: 650px;
|
||||
}
|
||||
@media (min-width: 1100px) {
|
||||
right: -140px;
|
||||
min-height: 650px;
|
||||
}
|
||||
@media (min-width: 1300px) {
|
||||
right: -100px;
|
||||
min-height: 650px;
|
||||
}
|
||||
@media (min-width: 1500px) {
|
||||
right: -50px;
|
||||
min-height: 650px;
|
||||
}
|
||||
img {
|
||||
height: 600px;
|
||||
|
||||
.decoration--mag {
|
||||
position: absolute;
|
||||
top: -20px;
|
||||
|
||||
@media (max-width: 499px) {
|
||||
right: -150px;
|
||||
}
|
||||
@media (min-width: 500px) {
|
||||
right: -120px;
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
right: -100px;
|
||||
}
|
||||
@media (min-width: 900px) {
|
||||
right: -100px;
|
||||
}
|
||||
@media (min-width: 1100px) {
|
||||
right: -140px;
|
||||
}
|
||||
@media (min-width: 1300px) {
|
||||
right: -100px;
|
||||
}
|
||||
@media (min-width: 1500px) {
|
||||
right: -50px;
|
||||
}
|
||||
img {
|
||||
height: 600px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
760
app/pages/orchestre/artiste-[id].vue
Normal file
760
app/pages/orchestre/artiste-[id].vue
Normal file
@@ -0,0 +1,760 @@
|
||||
<template>
|
||||
<div>
|
||||
<section v-if="pending" aria-busy="true" aria-live="polite">
|
||||
<p>en cours de chargement...</p>
|
||||
</section>
|
||||
<section v-else-if="error" aria-live="polite">
|
||||
<p>Impossible de charger la fiche artiste.</p>
|
||||
</section>
|
||||
|
||||
<template v-else>
|
||||
<PageSection tone="" content-size="default" class="breadcrum_wp">
|
||||
<Breadcrumb :current-label="artiste?.nom_artiste_ondif || ''" />
|
||||
</PageSection>
|
||||
|
||||
|
||||
<section class="fiche_header_wp">
|
||||
<div class="fiche_header_wp_gauche"></div>
|
||||
<div class="fiche_header_wp_gauche_carre"></div>
|
||||
<div class="fiche_header_inner">
|
||||
<div class="fiche_header_titres">
|
||||
<div>
|
||||
<DsHeading as="h1" tone="default" textcase="uppercase" class="concert-card__title">
|
||||
{{ artiste.nom_artiste_ondif }}
|
||||
</DsHeading>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fiche_header_img">
|
||||
<DsMedia
|
||||
v-if="illustration?.url"
|
||||
:src="illustration.url"
|
||||
:alt="illustration.alternativeText || artiste?.nom_artiste_ondif || ''"
|
||||
ratio="3-4"
|
||||
/>
|
||||
<div v-else class="img_placeholder" aria-hidden="true" />
|
||||
</div>
|
||||
<div class="fiche_header_bandeau"></div>
|
||||
<div class="fiche_header_infos">
|
||||
<div>
|
||||
<DsHeading as="h2" tone="invert" textcase="uppercase" class="fiche_header_infos_genre" v-if="postesLabel">
|
||||
{{ postesLabel }}
|
||||
</DsHeading>
|
||||
</div>
|
||||
<div v-if="artiste.url_artiste_ondif">
|
||||
<DsText as="p" tone="invert" weight="bold" spacing="space-0" class="">
|
||||
<a :href="artiste.url_artiste_ondif" target="_blank" rel="noopener noreferrer">Site internet</a>
|
||||
</DsText>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fiche_header_wp_droite"></div>
|
||||
</section>
|
||||
|
||||
|
||||
<PageSection tone="" content-size="default" class="fiche_description">
|
||||
|
||||
<section v-if="descriptionBlocks" class="description_wp">
|
||||
<StrapiBlocksConvert :blocks="descriptionBlocks" />
|
||||
</section>
|
||||
|
||||
<section v-if="imagesArtiste.length" class="img-gallery_wp">
|
||||
<div class="img-gallery">
|
||||
<DsMedia
|
||||
v-for="img in imagesArtiste"
|
||||
:key="img.id || img.url"
|
||||
:src="img.url"
|
||||
:alt="img.alternativeText || artiste?.nom_artiste_ondif || ''"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section v-if="youtubeEmbeds.length" class="youtube_wp">
|
||||
<div class="youtube-list">
|
||||
<div v-for="v in youtubeEmbeds" :key="v.id" class="youtube-item">
|
||||
<iframe
|
||||
:src="v.src"
|
||||
title="Vidéo YouTube"
|
||||
loading="lazy"
|
||||
referrerpolicy="strict-origin-when-cross-origin"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
||||
allowfullscreen
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</PageSection>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import DsMedia from '@root/design-system/primitives/DsMedia.vue'
|
||||
import DsHeading from '@root/design-system/primitives/DsHeading.vue'
|
||||
import DsText from '@root/design-system/primitives/DsText.vue'
|
||||
const route = useRoute()
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// RÉCUPÉRATION DU CONTENU STRAPI
|
||||
//////////////////////////////////////////////////////////////
|
||||
const artisteSlug = computed(() => String(route.params.id || ''))
|
||||
const populate = {
|
||||
image_illustration_artiste_ondif: true,
|
||||
postes_artiste_ondif: true,
|
||||
}
|
||||
const filters = computed(() => ({
|
||||
slug_artiste_ondif: {
|
||||
$eq: artisteSlug.value,
|
||||
},
|
||||
}))
|
||||
|
||||
const { items: artistes, pending, error } = useStrapi(
|
||||
"/api/__strapi__/artistes",
|
||||
{
|
||||
locale: "fr-FR",
|
||||
populate,
|
||||
filters,
|
||||
limit: 1,
|
||||
}
|
||||
)
|
||||
|
||||
const artiste = computed(() => artistes.value?.[0] || {})
|
||||
|
||||
|
||||
|
||||
|
||||
useSeoMeta({
|
||||
title: () => artiste.value?.nom_artiste_ondif || 'Artiste',
|
||||
})
|
||||
|
||||
const postesLabel = computed(() =>
|
||||
extractStrapiList(artiste.value?.postes_artiste_ondif)
|
||||
.map((p) => p?.nom_poste)
|
||||
.filter(Boolean)
|
||||
.join(', ')
|
||||
)
|
||||
|
||||
const illustration = computed(() => {
|
||||
const m = artiste.value?.image_illustration_artiste_ondif
|
||||
if (!m) return null
|
||||
if (m?.data?.attributes) return { id: m.data.id, ...m.data.attributes }
|
||||
if (m.url) return m
|
||||
return null
|
||||
})
|
||||
|
||||
const imagesArtiste = computed(() => {
|
||||
const value = artiste.value?.images_artiste_ondif
|
||||
return extractStrapiList(value).filter((img) => Boolean(img?.url))
|
||||
})
|
||||
|
||||
const descriptionBlocks = computed(() =>
|
||||
artiste.value?.description_artiste_ondif || artiste.value?.description_concert || null
|
||||
)
|
||||
|
||||
const youtube = computed(() => {
|
||||
const value = artiste.value?.liens_youtube_artiste_ondif
|
||||
if (!value) return []
|
||||
return extractStrapiList(value)
|
||||
})
|
||||
function getYoutubeId(url = '') {
|
||||
try {
|
||||
const u = new URL(url)
|
||||
if (u.hostname.includes('youtu.be')) return u.pathname.slice(1)
|
||||
if (u.pathname.startsWith('/shorts/')) return u.pathname.split('/')[2]
|
||||
if (u.pathname.startsWith('/embed/')) return u.pathname.split('/')[2]
|
||||
return u.searchParams.get('v')
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
const youtubeEmbeds = computed(() =>
|
||||
youtube.value
|
||||
.map((item) => {
|
||||
const id = getYoutubeId(item?.lien_youtube)
|
||||
if (!id) return null
|
||||
return {
|
||||
id: item.id || id,
|
||||
src: `https://www.youtube-nocookie.com/embed/${id}?rel=0&modestbranding=1&iv_load_policy=3&playsinline=1`,
|
||||
}
|
||||
})
|
||||
.filter(Boolean)
|
||||
)
|
||||
|
||||
function extractStrapiList(value) {
|
||||
if (!value) return []
|
||||
if (Array.isArray(value)) return value.map(normalizeStrapiItem).filter(Boolean)
|
||||
if (value?.data) {
|
||||
const rows = Array.isArray(value.data) ? value.data : [value.data]
|
||||
return rows.map(normalizeStrapiItem).filter(Boolean)
|
||||
}
|
||||
if (typeof value === 'object') return [normalizeStrapiItem(value)].filter(Boolean)
|
||||
return []
|
||||
}
|
||||
|
||||
function normalizeStrapiItem(item) {
|
||||
if (!item || typeof item !== 'object') return null
|
||||
if (item.attributes && typeof item.attributes === 'object') {
|
||||
return { id: item.id, ...item.attributes }
|
||||
}
|
||||
return item
|
||||
}
|
||||
|
||||
function appendPopulate(query, populateObj, prefix = "populate") {
|
||||
Object.entries(populateObj).forEach(([key, value]) => {
|
||||
if (value === true) {
|
||||
query.set(`${prefix}[${key}]`, "true")
|
||||
return
|
||||
}
|
||||
if (value && typeof value === "object") {
|
||||
appendPopulate(query, value, `${prefix}[${key}][populate]`)
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
.breadcrum_wp {
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
.fiche_header_wp {
|
||||
display: grid;
|
||||
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: auto 510px 20px 200px;
|
||||
padding-top: 40px;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-template-columns: minmax(10px, 10px) 580px 0px;
|
||||
grid-template-rows: 40px 280px 20px 230px;
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
grid-template-columns: minmax(10px, 10px) 660px 0px;
|
||||
grid-template-rows: 70px 250px 90px 300px;
|
||||
}
|
||||
@media (min-width: 800px) {
|
||||
grid-template-columns: minmax(10px, 10px) 780px minmax(10px, 10px);
|
||||
grid-template-rows: 60px 280px 70px 300px;
|
||||
}
|
||||
@media (min-width: 900px) {
|
||||
grid-template-columns: minmax(10px, 10px) 860px minmax(10px, 10px);
|
||||
grid-template-rows: 90px 340px 100px 250px;
|
||||
}
|
||||
@media (min-width: 1000px) {
|
||||
grid-template-columns: minmax(20px, auto) 950px minmax(10px, auto);
|
||||
grid-template-rows: 90px 340px 120px 270px;
|
||||
}
|
||||
@media (min-width: 1100px) {
|
||||
grid-template-columns: minmax(20px, auto) 1020px minmax(20px, auto);
|
||||
grid-template-rows: 90px 340px 140px 290px;
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
grid-template-columns: minmax(20px, auto) 1100px minmax(20px, auto);
|
||||
grid-template-rows: 90px 340px 160px 330px;
|
||||
}
|
||||
@media (min-width: 1300px) {
|
||||
grid-template-columns: minmax(20px, auto) 1200px minmax(20px, auto);
|
||||
grid-template-rows: 90px 340px 160px 330px;
|
||||
}
|
||||
@media (min-width: 1400px) {
|
||||
grid-template-columns: minmax(20px, auto) 1300px minmax(20px, auto);
|
||||
grid-template-rows: 90px 340px 160px 380px;
|
||||
}
|
||||
@media (min-width: 1500px) {
|
||||
grid-template-columns: minmax(20px, auto) 1400px minmax(20px, auto);
|
||||
grid-template-rows: 90px 340px 160px 380px;
|
||||
}
|
||||
}
|
||||
.fiche_header_wp_gauche {
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
display: none;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-column: 1;
|
||||
}
|
||||
}
|
||||
.fiche_header_wp_gauche_carre {
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
display: none;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-column: 1;
|
||||
grid-row: 4;
|
||||
}
|
||||
background-color: var(--c-backgroud-black);
|
||||
}
|
||||
.fiche_header_wp_droite {
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
display: none;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-column: 3;
|
||||
}
|
||||
}
|
||||
|
||||
.fiche_header_inner {
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
grid-column: 1;
|
||||
grid-row: 1/5;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-column: 2;
|
||||
grid-row: 1/5;
|
||||
}
|
||||
display: grid;
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
grid-template-columns: 4fr 1fr 0.5fr;
|
||||
grid-template-rows: auto 510px 20px 200px;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
width: 575px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 40px 280px 20px 230px;
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
width: 675px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 70px 250px 90px 300px;
|
||||
}
|
||||
@media (min-width: 800px) {
|
||||
width: 780px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 60px 280px 70px 300px;
|
||||
}
|
||||
@media (min-width: 900px) {
|
||||
width: 860px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 90px 340px 100px 250px;
|
||||
}
|
||||
@media (min-width: 1000px) {
|
||||
width: 950px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 90px 340px 120px 270px;
|
||||
}
|
||||
@media (min-width: 1100px) {
|
||||
width: 1020px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 90px 340px 140px 290px;
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
width: 1100px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 90px 340px 160px 330px;
|
||||
}
|
||||
@media (min-width: 1300px) {
|
||||
width: 1200px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 90px 340px 160px 330px;
|
||||
}
|
||||
@media (min-width: 1400px) {
|
||||
width: 1300px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 90px 340px 160px 380px;
|
||||
}
|
||||
@media (min-width: 1500px) {
|
||||
width: 1400px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 90px 340px 160px 380px;
|
||||
}
|
||||
@media (min-width: 1600px) {
|
||||
width: 1400px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 90px 340px 160px 380px;
|
||||
}
|
||||
@media (min-width: 1700px) {
|
||||
width: 1400px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 90px 340px 160px 380px;
|
||||
}
|
||||
@media (min-width: 1800px) {
|
||||
width: 1400px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 90px 340px 160px 380px;
|
||||
}
|
||||
}
|
||||
|
||||
.fiche_header_titres {
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
grid-column: 1;
|
||||
grid-row: 1;
|
||||
padding-bottom: 20px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-column: 1;
|
||||
grid-row: 2;
|
||||
}
|
||||
display: grid;
|
||||
align-content: start;
|
||||
gap: 0.75rem;
|
||||
h1 {
|
||||
font-size: 55px;
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
font-size: 25px;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
font-size: 25px;
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
font-size: 30px;
|
||||
}
|
||||
@media (min-width: 800px) {
|
||||
font-size: 30px;
|
||||
}
|
||||
@media (min-width: 900px) {
|
||||
font-size: 40px;
|
||||
}
|
||||
@media (min-width: 1000px) {
|
||||
font-size: 40px;
|
||||
}
|
||||
@media (min-width: 1100px) {
|
||||
font-size: 40px;
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
font-size: 50px;
|
||||
}
|
||||
@media (min-width: 1300px) {
|
||||
font-size: 55px;
|
||||
}
|
||||
@media (min-width: 1400px) {
|
||||
font-size: 55px;
|
||||
}
|
||||
@media (min-width: 1500px) {
|
||||
font-size: 55px;
|
||||
}
|
||||
@media (min-width: 1600px) {
|
||||
font-size: 55px;
|
||||
}
|
||||
@media (min-width: 1700px) {
|
||||
font-size: 55px;
|
||||
}
|
||||
@media (min-width: 1800px) {
|
||||
font-size: 55px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fiche_header_img {
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
grid-column: 1 / 4;
|
||||
grid-row: 2 / 4;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-column: 3 / 5;
|
||||
grid-row: 1 / 5;
|
||||
}
|
||||
overflow: hidden;
|
||||
.ds-media {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.fiche_header_infos {
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
grid-column: 1 / 2;
|
||||
grid-row: 4;
|
||||
margin-top: -30px;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-column: 1;
|
||||
grid-row: 4;
|
||||
}
|
||||
display: grid;
|
||||
align-content: center;
|
||||
justify-content: end;
|
||||
|
||||
@media (min-width: 0px) and (max-width: 700px) {
|
||||
gap: 7px;
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
text-align: right;
|
||||
.fiche_header_infos_genre {
|
||||
font-weight: 900;
|
||||
|
||||
}
|
||||
}
|
||||
.fiche_header_bandeau {
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
grid-column: 1 / 3;
|
||||
grid-row: 4;
|
||||
margin-top: -30px;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-column: 1 / 4;
|
||||
grid-row: 4;
|
||||
}
|
||||
background-color: var(--c-backgroud-black);
|
||||
}
|
||||
|
||||
/* ============================ */
|
||||
/* DISTRIBUTION / PROGRAMME */
|
||||
/* ============================ */
|
||||
.fiche_details_wp {
|
||||
.distribution_wp {
|
||||
padding-top: 50px;
|
||||
padding-bottom: 50px;
|
||||
padding-left: 20px;
|
||||
.distribution_item {
|
||||
display: flex;
|
||||
.distribution_item_poste {
|
||||
padding-right: 10px;
|
||||
font-weight: 200;
|
||||
}
|
||||
.direction {
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
.programme_wp {
|
||||
|
||||
background-color: var(--c-backgroud-brandreverse);
|
||||
margin-bottom: 70px;
|
||||
padding-top: 50px;
|
||||
padding-right: 30px;
|
||||
padding-left: 40px;
|
||||
padding-bottom: 50px;
|
||||
|
||||
/* DÉCALAGE DU BLOC VERS LA DROITE */
|
||||
position: relative;
|
||||
|
||||
@media (min-width: 0px) and (max-width: 700px) {
|
||||
width: 89vw;
|
||||
left: 5%;
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
width: 67vw;
|
||||
left: 30%;
|
||||
}
|
||||
@media (min-width: 800px) {
|
||||
width: 50vw;
|
||||
left: 49%;
|
||||
}
|
||||
transform: translateX(0px);
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
justify-content: initial;
|
||||
align-items: initial;
|
||||
|
||||
.programme_titre {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
.programme_list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
column-gap: 20px;
|
||||
row-gap: 20px;
|
||||
|
||||
}
|
||||
.programme_item {
|
||||
flex: 1 0 200px;
|
||||
|
||||
background-color: var(--c-surface);
|
||||
padding-top: 14px;
|
||||
padding-right: 20px;
|
||||
padding-left: 18px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================ */
|
||||
/* REPRÉSENTATIONS */
|
||||
/* ============================ */
|
||||
.representation_wp {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
/* justify-content: center; */
|
||||
column-gap: 30px;
|
||||
row-gap: 30px;
|
||||
padding-bottom: 70px;
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
padding-left: 20px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.representation_item {
|
||||
|
||||
@media (min-width: 0px) and (max-width: 500px) {
|
||||
width: 100%;
|
||||
}
|
||||
@media (min-width: 500px) {
|
||||
max-width: 215px;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
max-width: 262px;
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
max-width: 300px;
|
||||
}
|
||||
flex: 1 1 300px;
|
||||
display: grid;
|
||||
border: 2px var(--c-brand_rouge) solid;
|
||||
padding-top: 20px;
|
||||
> * {
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
.representation_item_comment_wp {
|
||||
padding-top: 5px;
|
||||
}
|
||||
.representation_item_comment {
|
||||
background-color: lightgray;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
}
|
||||
.representation_cta {
|
||||
color: var(--c-surface);
|
||||
background-color: var(--c-brand_rouge);
|
||||
margin-top: 15px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
text-align: center;
|
||||
a {
|
||||
font-family: var(--font-roboto);
|
||||
font-weight: 600;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================ */
|
||||
/* DESCRIPTION */
|
||||
/* ============================ */
|
||||
.fiche_description {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding-top: 70px;
|
||||
padding-bottom: 70px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
> * {
|
||||
max-width: 570px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
/* ============================ */
|
||||
/* GALERIES */
|
||||
/* ============================ */
|
||||
|
||||
.img-gallery_wp {
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
|
||||
.img-gallery {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 520px));
|
||||
gap: 1rem;
|
||||
justify-content: center;
|
||||
margin-top: 1.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.img-gallery > * {
|
||||
display: block;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.img-gallery :deep(.ds-media) {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.img-gallery :deep(.ds-media__img) {
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
transition: transform 0.25s ease, box-shadow 0.25s ease;
|
||||
}
|
||||
|
||||
.img-gallery :deep(.ds-media__img:hover) {
|
||||
transform: scale(1.02);
|
||||
}
|
||||
|
||||
@media (max-width: 1100px) {
|
||||
.img-gallery {
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 820px) {
|
||||
.img-gallery {
|
||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||
gap: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 520px) {
|
||||
.img-gallery {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.youtube_wp {
|
||||
margin-bottom: 70px;
|
||||
}
|
||||
.youtube-list {
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
/* flex-wrap: wrap; */
|
||||
gap: 20px;
|
||||
}
|
||||
.youtube-item {
|
||||
@media (min-width: 0px) and (max-width: 300px) {
|
||||
min-width: 290px;
|
||||
}
|
||||
|
||||
@media (min-width: 300px) {
|
||||
min-width: 298px;
|
||||
}
|
||||
|
||||
@media (min-width: 400px) {
|
||||
min-width: 398px;
|
||||
}
|
||||
@media (min-width: 500px) {
|
||||
min-width: 480px;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
min-width: 580px;
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
min-width: 670px;
|
||||
}
|
||||
}
|
||||
|
||||
.youtube-item iframe {
|
||||
|
||||
aspect-ratio: 16 / 9;
|
||||
border: 0;
|
||||
}
|
||||
</style>
|
||||
758
app/pages/orchestre/artisteinvitee-[id].vue
Normal file
758
app/pages/orchestre/artisteinvitee-[id].vue
Normal file
@@ -0,0 +1,758 @@
|
||||
<template>
|
||||
<div>
|
||||
<section v-if="pending" aria-busy="true" aria-live="polite">
|
||||
<p>en cours de chargement...</p>
|
||||
</section>
|
||||
<section v-else-if="error" aria-live="polite">
|
||||
<p>Impossible de charger la fiche artiste.</p>
|
||||
</section>
|
||||
|
||||
<template v-else>
|
||||
<PageSection tone="" content-size="default" class="breadcrum_wp">
|
||||
<Breadcrumb :current-label="artiste?.nom_artiste_invite || ''" />
|
||||
</PageSection>
|
||||
|
||||
|
||||
<section class="fiche_header_wp">
|
||||
<div class="fiche_header_wp_gauche"></div>
|
||||
<div class="fiche_header_wp_gauche_carre"></div>
|
||||
<div class="fiche_header_inner">
|
||||
<div class="fiche_header_titres">
|
||||
<div>
|
||||
<DsHeading as="h1" tone="default" textcase="uppercase" class="concert-card__title">
|
||||
{{ artiste.nom_artiste_invite }}
|
||||
</DsHeading>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fiche_header_img">
|
||||
<DsMedia
|
||||
v-if="illustration?.url"
|
||||
:src="illustration.url"
|
||||
:alt="illustration.alternativeText || artiste?.nom_artiste_invite || ''"
|
||||
ratio="3-4"
|
||||
/>
|
||||
<div v-else class="img_placeholder" aria-hidden="true" />
|
||||
</div>
|
||||
<div class="fiche_header_bandeau"></div>
|
||||
<div class="fiche_header_infos">
|
||||
<div>
|
||||
<DsHeading as="h2" tone="invert" textcase="uppercase" class="fiche_header_infos_genre" v-if="postesLabel">
|
||||
{{ postesLabel }}
|
||||
</DsHeading>
|
||||
</div>
|
||||
<div v-if="artiste.url_artiste_invite">
|
||||
<DsText as="p" tone="invert" weight="bold" spacing="space-0" class="">
|
||||
<a :href="artiste.url_artiste_invite" target="_blank" rel="noopener noreferrer">Site internet</a>
|
||||
</DsText>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fiche_header_wp_droite"></div>
|
||||
</section>
|
||||
|
||||
|
||||
<PageSection tone="" content-size="default" class="fiche_description">
|
||||
|
||||
<section v-if="descriptionBlocks" class="description_wp">
|
||||
<StrapiBlocksConvert :blocks="descriptionBlocks" />
|
||||
</section>
|
||||
|
||||
<section v-if="imagesArtiste.length" class="img-gallery_wp">
|
||||
<div class="img-gallery">
|
||||
<DsMedia
|
||||
v-for="img in imagesArtiste"
|
||||
:key="img.id || img.url"
|
||||
:src="img.url"
|
||||
:alt="img.alternativeText || artiste?.nom_artiste_invite || ''"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section v-if="youtubeEmbeds.length" class="youtube_wp">
|
||||
<div class="youtube-list">
|
||||
<div v-for="v in youtubeEmbeds" :key="v.id" class="youtube-item">
|
||||
<iframe
|
||||
:src="v.src"
|
||||
title="Vidéo YouTube"
|
||||
loading="lazy"
|
||||
referrerpolicy="strict-origin-when-cross-origin"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
||||
allowfullscreen
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</PageSection>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import DsMedia from '@root/design-system/primitives/DsMedia.vue'
|
||||
import DsHeading from '@root/design-system/primitives/DsHeading.vue'
|
||||
import DsText from '@root/design-system/primitives/DsText.vue'
|
||||
const route = useRoute()
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// RÉCUPÉRATION DU CONTENU
|
||||
//////////////////////////////////////////////////////////////
|
||||
const artisteSlug = computed(() => String(route.params.id || ''))
|
||||
const populate = {
|
||||
image_illustration_artiste_invite: true,
|
||||
postes_artiste_invite: true,
|
||||
}
|
||||
|
||||
const filters = computed(() => ({
|
||||
slug_artiste_invite: {
|
||||
$eq: artisteSlug.value,
|
||||
},
|
||||
}))
|
||||
|
||||
const { items: artistesinvitees, pending, error } = useStrapi(
|
||||
"/api/__strapi__/artistesinvitees",
|
||||
{
|
||||
locale: "fr-FR",
|
||||
populate,
|
||||
filters,
|
||||
limit: 1,
|
||||
}
|
||||
)
|
||||
|
||||
const artiste = computed(() => artistesinvitees.value?.[0] || {})
|
||||
|
||||
useSeoMeta({
|
||||
title: () => artiste.value?.nom_artiste_invite || 'Artiste',
|
||||
})
|
||||
|
||||
const postesLabel = computed(() =>
|
||||
extractStrapiList(artiste.value?.postes_artiste_invite)
|
||||
.map((p) => p?.nom_poste)
|
||||
.filter(Boolean)
|
||||
.join(', ')
|
||||
)
|
||||
|
||||
const illustration = computed(() => {
|
||||
const m = artiste.value?.image_illustration_artiste_invite
|
||||
if (!m) return null
|
||||
if (m?.data?.attributes) return { id: m.data.id, ...m.data.attributes }
|
||||
if (m.url) return m
|
||||
return null
|
||||
})
|
||||
|
||||
const imagesArtiste = computed(() => {
|
||||
const value = artiste.value?.images_artiste_invite
|
||||
return extractStrapiList(value).filter((img) => Boolean(img?.url))
|
||||
})
|
||||
|
||||
const descriptionBlocks = computed(() =>
|
||||
artiste.value?.description_artiste_invite || artiste.value?.description_concert || null
|
||||
)
|
||||
|
||||
const youtube = computed(() => {
|
||||
const value = artiste.value?.liens_youtube_artiste_invite
|
||||
if (!value) return []
|
||||
return extractStrapiList(value)
|
||||
})
|
||||
function getYoutubeId(url = '') {
|
||||
try {
|
||||
const u = new URL(url)
|
||||
if (u.hostname.includes('youtu.be')) return u.pathname.slice(1)
|
||||
if (u.pathname.startsWith('/shorts/')) return u.pathname.split('/')[2]
|
||||
if (u.pathname.startsWith('/embed/')) return u.pathname.split('/')[2]
|
||||
return u.searchParams.get('v')
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
const youtubeEmbeds = computed(() =>
|
||||
youtube.value
|
||||
.map((item) => {
|
||||
const id = getYoutubeId(item?.lien_youtube)
|
||||
if (!id) return null
|
||||
return {
|
||||
id: item.id || id,
|
||||
src: `https://www.youtube-nocookie.com/embed/${id}?rel=0&modestbranding=1&iv_load_policy=3&playsinline=1`,
|
||||
}
|
||||
})
|
||||
.filter(Boolean)
|
||||
)
|
||||
|
||||
function extractStrapiList(value) {
|
||||
if (!value) return []
|
||||
if (Array.isArray(value)) return value.map(normalizeStrapiItem).filter(Boolean)
|
||||
if (value?.data) {
|
||||
const rows = Array.isArray(value.data) ? value.data : [value.data]
|
||||
return rows.map(normalizeStrapiItem).filter(Boolean)
|
||||
}
|
||||
if (typeof value === 'object') return [normalizeStrapiItem(value)].filter(Boolean)
|
||||
return []
|
||||
}
|
||||
|
||||
function normalizeStrapiItem(item) {
|
||||
if (!item || typeof item !== 'object') return null
|
||||
if (item.attributes && typeof item.attributes === 'object') {
|
||||
return { id: item.id, ...item.attributes }
|
||||
}
|
||||
return item
|
||||
}
|
||||
|
||||
function appendPopulate(query, populateObj, prefix = "populate") {
|
||||
Object.entries(populateObj).forEach(([key, value]) => {
|
||||
if (value === true) {
|
||||
query.set(`${prefix}[${key}]`, "true")
|
||||
return
|
||||
}
|
||||
if (value && typeof value === "object") {
|
||||
appendPopulate(query, value, `${prefix}[${key}][populate]`)
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
.breadcrum_wp {
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
.fiche_header_wp {
|
||||
display: grid;
|
||||
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: auto 510px 20px 200px;
|
||||
padding-top: 40px;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-template-columns: minmax(10px, 10px) 580px 0px;
|
||||
grid-template-rows: 40px 280px 20px 230px;
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
grid-template-columns: minmax(10px, 10px) 660px 0px;
|
||||
grid-template-rows: 70px 250px 90px 300px;
|
||||
}
|
||||
@media (min-width: 800px) {
|
||||
grid-template-columns: minmax(10px, 10px) 780px minmax(10px, 10px);
|
||||
grid-template-rows: 60px 280px 70px 300px;
|
||||
}
|
||||
@media (min-width: 900px) {
|
||||
grid-template-columns: minmax(10px, 10px) 860px minmax(10px, 10px);
|
||||
grid-template-rows: 90px 340px 100px 250px;
|
||||
}
|
||||
@media (min-width: 1000px) {
|
||||
grid-template-columns: minmax(20px, auto) 950px minmax(10px, auto);
|
||||
grid-template-rows: 90px 340px 120px 270px;
|
||||
}
|
||||
@media (min-width: 1100px) {
|
||||
grid-template-columns: minmax(20px, auto) 1020px minmax(20px, auto);
|
||||
grid-template-rows: 90px 340px 140px 290px;
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
grid-template-columns: minmax(20px, auto) 1100px minmax(20px, auto);
|
||||
grid-template-rows: 90px 340px 160px 330px;
|
||||
}
|
||||
@media (min-width: 1300px) {
|
||||
grid-template-columns: minmax(20px, auto) 1200px minmax(20px, auto);
|
||||
grid-template-rows: 90px 340px 160px 330px;
|
||||
}
|
||||
@media (min-width: 1400px) {
|
||||
grid-template-columns: minmax(20px, auto) 1300px minmax(20px, auto);
|
||||
grid-template-rows: 90px 340px 160px 380px;
|
||||
}
|
||||
@media (min-width: 1500px) {
|
||||
grid-template-columns: minmax(20px, auto) 1400px minmax(20px, auto);
|
||||
grid-template-rows: 90px 340px 160px 380px;
|
||||
}
|
||||
}
|
||||
.fiche_header_wp_gauche {
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
display: none;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-column: 1;
|
||||
}
|
||||
}
|
||||
.fiche_header_wp_gauche_carre {
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
display: none;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-column: 1;
|
||||
grid-row: 4;
|
||||
}
|
||||
background-color: var(--c-backgroud-black);
|
||||
}
|
||||
.fiche_header_wp_droite {
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
display: none;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-column: 3;
|
||||
}
|
||||
}
|
||||
|
||||
.fiche_header_inner {
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
grid-column: 1;
|
||||
grid-row: 1/5;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-column: 2;
|
||||
grid-row: 1/5;
|
||||
}
|
||||
display: grid;
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
grid-template-columns: 4fr 1fr 0.5fr;
|
||||
grid-template-rows: auto 510px 20px 200px;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
width: 575px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 40px 280px 20px 230px;
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
width: 675px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 70px 250px 90px 300px;
|
||||
}
|
||||
@media (min-width: 800px) {
|
||||
width: 780px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 60px 280px 70px 300px;
|
||||
}
|
||||
@media (min-width: 900px) {
|
||||
width: 860px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 90px 340px 100px 250px;
|
||||
}
|
||||
@media (min-width: 1000px) {
|
||||
width: 950px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 90px 340px 120px 270px;
|
||||
}
|
||||
@media (min-width: 1100px) {
|
||||
width: 1020px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 90px 340px 140px 290px;
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
width: 1100px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 90px 340px 160px 330px;
|
||||
}
|
||||
@media (min-width: 1300px) {
|
||||
width: 1200px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 90px 340px 160px 330px;
|
||||
}
|
||||
@media (min-width: 1400px) {
|
||||
width: 1300px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 90px 340px 160px 380px;
|
||||
}
|
||||
@media (min-width: 1500px) {
|
||||
width: 1400px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 90px 340px 160px 380px;
|
||||
}
|
||||
@media (min-width: 1600px) {
|
||||
width: 1400px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 90px 340px 160px 380px;
|
||||
}
|
||||
@media (min-width: 1700px) {
|
||||
width: 1400px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 90px 340px 160px 380px;
|
||||
}
|
||||
@media (min-width: 1800px) {
|
||||
width: 1400px;
|
||||
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
|
||||
grid-template-rows: 90px 340px 160px 380px;
|
||||
}
|
||||
}
|
||||
|
||||
.fiche_header_titres {
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
grid-column: 1;
|
||||
grid-row: 1;
|
||||
padding-bottom: 20px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-column: 1;
|
||||
grid-row: 2;
|
||||
}
|
||||
display: grid;
|
||||
align-content: start;
|
||||
gap: 0.75rem;
|
||||
h1 {
|
||||
font-size: 55px;
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
font-size: 25px;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
font-size: 25px;
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
font-size: 30px;
|
||||
}
|
||||
@media (min-width: 800px) {
|
||||
font-size: 30px;
|
||||
}
|
||||
@media (min-width: 900px) {
|
||||
font-size: 40px;
|
||||
}
|
||||
@media (min-width: 1000px) {
|
||||
font-size: 40px;
|
||||
}
|
||||
@media (min-width: 1100px) {
|
||||
font-size: 40px;
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
font-size: 50px;
|
||||
}
|
||||
@media (min-width: 1300px) {
|
||||
font-size: 55px;
|
||||
}
|
||||
@media (min-width: 1400px) {
|
||||
font-size: 55px;
|
||||
}
|
||||
@media (min-width: 1500px) {
|
||||
font-size: 55px;
|
||||
}
|
||||
@media (min-width: 1600px) {
|
||||
font-size: 55px;
|
||||
}
|
||||
@media (min-width: 1700px) {
|
||||
font-size: 55px;
|
||||
}
|
||||
@media (min-width: 1800px) {
|
||||
font-size: 55px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fiche_header_img {
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
grid-column: 1 / 4;
|
||||
grid-row: 2 / 4;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-column: 3 / 5;
|
||||
grid-row: 1 / 5;
|
||||
}
|
||||
overflow: hidden;
|
||||
.ds-media {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.fiche_header_infos {
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
grid-column: 1 / 2;
|
||||
grid-row: 4;
|
||||
margin-top: -30px;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-column: 1;
|
||||
grid-row: 4;
|
||||
}
|
||||
display: grid;
|
||||
align-content: center;
|
||||
justify-content: end;
|
||||
|
||||
@media (min-width: 0px) and (max-width: 700px) {
|
||||
gap: 7px;
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
text-align: right;
|
||||
.fiche_header_infos_genre {
|
||||
font-weight: 900;
|
||||
|
||||
}
|
||||
}
|
||||
.fiche_header_bandeau {
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
grid-column: 1 / 3;
|
||||
grid-row: 4;
|
||||
margin-top: -30px;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-column: 1 / 4;
|
||||
grid-row: 4;
|
||||
}
|
||||
background-color: var(--c-backgroud-black);
|
||||
}
|
||||
|
||||
/* ============================ */
|
||||
/* DISTRIBUTION / PROGRAMME */
|
||||
/* ============================ */
|
||||
.fiche_details_wp {
|
||||
.distribution_wp {
|
||||
padding-top: 50px;
|
||||
padding-bottom: 50px;
|
||||
padding-left: 20px;
|
||||
.distribution_item {
|
||||
display: flex;
|
||||
.distribution_item_poste {
|
||||
padding-right: 10px;
|
||||
font-weight: 200;
|
||||
}
|
||||
.direction {
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
.programme_wp {
|
||||
|
||||
background-color: var(--c-backgroud-brandreverse);
|
||||
margin-bottom: 70px;
|
||||
padding-top: 50px;
|
||||
padding-right: 30px;
|
||||
padding-left: 40px;
|
||||
padding-bottom: 50px;
|
||||
|
||||
/* DÉCALAGE DU BLOC VERS LA DROITE */
|
||||
position: relative;
|
||||
|
||||
@media (min-width: 0px) and (max-width: 700px) {
|
||||
width: 89vw;
|
||||
left: 5%;
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
width: 67vw;
|
||||
left: 30%;
|
||||
}
|
||||
@media (min-width: 800px) {
|
||||
width: 50vw;
|
||||
left: 49%;
|
||||
}
|
||||
transform: translateX(0px);
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
justify-content: initial;
|
||||
align-items: initial;
|
||||
|
||||
.programme_titre {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
.programme_list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
column-gap: 20px;
|
||||
row-gap: 20px;
|
||||
|
||||
}
|
||||
.programme_item {
|
||||
flex: 1 0 200px;
|
||||
|
||||
background-color: var(--c-surface);
|
||||
padding-top: 14px;
|
||||
padding-right: 20px;
|
||||
padding-left: 18px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================ */
|
||||
/* REPRÉSENTATIONS */
|
||||
/* ============================ */
|
||||
.representation_wp {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
/* justify-content: center; */
|
||||
column-gap: 30px;
|
||||
row-gap: 30px;
|
||||
padding-bottom: 70px;
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
padding-left: 20px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.representation_item {
|
||||
|
||||
@media (min-width: 0px) and (max-width: 500px) {
|
||||
width: 100%;
|
||||
}
|
||||
@media (min-width: 500px) {
|
||||
max-width: 215px;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
max-width: 262px;
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
max-width: 300px;
|
||||
}
|
||||
flex: 1 1 300px;
|
||||
display: grid;
|
||||
border: 2px var(--c-brand_rouge) solid;
|
||||
padding-top: 20px;
|
||||
> * {
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
.representation_item_comment_wp {
|
||||
padding-top: 5px;
|
||||
}
|
||||
.representation_item_comment {
|
||||
background-color: lightgray;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
}
|
||||
.representation_cta {
|
||||
color: var(--c-surface);
|
||||
background-color: var(--c-brand_rouge);
|
||||
margin-top: 15px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
text-align: center;
|
||||
a {
|
||||
font-family: var(--font-roboto);
|
||||
font-weight: 600;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================ */
|
||||
/* DESCRIPTION */
|
||||
/* ============================ */
|
||||
.fiche_description {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding-top: 70px;
|
||||
padding-bottom: 70px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
> * {
|
||||
max-width: 570px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
/* ============================ */
|
||||
/* GALERIES */
|
||||
/* ============================ */
|
||||
|
||||
.img-gallery_wp {
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
|
||||
.img-gallery {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 520px));
|
||||
gap: 1rem;
|
||||
justify-content: center;
|
||||
margin-top: 1.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.img-gallery > * {
|
||||
display: block;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.img-gallery :deep(.ds-media) {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.img-gallery :deep(.ds-media__img) {
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
transition: transform 0.25s ease, box-shadow 0.25s ease;
|
||||
}
|
||||
|
||||
.img-gallery :deep(.ds-media__img:hover) {
|
||||
transform: scale(1.02);
|
||||
}
|
||||
|
||||
@media (max-width: 1100px) {
|
||||
.img-gallery {
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 820px) {
|
||||
.img-gallery {
|
||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||
gap: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 520px) {
|
||||
.img-gallery {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.youtube_wp {
|
||||
margin-bottom: 70px;
|
||||
}
|
||||
.youtube-list {
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
/* flex-wrap: wrap; */
|
||||
gap: 20px;
|
||||
}
|
||||
.youtube-item {
|
||||
@media (min-width: 0px) and (max-width: 300px) {
|
||||
min-width: 290px;
|
||||
}
|
||||
|
||||
@media (min-width: 300px) {
|
||||
min-width: 298px;
|
||||
}
|
||||
|
||||
@media (min-width: 400px) {
|
||||
min-width: 398px;
|
||||
}
|
||||
@media (min-width: 500px) {
|
||||
min-width: 480px;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
min-width: 580px;
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
min-width: 670px;
|
||||
}
|
||||
}
|
||||
|
||||
.youtube-item iframe {
|
||||
|
||||
aspect-ratio: 16 / 9;
|
||||
border: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -1,13 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
320
app/pages/orchestre/artistesinvitees.vue
Normal file
320
app/pages/orchestre/artistesinvitees.vue
Normal file
@@ -0,0 +1,320 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- ================== -->
|
||||
<!-- Fond noir -->
|
||||
<!-- ================== -->
|
||||
<PageSection tone="brandreverse" content-size="default" class="theme_bandeau--grid">
|
||||
<SectionContent pad="xs" class="theme_bandeau--grid--left">
|
||||
<SectionTitle tone="invert" pad="">
|
||||
LES ARTISTES INVITÉS
|
||||
</SectionTitle>
|
||||
<DsHeading as="h3" tone="invert">
|
||||
La patte de l’Orchestre national d’Île-de-France, c’est aussi la richesse de ses collaborations artistiques
|
||||
</DsHeading>
|
||||
</SectionContent>
|
||||
|
||||
|
||||
<SectionContent pad="xs" class="theme_bandeau--grid--right">
|
||||
<DsText tone="invert" size="lg" class="theme_bandeau--grid--right--text" >
|
||||
Chefs, solistes, comédiens, chaque saison, de nombreux talents viennent enrichir la programmation de l’Orchestre : découvrez ici tous les artistes de la saison !
|
||||
</DsText>
|
||||
</SectionContent>
|
||||
</PageSection>
|
||||
|
||||
<!-- ================== -->
|
||||
<!-- Listes des musiciens -->
|
||||
<!-- ================== -->
|
||||
|
||||
<!-- ================== -->
|
||||
<!-- DIRECTION -->
|
||||
<!-- ================== -->
|
||||
|
||||
<PageSection padded_size="md" content-size="default" class="musiciens_list_section remonter_artistes_list">
|
||||
|
||||
|
||||
<section v-if="pending" aria-busy="true" aria-live="polite">
|
||||
<DsText as="p" tone="default">Chargement des artistes...</DsText>
|
||||
</section>
|
||||
|
||||
<section v-else-if="error">
|
||||
<DsText as="p" tone="default">Impossible de charger les artistes.</DsText>
|
||||
</section>
|
||||
|
||||
<section v-else-if="artistesDirection.length" class="musiciens_list">
|
||||
<article v-for="a in artistesDirection" :key="a.id" class="musicien_card">
|
||||
<DsMedia
|
||||
v-if="a.image?.url"
|
||||
:src="a.image.url"
|
||||
:alt="a.image.alternativeText || a.nom_artiste_invite || ''"
|
||||
ratio="square"
|
||||
/>
|
||||
<div v-else class="musicien_card_media-placeholder" aria-hidden="true" />
|
||||
|
||||
<DsHeading as="h4" tone="default" class="musicien_card_nom">
|
||||
<NuxtLink :to="`/orchestre/artisteinvitee-${a.slug_artiste_invite}?from=artistesinvitees`">
|
||||
{{ a.nom_artiste_invite }}
|
||||
</NuxtLink>
|
||||
</DsHeading>
|
||||
|
||||
<DsText
|
||||
v-if="a.postesLabel"
|
||||
as="p"
|
||||
tone="default"
|
||||
size="md"
|
||||
class="musicien_card_postes"
|
||||
>
|
||||
{{ a.postesLabel }}
|
||||
</DsText>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section v-else>
|
||||
<DsText as="p" tone="default">Aucun artiste pour la direction.</DsText>
|
||||
</section>
|
||||
</PageSection>
|
||||
|
||||
<!-- ================== -->
|
||||
<!-- MUSICIENS -->
|
||||
<!-- ================== -->
|
||||
|
||||
<PageSection padded_size="md" content-size="default" class="musiciens_list_section musiciens_list_wp">
|
||||
|
||||
|
||||
<section v-if="pending" aria-busy="true" aria-live="polite">
|
||||
<DsText as="p" tone="default">Chargement des artistes...</DsText>
|
||||
</section>
|
||||
|
||||
<section v-else-if="error">
|
||||
<DsText as="p" tone="default">Impossible de charger les artistes.</DsText>
|
||||
</section>
|
||||
|
||||
<section v-else-if="artistesAutres.length" class="musiciens_list">
|
||||
<article v-for="a in artistesAutres" :key="a.id" class="musicien_card">
|
||||
<DsMedia
|
||||
v-if="a.image?.url"
|
||||
:src="a.image.url"
|
||||
:alt="a.image.alternativeText || a.nom_artiste_invite || ''"
|
||||
ratio="square"
|
||||
/>
|
||||
<div v-else class="musicien_card_media-placeholder" aria-hidden="true" />
|
||||
|
||||
<DsHeading as="h4" tone="default" class="musicien_card_nom">
|
||||
<NuxtLink :to="`/orchestre/artisteinvitee-${a.slug_artiste_invite}?from=artistesinvitees`">
|
||||
{{ a.nom_artiste_invite }}
|
||||
</NuxtLink>
|
||||
</DsHeading>
|
||||
|
||||
<DsText
|
||||
v-if="a.postesLabel"
|
||||
as="p"
|
||||
tone="default"
|
||||
size="md"
|
||||
class="musicien_card_postes"
|
||||
>
|
||||
{{ a.postesLabel }}
|
||||
</DsText>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section v-else>
|
||||
<DsText as="p" tone="default">Aucun autre artiste trouvé.</DsText>
|
||||
</section>
|
||||
</PageSection>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import DsHeading from '@root/design-system/primitives/DsHeading.vue'
|
||||
import DsText from '@root/design-system/primitives/DsText.vue'
|
||||
import DsMedia from '@root/design-system/primitives/DsMedia.vue'
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
const saisonFiltre = computed(() => String(runtimeConfig.public.saison || '').trim())
|
||||
const artistesFilters = computed(() => {
|
||||
if (!saisonFiltre.value) return null
|
||||
return {
|
||||
saisons_artiste_invite: {
|
||||
nom_saison: {
|
||||
$eq: saisonFiltre.value,
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
//--------------------
|
||||
// DONNÉES POUR LES ARTISTES
|
||||
//--------------------
|
||||
const { items: artistesinvitees, pending, error } = useStrapi(
|
||||
"/api/__strapi__/artistesinvitees",
|
||||
{
|
||||
locale: "fr-FR",
|
||||
sort: "nom_artiste_invite:asc",
|
||||
populate: {
|
||||
saisons_artiste_invite: true,
|
||||
image_illustration_artiste_invite: true,
|
||||
postes_artiste_invite: true,
|
||||
},
|
||||
filters: artistesFilters,
|
||||
}
|
||||
)
|
||||
|
||||
const artistesDisplay = computed(() => {
|
||||
return (artistesinvitees.value || []).map((artiste) => ({
|
||||
...artiste,
|
||||
image: getArtisteImage(artiste),
|
||||
postesLabel: getPostesLabel(artiste),
|
||||
}))
|
||||
})
|
||||
|
||||
const postesDirection = [
|
||||
"direction",
|
||||
"cheffe assistante",
|
||||
"chef assistante",
|
||||
]
|
||||
|
||||
const artistesDirection = computed(() =>
|
||||
artistesDisplay.value.filter((a) => isDirectionArtist(a))
|
||||
)
|
||||
|
||||
const artistesAutres = computed(() =>
|
||||
artistesDisplay.value.filter((a) => !isDirectionArtist(a))
|
||||
)
|
||||
|
||||
function getArtisteImage(artiste) {
|
||||
const media = artiste?.image_illustration_artiste_invite
|
||||
const rows = extractStrapiList(media)
|
||||
if (rows.length) return rows[0]
|
||||
if (media && typeof media === "object" && media.url) return media
|
||||
return null
|
||||
}
|
||||
|
||||
function getPostesLabel(artiste) {
|
||||
const postes = extractStrapiList(artiste?.postes_artiste_invite)
|
||||
return postes
|
||||
.map((p) => p?.nom_poste)
|
||||
.filter(Boolean)
|
||||
.join(", ")
|
||||
}
|
||||
|
||||
function isDirectionArtist(artiste) {
|
||||
const postes = extractStrapiList(artiste?.postes_artiste_invite)
|
||||
.map((p) => String(p?.nom_poste || "").trim().toLowerCase())
|
||||
.filter(Boolean)
|
||||
|
||||
return postes.some((poste) => postesDirection.includes(poste))
|
||||
}
|
||||
|
||||
function extractStrapiList(value) {
|
||||
if (!value) return []
|
||||
if (Array.isArray(value)) return value.map(normalizeStrapiItem).filter(Boolean)
|
||||
if (value?.data) {
|
||||
const rows = Array.isArray(value.data) ? value.data : [value.data]
|
||||
return rows.map(normalizeStrapiItem).filter(Boolean)
|
||||
}
|
||||
if (typeof value === "object") return [normalizeStrapiItem(value)].filter(Boolean)
|
||||
return []
|
||||
}
|
||||
|
||||
function normalizeStrapiItem(item) {
|
||||
if (!item || typeof item !== "object") return null
|
||||
if (item.attributes && typeof item.attributes === "object") {
|
||||
return { id: item.id, ...item.attributes }
|
||||
}
|
||||
return item
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
|
||||
.remonter_artistes_list {
|
||||
transform: translateY(-90px);
|
||||
}
|
||||
|
||||
.theme_bandeau--grid {
|
||||
> .page-section--inner {
|
||||
padding-top: 70px;
|
||||
padding-bottom: 150px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
column-gap: 120px;
|
||||
row-gap: 30px;
|
||||
}
|
||||
&--left {
|
||||
max-width: 40%;
|
||||
h1 {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
}
|
||||
&--right {
|
||||
max-width: 60%;
|
||||
&--text {
|
||||
max-width: 500px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.musiciens_list_wp {
|
||||
// parce que le bloc du dessus à un transform: translateY(-170px); alors cela laisse un espace vide que l'on comble avec ce margin-top négatif
|
||||
margin-top: -120px;
|
||||
}
|
||||
.musiciens_list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 28px;
|
||||
}
|
||||
|
||||
.musicien_card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.musicien_card_media-placeholder {
|
||||
width: 100%;
|
||||
aspect-ratio: 1 / 1;
|
||||
background: rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
.musicien_card_nom {
|
||||
margin-top: 8px;
|
||||
margin-left: 5px;
|
||||
&:hover {
|
||||
color: var(--c-brand_rouge);
|
||||
}
|
||||
}
|
||||
.musicien_card_postes {
|
||||
margin-left: 5px;
|
||||
text-transform: lowercase;
|
||||
&::first-letter {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@media (max-width: 980px) {
|
||||
.musiciens_list {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 400px) {
|
||||
.musiciens_list {
|
||||
grid-template-columns: 1fr;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.musiciens_list {
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -4,7 +4,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script setup>
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<div>
|
||||
|
||||
test
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script setup>
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,13 +1,474 @@
|
||||
<template>
|
||||
<div>
|
||||
Page en construction Missions
|
||||
</div>
|
||||
<div>
|
||||
<!-- ================== -->
|
||||
<!-- FILS D'ARIANE -->
|
||||
<!-- ================== -->
|
||||
<PageSection tone="" content-size="default" class="breadcrum_wp">
|
||||
<Breadcrumb/>
|
||||
</PageSection>
|
||||
|
||||
<!-- ================== -->
|
||||
<!-- EN-TêTE -->
|
||||
<!-- ================== -->
|
||||
<section class="fiche_header_wp">
|
||||
<div class="fiche_header_wp_gauche"></div>
|
||||
|
||||
<div class="fiche_header_inner">
|
||||
<div class="fiche_header_titres">
|
||||
<div>
|
||||
<DsHeading as="h1" tone="default" textcase="uppercase" class="concert-card__title">
|
||||
{{ missions?.header_titre }}
|
||||
</DsHeading>
|
||||
</div>
|
||||
|
||||
<DsText as="p" align="justify">
|
||||
{{ missions?.header_text }}
|
||||
</DsText>
|
||||
</div>
|
||||
<div class="fiche_header_img">
|
||||
<DsMedia
|
||||
v-if="missions?.image_illustration_header?.url"
|
||||
:src="missions.image_illustration_header.url"
|
||||
:alt="missions.image_illustration_header.alternativeText || ''"
|
||||
fit="contain"
|
||||
ratio="square"
|
||||
/>
|
||||
|
||||
<div v-else class="img_placeholder" aria-hidden="true" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="fiche_header_wp_droite"></div>
|
||||
|
||||
</section>
|
||||
|
||||
<!-- ================== -->
|
||||
<!-- PARTIE 1 -->
|
||||
<!-- ================== -->
|
||||
<PageSection tone="" content-size="default" padded_size="md" class="fiche_description">
|
||||
<SectionContent v-if="missions?.partie_1" class="description_wp">
|
||||
<StrapiBlocksConvert :blocks="missions.partie_1" />
|
||||
</SectionContent>
|
||||
</PageSection>
|
||||
|
||||
<!-- ================== -->
|
||||
<!-- decalage_gauche 1 -->
|
||||
<!-- ================== -->
|
||||
<PageSection :content="false">
|
||||
<Decalage tone="dark" title-tone="invert" position="left" button-tone="invert">
|
||||
<template #title>
|
||||
{{ missions?.decalage_gauche_1?.decalage_titre }}
|
||||
</template>
|
||||
<DsText as="p" tone="invert" align="justify">
|
||||
{{ missions?.decalage_gauche_1?.decalage_texte }}
|
||||
</DsText>
|
||||
</Decalage>
|
||||
</PageSection>
|
||||
|
||||
<!-- ================== -->
|
||||
<!-- PARTIE 2 -->
|
||||
<!-- ================== -->
|
||||
<PageSection tone="" content-size="default" padded_size="md" class="fiche_description">
|
||||
<SectionContent v-if="missions?.partie_2" class="description_wp">
|
||||
<StrapiBlocksConvert :blocks="missions.partie_2" />
|
||||
</SectionContent>
|
||||
</PageSection>
|
||||
|
||||
<!-- ================== -->
|
||||
<!-- decalage_droite_2 -->
|
||||
<!-- ================== -->
|
||||
<PageSection :content="false">
|
||||
<Decalage tone="brandreverse" title-tone="invert" position="right" button-tone="invert">
|
||||
<template #title>
|
||||
{{ missions?.decalage_droite_2?.decalage_titre }}
|
||||
</template>
|
||||
<DsText as="p" align="justify">
|
||||
{{ missions?.decalage_droite_2?.decalage_texte }}
|
||||
</DsText>
|
||||
</Decalage>
|
||||
</PageSection>
|
||||
|
||||
<!-- ================== -->
|
||||
<!-- PARTIE 3 -->
|
||||
<!-- ================== -->
|
||||
<PageSection tone="" content-size="default" padded_size="md" class="fiche_description">
|
||||
<SectionContent v-if="missions?.partie_3" class="description_wp">
|
||||
<StrapiBlocksConvert :blocks="missions.partie_3" />
|
||||
</SectionContent>
|
||||
</PageSection>
|
||||
|
||||
|
||||
|
||||
<!-- ================== -->
|
||||
<!-- decalage_droite_clic_4 -->
|
||||
<!-- ================== -->
|
||||
<PageSection :content="false">
|
||||
<Decalage tone="brand" title-tone="invert" position="right" button-tone="invert" ensavoirplus-target="texte_cache">
|
||||
<template #title>
|
||||
{{ missions?.decalage_droite_clic_4?.decalage_titre }}
|
||||
</template>
|
||||
<DsText as="p" tone="invert" align="justify">
|
||||
{{ missions?.decalage_droite_clic_4?.decalage_texte }}
|
||||
</DsText>
|
||||
</Decalage>
|
||||
</PageSection>
|
||||
|
||||
<PageSection>
|
||||
<div id="texte_cache" class="decalage_ensavoirplus--hidden">Texte caché</div>
|
||||
</PageSection>
|
||||
|
||||
<!-- ================== -->
|
||||
<!-- L'ORCHESTRE POUR LES PROS -->
|
||||
<!-- ================== -->
|
||||
<PageSection padded_size="lg">
|
||||
<SectionContent>
|
||||
<SectionTitle tone="" pad="xs">
|
||||
L'ORCHESTRE POUR LES PROS
|
||||
</SectionTitle>
|
||||
</SectionContent>
|
||||
|
||||
<SectionContent>
|
||||
<BannierePros />
|
||||
</SectionContent>
|
||||
</PageSection>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script setup>
|
||||
import DsHeading from '@root/design-system/primitives/DsHeading.vue'
|
||||
import DsText from '@root/design-system/primitives/DsText.vue'
|
||||
import DsMedia from '@root/design-system/primitives/DsMedia.vue'
|
||||
import DsButton from '@root/design-system/primitives/DsButton.vue'
|
||||
|
||||
//--------------------
|
||||
// RÉCUPÉRATION DES DONNÉES STRAPI
|
||||
//--------------------
|
||||
const { items: mission, pending, error, refresh } = useStrapi(
|
||||
"/api/__strapi__/missions",
|
||||
{ locale: "fr-FR",
|
||||
populate: {
|
||||
decalage_gauche_1: true,
|
||||
decalage_droite_2: true,
|
||||
decalage_gauche_3: true,
|
||||
decalage_droite_clic_4: true,
|
||||
image_illustration_header: true,
|
||||
},
|
||||
}
|
||||
)
|
||||
const missions = computed(() => mission.value?.[0] || null)
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
<style lang="scss">
|
||||
|
||||
</style>
|
||||
|
||||
.breadcrum_wp {
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
.fiche_header_wp {
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
padding-bottom: 100px;
|
||||
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: auto 510px;
|
||||
padding-top: 40px;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-template-columns: minmax(10px, 10px) 580px 0px;
|
||||
grid-template-rows: 40px 380px;
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
grid-template-columns: minmax(10px, 10px) 660px 0px;
|
||||
grid-template-rows: 40px 380px;
|
||||
}
|
||||
@media (min-width: 800px) {
|
||||
grid-template-columns: minmax(10px, 10px) auto minmax(10px, 10px);
|
||||
grid-template-rows: 40px 340px;
|
||||
}
|
||||
@media (min-width: 900px) {
|
||||
grid-template-columns: minmax(10px, 10px) 860px minmax(10px, 10px);
|
||||
grid-template-rows: 40px 400px;
|
||||
}
|
||||
@media (min-width: 1000px) {
|
||||
grid-template-columns: minmax(20px, auto) 950px minmax(10px, auto);
|
||||
grid-template-rows: 40px 400px;
|
||||
}
|
||||
@media (min-width: 1100px) {
|
||||
grid-template-columns: minmax(20px, auto) 1020px minmax(20px, auto);
|
||||
grid-template-rows: 40px 400px;
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
grid-template-columns: minmax(20px, auto) 1100px minmax(20px, auto);
|
||||
grid-template-rows: 40px 400px;
|
||||
}
|
||||
@media (min-width: 1300px) {
|
||||
grid-template-columns: minmax(20px, auto) 1200px minmax(20px, auto);
|
||||
grid-template-rows: 40px 400px;
|
||||
}
|
||||
@media (min-width: 1400px) {
|
||||
grid-template-columns: minmax(20px, auto) 1300px minmax(20px, auto);
|
||||
grid-template-rows: 40px 400px;
|
||||
}
|
||||
@media (min-width: 1500px) {
|
||||
grid-template-columns: minmax(20px, auto) 1400px minmax(20px, auto);
|
||||
grid-template-rows: 40px 400px;
|
||||
}
|
||||
}
|
||||
.fiche_header_wp_gauche {
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
display: none;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-column: 1;
|
||||
}
|
||||
}
|
||||
.fiche_header_wp_gauche_carre {
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
display: none;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-column: 1;
|
||||
grid-row: 4;
|
||||
}
|
||||
}
|
||||
.fiche_header_wp_droite {
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
display: none;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-column: 3;
|
||||
}
|
||||
}
|
||||
|
||||
.fiche_header_inner {
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
grid-column: 1;
|
||||
grid-row: 1/3;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-column: 2;
|
||||
grid-row: 1/3;
|
||||
}
|
||||
display: grid;
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: auto 510px;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
width: 575px;
|
||||
grid-template-columns: 4fr 0.5fr 3.5fr;
|
||||
grid-template-rows: 40px 380px;
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
width: 675px;
|
||||
grid-template-columns: 4fr 0.5fr 3.5fr;
|
||||
grid-template-rows: 40px 380px;
|
||||
}
|
||||
@media (min-width: 800px) {
|
||||
width: 780px;
|
||||
grid-template-columns: 4fr 0.5fr 3.5fr;
|
||||
grid-template-rows: 40px 340px;
|
||||
}
|
||||
@media (min-width: 900px) {
|
||||
width: 860px;
|
||||
grid-template-columns: 4fr 0.5fr 3.5fr;
|
||||
grid-template-rows: 40px 400px;
|
||||
}
|
||||
@media (min-width: 1000px) {
|
||||
width: 950px;
|
||||
grid-template-columns: 4fr 0.5fr 3.5fr;
|
||||
grid-template-rows: 40px 400px;
|
||||
}
|
||||
@media (min-width: 1100px) {
|
||||
width: 1020px;
|
||||
grid-template-columns: 4fr 0.5fr 3.5fr;
|
||||
grid-template-rows: 40px 400px;
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
width: 1100px;
|
||||
grid-template-columns: 4fr 0.5fr 3.5fr;
|
||||
grid-template-rows: 40px 400px;
|
||||
}
|
||||
@media (min-width: 1300px) {
|
||||
width: 1200px;
|
||||
grid-template-columns: 4fr 0.5fr 3.5fr;
|
||||
grid-template-rows: 40px 400px;
|
||||
}
|
||||
@media (min-width: 1400px) {
|
||||
width: 1300px;
|
||||
grid-template-columns: 4fr 0.5fr 3.5fr;
|
||||
grid-template-rows: 40px 400px;
|
||||
}
|
||||
@media (min-width: 1500px) {
|
||||
width: 1400px;
|
||||
grid-template-columns: 4fr 0.5fr 3.5fr;
|
||||
grid-template-rows: 40px 400px;
|
||||
}
|
||||
@media (min-width: 1600px) {
|
||||
width: 1400px;
|
||||
grid-template-columns: 4fr 0.5fr 3.5fr;
|
||||
grid-template-rows: 40px 400px;
|
||||
}
|
||||
@media (min-width: 1700px) {
|
||||
width: 1400px;
|
||||
grid-template-columns: 4fr 0.5fr 3.5fr;
|
||||
grid-template-rows: 40px 400px;
|
||||
}
|
||||
@media (min-width: 1800px) {
|
||||
width: 1400px;
|
||||
grid-template-columns: 4fr 0.5fr 3.5fr;
|
||||
grid-template-rows: 40px 400px;
|
||||
}
|
||||
}
|
||||
|
||||
.fiche_header_titres {
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
grid-column: 1;
|
||||
grid-row: 1;
|
||||
padding-bottom: 20px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-column: 1;
|
||||
grid-row: 2;
|
||||
}
|
||||
display: grid;
|
||||
align-content: start;
|
||||
gap: 0.75rem;
|
||||
max-width: 475px;
|
||||
|
||||
h1 {
|
||||
font-size: 55px;
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
font-size: 25px;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
font-size: 25px;
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
font-size: 30px;
|
||||
}
|
||||
@media (min-width: 800px) {
|
||||
font-size: 30px;
|
||||
}
|
||||
@media (min-width: 900px) {
|
||||
font-size: 40px;
|
||||
}
|
||||
@media (min-width: 1000px) {
|
||||
font-size: 40px;
|
||||
}
|
||||
@media (min-width: 1100px) {
|
||||
font-size: 40px;
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
font-size: 50px;
|
||||
}
|
||||
@media (min-width: 1300px) {
|
||||
font-size: 55px;
|
||||
}
|
||||
@media (min-width: 1400px) {
|
||||
font-size: 55px;
|
||||
}
|
||||
@media (min-width: 1500px) {
|
||||
font-size: 55px;
|
||||
}
|
||||
@media (min-width: 1600px) {
|
||||
font-size: 55px;
|
||||
}
|
||||
@media (min-width: 1700px) {
|
||||
font-size: 55px;
|
||||
}
|
||||
@media (min-width: 1800px) {
|
||||
font-size: 55px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fiche_header_img {
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
grid-column: 1 / 4;
|
||||
grid-row: 2 / 3;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-column: 3 / 5;
|
||||
grid-row: 1 / 3;
|
||||
}
|
||||
overflow: hidden;
|
||||
.ds-media {
|
||||
@media (min-width: 600px) {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fiche_header_infos {
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
grid-column: 1 / 2;
|
||||
grid-row: 4;
|
||||
margin-top: -30px;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-column: 1;
|
||||
grid-row: 4;
|
||||
}
|
||||
display: grid;
|
||||
align-content: center;
|
||||
justify-content: end;
|
||||
|
||||
@media (min-width: 0px) and (max-width: 700px) {
|
||||
gap: 7px;
|
||||
}
|
||||
@media (min-width: 700px) {
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
text-align: right;
|
||||
.fiche_header_infos_genre {
|
||||
font-weight: 900;
|
||||
|
||||
}
|
||||
}
|
||||
.fiche_header_bandeau {
|
||||
|
||||
@media (min-width: 0px) and (max-width: 600px) {
|
||||
grid-column: 1 / 3;
|
||||
grid-row: 4;
|
||||
margin-top: -30px;
|
||||
}
|
||||
@media (min-width: 600px) {
|
||||
grid-column: 1 / 4;
|
||||
grid-row: 4;
|
||||
}
|
||||
background-color: var(--c-backgroud-black);
|
||||
}
|
||||
|
||||
.fiche_description > * {
|
||||
max-width: 570px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.fiche_description {
|
||||
.page-section--inner {
|
||||
|
||||
@media (max-width: 599px) {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,13 +1,320 @@
|
||||
<template>
|
||||
<div>
|
||||
|
||||
<!-- ================== -->
|
||||
<!-- Fond noir -->
|
||||
<!-- ================== -->
|
||||
<PageSection tone="bleu" content-size="default" class="theme_bandeau--grid">
|
||||
<SectionContent pad="xs" class="theme_bandeau--grid--left">
|
||||
<SectionTitle tone="invert" pad="">
|
||||
LES MUSICIENS
|
||||
</SectionTitle>
|
||||
<DsHeading as="h3" tone="invert">
|
||||
95 musiciens engagés Partout et pour tous en Île-de-France !
|
||||
</DsHeading>
|
||||
</SectionContent>
|
||||
|
||||
|
||||
<SectionContent pad="xs" class="theme_bandeau--grid--right">
|
||||
<DsText tone="invert" size="lg" class="theme_bandeau--grid--right--text" >
|
||||
Les 95 musiciennes et musiciens proposent chaque saison plus de 120 concerts dans des salles et théâtres, des lieux culturels et des espaces atypiques de la région francilienne. Porté par une forte mission territoriale, l’orchestre s’engage à rendre la musique symphonique accessible à toutes et tous, en la faisant vivre au plus près des habitants grâce notamment à des actions culturelles, pédagogiques et participatives au cœur du territoire.
|
||||
</DsText>
|
||||
</SectionContent>
|
||||
</PageSection>
|
||||
|
||||
<!-- ================== -->
|
||||
<!-- Listes des musiciens -->
|
||||
<!-- ================== -->
|
||||
|
||||
<!-- ================== -->
|
||||
<!-- DIRECTION -->
|
||||
<!-- ================== -->
|
||||
|
||||
<PageSection padded_size="md" content-size="default" class="musiciens_list_section remonter_artistes_list">
|
||||
|
||||
|
||||
<section v-if="pending" aria-busy="true" aria-live="polite">
|
||||
<DsText as="p" tone="default">Chargement des artistes...</DsText>
|
||||
</section>
|
||||
|
||||
<section v-else-if="error">
|
||||
<DsText as="p" tone="default">Impossible de charger les artistes.</DsText>
|
||||
</section>
|
||||
|
||||
<section v-else-if="artistesDirection.length" class="musiciens_list">
|
||||
<article v-for="a in artistesDirection" :key="a.id" class="musicien_card">
|
||||
<DsMedia
|
||||
v-if="a.image?.url"
|
||||
:src="a.image.url"
|
||||
:alt="a.image.alternativeText || a.nom_artiste_ondif || ''"
|
||||
ratio="square"
|
||||
/>
|
||||
<div v-else class="musicien_card_media-placeholder" aria-hidden="true" />
|
||||
|
||||
<DsHeading as="h4" tone="default" class="musicien_card_nom">
|
||||
<NuxtLink :to="`/orchestre/artiste-${a.slug_artiste_ondif}?from=musiciens`">
|
||||
{{ a.nom_artiste_ondif }}
|
||||
</NuxtLink>
|
||||
</DsHeading>
|
||||
|
||||
<DsText
|
||||
v-if="a.postesLabel"
|
||||
as="p"
|
||||
tone="default"
|
||||
size="md"
|
||||
class="musicien_card_postes"
|
||||
>
|
||||
{{ a.postesLabel }}
|
||||
</DsText>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section v-else>
|
||||
<DsText as="p" tone="default">Aucun artiste pour la direction.</DsText>
|
||||
</section>
|
||||
</PageSection>
|
||||
|
||||
<!-- ================== -->
|
||||
<!-- MUSICIENS -->
|
||||
<!-- ================== -->
|
||||
|
||||
<PageSection padded_size="md" content-size="default" class="musiciens_list_section musiciens_list_wp">
|
||||
|
||||
|
||||
<section v-if="pending" aria-busy="true" aria-live="polite">
|
||||
<DsText as="p" tone="default">Chargement des artistes...</DsText>
|
||||
</section>
|
||||
|
||||
<section v-else-if="error">
|
||||
<DsText as="p" tone="default">Impossible de charger les artistes.</DsText>
|
||||
</section>
|
||||
|
||||
<section v-else-if="artistesAutres.length" class="musiciens_list">
|
||||
<article v-for="a in artistesAutres" :key="a.id" class="musicien_card">
|
||||
<DsMedia
|
||||
v-if="a.image?.url"
|
||||
:src="a.image.url"
|
||||
:alt="a.image.alternativeText || a.nom_artiste_ondif || ''"
|
||||
ratio="square"
|
||||
/>
|
||||
<div v-else class="musicien_card_media-placeholder" aria-hidden="true" />
|
||||
|
||||
<DsHeading as="h4" tone="default" class="musicien_card_nom">
|
||||
<NuxtLink :to="`/orchestre/artiste-${a.slug_artiste_ondif}?from=musiciens`">
|
||||
{{ a.nom_artiste_ondif }}
|
||||
</NuxtLink>
|
||||
</DsHeading>
|
||||
|
||||
<DsText
|
||||
v-if="a.postesLabel"
|
||||
as="p"
|
||||
tone="default"
|
||||
size="md"
|
||||
class="musicien_card_postes"
|
||||
>
|
||||
{{ a.postesLabel }}
|
||||
</DsText>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section v-else>
|
||||
<DsText as="p" tone="default">Aucun autre artiste trouvé.</DsText>
|
||||
</section>
|
||||
</PageSection>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script setup>
|
||||
import DsHeading from '@root/design-system/primitives/DsHeading.vue'
|
||||
import DsText from '@root/design-system/primitives/DsText.vue'
|
||||
import DsMedia from '@root/design-system/primitives/DsMedia.vue'
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
const saisonFiltre = computed(() => String(runtimeConfig.public.saison || '').trim())
|
||||
const artistesFilters = computed(() => {
|
||||
if (!saisonFiltre.value) return null
|
||||
return {
|
||||
saisons_artiste_ondif: {
|
||||
nom_saison: {
|
||||
$eq: saisonFiltre.value,
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
//--------------------
|
||||
// DONNÉES POUR LES ARTISTES
|
||||
//--------------------
|
||||
const { items: artistes, pending, error } = useStrapi(
|
||||
"/api/__strapi__/artistes",
|
||||
{
|
||||
locale: "fr-FR",
|
||||
sort: "ordre_artiste_ondif:asc",
|
||||
populate: {
|
||||
saisons_artiste_ondif: true,
|
||||
image_illustration_artiste_ondif: true,
|
||||
postes_artiste_ondif: true,
|
||||
},
|
||||
filters: artistesFilters,
|
||||
}
|
||||
)
|
||||
|
||||
const artistesDisplay = computed(() => {
|
||||
return (artistes.value || []).map((artiste) => ({
|
||||
...artiste,
|
||||
image: getArtisteImage(artiste),
|
||||
postesLabel: getPostesLabel(artiste),
|
||||
}))
|
||||
})
|
||||
|
||||
const postesDirection = [
|
||||
"direction",
|
||||
"cheffe assistante",
|
||||
"chef assistante",
|
||||
]
|
||||
|
||||
const artistesDirection = computed(() =>
|
||||
artistesDisplay.value.filter((a) => isDirectionArtist(a))
|
||||
)
|
||||
|
||||
const artistesAutres = computed(() =>
|
||||
artistesDisplay.value.filter((a) => !isDirectionArtist(a))
|
||||
)
|
||||
|
||||
function getArtisteImage(artiste) {
|
||||
const media = artiste?.image_illustration_artiste_ondif
|
||||
const rows = extractStrapiList(media)
|
||||
if (rows.length) return rows[0]
|
||||
if (media && typeof media === "object" && media.url) return media
|
||||
return null
|
||||
}
|
||||
|
||||
function getPostesLabel(artiste) {
|
||||
const postes = extractStrapiList(artiste?.postes_artiste_ondif)
|
||||
return postes
|
||||
.map((p) => p?.nom_poste)
|
||||
.filter(Boolean)
|
||||
.join(", ")
|
||||
}
|
||||
|
||||
function isDirectionArtist(artiste) {
|
||||
const postes = extractStrapiList(artiste?.postes_artiste_ondif)
|
||||
.map((p) => String(p?.nom_poste || "").trim().toLowerCase())
|
||||
.filter(Boolean)
|
||||
|
||||
return postes.some((poste) => postesDirection.includes(poste))
|
||||
}
|
||||
|
||||
function extractStrapiList(value) {
|
||||
if (!value) return []
|
||||
if (Array.isArray(value)) return value.map(normalizeStrapiItem).filter(Boolean)
|
||||
if (value?.data) {
|
||||
const rows = Array.isArray(value.data) ? value.data : [value.data]
|
||||
return rows.map(normalizeStrapiItem).filter(Boolean)
|
||||
}
|
||||
if (typeof value === "object") return [normalizeStrapiItem(value)].filter(Boolean)
|
||||
return []
|
||||
}
|
||||
|
||||
function normalizeStrapiItem(item) {
|
||||
if (!item || typeof item !== "object") return null
|
||||
if (item.attributes && typeof item.attributes === "object") {
|
||||
return { id: item.id, ...item.attributes }
|
||||
}
|
||||
return item
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
<style lang="scss">
|
||||
|
||||
</style>
|
||||
|
||||
.remonter_artistes_list {
|
||||
transform: translateY(-90px);
|
||||
}
|
||||
|
||||
.theme_bandeau--grid {
|
||||
> .page-section--inner {
|
||||
padding-top: 70px;
|
||||
padding-bottom: 150px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
column-gap: 120px;
|
||||
row-gap: 30px;
|
||||
}
|
||||
&--left {
|
||||
max-width: 40%;
|
||||
h1 {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
}
|
||||
&--right {
|
||||
max-width: 60%;
|
||||
&--text {
|
||||
max-width: 500px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.musiciens_list_wp {
|
||||
// parce que le bloc du dessus à un transform: translateY(-170px); alors cela laisse un espace vide que l'on comble avec ce margin-top négatif
|
||||
margin-top: -120px;
|
||||
}
|
||||
.musiciens_list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 28px;
|
||||
}
|
||||
|
||||
.musicien_card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.musicien_card_media-placeholder {
|
||||
width: 100%;
|
||||
aspect-ratio: 1 / 1;
|
||||
background: rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
.musicien_card_nom {
|
||||
margin-top: 8px;
|
||||
margin-left: 5px;
|
||||
&:hover {
|
||||
color: var(--c-brand_rouge);
|
||||
}
|
||||
}
|
||||
.musicien_card_postes {
|
||||
margin-left: 5px;
|
||||
text-transform: lowercase;
|
||||
&::first-letter {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@media (max-width: 980px) {
|
||||
.musiciens_list {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 400px) {
|
||||
.musiciens_list {
|
||||
grid-template-columns: 1fr;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.musiciens_list {
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script setup>
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script setup>
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<template>
|
||||
<div class="ds-media" :class="`ds-media--${ratio}`">
|
||||
<div class="ds-media" :class="[`ds-media--${ratio}`]">
|
||||
<img
|
||||
class="ds-media__img"
|
||||
:class="[`ds-media__img--${fit}`]"
|
||||
:src="src"
|
||||
:alt="alt"
|
||||
loading="lazy"
|
||||
@@ -14,25 +15,29 @@
|
||||
defineProps({
|
||||
src: { type: String, required: true },
|
||||
alt: { type: String, default: '' },
|
||||
fit: { type: String, default: 'cover' },
|
||||
ratio: { type: String, default: '' }, // 16-9 / 4-3 / square
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.ds-media {
|
||||
width: 100%;
|
||||
background: rgba(0,0,0,0.04);
|
||||
overflow: hidden;
|
||||
&--16-9 { aspect-ratio: 16 / 9; }
|
||||
&--4-3 { aspect-ratio: 4 / 3; }
|
||||
&--3-4 { aspect-ratio: 3 / 4; }
|
||||
&--square { aspect-ratio: 1 / 1; }
|
||||
|
||||
.ds-media__img {
|
||||
.ds-media {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
background: rgba(0,0,0,0.04);
|
||||
overflow: hidden;
|
||||
&--16-9 { aspect-ratio: 16 / 9; }
|
||||
&--4-3 { aspect-ratio: 4 / 3; }
|
||||
&--3-4 { aspect-ratio: 3 / 4; }
|
||||
&--square { aspect-ratio: 1 / 1; }
|
||||
|
||||
.ds-media__img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
&--cover { object-fit:cover; }
|
||||
&--contain { object-fit:contain; }
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
</style>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
`ds-text--${props.weight || resolvedWeight}`, //si la classe weight n'est pas donné dans la classe on prend la mapping par défaut
|
||||
`ds-text--${props.spacing || resolvedspacing}`,
|
||||
`ds-text--${props.tone}`,
|
||||
`ds-text--${props.align}`,
|
||||
props.clamp ? `ds-text--clamp_${props.clamp}` : '',
|
||||
]"
|
||||
>
|
||||
@@ -25,6 +26,7 @@
|
||||
spacing: { type: String, default: '' },
|
||||
tone: { type: String, default: 'default' }, // default/muted/invert
|
||||
weight: { type: String, default: 'regular' }, // regular/medium
|
||||
align: { type: String, default: '' },
|
||||
clamp: { type: Number, default: undefined }, // nombre de lignes du contenu
|
||||
})
|
||||
|
||||
@@ -113,6 +115,10 @@
|
||||
&--bleu_fonce { color: var(--c-bleu_fonce); }
|
||||
&--bleu_clair { color: var(--c-bleu_clair); }
|
||||
|
||||
&--justify {
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
// clampé sur 2 lignes pour les cartes (résumé, programme, etc.).
|
||||
// Si ça dépasse, ça coupe proprement. Pour du texte de description qui doit tenir dans un cadre, mais qui a été écrit trop long, pour ne pas casser le design du site, on va limiter l'affichage à 2 lignes. c'est pour des espace réduit. Pour ne pas casser le design de la page. J'ai presque écrit 2 lignes, je vais bientôt être censurée.
|
||||
&--clamp_3 {
|
||||
|
||||
@@ -9,11 +9,13 @@
|
||||
/* Marque / accent (ex: rouge ONDIF) */
|
||||
//--c-brand_rouge: #E30613;
|
||||
--c-brand_rouge: #E20018;
|
||||
--c-brand_rouge45: rgba(226, 0, 24, 0.45);
|
||||
--c-brand_rouge45: #e2001873;
|
||||
--c-brand_rouge-weak: #e3061391;
|
||||
--c-backgroud-black: #111;
|
||||
--c-backgroud-brandreverse: #ACCFCF;
|
||||
--c-background-blanc-casse: #FCFCFC;
|
||||
--c-background-jaune: #fac020;
|
||||
--c-background-bleu: #002b95;
|
||||
|
||||
/* États */
|
||||
--c-success: green;
|
||||
|
||||
@@ -14,6 +14,7 @@ module.exports = {
|
||||
// Auto-mapping Nuxt runtimeConfig.strapiToken
|
||||
// (si tu l'utilises vraiment)
|
||||
NUXT_STRAPI_TOKEN: "",
|
||||
NUXT_PUBLIC_SAISON: "2025/2026"
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -55,6 +55,7 @@ export default defineNuxtConfig({
|
||||
// lit implicitement la variables .env process.env.NUXT_PUBLIC_STRAPI_URL
|
||||
public: {
|
||||
strapiUrl: '',
|
||||
saison: '',
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
24
server/api/__strapi__/[collection].get.js
Normal file
24
server/api/__strapi__/[collection].get.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import { createError, getRouterParam } from "h3"
|
||||
import { createStrapiProxyHandler } from "~~/server/utils/strapiEndpoint"
|
||||
|
||||
const COLLECTION_MAP = {
|
||||
artistes: "/api/artistes-ondifs",
|
||||
artistesinvitees: "/api/artistes-invites",
|
||||
concerts: "/api/concerts",
|
||||
missions: "/api/mission",
|
||||
mission: "/api/mission",
|
||||
}
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const collection = getRouterParam(event, "collection")
|
||||
const strapiPath = COLLECTION_MAP[collection]
|
||||
|
||||
if (!strapiPath) {
|
||||
throw createError({
|
||||
statusCode: 404,
|
||||
statusMessage: "Unknown Strapi collection",
|
||||
})
|
||||
}
|
||||
|
||||
return createStrapiProxyHandler({ strapiPath })(event)
|
||||
})
|
||||
7
server/api/__strapi__/asuppr_artistes.get.js
Normal file
7
server/api/__strapi__/asuppr_artistes.get.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import { createStrapiProxyHandler } from "~~/server/utils/strapiEndpoint"
|
||||
|
||||
export default defineEventHandler(
|
||||
createStrapiProxyHandler({
|
||||
strapiPath: "/api/artistes-ondifs",
|
||||
})
|
||||
)
|
||||
7
server/api/__strapi__/asuppr_artistesinvitees.get.js
Normal file
7
server/api/__strapi__/asuppr_artistesinvitees.get.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import { createStrapiProxyHandler } from "~~/server/utils/strapiEndpoint"
|
||||
|
||||
export default defineEventHandler(
|
||||
createStrapiProxyHandler({
|
||||
strapiPath: "/api/artistes-invites",
|
||||
})
|
||||
)
|
||||
Reference in New Issue
Block a user