Files
YG-Datasets/easy-dataset-main/app/projects/[projectId]/images/components/QuestionDialog.js

136 lines
3.5 KiB
JavaScript

'use client';
import { useState, useEffect } from 'react';
import {
Dialog,
DialogTitle,
DialogContent,
DialogActions,
Button,
TextField,
CircularProgress,
Alert,
Box,
Typography
} from '@mui/material';
import { useTranslation } from 'react-i18next';
import { useAtomValue } from 'jotai';
import { selectedModelInfoAtom } from '@/lib/store';
import { toast } from 'sonner';
import axios from 'axios';
export default function QuestionDialog({ open, projectId, image, onClose, onSuccess }) {
const { t, i18n } = useTranslation();
const selectedModel = useAtomValue(selectedModelInfoAtom);
const [count, setCount] = useState(3);
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
useEffect(() => {
if (open) {
setCount(3);
setError('');
}
}, [open]);
const handleGenerate = async () => {
if (!selectedModel) {
setError(t('images.selectModelFirst'));
return;
}
if (selectedModel.type !== 'vision') {
setError(t('images.visionModelRequired'));
return;
}
if (count < 1 || count > 10) {
setError(t('images.countRange'));
return;
}
try {
setLoading(true);
setError('');
const response = await axios.post(`/api/projects/${projectId}/images/questions`, {
imageName: image.imageName,
count,
model: selectedModel,
language: i18n.language
});
toast.success(t('images.questionsGenerated', { count: response.data.questions.length }));
onSuccess?.();
onClose();
} catch (err) {
console.error('Failed to generate questions:', err);
setError(err.response?.data?.error || t('images.generateFailed'));
} finally {
setLoading(false);
}
};
const handleClose = () => {
if (!loading) {
onClose();
}
};
return (
<Dialog open={open} onClose={handleClose} maxWidth="sm" fullWidth>
<DialogTitle>{t('images.generateQuestions')}</DialogTitle>
<DialogContent sx={{ pt: 2 }}>
{error && (
<Alert severity="error" sx={{ mb: 2 }}>
{error}
</Alert>
)}
{image && (
<Box sx={{ mb: 2 }}>
<Typography variant="subtitle2" gutterBottom>
{t('images.imageName')}
</Typography>
<Typography variant="body2" color="text.secondary">
{image.imageName}
</Typography>
</Box>
)}
<TextField
fullWidth
type="number"
label={t('images.questionCount')}
value={count}
onChange={e => setCount(parseInt(e.target.value) || 1)}
inputProps={{ min: 1, max: 10 }}
helperText={t('images.questionCountHelp')}
disabled={loading}
/>
{selectedModel && (
<Box sx={{ mt: 2 }}>
<Typography variant="caption" color="text.secondary">
{t('images.currentModel')}: {selectedModel.modelName}
</Typography>
</Box>
)}
</DialogContent>
<DialogActions>
<Button onClick={handleClose} disabled={loading}>
{t('common.cancel')}
</Button>
<Button
onClick={handleGenerate}
variant="contained"
disabled={loading || !selectedModel}
startIcon={loading ? <CircularProgress size={20} /> : null}
>
{t('images.generateQuestions')}
</Button>
</DialogActions>
</Dialog>
);
}