Lin / frontend /src /components /KeywordTrendAnalyzer.jsx
Zelyanoth's picture
feat: add keyword analysis functionality and enhance content service
3c29fcc
import React from 'react';
import useKeywordAnalysis from '../hooks/useKeywordAnalysis';
const KeywordTrendAnalyzer = () => {
const {
keyword,
setKeyword,
analysisData,
patternAnalysis,
loading,
patternLoading,
error,
analyzeKeyword,
analyzeKeywordPattern
} = useKeywordAnalysis();
const handleAnalyzeClick = async () => {
try {
// Run both analyses in parallel
await Promise.all([
analyzeKeyword(),
analyzeKeywordPattern()
]);
} catch (err) {
// Error is handled within the individual functions
console.error('Analysis error:', err);
}
};
return (
<div className="keyword-trend-analyzer p-6 bg-white rounded-lg shadow-md">
<h2 className="text-xl font-bold mb-4 text-gray-900">Keyword Frequency Pattern Analysis</h2>
<div className="flex gap-4 mb-6">
<input
type="text"
value={keyword}
onChange={(e) => setKeyword(e.target.value)}
placeholder="Enter keyword to analyze"
className="flex-1 px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 text-gray-900"
/>
<button
onClick={handleAnalyzeClick}
disabled={loading || patternLoading}
className="px-6 py-2 rounded-md bg-blue-600 hover:bg-blue-700 text-white focus:outline-none focus:ring-2 focus:ring-blue-500 disabled:opacity-50"
>
{loading || patternLoading ? 'Processing...' : 'Analyze'}
</button>
</div>
{error && (
<div className="mb-4 p-3 bg-red-100 text-red-700 rounded-md">
{error}
</div>
)}
{/* Pattern Analysis Results */}
{patternAnalysis && !patternLoading && (
<div className="mt-6">
<h3 className="text-lg font-semibold mb-4 text-gray-900">Frequency Pattern Analysis for "{keyword}"</h3>
<div className="bg-gray-50 rounded-lg p-4 mb-6">
<div className="flex items-center justify-between mb-2">
<span className="text-sm font-medium text-gray-700">Pattern:</span>
<span className={`px-3 py-1 rounded-full text-sm font-semibold ${
patternAnalysis.pattern === 'daily' ? 'bg-blue-100 text-blue-800' :
patternAnalysis.pattern === 'weekly' ? 'bg-green-100 text-green-800' :
patternAnalysis.pattern === 'monthly' ? 'bg-yellow-100 text-yellow-800' :
'bg-red-100 text-red-800'
}`}>
{patternAnalysis.pattern.toUpperCase()}
</span>
</div>
<p className="text-gray-600 text-sm mb-1"><strong>Explanation:</strong> {patternAnalysis.details.explanation}</p>
<p className="text-gray-600 text-sm"><strong>Confidence:</strong> {(patternAnalysis.details.confidence * 100).toFixed(0)}%</p>
<p className="text-gray-600 text-sm"><strong>Total Articles:</strong> {patternAnalysis.total_articles}</p>
{patternAnalysis.date_range.start && patternAnalysis.date_range.end && (
<p className="text-gray-600 text-sm">
<strong>Date Range:</strong> {patternAnalysis.date_range.start} to {patternAnalysis.date_range.end}
</p>
)}
</div>
</div>
)}
{/* Recent Articles Table */}
{patternAnalysis && patternAnalysis.articles && patternAnalysis.articles.length > 0 && (
<div className="mt-6">
<h3 className="text-lg font-semibold mb-4 text-gray-900">5 Most Recent Articles for "{keyword}"</h3>
<div className="overflow-x-auto">
<table className="min-w-full border border-gray-200 rounded-md">
<thead>
<tr className="bg-gray-100">
<th className="py-2 px-4 border-b text-left text-gray-700">Title</th>
<th className="py-2 px-4 border-b text-left text-gray-700">Date</th>
</tr>
</thead>
<tbody>
{patternAnalysis.articles.slice(0, 5).map((article, index) => {
// Format the date from the article
let formattedDate = 'N/A';
if (article.date) {
try {
// Parse the date string - it could be in various formats
const date = new Date(article.date);
// If the date parsing failed, try to extract date from the link if it's in the format needed
if (isNaN(date.getTime())) {
// Handle different date formats if needed
// Try to extract from the link or other format
formattedDate = 'N/A';
} else {
// Format date as "09/oct/25" (day/mon/yy)
const day = date.getDate().toString().padStart(2, '0');
const month = date.toLocaleString('default', { month: 'short' }).toLowerCase();
const year = date.getFullYear().toString().slice(-2);
formattedDate = `${day}/${month}/${year}`;
}
} catch (e) {
formattedDate = 'N/A';
}
}
return (
<tr key={index} className={index % 2 === 0 ? 'bg-white' : 'bg-gray-50'}>
<td className="py-2 px-4 border-b text-gray-900 text-sm">
<a
href={article.link}
target="_blank"
rel="noopener noreferrer"
className="text-blue-600 hover:text-blue-800 underline"
>
{article.title}
</a>
</td>
<td className="py-2 px-4 border-b text-gray-900 text-sm">{formattedDate}</td>
</tr>
);
})}
</tbody>
</table>
</div>
</div>
)}
</div>
);
};
export default KeywordTrendAnalyzer;