react-native-elearn-ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +37 -0
  3. package/lib/module/components/Button.js +82 -0
  4. package/lib/module/components/Button.js.map +1 -0
  5. package/lib/module/components/Card.js +49 -0
  6. package/lib/module/components/Card.js.map +1 -0
  7. package/lib/module/components/CircularProgress.js +80 -0
  8. package/lib/module/components/CircularProgress.js.map +1 -0
  9. package/lib/module/components/Icon.js +268 -0
  10. package/lib/module/components/Icon.js.map +1 -0
  11. package/lib/module/components/ProgressBar.js +39 -0
  12. package/lib/module/components/ProgressBar.js.map +1 -0
  13. package/lib/module/components/Typography.js +102 -0
  14. package/lib/module/components/Typography.js.map +1 -0
  15. package/lib/module/components/index.js +10 -0
  16. package/lib/module/components/index.js.map +1 -0
  17. package/lib/module/context/ElearnConfigContext.js +76 -0
  18. package/lib/module/context/ElearnConfigContext.js.map +1 -0
  19. package/lib/module/context/ThemeContext.js +45 -0
  20. package/lib/module/context/ThemeContext.js.map +1 -0
  21. package/lib/module/index.js +13 -0
  22. package/lib/module/index.js.map +1 -0
  23. package/lib/module/multiply.js +6 -0
  24. package/lib/module/multiply.js.map +1 -0
  25. package/lib/module/package.json +1 -0
  26. package/lib/module/screens/HomeScreen.js +330 -0
  27. package/lib/module/screens/HomeScreen.js.map +1 -0
  28. package/lib/module/screens/QbankScreen.js +200 -0
  29. package/lib/module/screens/QbankScreen.js.map +1 -0
  30. package/lib/module/screens/QuestionScreen.js +383 -0
  31. package/lib/module/screens/QuestionScreen.js.map +1 -0
  32. package/lib/module/screens/QuizStartScreen.js +230 -0
  33. package/lib/module/screens/QuizStartScreen.js.map +1 -0
  34. package/lib/module/screens/ResultScreen.js +318 -0
  35. package/lib/module/screens/ResultScreen.js.map +1 -0
  36. package/lib/module/screens/TopicListScreen.js +222 -0
  37. package/lib/module/screens/TopicListScreen.js.map +1 -0
  38. package/lib/module/screens/index.js +9 -0
  39. package/lib/module/screens/index.js.map +1 -0
  40. package/lib/module/types/index.js +2 -0
  41. package/lib/module/types/index.js.map +1 -0
  42. package/lib/typescript/package.json +1 -0
  43. package/lib/typescript/src/components/Button.d.ts +14 -0
  44. package/lib/typescript/src/components/Button.d.ts.map +1 -0
  45. package/lib/typescript/src/components/Card.d.ts +12 -0
  46. package/lib/typescript/src/components/Card.d.ts.map +1 -0
  47. package/lib/typescript/src/components/CircularProgress.d.ts +15 -0
  48. package/lib/typescript/src/components/CircularProgress.d.ts.map +1 -0
  49. package/lib/typescript/src/components/Icon.d.ts +11 -0
  50. package/lib/typescript/src/components/Icon.d.ts.map +1 -0
  51. package/lib/typescript/src/components/ProgressBar.d.ts +11 -0
  52. package/lib/typescript/src/components/ProgressBar.d.ts.map +1 -0
  53. package/lib/typescript/src/components/Typography.d.ts +12 -0
  54. package/lib/typescript/src/components/Typography.d.ts.map +1 -0
  55. package/lib/typescript/src/components/index.d.ts +9 -0
  56. package/lib/typescript/src/components/index.d.ts.map +1 -0
  57. package/lib/typescript/src/context/ElearnConfigContext.d.ts +22 -0
  58. package/lib/typescript/src/context/ElearnConfigContext.d.ts.map +1 -0
  59. package/lib/typescript/src/context/ThemeContext.d.ts +11 -0
  60. package/lib/typescript/src/context/ThemeContext.d.ts.map +1 -0
  61. package/lib/typescript/src/index.d.ts +6 -0
  62. package/lib/typescript/src/index.d.ts.map +1 -0
  63. package/lib/typescript/src/multiply.d.ts +2 -0
  64. package/lib/typescript/src/multiply.d.ts.map +1 -0
  65. package/lib/typescript/src/screens/HomeScreen.d.ts +3 -0
  66. package/lib/typescript/src/screens/HomeScreen.d.ts.map +1 -0
  67. package/lib/typescript/src/screens/QbankScreen.d.ts +3 -0
  68. package/lib/typescript/src/screens/QbankScreen.d.ts.map +1 -0
  69. package/lib/typescript/src/screens/QuestionScreen.d.ts +11 -0
  70. package/lib/typescript/src/screens/QuestionScreen.d.ts.map +1 -0
  71. package/lib/typescript/src/screens/QuizStartScreen.d.ts +10 -0
  72. package/lib/typescript/src/screens/QuizStartScreen.d.ts.map +1 -0
  73. package/lib/typescript/src/screens/ResultScreen.d.ts +11 -0
  74. package/lib/typescript/src/screens/ResultScreen.d.ts.map +1 -0
  75. package/lib/typescript/src/screens/TopicListScreen.d.ts +9 -0
  76. package/lib/typescript/src/screens/TopicListScreen.d.ts.map +1 -0
  77. package/lib/typescript/src/screens/index.d.ts +7 -0
  78. package/lib/typescript/src/screens/index.d.ts.map +1 -0
  79. package/lib/typescript/src/types/index.d.ts +107 -0
  80. package/lib/typescript/src/types/index.d.ts.map +1 -0
  81. package/package.json +121 -0
  82. package/src/components/Button.tsx +101 -0
  83. package/src/components/Card.tsx +57 -0
  84. package/src/components/CircularProgress.tsx +93 -0
  85. package/src/components/Icon.tsx +338 -0
  86. package/src/components/ProgressBar.tsx +47 -0
  87. package/src/components/Typography.tsx +112 -0
  88. package/src/components/index.ts +8 -0
  89. package/src/context/ElearnConfigContext.tsx +90 -0
  90. package/src/context/ThemeContext.tsx +37 -0
  91. package/src/index.tsx +33 -0
  92. package/src/multiply.tsx +3 -0
  93. package/src/screens/HomeScreen.tsx +291 -0
  94. package/src/screens/QbankScreen.tsx +176 -0
  95. package/src/screens/QuestionScreen.tsx +402 -0
  96. package/src/screens/QuizStartScreen.tsx +215 -0
  97. package/src/screens/ResultScreen.tsx +303 -0
  98. package/src/screens/TopicListScreen.tsx +200 -0
  99. package/src/screens/index.ts +6 -0
  100. package/src/types/index.ts +122 -0
