main
UI Deploy (Next-Auth Support) 🎨 / build-and-deploy (push) Has been cancelled

This commit is contained in:
Harun CAN
2026-04-05 17:29:01 +03:00
parent 0c29878fb3
commit d8f9865dcf
8 changed files with 96 additions and 139 deletions
+3 -7
View File
@@ -1,14 +1,10 @@
'use client';
import Footer from '@/components/layout/footer/footer';
import { Box, Flex } from '@chakra-ui/react';
function AuthLayout({ children }: { children: React.ReactNode }) {
return (
<Flex minH='100vh' direction='column'>
<Box as='main'>{children}</Box>
<Footer />
</Flex>
<div style={{ minHeight: '100vh', display: 'flex', flexDirection: 'column' }}>
<main style={{ flex: 1 }}>{children}</main>
</div>
);
}
@@ -21,6 +21,7 @@ import Link from "next/link";
import { cn } from "@/lib/utils";
import { useCreateProject } from "@/hooks/use-api";
import { useToast } from "@/components/ui/toast";
import { projectsApi } from "@/lib/api/api-service";
const steps = ["Konu & Dil", "Stil & Süre", "AI Senaryo"];
@@ -69,17 +70,22 @@ export default function NewProjectPage() {
const handleGenerate = async () => {
try {
// Backend DTO alanları: prompt (zorunlu), videoStyle, title, language, aspectRatio, targetDuration
const result = await createProject.mutateAsync({
title: topic.slice(0, 80),
topic,
prompt: topic, // ← topic → prompt (backend alanı)
language,
style,
videoStyle: style, // ← style → videoStyle (backend alanı)
targetDuration: duration,
aspectRatio,
});
toast.success("Proje başarıyla oluşturuldu! AI senaryo üretiliyor...");
const projectId = result?.id;
if (projectId) {
// Proje oluşturulduktan sonra otomatik senaryo üretimini tetikle
projectsApi.generateScript(projectId).catch((err) => {
console.error("Senaryo üretimi başlatılamadı:", err);
});
router.push(`/dashboard/projects/${projectId}`);
} else {
router.push("/dashboard/projects");
@@ -88,8 +88,13 @@ export default function XToVideoPage() {
targetDuration: duration,
});
toast.success("Tweet → Video projesi oluşturuldu!");
const projectId = result?.id ?? result?.data?.id;
const projectId = result?.id;
if (projectId) {
// Otomatik senaryo üretimini tetikle
const { projectsApi } = await import("@/lib/api/api-service");
projectsApi.generateScript(projectId).catch((err) => {
console.error("Tweet→Video senaryo üretimi başlatılamadı:", err);
});
router.push(`/dashboard/projects/${projectId}`);
} else {
router.push("/dashboard/projects");
@@ -178,35 +183,37 @@ export default function XToVideoPage() {
{/* Author */}
<div className="flex items-center gap-3">
<div className="w-9 h-9 rounded-full bg-gradient-to-br from-violet-500/20 to-cyan-500/20 flex items-center justify-center text-sm font-bold text-violet-300">
{(previewData.author?.name ?? previewData.authorName ?? "X")?.[0]}
{(previewData.tweet?.author?.name ?? "X")?.[0]}
</div>
<div>
<p className="text-sm font-bold text-[var(--color-text-primary)]">
{previewData.author?.name ?? previewData.authorName ?? "Kullanıcı"}
{previewData.tweet?.author?.name ?? "Kullanıcı"}
</p>
<p className="text-[11px] text-[var(--color-text-ghost)]">
@{previewData.author?.handle ?? previewData.authorHandle ?? "handle"}
@{previewData.tweet?.author?.username ?? "handle"}
</p>
</div>
</div>
{/* Content */}
<p className="text-sm text-[var(--color-text-secondary)] whitespace-pre-line">
{previewData.text ?? previewData.content ?? ""}
{previewData.tweet?.text ?? ""}
</p>
{/* Images */}
{(previewData.images?.length > 0 || previewData.mediaUrls?.length > 0) && (
{(previewData.tweet?.media?.length > 0) && (
<div className="flex gap-2 overflow-x-auto">
{(previewData.images ?? previewData.mediaUrls ?? []).map(
(url: string, i: number) => (
{(previewData.tweet.media ?? [])
.filter((m: any) => m.type === 'photo')
.map(
(m: any, i: number) => (
<div
key={i}
className="w-20 h-20 rounded-lg bg-[var(--color-bg-elevated)] overflow-hidden shrink-0"
>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={url}
src={m.url}
alt={`Media ${i + 1}`}
className="w-full h-full object-cover"
/>
@@ -220,30 +227,38 @@ export default function XToVideoPage() {
<div className="flex items-center gap-4 text-[11px] text-[var(--color-text-ghost)]">
<span className="flex items-center gap-1">
<Heart size={12} />
{previewData.likes ?? previewData.stats?.likes ?? 0}
{previewData.tweet?.metrics?.likes ?? 0}
</span>
<span className="flex items-center gap-1">
<Repeat2 size={12} />
{previewData.retweets ?? previewData.stats?.retweets ?? 0}
{previewData.tweet?.metrics?.retweets ?? 0}
</span>
<span className="flex items-center gap-1">
<Eye size={12} />
{previewData.views ?? previewData.stats?.views ?? 0}
{previewData.tweet?.metrics?.views ?? 0}
</span>
{previewData.threadLength > 1 && (
{previewData.tweet?.isThread && (
<span className="flex items-center gap-1 text-violet-400">
<MessageSquare size={12} />
{previewData.threadLength} tweet thread
{previewData.tweet?.threadTweets?.length ?? 0} tweet thread
</span>
)}
</div>
</div>
{/* Suggested info */}
{previewData.suggestedTitle && (
<div className="flex items-center gap-1.5 text-[11px] text-cyan-400">
<Sparkles size={12} />
Önerilen başlık: {previewData.suggestedTitle} · Tahmini süre: {previewData.estimatedDuration}sn · Viral skoru: {previewData.viralScore}/100
</div>
)}
{/* Images tag */}
{(previewData.images?.length > 0 || previewData.mediaUrls?.length > 0) && (
{(previewData.tweet?.media?.filter((m: any) => m.type === 'photo')?.length > 0) && (
<div className="flex items-center gap-1.5 text-[11px] text-cyan-400">
<ImageIcon size={12} />
{(previewData.images ?? previewData.mediaUrls ?? []).length} görsel referans olarak kullanılacak + AI görsel üretilecek
{previewData.tweet.media.filter((m: any) => m.type === 'photo').length} görsel referans olarak kullanılacak + AI görsel üretilecek
</div>
)}
</motion.div>