ads/chrome: banners on /search and /reading-list; wrap /contributor with site chrome
- /search and /reading-list already had Header + Footer; add a
single in-content 728x90 banner at the bottom of each main column
(gated on ADS_728X90.length > 0, hidden on mobile).
- /contributor was a bare dashboard with sidebar + main, no site
chrome at all. Wrap it in the standard Header + Footer; drop the
inner sidebar/main wrapper from min-h-screen to a natural-height
flex so the dashboard sits below the header instead of competing
with it for full viewport. Header brings the site-wide 728x90
leaderboard with it, so contributors see the same ad inventory
as the public site without a second in-content banner cluttering
the dashboard panes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,8 @@ import React, { useState, useEffect, useCallback } from 'react';
|
|||||||
import { useAuth } from '@/contexts/AuthContext';
|
import { useAuth } from '@/contexts/AuthContext';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { createClient } from '@/lib/supabase/client';
|
import { createClient } from '@/lib/supabase/client';
|
||||||
|
import Header from '@/components/Header';
|
||||||
|
import Footer from '@/components/Footer';
|
||||||
|
|
||||||
// ─── Types ────────────────────────────────────────────────────────────────────
|
// ─── Types ────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -246,6 +248,7 @@ export default function ContributorDashboard() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-[#0a0a0a] text-white">
|
<div className="min-h-screen bg-[#0a0a0a] text-white">
|
||||||
|
<Header />
|
||||||
{notification && (
|
{notification && (
|
||||||
<div className={`fixed top-4 right-4 z-50 max-w-sm px-5 py-3 rounded-lg text-sm font-medium shadow-lg ${
|
<div className={`fixed top-4 right-4 z-50 max-w-sm px-5 py-3 rounded-lg text-sm font-medium shadow-lg ${
|
||||||
notification.type === 'success' ? 'bg-green-500/20 border border-green-500/40 text-green-300' : 'bg-red-500/20 border border-red-500/40 text-red-300'
|
notification.type === 'success' ? 'bg-green-500/20 border border-green-500/40 text-green-300' : 'bg-red-500/20 border border-red-500/40 text-red-300'
|
||||||
@@ -254,7 +257,7 @@ export default function ContributorDashboard() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="flex min-h-screen">
|
<div className="flex">
|
||||||
{/* Sidebar */}
|
{/* Sidebar */}
|
||||||
<aside className="w-60 bg-[#111] border-r border-[#222] flex flex-col">
|
<aside className="w-60 bg-[#111] border-r border-[#222] flex flex-col">
|
||||||
<div className="p-5 border-b border-[#222]">
|
<div className="p-5 border-b border-[#222]">
|
||||||
@@ -569,6 +572,7 @@ export default function ContributorDashboard() {
|
|||||||
)}
|
)}
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import Link from "next/link";
|
|||||||
import AppImage from "@/components/ui/AppImage";
|
import AppImage from "@/components/ui/AppImage";
|
||||||
import Header from "@/components/Header";
|
import Header from "@/components/Header";
|
||||||
import Footer from "@/components/Footer";
|
import Footer from "@/components/Footer";
|
||||||
|
import AdImage from "@/components/AdImage";
|
||||||
|
import { ADS_728X90, shuffle } from "@/lib/ads";
|
||||||
import { createClient } from "@/lib/supabase/client";
|
import { createClient } from "@/lib/supabase/client";
|
||||||
|
|
||||||
interface SavedArticle {
|
interface SavedArticle {
|
||||||
@@ -309,6 +311,13 @@ export default function ReadingListPage() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* In-content 728x90 banner */}
|
||||||
|
{ADS_728X90.length > 0 && (
|
||||||
|
<div className="max-w-container mx-auto px-4 mt-10 mb-6 hidden md:flex justify-center" aria-label="Advertisement">
|
||||||
|
<AdImage ad={shuffle(ADS_728X90)[0]} page="reading-list" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</main>
|
</main>
|
||||||
<Footer />
|
<Footer />
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import Link from "next/link";
|
|||||||
import Header from "@/components/Header";
|
import Header from "@/components/Header";
|
||||||
import Footer from "@/components/Footer";
|
import Footer from "@/components/Footer";
|
||||||
import AppImage from "@/components/ui/AppImage";
|
import AppImage from "@/components/ui/AppImage";
|
||||||
|
import AdImage from "@/components/AdImage";
|
||||||
|
import { ADS_728X90, shuffle } from "@/lib/ads";
|
||||||
import { searchLegacyArticles } from "@/lib/articles/legacy-source";
|
import { searchLegacyArticles } from "@/lib/articles/legacy-source";
|
||||||
|
|
||||||
export const revalidate = 60;
|
export const revalidate = 60;
|
||||||
@@ -93,6 +95,13 @@ export default async function SearchPage({ searchParams }: SearchPageProps) {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* In-content 728x90 banner */}
|
||||||
|
{ADS_728X90.length > 0 && (
|
||||||
|
<div className="mt-10 hidden md:flex justify-center" aria-label="Advertisement">
|
||||||
|
<AdImage ad={shuffle(ADS_728X90)[0]} page="search" />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</main>
|
</main>
|
||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user