react-native-elearn-ui 0.1.9 → 0.1.11

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 (52) hide show
  1. package/lib/module/index.js +1 -1
  2. package/lib/module/index.js.map +1 -1
  3. package/lib/module/screens/HomeScreen.js +2 -1
  4. package/lib/module/screens/HomeScreen.js.map +1 -1
  5. package/lib/module/screens/PearlChaptersScreen.js +359 -0
  6. package/lib/module/screens/PearlChaptersScreen.js.map +1 -0
  7. package/lib/module/screens/PearlReaderScreen.js +313 -0
  8. package/lib/module/screens/PearlReaderScreen.js.map +1 -0
  9. package/lib/module/screens/PearlsScreen.js +43 -631
  10. package/lib/module/screens/PearlsScreen.js.map +1 -1
  11. package/lib/module/screens/QbankScreen.js +2 -1
  12. package/lib/module/screens/QbankScreen.js.map +1 -1
  13. package/lib/module/screens/QuestionScreen.js +2 -1
  14. package/lib/module/screens/QuestionScreen.js.map +1 -1
  15. package/lib/module/screens/QuizStartScreen.js +2 -1
  16. package/lib/module/screens/QuizStartScreen.js.map +1 -1
  17. package/lib/module/screens/ResultScreen.js +2 -1
  18. package/lib/module/screens/ResultScreen.js.map +1 -1
  19. package/lib/module/screens/TopicListScreen.js +2 -1
  20. package/lib/module/screens/TopicListScreen.js.map +1 -1
  21. package/lib/module/screens/index.js +2 -0
  22. package/lib/module/screens/index.js.map +1 -1
  23. package/lib/module/screens/pearlsMockData.js +77 -0
  24. package/lib/module/screens/pearlsMockData.js.map +1 -0
  25. package/lib/typescript/src/index.d.ts +1 -1
  26. package/lib/typescript/src/index.d.ts.map +1 -1
  27. package/lib/typescript/src/screens/PearlChaptersScreen.d.ts +13 -0
  28. package/lib/typescript/src/screens/PearlChaptersScreen.d.ts.map +1 -0
  29. package/lib/typescript/src/screens/PearlReaderScreen.d.ts +14 -0
  30. package/lib/typescript/src/screens/PearlReaderScreen.d.ts.map +1 -0
  31. package/lib/typescript/src/screens/PearlsScreen.d.ts +3 -0
  32. package/lib/typescript/src/screens/PearlsScreen.d.ts.map +1 -1
  33. package/lib/typescript/src/screens/index.d.ts +2 -0
  34. package/lib/typescript/src/screens/index.d.ts.map +1 -1
  35. package/lib/typescript/src/screens/pearlsMockData.d.ts +3 -0
  36. package/lib/typescript/src/screens/pearlsMockData.d.ts.map +1 -0
  37. package/lib/typescript/src/types/index.d.ts +15 -0
  38. package/lib/typescript/src/types/index.d.ts.map +1 -1
  39. package/package.json +3 -1
  40. package/src/index.tsx +2 -0
  41. package/src/screens/HomeScreen.tsx +1 -1
  42. package/src/screens/PearlChaptersScreen.tsx +330 -0
  43. package/src/screens/PearlReaderScreen.tsx +306 -0
  44. package/src/screens/PearlsScreen.tsx +30 -603
  45. package/src/screens/QbankScreen.tsx +1 -1
  46. package/src/screens/QuestionScreen.tsx +1 -1
  47. package/src/screens/QuizStartScreen.tsx +1 -1
  48. package/src/screens/ResultScreen.tsx +1 -1
  49. package/src/screens/TopicListScreen.tsx +1 -1
  50. package/src/screens/index.ts +2 -0
  51. package/src/screens/pearlsMockData.ts +70 -0
  52. package/src/types/index.ts +17 -0
