correction responsive mobile

This commit is contained in:
2026-05-12 20:18:43 +02:00
parent b81216210a
commit bd6380b7aa
5 changed files with 43 additions and 31 deletions

View File

@@ -2,6 +2,7 @@ import type { NextConfig } from "next";
import path from "path"; import path from "path";
const nextConfig: NextConfig = { const nextConfig: NextConfig = {
output: 'standalone', output: 'standalone',
allowedDevOrigins: ['10.0.2.2'],
// 1. On ignore les erreurs de type et ESLint pour que le build // 1. On ignore les erreurs de type et ESLint pour que le build
// de production ne plante pas à cause des imports Prisma // de production ne plante pas à cause des imports Prisma

View File

@@ -101,24 +101,24 @@ export default async function BlogPostPage({ params }: Props) {
} }
return ( return (
<article className="bg-gray-50 min-h-screen py-12 relative"> <article className="bg-white sm:bg-gray-50 min-h-screen py-0 sm:py-12 relative">
{/* Injection du style de force pour le texte */} {/* Injection du style de force pour le texte */}
<style dangerouslySetInnerHTML={{ __html: noBreakStyle }} /> <style dangerouslySetInnerHTML={{ __html: noBreakStyle }} />
<div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 flex gap-4 lg:gap-8 justify-center relative"> <div className="max-w-5xl mx-auto px-0 sm:px-6 lg:px-8 flex gap-4 lg:gap-8 justify-center relative">
{/* Conteneur principal de l'article */} {/* Conteneur principal de l'article */}
<div className="w-[calc(100%-3rem)] sm:w-full max-w-3xl relative"> <div className="w-full max-w-3xl relative">
{/* Navigation */} {/* Navigation */}
<div className="mb-8"> <div className="mb-4 sm:mb-8 px-4 sm:px-0 pt-4 sm:pt-0">
<Link href="/actualites" className="inline-flex items-center text-gray-500 hover:text-brand-600 text-sm font-medium transition-colors"> <Link href="/actualites" className="inline-flex items-center text-gray-500 hover:text-brand-600 text-sm font-medium transition-colors">
<ArrowLeft className="w-4 h-4 mr-1" /> Retour aux articles <ArrowLeft className="w-4 h-4 mr-1" /> Retour aux articles
</Link> </Link>
</div> </div>
<div className="bg-white rounded-xl shadow-sm p-6 md:p-10 border border-gray-100 relative z-10"> <div className="bg-white sm:rounded-xl shadow-none sm:shadow-sm sm:p-10 border-none sm:border sm:border-gray-100 relative z-10">
{/* Image d'en-tête */} {/* Image d'en-tête en pleine largeur sur mobile */}
<div className="w-full h-64 md:h-80 relative mb-8 rounded-lg overflow-hidden shadow-md"> <div className="w-full h-64 md:h-80 relative mb-6 sm:mb-8 sm:rounded-lg overflow-hidden shadow-none sm:shadow-md">
<LightboxImage <LightboxImage
src={post.imageUrl} src={post.imageUrl}
alt={post.title} alt={post.title}
@@ -128,7 +128,7 @@ export default async function BlogPostPage({ params }: Props) {
</div> </div>
{/* Header de l'article */} {/* Header de l'article */}
<header className="mb-8 border-b border-gray-100 pb-8"> <header className="mb-6 sm:mb-8 border-b border-gray-100 pb-6 sm:pb-8 px-4 sm:px-0">
<div className="flex flex-wrap items-center gap-4 text-sm text-gray-500 mb-4"> <div className="flex flex-wrap items-center gap-4 text-sm text-gray-500 mb-4">
<span className="flex items-center"> <span className="flex items-center">
<User className="w-4 h-4 mr-1 text-brand-500" /> <User className="w-4 h-4 mr-1 text-brand-500" />
@@ -156,7 +156,7 @@ export default async function BlogPostPage({ params }: Props) {
</header> </header>
{/* Contenu de l'article */} {/* Contenu de l'article */}
<div className="prose prose-lg prose-orange max-w-none text-gray-600"> <div className="prose sm:prose-lg prose-orange max-w-none text-gray-600 px-4 sm:px-0">
{/* Résumé / Lead */} {/* Résumé / Lead */}
<p className="lead text-xl text-gray-500 font-serif italic mb-6 border-b border-gray-100 pb-6"> <p className="lead text-xl text-gray-500 font-serif italic mb-6 border-b border-gray-100 pb-6">
{post.excerpt} {post.excerpt}
@@ -172,7 +172,7 @@ export default async function BlogPostPage({ params }: Props) {
{/* Sources Section */} {/* Sources Section */}
{Array.isArray(post.sources) && post.sources.length > 0 && ( {Array.isArray(post.sources) && post.sources.length > 0 && (
<div className="mt-12 p-6 bg-gray-50 rounded-xl border border-gray-100"> <div className="mt-8 sm:mt-12 p-4 sm:p-6 bg-gray-50 sm:rounded-xl border-t sm:border border-gray-100 mx-4 sm:mx-0">
<h3 className="text-sm font-bold uppercase tracking-wider text-gray-400 mb-4 flex items-center gap-2"> <h3 className="text-sm font-bold uppercase tracking-wider text-gray-400 mb-4 flex items-center gap-2">
<Share2 className="w-4 h-4 text-brand-500" /> <Share2 className="w-4 h-4 text-brand-500" />
Sources & Références Sources & Références
@@ -196,8 +196,14 @@ export default async function BlogPostPage({ params }: Props) {
</div> </div>
)} )}
{/* Partage sur mobile */}
<div className="mt-8 pt-6 border-t border-gray-100 block sm:hidden px-4">
<p className="text-xs font-bold uppercase tracking-wider text-gray-400 mb-4 text-center">Partager cet article</p>
<BlogShareButtons title={post.title} layout="horizontal" />
</div>
{/* Partage / Footer */} {/* Partage / Footer */}
<div className="mt-12 pt-8 border-t border-gray-100 flex flex-col sm:flex-row justify-between items-center gap-4"> <div className="mt-8 sm:mt-12 pt-6 sm:pt-8 border-t border-gray-100 flex flex-col sm:flex-row justify-between items-center gap-4 px-4 sm:px-0">
<p className="text-gray-500 font-medium">Vous avez aimé cet article ?</p> <p className="text-gray-500 font-medium">Vous avez aimé cet article ?</p>
<Link <Link
href="/actualites" href="/actualites"
@@ -211,7 +217,7 @@ export default async function BlogPostPage({ params }: Props) {
</div> </div>
{/* Sidebar flottante verticale à droite (suit l'article et s'arrête à la fin) */} {/* Sidebar flottante verticale à droite (suit l'article et s'arrête à la fin) */}
<div className="w-10 shrink-0 relative"> <div className="hidden sm:block w-10 shrink-0 relative">
<div className="sticky top-32 z-50"> <div className="sticky top-32 z-50">
<BlogShareButtons title={post.title} /> <BlogShareButtons title={post.title} />
</div> </div>

View File

@@ -6,6 +6,7 @@ import { sanitizeHTML } from '../../../lib/sanitize';
import { prisma } from '../../../lib/prisma'; import { prisma } from '../../../lib/prisma';
import { InterviewType } from '@prisma/client'; import { InterviewType } from '@prisma/client';
import LightboxImage from '@/components/LightboxImage'; import LightboxImage from '@/components/LightboxImage';
import BlogShareButtons from '../../../components/BlogShareButtons';
import { Metadata } from 'next'; import { Metadata } from 'next';
@@ -91,13 +92,15 @@ export default async function AfroLifeDetailPage({ params }: Props) {
return ( return (
<div className="bg-white min-h-screen"> <div className="bg-white min-h-screen">
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-12"> <div className="max-w-4xl mx-auto px-0 sm:px-6 lg:px-8 py-0 sm:py-12">
<Link href="/afrolife" className="inline-flex items-center text-gray-500 hover:text-brand-600 mb-8 transition-colors"> <div className="pt-4 sm:pt-0 px-4 sm:px-0 mb-6 sm:mb-8">
<ArrowLeft className="w-4 h-4 mr-2" /> Retour à Afro Life <Link href="/afrolife" className="inline-flex items-center text-gray-500 hover:text-brand-600 transition-colors">
</Link> <ArrowLeft className="w-4 h-4 mr-2" /> Retour à Afro Life
</Link>
</div>
{/* Header Info */} {/* Header Info */}
<div className="text-center mb-10"> <div className="text-center mb-8 sm:mb-10 px-4 sm:px-0">
<div className="inline-flex items-center justify-center px-3 py-1 rounded-full bg-gray-100 text-gray-600 text-xs font-bold uppercase tracking-wider mb-4"> <div className="inline-flex items-center justify-center px-3 py-1 rounded-full bg-gray-100 text-gray-600 text-xs font-bold uppercase tracking-wider mb-4">
{isEvent ? 'Événement' : (isVideo ? 'Interview Vidéo' : 'Grand Entretien')} {isEvent ? 'Événement' : (isVideo ? 'Interview Vidéo' : 'Grand Entretien')}
</div> </div>
@@ -143,9 +146,9 @@ export default async function AfroLifeDetailPage({ params }: Props) {
</div> </div>
</div> </div>
{/* Main Content Area */} {/* Main Content Area en pleine largeur sur mobile */}
{isVideo ? ( {isVideo ? (
<div className="bg-black rounded-xl overflow-hidden shadow-2xl aspect-w-16 aspect-h-9 mb-10"> <div className="bg-black rounded-none sm:rounded-xl overflow-hidden shadow-none sm:shadow-2xl aspect-w-16 aspect-h-9 mb-8 sm:mb-10 w-full">
{(interview as any).videoUrl ? ( {(interview as any).videoUrl ? (
<iframe <iframe
src={getEmbedUrl((interview as any).videoUrl) || ''} src={getEmbedUrl((interview as any).videoUrl) || ''}
@@ -161,7 +164,7 @@ export default async function AfroLifeDetailPage({ params }: Props) {
)} )}
</div> </div>
) : ( ) : (
<div className="relative h-64 md:h-96 rounded-xl overflow-hidden shadow-lg mb-10"> <div className="relative h-64 md:h-96 rounded-none sm:rounded-xl overflow-hidden shadow-none sm:shadow-lg mb-8 sm:mb-10 w-full">
<LightboxImage <LightboxImage
src={item!.thumbnailUrl} src={item!.thumbnailUrl}
alt={item!.title} alt={item!.title}
@@ -172,7 +175,7 @@ export default async function AfroLifeDetailPage({ params }: Props) {
)} )}
{/* Description / Article Content / Event Content */} {/* Description / Article Content / Event Content */}
<div className="prose prose-lg prose-orange max-w-none mx-auto text-gray-600"> <div className="prose sm:prose-lg prose-orange max-w-none mx-auto text-gray-600 px-4 sm:px-0">
{isEvent ? ( {isEvent ? (
<div dangerouslySetInnerHTML={{ __html: sanitizeHTML((event as any).description) }} /> <div dangerouslySetInnerHTML={{ __html: sanitizeHTML((event as any).description) }} />
) : ( ) : (
@@ -188,7 +191,7 @@ export default async function AfroLifeDetailPage({ params }: Props) {
{/* Event Link Action */} {/* Event Link Action */}
{isEvent && (event as any).link && ( {isEvent && (event as any).link && (
<div className="mt-10 text-center"> <div className="mt-10 text-center px-4 sm:px-0">
<Link <Link
href={(event as any).link} href={(event as any).link}
target="_blank" target="_blank"
@@ -199,12 +202,12 @@ export default async function AfroLifeDetailPage({ params }: Props) {
</div> </div>
)} )}
{/* Footer Actions */} {/* Footer Actions / Partage */}
<div className="mt-12 pt-8 border-t border-gray-100 flex justify-center"> <div className="mt-10 sm:mt-12 pt-6 sm:pt-8 border-t border-gray-100 px-4 sm:px-0 pb-8 sm:pb-0">
<button className="flex items-center px-6 py-3 rounded-full bg-brand-50 text-brand-700 font-medium hover:bg-brand-100 transition-colors"> <p className="text-xs font-bold uppercase tracking-wider text-gray-400 mb-4 text-center">
<Share2 className="w-5 h-5 mr-2" />
Partager {isEvent ? "cet événement" : "cette interview"} Partager {isEvent ? "cet événement" : "cette interview"}
</button> </p>
<BlogShareButtons title={item!.title} layout="horizontal" />
</div> </div>
</div> </div>
</div> </div>

View File

@@ -6,9 +6,10 @@ import toast from 'react-hot-toast';
interface Props { interface Props {
title: string; title: string;
layout?: 'vertical' | 'horizontal';
} }
export default function BlogShareButtons({ title }: Props) { export default function BlogShareButtons({ title, layout = 'vertical' }: Props) {
const [copied, setCopied] = useState(false); const [copied, setCopied] = useState(false);
const [url, setUrl] = useState(''); const [url, setUrl] = useState('');
@@ -32,12 +33,12 @@ export default function BlogShareButtons({ title }: Props) {
if (!url) return null; if (!url) return null;
return ( return (
<div className="flex flex-col gap-3 z-50"> <div className={`flex ${layout === 'horizontal' ? 'flex-row gap-4 justify-center flex-wrap' : 'flex-col gap-3'} z-50`}>
<a <a
href={shareLinks.facebook} href={shareLinks.facebook}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="w-10 h-10 rounded-full bg-white text-[#1877F2] shadow-xl flex items-center justify-center hover:scale-110 transition-transform" className="w-10 h-10 rounded-full bg-white text-[#1877F2] shadow-xl flex items-center justify-center hover:scale-110 transition-transform border border-gray-100"
title="Partager sur Facebook" title="Partager sur Facebook"
> >
<Facebook className="w-5 h-5" /> <Facebook className="w-5 h-5" />

View File

@@ -9,6 +9,7 @@ const nextConfig = {
reactStrictMode: true, reactStrictMode: true,
//output: 'standalone', //output: 'standalone',
poweredByHeader: false, poweredByHeader: false,
allowedDevOrigins: ['10.0.2.2'],
turbopack: { turbopack: {
root: __dirname, root: __dirname,
}, },
@@ -28,7 +29,7 @@ const nextConfig = {
}, },
{ {
key: 'Content-Security-Policy', key: 'Content-Security-Policy',
value: "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https:; font-src 'self' data:; media-src 'self' https:; connect-src 'self' wss: https:; base-uri 'self'; form-action 'self'; frame-ancestors 'self'; object-src 'none';", value: "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https: http:; font-src 'self' data:; media-src 'self' https: http:; connect-src 'self' ws: wss: https: http:; base-uri 'self'; form-action 'self'; frame-ancestors 'self'; object-src 'none';",
}, },
{ {
key: 'X-Content-Type-Options', key: 'X-Content-Type-Options',