import { useMemo, useState } from "react"; import { Button } from "@/components/ui/button"; import { Textarea } from "@/components/ui/textarea"; import { Badge } from "@/components/ui/badge"; import { cn } from "@/lib/utils"; import { Loader2, Send, Sparkles, ThumbsUp, ThumbsDown, Minus, } from "lucide-react"; import { motion, AnimatePresence } from "framer-motion"; import { Input } from "../ui/input"; import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue, } from "../ui/select"; import { Combobox, ComboboxContent, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList, } from "../ui/combobox"; import { Item, ItemContent, ItemDescription, ItemTitle } from "../ui/item"; interface AnalysisResult { sentiment: "positif" | "negatif" | "netral"; confidence: number; keywords: string[]; } export function SentimentAnalyzer() { const [text, setText] = useState(""); const [laptopName, setLaptopName] = useState(""); const [isAnalyzing, setIsAnalyzing] = useState(false); const [result, setResult] = useState(null); const [selectedModel, setSelectedModel] = useState< (typeof models)[number] | null >(null); const [searchQuery, setSearchQuery] = useState(""); const isFormValid = text.trim() !== "" && laptopName.trim() !== "" && selectedModel !== null; const analyzeText = async () => { if (!text.trim()) return; setIsAnalyzing(true); setResult(null); await new Promise((resolve) => setTimeout(resolve, 1500)); const positiveWords = [ "bagus", "cepat", "aman", "baik", "mulus", "moga", "awet", "mantap", "sangat", "fungsi", ]; const negativeWords = [ "lebih", "jual", "baru", "lalu", "tahun", "masalah", "rusak", "garansi", "layar", "kecewa", ]; const lowerText = text.toLowerCase(); let positiveScore = 0; let negativeScore = 0; const foundKeywords: string[] = []; positiveWords.forEach((word) => { if (lowerText.includes(word)) { positiveScore++; foundKeywords.push(word); } }); negativeWords.forEach((word) => { if (lowerText.includes(word)) { negativeScore++; foundKeywords.push(word); } }); let sentiment: AnalysisResult["sentiment"]; let confidence: number; if (positiveScore > negativeScore) { sentiment = "positif"; confidence = 0.75 + Math.random() * 0.2; } else if (negativeScore > positiveScore) { sentiment = "negatif"; confidence = 0.75 + Math.random() * 0.2; } else { sentiment = "netral"; confidence = 0.6 + Math.random() * 0.2; } setResult({ sentiment, confidence, keywords: foundKeywords, }); setIsAnalyzing(false); }; const getSentimentDisplay = (sentiment: AnalysisResult["sentiment"]) => { const config = { positif: { icon: ThumbsUp, label: "Positif", bgClass: "bg-sentiment-positive-light", textClass: "text-sentiment-positive", borderClass: "border-sentiment-positive/30", }, negatif: { icon: ThumbsDown, label: "Negatif", bgClass: "bg-sentiment-negative-light", textClass: "text-sentiment-negative", borderClass: "border-sentiment-negative/30", }, netral: { icon: Minus, label: "Netral", bgClass: "bg-sentiment-neutral-light", textClass: "text-sentiment-neutral", borderClass: "border-sentiment-neutral/30", }, }; return config[sentiment]; }; const models = [ { code: "none", value: "xgboost", label: "XGBoost (Baseline)", desc: "Model 1", }, { code: "Grid Search", value: "xgboost", label: "XGBoost (Tuned)", desc: "Model 2", }, { code: "recommended", value: "xgboost", label: "XGBoost (Fully Optimized)", desc: "Model 3", }, ]; const filteredItems = useMemo(() => { if (!searchQuery) return models; return models.filter( (model) => model.label.toLowerCase().includes(searchQuery.toLowerCase()) || model.code.toLowerCase().includes(searchQuery.toLowerCase()), ); }, [searchQuery]); return (

Analisis Sentimen Real-time

Masukkan ulasan produk laptop untuk menganalisis sentimennya menggunakan model XGBoost

setSelectedModel(val)} itemToStringValue={(model) => model?.label ?? ""} > setSearchQuery(e.target.value)} /> {filteredItems.length === 0 && ( Model "{searchQuery}" tidak ditemukan. )} {filteredItems.map((model) => ( {model.label} {model.desc} ({model.code}) ))} setLaptopName(e.target.value)} />