| | 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 { |
| | |
| | await Promise.all([ |
| | analyzeKeyword(), |
| | analyzeKeywordPattern() |
| | ]); |
| | } catch (err) { |
| | |
| | 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; |