Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/pages/AnalyzePage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ function AnalyzePage() {
localStorage.setItem('triageHistory', JSON.stringify(history))
} catch (error) {
console.error('Error analyzing message:', error)
alert('Error analyzing message. Please try again.')
alert('Error analyzing message. Please check your API key setup.')
} finally {
setIsLoading(false)
}
Expand Down
8 changes: 4 additions & 4 deletions src/pages/DashboardPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@ function DashboardPage() {
const [categoryData, setCategoryData] = useState([])
const [urgencyData, setUrgencyData] = useState({ High: 0, Medium: 0, Low: 0 })

useEffect(() => {
loadDashboardData()
}, [])

const loadDashboardData = () => {
const history = JSON.parse(localStorage.getItem('triageHistory') || '[]')
const today = new Date().toDateString()
Expand Down Expand Up @@ -47,6 +43,10 @@ function DashboardPage() {
setUrgencyData(urgency)
}

useEffect(() => {
loadDashboardData()
}, []) // eslint-disable-line react-hooks/exhaustive-deps

return (
<div className="min-h-screen bg-gray-50 py-8">
<div className="max-w-7xl mx-auto px-4">
Expand Down
149 changes: 109 additions & 40 deletions src/pages/HistoryPage.jsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
import { useState, useEffect } from 'react'
import ReactMarkdown from 'react-markdown'

function HistoryPage() {
const [history, setHistory] = useState([])
const [filter, setFilter] = useState('all')
const [categoryFilter, setCategoryFilter] = useState('all')
const [urgencyFilter, setUrgencyFilter] = useState('all')
const [expandedIndex, setExpandedIndex] = useState(null)

/* eslint-disable react-hooks/set-state-in-effect */
useEffect(() => {
loadHistory()
try {
const savedHistory = JSON.parse(localStorage.getItem('triageHistory') || '[]')
setHistory(savedHistory)
} catch (error) {
console.error('Error loading history:', error)
setHistory([])
}
}, [])

const loadHistory = () => {
const savedHistory = JSON.parse(localStorage.getItem('triageHistory') || '[]')
setHistory(savedHistory)
}
/* eslint-enable react-hooks/set-state-in-effect */

const clearHistory = () => {
if (window.confirm('Are you sure you want to clear all history?')) {
Expand All @@ -26,11 +29,14 @@ function HistoryPage() {
a.message.localeCompare(b.message)
)

const filteredHistory = filter === 'all'
? sortedHistory
: sortedHistory.filter(item => item.category === filter)
const filteredHistory = sortedHistory.filter(item => {
const categoryMatch = categoryFilter === 'all' || item.category === categoryFilter
const urgencyMatch = urgencyFilter === 'all' || item.urgency === urgencyFilter
return categoryMatch && urgencyMatch
})

const categories = [...new Set(history.map(item => item.category))]
const categories = [...new Set(history.map(item => item.category).filter(Boolean))]
const urgencies = ['High', 'Medium', 'Low']

return (
<div className="min-h-screen bg-gray-50 py-8">
Expand All @@ -53,36 +59,82 @@ function HistoryPage() {

{/* Filter Buttons */}
{history.length > 0 && (
<div className="flex flex-wrap gap-2 mb-6">
<button
onClick={() => setFilter('all')}
className={`px-4 py-2 rounded-lg font-semibold ${
filter === 'all'
? 'bg-blue-600 text-white'
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
}`}
>
All ({history.length})
</button>
{categories.map(category => (
<button
key={category}
onClick={() => setFilter(category)}
className={`px-4 py-2 rounded-lg font-semibold ${
filter === category
? 'bg-blue-600 text-white'
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
}`}
>
{category} ({history.filter(h => h.category === category).length})
</button>
))}
<div className="space-y-4 mb-6">
{/* Category Filters */}
<div>
<h3 className="text-sm font-semibold text-gray-700 mb-2">Filter by Category:</h3>
<div className="flex flex-wrap gap-2">
<button
onClick={() => setCategoryFilter('all')}
className={`px-4 py-2 rounded-lg font-semibold ${
categoryFilter === 'all'
? 'bg-blue-600 text-white'
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
}`}
>
All Categories ({history.length})
</button>
{categories.map(category => {
const count = history.filter(h => h.category === category).length
return (
<button
key={category}
onClick={() => setCategoryFilter(category)}
className={`px-4 py-2 rounded-lg font-semibold ${
categoryFilter === category
? 'bg-blue-600 text-white'
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
}`}
>
{category} ({count})
</button>
)
})}
</div>
</div>

{/* Urgency Filters */}
<div>
<h3 className="text-sm font-semibold text-gray-700 mb-2">Filter by Urgency:</h3>
<div className="flex flex-wrap gap-2">
<button
onClick={() => setUrgencyFilter('all')}
className={`px-4 py-2 rounded-lg font-semibold ${
urgencyFilter === 'all'
? 'bg-green-600 text-white'
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
}`}
>
All Urgencies ({history.length})
</button>
{urgencies.map(urgency => {
const count = history.filter(h => h.urgency === urgency).length
return (
<button
key={urgency}
onClick={() => setUrgencyFilter(urgency)}
className={`px-4 py-2 rounded-lg font-semibold ${
urgencyFilter === urgency
? urgency === 'High' ? 'bg-red-600 text-white' :
urgency === 'Medium' ? 'bg-yellow-600 text-white' :
'bg-green-600 text-white'
: urgency === 'High' ? 'bg-red-100 text-red-700 hover:bg-red-200' :
urgency === 'Medium' ? 'bg-yellow-100 text-yellow-700 hover:bg-yellow-200' :
'bg-green-100 text-green-700 hover:bg-green-200'
}`}
>
{urgency} Urgency ({count})
</button>
)
})}
</div>
</div>
</div>
)}
</div>

{/* History List */}
{filteredHistory.length === 0 && (
{filteredHistory.length === 0 && history.length === 0 && (
<div className="bg-white rounded-lg shadow-md p-12 text-center">
<div className="text-5xl mb-4">📭</div>
<div className="text-xl text-gray-600 mb-2">No history yet</div>
Expand All @@ -98,6 +150,25 @@ function HistoryPage() {
</div>
)}

{filteredHistory.length === 0 && history.length > 0 && (
<div className="bg-white rounded-lg shadow-md p-12 text-center">
<div className="text-3xl mb-4">🔍</div>
<div className="text-xl text-gray-600 mb-2">No results match your filters</div>
<p className="text-gray-500 mb-6">
Try adjusting your category or urgency filters
</p>
<button
onClick={() => {
setCategoryFilter('all')
setUrgencyFilter('all')
}}
className="inline-block bg-blue-600 text-white px-6 py-3 rounded-lg hover:bg-blue-700 font-semibold"
>
Clear Filters
</button>
</div>
)}

<div className="space-y-4">
{filteredHistory.map((item, index) => (
<div
Expand Down Expand Up @@ -154,9 +225,7 @@ function HistoryPage() {
<div className="text-xs font-semibold text-gray-600 mb-1">AI Reasoning</div>
<div className="bg-white p-3 rounded border border-gray-200">
<div className="prose prose-sm max-w-none text-gray-700">
<ReactMarkdown>
{item.reasoning}
</ReactMarkdown>
<pre className="whitespace-pre-wrap font-sans">{item.reasoning}</pre>
</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/HomePage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function HomePage() {

// Get recent 3 items
setRecentActivity(history.slice(-3).reverse())
}, [])
}, []) // eslint-disable-line react-hooks/exhaustive-deps

return (
<div className="min-h-screen bg-gray-50 py-8">
Expand Down
8 changes: 6 additions & 2 deletions src/utils/llmHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import Groq from 'groq-sdk';
*/

// Initialize Groq client
const groq = new Groq({
const groq = import.meta.env.VITE_GROQ_API_KEY ? new Groq({
apiKey: import.meta.env.VITE_GROQ_API_KEY,
dangerouslyAllowBrowser: true // Required for browser-based calls (not recommended for production!)
});
}) : null;

/**
* Categorize a customer support message using Groq AI
Expand All @@ -18,6 +18,10 @@ const groq = new Groq({
* @returns {Promise<{category: string, reasoning: string}>}
*/
export async function categorizeMessage(message) {
if (!groq) {
throw new Error('Groq API key not configured. Please set VITE_GROQ_API_KEY in your .env.local file.')
}

try {
const response = await groq.chat.completions.create({
model: "llama-3.3-70b-versatile",
Expand Down