Kamis, 31 Juli 2025

Simulator Roma 5:5

import React, { useState, useEffect, useRef } from 'react'; import { Send, Loader, AlertCircle } from 'lucide-react'; const initialPrompt = "Selamat datang! Simulator ini dirancang untuk mendiskusikan dan merefleksikan Roma 5:5 secara mendalam.\n\nMari kita mulai. Menurut Anda, apa makna dari 'pengharapan yang tidak mengecewakan' yang disebutkan dalam ayat ini, dan apa yang membedakannya dari optimisme biasa?"; export default function App() { const [conversation, setConversation] = useState([{ role: 'model', text: initialPrompt }]); const [userInput, setUserInput] = useState(''); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const messagesEndRef = useRef(null); // Auto-scroll to the bottom of the conversation useEffect(() => { messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); }, [conversation]); const handleSendMessage = async (e) => { e.preventDefault(); if (!userInput.trim() || isLoading) return; setError(null); const newConversation = [...conversation, { role: 'user', text: userInput }]; setConversation(newConversation); setUserInput(''); setIsLoading(true); try { // Prepare the conversation history for the API call const payload = { contents: newConversation.map(msg => ({ role: msg.role === 'user' ? 'user' : 'model', parts: [{ text: msg.text }] })) }; const apiKey = ""; const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-preview-05-20:generateContent?key=${apiKey}`; const response = await fetch(apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!response.ok) { throw new Error(`API error: ${response.status} ${response.statusText}`); } const result = await response.json(); if (result.candidates && result.candidates.length > 0 && result.candidates[0].content && result.candidates[0].content.parts && result.candidates[0].content.parts.length > 0) { const modelResponse = result.candidates[0].content.parts[0].text; setConversation(prev => [...prev, { role: 'model', text: modelResponse }]); } else { throw new Error('Unexpected API response format or empty content.'); } } catch (err) { console.error(err); setError("Maaf, terjadi kesalahan. Silakan coba lagi."); setConversation(prev => [...prev, { role: 'model', text: "Maaf, saya mengalami kesulitan untuk merespons. Bisakah Anda coba lagi atau menanyakan sesuatu yang lain?" }]); } finally { setIsLoading(false); } }; const getRoleClass = (role) => { return role === 'user' ? 'bg-orange-50 text-stone-800 self-end rounded-br-none' : 'bg-stone-50 text-stone-800 self-start rounded-bl-none'; }; return (
{conversation.map((message, index) => (

{message.text}

))} {isLoading && (
)}
{error && (

{error}

)}
setUserInput(e.target.value)} placeholder="Ketik respons atau pertanyaan Anda..." className="flex-1 p-3 border-2 border-stone-300 rounded-lg focus:outline-none focus:border-orange-500 transition-colors" disabled={isLoading} />
); }