Shih-hungg commited on
Commit
fe844e6
·
1 Parent(s): 34d6b36

Rearrange article parameters

Browse files
src/app/page.tsx CHANGED
@@ -258,7 +258,7 @@ export default function QuestionBuilder() {
258
  <div className="flex-1 flex flex-col">
259
  {/* Upper Right Panel: Source Article Editor */}
260
  <Article
261
- className="h-1/2"
262
  sourceArticle={sourceArticle}
263
  onSourceArticleChange={setSourceArticle}
264
  isSourceLocked={isSourceLocked}
@@ -267,7 +267,7 @@ export default function QuestionBuilder() {
267
 
268
  {/* Lower Right Panel: Question List */}
269
  <QuestionList
270
- className="h-1/2"
271
  questions={questions}
272
  questionTypes={QUESTION_TYPES}
273
  selectedQuestions={selectedQuestions}
 
258
  <div className="flex-1 flex flex-col">
259
  {/* Upper Right Panel: Source Article Editor */}
260
  <Article
261
+ className="flex-1"
262
  sourceArticle={sourceArticle}
263
  onSourceArticleChange={setSourceArticle}
264
  isSourceLocked={isSourceLocked}
 
267
 
268
  {/* Lower Right Panel: Question List */}
269
  <QuestionList
270
+ className="flex-1"
271
  questions={questions}
272
  questionTypes={QUESTION_TYPES}
273
  selectedQuestions={selectedQuestions}
src/components/article/Article.tsx CHANGED
@@ -7,6 +7,7 @@ import { Checkbox } from '@/components/ui/checkbox';
7
  import { Label } from '@/components/ui/label';
8
  import { Textarea } from '@/components/ui/textarea';
9
  import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
 
10
 
11
  interface ArticleProps {
12
  className?: string;
@@ -27,6 +28,7 @@ export function Article({
27
  const [wordCount, setWordCount] = useState(0);
28
  const [isModalOpen, setIsModalOpen] = useState(false);
29
  const [isGeneratingArticle, setIsGeneratingArticle] = useState(false);
 
30
 
31
  const updateWordCount = (text: string) => {
32
  const words = text.trim().split(/\s+/).length;
@@ -68,8 +70,8 @@ export function Article({
68
  };
69
 
70
  return (
71
- <Card className={`border-b ${className}`}>
72
- <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
73
  <CardTitle className="text-lg font-semibold">
74
  📄 Source Article
75
  </CardTitle>
@@ -94,16 +96,24 @@ export function Article({
94
  🔒 Lock
95
  </Label>
96
  </div>
 
 
 
 
 
 
 
 
97
  </div>
98
  </CardHeader>
99
 
100
- <CardContent className="h-[calc(100%-80px)]">
101
  <Textarea
102
  value={sourceArticle}
103
  onChange={(e) => handleSourceArticleChange(e.target.value)}
104
  placeholder="Paste or type your source article here (articles, passages, etc.)..."
105
  disabled={isSourceLocked}
106
- className="w-full h-full resize-none min-h-[300px]"
107
  />
108
  </CardContent>
109
 
@@ -113,6 +123,24 @@ export function Article({
113
  onGenerate={handleGenerateArticle}
114
  isGenerating={isGeneratingArticle}
115
  />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  </Card>
117
  );
118
  }
 
7
  import { Label } from '@/components/ui/label';
8
  import { Textarea } from '@/components/ui/textarea';
9
  import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
10
+ import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
11
 
12
  interface ArticleProps {
13
  className?: string;
 
28
  const [wordCount, setWordCount] = useState(0);
29
  const [isModalOpen, setIsModalOpen] = useState(false);
30
  const [isGeneratingArticle, setIsGeneratingArticle] = useState(false);
31
+ const [isExpandOpen, setIsExpandOpen] = useState(false);
32
 
33
  const updateWordCount = (text: string) => {
34
  const words = text.trim().split(/\s+/).length;
 
70
  };
71
 
72
  return (
73
+ <Card className={`flex flex-col ${className}`}>
74
+ <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-4 px-6 pt-2">
75
  <CardTitle className="text-lg font-semibold">
76
  📄 Source Article
77
  </CardTitle>
 
96
  🔒 Lock
97
  </Label>
98
  </div>
99
+ <Button
100
+ onClick={() => setIsExpandOpen(true)}
101
+ disabled={isSourceLocked}
102
+ variant="outline"
103
+ size="sm"
104
+ >
105
+ ⤢ Expand
106
+ </Button>
107
  </div>
108
  </CardHeader>
109
 
110
+ <CardContent className="flex-1 px-6 pb-6">
111
  <Textarea
112
  value={sourceArticle}
113
  onChange={(e) => handleSourceArticleChange(e.target.value)}
114
  placeholder="Paste or type your source article here (articles, passages, etc.)..."
115
  disabled={isSourceLocked}
116
+ className="w-full h-full resize-none min-h-[200px]"
117
  />
118
  </CardContent>
119
 
 
123
  onGenerate={handleGenerateArticle}
124
  isGenerating={isGeneratingArticle}
125
  />
126
+
127
+ {/* Full-screen editor dialog for comfortable editing */}
128
+ <Dialog open={isExpandOpen} onOpenChange={setIsExpandOpen}>
129
+ <DialogContent className="w-[98vw] sm:max-w-none md:max-w-[90vw] h-[70vh] max-h-[95vh] p-0 flex flex-col">
130
+ <DialogHeader className="px-6 pt-6 pb-2">
131
+ <DialogTitle>📄 Edit Source Article</DialogTitle>
132
+ </DialogHeader>
133
+ <div className="flex-1 px-6 pb-6">
134
+ <Textarea
135
+ value={sourceArticle}
136
+ onChange={(e) => handleSourceArticleChange(e.target.value)}
137
+ placeholder="Paste or type your source article here (articles, passages, etc.)..."
138
+ disabled={isSourceLocked}
139
+ className="w-full h-full resize-none"
140
+ />
141
+ </div>
142
+ </DialogContent>
143
+ </Dialog>
144
  </Card>
145
  );
146
  }
src/components/article/ArticleGenerationModal.tsx CHANGED
@@ -132,15 +132,32 @@ export function ArticleGenerationModal({
132
 
133
  <ScrollArea className="h-[calc(90vh-200px)] pr-4">
134
  <form onSubmit={handleSubmit} className="space-y-6">
135
- <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
136
- <CheckboxField
137
- label="出版社 (Publisher)"
138
- fieldName="publisher"
139
- value={formData.publisher}
140
- onChange={(value: string) => handleCheckboxChange('publisher', value)}
141
- options={PUBLISHER_OPTIONS}
142
- columns={1}
 
 
 
143
  />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  <CheckboxField
145
  label="學生年級 (Grade Level)"
146
  fieldName="grade"
@@ -149,41 +166,17 @@ export function ArticleGenerationModal({
149
  options={GRADE_OPTIONS}
150
  columns={1}
151
  />
152
- </div>
153
-
154
- <CheckboxField
155
- label="課程範圍 (Unit Range)"
156
- fieldName="unit"
157
- value={formData.unit}
158
- onChange={(value: string) => handleCheckboxChange('unit', value)}
159
- options={UNIT_OPTIONS}
160
- columns={3}
161
- />
162
-
163
- <div>
164
- <Label htmlFor="textbook-vocab" className="mb-2">
165
- 課本單字列表 (Textbook Vocabulary)
166
- </Label>
167
- <Textarea
168
- id="textbook-vocab"
169
- value={formData.textbookVocab}
170
- readOnly
171
- placeholder="Select units to see vocabulary"
172
- className="bg-muted"
173
- />
174
- </div>
175
- <div>
176
- <Label htmlFor="additional-vocab" className="mb-2">
177
- 額外單字列表 (Additional Vocabulary)
178
- </Label>
179
- <Textarea
180
- id="additional-vocab"
181
- value={formData.additionalVocab}
182
- onChange={(e) => handleTextChange('additionalVocab', e.target.value)}
183
- placeholder="Enter additional vocabulary words, separated by commas"
184
  />
185
  </div>
186
 
 
187
  <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
188
  <CheckboxField
189
  label="文法範圍 (Grammar Focus)"
@@ -203,16 +196,30 @@ export function ArticleGenerationModal({
203
  />
204
  </div>
205
 
 
206
  <div>
207
- <Label htmlFor="input-article" className="mb-2">
208
- 初始文章 (Initial Article)
209
  </Label>
210
  <Textarea
211
- id="input-article"
212
- value={formData.inputArticle}
213
- onChange={(e) => handleTextChange('inputArticle', e.target.value)}
214
- placeholder="Enter an initial article or topic to base the generation on..."
215
- className="min-h-[120px]"
 
 
 
 
 
 
 
 
 
 
 
 
 
216
  />
217
  </div>
218
  </form>
 
132
 
133
  <ScrollArea className="h-[calc(90vh-200px)] pr-4">
134
  <form onSubmit={handleSubmit} className="space-y-6">
135
+ {/* 初始文章 */}
136
+ <div>
137
+ <Label htmlFor="input-article" className="mb-2">
138
+ 初始文章 (Initial Article)
139
+ </Label>
140
+ <Textarea
141
+ id="input-article"
142
+ value={formData.inputArticle}
143
+ onChange={(e) => handleTextChange('inputArticle', e.target.value)}
144
+ placeholder="Enter an initial article or topic to base the generation on..."
145
+ className="min-h-[120px]"
146
  />
147
+ </div>
148
+
149
+ {/* 出版社 */}
150
+ <CheckboxField
151
+ label="出版社 (Publisher)"
152
+ fieldName="publisher"
153
+ value={formData.publisher}
154
+ onChange={(value: string) => handleCheckboxChange('publisher', value)}
155
+ options={PUBLISHER_OPTIONS}
156
+ columns={1}
157
+ />
158
+
159
+ {/* 學生年級 + 課程範圍 */}
160
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
161
  <CheckboxField
162
  label="學生年級 (Grade Level)"
163
  fieldName="grade"
 
166
  options={GRADE_OPTIONS}
167
  columns={1}
168
  />
169
+ <CheckboxField
170
+ label="課程範圍 (Unit Range)"
171
+ fieldName="unit"
172
+ value={formData.unit}
173
+ onChange={(value: string) => handleCheckboxChange('unit', value)}
174
+ options={UNIT_OPTIONS}
175
+ columns={1}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  />
177
  </div>
178
 
179
+ {/* 文法範圍 + 主題範圍 */}
180
  <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
181
  <CheckboxField
182
  label="文法範圍 (Grammar Focus)"
 
196
  />
197
  </div>
198
 
199
+ {/* 單字列表 */}
200
  <div>
201
+ <Label htmlFor="textbook-vocab" className="mb-2">
202
+ 課本單字列表 (Textbook Vocabulary)
203
  </Label>
204
  <Textarea
205
+ id="textbook-vocab"
206
+ value={formData.textbookVocab}
207
+ readOnly
208
+ placeholder="Select units to see vocabulary"
209
+ className="bg-muted"
210
+ />
211
+ </div>
212
+
213
+ {/* 額外單字列表 */}
214
+ <div>
215
+ <Label htmlFor="additional-vocab" className="mb-2">
216
+ 額外單字列表 (Additional Vocabulary)
217
+ </Label>
218
+ <Textarea
219
+ id="additional-vocab"
220
+ value={formData.additionalVocab}
221
+ onChange={(e) => handleTextChange('additionalVocab', e.target.value)}
222
+ placeholder="Enter additional vocabulary words, separated by commas"
223
  />
224
  </div>
225
  </form>