Skip to content

Commit a075dbc

Browse files
committed
feat: integrate Mux Video System into CMS content blocks
1 parent 4fb6d64 commit a075dbc

File tree

3 files changed

+63
-1
lines changed

3 files changed

+63
-1
lines changed

app/admin/cms/[id]/CMSEditor.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { useState } from "react"
44
import { motion, Reorder, AnimatePresence } from "framer-motion"
5-
import { GripVertical, Trash2, Plus, Save, Settings2, Image as ImageIcon, Type, LayoutGrid, Palette, Sparkles, Loader2, Mail } from "lucide-react"
5+
import { GripVertical, Trash2, Plus, Save, Settings2, Image as ImageIcon, Type, LayoutGrid, Palette, Sparkles, Loader2, Mail, Film } from "lucide-react"
66
import { saveSections } from "@/lib/actions/cms"
77
import { toast } from "sonner"
88
import { SingleImageUpload } from "@/components/admin/SingleImageUpload"
@@ -21,6 +21,7 @@ const COMPONENT_TYPES = [
2121
{ type: "richText", label: "Philosophy Block", icon: Type, color: "text-blue-400", defaultProps: { content: "Add your storytelling here..." } },
2222
{ type: "philosophyGrid", label: "Philosophy Grid", icon: LayoutGrid, color: "text-amber-500/80", defaultProps: {} },
2323
{ type: "imageBanner", label: "Visual Vibe", icon: ImageIcon, color: "text-purple-400", defaultProps: { imageUrl: "", title: "", subtitle: "", ctaText: "", ctaLink: "", overlayOpacity: 0.4, height: "70vh" } },
24+
{ type: "videoBlock", label: "Video Showcase", icon: Film, color: "text-red-400", defaultProps: { playbackId: "", title: "", subtitle: "", autoPlay: 1 } },
2425
{ type: "contactForm", label: "Concierge Link", icon: Mail, color: "text-gold", defaultProps: {} },
2526
]
2627

components/cms/CMSRenderer.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import PhilosophyBlock from "./PhilosophyBlock";
55
import ImageBannerSection from "./ImageBannerSection";
66
import PhilosophyGrid from "./PhilosophyGrid";
77
import ContactSection from "./ContactSection";
8+
import VideoShowcaseSection from "./VideoShowcaseSection";
89

910
interface Section {
1011
type: string
@@ -18,6 +19,7 @@ const COMPONENT_MAP: Record<string, React.FC<any>> = {
1819
imageBanner: ImageBannerSection,
1920
philosophyGrid: PhilosophyGrid,
2021
contactForm: ContactSection,
22+
videoBlock: VideoShowcaseSection,
2123
};
2224

2325
export default function CMSRenderer({ sections }: { sections: Section[] }) {
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import VideoPlayer from "../VideoPlayer";
2+
3+
interface VideoShowcaseProps {
4+
playbackId: string;
5+
title?: string;
6+
subtitle?: string;
7+
autoPlay?: boolean | number;
8+
}
9+
10+
export default function VideoShowcaseSection({
11+
playbackId,
12+
title,
13+
subtitle,
14+
autoPlay = 1,
15+
}: VideoShowcaseProps) {
16+
return (
17+
<section className="relative w-full overflow-hidden bg-black/95 py-24 border-y border-white/5">
18+
<div className="max-w-[1400px] mx-auto px-6">
19+
{(title || subtitle) && (
20+
<div className="text-center mb-12 animate-luxury-fade space-y-4">
21+
{subtitle && (
22+
<p className="text-gold text-[10px] uppercase tracking-[0.4em] font-bold">
23+
{subtitle}
24+
</p>
25+
)}
26+
{title && (
27+
<h2 className="text-3xl md:text-5xl font-serif text-white tracking-tight leading-tight">
28+
{title}
29+
</h2>
30+
)}
31+
</div>
32+
)}
33+
34+
<div className="relative rounded-2xl overflow-hidden border border-white/10 shadow-2xl group max-w-5xl mx-auto">
35+
{playbackId ? (
36+
<VideoPlayer
37+
playbackId={playbackId}
38+
autoPlay={!!autoPlay}
39+
muted={!!autoPlay}
40+
loop={!!autoPlay}
41+
controls={!autoPlay}
42+
aspectClass="aspect-video"
43+
/>
44+
) : (
45+
<div className="aspect-video w-full bg-neutral-950 flex flex-col items-center justify-center space-y-3">
46+
<div className="w-12 h-12 rounded-full border border-white/10 flex items-center justify-center text-white/20">
47+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="lucide lucide-film"><rect width="18" height="18" x="3" y="3" rx="2"/><path d="M7 3v18"/><path d="M3 7.5h4"/><path d="M3 12h18"/><path d="M3 16.5h4"/><path d="M17 3v18"/><path d="M17 7.5h4"/><path d="M17 16.5h4"/></svg>
48+
</div>
49+
<p className="text-white/20 uppercase tracking-widest text-[9px] font-bold">Awaiting Video Configuration</p>
50+
</div>
51+
)}
52+
53+
{/* Decorative overlay */}
54+
<div className="absolute inset-0 border border-white/5 pointer-events-none mix-blend-overlay rounded-2xl" />
55+
</div>
56+
</div>
57+
</section>
58+
);
59+
}

0 commit comments

Comments
 (0)