import React, { useState, useEffect, useRef } from 'react'; import { Camera, Type, ArrowLeft, Sparkles, Copy, RefreshCw, Check, Upload, ChevronRight, Loader2, AlertCircle } from 'lucide-react'; const API_KEY = ""; // Environment menyediakan API Key otomatis export default function App() { const [step, setStep] = useState(1); const [inputMode, setInputMode] = useState(null); const [isLoading, setIsLoading] = useState(false); const [result, setResult] = useState(null); const [copySuccess, setCopySuccess] = useState(false); const [errorMessage, setErrorMessage] = useState(""); const [formData, setFormData] = useState({ productName: '', productDesc: '', userIdea: '', photoData: null, style: 'Story Telling', format: 'Ngomong ke Kamera', duration: '30', target: 'Audiens Umum', platform: 'TikTok' }); const fileInputRef = useRef(null); const styles = ['Story Telling', 'Santai atau Kasual', 'Edukasi', 'Soft Selling', 'Hard Selling', 'Review Produk']; const formats = ['Ngomong ke Kamera', 'Voice Over', 'Masalah dan Solusi', 'Hook > Jelaskan > CTA']; const durations = ['15', '30', '60']; const targets = [ 'Cowok 18-24 tahun (Gen Z)', 'Cewek 18-24 tahun (Gen Z)', 'Cowok 25-34 tahun', 'Cewek 25-34 tahun', 'Bapak-bapak dan Ibu-ibu', 'Audiens Umum' ]; const platforms = ['TikTok', 'Instagram', 'Facebook', 'YouTube']; const handleInputChange = (field, value) => { setFormData(prev => ({ ...prev, [field]: value })); }; const handleFileUpload = (e) => { const file = e.target.files[0]; if (file) { if (file.size > 4 * 1024 * 1024) { setErrorMessage("Ukuran foto terlalu besar (maks 4MB)"); return; } const reader = new FileReader(); reader.onloadend = () => { handleInputChange('photoData', reader.result); setErrorMessage(""); }; reader.readAsDataURL(file); } }; const generateScript = async () => { setIsLoading(true); setResult(null); setErrorMessage(""); const systemPrompt = `Kamu adalah pakar Viral Copywriter. Buat script video pendek. Output WAJIB JSON murni: { "hook": "1 kalimat pancingan", "content": "naskah inti", "cta": "ajakan bertindak", "longCaption": "caption 3 paragraf persuasif", "hashtags": "#tag1 #tag2 #tag3" }`; const userPrompt = `Produk: ${formData.productName}. Deskripsi: ${formData.productDesc}. Ide: ${formData.userIdea}. Gaya: ${formData.style}. Format: ${formData.format}. Durasi: ${formData.duration}s. Target: ${formData.target}. Platform: ${formData.platform}.`; const fetchWithRetry = async (retries = 3, backoff = 1000) => { try { const isPhoto = inputMode === 'photo' && formData.photoData; const response = await fetch( `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-preview-09-2025:generateContent?key=${API_KEY}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ contents: [{ parts: [ { text: userPrompt }, ...(isPhoto ? [{ inlineData: { mimeType: "image/png", data: formData.photoData.split(',')[1] } }] : []) ] }], systemInstruction: { parts: [{ text: systemPrompt }] }, generationConfig: { responseMimeType: "application/json" } }) } ); if (!response.ok) throw new Error(`HTTP Error ${response.status}`); const data = await response.json(); const textResponse = data.candidates?.[0]?.content?.parts?.[0]?.text; if (!textResponse) throw new Error("AI tidak memberikan respon teks."); const parsedData = JSON.parse(textResponse); setResult(parsedData); setStep(3); } catch (error) { if (retries > 0) { await new Promise(r => setTimeout(r, backoff)); return fetchWithRetry(retries - 1, backoff * 2); } setErrorMessage("Gagal membuat script. Silakan periksa koneksi atau coba deskripsi yang lebih pendek."); console.error(error); } finally { setIsLoading(false); } }; fetchWithRetry(); }; const copyToClipboard = () => { const textToCopy = `[HOOK]\n${result.hook}\n\n[ISI]\n${result.content}\n\n[CTA]\n${result.cta}\n\n[CAPTION]\n${result.longCaption}\n\n[TAGS]\n${result.hashtags}`; const textArea = document.createElement("textarea"); textArea.value = textToCopy; document.body.appendChild(textArea); textArea.select(); document.execCommand('copy'); document.body.removeChild(textArea); setCopySuccess(true); setTimeout(() => setCopySuccess(false), 2000); }; return (
{/* Header */}

Ardi'Script Generator

{step > 1 && !isLoading && ( )}
{errorMessage && (

{errorMessage}

)} {step === 1 && (

Mulai Konten Viral!

Pilih metode input untuk naskah AI Anda.

)} {step === 2 && (
{inputMode === 'text' ? (