Spaces:
Paused
Paused
Yu Chen commited on
Commit ยท
12a814d
1
Parent(s): 4e640d9
add custom logic handling for comprehensive questions ( no need sub categories )
Browse files- src/app/page.tsx +87 -9
src/app/page.tsx
CHANGED
|
@@ -10,19 +10,37 @@ import { Button } from '@/components/ui/button';
|
|
| 10 |
import { Input } from '@/components/ui/input';
|
| 11 |
import { ChevronRight, ChevronLeft } from 'lucide-react';
|
| 12 |
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
{ id: 'paragraph-summary', name: 'Paragraph Summary', icon: '๐', description: 'Create summaries of text passages' },
|
| 15 |
{ id: 'paragraph-details', name: 'Paragraph Details', icon: '๐', description: 'Identify key details in paragraphs' },
|
| 16 |
-
// { id: 'cloze', name: 'Cloze (Fill-in-the-blank)', icon: '๐ค', description: 'Fill in missing words or phrases' },
|
| 17 |
{ id: 'word-comprehension', name: 'Word Comprehension', icon: '๐', description: 'Test vocabulary understanding in context' },
|
| 18 |
{ id: 'grammatical-structure', name: 'Grammar Structure', icon: '๐', description: 'Identify grammatical patterns and structures' },
|
| 19 |
{ id: 'paragraph-structure', name: 'Paragraph Structure', icon: '๐', description: 'Analyze paragraph organization and flow' },
|
| 20 |
{ id: 'textual-inference', name: 'Textual Inference', icon: '๐ง ', description: 'Make inferences from text passages' },
|
| 21 |
];
|
| 22 |
|
|
|
|
|
|
|
| 23 |
export default function QuestionBuilder() {
|
| 24 |
// Chat builder state
|
| 25 |
-
const [currentStep, setCurrentStep] = useState<'type-selection' | 'parameters' | 'generation' | 'editing'>('
|
|
|
|
| 26 |
const [selectedQuestionType, setSelectedQuestionType] = useState<QuestionType | null>(null);
|
| 27 |
const [questionParameters, setQuestionParameters] = useState<QuestionParameters>({});
|
| 28 |
const [isGenerating, setIsGenerating] = useState(false);
|
|
@@ -46,6 +64,11 @@ export default function QuestionBuilder() {
|
|
| 46 |
// Collapse state for question builder panel
|
| 47 |
const [isQuestionBuilderCollapsed, setIsQuestionBuilderCollapsed] = useState(false);
|
| 48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
const handleQuestionTypeSelect = (questionType: QuestionType) => {
|
| 50 |
setSelectedQuestionType(questionType);
|
| 51 |
setCurrentStep('parameters');
|
|
@@ -62,6 +85,7 @@ export default function QuestionBuilder() {
|
|
| 62 |
|
| 63 |
const { k: _omitK, ...payloadParameters } = questionParameters as Record<string, unknown>;
|
| 64 |
|
|
|
|
| 65 |
const requests = Array.from({ length: k }, () =>
|
| 66 |
fetch('/api/generate-question', {
|
| 67 |
method: 'POST',
|
|
@@ -69,7 +93,7 @@ export default function QuestionBuilder() {
|
|
| 69 |
body: JSON.stringify({
|
| 70 |
type: selectedQuestionType.id,
|
| 71 |
parameters: payloadParameters,
|
| 72 |
-
sourceArticle,
|
| 73 |
}),
|
| 74 |
})
|
| 75 |
);
|
|
@@ -92,7 +116,8 @@ export default function QuestionBuilder() {
|
|
| 92 |
createdAt: new Date(),
|
| 93 |
})),
|
| 94 |
]);
|
| 95 |
-
setCurrentStep('
|
|
|
|
| 96 |
setSelectedQuestionType(null);
|
| 97 |
setQuestionParameters({});
|
| 98 |
}
|
|
@@ -235,16 +260,55 @@ export default function QuestionBuilder() {
|
|
| 235 |
|
| 236 |
{!isQuestionBuilderCollapsed && (
|
| 237 |
<div className="flex-1 overflow-y-auto p-4">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 238 |
{currentStep === 'type-selection' && (
|
| 239 |
<div className="space-y-4">
|
| 240 |
<div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-700 rounded-lg p-4">
|
| 241 |
<p className="text-blue-800 dark:text-blue-200">
|
| 242 |
-
๐ค
|
| 243 |
</p>
|
| 244 |
</div>
|
| 245 |
-
|
| 246 |
<div className="space-y-2">
|
| 247 |
-
{
|
| 248 |
<Button
|
| 249 |
key={type.id}
|
| 250 |
onClick={() => handleQuestionTypeSelect(type)}
|
|
@@ -261,6 +325,16 @@ export default function QuestionBuilder() {
|
|
| 261 |
</Button>
|
| 262 |
))}
|
| 263 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 264 |
</div>
|
| 265 |
)}
|
| 266 |
|
|
@@ -274,7 +348,11 @@ export default function QuestionBuilder() {
|
|
| 274 |
|
| 275 |
<div className="flex space-x-2">
|
| 276 |
<Button
|
| 277 |
-
onClick={() =>
|
|
|
|
|
|
|
|
|
|
|
|
|
| 278 |
variant="outline"
|
| 279 |
>
|
| 280 |
Back
|
|
|
|
| 10 |
import { Input } from '@/components/ui/input';
|
| 11 |
import { ChevronRight, ChevronLeft } from 'lucide-react';
|
| 12 |
|
| 13 |
+
// Translation map for comprehensive question categories (Chinese โ English)
|
| 14 |
+
const COMPREHENSIVE_CATEGORY_MAP: Record<string, { name: string; icon: string; description: string }> = {
|
| 15 |
+
'ๅฎๅญ่็่ช': { name: 'Vocabulary & Phrases', icon: '๐', description: 'Word meanings, phrases, and vocabulary in context' },
|
| 16 |
+
'ๆๆณ่ๅฅๅ': { name: 'Grammar & Sentence Patterns', icon: '๐', description: 'Grammar rules, verb tenses, and sentence structures' },
|
| 17 |
+
'ๆๆ็่งฃ่ๆ็จ': { name: 'Text Comprehension & Application', icon: '๐ก', description: 'Understanding meaning and applying context clues' },
|
| 18 |
+
};
|
| 19 |
+
|
| 20 |
+
const COMPREHENSIVE_TYPES: QuestionType[] = Object.entries(COMPREHENSIVE_CATEGORY_MAP).map(
|
| 21 |
+
([chineseKey, { name, icon, description }]) => ({
|
| 22 |
+
id: `comprehensive-${chineseKey}`,
|
| 23 |
+
name,
|
| 24 |
+
icon,
|
| 25 |
+
description,
|
| 26 |
+
})
|
| 27 |
+
);
|
| 28 |
+
|
| 29 |
+
const READING_COMPREHENSION_TYPES: QuestionType[] = [
|
| 30 |
{ id: 'paragraph-summary', name: 'Paragraph Summary', icon: '๐', description: 'Create summaries of text passages' },
|
| 31 |
{ id: 'paragraph-details', name: 'Paragraph Details', icon: '๐', description: 'Identify key details in paragraphs' },
|
|
|
|
| 32 |
{ id: 'word-comprehension', name: 'Word Comprehension', icon: '๐', description: 'Test vocabulary understanding in context' },
|
| 33 |
{ id: 'grammatical-structure', name: 'Grammar Structure', icon: '๐', description: 'Identify grammatical patterns and structures' },
|
| 34 |
{ id: 'paragraph-structure', name: 'Paragraph Structure', icon: '๐', description: 'Analyze paragraph organization and flow' },
|
| 35 |
{ id: 'textual-inference', name: 'Textual Inference', icon: '๐ง ', description: 'Make inferences from text passages' },
|
| 36 |
];
|
| 37 |
|
| 38 |
+
const QUESTION_TYPES: QuestionType[] = [...COMPREHENSIVE_TYPES, ...READING_COMPREHENSION_TYPES];
|
| 39 |
+
|
| 40 |
export default function QuestionBuilder() {
|
| 41 |
// Chat builder state
|
| 42 |
+
const [currentStep, setCurrentStep] = useState<'category-selection' | 'type-selection' | 'parameters' | 'generation' | 'editing'>('category-selection');
|
| 43 |
+
const [selectedCategory, setSelectedCategory] = useState<'comprehensive' | 'reading-comprehension' | null>(null);
|
| 44 |
const [selectedQuestionType, setSelectedQuestionType] = useState<QuestionType | null>(null);
|
| 45 |
const [questionParameters, setQuestionParameters] = useState<QuestionParameters>({});
|
| 46 |
const [isGenerating, setIsGenerating] = useState(false);
|
|
|
|
| 64 |
// Collapse state for question builder panel
|
| 65 |
const [isQuestionBuilderCollapsed, setIsQuestionBuilderCollapsed] = useState(false);
|
| 66 |
|
| 67 |
+
const handleCategorySelect = (category: 'comprehensive' | 'reading-comprehension') => {
|
| 68 |
+
setSelectedCategory(category);
|
| 69 |
+
setCurrentStep('type-selection');
|
| 70 |
+
};
|
| 71 |
+
|
| 72 |
const handleQuestionTypeSelect = (questionType: QuestionType) => {
|
| 73 |
setSelectedQuestionType(questionType);
|
| 74 |
setCurrentStep('parameters');
|
|
|
|
| 85 |
|
| 86 |
const { k: _omitK, ...payloadParameters } = questionParameters as Record<string, unknown>;
|
| 87 |
|
| 88 |
+
const isComprehensive = selectedQuestionType.id.startsWith('comprehensive-');
|
| 89 |
const requests = Array.from({ length: k }, () =>
|
| 90 |
fetch('/api/generate-question', {
|
| 91 |
method: 'POST',
|
|
|
|
| 93 |
body: JSON.stringify({
|
| 94 |
type: selectedQuestionType.id,
|
| 95 |
parameters: payloadParameters,
|
| 96 |
+
...(isComprehensive ? {} : { sourceArticle }),
|
| 97 |
}),
|
| 98 |
})
|
| 99 |
);
|
|
|
|
| 116 |
createdAt: new Date(),
|
| 117 |
})),
|
| 118 |
]);
|
| 119 |
+
setCurrentStep('category-selection');
|
| 120 |
+
setSelectedCategory(null);
|
| 121 |
setSelectedQuestionType(null);
|
| 122 |
setQuestionParameters({});
|
| 123 |
}
|
|
|
|
| 260 |
|
| 261 |
{!isQuestionBuilderCollapsed && (
|
| 262 |
<div className="flex-1 overflow-y-auto p-4">
|
| 263 |
+
{currentStep === 'category-selection' && (
|
| 264 |
+
<div className="space-y-4">
|
| 265 |
+
<div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-700 rounded-lg p-4">
|
| 266 |
+
<p className="text-blue-800 dark:text-blue-200">
|
| 267 |
+
๐ค Hi! What category of question would you like to create?
|
| 268 |
+
</p>
|
| 269 |
+
</div>
|
| 270 |
+
|
| 271 |
+
<div className="space-y-2">
|
| 272 |
+
<Button
|
| 273 |
+
onClick={() => handleCategorySelect('comprehensive')}
|
| 274 |
+
variant="outline"
|
| 275 |
+
className="w-full justify-start p-4 h-auto"
|
| 276 |
+
>
|
| 277 |
+
<div className="flex items-center space-x-3">
|
| 278 |
+
<span className="text-lg">๐</span>
|
| 279 |
+
<div className="text-left">
|
| 280 |
+
<div className="font-medium">Comprehensive Questions</div>
|
| 281 |
+
<div className="text-sm text-muted-foreground">Standalone vocabulary, grammar, and sentence-level questions</div>
|
| 282 |
+
</div>
|
| 283 |
+
</div>
|
| 284 |
+
</Button>
|
| 285 |
+
<Button
|
| 286 |
+
onClick={() => handleCategorySelect('reading-comprehension')}
|
| 287 |
+
variant="outline"
|
| 288 |
+
className="w-full justify-start p-4 h-auto"
|
| 289 |
+
>
|
| 290 |
+
<div className="flex items-center space-x-3">
|
| 291 |
+
<span className="text-lg">๐</span>
|
| 292 |
+
<div className="text-left">
|
| 293 |
+
<div className="font-medium">Reading Comprehension</div>
|
| 294 |
+
<div className="text-sm text-muted-foreground">Passage-based questions requiring a source article</div>
|
| 295 |
+
</div>
|
| 296 |
+
</div>
|
| 297 |
+
</Button>
|
| 298 |
+
</div>
|
| 299 |
+
</div>
|
| 300 |
+
)}
|
| 301 |
+
|
| 302 |
{currentStep === 'type-selection' && (
|
| 303 |
<div className="space-y-4">
|
| 304 |
<div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-700 rounded-lg p-4">
|
| 305 |
<p className="text-blue-800 dark:text-blue-200">
|
| 306 |
+
๐ค Select a question type:
|
| 307 |
</p>
|
| 308 |
</div>
|
| 309 |
+
|
| 310 |
<div className="space-y-2">
|
| 311 |
+
{(selectedCategory === 'comprehensive' ? COMPREHENSIVE_TYPES : READING_COMPREHENSION_TYPES).map((type) => (
|
| 312 |
<Button
|
| 313 |
key={type.id}
|
| 314 |
onClick={() => handleQuestionTypeSelect(type)}
|
|
|
|
| 325 |
</Button>
|
| 326 |
))}
|
| 327 |
</div>
|
| 328 |
+
|
| 329 |
+
<Button
|
| 330 |
+
onClick={() => {
|
| 331 |
+
setSelectedCategory(null);
|
| 332 |
+
setCurrentStep('category-selection');
|
| 333 |
+
}}
|
| 334 |
+
variant="outline"
|
| 335 |
+
>
|
| 336 |
+
Back
|
| 337 |
+
</Button>
|
| 338 |
</div>
|
| 339 |
)}
|
| 340 |
|
|
|
|
| 348 |
|
| 349 |
<div className="flex space-x-2">
|
| 350 |
<Button
|
| 351 |
+
onClick={() => {
|
| 352 |
+
setCurrentStep('type-selection');
|
| 353 |
+
setSelectedQuestionType(null);
|
| 354 |
+
setQuestionParameters({});
|
| 355 |
+
}}
|
| 356 |
variant="outline"
|
| 357 |
>
|
| 358 |
Back
|