Compare commits
No commits in common. "261323b4ce144bf5d93e5d24d9e27f3044cab0fd" and "d82e51c4c9871753e335ddf00708a2e86a13e2c2" have entirely different histories.
261323b4ce
...
d82e51c4c9
50 changed files with 135 additions and 186 deletions
|
|
@ -4,7 +4,6 @@ import tailwind from "@astrojs/tailwind";
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
devToolbar: { enabled: false },
|
|
||||||
integrations: [tailwind()],
|
integrations: [tailwind()],
|
||||||
i18n: {
|
i18n: {
|
||||||
defaultLocale: "fr",
|
defaultLocale: "fr",
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,6 @@ const categories = sortedCategories.map(cat => ({ id: cat.id, title: cat.data.ti
|
||||||
<HomeIcon size={16} />
|
<HomeIcon size={16} />
|
||||||
<span class="site-name">Jalil Arfaoui</span>
|
<span class="site-name">Jalil Arfaoui</span>
|
||||||
</a>
|
</a>
|
||||||
<span class="nav-separator"></span>
|
|
||||||
<a href="/photo" class="nav-link">Photo</a>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Bouton hamburger (mobile) -->
|
<!-- Bouton hamburger (mobile) -->
|
||||||
|
|
@ -71,13 +69,6 @@ const categories = sortedCategories.map(cat => ({ id: cat.id, title: cat.data.ti
|
||||||
height: 53px;
|
height: 53px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.site-title {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 10px;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.site-link {
|
.site-link {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
@ -93,11 +84,6 @@ const categories = sortedCategories.map(cat => ({ id: cat.id, title: cat.data.ti
|
||||||
color: rgba(255, 255, 255, 0.8);
|
color: rgba(255, 255, 255, 0.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
.site-title .nav-link {
|
|
||||||
padding-bottom: 0;
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger {
|
.hamburger {
|
||||||
display: none;
|
display: none;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
@ -207,14 +193,14 @@ const categories = sortedCategories.map(cat => ({ id: cat.id, title: cat.data.ti
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-menu .nav-link {
|
.nav-link {
|
||||||
display: block;
|
display: block;
|
||||||
padding: 15px 20px;
|
padding: 15px 20px;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-menu .nav-link.active {
|
.nav-link.active {
|
||||||
background: rgba(255, 255, 255, 0.1);
|
background: rgba(255, 255, 255, 0.1);
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
|
|
@ -234,8 +220,7 @@ const categories = sortedCategories.map(cat => ({ id: cat.id, title: cat.data.ti
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 480px) {
|
@media (max-width: 480px) {
|
||||||
.site-name,
|
.site-name {
|
||||||
.site-title .nav-separator {
|
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
<footer class="photo-footer">
|
|
||||||
<div class="photo-footer-inner">
|
|
||||||
<div class="photo-footer-links">
|
|
||||||
<a href="/a-propos">À propos</a>
|
|
||||||
<a href="mailto:jalil@arfaoui.net">Contact</a>
|
|
||||||
<a href="https://instagram.com/l.i.l.a.j" target="_blank" rel="noopener noreferrer">Instagram</a>
|
|
||||||
</div>
|
|
||||||
<div class="photo-footer-copy">
|
|
||||||
© Jalil Arfaoui <a href="https://creativecommons.org/licenses/by-nc/4.0/" target="_blank" rel="noopener noreferrer">Creative Commons CC-BY-NC 4.0</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.photo-footer {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
z-index: 40;
|
|
||||||
background: rgba(0, 0, 0, 0.3);
|
|
||||||
backdrop-filter: blur(8px);
|
|
||||||
transition: transform 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.photo-footer-inner {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0 20px;
|
|
||||||
height: 54px;
|
|
||||||
font-size: 16px;
|
|
||||||
color: rgba(255, 255, 255, 0.7);
|
|
||||||
}
|
|
||||||
|
|
||||||
.photo-footer-links {
|
|
||||||
display: flex;
|
|
||||||
gap: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.photo-footer-links a,
|
|
||||||
.photo-footer-copy,
|
|
||||||
.photo-footer-copy a {
|
|
||||||
color: rgba(255, 255, 255, 0.7);
|
|
||||||
text-decoration: none;
|
|
||||||
transition: color 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.photo-footer-links a:hover,
|
|
||||||
.photo-footer-copy a:hover {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 640px) {
|
|
||||||
.photo-footer-inner {
|
|
||||||
flex-direction: column;
|
|
||||||
height: auto;
|
|
||||||
padding: 10px 20px;
|
|
||||||
gap: 4px;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -72,7 +72,7 @@
|
||||||
.prev-btn,
|
.prev-btn,
|
||||||
.next-btn {
|
.next-btn {
|
||||||
top: auto;
|
top: auto;
|
||||||
bottom: 5rem;
|
bottom: 2rem;
|
||||||
transform: none;
|
transform: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,11 +67,11 @@ const talksCollection = defineCollection({
|
||||||
|
|
||||||
const photoBlogPostsCollection = defineCollection({
|
const photoBlogPostsCollection = defineCollection({
|
||||||
type: "content",
|
type: "content",
|
||||||
schema: z.object({
|
schema: ({ image }) => z.object({
|
||||||
title: z.string(),
|
title: z.string(),
|
||||||
description: z.string(),
|
description: z.string(),
|
||||||
date: z.date(),
|
date: z.date(),
|
||||||
coverImage: z.string(),
|
coverImage: image(),
|
||||||
tags: z.array(z.string()).optional(),
|
tags: z.array(z.string()).optional(),
|
||||||
featured: z.boolean().default(false),
|
featured: z.boolean().default(false),
|
||||||
draft: z.boolean().default(false),
|
draft: z.boolean().default(false),
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ description: |
|
||||||
|
|
||||||
تغطية.
|
تغطية.
|
||||||
date: 2015-04-25
|
date: 2015-04-25
|
||||||
coverImage: "01-Enigma-v1.jpg"
|
coverImage: "../../assets/images/photos/blog/enigma/01-Enigma-v1.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -5,7 +5,7 @@ description: |
|
||||||
|
|
||||||
Recap.
|
Recap.
|
||||||
date: 2015-04-25
|
date: 2015-04-25
|
||||||
coverImage: "01-Enigma-v1.jpg"
|
coverImage: "../../assets/images/photos/blog/enigma/01-Enigma-v1.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -5,7 +5,7 @@ description: |
|
||||||
|
|
||||||
Récap.
|
Récap.
|
||||||
date: 2015-04-25
|
date: 2015-04-25
|
||||||
coverImage: "11-Enigma-v1-11.jpg"
|
coverImage: "../../assets/images/photos/blog/enigma/11-Enigma-v1-11.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "تصوير إيرول"
|
title: "تصوير إيرول"
|
||||||
description: "أراد إيرول صورًا له لإعداد كتاب أعمال. عملنا طوال اليوم لتنويع الأجواء..."
|
description: "أراد إيرول صورًا له لإعداد كتاب أعمال. عملنا طوال اليوم لتنويع الأجواء..."
|
||||||
date: 2011-10-02
|
date: 2011-10-02
|
||||||
coverImage: "18-Eroll-Shooting-1-19.jpg"
|
coverImage: "../../assets/images/photos/blog/eroll/18-Eroll-Shooting-1-19.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Shooting Eroll"
|
title: "Shooting Eroll"
|
||||||
description: "Eroll wanted some photos of him in order to have a modeling book. We worked all day in order to have some ambiance variations..."
|
description: "Eroll wanted some photos of him in order to have a modeling book. We worked all day in order to have some ambiance variations..."
|
||||||
date: 2011-10-02
|
date: 2011-10-02
|
||||||
coverImage: "18-Eroll-Shooting-1-19.jpg"
|
coverImage: "../../assets/images/photos/blog/eroll/18-Eroll-Shooting-1-19.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Shooting Eroll"
|
title: "Shooting Eroll"
|
||||||
description: "Eroll voulait des photos de lui pour constituer un book. On a travaillé toute la journée pour varier les ambiances..."
|
description: "Eroll voulait des photos de lui pour constituer un book. On a travaillé toute la journée pour varier les ambiances..."
|
||||||
date: 2011-10-02
|
date: 2011-10-02
|
||||||
coverImage: "18-Eroll-Shooting-1-19.jpg"
|
coverImage: "../../assets/images/photos/blog/eroll/18-Eroll-Shooting-1-19.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Field of Stones"
|
title: "Field of Stones"
|
||||||
description: "كواليس تصوير غلاف ألبوم ماركو وولتر. أراد أن تُلتقط الصورة في سينماتيك طنجة. لا وقت، لا إضاءة، لكن لا خيار. حاولنا تقديم أفضل ما لدينا..."
|
description: "كواليس تصوير غلاف ألبوم ماركو وولتر. أراد أن تُلتقط الصورة في سينماتيك طنجة. لا وقت، لا إضاءة، لكن لا خيار. حاولنا تقديم أفضل ما لدينا..."
|
||||||
date: 2015-04-02
|
date: 2015-04-02
|
||||||
coverImage: "01-Marco-Wolter-Field-of-Stones-2.jpg"
|
coverImage: "../../assets/images/photos/blog/field-of-stones/01-Marco-Wolter-Field-of-Stones-2.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Field of Stones"
|
title: "Field of Stones"
|
||||||
description: "Making of the album cover for Marco Wolter. He wanted it to be shot in the Cinémathèque of Tangier. We had no time, no light, but no choice. We tried to make the best of it..."
|
description: "Making of the album cover for Marco Wolter. He wanted it to be shot in the Cinémathèque of Tangier. We had no time, no light, but no choice. We tried to make the best of it..."
|
||||||
date: 2015-04-02
|
date: 2015-04-02
|
||||||
coverImage: "01-Marco-Wolter-Field-of-Stones-2.jpg"
|
coverImage: "../../assets/images/photos/blog/field-of-stones/01-Marco-Wolter-Field-of-Stones-2.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Field of Stones"
|
title: "Field of Stones"
|
||||||
description: "Making of de la pochette de l'album de Marco Wolter. Il voulait que la photo soit prise à la Cinémathèque de Tanger. Pas de temps, pas de lumière, mais pas le choix. On a fait au mieux..."
|
description: "Making of de la pochette de l'album de Marco Wolter. Il voulait que la photo soit prise à la Cinémathèque de Tanger. Pas de temps, pas de lumière, mais pas le choix. On a fait au mieux..."
|
||||||
date: 2015-04-02
|
date: 2015-04-02
|
||||||
coverImage: "01-Marco-Wolter-Field-of-Stones-2.jpg"
|
coverImage: "../../assets/images/photos/blog/field-of-stones/01-Marco-Wolter-Field-of-Stones-2.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "هلسنكي"
|
title: "هلسنكي"
|
||||||
description: "اختفى الثلج من هلسنكي وسرعان ما أفسح المجال للربيع..."
|
description: "اختفى الثلج من هلسنكي وسرعان ما أفسح المجال للربيع..."
|
||||||
date: 2013-05-15
|
date: 2013-05-15
|
||||||
coverImage: "01-Library-of-University-of-Helsinki.jpg"
|
coverImage: "../../assets/images/photos/blog/helsinki/01-Library-of-University-of-Helsinki.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Helsinki"
|
title: "Helsinki"
|
||||||
description: "The snow has disappeared from Helsinki and quickly gave way to spring..."
|
description: "The snow has disappeared from Helsinki and quickly gave way to spring..."
|
||||||
date: 2013-05-15
|
date: 2013-05-15
|
||||||
coverImage: "01-Library-of-University-of-Helsinki.jpg"
|
coverImage: "../../assets/images/photos/blog/helsinki/01-Library-of-University-of-Helsinki.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Helsinki"
|
title: "Helsinki"
|
||||||
description: "La neige a disparu d'Helsinki et a vite laissé place au printemps..."
|
description: "La neige a disparu d'Helsinki et a vite laissé place au printemps..."
|
||||||
date: 2013-05-15
|
date: 2013-05-15
|
||||||
coverImage: "01-Library-of-University-of-Helsinki.jpg"
|
coverImage: "../../assets/images/photos/blog/helsinki/01-Library-of-University-of-Helsinki.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "نزهة في إفران"
|
title: "نزهة في إفران"
|
||||||
description: "نزهة شتوية في جبال الأطلس المتوسط."
|
description: "نزهة شتوية في جبال الأطلس المتوسط."
|
||||||
date: 2013-01-13
|
date: 2013-01-13
|
||||||
coverImage: "03-3.jpg"
|
coverImage: "../../assets/images/photos/blog/ifrane-hike/03-3.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Ifrane Hike"
|
title: "Ifrane Hike"
|
||||||
description: "Winter hike in the Middle Atlas mountains."
|
description: "Winter hike in the Middle Atlas mountains."
|
||||||
date: 2013-01-13
|
date: 2013-01-13
|
||||||
coverImage: "03-3.jpg"
|
coverImage: "../../assets/images/photos/blog/ifrane-hike/03-3.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Randonnée à Ifrane"
|
title: "Randonnée à Ifrane"
|
||||||
description: "Randonnée hivernale dans les montagnes du Moyen Atlas"
|
description: "Randonnée hivernale dans les montagnes du Moyen Atlas"
|
||||||
date: 2013-01-13
|
date: 2013-01-13
|
||||||
coverImage: "03-3.jpg"
|
coverImage: "../../assets/images/photos/blog/ifrane-hike/03-3.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Inox Park Paris 2011"
|
title: "Inox Park Paris 2011"
|
||||||
description: "بعد نجاحه في 2010، يعود مهرجان Inox Park Paris إلى جزيرة شاتو في نسخته الثانية. ثلاث مسارح، 15 دي جي، 12 ساعة من الحفل في الهواء الطلق: Tiësto، Joachim Garraud، Sven Väth، Steve Aoki..."
|
description: "بعد نجاحه في 2010، يعود مهرجان Inox Park Paris إلى جزيرة شاتو في نسخته الثانية. ثلاث مسارح، 15 دي جي، 12 ساعة من الحفل في الهواء الطلق: Tiësto، Joachim Garraud، Sven Väth، Steve Aoki..."
|
||||||
date: 2011-09-10
|
date: 2011-09-10
|
||||||
coverImage: "01-Inox-Park-Paris-Chatou-2011.jpg"
|
coverImage: "../../assets/images/photos/blog/inox-park-2011/01-Inox-Park-Paris-Chatou-2011.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Inox Park Paris 2011"
|
title: "Inox Park Paris 2011"
|
||||||
description: "After its 2010 success, the Inox Park Paris Electro Festival is back to the island of Chatou for its second edition. Three stages, 15 DJs, 12 hours of outdoor party: Tiësto, Joachim Garraud, Sven Väth, Steve Aoki..."
|
description: "After its 2010 success, the Inox Park Paris Electro Festival is back to the island of Chatou for its second edition. Three stages, 15 DJs, 12 hours of outdoor party: Tiësto, Joachim Garraud, Sven Väth, Steve Aoki..."
|
||||||
date: 2011-09-10
|
date: 2011-09-10
|
||||||
coverImage: "01-Inox-Park-Paris-Chatou-2011.jpg"
|
coverImage: "../../assets/images/photos/blog/inox-park-2011/01-Inox-Park-Paris-Chatou-2011.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Inox Park Paris 2011"
|
title: "Inox Park Paris 2011"
|
||||||
description: "Après son succès de 2010, le festival Inox Park Paris revient sur l'île de Chatou pour sa deuxième édition. Trois scènes, 15 DJs, 12 heures de fête en plein air : Tiësto, Joachim Garraud, Sven Väth, Steve Aoki..."
|
description: "Après son succès de 2010, le festival Inox Park Paris revient sur l'île de Chatou pour sa deuxième édition. Trois scènes, 15 DJs, 12 heures de fête en plein air : Tiësto, Joachim Garraud, Sven Väth, Steve Aoki..."
|
||||||
date: 2011-09-10
|
date: 2011-09-10
|
||||||
coverImage: "10-Inox-Park-Paris-Chatou-2011-7.jpg"
|
coverImage: "../../assets/images/photos/blog/inox-park-2011/10-Inox-Park-Paris-Chatou-2011-7.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "London Calling"
|
title: "London Calling"
|
||||||
description: "عطلة نهاية أسبوع فوتوغرافية في لندن."
|
description: "عطلة نهاية أسبوع فوتوغرافية في لندن."
|
||||||
date: 2014-07-15
|
date: 2014-07-15
|
||||||
coverImage: "01-The-sky-inside.jpg"
|
coverImage: "../../assets/images/photos/blog/london-calling/01-The-sky-inside.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "London Calling"
|
title: "London Calling"
|
||||||
description: "A photographic weekend in London."
|
description: "A photographic weekend in London."
|
||||||
date: 2014-07-15
|
date: 2014-07-15
|
||||||
coverImage: "01-The-sky-inside.jpg"
|
coverImage: "../../assets/images/photos/blog/london-calling/01-The-sky-inside.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "London Calling"
|
title: "London Calling"
|
||||||
description: "Week-end photographique à Londres"
|
description: "Week-end photographique à Londres"
|
||||||
date: 2014-07-15
|
date: 2014-07-15
|
||||||
coverImage: "01-The-sky-inside.jpg"
|
coverImage: "../../assets/images/photos/blog/london-calling/01-The-sky-inside.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "لا رياح في لاس كويفاس"
|
title: "لا رياح في لاس كويفاس"
|
||||||
description: "كان من المفترض أن يكون يومًا مثاليًا لتطيير طائرتنا الورقية: مشمس وعاصف. مشمس كان، لكن الرياح لم تأتِ أبدًا."
|
description: "كان من المفترض أن يكون يومًا مثاليًا لتطيير طائرتنا الورقية: مشمس وعاصف. مشمس كان، لكن الرياح لم تأتِ أبدًا."
|
||||||
date: 2015-01-10
|
date: 2015-01-10
|
||||||
coverImage: "13-No-wind-at-Las-Cuevas.jpg"
|
coverImage: "../../assets/images/photos/blog/no-wind-las-cuevas/13-No-wind-at-Las-Cuevas.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "No Wind at Las Cuevas"
|
title: "No Wind at Las Cuevas"
|
||||||
description: "It was supposed to be a perfect day for flying our kite: sunny and windy. Sunny it was, but the wind never came."
|
description: "It was supposed to be a perfect day for flying our kite: sunny and windy. Sunny it was, but the wind never came."
|
||||||
date: 2015-01-10
|
date: 2015-01-10
|
||||||
coverImage: "13-No-wind-at-Las-Cuevas.jpg"
|
coverImage: "../../assets/images/photos/blog/no-wind-las-cuevas/13-No-wind-at-Las-Cuevas.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Pas de vent à Las Cuevas"
|
title: "Pas de vent à Las Cuevas"
|
||||||
description: "Ça devait être une journée parfaite pour faire voler notre cerf-volant : ensoleillée et venteuse. Ensoleillée, oui. Mais le vent n'est jamais venu."
|
description: "Ça devait être une journée parfaite pour faire voler notre cerf-volant : ensoleillée et venteuse. Ensoleillée, oui. Mais le vent n'est jamais venu."
|
||||||
date: 2015-01-10
|
date: 2015-01-10
|
||||||
coverImage: "13-No-wind-at-Las-Cuevas.jpg"
|
coverImage: "../../assets/images/photos/blog/no-wind-las-cuevas/13-No-wind-at-Las-Cuevas.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "عملية المحفظة 2012"
|
title: "عملية المحفظة 2012"
|
||||||
description: "توزيع محافظ مدرسية مجانية في مدارس محرومة من طرف جمعية محلية (JCI)، طنجة، المغرب."
|
description: "توزيع محافظ مدرسية مجانية في مدارس محرومة من طرف جمعية محلية (JCI)، طنجة، المغرب."
|
||||||
date: 2012-09-30
|
date: 2012-09-30
|
||||||
coverImage: "35-Moroccan-Schoolgirls.jpg"
|
coverImage: "../../assets/images/photos/blog/schoolbag-operation-2012/35-Moroccan-Schoolgirls.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Schoolbag Operation 2012"
|
title: "Schoolbag Operation 2012"
|
||||||
description: "During a distribution of free schoolbags in poor schools by a local association (JCI), Tangier, Morocco."
|
description: "During a distribution of free schoolbags in poor schools by a local association (JCI), Tangier, Morocco."
|
||||||
date: 2012-09-30
|
date: 2012-09-30
|
||||||
coverImage: "35-Moroccan-Schoolgirls.jpg"
|
coverImage: "../../assets/images/photos/blog/schoolbag-operation-2012/35-Moroccan-Schoolgirls.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Opération Cartable 2012"
|
title: "Opération Cartable 2012"
|
||||||
description: "Distribution gratuite de cartables dans des écoles défavorisées par une association locale (JCI), Tanger, Maroc."
|
description: "Distribution gratuite de cartables dans des écoles défavorisées par une association locale (JCI), Tanger, Maroc."
|
||||||
date: 2012-09-30
|
date: 2012-09-30
|
||||||
coverImage: "35-Moroccan-Schoolgirls.jpg"
|
coverImage: "../../assets/images/photos/blog/schoolbag-operation-2012/35-Moroccan-Schoolgirls.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "أحد سيكواني"
|
title: "أحد سيكواني"
|
||||||
description: "نزهة يوم أحد على ضفاف نهر السين."
|
description: "نزهة يوم أحد على ضفاف نهر السين."
|
||||||
date: 2014-05-18
|
date: 2014-05-18
|
||||||
coverImage: "04-La-Defense-seen-from-Pont-de-Suresnes-2.jpg"
|
coverImage: "../../assets/images/photos/blog/sequanian-sunday/04-La-Defense-seen-from-Pont-de-Suresnes-2.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Sequanian Sunday"
|
title: "Sequanian Sunday"
|
||||||
description: "A sunday walk near the Seine."
|
description: "A sunday walk near the Seine."
|
||||||
date: 2014-05-18
|
date: 2014-05-18
|
||||||
coverImage: "04-La-Defense-seen-from-Pont-de-Suresnes-2.jpg"
|
coverImage: "../../assets/images/photos/blog/sequanian-sunday/04-La-Defense-seen-from-Pont-de-Suresnes-2.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Dimanche Séquanais"
|
title: "Dimanche Séquanais"
|
||||||
description: "Balade dominicale au bord de la Seine."
|
description: "Balade dominicale au bord de la Seine."
|
||||||
date: 2014-05-18
|
date: 2014-05-18
|
||||||
coverImage: "04-La-Defense-seen-from-Pont-de-Suresnes-2.jpg"
|
coverImage: "../../assets/images/photos/blog/sequanian-sunday/04-La-Defense-seen-from-Pont-de-Suresnes-2.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "جولة في طنجة"
|
title: "جولة في طنجة"
|
||||||
description: "جولة فوتوغرافية في شوارع طنجة."
|
description: "جولة فوتوغرافية في شوارع طنجة."
|
||||||
date: 2012-05-26
|
date: 2012-05-26
|
||||||
coverImage: "01-Observer-le-changement.jpg"
|
coverImage: "../../assets/images/photos/blog/tangier-walk/01-Observer-le-changement.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Tangier Walk"
|
title: "Tangier Walk"
|
||||||
description: "A photographic walk through the streets of Tangier."
|
description: "A photographic walk through the streets of Tangier."
|
||||||
date: 2012-05-26
|
date: 2012-05-26
|
||||||
coverImage: "01-Observer-le-changement.jpg"
|
coverImage: "../../assets/images/photos/blog/tangier-walk/01-Observer-le-changement.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Balade à Tanger"
|
title: "Balade à Tanger"
|
||||||
description: "Promenade photographique dans les rues de Tanger"
|
description: "Promenade photographique dans les rues de Tanger"
|
||||||
date: 2012-05-26
|
date: 2012-05-26
|
||||||
coverImage: "01-Observer-le-changement.jpg"
|
coverImage: "../../assets/images/photos/blog/tangier-walk/01-Observer-le-changement.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: false
|
featured: false
|
||||||
draft: false
|
draft: false
|
||||||
12
src/content/photoBlogPosts/waiting-for-the-bride.ar.md
Normal file
12
src/content/photoBlogPosts/waiting-for-the-bride.ar.md
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
title: "في انتظار العروس"
|
||||||
|
description: "تحضيرات زفاف."
|
||||||
|
date: 2014-10-25
|
||||||
|
coverImage: "../../assets/images/photos/blog/waiting-for-the-bride/01-.jpg"
|
||||||
|
tags: []
|
||||||
|
featured: false
|
||||||
|
draft: false
|
||||||
|
lang: ar
|
||||||
|
---
|
||||||
|
|
||||||
|
تحضيرات زفاف.
|
||||||
12
src/content/photoBlogPosts/waiting-for-the-bride.en.md
Normal file
12
src/content/photoBlogPosts/waiting-for-the-bride.en.md
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
title: "Waiting for the Bride"
|
||||||
|
description: "Wedding preparations."
|
||||||
|
date: 2014-10-25
|
||||||
|
coverImage: "../../assets/images/photos/blog/waiting-for-the-bride/01-.jpg"
|
||||||
|
tags: []
|
||||||
|
featured: false
|
||||||
|
draft: false
|
||||||
|
lang: en
|
||||||
|
---
|
||||||
|
|
||||||
|
Wedding preparations.
|
||||||
11
src/content/photoBlogPosts/waiting-for-the-bride.md
Normal file
11
src/content/photoBlogPosts/waiting-for-the-bride.md
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
---
|
||||||
|
title: "En attendant la mariée"
|
||||||
|
description: "Préparatifs d'un mariage"
|
||||||
|
date: 2014-10-25
|
||||||
|
coverImage: "../../assets/images/photos/blog/waiting-for-the-bride/01-.jpg"
|
||||||
|
tags: []
|
||||||
|
featured: false
|
||||||
|
draft: false
|
||||||
|
---
|
||||||
|
|
||||||
|
Préparatifs d'un mariage.
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "تجوال في مدينة طنجة القديمة"
|
title: "تجوال في مدينة طنجة القديمة"
|
||||||
description: "أثناء التجوال في أزقة طنجة القديمة، صادفت ساعاتيًا، ونجّارًا، وقمرًا عملاقًا..."
|
description: "أثناء التجوال في أزقة طنجة القديمة، صادفت ساعاتيًا، ونجّارًا، وقمرًا عملاقًا..."
|
||||||
date: 2014-08-10
|
date: 2014-08-10
|
||||||
coverImage: "01-The-watchmaker.jpg"
|
coverImage: "../../assets/images/photos/blog/wandering-tangier-medina/01-The-watchmaker.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: true
|
featured: true
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Wandering Tangier Medina"
|
title: "Wandering Tangier Medina"
|
||||||
description: "Walking in the streets of the old Tangier, met a watchmaker, a carpenter and a super-moon..."
|
description: "Walking in the streets of the old Tangier, met a watchmaker, a carpenter and a super-moon..."
|
||||||
date: 2014-08-10
|
date: 2014-08-10
|
||||||
coverImage: "01-The-watchmaker.jpg"
|
coverImage: "../../assets/images/photos/blog/wandering-tangier-medina/01-The-watchmaker.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: true
|
featured: true
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Dans la médina de Tanger"
|
title: "Dans la médina de Tanger"
|
||||||
description: "En marchant dans les rues du vieux Tanger, j'ai croisé un horloger, un menuisier et une super-lune..."
|
description: "En marchant dans les rues du vieux Tanger, j'ai croisé un horloger, un menuisier et une super-lune..."
|
||||||
date: 2014-08-10
|
date: 2014-08-10
|
||||||
coverImage: "01-The-watchmaker.jpg"
|
coverImage: "../../assets/images/photos/blog/wandering-tangier-medina/01-The-watchmaker.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: true
|
featured: true
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "زفاف أورور وتوما"
|
title: "زفاف أورور وتوما"
|
||||||
description: "كان لي شرف ومتعة أن أكون شاهد توما في زفافه الجميل مع أورور. ليس سهلًا التصوير في نفس الوقت، لكن كل الصور مليئة بالحب."
|
description: "كان لي شرف ومتعة أن أكون شاهد توما في زفافه الجميل مع أورور. ليس سهلًا التصوير في نفس الوقت، لكن كل الصور مليئة بالحب."
|
||||||
date: 2015-09-26
|
date: 2015-09-26
|
||||||
coverImage: "10-Mariage-Aurore-Thomas-10.jpg"
|
coverImage: "../../assets/images/photos/blog/wedding-aurore-thomas/10-Mariage-Aurore-Thomas-10.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: true
|
featured: true
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Wedding Aurore & Thomas"
|
title: "Wedding Aurore & Thomas"
|
||||||
description: "I had the honor and pleasure to be Thomas' best man for his beautiful wedding with Aurore. Not easy to shoot pictures though, but all of them are filled with love."
|
description: "I had the honor and pleasure to be Thomas' best man for his beautiful wedding with Aurore. Not easy to shoot pictures though, but all of them are filled with love."
|
||||||
date: 2015-09-26
|
date: 2015-09-26
|
||||||
coverImage: "10-Mariage-Aurore-Thomas-10.jpg"
|
coverImage: "../../assets/images/photos/blog/wedding-aurore-thomas/10-Mariage-Aurore-Thomas-10.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: true
|
featured: true
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
title: "Mariage Aurore & Thomas"
|
title: "Mariage Aurore & Thomas"
|
||||||
description: "J'ai eu l'honneur et le plaisir d'être le témoin de Thomas pour son beau mariage avec Aurore. Pas facile de shooter en même temps, mais toutes les photos sont remplies d'amour."
|
description: "J'ai eu l'honneur et le plaisir d'être le témoin de Thomas pour son beau mariage avec Aurore. Pas facile de shooter en même temps, mais toutes les photos sont remplies d'amour."
|
||||||
date: 2015-09-26
|
date: 2015-09-26
|
||||||
coverImage: "10-Mariage-Aurore-Thomas-10.jpg"
|
coverImage: "../../assets/images/photos/blog/wedding-aurore-thomas/10-Mariage-Aurore-Thomas-10.jpg"
|
||||||
tags: []
|
tags: []
|
||||||
featured: true
|
featured: true
|
||||||
draft: false
|
draft: false
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
---
|
---
|
||||||
import PhotoFooter from '../components/photo/PhotoFooter.astro';
|
|
||||||
|
|
||||||
const { title = "Galerie Photo - Jalil Arfaoui", enableScroll = false } = Astro.props;
|
const { title = "Galerie Photo - Jalil Arfaoui", enableScroll = false } = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -27,7 +25,19 @@ const { title = "Galerie Photo - Jalil Arfaoui", enableScroll = false } = Astro.
|
||||||
<body class={`antialiased bg-black text-white ${enableScroll ? '' : 'overflow-hidden'}`} style="font-family: 'Karla', 'Helvetica Neue', Helvetica, Arial, sans-serif;">
|
<body class={`antialiased bg-black text-white ${enableScroll ? '' : 'overflow-hidden'}`} style="font-family: 'Karla', 'Helvetica Neue', Helvetica, Arial, sans-serif;">
|
||||||
<slot />
|
<slot />
|
||||||
|
|
||||||
<PhotoFooter />
|
<!-- Footer bandeau -->
|
||||||
|
<footer class="fixed bottom-0 left-0 right-0 z-40 bg-black/30 backdrop-blur-sm transition-transform duration-300">
|
||||||
|
<div class="flex justify-between items-center w-full" style="padding-left: 20px; padding-right: 20px; height: 54px; line-height: 54px;">
|
||||||
|
<div class="footer-left flex items-center text-white/70" style="font-size: 16px; font-weight: normal;">
|
||||||
|
<a href="/a-propos" class="hover:text-white transition-colors" style="margin-right: 15px;">À propos</a>
|
||||||
|
<a href="mailto:jalil@arfaoui.net" class="hover:text-white transition-colors" style="margin-right: 15px;">Contact</a>
|
||||||
|
<a href="https://instagram.com/l.i.l.a.j" target="_blank" rel="noopener noreferrer" class="hover:text-white transition-colors">Instagram</a>
|
||||||
|
</div>
|
||||||
|
<div class="footer-right text-white/70" style="font-size: 16px; font-weight: normal;">
|
||||||
|
© Jalil Arfaoui Creative Commons CC-BY-NC 4.0
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
<Fragment set:html={import.meta.env.FOOTER_INJECT} />
|
<Fragment set:html={import.meta.env.FOOTER_INJECT} />
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
---
|
---
|
||||||
import PhotoLayout from '../../../../layouts/PhotoLayout.astro';
|
import PhotoLayout from '../../../layouts/PhotoLayout.astro';
|
||||||
import CategoryNav from '../../../../components/photo/CategoryNav.astro';
|
import CategoryNav from '../../../components/photo/CategoryNav.astro';
|
||||||
import AlbumHeader from '../../../../components/photo/AlbumHeader.astro';
|
import AlbumHeader from '../../../components/photo/AlbumHeader.astro';
|
||||||
import MasonryGallery from '../../../../components/photo/MasonryGallery.astro';
|
import MasonryGallery from '../../../components/photo/MasonryGallery.astro';
|
||||||
import Lightbox from '../../../../components/photo/Lightbox.astro';
|
import Lightbox from '../../../components/photo/Lightbox.astro';
|
||||||
import { getCollection } from 'astro:content';
|
import { getCollection } from 'astro:content';
|
||||||
|
|
||||||
// Importer toutes les images du dossier photos
|
// Importer toutes les images du dossier photos
|
||||||
|
|
@ -11,37 +11,27 @@ const allImages = import.meta.glob<{ default: ImageMetadata }>('/src/assets/imag
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
const allPhotoBlogPosts = await getCollection('photoBlogPosts');
|
const allPhotoBlogPosts = await getCollection('photoBlogPosts');
|
||||||
return allPhotoBlogPosts.map(post => {
|
return allPhotoBlogPosts.map(post => ({
|
||||||
// Le slug Astro inclut le préfixe d'année (ex: "2015/enigma.en")
|
params: { slug: post.slug },
|
||||||
const slug = post.slug.replace(/^\d{4}\//, '');
|
props: { post },
|
||||||
return {
|
}));
|
||||||
params: {
|
|
||||||
year: String(post.data.date.getFullYear()),
|
|
||||||
slug,
|
|
||||||
},
|
|
||||||
props: { post },
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { post } = Astro.props;
|
const { post } = Astro.props;
|
||||||
const { Content } = await post.render();
|
const { Content } = await post.render();
|
||||||
|
|
||||||
// Slug de base sans préfixe d'année ni suffixe de langue (2015/enigma.en → enigma)
|
// coverImage est déjà un ImageMetadata grâce au schema image() dans config.ts
|
||||||
const baseSlug = post.slug.replace(/^\d{4}\//, '').replace(/\.(en|ar)$/, '');
|
const coverImage = post.data.coverImage;
|
||||||
|
|
||||||
// Construire le chemin de l'album avec l'année
|
// Slug de base sans suffixe de langue (enigma.en → enigma)
|
||||||
const year = post.data.date.getFullYear();
|
const baseSlug = post.slug.replace(/\.(en|ar)$/, '');
|
||||||
const albumPath = `/src/assets/images/photos/blog/${year}/${baseSlug}/`;
|
|
||||||
|
// Charger toutes les images du dossier correspondant au slug
|
||||||
|
const albumPath = `/src/assets/images/photos/blog/${baseSlug}/`;
|
||||||
const albumImages = Object.keys(allImages)
|
const albumImages = Object.keys(allImages)
|
||||||
.filter(path => path.startsWith(albumPath))
|
.filter(path => path.startsWith(albumPath))
|
||||||
.sort();
|
.sort();
|
||||||
|
|
||||||
// Résoudre la cover image depuis le glob
|
|
||||||
const coverPath = `/src/assets/images/photos/blog/${year}/${baseSlug}/${post.data.coverImage}`;
|
|
||||||
const coverImageLoader = allImages[coverPath];
|
|
||||||
const coverImage = coverImageLoader ? (await coverImageLoader()).default : undefined;
|
|
||||||
|
|
||||||
// Résoudre les images de la galerie
|
// Résoudre les images de la galerie
|
||||||
const galleryImages = await Promise.all(
|
const galleryImages = await Promise.all(
|
||||||
albumImages.map(async (imagePath) => {
|
albumImages.map(async (imagePath) => {
|
||||||
|
|
@ -125,4 +115,4 @@ const lightboxImages = galleryImages.map(img => ({
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
margin: 2em 0;
|
margin: 2em 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -4,11 +4,6 @@ import CategoryNav from '../../../components/photo/CategoryNav.astro';
|
||||||
import { getCollection } from 'astro:content';
|
import { getCollection } from 'astro:content';
|
||||||
import { Picture } from 'astro:assets';
|
import { Picture } from 'astro:assets';
|
||||||
|
|
||||||
// Importer toutes les images pour résoudre les cover images
|
|
||||||
const allImages = import.meta.glob<{ default: ImageMetadata }>(
|
|
||||||
'/src/assets/images/photos/blog/**/*.{jpg,jpeg,png,webp}'
|
|
||||||
);
|
|
||||||
|
|
||||||
// Récupération des posts photo (langue par défaut : FR)
|
// Récupération des posts photo (langue par défaut : FR)
|
||||||
const allPhotoBlogPosts = (await getCollection('photoBlogPosts'))
|
const allPhotoBlogPosts = (await getCollection('photoBlogPosts'))
|
||||||
.filter(post => (post.data.lang ?? 'fr') === 'fr');
|
.filter(post => (post.data.lang ?? 'fr') === 'fr');
|
||||||
|
|
@ -18,14 +13,10 @@ const sortedPosts = allPhotoBlogPosts.sort((a, b) =>
|
||||||
new Date(b.data.date).getTime() - new Date(a.data.date).getTime()
|
new Date(b.data.date).getTime() - new Date(a.data.date).getTime()
|
||||||
);
|
);
|
||||||
|
|
||||||
// Résoudre les cover images via le glob
|
// coverImage est déjà un ImageMetadata grâce au schema image() dans config.ts
|
||||||
const postsWithImages = await Promise.all(sortedPosts.map(async (post) => {
|
const postsWithImages = sortedPosts.map((post) => ({
|
||||||
const year = post.data.date.getFullYear();
|
...post,
|
||||||
const baseSlug = post.slug.replace(/^\d{4}\//, '').replace(/\.(en|ar)$/, '');
|
resolvedCoverImage: post.data.coverImage
|
||||||
const coverPath = `/src/assets/images/photos/blog/${year}/${baseSlug}/${post.data.coverImage}`;
|
|
||||||
const loader = allImages[coverPath];
|
|
||||||
const resolvedCoverImage = loader ? (await loader()).default : undefined;
|
|
||||||
return { ...post, resolvedCoverImage };
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Séparer les posts à la une des autres
|
// Séparer les posts à la une des autres
|
||||||
|
|
@ -50,6 +41,7 @@ const regularPosts = postsWithImages.filter(post => !post.data.featured);
|
||||||
<div class="post-content">
|
<div class="post-content">
|
||||||
<span class="post-badge">À la une</span>
|
<span class="post-badge">À la une</span>
|
||||||
<h2 class="post-title">{post.data.title}</h2>
|
<h2 class="post-title">{post.data.title}</h2>
|
||||||
|
<p class="post-description">{post.data.description}</p>
|
||||||
<time class="post-date">
|
<time class="post-date">
|
||||||
{new Date(post.data.date).toLocaleDateString('fr-FR', {
|
{new Date(post.data.date).toLocaleDateString('fr-FR', {
|
||||||
year: 'numeric',
|
year: 'numeric',
|
||||||
|
|
@ -77,6 +69,7 @@ const regularPosts = postsWithImages.filter(post => !post.data.featured);
|
||||||
<div class="post-overlay">
|
<div class="post-overlay">
|
||||||
<div class="overlay-content">
|
<div class="overlay-content">
|
||||||
<h3 class="post-title">{post.data.title}</h3>
|
<h3 class="post-title">{post.data.title}</h3>
|
||||||
|
<p class="post-subtitle">{post.data.description}</p>
|
||||||
<time class="post-date">
|
<time class="post-date">
|
||||||
{new Date(post.data.date).toLocaleDateString('fr-FR', {
|
{new Date(post.data.date).toLocaleDateString('fr-FR', {
|
||||||
year: 'numeric',
|
year: 'numeric',
|
||||||
|
|
@ -103,13 +96,15 @@ const regularPosts = postsWithImages.filter(post => !post.data.featured);
|
||||||
|
|
||||||
/* Section à la une */
|
/* Section à la une */
|
||||||
.featured-section {
|
.featured-section {
|
||||||
padding: 16px 16px 0;
|
padding: 40px 20px 60px;
|
||||||
|
max-width: 1600px;
|
||||||
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.featured-grid {
|
.featured-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
|
||||||
gap: 16px;
|
gap: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.featured-post {
|
.featured-post {
|
||||||
|
|
@ -146,10 +141,13 @@ const regularPosts = postsWithImages.filter(post => !post.data.featured);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
padding: 40px;
|
padding: 40px;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.featured-post .post-content {
|
.featured-post .post-content {
|
||||||
color: white;
|
color: white;
|
||||||
|
max-height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.post-badge {
|
.post-badge {
|
||||||
|
|
@ -167,7 +165,7 @@ const regularPosts = postsWithImages.filter(post => !post.data.featured);
|
||||||
.featured-post .post-title {
|
.featured-post .post-title {
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin: 0 0 4px 0;
|
margin: 0 0 12px 0;
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -184,20 +182,21 @@ const regularPosts = postsWithImages.filter(post => !post.data.featured);
|
||||||
}
|
}
|
||||||
|
|
||||||
.featured-post .post-date {
|
.featured-post .post-date {
|
||||||
display: block;
|
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Grille des posts */
|
/* Grille des posts */
|
||||||
.posts-grid {
|
.posts-grid {
|
||||||
padding: 16px 16px 100px;
|
padding: 0 20px 100px;
|
||||||
|
max-width: 1600px;
|
||||||
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-container {
|
.grid-container {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(4, 1fr);
|
grid-template-columns: repeat(4, 1fr);
|
||||||
gap: 16px;
|
gap: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.post-item {
|
.post-item {
|
||||||
|
|
@ -212,11 +211,6 @@ const regularPosts = postsWithImages.filter(post => !post.data.featured);
|
||||||
aspect-ratio: 3/2;
|
aspect-ratio: 3/2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.featured-post .post-link {
|
|
||||||
aspect-ratio: auto;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.post-link img {
|
.post-link img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
@ -227,19 +221,18 @@ const regularPosts = postsWithImages.filter(post => !post.data.featured);
|
||||||
|
|
||||||
.post-item .post-overlay {
|
.post-item .post-overlay {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
background: linear-gradient(to top, rgba(0,0,0,0.85) 0%, rgba(0,0,0,0.5) 25%, rgba(0,0,0,0) 50%);
|
background: linear-gradient(to top, rgba(0,0,0,0.8) 0%, rgba(0,0,0,0) 100%);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
padding: 12px 16px;
|
padding: 20px;
|
||||||
transition: background 0.3s ease;
|
transition: background 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.post-item:hover .post-overlay {
|
.post-item:hover .post-overlay {
|
||||||
background: linear-gradient(to top, rgba(0,0,0,0.95) 0%, rgba(0,0,0,0.7) 25%, rgba(0,0,0,0) 50%);
|
background: linear-gradient(to top, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0.2) 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.post-item:hover img {
|
.post-item:hover img {
|
||||||
|
|
@ -253,7 +246,7 @@ const regularPosts = postsWithImages.filter(post => !post.data.featured);
|
||||||
.post-item .post-title {
|
.post-item .post-title {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin: 0 0 2px 0;
|
margin: 0 0 4px 0;
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
text-shadow: 0 1px 3px rgba(0,0,0,0.8);
|
text-shadow: 0 1px 3px rgba(0,0,0,0.8);
|
||||||
}
|
}
|
||||||
|
|
@ -286,7 +279,7 @@ const regularPosts = postsWithImages.filter(post => !post.data.featured);
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.featured-grid {
|
.featured-grid {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
gap: 12px;
|
gap: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.featured-post {
|
.featured-post {
|
||||||
|
|
@ -316,11 +309,11 @@ const regularPosts = postsWithImages.filter(post => !post.data.featured);
|
||||||
}
|
}
|
||||||
|
|
||||||
.featured-section {
|
.featured-section {
|
||||||
padding: 12px 12px 0;
|
padding: 20px 15px 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.posts-grid {
|
.posts-grid {
|
||||||
padding: 12px 12px 80px;
|
padding: 0 15px 80px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
Loading…
Add table
Reference in a new issue