From 878e15e1c89f7fd64e514138f99c8d7c7f51f847 Mon Sep 17 00:00:00 2001 From: akramj13 <125495000+akramj13@users.noreply.github.com> Date: Tue, 18 Mar 2025 00:25:13 -0400 Subject: [PATCH] updated chatgpt styles --- app/dashboard/chatgpt-video/page.tsx | 662 ++++++++++-------- app/dashboard/chatgpt-video/preview/page.tsx | 149 ++-- .../select-caption-style/page.tsx | 25 +- .../chatgpt-video/select-voice/page.tsx | 30 +- .../chatgpt-video/video-style/page.tsx | 357 ++++++++++ 5 files changed, 825 insertions(+), 398 deletions(-) create mode 100644 app/dashboard/chatgpt-video/video-style/page.tsx diff --git a/app/dashboard/chatgpt-video/page.tsx b/app/dashboard/chatgpt-video/page.tsx index 3c968c3..841cbe9 100644 --- a/app/dashboard/chatgpt-video/page.tsx +++ b/app/dashboard/chatgpt-video/page.tsx @@ -1,355 +1,411 @@ "use client"; -import React, { useState, useEffect } from "react"; +import { useState } from "react"; import { useRouter } from "next/navigation"; -import { - Card, - CardContent, - CardHeader, - CardTitle, - CardDescription, -} from "@/components/ui/card"; import { Button } from "@/components/ui/button"; -import { Input } from "@/components/ui/input"; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/components/ui/select"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { Card, CardContent } from "@/components/ui/card"; import { useVideoContext } from "@/app/dashboard/_components/VideoContext"; -import { Label } from "@/components/ui/label"; import { motion, AnimatePresence } from "framer-motion"; -import { ArrowRight, Sparkles, Brain, AlertCircle } from "lucide-react"; -import { Alert, AlertDescription } from "@/components/ui/alert"; +import { + BrainCircuit, + Sparkles, + MessageCircle, + ArrowRight, + Bot, + Edit, +} from "lucide-react"; -const CATEGORIES = [ - { - id: "education", - name: "Education", - example: "How Quantum Computing Works", - icon: "🧠", - }, - { - id: "science-tech", - name: "Science & Tech", - example: "The Future of AI", - icon: "🔬", - }, - { - id: "entertainment", - name: "Entertainment", - example: "The Best Movies of 2025", - icon: "🎬", - }, - { - id: "business-finance", - name: "Business & Finance", - example: "How to Invest in 2025", - icon: "💼", - }, - { - id: "history-geography", - name: "History & Geography", - example: "The Fall of the Roman Empire", - icon: "🏛️", - }, -]; +// Custom animated tabs trigger component +interface AnimatedTabsTriggerProps { + value: string; + activeTab: string; + icon: React.ReactNode; + label: string; +} -const VIDEO_STYLES = [ - { - type: "minimalist", - name: "Minimalist", - description: "Simple text animations & clean design", - icon: "🎨", - }, - { - type: "animated", - name: "Animated", - description: "AI-generated visuals & icons", - icon: "🖼", - }, - { - type: "cinematic", - name: "Cinematic", - description: "Realistic visuals & dramatic effects", - icon: "🎥", - }, - { - type: "storytelling", - name: "Storytelling", - description: "More personal & engaging", - icon: "📖", - }, - { - type: "news-report", - name: "News Report", - description: "Professional & factual", - icon: "📰", - }, - { - type: "gaming", - name: "Gaming Style", - description: "Bright, high-energy visuals", - icon: "🎮", - }, -]; +const AnimatedTabsTrigger = ({ + value, + activeTab, + icon, + label, +}: AnimatedTabsTriggerProps) => { + const isActive = activeTab === value; + + return ( + + + {icon} + {label} + + + ); +}; -// Animation variants const containerVariants = { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { - duration: 0.5, - when: "beforeChildren", staggerChildren: 0.1, + delayChildren: 0.2, }, }, }; const itemVariants = { - hidden: { y: 20, opacity: 0 }, + hidden: { y: 10, opacity: 0 }, visible: { y: 0, opacity: 1, - transition: { duration: 0.4 }, + transition: { + type: "spring", + stiffness: 260, + damping: 20, + }, }, }; -const cardHoverVariants = { - hover: { - y: -5, - boxShadow: "0 10px 25px -5px rgba(124, 58, 237, 0.2)", - transition: { duration: 0.2 }, +const glowVariants = { + initial: { scale: 0.95, opacity: 0.5 }, + animate: { + scale: [0.95, 1.05, 0.95], + opacity: [0.5, 0.8, 0.5], + transition: { + duration: 4, + repeat: Infinity, + ease: "easeInOut", + }, }, }; -function ChatGPTVideoPage() { - const router = useRouter(); - const { videoData, setVideoData } = useVideoContext(); - const [selectedCategory, setSelectedCategory] = useState(""); - const [customTopic, setCustomTopic] = useState(""); - const [selectedStyle, setSelectedStyle] = useState("minimalist"); - const [error, setError] = useState(""); - const [isMobileView, setIsMobileView] = useState(false); - - // Check for mobile view on mount and window resize - useEffect(() => { - const checkMobileView = () => { - setIsMobileView(window.innerWidth < 768); - }; - - // Initial check - checkMobileView(); +// Add tab content animation variants +const tabContentVariants = { + hidden: { + opacity: 0, + y: 20, + scale: 0.95, + }, + visible: { + opacity: 1, + y: 0, + scale: 1, + transition: { + type: "spring", + stiffness: 300, + damping: 30, + duration: 0.4, + }, + }, + exit: { + opacity: 0, + y: -20, + scale: 0.95, + transition: { + duration: 0.3, + }, + }, +}; - // Add event listener for window resize - window.addEventListener("resize", checkMobileView); +// Add tab trigger animation variants +const tabTriggerVariants = { + inactive: { + scale: 0.95, + opacity: 0.7, + }, + active: { + scale: 1, + opacity: 1, + transition: { + type: "spring", + stiffness: 300, + damping: 20, + }, + }, +}; - // Cleanup - return () => { - window.removeEventListener("resize", checkMobileView); - }; - }, []); +export default function ChatGPTVideoPage() { + const router = useRouter(); + const { videoData, setVideoData } = useVideoContext(); + const [activeTab, setActiveTab] = useState("features"); const handleContinue = () => { - if (!selectedCategory && !customTopic) { - setError("Please select a category or enter a custom topic"); - return; - } - - // Update video data with selected options setVideoData({ - ...videoData, type: "chatgpt", content: { - ...videoData?.content, - text: customTopic || selectedCategory, // Store the actual topic text - }, - style: { - ...videoData?.style, - chatgptSelectedTopic: selectedCategory || undefined, // Store selected category if any - chatgptCustomTopic: customTopic || undefined, // Store custom topic if any - chatgptVideoStyle: selectedStyle, + text: "", }, }); - // Navigate to the next step - router.push("/dashboard/chatgpt-video/select-voice"); + router.push("/dashboard/chatgpt-video/video-style"); }; return ( - - - - - - - - Create ChatGPT Style Video - - - - Generate engaging AI-powered videos with just a few clicks - - - - {/* Error Alert */} - - {error && ( - - - - {error} - - - )} - +
+ {/* Decorative Elements */} +
+ + +
- {/* Topic Selection */} - -
-
- 1 -
- -
+ {/* Main Content Container */} +
+ {/* Header Section */} +
+
+ + + + + + +
+ +