@@ -0,0 +1,303 @@
1
+ import React from 'react';
2
+ import {
3
+ View,
4
+ ScrollView,
5
+ StyleSheet,
6
+ TouchableOpacity,
7
+ SafeAreaView,
8
+ StatusBar,
9
+ } from 'react-native';
10
+ import type { QuizResults, Question } from '../types';
11
+ import { useElearnConfig } from '../context/ElearnConfigContext';
12
+ import { useTheme } from '../context/ThemeContext';
13
+ import { Typography, Card, CircularProgress, Button, Icon } from '../components';
14
+
15
+ interface ResultScreenProps {
16
+ results: QuizResults;
17
+ questions: Question[];
18
+ onClose: () => void;
19
+ onReviewAnswers?: () => void;
20
+ }
21
+
22
+ export const ResultScreen: React.FC<ResultScreenProps> = ({
23
+ results,
24
+ questions,
25
+ onClose,
26
+ onReviewAnswers,
27
+ }) => {
28
+ const { getString } = useElearnConfig();
29
+ const theme = useTheme();
30
+
31
+ const formatTime = (totalSeconds: number) => {
32
+ const mins = Math.floor(totalSeconds / 60);
33
+ const secs = totalSeconds % 60;
34
+ if (mins > 0) {
35
+ return `${mins}m ${secs}s`;
36
+ }
37
+ return `${secs}s`;
38
+ };
39
+
40
+ return (
41
+ <SafeAreaView style={[styles.safeArea, { backgroundColor: theme.background }]}>
42
+ <StatusBar barStyle="dark-content" />
43
+
44
+ {/* Header */}
45
+ <View style={styles.header}>
46
+ <View style={styles.headerLeftPlaceholder} />
47
+ <Typography variant="h2" bold>
48
+ {getString('resultsTitle')}
49
+ </Typography>
50
+ <TouchableOpacity onPress={onClose} style={styles.closeButton}>
51
+ <Icon name="x-circle" size={24} color={theme.textSecondary} />
52
+ </TouchableOpacity>
53
+ </View>
54
+
55
+ <ScrollView contentContainerStyle={styles.scrollContent} showsVerticalScrollIndicator={false}>
56
+
57
+ {/* Scorecard Summary */}
58
+ <Card bordered style={styles.summaryCard}>
59
+ <View style={styles.summaryRow}>
60
+ <View style={styles.summaryLeft}>
61
+ <Typography variant="h1" bold color={theme.textPrimary}>
62
+ {getString('scorecardTitle')}
63
+ </Typography>
64
+ <Typography variant="body" color={theme.textSecondary} style={styles.summarySubtitle}>
65
+ {getString('resultsSubtitle')}
66
+ </Typography>
67
+
68
+ <View style={styles.statsContainer}>
69
+ <View style={styles.statBox}>
70
+ <Typography variant="caption" color={theme.textSecondary}>
71
+ {getString('correctAnswersCountLabel')}
72
+ </Typography>
73
+ <Typography variant="h2" bold color={theme.success}>
74
+ {results.correctCount} / {results.totalQuestions}
75
+ </Typography>
76
+ </View>
77
+
78
+ <View style={styles.statBox}>
79
+ <Typography variant="caption" color={theme.textSecondary}>
80
+ {getString('timeSpentLabel')}
81
+ </Typography>
82
+ <Typography variant="h2" bold color={theme.textPrimary}>
83
+ {formatTime(results.timeSpentSeconds)}
84
+ </Typography>
85
+ </View>
86
+ </View>
87
+ </View>
88
+
89
+ <View style={styles.summaryRight}>
90
+ <CircularProgress
91
+ progress={results.accuracy / 100}
92
+ size={84}
93
+ strokeWidth={8}
94
+ color={results.accuracy >= 60 ? theme.success : theme.warning}
95
+ backgroundColor={theme.secondary}
96
+ textStyle={{ fontSize: 16 }}
97
+ />
98
+ <Typography variant="caption" color={theme.textSecondary} style={styles.accuracyText}>
99
+ {getString('accuracyLabel')}
100
+ </Typography>
101
+ </View>
102
+ </View>
103
+ </Card>
104
+
105
+ {/* Detailed Question Review List */}
106
+ <View style={styles.sectionHeader}>
107
+ <Typography variant="h2" bold>
108
+ Questions Summary
109
+ </Typography>
110
+ </View>
111
+
112
+ <View style={styles.reviewList}>
113
+ {questions.map((question, idx) => {
114
+ const userAnswerIdx = results.userAnswers[question.id];
115
+ const isCorrect = userAnswerIdx === question.correctOptionIndex;
116
+ const optionPrefixes = ['A', 'B', 'C', 'D', 'E'];
117
+
118
+ return (
119
+ <Card key={question.id} bordered style={styles.reviewCard}>
120
+ <View style={styles.reviewCardHeader}>
121
+ <View style={[styles.questionNumBadge, { backgroundColor: theme.secondary }]}>
122
+ <Typography variant="caption" bold color={theme.primary}>
123
+ Q{idx + 1}
124
+ </Typography>
125
+ </View>
126
+
127
+ <View style={styles.statusBadge}>
128
+ <Icon
129
+ name={isCorrect ? 'check-circle' : 'x-circle'}
130
+ size={18}
131
+ color={isCorrect ? theme.success : theme.danger}
132
+ />
133
+ <Typography
134
+ variant="caption"
135
+ bold
136
+ color={isCorrect ? theme.success : theme.danger}
137
+ style={styles.statusBadgeText}
138
+ >
139
+ {isCorrect ? 'Correct' : 'Incorrect'}
140
+ </Typography>
141
+ </View>
142
+ </View>
143
+
144
+ <Typography variant="body" bold style={styles.reviewQuestionText}>
145
+ {question.text}
146
+ </Typography>
147
+
148
+ <View style={styles.userSelectionContainer}>
149
+ <Typography variant="caption" color={theme.textSecondary}>
150
+ Your answer:{' '}
151
+ <Typography variant="caption" bold color={isCorrect ? theme.success : theme.danger}>
152
+ {userAnswerIdx !== undefined
153
+ ? `Option ${optionPrefixes[userAnswerIdx] || userAnswerIdx + 1}`
154
+ : 'Skipped'}
155
+ </Typography>
156
+ </Typography>
157
+
158
+ {!isCorrect && (
159
+ <Typography variant="caption" color={theme.textSecondary} style={styles.correctAnswerText}>
160
+ Correct answer:{' '}
161
+ <Typography variant="caption" bold color={theme.success}>
162
+ Option {optionPrefixes[question.correctOptionIndex] || question.correctOptionIndex + 1}
163
+ </Typography>
164
+ </Typography>
165
+ )}
166
+ </View>
167
+ </Card>
168
+ );
169
+ })}
170
+ </View>
171
+
172
+ </ScrollView>
173
+
174
+ {/* Footer Controls */}
175
+ <View style={[styles.footer, { backgroundColor: theme.cardBackground, borderTopColor: theme.border }]}>
176
+ {onReviewAnswers && (
177
+ <Button
178
+ title={getString('reviewAnswersButton')}
179
+ onPress={onReviewAnswers}
180
+ variant="outline"
181
+ style={styles.reviewBtn}
182
+ />
183
+ )}
184
+ <Button
185
+ title={getString('goHomeButton')}
186
+ onPress={onClose}
187
+ variant="primary"
188
+ style={styles.homeBtn}
189
+ />
190
+ </View>
191
+ </SafeAreaView>
192
+ );
193
+ };
194
+
195
+ const styles = StyleSheet.create({
196
+ safeArea: {
197
+ flex: 1,
198
+ },
199
+ header: {
200
+ flexDirection: 'row',
201
+ justifyContent: 'space-between',
202
+ alignItems: 'center',
203
+ paddingHorizontal: 20,
204
+ paddingVertical: 12,
205
+ },
206
+ headerLeftPlaceholder: {
207
+ width: 40,
208
+ },
209
+ closeButton: {
210
+ padding: 4,
211
+ },
212
+ scrollContent: {
213
+ paddingHorizontal: 20,
214
+ paddingTop: 12,
215
+ paddingBottom: 40,
216
+ },
217
+ summaryCard: {
218
+ padding: 20,
219
+ borderRadius: 20,
220
+ },
221
+ summaryRow: {
222
+ flexDirection: 'row',
223
+ justifyContent: 'space-between',
224
+ alignItems: 'center',
225
+ },
226
+ summaryLeft: {
227
+ flex: 1,
228
+ paddingRight: 16,
229
+ },
230
+ summarySubtitle: {
231
+ marginTop: 4,
232
+ marginBottom: 16,
233
+ },
234
+ statsContainer: {
235
+ flexDirection: 'row',
236
+ },
237
+ statBox: {
238
+ marginRight: 24,
239
+ },
240
+ summaryRight: {
241
+ alignItems: 'center',
242
+ justifyContent: 'center',
243
+ },
244
+ accuracyText: {
245
+ marginTop: 8,
246
+ fontWeight: '600',
247
+ },
248
+ sectionHeader: {
249
+ marginTop: 28,
250
+ marginBottom: 12,
251
+ },
252
+ reviewList: {
253
+ marginTop: 4,
254
+ },
255
+ reviewCard: {
256
+ padding: 16,
257
+ marginBottom: 12,
258
+ },
259
+ reviewCardHeader: {
260
+ flexDirection: 'row',
261
+ justifyContent: 'space-between',
262
+ alignItems: 'center',
263
+ marginBottom: 10,
264
+ },
265
+ questionNumBadge: {
266
+ paddingHorizontal: 8,
267
+ paddingVertical: 4,
268
+ borderRadius: 8,
269
+ },
270
+ statusBadge: {
271
+ flexDirection: 'row',
272
+ alignItems: 'center',
273
+ },
274
+ statusBadgeText: {
275
+ marginLeft: 6,
276
+ },
277
+ reviewQuestionText: {
278
+ lineHeight: 20,
279
+ marginBottom: 10,
280
+ },
281
+ userSelectionContainer: {
282
+ backgroundColor: '#F8FAFC',
283
+ padding: 10,
284
+ borderRadius: 8,
285
+ },
286
+ correctAnswerText: {
287
+ marginTop: 4,
288
+ },
289
+ footer: {
290
+ paddingHorizontal: 20,
291
+ paddingVertical: 14,
292
+ borderTopWidth: 1,
293
+ flexDirection: 'row',
294
+ justifyContent: 'space-between',
295
+ },
296
+ reviewBtn: {
297
+ flex: 1,
298
+ marginRight: 12,
299
+ },
300
+ homeBtn: {
301
+ flex: 1,
302
+ },
303
+ });
@@ -0,0 +1,200 @@
1
+ import React from 'react';
2
+ import {
3
+ View,
4
+ ScrollView,
5
+ StyleSheet,
6
+ TouchableOpacity,
7
+ SafeAreaView,
8
+ StatusBar,
9
+ } from 'react-native';
10
+ import type { Course } from '../types';
11
+ import { useElearnConfig } from '../context/ElearnConfigContext';
12
+ import { useTheme } from '../context/ThemeContext';
13
+ import { Typography, Card, ProgressBar, Icon } from '../components';
14
+
15
+ interface TopicListScreenProps {
16
+ course: Course;
17
+ onBack: () => void;
18
+ }
19
+
20
+ export const TopicListScreen: React.FC<TopicListScreenProps> = ({
21
+ course,
22
+ onBack,
23
+ }) => {
24
+ const { callbacks, getString } = useElearnConfig();
25
+ const theme = useTheme();
26
+
27
+ return (
28
+ <SafeAreaView style={[styles.safeArea, { backgroundColor: theme.background }]}>
29
+ <StatusBar barStyle="dark-content" />
30
+
31
+ {/* Header */}
32
+ <View style={styles.header}>
33
+ <TouchableOpacity
34
+ onPress={onBack}
35
+ style={[styles.backButton, { borderColor: theme.border }]}
36
+ >
37
+ <Icon name="arrow-left" size={20} color={theme.textPrimary} />
38
+ </TouchableOpacity>
39
+ <Typography variant="h3" bold style={styles.headerTitle} numberOfLines={1}>
40
+ {course.title}
41
+ </Typography>
42
+ <View style={styles.headerRightPlaceholder} />
43
+ </View>
44
+
45
+ <ScrollView contentContainerStyle={styles.scrollContent} showsVerticalScrollIndicator={false}>
46
+
47
+ {/* Subject Summary Card */}
48
+ <Card style={[styles.summaryCard, { backgroundColor: theme.primary }]}>
49
+ <Typography variant="h2" bold color="#FFFFFF">
50
+ {course.title}
51
+ </Typography>
52
+ {course.description && (
53
+ <Typography variant="caption" color="rgba(255, 255, 255, 0.8)" style={styles.summaryDesc}>
54
+ {course.description}
55
+ </Typography>
56
+ )}
57
+ <View style={styles.progressSummaryContainer}>
58
+ <View style={styles.progressSummaryText}>
59
+ <Typography variant="caption" color="#FFFFFF">
60
+ Overall Subject Progress
61
+ </Typography>
62
+ <Typography variant="label" bold color="#FFFFFF">
63
+ {course.completedQuestions}/{course.totalQuestions} Questions answered
64
+ </Typography>
65
+ </View>
66
+ <Typography variant="h2" bold color="#FFFFFF">
67
+ {Math.round(course.progress * 100)}%
68
+ </Typography>
69
+ </View>
70
+ <ProgressBar progress={course.progress} color="#FFFFFF" style={styles.summaryProgressBar} />
71
+ </Card>
72
+
73
+ {/* List of Topics */}
74
+ <View style={styles.sectionHeader}>
75
+ <Typography variant="h2" bold color={theme.textPrimary}>
76
+ {getString('topicsLabel')} ({course.topics.length})
77
+ </Typography>
78
+ </View>
79
+
80
+ <View style={styles.topicsList}>
81
+ {course.topics.map((topic) => {
82
+ const pct = Math.round(topic.progress * 100);
83
+
84
+ return (
85
+ <TouchableOpacity
86
+ key={topic.id}
87
+ activeOpacity={0.8}
88
+ onPress={() => callbacks.onSelectTopic?.(course, topic)}
89
+ >
90
+ <Card bordered style={styles.topicCard}>
91
+ <View style={styles.topicCardHeader}>
92
+ <View style={styles.topicTitleSection}>
93
+ <Typography variant="h3" bold color={theme.textPrimary}>
94
+ {topic.title}
95
+ </Typography>
96
+ <Typography variant="caption" color={theme.textSecondary}>
97
+ {topic.completedQuestions}/{topic.totalQuestions} {getString('questionsCountLabel')}
98
+ </Typography>
99
+ </View>
100
+ <View style={styles.pctBadge}>
101
+ <Typography variant="caption" bold color={theme.primary}>
102
+ {pct}%
103
+ </Typography>
104
+ </View>
105
+ </View>
106
+ <ProgressBar progress={topic.progress} style={styles.topicProgressBar} />
107
+ </Card>
108
+ </TouchableOpacity>
109
+ );
110
+ })}
111
+ </View>
112
+
113
+ </ScrollView>
114
+ </SafeAreaView>
115
+ );
116
+ };
117
+
118
+ const styles = StyleSheet.create({
119
+ safeArea: {
120
+ flex: 1,
121
+ },
122
+ header: {
123
+ flexDirection: 'row',
124
+ justifyContent: 'space-between',
125
+ alignItems: 'center',
126
+ paddingHorizontal: 20,
127
+ paddingVertical: 12,
128
+ },
129
+ backButton: {
130
+ width: 40,
131
+ height: 40,
132
+ borderRadius: 20,
133
+ borderWidth: 1,
134
+ justifyContent: 'center',
135
+ alignItems: 'center',
136
+ },
137
+ headerTitle: {
138
+ flex: 1,
139
+ textAlign: 'center',
140
+ marginHorizontal: 12,
141
+ },
142
+ headerRightPlaceholder: {
143
+ width: 40,
144
+ },
145
+ scrollContent: {
146
+ paddingHorizontal: 20,
147
+ paddingBottom: 24,
148
+ },
149
+ summaryCard: {
150
+ padding: 20,
151
+ borderRadius: 20,
152
+ marginTop: 12,
153
+ },
154
+ summaryDesc: {
155
+ marginTop: 6,
156
+ },
157
+ progressSummaryContainer: {
158
+ flexDirection: 'row',
159
+ justifyContent: 'space-between',
160
+ alignItems: 'flex-end',
161
+ marginTop: 20,
162
+ marginBottom: 8,
163
+ },
164
+ progressSummaryText: {
165
+ flex: 1,
166
+ },
167
+ summaryProgressBar: {
168
+ backgroundColor: 'rgba(255, 255, 255, 0.25)',
169
+ },
170
+ sectionHeader: {
171
+ marginTop: 24,
172
+ marginBottom: 12,
173
+ },
174
+ topicsList: {
175
+ marginTop: 4,
176
+ },
177
+ topicCard: {
178
+ padding: 16,
179
+ marginBottom: 12,
180
+ },
181
+ topicCardHeader: {
182
+ flexDirection: 'row',
183
+ justifyContent: 'space-between',
184
+ alignItems: 'center',
185
+ marginBottom: 12,
186
+ },
187
+ topicTitleSection: {
188
+ flex: 1,
189
+ paddingRight: 12,
190
+ },
191
+ pctBadge: {
192
+ paddingHorizontal: 8,
193
+ paddingVertical: 4,
194
+ borderRadius: 8,
195
+ backgroundColor: 'rgba(0, 122, 135, 0.1)', // Dynamic overlay of primary color
196
+ },
197
+ topicProgressBar: {
198
+ height: 6,
199
+ },
200
+ });
@@ -0,0 +1,6 @@
1
+ export { HomeScreen } from './HomeScreen';
2
+ export { QbankScreen } from './QbankScreen';
3
+ export { TopicListScreen } from './TopicListScreen';
4
+ export { QuizStartScreen } from './QuizStartScreen';
5
+ export { QuestionScreen } from './QuestionScreen';
6
+ export { ResultScreen } from './ResultScreen';
@@ -0,0 +1,122 @@
1
+ export interface ThemeConfig {
2
+ primary: string;
3
+ secondary: string;
4
+ success: string;
5
+ danger: string;
6
+ warning: string;
7
+ background: string;
8
+ cardBackground: string;
9
+ textPrimary: string;
10
+ textSecondary: string;
11
+ textInverse: string;
12
+ border: string;
13
+ fontRegular?: string;
14
+ fontMedium?: string;
15
+ fontBold?: string;
16
+ }
17
+
18
+ export interface StringsConfig {
19
+ // Home Screen
20
+ homeHeaderTitle?: string;
21
+ homeHeaderSubtitle?: string;
22
+ dailyQuizTitle?: string;
23
+ dailyQuizSubtitle?: string;
24
+ dailyQuizProgressLabel?: string;
25
+ trackQuickLabel?: string;
26
+ subjectsTitle?: string;
27
+ popularTopicsTitle?: string;
28
+
29
+ // QBank
30
+ qbankTitle?: string;
31
+ qbankSubtitle?: string;
32
+ topicsLabel?: string;
33
+ questionsCountLabel?: string;
34
+
35
+ // Topics & Detail
36
+ startQuizButton?: string;
37
+ topicsAndItemsLabel?: string;
38
+ infoTitle?: string;
39
+
40
+ // Question & Explanation
41
+ questionLabel?: string;
42
+ explanationLabel?: string;
43
+ nextButtonLabel?: string;
44
+ submitButtonLabel?: string;
45
+ correctAnswerLabel?: string;
46
+ incorrectAnswerLabel?: string;
47
+
48
+ // Results
49
+ resultsTitle?: string;
50
+ resultsSubtitle?: string;
51
+ accuracyLabel?: string;
52
+ timeSpentLabel?: string;
53
+ correctAnswersCountLabel?: string;
54
+ reviewAnswersButton?: string;
55
+ goHomeButton?: string;
56
+ scorecardTitle?: string;
57
+ }
58
+
59
+ export interface Question {
60
+ id: string;
61
+ text: string;
62
+ imageUrl?: string;
63
+ options: string[];
64
+ correctOptionIndex: number;
65
+ explanation: string;
66
+ }
67
+
68
+ export interface Topic {
69
+ id: string;
70
+ title: string;
71
+ totalQuestions: number;
72
+ completedQuestions: number;
73
+ progress: number; // 0 to 1
74
+ questions?: Question[];
75
+ }
76
+
77
+ export interface Course {
78
+ id: string;
79
+ title: string;
80
+ description?: string;
81
+ iconName?: string; // name to match vector icons or pre-bundled icons
82
+ progress: number; // 0 to 1
83
+ totalQuestions: number;
84
+ completedQuestions: number;
85
+ topics: Topic[];
86
+ }
87
+
88
+ export interface DailyQuizConfig {
89
+ id: string;
90
+ title: string;
91
+ description: string;
92
+ questionsCount: number;
93
+ progressPercentage: number;
94
+ questions: Question[];
95
+ }
96
+
97
+ export interface ElearnConfig {
98
+ theme?: Partial<ThemeConfig>;
99
+ strings?: Partial<StringsConfig>;
100
+ courses?: Course[];
101
+ dailyQuiz?: DailyQuizConfig;
102
+ }
103
+
104
+ // Navigation / Interaction callbacks
105
+ export interface ElearnCallbacks {
106
+ onStartQuiz?: (quizId: string, questions: Question[], title: string) => void;
107
+ onSelectCourse?: (course: Course) => void;
108
+ onSelectTopic?: (course: Course, topic: Topic) => void;
109
+ onFinishQuiz?: (quizId: string, results: QuizResults) => void;
110
+ onBackToDashboard?: () => void;
111
+ }
112
+
113
+ export interface QuizResults {
114
+ quizId: string;
115
+ totalQuestions: number;
116
+ correctCount: number;
117
+ wrongCount: number;
118
+ skippedCount: number;
119
+ accuracy: number; // percentage, e.g. 75
120
+ timeSpentSeconds: number;
121
+ userAnswers: { [questionId: string]: number }; // questionId -> selectedIndex
122
+ }