generated from fahricansecer/boilerplate-fe
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
import { useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useCreateFromDocument } from "@/hooks/use-api";
|
||||
import { useExtractDocumentTopics, useCreateFromExtractedText } from "@/hooks/use-api";
|
||||
import { useToast } from "@/components/ui/toast";
|
||||
import {
|
||||
FileText,
|
||||
@@ -42,9 +42,13 @@ export default function DocumentToVideoPage() {
|
||||
const router = useRouter();
|
||||
const { toast } = useToast();
|
||||
|
||||
const createFromDocument = useCreateFromDocument();
|
||||
const extractDocumentTopics = useExtractDocumentTopics();
|
||||
const createFromExtractedText = useCreateFromExtractedText();
|
||||
|
||||
const [file, setFile] = useState<File | null>(null);
|
||||
const [extractedData, setExtractedData] = useState<{text: string; topics: string[]; originalFilename: string} | null>(null);
|
||||
const [selectedTopic, setSelectedTopic] = useState<string | null>(null);
|
||||
|
||||
const [style, setStyle] = useState("CINEMATIC");
|
||||
const [cinematicReference, setCinematicReference] = useState("");
|
||||
const [duration, setDuration] = useState(60);
|
||||
@@ -54,18 +58,40 @@ export default function DocumentToVideoPage() {
|
||||
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (e.target.files && e.target.files.length > 0) {
|
||||
setFile(e.target.files[0]);
|
||||
setExtractedData(null);
|
||||
setSelectedTopic(null);
|
||||
}
|
||||
};
|
||||
|
||||
const handleGenerate = async () => {
|
||||
const handleExtractTopics = async () => {
|
||||
if (!file) {
|
||||
toast("error", "Lütfen bir belge seçin.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const result: any = await createFromDocument.mutateAsync({
|
||||
file,
|
||||
const result = await extractDocumentTopics.mutateAsync({ file });
|
||||
setExtractedData(result);
|
||||
if (result.topics.length > 0) {
|
||||
setSelectedTopic(result.topics[0]);
|
||||
}
|
||||
toast("success", "Belge incelendi ve konular çıkarıldı!");
|
||||
} catch (error) {
|
||||
toast("error", "Konu çıkarılırken hata oluştu. Belki belge okunamıyor veya çok büyük.");
|
||||
}
|
||||
};
|
||||
|
||||
const handleGenerate = async () => {
|
||||
if (!extractedData || !selectedTopic) {
|
||||
toast("error", "Lütfen bir belge yükleyip konu seçin.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const result: any = await createFromExtractedText.mutateAsync({
|
||||
text: extractedData.text,
|
||||
topic: selectedTopic,
|
||||
originalFilename: extractedData.originalFilename,
|
||||
language,
|
||||
aspectRatio,
|
||||
videoStyle: style,
|
||||
@@ -73,7 +99,7 @@ export default function DocumentToVideoPage() {
|
||||
targetDuration: duration,
|
||||
});
|
||||
|
||||
toast("success", "Belge → Video projesi oluşturuldu!");
|
||||
toast("success", "Video projesi oluşturuldu!");
|
||||
router.push(`/dashboard/projects/${result.id}`);
|
||||
} catch (error) {
|
||||
toast("error", "Proje oluşturulurken hata oluştu.");
|
||||
@@ -115,6 +141,51 @@ export default function DocumentToVideoPage() {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{!extractedData && file && (
|
||||
<button
|
||||
onClick={handleExtractTopics}
|
||||
disabled={extractDocumentTopics.isPending}
|
||||
className="w-full flex items-center justify-center gap-2 py-3.5 rounded-xl font-medium text-white shadow-lg bg-blue-500 hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
{extractDocumentTopics.isPending ? (
|
||||
<>
|
||||
<Loader2 size={18} className="animate-spin" />
|
||||
Belge İnceleniyor...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<FileText size={18} />
|
||||
Konu Çıkar
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
)}
|
||||
|
||||
{extractedData && (
|
||||
<div className="mt-6 p-4 rounded-xl bg-blue-500/5 border border-blue-500/20">
|
||||
<h3 className="font-medium text-blue-400 mb-3 text-sm flex items-center gap-2">
|
||||
<Wand2 size={16} />
|
||||
Şu Konulardan Birini Seçin:
|
||||
</h3>
|
||||
<div className="space-y-2">
|
||||
{extractedData.topics.map((topic, i) => (
|
||||
<div
|
||||
key={i}
|
||||
onClick={() => setSelectedTopic(topic)}
|
||||
className={cn(
|
||||
"p-3 rounded-lg border text-sm cursor-pointer transition-all",
|
||||
selectedTopic === topic
|
||||
? "bg-blue-500/20 border-blue-500 text-blue-400"
|
||||
: "bg-[var(--color-bg-surface)] border-[var(--color-border-faint)] text-[var(--color-text-secondary)] hover:border-blue-500/50"
|
||||
)}
|
||||
>
|
||||
{topic}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Video Settings */}
|
||||
@@ -235,16 +306,16 @@ export default function DocumentToVideoPage() {
|
||||
|
||||
<button
|
||||
onClick={handleGenerate}
|
||||
disabled={createFromDocument.isPending || !file}
|
||||
disabled={createFromExtractedText.isPending || !selectedTopic}
|
||||
className={cn(
|
||||
"w-full py-4 rounded-xl font-semibold text-base flex items-center justify-center gap-2 transition-all",
|
||||
createFromDocument.isPending
|
||||
createFromExtractedText.isPending
|
||||
? "bg-blue-500/20 text-blue-400 cursor-wait"
|
||||
: "bg-blue-500 hover:bg-blue-600 text-white shadow-lg shadow-blue-500/20",
|
||||
!file && "opacity-50 cursor-not-allowed"
|
||||
!selectedTopic && "opacity-50 cursor-not-allowed"
|
||||
)}
|
||||
>
|
||||
{createFromDocument.isPending ? (
|
||||
{createFromExtractedText.isPending ? (
|
||||
<>
|
||||
<Loader2 size={20} className="animate-spin" />
|
||||
<span>Video Projesi Oluşturuluyor... (Bu işlem uzun sürebilir)</span>
|
||||
@@ -252,7 +323,7 @@ export default function DocumentToVideoPage() {
|
||||
) : (
|
||||
<>
|
||||
<Wand2 size={20} />
|
||||
<span>Belge → Video Oluştur</span>
|
||||
<span>Konudan Video Oluştur</span>
|
||||
<ArrowRight size={16} />
|
||||
</>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user