Bbcfgh

import React, { useState, useEffect } from 'react'; import { initializeApp } from 'firebase/app'; import { getAuth, signInWithCustomToken, signInAnonymously, GoogleAuthProvider, signInWithPopup, signOut, onAuthStateChanged } from 'firebase/auth'; import { getFirestore, collection, query, onSnapshot, addDoc, serverTimestamp, getDocs, where } from 'firebase/firestore'; import { Star, Send, LogIn, LogOut, ShieldCheck, AlertCircle, Loader2 } from 'lucide-react'; // ========================================== // CONFIGURASI FIREBASE // Tempelkan konfigurasi Firebase Anda di sini // ========================================== const firebaseConfig = JSON.parse(__firebase_config); const app = initializeApp(firebaseConfig); const auth = getAuth(app); const db = getFirestore(app); const appId = typeof __app_id !== 'undefined' ? __app_id : 'blogger-comments-v1'; const apiKey = ""; // API Key untuk Gemini AI (otomatis terisi di runtime) const App = () => { const [user, setUser] = useState(null); const [comments, setComments] = useState([]); const [newComment, setNewComment] = useState(""); const [rating, setRating] = useState(5); const [hover, setHover] = useState(0); const [loading, setLoading] = useState(false); const [hasCommented, setHasCommented] = useState(false); const [error, setError] = useState(null); // 1. Initial Auth & User State useEffect(() => { const initAuth = async () => { if (typeof __initial_auth_token !== 'undefined' && __initial_auth_token) { await signInWithCustomToken(auth, __initial_auth_token); } }; initAuth(); const unsubscribe = onAuthStateChanged(auth, (u) => { setUser(u); if (u) checkUserCommentStatus(u.uid); }); return () => unsubscribe(); }, []); // 2. Real-time Comments Fetching useEffect(() => { if (!user) return; const q = collection(db, 'artifacts', appId, 'public', 'data', 'comments'); const unsubscribe = onSnapshot(q, (snapshot) => { const docs = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })); // Sort manual (Rule 2: No complex queries/orderBy) const sorted = docs.sort((a, b) => b.createdAt?.seconds - a.createdAt?.seconds); setComments(sorted); }, (err) => { console.error("Firestore Error:", err); }); return () => unsubscribe(); }, [user]); const checkUserCommentStatus = async (uid) => { const q = collection(db, 'artifacts', appId, 'public', 'data', 'comments'); const querySnapshot = await getDocs(q); const alreadyCommented = querySnapshot.docs.some(doc => doc.data().userId === uid); setHasCommented(alreadyCommented); }; const handleGoogleLogin = async () => { const provider = new GoogleAuthProvider(); try { await signInWithPopup(auth, provider); } catch (err) { setError("Gagal login dengan Google."); } }; const handleLogout = () => signOut(auth); // 3. AI Moderation via Gemini const moderateWithAI = async (text) => { try { const prompt = `Lakukan moderasi konten untuk komentar blog berikut: "${text}". Berikan respon JSON murni dengan format: {"isSafe": boolean, "reason": "string"}. isSafe false jika mengandung kata kasar, spam, sara, atau ujaran kebencian dalam bahasa Indonesia.`; const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-preview-09-2025:generateContent?key=${apiKey}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ contents: [{ parts: [{ text: prompt }] }], generationConfig: { responseMimeType: "application/json" } }) }); const result = await response.json(); return JSON.parse(result.candidates[0].content.parts[0].text); } catch (err) { console.error("AI Moderation Error", err); return { isSafe: true }; // Fallback jika AI error } }; const handleSubmit = async (e) => { e.preventDefault(); if (!newComment.trim() || hasCommented) return; setLoading(true); setError(null); // AI Check const moderation = await moderateWithAI(newComment); if (!moderation.isSafe) { setError(`Komentar ditolak: ${moderation.reason}`); setLoading(false); return; } try { await addDoc(collection(db, 'artifacts', appId, 'public', 'data', 'comments'), { userId: user.uid, userName: user.displayName, userPhoto: user.photoURL, text: newComment, rating: rating, createdAt: serverTimestamp() }); setNewComment(""); setHasCommented(true); } catch (err) { setError("Gagal mengirim komentar."); } finally { setLoading(false); } }; return (

Komentar & Rating

{/* Auth Section */} {!user ? (

Login Diperlukan

Silakan login dengan akun Gmail Anda untuk memberikan rating dan komentar.

) : (
{/* Form Komentar */} {!hasCommented ? (
{user.displayName}

{user.displayName}

Memberikan ulasan sekali saja

{/* Bintang Rating */}
{[1, 2, 3, 4, 5].map((star) => ( ))}
{/* Input Teks */}