import React, { useState, useEffect } from 'react'; import * as Icons from 'react-icons/fi'; import taService from '../../services/ta.service'; const QuizWorkflow = ({ quizId, spaceId, onBack, onSave, onSend, onViewResults }) => { const [loading, setLoading] = useState(false); const [saving, setSaving] = useState(false); const [quiz, setQuiz] = useState(null); const [questions, setQuestions] = useState([]); const [expandedCard, setExpandedCard] = useState(null); const [isInfoCollapsed, setIsInfoCollapsed] = useState(false); useEffect(() => { if (quizId) { fetchQuiz(); } }, [quizId]); const fetchQuiz = async () => { setLoading(true); try { const res = await taService.getQuiz(quizId); if (res.success) { setQuiz(res.data.quiz); setQuestions((res.data.questions || []).map(normalizeQuestion)); } } catch (error) { console.error('Failed to fetch quiz:', error); } finally { setLoading(false); } }; const addQuestion = () => { const newQuestion = { id: `temp-${Date.now()}`, order: questions.length + 1, topic: 'Chung', difficulty: 'medium', question_text: '', options: [ { id: 'a', text: '' }, { id: 'b', text: '' }, { id: 'c', text: '' }, { id: 'd', text: '' } ], correct_answer: 'a', explanation: '' }; setQuestions([...questions, newQuestion]); setExpandedCard(newQuestion.id); }; const updateQuestion = (index, field, value) => { const updated = [...questions]; updated[index] = { ...updated[index], [field]: value }; setQuestions(updated); }; const updateOption = (qIndex, oIndex, value) => { const updated = [...questions]; const options = normalizeOptions(updated[qIndex].options); options[oIndex] = { ...options[oIndex], text: value }; updated[qIndex] = { ...updated[qIndex], options }; setQuestions(updated); }; const removeQuestion = (index) => { const updated = questions.filter((_, i) => i !== index); setQuestions(updated.map((q, i) => ({ ...q, order: i + 1 }))); }; const moveQuestion = (index, direction) => { const newIndex = index + direction; if (newIndex < 0 || newIndex >= questions.length) return; const updated = [...questions]; [updated[index], updated[newIndex]] = [updated[newIndex], updated[index]]; setQuestions(updated.map((q, i) => ({ ...q, order: i + 1 }))); }; const setCorrectAnswer = (qIndex, optionId) => { const updated = [...questions]; updated[qIndex] = { ...updated[qIndex], correct_answer: optionId }; setQuestions(updated); }; const duplicateQuestion = (index) => { const duplicate = { ...questions[index], id: `temp-${Date.now()}`, order: questions.length + 1, question_text: questions[index].question_text + ' (copy)' }; const newQuestions = [...questions]; newQuestions.splice(index + 1, 0, duplicate); setQuestions(newQuestions); }; const handleSave = async () => { setSaving(true); try { const res = await taService.updateQuiz(quizId, buildPayload()); if (res.success) { onSave?.(res.data); } } catch (error) { console.error('Failed to save quiz:', error); } finally { setSaving(false); } }; const buildPayload = () => ({ title: quiz.title, description: quiz.description, status: quiz.status, passing_score: quiz.passing_score || 60, due_at: quiz.due_at || null, questions: questions.map(toQuestionPayload) }); const normalizeOptions = (options) => { if (Array.isArray(options)) return options; if (typeof options === 'string') { try { const parsed = JSON.parse(options); return Array.isArray(parsed) ? parsed : []; } catch { return []; } } return []; }; const normalizeQuestion = (question) => ({ ...question, options: normalizeOptions(question.options) }); const toQuestionPayload = (question, index) => { const normalized = normalizeQuestion(question); return { order: Number(normalized.order || index + 1), topic: normalized.topic || 'Chung', difficulty: normalized.difficulty || 'medium', question_text: normalized.question_text || '', options: normalizeOptions(normalized.options).map((option, optionIndex) => ({ id: String(option.id || ['a', 'b', 'c', 'd'][optionIndex] || optionIndex + 1), text: String(option.text || '') })), correct_answer: normalized.correct_answer || 'a', explanation: normalized.explanation || '' }; }; const handleSend = async () => { setSaving(true); try { const saveRes = await taService.updateQuiz(quizId, buildPayload()); if (!saveRes.success) return; const res = await taService.sendQuiz(quizId, { space_id: spaceId }); if (res.success) { onSend?.(res.data); } } catch (error) { console.error('Failed to send quiz:', error); } finally { setSaving(false); } }; const handleDelete = async () => { if (!confirm('Bạn có chắc muốn lưu trữ quiz này? Quiz sẽ không hiển thị cho học viên nữa nhưng có thể khôi phục sau.')) return; setSaving(true); try { await taService.updateQuiz(quizId, { ...buildPayload(), status: 'archived' }); onBack?.(); } catch (error) { console.error('Failed to archive quiz:', error); } finally { setSaving(false); } }; const getDifficultyColor = (difficulty) => { switch (difficulty) { case 'easy': return 'var(--ta-green)'; case 'medium': return 'var(--ta-amber)'; case 'hard': return 'var(--ta-red)'; default: return 'var(--text-muted)'; } }; const getDifficultyBg = (difficulty) => { switch (difficulty) { case 'easy': return 'var(--ta-green-bg)'; case 'medium': return 'var(--ta-amber-bg)'; case 'hard': return 'var(--ta-red-bg)'; default: return 'var(--bg-surface-tertiary)'; } }; if (loading) { return (
Chưa có câu hỏi nào
Nhấn nút bên dưới để bắt đầu
{q.question_text || 'Chưa có nội dung câu hỏi'}