Omarrran commited on
Commit
fe2bc51
·
1 Parent(s): d4b5ccf

Centered help modal, add dataset format guide, add welcome popup

Browse files
src/app/page.tsx CHANGED
@@ -2,6 +2,7 @@
2
 
3
  import React, { useState, useEffect } from 'react';
4
  import HelpModal from '@/components/HelpModal';
 
5
 
6
 
7
  import TextInput from '@/components/TextInput';
@@ -424,6 +425,7 @@ export default function Home() {
424
  datasetName={datasetName}
425
  />
426
  <HelpModal isOpen={isHelpOpen} onClose={() => setIsHelpOpen(false)} />
 
427
  </main>
428
  );
429
  }
 
2
 
3
  import React, { useState, useEffect } from 'react';
4
  import HelpModal from '@/components/HelpModal';
5
+ import QuickTourPopup from '@/components/QuickTourPopup';
6
 
7
 
8
  import TextInput from '@/components/TextInput';
 
425
  datasetName={datasetName}
426
  />
427
  <HelpModal isOpen={isHelpOpen} onClose={() => setIsHelpOpen(false)} />
428
+ <QuickTourPopup />
429
  </main>
430
  );
431
  }
src/components/HelpModal.tsx CHANGED
@@ -1,7 +1,7 @@
1
  'use client';
2
 
3
  import React from 'react';
4
- import { X, Keyboard, Mic, Save, Search, SkipForward, Bookmark, HelpCircle } from 'lucide-react';
5
  import { motion, AnimatePresence } from 'framer-motion';
6
  import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
7
 
