feat: Implement text-to-video and fix hydration UI issues

This commit is contained in:
Harun CAN
2026-04-28 09:48:43 +02:00
parent 89eb9d4dfd
commit 1b69eaf219
13 changed files with 387 additions and 17 deletions
@@ -1,5 +1,6 @@
"use client";
import { useState, useEffect } from "react";
import {
AreaChart,
Area,
@@ -59,13 +60,19 @@ function formatPieData(stats: Record<string, unknown> | undefined) {
}
export function DashboardCharts() {
const [mounted, setMounted] = useState(false);
const { data, isLoading } = useDashboardStats();
useEffect(() => {
setMounted(true);
}, []);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const stats = (data as any)?.data ?? data;
const weekData = formatWeekData(stats);
const pieData = formatPieData(stats);
if (isLoading) {
if (!mounted || isLoading) {
return (
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4 md:gap-6">
{[1, 2].map((i) => (
+1
View File
@@ -13,6 +13,7 @@ const navItems = [
{ href: "/dashboard", icon: Home, label: "Ana Sayfa" },
{ href: "/dashboard/projects", icon: FolderOpen, label: "Projeler" },
{ href: "/dashboard/render-queue", icon: Activity, label: "Render Monitör" },
{ href: "/dashboard/text-to-video", icon: FileText, label: "Metin → Video" },
{ href: "/dashboard/x-to-video", icon: AtSign, label: "X → Video" },
{ href: "/dashboard/youtube-to-video", icon: Link2, label: "YT → Video" },
{ href: "/dashboard/document-to-video", icon: FileText, label: "Belge → Video" },
+31 -2
View File
@@ -16,12 +16,41 @@ const STAGE_DETAILS: Record<string, { label: string; icon: string; color: string
interface RenderProgressProps {
renderState: RenderProgressState;
projectStatus?: string;
}
export function RenderProgress({ renderState }: RenderProgressProps) {
export function RenderProgress({ renderState, projectStatus }: RenderProgressProps) {
const { progress, stage, stageLabel, currentScene, totalScenes, eta, status, isConnected } = renderState;
if (status === 'idle') return null;
if (status === 'idle') {
return (
<motion.div
initial={{ opacity: 0, y: 12 }}
animate={{ opacity: 1, y: 0 }}
className="card-surface p-5 md:p-6"
>
<div className="flex items-center justify-between">
<div className="flex items-center gap-2.5">
<Loader2 size={18} className="animate-spin text-amber-400" />
<h3 className="text-sm font-semibold text-[var(--color-text-primary)]">
{projectStatus === 'GENERATING_SCRIPT' ? 'AI Senaryo Üretiyor...' : 'İşlem kuyrukta veya başlatılıyor...'}
</h3>
</div>
<div className="flex items-center gap-1.5">
{isConnected ? (
<Wifi size={13} className="text-emerald-400" />
) : (
<WifiOff size={13} className="text-red-400" />
)}
<span className="text-[10px] text-[var(--color-text-ghost)]">
{isConnected ? 'Canlı' : 'Bağlantı koptu'}
</span>
</div>
</div>
</motion.div>
);
}
return (
<motion.div
+16 -12
View File
@@ -1,5 +1,7 @@
"use client";
import { ChakraProvider } from "@chakra-ui/react";
import { system } from "@/theme/theme";
import { SessionProvider } from "next-auth/react";
import { ThemeProvider } from "next-themes";
import ReactQueryProvider from "@/provider/react-query-provider";
@@ -7,17 +9,19 @@ import { ToastProvider } from "@/components/ui/toast";
export function Provider({ children }: { children: React.ReactNode }) {
return (
<SessionProvider>
<ReactQueryProvider>
<ThemeProvider
attribute="class"
defaultTheme="dark"
enableSystem={false}
disableTransitionOnChange
>
<ToastProvider>{children}</ToastProvider>
</ThemeProvider>
</ReactQueryProvider>
</SessionProvider>
<ChakraProvider value={system}>
<SessionProvider>
<ReactQueryProvider>
<ThemeProvider
attribute="class"
defaultTheme="dark"
enableSystem={false}
disableTransitionOnChange
>
<ToastProvider>{children}</ToastProvider>
</ThemeProvider>
</ReactQueryProvider>
</SessionProvider>
</ChakraProvider>
);
}