TIFNGK_E41222719/src/hooks/useSentiment.ts

167 lines
3.8 KiB
TypeScript

import { useMemo, useState } from "react";
import { AnalysisResult } from "../types";
import { Minus, ThumbsDown, ThumbsUp } from "lucide-react";
export const useSentiment = () => {
const [text, setText] = useState("");
const [laptopName, setLaptopName] = useState("");
const [isAnalyzing, setIsAnalyzing] = useState(false);
const [result, setResult] = useState<AnalysisResult | null>(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 = "POSITIVE";
confidence = 0.75 + Math.random() * 0.2;
} else if (negativeScore > positiveScore) {
sentiment = "NEGATIVE";
confidence = 0.75 + Math.random() * 0.2;
} else {
sentiment = "NEUTRAL";
confidence = 0.6 + Math.random() * 0.2;
}
setResult({
sentiment,
confidence,
keywords: foundKeywords,
});
setIsAnalyzing(false);
};
const getSentimentDisplay = (sentiment: AnalysisResult["sentiment"]) => {
const config = {
POSITIVE: {
icon: ThumbsUp,
label: "Positif",
bgClass: "bg-sentiment-positive-light",
textClass: "text-sentiment-positive",
borderClass: "border-sentiment-positive/30",
},
NEGATIVE: {
icon: ThumbsDown,
label: "Negatif",
bgClass: "bg-sentiment-negative-light",
textClass: "text-sentiment-negative",
borderClass: "border-sentiment-negative/30",
},
NEUTRAL: {
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 {
selectedModel,
setSelectedModel,
text,
setText,
laptopName,
setLaptopName,
isAnalyzing,
analyzeText,
result,
getSentimentDisplay,
searchQuery,
setSearchQuery,
filteredItems,
isFormValid,
};
};