File size: 6,267 Bytes
3c29fcc |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
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; |