@@ -0,0 +1,306 @@
1
+ import React, { useState } from 'react';
2
+ import {
3
+ View,
4
+ ScrollView,
5
+ StyleSheet,
6
+ TouchableOpacity,
7
+ StatusBar,
8
+ } from 'react-native';
9
+ import { SafeAreaView } from 'react-native-safe-area-context';
10
+ import { useTheme } from '../context/ThemeContext';
11
+ import { Typography, Icon } from '../components';
12
+ import { MOCK_PEARLS_TOPICS } from './pearlsMockData';
13
+ import type { PearlTopic, PearlChapter } from '../types';
14
+
15
+ interface PearlReaderScreenProps {
16
+ topic?: PearlTopic;
17
+ topicId?: string;
18
+ chapter?: PearlChapter;
19
+ chapterId?: string;
20
+ onBack: () => void;
21
+ hideHeader?: boolean;
22
+ title?: string;
23
+ }
24
+
25
+ export const PearlReaderScreen: React.FC<PearlReaderScreenProps> = ({
26
+ topic,
27
+ topicId,
28
+ chapter,
29
+ chapterId,
30
+ onBack,
31
+ hideHeader = false,
32
+ title = 'Pearls',
33
+ }) => {
34
+ const theme = useTheme();
35
+
36
+ const activeTopic = topic || MOCK_PEARLS_TOPICS.find((t) => t.id === topicId);
37
+
38
+ // Flatten chapters for reader mode navigation
39
+ const flattenedChapters: PearlChapter[] = [];
40
+ if (activeTopic && activeTopic.sections) {
41
+ Object.keys(activeTopic.sections).forEach((sectionName) => {
42
+ const sectionChapters = activeTopic.sections?.[sectionName] || [];
43
+ flattenedChapters.push(...sectionChapters);
44
+ });
45
+ }
46
+
47
+ const initialIndex = chapterId
48
+ ? flattenedChapters.findIndex((c) => c.id === chapterId)
49
+ : chapter
50
+ ? flattenedChapters.findIndex((c) => c.id === chapter.id)
51
+ : 0;
52
+
53
+ const [activeChapterIndex, setActiveChapterIndex] = useState<number>(initialIndex >= 0 ? initialIndex : 0);
54
+ const [isCompleted, setIsCompleted] = useState(false);
55
+
56
+ const activeChapter = flattenedChapters[activeChapterIndex];
57
+
58
+ if (!activeChapter) {
59
+ return (
60
+ <SafeAreaView style={[styles.safeArea, { backgroundColor: theme.background }]}>
61
+ <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20 }}>
62
+ <Typography variant="h2" bold style={{ marginBottom: 12 }}>Chapter not found</Typography>
63
+ <TouchableOpacity
64
+ onPress={onBack}
65
+ style={{
66
+ paddingHorizontal: 20,
67
+ paddingVertical: 10,
68
+ borderRadius: 8,
69
+ backgroundColor: theme.primary,
70
+ }}
71
+ >
72
+ <Typography variant="body" bold color="#FFFFFF">Go Back</Typography>
73
+ </TouchableOpacity>
74
+ </View>
75
+ </SafeAreaView>
76
+ );
77
+ }
78
+
79
+ const handlePrevChapter = () => {
80
+ if (activeChapterIndex > 0) {
81
+ setActiveChapterIndex(activeChapterIndex - 1);
82
+ setIsCompleted(false);
83
+ }
84
+ };
85
+
86
+ const handleNextChapter = () => {
87
+ if (activeChapterIndex < flattenedChapters.length - 1) {
88
+ setActiveChapterIndex(activeChapterIndex + 1);
89
+ setIsCompleted(false);
90
+ }
91
+ };
92
+
93
+ return (
94
+ <SafeAreaView style={[styles.safeArea, { backgroundColor: theme.background }]}>
95
+ <StatusBar barStyle="dark-content" />
96
+
97
+ {/* Header */}
98
+ {!hideHeader && (
99
+ <View style={styles.header}>
100
+ <TouchableOpacity onPress={onBack} style={styles.backButton}>
101
+ <Icon name="arrow-left" size={20} color={theme.textPrimary} />
102
+ </TouchableOpacity>
103
+
104
+ <Typography variant="h2" bold style={styles.headerTitle}>
105
+ {title}
106
+ </Typography>
107
+
108
+ <View style={styles.headerRightPlaceholder} />
109
+ </View>
110
+ )}
111
+
112
+ {/* Reader Container */}
113
+ <View style={styles.readerContainer}>
114
+ {/* Subheader progress banner */}
115
+ <View style={styles.readerSubHeader}>
116
+ <Typography variant="body" bold color={theme.textPrimary} style={styles.readerSubTitle}>
117
+ {activeChapter.title.split('.')[0] || activeChapter.title}
118
+ </Typography>
119
+ <Typography variant="body" bold color={theme.textSecondary}>
120
+ {activeChapterIndex + 1}/{flattenedChapters.length}
121
+ </Typography>
122
+ </View>
123
+
124
+ <ScrollView contentContainerStyle={styles.readerScroll} showsVerticalScrollIndicator={false}>
125
+ {activeChapter.bullets.map((bullet, idx) => {
126
+ const parts = bullet.split(':');
127
+ const boldPart = parts[0];
128
+ const rest = parts.slice(1).join(':');
129
+
130
+ return (
131
+ <View key={idx} style={styles.bulletRow}>
132
+ <Typography variant="body" color={theme.textPrimary} style={styles.bulletPointDot}>
133
+
134
+ </Typography>
135
+ <Typography variant="body" color={theme.textPrimary} style={styles.bulletText}>
136
+ {rest ? (
137
+ <>
138
+ <Typography variant="body" bold>{boldPart}:</Typography>
139
+ {rest}
140
+ </>
141
+ ) : (
142
+ bullet
143
+ )}
144
+ </Typography>
145
+ </View>
146
+ );
147
+ })}
148
+ </ScrollView>
149
+
150
+ {/* Checkbox status bar */}
151
+ <View style={styles.checkboxBar}>
152
+ <TouchableOpacity
153
+ activeOpacity={0.8}
154
+ onPress={() => setIsCompleted(!isCompleted)}
155
+ style={styles.checkboxRow}
156
+ >
157
+ <View style={[
158
+ styles.checkboxBox,
159
+ { borderColor: theme.border },
160
+ isCompleted && { backgroundColor: theme.primary, borderColor: theme.primary }
161
+ ]}>
162
+ {isCompleted && <View style={styles.checkboxInner} />}
163
+ </View>
164
+ <Typography variant="body" bold color={theme.textPrimary}>
165
+ Mark as Complete
166
+ </Typography>
167
+ </TouchableOpacity>
168
+ </View>
169
+
170
+ {/* Navigation bottom buttons */}
171
+ <View style={styles.footerRow}>
172
+ <TouchableOpacity
173
+ onPress={handlePrevChapter}
174
+ disabled={activeChapterIndex === 0}
175
+ style={[styles.footerBtn, activeChapterIndex === 0 && { opacity: 0.4 }]}
176
+ >
177
+ <Typography variant="body" bold color={theme.textPrimary}>
178
+ Prev
179
+ </Typography>
180
+ </TouchableOpacity>
181
+
182
+ <TouchableOpacity
183
+ onPress={handleNextChapter}
184
+ disabled={activeChapterIndex === flattenedChapters.length - 1}
185
+ style={[
186
+ styles.nextActionBtn,
187
+ { backgroundColor: theme.primary },
188
+ activeChapterIndex === flattenedChapters.length - 1 && { opacity: 0.4 }
189
+ ]}
190
+ >
191
+ <Typography variant="body" bold color="#FFFFFF">
192
+ Next
193
+ </Typography>
194
+ </TouchableOpacity>
195
+ </View>
196
+ </View>
197
+ </SafeAreaView>
198
+ );
199
+ };
200
+
201
+ const styles = StyleSheet.create({
202
+ safeArea: {
203
+ flex: 1,
204
+ },
205
+ header: {
206
+ flexDirection: 'row',
207
+ justifyContent: 'space-between',
208
+ alignItems: 'center',
209
+ paddingHorizontal: 16,
210
+ paddingVertical: 12,
211
+ },
212
+ backButton: {
213
+ padding: 6,
214
+ },
215
+ headerTitle: {
216
+ fontSize: 18,
217
+ fontWeight: '700',
218
+ },
219
+ headerRightPlaceholder: {
220
+ width: 32,
221
+ },
222
+ readerContainer: {
223
+ flex: 1,
224
+ },
225
+ readerSubHeader: {
226
+ flexDirection: 'row',
227
+ justifyContent: 'space-between',
228
+ alignItems: 'center',
229
+ paddingHorizontal: 16,
230
+ paddingVertical: 12,
231
+ borderBottomWidth: 1,
232
+ borderBottomColor: '#E2E8F0',
233
+ },
234
+ readerSubTitle: {
235
+ flex: 1,
236
+ fontSize: 14,
237
+ marginRight: 16,
238
+ },
239
+ readerScroll: {
240
+ paddingHorizontal: 16,
241
+ paddingVertical: 16,
242
+ },
243
+ bulletRow: {
244
+ flexDirection: 'row',
245
+ alignItems: 'flex-start',
246
+ marginBottom: 16,
247
+ },
248
+ bulletPointDot: {
249
+ fontSize: 18,
250
+ marginRight: 10,
251
+ lineHeight: 20,
252
+ },
253
+ bulletText: {
254
+ flex: 1,
255
+ fontSize: 14,
256
+ lineHeight: 22,
257
+ },
258
+ checkboxBar: {
259
+ paddingHorizontal: 16,
260
+ paddingVertical: 14,
261
+ borderTopWidth: 1,
262
+ borderTopColor: '#E2E8F0',
263
+ backgroundColor: '#F8FAFC',
264
+ },
265
+ checkboxRow: {
266
+ flexDirection: 'row',
267
+ alignItems: 'center',
268
+ },
269
+ checkboxBox: {
270
+ width: 20,
271
+ height: 20,
272
+ borderWidth: 2,
273
+ borderRadius: 4,
274
+ justifyContent: 'center',
275
+ alignItems: 'center',
276
+ marginRight: 10,
277
+ },
278
+ checkboxInner: {
279
+ width: 10,
280
+ height: 10,
281
+ borderRadius: 2,
282
+ backgroundColor: '#FFFFFF',
283
+ },
284
+ footerRow: {
285
+ flexDirection: 'row',
286
+ alignItems: 'center',
287
+ paddingHorizontal: 16,
288
+ paddingVertical: 12,
289
+ backgroundColor: '#FFFFFF',
290
+ borderTopWidth: 1,
291
+ borderTopColor: '#E2E8F0',
292
+ justifyContent: 'space-between',
293
+ },
294
+ footerBtn: {
295
+ paddingVertical: 8,
296
+ paddingHorizontal: 12,
297
+ },
298
+ nextActionBtn: {
299
+ paddingHorizontal: 24,
300
+ paddingVertical: 10,
301
+ borderRadius: 8,
302
+ minWidth: 80,
303
+ justifyContent: 'center',
304
+ alignItems: 'center',
305
+ },
306
+ });