@@ -23,36 +23,36 @@ export default function HelpModal({ isOpen, onClose }: HelpModalProps) {
23
  onClick={onClose}
24
  />
25
  <motion.div
26
- initial={{ opacity: 0, scale: 0.95, y: 20 }}
27
- animate={{ opacity: 1, scale: 1, y: 0 }}
28
- exit={{ opacity: 0, scale: 0.95, y: 20 }}
29
- className="fixed left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 w-full max-w-2xl z-50 max-h-[85vh] overflow-y-auto"
30
  >
31
- <Card>
32
- <CardHeader>
33
  <CardTitle className="flex items-center justify-between">
34
  <div className="flex items-center gap-2">
35
  <HelpCircle className="w-5 h-5 text-primary" />
36
  <span>Help & Documentation</span>
37
  </div>
38
- <button onClick={onClose} className="text-muted-foreground hover:text-foreground">
39
  <X className="w-5 h-5" />
40
  </button>
41
  </CardTitle>
42
  </CardHeader>
43
- <CardContent className="space-y-6">
44
  {/* Quick Start */}
45
  <section className="space-y-3">
46
  <h3 className="text-lg font-semibold flex items-center gap-2">
47
  🚀 Quick Start
48
  </h3>
49
  <ol className="list-decimal list-inside space-y-2 text-sm text-muted-foreground ml-2">
50
- <li>Enter a <strong>Speaker ID</strong> and <strong>Dataset Name</strong>.</li>
51
- <li>Paste your text sentences into the text area and click <strong>Load Sentences</strong>.</li>
52
- <li>Press <strong>Spacebar</strong> or click the microphone to start recording.</li>
53
  <li>Rate the recording and select an emotion (optional).</li>
54
- <li>Press <strong>Ctrl + S</strong> or click "Save & Next" to save and move to the next sentence.</li>
55
- <li>When finished, go to <strong>Settings</strong> to export your dataset.</li>
56
  </ol>
57
  </section>
58
 
@@ -64,19 +64,19 @@ export default function HelpModal({ isOpen, onClose }: HelpModalProps) {
64
  </h3>
65
  <ul className="space-y-2 text-sm">
66
  <li className="flex items-start gap-2">
67
- <Mic className="w-4 h-4 mt-0.5 text-primary" />
68
  <span><strong>Emotion Tagging:</strong> Label recordings with emotions like Happy, Sad, or Whisper.</span>
69
  </li>
70
  <li className="flex items-start gap-2">
71
- <Bookmark className="w-4 h-4 mt-0.5 text-primary" />
72
  <span><strong>Bookmarks:</strong> Flag difficult sentences to review later.</span>
73
  </li>
74
  <li className="flex items-start gap-2">
75
- <Search className="w-4 h-4 mt-0.5 text-primary" />
76
  <span><strong>Search:</strong> Find specific sentences by keyword.</span>
77
  </li>
78
  <li className="flex items-start gap-2">
79
- <SkipForward className="w-4 h-4 mt-0.5 text-primary" />
80
  <span><strong>Skip:</strong> Skip irrelevant or problematic sentences.</span>
81
  </li>
82
  </ul>
@@ -90,27 +90,125 @@ export default function HelpModal({ isOpen, onClose }: HelpModalProps) {
90
  <div className="space-y-2 text-sm">
91
  <div className="flex justify-between items-center bg-secondary/30 p-2 rounded">
92
  <span>Start/Stop Recording</span>
93
- <kbd className="bg-background border border-border px-1.5 rounded text-xs">Space</kbd>
94
  </div>
95
  <div className="flex justify-between items-center bg-secondary/30 p-2 rounded">
96
  <span>Save & Next</span>
97
- <kbd className="bg-background border border-border px-1.5 rounded text-xs">Ctrl + S</kbd>
98
  </div>
99
  <div className="flex justify-between items-center bg-secondary/30 p-2 rounded">
100
  <span>Next Sentence</span>
101
- <kbd className="bg-background border border-border px-1.5 rounded text-xs">→</kbd>
102
  </div>
103
  <div className="flex justify-between items-center bg-secondary/30 p-2 rounded">
104
  <span>Previous Sentence</span>
105
- <kbd className="bg-background border border-border px-1.5 rounded text-xs">←</kbd>
106
  </div>
107
  <div className="flex justify-between items-center bg-secondary/30 p-2 rounded">
108
  <span>Focus Search</span>
109
- <kbd className="bg-background border border-border px-1.5 rounded text-xs">Ctrl + F</kbd>
110
  </div>
111
  </div>
112
  </section>
113
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  </CardContent>
115
  </Card>
116
  </motion.div>
 
1
  'use client';
2
 
3
  import React from 'react';
4
+ import { X, Keyboard, Mic, Save, Search, SkipForward, Bookmark, HelpCircle, FolderDown, FileAudio, FileText, FileJson } from 'lucide-react';
5
  import { motion, AnimatePresence } from 'framer-motion';
6
  import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
7
 
 
23
  onClick={onClose}
24
  />
25
  <motion.div
26
+ initial={{ opacity: 0, scale: 0.95 }}
27
+ animate={{ opacity: 1, scale: 1 }}
28
+ exit={{ opacity: 0, scale: 0.95 }}
29
+ className="fixed inset-0 z-50 flex items-center justify-center p-4"
30
  >
31
+ <Card className="w-full max-w-3xl max-h-[85vh] overflow-y-auto">
32
+ <CardHeader className="sticky top-0 bg-card z-10 border-b border-border">
33
  <CardTitle className="flex items-center justify-between">
34
  <div className="flex items-center gap-2">
35
  <HelpCircle className="w-5 h-5 text-primary" />
36
  <span>Help & Documentation</span>
37
  </div>
38
+ <button onClick={onClose} className="text-muted-foreground hover:text-foreground p-1 rounded-lg hover:bg-secondary">
39
  <X className="w-5 h-5" />
40
  </button>
41
  </CardTitle>
42
  </CardHeader>
43
+ <CardContent className="space-y-6 pt-6">
44
  {/* Quick Start */}
45
  <section className="space-y-3">
46
  <h3 className="text-lg font-semibold flex items-center gap-2">
47
  🚀 Quick Start
48
  </h3>
49
  <ol className="list-decimal list-inside space-y-2 text-sm text-muted-foreground ml-2">
50
+ <li>Enter a <strong className="text-foreground">Speaker ID</strong> and <strong className="text-foreground">Dataset Name</strong>.</li>
51
+ <li>Paste your text sentences into the text area and click <strong className="text-foreground">Load Sentences</strong>.</li>
52
+ <li>Press <kbd className="bg-secondary border border-border px-1.5 py-0.5 rounded text-xs">Space</kbd> or click the microphone to start recording.</li>
53
  <li>Rate the recording and select an emotion (optional).</li>
54
+ <li>Press <kbd className="bg-secondary border border-border px-1.5 py-0.5 rounded text-xs">Ctrl + S</kbd> or click "Save & Next" to save.</li>
55
+ <li>When finished, click <strong className="text-foreground">Download Dataset</strong> in Settings.</li>
56
  </ol>
57
  </section>
58
 
 
64
  </h3>
65
  <ul className="space-y-2 text-sm">
66
  <li className="flex items-start gap-2">
67
+ <Mic className="w-4 h-4 mt-0.5 text-primary flex-shrink-0" />
68
  <span><strong>Emotion Tagging:</strong> Label recordings with emotions like Happy, Sad, or Whisper.</span>
69
  </li>
70
  <li className="flex items-start gap-2">
71
+ <Bookmark className="w-4 h-4 mt-0.5 text-primary flex-shrink-0" />
72
  <span><strong>Bookmarks:</strong> Flag difficult sentences to review later.</span>
73
  </li>
74
  <li className="flex items-start gap-2">
75
+ <Search className="w-4 h-4 mt-0.5 text-primary flex-shrink-0" />
76
  <span><strong>Search:</strong> Find specific sentences by keyword.</span>
77
  </li>
78
  <li className="flex items-start gap-2">
79
+ <SkipForward className="w-4 h-4 mt-0.5 text-primary flex-shrink-0" />
80
  <span><strong>Skip:</strong> Skip irrelevant or problematic sentences.</span>
81
  </li>
82
  </ul>
 
90
  <div className="space-y-2 text-sm">
91
  <div className="flex justify-between items-center bg-secondary/30 p-2 rounded">
92
  <span>Start/Stop Recording</span>
93
+ <kbd className="bg-background border border-border px-2 py-0.5 rounded text-xs font-mono">Space</kbd>
94
  </div>
95
  <div className="flex justify-between items-center bg-secondary/30 p-2 rounded">
96
  <span>Save & Next</span>
97
+ <kbd className="bg-background border border-border px-2 py-0.5 rounded text-xs font-mono">Ctrl + S</kbd>
98
  </div>
99
  <div className="flex justify-between items-center bg-secondary/30 p-2 rounded">
100
  <span>Next Sentence</span>
101
+ <kbd className="bg-background border border-border px-2 py-0.5 rounded text-xs font-mono">→</kbd>
102
  </div>
103
  <div className="flex justify-between items-center bg-secondary/30 p-2 rounded">
104
  <span>Previous Sentence</span>
105
+ <kbd className="bg-background border border-border px-2 py-0.5 rounded text-xs font-mono">←</kbd>
106
  </div>
107
  <div className="flex justify-between items-center bg-secondary/30 p-2 rounded">
108
  <span>Focus Search</span>
109
+ <kbd className="bg-background border border-border px-2 py-0.5 rounded text-xs font-mono">Ctrl + F</kbd>
110
  </div>
111
  </div>
112
  </section>
113
  </div>
114
+
115
+ {/* Dataset Format */}
116
+ <section className="space-y-3 border-t border-border pt-6">
117
+ <h3 className="text-lg font-semibold flex items-center gap-2">
118
+ <FolderDown className="w-5 h-5 text-primary" />
119
+ Dataset Export Format
120
+ </h3>
121
+ <p className="text-sm text-muted-foreground">
122
+ When you download your dataset, you'll get a ZIP file with the following structure:
123
+ </p>
124
+
125
+ <div className="bg-secondary/30 rounded-lg p-4 font-mono text-sm">
126
+ <div className="space-y-1">
127
+ <div className="flex items-center gap-2">
128
+ <FolderDown className="w-4 h-4 text-yellow-500" />
129
+ <span className="font-semibold">dataset.zip</span>
130
+ </div>
131
+ <div className="ml-6 space-y-1 border-l-2 border-border pl-4">
132
+ <div className="flex items-center gap-2">
133
+ <FolderDown className="w-4 h-4 text-yellow-500" />
134
+ <span>audio/</span>
135
+ </div>
136
+ <div className="ml-6 space-y-1 border-l-2 border-border pl-4">
137
+ <div className="flex items-center gap-2 text-muted-foreground">
138
+ <FileAudio className="w-4 h-4 text-blue-500" />
139
+ <span>speaker_001_line1_hello_world.wav</span>
140
+ </div>
141
+ <div className="flex items-center gap-2 text-muted-foreground">
142
+ <FileAudio className="w-4 h-4 text-blue-500" />
143
+ <span>speaker_001_line2_how_are_you.wav</span>
144
+ </div>
145
+ </div>
146
+ <div className="flex items-center gap-2">
147
+ <FolderDown className="w-4 h-4 text-yellow-500" />
148
+ <span>transcriptions/</span>
149
+ </div>
150
+ <div className="ml-6 space-y-1 border-l-2 border-border pl-4">
151
+ <div className="flex items-center gap-2 text-muted-foreground">
152
+ <FileText className="w-4 h-4 text-green-500" />
153
+ <span>speaker_001_line1_hello_world.txt</span>
154
+ </div>
155
+ <div className="flex items-center gap-2 text-muted-foreground">
156
+ <FileText className="w-4 h-4 text-green-500" />
157
+ <span>speaker_001_line2_how_are_you.txt</span>
158
+ </div>
159
+ </div>
160
+ </div>
161
+ </div>
162
+ </div>
163
+
164
+ {/* Transcription Format */}
165
+ <div className="mt-4">
166
+ <h4 className="font-semibold text-sm mb-2 flex items-center gap-2">
167
+ <FileText className="w-4 h-4 text-green-500" />
168
+ Transcription File Format
169
+ </h4>
170
+ <div className="bg-secondary/30 rounded-lg p-4 font-mono text-xs overflow-x-auto">
171
+ <pre className="text-muted-foreground">{`[METADATA]
172
+ Recording_ID: speaker_001_line1_hello_world.wav
173
+ Speaker_ID: speaker_001
174
+ Dataset_Name: my_dataset
175
+ Timestamp: 2024-12-13T10:30:00Z
176
+ Emotion: neutral
177
+ Rating: 5
178
+ Duration: 2.5
179
+ [TEXT]
180
+ Hello world, this is a sample sentence.`}</pre>
181
+ </div>
182
+ </div>
183
+
184
+ {/* Audio Format */}
185
+ <div className="mt-4 grid md:grid-cols-2 gap-4">
186
+ <div>
187
+ <h4 className="font-semibold text-sm mb-2 flex items-center gap-2">
188
+ <FileAudio className="w-4 h-4 text-blue-500" />
189
+ Audio Format
190
+ </h4>
191
+ <ul className="text-sm text-muted-foreground space-y-1">
192
+ <li>• Format: <strong className="text-foreground">WAV</strong></li>
193
+ <li>• Sample Rate: <strong className="text-foreground">48kHz</strong></li>
194
+ <li>• Channels: <strong className="text-foreground">Mono</strong></li>
195
+ <li>• Bit Depth: <strong className="text-foreground">16-bit</strong></li>
196
+ </ul>
197
+ </div>
198
+ <div>
199
+ <h4 className="font-semibold text-sm mb-2 flex items-center gap-2">
200
+ <FileJson className="w-4 h-4 text-purple-500" />
201
+ Compatible With
202
+ </h4>
203
+ <ul className="text-sm text-muted-foreground space-y-1">
204
+ <li>• Coqui TTS</li>
205
+ <li>• Mozilla TTS</li>
206
+ <li>• VITS / SoVITS</li>
207
+ <li>• Hugging Face Datasets</li>
208
+ </ul>
209
+ </div>
210
+ </div>
211
+ </section>
212
  </CardContent>
213
  </Card>
214
  </motion.div>
src/components/QuickTourPopup.tsx ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client';
2
+
3
+ import React, { useState, useEffect } from 'react';
4
+ import { motion, AnimatePresence } from 'framer-motion';
5
+ import { Mic2, HelpCircle } from 'lucide-react';
6
+
7
+ export default function QuickTourPopup() {
8
+ const [isVisible, setIsVisible] = useState(false);
9
+
10
+ useEffect(() => {
11
+ // Show popup after a brief delay
12
+ const showTimer = setTimeout(() => {
13
+ setIsVisible(true);
14
+ }, 500);
15
+
16
+ // Hide popup after 3 seconds
17
+ const hideTimer = setTimeout(() => {
18
+ setIsVisible(false);
19
+ }, 3500);
20
+
21
+ return () => {
22
+ clearTimeout(showTimer);
23
+ clearTimeout(hideTimer);
24
+ };
25
+ }, []);
26
+
27
+ return (
28
+ <AnimatePresence>
29
+ {isVisible && (
30
+ <motion.div
31
+ initial={{ opacity: 0, y: 50, scale: 0.9 }}
32
+ animate={{ opacity: 1, y: 0, scale: 1 }}
33
+ exit={{ opacity: 0, y: 20, scale: 0.95 }}
34
+ transition={{ type: 'spring', damping: 20, stiffness: 300 }}
35
+ className="fixed bottom-6 left-1/2 -translate-x-1/2 z-50"
36
+ >
37
+ <div className="bg-primary text-primary-foreground px-6 py-4 rounded-2xl shadow-2xl shadow-primary/25 flex items-center gap-4 max-w-md">
38
+ <div className="w-12 h-12 bg-white/20 rounded-xl flex items-center justify-center flex-shrink-0">
39
+ <Mic2 className="w-6 h-6" />
40
+ </div>
41
+ <div>
42
+ <h3 className="font-bold text-lg">Welcome to TTS Dataset Collector!</h3>
43
+ <p className="text-sm opacity-90 mt-1">
44
+ Click the <HelpCircle className="w-4 h-4 inline mx-1" /> icon anytime for help & shortcuts
45
+ </p>
46
+ </div>
47
+ </div>
48
+ </motion.div>
49
+ )}
50
+ </AnimatePresence>
51
+ );
52
+ }