+ + ChatGPT Video Creator + +

+

+ Transform AI-generated content into engaging videos with + customizable styles +

+
- {/* Category Selection */} - - - - + + + - {/* Custom Topic Input */} - - - { - setCustomTopic(e.target.value); - setError(""); - }} - className="bg-gray-800 border-gray-700 text-gray-200 focus:ring-purple-500 focus:border-purple-500" - /> - - + + +
    +
  1. +
    + 1 +
    +
    +

    + Define Topic +

    +

    + Enter your main idea or topic for the AI to + develop +

    +
    +
  2. - {/* Video Style Selection */} - -
    -
    - 2 -
    - -
    -
    - {VIDEO_STYLES.map((style) => ( - setSelectedStyle(style.type)} - > -
    -
    - {style.icon} -
    -

    - {style.name} -

    -
    -

    - {style.description} -

    -
    - ))} -
    -
    +
  3. +
    + 2 +
    +
    +

    + Customize AI Parameters +

    +

    + Adjust tone, length, and style of the generated + content +

    +
    +
  4. - {/* Continue Button */} - - - +
  5. +
    + 3 +
    +
    +

    + Review & Edit Content +

    +

    + Refine the AI-generated script to your liking +

    +
    +
  6. - {/* AI Powered Indicator */} - - - Powered by vidsynth.ai - - - - - - +
  7. +
    + 4 +
    +
    +

    + Select Voice & Style +

    +

    + Choose voice narration and visual appearance for + your video +

    +
    +
  8. + +
  9. +
    + 5 +
    +
    +

    + Generate Video +

    +

    + Our AI combines everything into a professional + video +

    +
    +
  10. +
