Spaces:
Running
Running
import React, { useState } from 'react'; | |
import { useAuth } from '../../hooks/useAuth'; | |
import { | |
Box, | |
Button, | |
Typography, | |
Paper, | |
Radio, | |
RadioGroup, | |
FormControlLabel, | |
FormControl, | |
FormLabel, | |
Slider, | |
Rating, | |
Alert | |
} from '@mui/material'; | |
import styled from '@emotion/styled'; | |
import { saveFeedback } from '../../services/search'; | |
const StyledPaper = styled(Paper)(({ theme }) => ({ | |
padding: theme.spacing(3), | |
marginTop: theme.spacing(3), | |
backgroundColor: theme.palette.background.paper, | |
})); | |
const FeedbackForm = ({ searchResult, query, onFeedbackSubmitted }) => { | |
const { user, authTokens, userType } = useAuth(); | |
const [reaction, setReaction] = useState(''); | |
const [confidence, setConfidence] = useState(5); | |
const [rating, setRating] = useState(3); | |
const [isSubmitting, setIsSubmitting] = useState(false); | |
const [error, setError] = useState(null); | |
const [success, setSuccess] = useState(false); | |
if (!searchResult || typeof searchResult !== 'object') { | |
return ( | |
<Alert severity="error">Invalid search result data</Alert> | |
); | |
} | |
const handleSubmit = async (e) => { | |
e.preventDefault(); | |
setIsSubmitting(true); | |
setError(null); | |
try { | |
// Extract only the needed properties for the backend | |
const feedbackData = { | |
user_type: userType, | |
username: user, | |
query: query || '', | |
retrieved_text: searchResult.content || searchResult.text || JSON.stringify(searchResult), | |
model_type: searchResult.model_type || 'unknown', | |
result_label: searchResult.resultLabel || '', | |
reaction, | |
confidence_score: searchResult.similarity || 0, // Send the model confidence score | |
user_confidence: confidence, // User's confidence in their rating | |
rating | |
}; | |
await saveFeedback(feedbackData, authTokens.access); | |
setSuccess(true); | |
if (onFeedbackSubmitted) onFeedbackSubmitted(); | |
// Reset form | |
setReaction(''); | |
setConfidence(5); | |
setRating(3); | |
} catch (err) { | |
console.error("Feedback submission error:", err); | |
setError(typeof err === 'string' ? err : (err.message || 'Failed to submit feedback')); | |
} finally { | |
setIsSubmitting(false); | |
} | |
}; | |
return ( | |
<StyledPaper elevation={2}> | |
<Typography variant="h6" gutterBottom> | |
Was this result helpful? | |
</Typography> | |
{error && ( | |
<Alert severity="error" sx={{ mb: 2 }}> | |
{typeof error === 'string' ? error : 'An error occurred'} | |
</Alert> | |
)} | |
{success ? ( | |
<Alert severity="success" sx={{ mb: 2 }}> | |
Thank you for your feedback! | |
</Alert> | |
) : ( | |
<Box component="form" onSubmit={handleSubmit}> | |
<FormControl component="fieldset" sx={{ mb: 3 }} fullWidth> | |
<FormLabel component="legend">Your reaction to this result:</FormLabel> | |
<RadioGroup | |
row | |
value={reaction} | |
onChange={(e) => setReaction(e.target.value)} | |
> | |
<FormControlLabel value="π" control={<Radio />} label="π" /> | |
<FormControlLabel value="π€·ββοΈ" control={<Radio />} label="π€·ββοΈ" /> | |
<FormControlLabel value="π" control={<Radio />} label="π" /> | |
</RadioGroup> | |
</FormControl> | |
<Box sx={{ mb: 3 }}> | |
<Typography gutterBottom>How confident are you in this rating?</Typography> | |
<Slider | |
value={confidence} | |
onChange={(e, newValue) => setConfidence(newValue)} | |
min={1} | |
max={10} | |
step={1} | |
marks | |
valueLabelDisplay="auto" | |
aria-labelledby="confidence-slider" | |
/> | |
</Box> | |
<Box sx={{ mb: 3 }}> | |
<Typography component="legend">Overall quality rating</Typography> | |
<Rating | |
name="quality-rating" | |
value={rating} | |
onChange={(e, newValue) => setRating(newValue)} | |
precision={0.5} | |
/> | |
</Box> | |
<Button | |
type="submit" | |
variant="contained" | |
color="primary" | |
disabled={!reaction || isSubmitting} | |
fullWidth | |
> | |
{isSubmitting ? 'Submitting...' : 'Submit Feedback'} | |
</Button> | |
</Box> | |
)} | |
</StyledPaper> | |
); | |
}; | |
export default FeedbackForm; |