import React, { useState, useEffect } from 'react'; const FeedbackWeighting = ({ onComplete, onCancel }) => { const [feedbackWords, setFeedbackWords] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [submitting, setSubmitting] = useState(false); const [weights, setWeights] = useState({}); useEffect(() => { fetchQueuedFeedbackWords(); }, []); const fetchQueuedFeedbackWords = async () => { setLoading(true); setError(null); try { const response = await fetch('/api/v1/feedback/queued'); if (response.ok) { const data = await response.json(); const words = data.queued_words || []; setFeedbackWords(words); // Initialize weights state const initialWeights = {}; words.forEach(word => { initialWeights[word.word] = word.weight; }); setWeights(initialWeights); } else { throw new Error(`Failed to fetch feedback words: ${response.status}`); } } catch (err) { console.error('Error fetching feedback words:', err); setError('Failed to load feedback words. Please try again.'); // Fallback to mock data for development const mockWords = [ { key: 'feedback00', word: 'labyrinth', weight: 3 }, { key: 'feedback01', word: 'residue', weight: 3 }, { key: 'feedback02', word: 'tremor', weight: 3 }, { key: 'feedback03', word: 'effigy', weight: 3 }, { key: 'feedback04', word: 'quasar', weight: 3 }, { key: 'feedback05', word: 'gossamer', weight: 3 } ]; setFeedbackWords(mockWords); const initialWeights = {}; mockWords.forEach(word => { initialWeights[word.word] = word.weight; }); setWeights(initialWeights); } finally { setLoading(false); } }; const handleWeightChange = (word, newWeight) => { setWeights(prev => ({ ...prev, [word]: newWeight })); }; const handleSubmit = async () => { setSubmitting(true); setError(null); try { const response = await fetch('/api/v1/feedback/rate', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ ratings: weights }) }); if (response.ok) { const data = await response.json(); console.log('Feedback words rated successfully:', data); // Call onComplete callback if provided if (onComplete) { onComplete(data); } } else { const errorData = await response.json(); throw new Error(errorData.detail || `Failed to rate feedback words: ${response.status}`); } } catch (err) { console.error('Error rating feedback words:', err); setError(`Failed to submit ratings: ${err.message}`); } finally { setSubmitting(false); } }; const getWeightLabel = (weight) => { const labels = { 0: 'Ignore', 1: 'Very Low', 2: 'Low', 3: 'Medium', 4: 'High', 5: 'Very High', 6: 'Essential' }; return labels[weight] || 'Medium'; }; const getWeightColor = (weight) => { const colors = { 0: 'bg-gray-200 text-gray-700', 1: 'bg-red-100 text-red-700', 2: 'bg-orange-100 text-orange-700', 3: 'bg-yellow-100 text-yellow-700', 4: 'bg-blue-100 text-blue-700', 5: 'bg-indigo-100 text-indigo-700', 6: 'bg-purple-100 text-purple-700' }; return colors[weight] || 'bg-yellow-100 text-yellow-700'; }; if (loading) { return (
Loading feedback words...
); } return (

Weight Feedback Themes

Rate how much each theme should influence future prompt generation. Higher weights mean the theme will have more influence.

{error && (

{error}

)}
{feedbackWords.map((item, index) => (
Theme {index + 1}

{item.word}

{getWeightLabel(weights[item.word] || 3)}
handleWeightChange(item.word, parseInt(e.target.value))} className="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer" />
Ignore (0) Medium (3) Essential (6)
{[0, 1, 2, 3, 4, 5, 6].map(weight => ( ))}
Current: {weights[item.word] || 3}
))}
Your ratings will influence future prompt generation
); }; export default FeedbackWeighting;