+ + +
+
+ +
+ +
+ + + + ); } - -export default ChatGPTVideoPage; diff --git a/app/dashboard/chatgpt-video/preview/page.tsx b/app/dashboard/chatgpt-video/preview/page.tsx index 9f33bd1..1909b7d 100644 --- a/app/dashboard/chatgpt-video/preview/page.tsx +++ b/app/dashboard/chatgpt-video/preview/page.tsx @@ -73,7 +73,7 @@ interface VideoData { captions?: string; imagesList?: string[]; script?: string | ScriptData; - type?: 'reddit' | 'split-screen' | 'chatgpt'; + type?: "reddit" | "split-screen" | "chatgpt"; } interface RemotionProps { @@ -86,7 +86,7 @@ interface RemotionProps { audio_duration?: number; captions?: Caption[] | string; title_captions?: Caption[] | string; - type?: 'reddit' | 'split-screen' | 'chatgpt'; + type?: "reddit" | "split-screen" | "chatgpt"; imagesList?: string[]; script?: string | ScriptData; }; @@ -222,11 +222,11 @@ export default function PreviewPage() { initial={{ opacity: 0, scale: 0.9 }} animate={{ opacity: 1, scale: 1 }} transition={{ duration: 0.5 }} - className="bg-white/5 backdrop-blur-md rounded-2xl p-8 shadow-xl" + className="bg-black/40 backdrop-blur-md rounded-2xl p-8 shadow-xl" >
-
- +
+ Loading video data...
@@ -297,15 +297,17 @@ export default function PreviewPage() { const FPS = 30; // For ChatGPT videos, calculate duration based on last caption plus 1 second - if (video?.type === 'chatgpt' && video.captions) { + if (video?.type === "chatgpt" && video.captions) { try { - const parsedCaptions = typeof video.captions === "string" - ? JSON.parse(video.captions) - : video.captions; + const parsedCaptions = + typeof video.captions === "string" + ? JSON.parse(video.captions) + : video.captions; if (Array.isArray(parsedCaptions) && parsedCaptions.length > 0) { // Find the last caption's end time and add 1 second buffer - const lastCaptionEndTime = Math.max(...parsedCaptions.map(cap => cap.end)) / 1000; // Convert ms to seconds + const lastCaptionEndTime = + Math.max(...parsedCaptions.map((cap) => cap.end)) / 1000; // Convert ms to seconds return Math.ceil((lastCaptionEndTime + 1) * FPS); // Add 1 second buffer } } catch (e) { @@ -321,12 +323,14 @@ export default function PreviewPage() { let lastCaptionEndTime = 0; if (video?.captions) { try { - const parsedCaptions = typeof video.captions === "string" - ? JSON.parse(video.captions) - : video.captions; + const parsedCaptions = + typeof video.captions === "string" + ? JSON.parse(video.captions) + : video.captions; if (Array.isArray(parsedCaptions) && parsedCaptions.length > 0) { - lastCaptionEndTime = Math.max(...parsedCaptions.map(cap => cap.end)) / 1000; + lastCaptionEndTime = + Math.max(...parsedCaptions.map((cap) => cap.end)) / 1000; } } catch (e) { console.error("Error parsing captions:", e); @@ -358,9 +362,9 @@ export default function PreviewPage() { variants={itemVariants} className="flex-1 order-1 md:max-w-[45%]" > - - - + + + Video Preview @@ -369,15 +373,16 @@ export default function PreviewPage() { {remotionProps && (
-
+
video && handleDownload(video.id)} disabled={isGenerating || !video} - className="w-full bg-gradient-to-r from-purple-600 to-blue-600 hover:from-purple-700 hover:to-blue-700 text-white font-medium py-3 rounded-xl shadow-lg hover:shadow-purple-500/25 transition-all duration-300 flex items-center justify-center gap-2" + className="w-full bg-gradient-to-r from-emerald-600 to-teal-600 hover:from-emerald-500 hover:to-teal-500 text-white font-medium py-3 rounded-xl shadow-[0_0_15px_rgba(16,185,129,0.3)] hover:shadow-[0_0_20px_rgba(16,185,129,0.4)] transition-all duration-300 flex items-center justify-center gap-2" > {isGenerating ? ( <> @@ -429,7 +434,7 @@ export default function PreviewPage() { ?.classList.toggle("translate-y-full") } variant="outline" - className="w-full border border-white/10 bg-white/5 hover:bg-white/10 text-white font-medium py-2 rounded-xl transition-all duration-300 flex items-center justify-center gap-2" + className="w-full border border-emerald-500/20 bg-black/40 hover:bg-emerald-950/20 text-white font-medium py-2 rounded-xl transition-all duration-300 flex items-center justify-center gap-2" > View Details @@ -439,9 +444,9 @@ export default function PreviewPage() { {/* Video Details Section - Hidden on Mobile */} - - - + + + Video Details @@ -449,10 +454,10 @@ export default function PreviewPage() {
- +

Title

@@ -463,15 +468,15 @@ export default function PreviewPage() {
- +

Content

-

+

{video.text}

@@ -481,7 +486,7 @@ export default function PreviewPage() {
@@ -490,15 +495,20 @@ export default function PreviewPage() {
- {typeof video.script === 'string' + {typeof video.script === "string" ? video.script - : (video.script as ScriptData)?.sections?.map((section: ScriptSection, index: number) => ( -
-

{section.narration}

-

{section.imageDescription}

-
- )) - } + : (video.script as ScriptData)?.sections?.map( + (section: ScriptSection, index: number) => ( +
+

+ {section.narration} +

+

+ {section.imageDescription} +

+
+ ) + )}
)} @@ -507,7 +517,7 @@ export default function PreviewPage() {
@@ -521,10 +531,10 @@ export default function PreviewPage() {
- +

Background

@@ -537,10 +547,10 @@ export default function PreviewPage() {
- +

Caption Style: @@ -550,7 +560,7 @@ export default function PreviewPage() {

- +

Duration:{" "} {video.audio_duration @@ -571,7 +581,7 @@ export default function PreviewPage() { >

-

+

Video Details

diff --git a/app/dashboard/chatgpt-video/select-voice/page.tsx b/app/dashboard/chatgpt-video/select-voice/page.tsx index 9767609..b46505a 100644 --- a/app/dashboard/chatgpt-video/select-voice/page.tsx +++ b/app/dashboard/chatgpt-video/select-voice/page.tsx @@ -119,24 +119,24 @@ function VoiceSelectionPage() { transition={{ duration: 0.5 }} className="w-full" > - +
- + Select Voice - Choose a voice for your video narration + Choose a voice for your ChatGPT video
@@ -145,9 +145,9 @@ function VoiceSelectionPage() { -
+
{selectedVoiceInfo?.initials}
@@ -168,7 +168,7 @@ function VoiceSelectionPage() { setSearchQuery(e.target.value)} /> @@ -176,12 +176,12 @@ function VoiceSelectionPage() {
- + {voiceCategories.map((category) => ( {category} @@ -211,14 +211,14 @@ function VoiceSelectionPage() { whileTap={{ scale: 0.98 }} className={`relative overflow-hidden rounded-xl border ${ selectedVoice === voice.id - ? "border-purple-500 bg-gradient-to-br from-purple-500/20 to-pink-500/20" - : "border-white/10 bg-white/5" - } p-3 sm:p-4 hover:bg-white/10 transition-all cursor-pointer group text-white`} + ? "border-emerald-500 bg-gradient-to-br from-emerald-500/20 to-teal-500/20" + : "border-emerald-500/20 bg-black/50" + } p-3 sm:p-4 hover:bg-emerald-950/30 transition-all cursor-pointer group text-white`} onClick={() => handleVoiceSelect(voice.id)} >
- + {voice.category} @@ -321,7 +321,7 @@ function VoiceSelectionPage() { > + + + {/* AI Powered Indicator */} + + + Powered by vidsynth.ai + + + + + + + ); +} + +export default ChatGPTVideoPage;