feat: Add Admin UI for banner management

- Create /admin/banners page with full CRUD operations
- Add BannerManager.tsx client component for interactive management
- Add banner-actions.ts server actions (create, update, toggle, delete)
- Add 'Manage Banners' link to admin dashboard
- Features: image preview, activate/deactivate toggle, edit inline
This commit is contained in:
2026-01-19 11:23:46 +01:00
parent 169fa0ad63
commit c047966b43
4 changed files with 581 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
export const dynamic = 'force-dynamic';
import { createClient } from '@/lib/supabase/server';
import { redirect } from 'next/navigation';
import { checkIsAdmin } from '@/services/track-api-usage';
import { getBanners } from '@/services/banner-actions';
import Link from 'next/link';
import { ArrowLeft, Image, ExternalLink, ToggleLeft, ToggleRight, Trash2, Plus, Edit2 } from 'lucide-react';
import BannerManager from './BannerManager';
export default async function AdminBannersPage() {
const supabase = await createClient();
const { data: { user } } = await supabase.auth.getUser();
if (!user) {
redirect('/');
}
const isAdmin = await checkIsAdmin(user.id);
if (!isAdmin) {
redirect('/');
}
const { banners, error } = await getBanners();
return (
<main className="min-h-screen bg-zinc-950 p-6 pb-24">
<div className="max-w-4xl mx-auto">
{/* Header */}
<div className="flex items-center gap-4 mb-8">
<Link
href="/admin"
className="p-2 rounded-xl bg-zinc-900 border border-zinc-800 text-zinc-400 hover:text-white hover:border-zinc-700 transition-colors"
>
<ArrowLeft size={20} />
</Link>
<div className="flex-1">
<h1 className="text-2xl font-bold text-white">Banner Management</h1>
<p className="text-sm text-zinc-500">
Manage hero banners for the home page
</p>
</div>
</div>
{error && (
<div className="mb-6 p-4 bg-red-500/20 border border-red-500/50 rounded-xl text-red-400 text-sm">
Error loading banners: {error}
</div>
)}
{/* Client Component for Interactive Banner Management */}
<BannerManager initialBanners={banners} />
</div>
</main>
);
}