"use client"; import { useState } from "react"; import { useRouter } from "next/navigation"; import { motion, AnimatePresence } from "framer-motion"; import { AtSign, Link2, Loader2, ArrowRight, Clock, Palette, Monitor, Smartphone, Square, Sparkles, Wand2, MessageSquare, Heart, Repeat2, Eye, Image as ImageIcon, } from "lucide-react"; import { cn } from "@/lib/utils"; import { useTweetPreview, useCreateFromTweet } from "@/hooks/use-api"; import { useToast } from "@/components/ui/toast"; const videoStyles = [ { id: "CINEMATIC", label: "Sinematik", emoji: "🎬" }, { id: "DOCUMENTARY", label: "Belgesel", emoji: "📹" }, { id: "EDUCATIONAL", label: "Eğitim", emoji: "📚" }, { id: "STORYTELLING", label: "Hikâye", emoji: "📖" }, { id: "NEWS", label: "Haber", emoji: "📰" }, ]; const aspectRatios = [ { id: "PORTRAIT_9_16", label: "9:16", icon: Smartphone, desc: "Shorts / Reels" }, { id: "SQUARE_1_1", label: "1:1", icon: Square, desc: "Instagram" }, { id: "LANDSCAPE_16_9", label: "16:9", icon: Monitor, desc: "YouTube" }, ]; const languages = [ { code: "tr", label: "Türkçe", flag: "🇹🇷" }, { code: "en", label: "English", flag: "🇺🇸" }, { code: "de", label: "Deutsch", flag: "🇩🇪" }, { code: "es", label: "Español", flag: "🇪🇸" }, ]; export default function XToVideoPage() { const router = useRouter(); const toast = useToast(); const tweetPreview = useTweetPreview(); const createFromTweet = useCreateFromTweet(); const [tweetUrl, setTweetUrl] = useState(""); const [style, setStyle] = useState("CINEMATIC"); const [duration, setDuration] = useState(60); const [aspectRatio, setAspectRatio] = useState("PORTRAIT_9_16"); const [language, setLanguage] = useState("tr"); // eslint-disable-next-line @typescript-eslint/no-explicit-any const [previewData, setPreviewData] = useState(null); const isValidUrl = /https?:\/\/(x\.com|twitter\.com)\/\w+\/status\/\d+/.test(tweetUrl); const handlePreview = async () => { if (!isValidUrl) { toast.error("Geçerli bir X/Twitter URL'si girin (https://x.com/...)"); return; } try { const result = await tweetPreview.mutateAsync(tweetUrl); setPreviewData(result); toast.success("Tweet başarıyla yüklendi!"); } catch { toast.error("Tweet yüklenemedi. URL'yi kontrol edin."); } }; const handleGenerate = async () => { try { // eslint-disable-next-line @typescript-eslint/no-explicit-any const result: any = await createFromTweet.mutateAsync({ tweetUrl, language, aspectRatio, videoStyle: style, targetDuration: duration, }); toast.success("Tweet → Video projesi oluşturuldu!"); const projectId = result?.id; if (projectId) { router.push(`/dashboard/projects/${projectId}`); } else { router.push("/dashboard/projects"); } } catch { toast.error("Proje oluşturulurken bir hata oluştu."); } }; return (
{/* Header */}
X → Video

Tweet'ten Video Oluştur

X/Twitter yazılarını AI ile kısa videolara dönüştürün

{/* URL Input */}
{ setTweetUrl(e.target.value); setPreviewData(null); }} placeholder="https://x.com/username/status/123456..." className="flex-1 px-4 py-2.5 rounded-xl bg-[var(--color-bg-surface)] border border-[var(--color-border-faint)] text-sm text-[var(--color-text-primary)] placeholder:text-[var(--color-text-ghost)] focus:outline-none focus:border-violet-500/40 focus:ring-1 focus:ring-violet-500/20 transition-all" />

Thread desteği: Çoklu tweet zincirleri de otomatik olarak algılanır

{/* Tweet Preview */} {previewData && (

Tweet Önizleme

{/* Author */}
{(previewData.tweet?.author?.name ?? "X")?.[0]}

{previewData.tweet?.author?.name ?? "Kullanıcı"}

@{previewData.tweet?.author?.username ?? "handle"}

{/* Content */}

{previewData.tweet?.text ?? ""}

{/* Images */} {(previewData.tweet?.media?.length > 0) && (
{(previewData.tweet.media ?? []) .filter((m: any) => m.type === 'photo') .map( (m: any, i: number) => (
{/* eslint-disable-next-line @next/next/no-img-element */} {`Media
), )}
)} {/* Stats */}
{previewData.tweet?.metrics?.likes ?? 0} {previewData.tweet?.metrics?.retweets ?? 0} {previewData.tweet?.metrics?.views ?? 0} {previewData.tweet?.isThread && ( {previewData.tweet?.threadTweets?.length ?? 0} tweet thread )}
{/* Suggested info */} {previewData.suggestedTitle && (
Önerilen başlık: {previewData.suggestedTitle} · Tahmini süre: {previewData.estimatedDuration}sn · Viral skoru: {previewData.viralScore}/100
)} {/* Images tag */} {(previewData.tweet?.media?.filter((m: any) => m.type === 'photo')?.length > 0) && (
{previewData.tweet.media.filter((m: any) => m.type === 'photo').length} görsel referans olarak kullanılacak + AI görsel üretilecek
)}
)}
{/* Video Settings */} {previewData && ( {/* Language */}
{languages.map((l) => ( ))}
{/* Style */}
{videoStyles.map((s) => ( ))}
{/* Duration + Aspect Ratio */}
setDuration(Number(e.target.value))} className="w-full h-1.5 rounded-full bg-[var(--color-bg-elevated)] appearance-none cursor-pointer [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:w-5 [&::-webkit-slider-thumb]:h-5 [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-violet-500 [&::-webkit-slider-thumb]:shadow-[0_0_12px_rgba(139,92,246,0.4)] [&::-webkit-slider-thumb]:cursor-grab" />
{aspectRatios.map((ar) => { const Icon = ar.icon; return ( ); })}
{/* Generate Button */}

Bu işlem 1 kredi kullanır • AI senaryo + görsel üretim dahil

)}
{/* Info Box */} {!previewData && (

Nasıl Çalışır?

  1. X/Twitter URL'sini yapıştırın ve "Önizle" butonuna tıklayın
  2. Tweet içeriği otomatik olarak çekilir (thread desteği dahil)
  3. Video stilini, süresini ve dilini seçin
  4. AI otomatik olarak senaryo yazar ve görseller üretir
  5. Video render edilir ve indirilmeye hazır hale gelir
)}
); }