"use client"; import React, { useMemo, useState } from "react"; import { Monitor, Smartphone, RefreshCw } from "lucide-react"; import { buildBrandScale, buildSecondaryTokens, buildAccentTokens, contrastForeground, isValidHex } from "@/lib/colorScale"; type View = "website" | "email"; type Viewport = "desktop" | "mobile"; /** * Hand-built mockup (not an iframe of the real site) so it can reflect * in-progress, unsaved color-picker values instantly — the real site's CSS * variables only update once the admin actually saves (see layout.tsx's SSR * style tag), and this preview must not leak into the surrounding admin * page's own theme while the admin is still experimenting with colors. */ export function BrandingPreviewPanel({ primaryColor, secondaryColor, accentColor, logoSrc, orgName, orgTagline, }: { primaryColor: string; secondaryColor: string; accentColor: string; logoSrc: string | null; orgName: string; orgTagline?: string; }) { const [view, setView] = useState("website"); const [viewport, setViewport] = useState("desktop"); const safePrimary = isValidHex(primaryColor) ? primaryColor : "#4F46E5"; const safeSecondary = isValidHex(secondaryColor) ? secondaryColor : "#8B5CF6"; const safeAccent = isValidHex(accentColor) ? accentColor : "#EC4899"; const scale = useMemo(() => buildBrandScale(safePrimary), [safePrimary]); const secondary = useMemo(() => buildSecondaryTokens(safeSecondary), [safeSecondary]); const accent = useMemo(() => buildAccentTokens(safeAccent), [safeAccent]); const primaryFg = useMemo(() => contrastForeground(safePrimary), [safePrimary]); return (

Live Preview

See how your branding looks across the site.

{view === "website" && (
)}
{view === "website" ? (
{/* Header */}
{logoSrc ? ( // eslint-disable-next-line @next/next/no-img-element Logo ) : (
)} {orgName || "Your Organisation"}
HomeEventsContact
{/* Hero */}

Welcome to {orgName || "Your Organisation"}

Experience unforgettable moments.

View Events My Dashboard
{/* Upcoming events */}

Upcoming events

{["Sunday Service", "Community Outreach"].map((title) => (
{title} New
))}
{/* Footer — fixed dark neutral, not brand-driven */}

© {new Date().getFullYear()} {orgName || "Your Organisation"}. All rights reserved.

) : (

{orgName || "Your Organisation"}

{orgTagline &&

{orgTagline}

}

Sample notification

Call to action
)}
Updates live as you change colors — save to apply site-wide.
); }