@ubkinfotech/tecaher-erp 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 (146) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +413 -0
  3. package/lib/commonjs/core/api/apiClient.js +38 -0
  4. package/lib/commonjs/core/api/endpoints.js +139 -0
  5. package/lib/commonjs/core/api/interceptor.js +64 -0
  6. package/lib/commonjs/core/auth/authContext.js +30 -0
  7. package/lib/commonjs/core/auth/authService.js +12 -0
  8. package/lib/commonjs/core/hooks/useApiQuery.js +26 -0
  9. package/lib/commonjs/core/provider/ERPProvider.js +63 -0
  10. package/lib/commonjs/core/provider/types.js +5 -0
  11. package/lib/commonjs/core/provider/useERP.js +17 -0
  12. package/lib/commonjs/core/types/api.js +1 -0
  13. package/lib/commonjs/index.js +110 -0
  14. package/lib/commonjs/modules/assignment/hooks/useAssignmentList.js +16 -0
  15. package/lib/commonjs/modules/assignment/hooks/useHomeworkDetails.js +16 -0
  16. package/lib/commonjs/modules/assignment/hooks/useHomeworkSubmissions.js +16 -0
  17. package/lib/commonjs/modules/assignment/screens/AssignmentScreen.js +2615 -0
  18. package/lib/commonjs/modules/assignment/services/assignmentService.js +75 -0
  19. package/lib/commonjs/modules/attendance/hooks/useAttendance.js +16 -0
  20. package/lib/commonjs/modules/attendance/screens/AttendanceScreen.js +866 -0
  21. package/lib/commonjs/modules/attendance/services/attendanceService.js +31 -0
  22. package/lib/commonjs/modules/leaveRequest/hooks/useLeaveRequests.js +16 -0
  23. package/lib/commonjs/modules/leaveRequest/screens/LeaveRequestScreen.js +991 -0
  24. package/lib/commonjs/modules/leaveRequest/services/leaveRequestService.js +42 -0
  25. package/lib/commonjs/modules/marks/hooks/useMarks.js +14 -0
  26. package/lib/commonjs/modules/marks/screens/MarksScreen.js +1621 -0
  27. package/lib/commonjs/modules/marks/services/marksService.js +71 -0
  28. package/lib/commonjs/modules/myAttendance/hooks/useMyAttendance.js +16 -0
  29. package/lib/commonjs/modules/myAttendance/screens/MyAttendanceScreen.js +357 -0
  30. package/lib/commonjs/modules/myAttendance/services/myAttendanceService.js +11 -0
  31. package/lib/commonjs/modules/notes/hooks/useNotes.js +16 -0
  32. package/lib/commonjs/modules/notes/screens/NotesScreen.js +1287 -0
  33. package/lib/commonjs/modules/notes/services/notesService.js +65 -0
  34. package/lib/commonjs/modules/noticeboard/hooks/useNoticeboard.js +16 -0
  35. package/lib/commonjs/modules/noticeboard/screens/NoticeBoardScreen.js +381 -0
  36. package/lib/commonjs/modules/noticeboard/services/noticeboardService.js +16 -0
  37. package/lib/commonjs/modules/notification/hooks/useNotifications.js +16 -0
  38. package/lib/commonjs/modules/notification/screens/NotificationScreen.js +186 -0
  39. package/lib/commonjs/modules/notification/services/notificationService.js +16 -0
  40. package/lib/commonjs/modules/promoteStudent/hooks/usePromoteStudent.js +16 -0
  41. package/lib/commonjs/modules/promoteStudent/screens/PromoteStudentScreen.js +644 -0
  42. package/lib/commonjs/modules/promoteStudent/services/promoteStudentService.js +36 -0
  43. package/lib/commonjs/modules/timetable/hooks/useTimeTable.js +14 -0
  44. package/lib/commonjs/modules/timetable/screens/TimeTableScreen.js +258 -0
  45. package/lib/commonjs/modules/timetable/services/timetableService.js +16 -0
  46. package/lib/commonjs/package.json +1 -0
  47. package/lib/commonjs/shared/empty-states/EmptyState.js +45 -0
  48. package/lib/commonjs/shared/empty-states/ErrorState.js +45 -0
  49. package/lib/commonjs/shared/loaders/LoadingState.js +25 -0
  50. package/lib/commonjs/shared/theme/theme.js +22 -0
  51. package/lib/module/core/api/apiClient.js +32 -0
  52. package/lib/module/core/api/endpoints.js +135 -0
  53. package/lib/module/core/api/interceptor.js +60 -0
  54. package/lib/module/core/auth/authContext.js +23 -0
  55. package/lib/module/core/auth/authService.js +8 -0
  56. package/lib/module/core/hooks/useApiQuery.js +21 -0
  57. package/lib/module/core/provider/ERPProvider.js +56 -0
  58. package/lib/module/core/provider/types.js +3 -0
  59. package/lib/module/core/provider/useERP.js +12 -0
  60. package/lib/module/core/types/api.js +1 -0
  61. package/lib/module/index.js +17 -0
  62. package/lib/module/modules/assignment/hooks/useAssignmentList.js +12 -0
  63. package/lib/module/modules/assignment/hooks/useHomeworkDetails.js +12 -0
  64. package/lib/module/modules/assignment/hooks/useHomeworkSubmissions.js +12 -0
  65. package/lib/module/modules/assignment/screens/AssignmentScreen.js +2609 -0
  66. package/lib/module/modules/assignment/services/assignmentService.js +62 -0
  67. package/lib/module/modules/attendance/hooks/useAttendance.js +12 -0
  68. package/lib/module/modules/attendance/screens/AttendanceScreen.js +860 -0
  69. package/lib/module/modules/attendance/services/attendanceService.js +23 -0
  70. package/lib/module/modules/leaveRequest/hooks/useLeaveRequests.js +12 -0
  71. package/lib/module/modules/leaveRequest/screens/LeaveRequestScreen.js +985 -0
  72. package/lib/module/modules/leaveRequest/services/leaveRequestService.js +35 -0
  73. package/lib/module/modules/marks/hooks/useMarks.js +10 -0
  74. package/lib/module/modules/marks/screens/MarksScreen.js +1615 -0
  75. package/lib/module/modules/marks/services/marksService.js +55 -0
  76. package/lib/module/modules/myAttendance/hooks/useMyAttendance.js +12 -0
  77. package/lib/module/modules/myAttendance/screens/MyAttendanceScreen.js +351 -0
  78. package/lib/module/modules/myAttendance/services/myAttendanceService.js +7 -0
  79. package/lib/module/modules/notes/hooks/useNotes.js +12 -0
  80. package/lib/module/modules/notes/screens/NotesScreen.js +1281 -0
  81. package/lib/module/modules/notes/services/notesService.js +54 -0
  82. package/lib/module/modules/noticeboard/hooks/useNoticeboard.js +12 -0
  83. package/lib/module/modules/noticeboard/screens/NoticeBoardScreen.js +375 -0
  84. package/lib/module/modules/noticeboard/services/noticeboardService.js +12 -0
  85. package/lib/module/modules/notification/hooks/useNotifications.js +12 -0
  86. package/lib/module/modules/notification/screens/NotificationScreen.js +180 -0
  87. package/lib/module/modules/notification/services/notificationService.js +12 -0
  88. package/lib/module/modules/promoteStudent/hooks/usePromoteStudent.js +12 -0
  89. package/lib/module/modules/promoteStudent/screens/PromoteStudentScreen.js +638 -0
  90. package/lib/module/modules/promoteStudent/services/promoteStudentService.js +27 -0
  91. package/lib/module/modules/timetable/hooks/useTimeTable.js +10 -0
  92. package/lib/module/modules/timetable/screens/TimeTableScreen.js +252 -0
  93. package/lib/module/modules/timetable/services/timetableService.js +11 -0
  94. package/lib/module/package.json +1 -0
  95. package/lib/module/shared/empty-states/EmptyState.js +40 -0
  96. package/lib/module/shared/empty-states/ErrorState.js +40 -0
  97. package/lib/module/shared/loaders/LoadingState.js +20 -0
  98. package/lib/module/shared/theme/theme.js +18 -0
  99. package/lib/typescript/core/api/apiClient.d.ts +14 -0
  100. package/lib/typescript/core/api/endpoints.d.ts +164 -0
  101. package/lib/typescript/core/api/interceptor.d.ts +4 -0
  102. package/lib/typescript/core/auth/authContext.d.ts +11 -0
  103. package/lib/typescript/core/auth/authService.d.ts +9 -0
  104. package/lib/typescript/core/hooks/useApiQuery.d.ts +7 -0
  105. package/lib/typescript/core/provider/ERPProvider.d.ts +14 -0
  106. package/lib/typescript/core/provider/types.d.ts +34 -0
  107. package/lib/typescript/core/provider/useERP.d.ts +3 -0
  108. package/lib/typescript/core/types/api.d.ts +11 -0
  109. package/lib/typescript/index.d.ts +18 -0
  110. package/lib/typescript/modules/assignment/hooks/useAssignmentList.d.ts +3 -0
  111. package/lib/typescript/modules/assignment/hooks/useHomeworkDetails.d.ts +4 -0
  112. package/lib/typescript/modules/assignment/hooks/useHomeworkSubmissions.d.ts +4 -0
  113. package/lib/typescript/modules/assignment/screens/AssignmentScreen.d.ts +9 -0
  114. package/lib/typescript/modules/assignment/services/assignmentService.d.ts +89 -0
  115. package/lib/typescript/modules/attendance/hooks/useAttendance.d.ts +3 -0
  116. package/lib/typescript/modules/attendance/screens/AttendanceScreen.d.ts +5 -0
  117. package/lib/typescript/modules/attendance/services/attendanceService.d.ts +33 -0
  118. package/lib/typescript/modules/leaveRequest/hooks/useLeaveRequests.d.ts +3 -0
  119. package/lib/typescript/modules/leaveRequest/screens/LeaveRequestScreen.d.ts +5 -0
  120. package/lib/typescript/modules/leaveRequest/services/leaveRequestService.d.ts +39 -0
  121. package/lib/typescript/modules/marks/hooks/useMarks.d.ts +2 -0
  122. package/lib/typescript/modules/marks/screens/MarksScreen.d.ts +6 -0
  123. package/lib/typescript/modules/marks/services/marksService.d.ts +150 -0
  124. package/lib/typescript/modules/myAttendance/hooks/useMyAttendance.d.ts +3 -0
  125. package/lib/typescript/modules/myAttendance/screens/MyAttendanceScreen.d.ts +5 -0
  126. package/lib/typescript/modules/myAttendance/services/myAttendanceService.d.ts +10 -0
  127. package/lib/typescript/modules/notes/hooks/useNotes.d.ts +3 -0
  128. package/lib/typescript/modules/notes/screens/NotesScreen.d.ts +8 -0
  129. package/lib/typescript/modules/notes/services/notesService.d.ts +58 -0
  130. package/lib/typescript/modules/noticeboard/hooks/useNoticeboard.d.ts +3 -0
  131. package/lib/typescript/modules/noticeboard/screens/NoticeBoardScreen.d.ts +5 -0
  132. package/lib/typescript/modules/noticeboard/services/noticeboardService.d.ts +17 -0
  133. package/lib/typescript/modules/notification/hooks/useNotifications.d.ts +3 -0
  134. package/lib/typescript/modules/notification/screens/NotificationScreen.d.ts +5 -0
  135. package/lib/typescript/modules/notification/services/notificationService.d.ts +8 -0
  136. package/lib/typescript/modules/promoteStudent/hooks/usePromoteStudent.d.ts +3 -0
  137. package/lib/typescript/modules/promoteStudent/screens/PromoteStudentScreen.d.ts +5 -0
  138. package/lib/typescript/modules/promoteStudent/services/promoteStudentService.d.ts +40 -0
  139. package/lib/typescript/modules/timetable/hooks/useTimeTable.d.ts +3 -0
  140. package/lib/typescript/modules/timetable/screens/TimeTableScreen.d.ts +5 -0
  141. package/lib/typescript/modules/timetable/services/timetableService.d.ts +14 -0
  142. package/lib/typescript/shared/empty-states/EmptyState.d.ts +6 -0
  143. package/lib/typescript/shared/empty-states/ErrorState.d.ts +6 -0
  144. package/lib/typescript/shared/loaders/LoadingState.d.ts +3 -0
  145. package/lib/typescript/shared/theme/theme.d.ts +17 -0
  146. package/package.json +89 -0
@@ -0,0 +1,1621 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.MarksScreen = MarksScreen;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _reactNative = require("react-native");
9
+ var _useERP = require("../../../core/provider/useERP");
10
+ var _EmptyState = require("../../../shared/empty-states/EmptyState");
11
+ var _LoadingState = require("../../../shared/loaders/LoadingState");
12
+ var _marksService = require("../services/marksService");
13
+ var _jsxRuntime = require("react/jsx-runtime");
14
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
15
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
16
+ const REMARK_OPTIONS = ['Good in studies. Needs to put in a little more effort in oral work.', 'Needs to work hard for better marks. Needs practice in both writing and oral work', 'Has shown considerable improvement b needs to pay more attention to conversation skills.', 'Needs systematic and regular follow up at home with regard to studies.', 'Can do better with some help at home. Oral work needs brushing up', 'promising child who needs to put in a little more effort', 'Has the potential to do very well but needs more focused attention.', 'Good in studies. Can be excellent with a little extra care.', 'Has shown good improvement. Has the potential to do even better.', 'Extra care can bring improvement in performance. All round improvement required.', 'Has not yet become familiar with the school atmosphere. No amount of coaxing can make him write.', 'Has performed below ability. Needs special care, time and encouragement to do better.', 'Has not yet become familiar with the school atmosphere. No amount of coaxing can make him write.', 'Needs to be more patient with written work. More practice in conversation is also required.', 'Has shown no improvement. Parents are requested to give special care at home.', 'Finishes the given work but is very talkative and disturbing in class.', 'Handwriting needs to improve. Proper guidance at home can bring good results.', 'Weak in studies. Does not respond in class. Needs to work much harder in order to get promotion.', 'An average child who can improve with a little more care and attention at home.', 'Inattentive in class. Does not follow class room instructions. Needs to pay attention to his studies.', 'Others'];
17
+ function normalizeList(result) {
18
+ if (Array.isArray(result)) {
19
+ return result;
20
+ }
21
+ if (Array.isArray(result?.data)) {
22
+ return result.data;
23
+ }
24
+ if (Array.isArray(result?.data?.data)) {
25
+ return result.data.data;
26
+ }
27
+ return [];
28
+ }
29
+ function normalizeOptions(result) {
30
+ const list = normalizeList(result);
31
+ return list.map((item, index) => ({
32
+ label: String(item?.label ?? item?.type ?? item?.title ?? item?.skill ?? item?.name ?? `Option ${index + 1}`),
33
+ value: item?.value ?? item?.id ?? item?.mark_to ?? index + 1,
34
+ parent: item?.parent,
35
+ raw: item
36
+ }));
37
+ }
38
+ function normalizeGradeOptions(list) {
39
+ return list.map((item, index) => ({
40
+ label: String(item?.label ?? item?.title ?? item?.mark_to ?? item?.value ?? `Grade ${index + 1}`),
41
+ value: String(item?.value ?? item?.mark_to ?? item?.id ?? ''),
42
+ raw: item
43
+ }));
44
+ }
45
+ function matchesValue(a, b) {
46
+ return String(a ?? '') === String(b ?? '');
47
+ }
48
+ function findOption(options, value) {
49
+ return options.find(item => matchesValue(item.value, value)) ?? null;
50
+ }
51
+ function hasOverLimit(value, fullMarks) {
52
+ const parsed = Number(value ?? '');
53
+ const max = Number(fullMarks ?? '');
54
+ if (!Number.isFinite(parsed) || !Number.isFinite(max)) {
55
+ return false;
56
+ }
57
+ return parsed > max;
58
+ }
59
+ function buildRemarkForm(student) {
60
+ const existingRemark = String(student?.exam_remarks ?? '');
61
+ const predefined = REMARK_OPTIONS.find(item => item === existingRemark) ?? '';
62
+ return {
63
+ selectedRemark: predefined || (existingRemark ? 'Others' : ''),
64
+ remarks: predefined ? predefined : existingRemark,
65
+ metting_date_1: String(student?.metting_date_1 ?? ''),
66
+ attended_1: String(student?.attended_1 ?? ''),
67
+ metting_date_2: String(student?.metting_date_2 ?? ''),
68
+ attended_2: String(student?.attended_2 ?? ''),
69
+ metting_date_3: String(student?.metting_date_3 ?? ''),
70
+ attended_3: String(student?.attended_3 ?? ''),
71
+ working_days: String(student?.working_days ?? ''),
72
+ days_present: String(student?.days_present ?? '')
73
+ };
74
+ }
75
+ function SelectField({
76
+ label,
77
+ value,
78
+ options,
79
+ placeholder,
80
+ onChange
81
+ }) {
82
+ const [open, setOpen] = (0, _react.useState)(false);
83
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
84
+ style: styles.field,
85
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
86
+ style: styles.label,
87
+ children: label
88
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
89
+ onPress: () => setOpen(true),
90
+ style: styles.select,
91
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
92
+ style: styles.selectText,
93
+ children: value?.label ?? placeholder
94
+ })
95
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Modal, {
96
+ visible: open,
97
+ transparent: true,
98
+ animationType: "fade",
99
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
100
+ style: styles.modalOverlay,
101
+ onPress: () => setOpen(false),
102
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Pressable, {
103
+ style: styles.modalCard,
104
+ onPress: () => {},
105
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
106
+ style: styles.modalTitle,
107
+ children: label
108
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.FlatList, {
109
+ data: options,
110
+ keyExtractor: (item, index) => `${item.value}-${index}`,
111
+ renderItem: ({
112
+ item
113
+ }) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
114
+ style: styles.optionRow,
115
+ onPress: () => {
116
+ onChange(item);
117
+ setOpen(false);
118
+ },
119
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
120
+ style: styles.optionText,
121
+ children: item.label
122
+ })
123
+ }),
124
+ ListEmptyComponent: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
125
+ style: styles.optionEmpty,
126
+ children: "No options"
127
+ })
128
+ })]
129
+ })
130
+ })
131
+ })]
132
+ });
133
+ }
134
+ function FlowTab({
135
+ title,
136
+ active,
137
+ onPress
138
+ }) {
139
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
140
+ onPress: onPress,
141
+ style: [styles.tabBtn, active ? styles.tabBtnActive : null],
142
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
143
+ style: [styles.tabBtnText, active ? styles.tabBtnTextActive : null],
144
+ children: title
145
+ })
146
+ });
147
+ }
148
+ function StatusToggle({
149
+ label,
150
+ value,
151
+ onValueChange
152
+ }) {
153
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
154
+ style: styles.toggleLine,
155
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
156
+ style: styles.toggleText,
157
+ children: label
158
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Switch, {
159
+ value: value,
160
+ onValueChange: onValueChange
161
+ })]
162
+ });
163
+ }
164
+ function MarksInput({
165
+ label,
166
+ value,
167
+ fullMarks,
168
+ absent,
169
+ useSelect,
170
+ onTextChange,
171
+ onPick,
172
+ onAbsentChange
173
+ }) {
174
+ const overLimit = hasOverLimit(value, fullMarks);
175
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
176
+ style: styles.markField,
177
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
178
+ style: styles.markHeader,
179
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
180
+ style: styles.markLabel,
181
+ children: label
182
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
183
+ style: styles.markMax,
184
+ children: ["Max: ", String(fullMarks ?? '-')]
185
+ })]
186
+ }), useSelect ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
187
+ style: [styles.markSelectBtn, absent ? styles.disabledInput : null],
188
+ onPress: onPick,
189
+ disabled: absent,
190
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
191
+ style: styles.markSelectText,
192
+ children: value || 'Select Grade'
193
+ })
194
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
195
+ value: value,
196
+ onChangeText: onTextChange,
197
+ placeholder: "Enter marks",
198
+ placeholderTextColor: "#9CA3AF",
199
+ keyboardType: "numeric",
200
+ editable: !absent,
201
+ style: [styles.input, absent ? styles.disabledInput : null, overLimit ? styles.errorBorder : null]
202
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(StatusToggle, {
203
+ label: "Absent",
204
+ value: absent,
205
+ onValueChange: onAbsentChange
206
+ }), overLimit ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
207
+ style: styles.errorText,
208
+ children: "Marks exceed max marks"
209
+ }) : null]
210
+ });
211
+ }
212
+ function MarksScreen(props) {
213
+ const {
214
+ api
215
+ } = (0, _useERP.useERP)();
216
+ const sessionId = props.sessionId;
217
+ const [flow, setFlow] = (0, _react.useState)('scholastic');
218
+ const [entryMode, setEntryMode] = (0, _react.useState)('filters');
219
+ const [classes, setClasses] = (0, _react.useState)([]);
220
+ const [sections, setSections] = (0, _react.useState)([]);
221
+ const [exams, setExams] = (0, _react.useState)([]);
222
+ const [subjects, setSubjects] = (0, _react.useState)([]);
223
+ const [selectedClass, setSelectedClass] = (0, _react.useState)(null);
224
+ const [selectedSection, setSelectedSection] = (0, _react.useState)(null);
225
+ const [selectedExam, setSelectedExam] = (0, _react.useState)(null);
226
+ const [selectedSubject, setSelectedSubject] = (0, _react.useState)(null);
227
+ const [loadingFilters, setLoadingFilters] = (0, _react.useState)(true);
228
+ const [busy, setBusy] = (0, _react.useState)(false);
229
+ const [gradeModal, setGradeModal] = (0, _react.useState)({
230
+ visible: false,
231
+ title: '',
232
+ options: []
233
+ });
234
+ const [scholasticStudents, setScholasticStudents] = (0, _react.useState)([]);
235
+ const [scholasticExam, setScholasticExam] = (0, _react.useState)(null);
236
+ const [scholasticGrades, setScholasticGrades] = (0, _react.useState)([]);
237
+ const [coStudents, setCoStudents] = (0, _react.useState)([]);
238
+ const [coAreas, setCoAreas] = (0, _react.useState)([]);
239
+ const [coGrades, setCoGrades] = (0, _react.useState)([]);
240
+ const [coFormData, setCoFormData] = (0, _react.useState)([]);
241
+ const [remarkStudents, setRemarkStudents] = (0, _react.useState)([]);
242
+ const [remarkModalVisible, setRemarkModalVisible] = (0, _react.useState)(false);
243
+ const [selectedRemarkStudent, setSelectedRemarkStudent] = (0, _react.useState)(null);
244
+ const [remarkForm, setRemarkForm] = (0, _react.useState)({
245
+ selectedRemark: '',
246
+ remarks: '',
247
+ metting_date_1: '',
248
+ attended_1: '',
249
+ metting_date_2: '',
250
+ attended_2: '',
251
+ metting_date_3: '',
252
+ attended_3: '',
253
+ working_days: '',
254
+ days_present: ''
255
+ });
256
+ const resetFilters = (0, _react.useCallback)(() => {
257
+ setSections([]);
258
+ setExams([]);
259
+ setSubjects([]);
260
+ setSelectedClass(null);
261
+ setSelectedSection(null);
262
+ setSelectedExam(null);
263
+ setSelectedSubject(null);
264
+ setEntryMode('filters');
265
+ setScholasticStudents([]);
266
+ setScholasticExam(null);
267
+ setScholasticGrades([]);
268
+ setCoStudents([]);
269
+ setCoAreas([]);
270
+ setCoGrades([]);
271
+ setCoFormData([]);
272
+ setRemarkStudents([]);
273
+ }, []);
274
+ (0, _react.useEffect)(() => {
275
+ resetFilters();
276
+ setLoadingFilters(true);
277
+ const load = async () => {
278
+ try {
279
+ const res = flow === 'remarks' ? await (0, _marksService.fetchClassTeacherClasses)(api) : await (0, _marksService.fetchMarksClasses)(api);
280
+ setClasses(normalizeOptions(res));
281
+ } catch (error) {
282
+ _reactNative.Alert.alert('Error', String(error?.message ?? 'Could not load classes'));
283
+ } finally {
284
+ setLoadingFilters(false);
285
+ }
286
+ };
287
+ load().catch(() => {});
288
+ }, [api, flow, resetFilters]);
289
+ (0, _react.useEffect)(() => {
290
+ if (!selectedClass?.value) {
291
+ setSections([]);
292
+ setExams([]);
293
+ setSubjects([]);
294
+ setSelectedSection(null);
295
+ setSelectedExam(null);
296
+ setSelectedSubject(null);
297
+ return;
298
+ }
299
+ (0, _marksService.fetchMarksSections)(api, {
300
+ classId: selectedClass.value
301
+ }).then(res => {
302
+ setSections(normalizeOptions(res));
303
+ }).catch(error => {
304
+ _reactNative.Alert.alert('Error', String(error?.message ?? 'Could not load sections'));
305
+ });
306
+ if (sessionId === undefined) {
307
+ setExams([]);
308
+ return;
309
+ }
310
+ (0, _marksService.fetchExamDropdown)(api, {
311
+ sessionId,
312
+ classId: selectedClass.value
313
+ }).then(res => {
314
+ setExams(normalizeOptions(res));
315
+ }).catch(error => {
316
+ _reactNative.Alert.alert('Error', String(error?.message ?? 'Could not load exams'));
317
+ });
318
+ }, [api, selectedClass?.value, sessionId]);
319
+ (0, _react.useEffect)(() => {
320
+ setSubjects([]);
321
+ setSelectedSubject(null);
322
+ if (!selectedClass?.value || !selectedExam?.value || sessionId === undefined) {
323
+ return;
324
+ }
325
+ if (flow === 'scholastic') {
326
+ if (!selectedSection?.value) {
327
+ return;
328
+ }
329
+ const args = {
330
+ sessionId,
331
+ classId: selectedClass.value,
332
+ sectionId: selectedSection.value,
333
+ examId: selectedExam.value
334
+ };
335
+ (0, _marksService.fetchTeacherSubjectsForExam)(api, args).then(res => {
336
+ const normalized = normalizeOptions(res);
337
+ const list = normalized.flatMap(item => {
338
+ const raw = item.raw;
339
+ if (Array.isArray(raw?.options)) {
340
+ return raw.options.map((opt, index) => ({
341
+ label: String(opt?.label ?? `Subject ${index + 1}`),
342
+ value: opt?.value ?? opt?.id ?? index + 1,
343
+ raw: opt
344
+ }));
345
+ }
346
+ return [item];
347
+ });
348
+ setSubjects(list);
349
+ }).catch(error => {
350
+ _reactNative.Alert.alert('Error', String(error?.message ?? 'Could not load subjects'));
351
+ });
352
+ return;
353
+ }
354
+ if (flow === 'coscholastic') {
355
+ (0, _marksService.fetchCoScholasticCategories)(api, {
356
+ sessionId,
357
+ classId: selectedClass.value,
358
+ examId: selectedExam.value
359
+ }).then(res => {
360
+ setSubjects(normalizeOptions(res));
361
+ }).catch(error => {
362
+ _reactNative.Alert.alert('Error', String(error?.message ?? 'Could not load categories'));
363
+ });
364
+ }
365
+ }, [api, flow, selectedClass?.value, selectedExam?.value, selectedSection?.value, sessionId]);
366
+ const openGradePicker = (0, _react.useCallback)((title, options, onSelect) => {
367
+ setGradeModal({
368
+ visible: true,
369
+ title,
370
+ options,
371
+ onSelect
372
+ });
373
+ }, []);
374
+ const closeGradePicker = (0, _react.useCallback)(() => {
375
+ setGradeModal({
376
+ visible: false,
377
+ title: '',
378
+ options: [],
379
+ onSelect: undefined
380
+ });
381
+ }, []);
382
+ const handleScholasticMarkChange = (0, _react.useCallback)((studentId, subject, value, assessmentIndex) => {
383
+ setScholasticStudents(prev => prev.map(student => {
384
+ if (!matchesValue(student.id, studentId)) {
385
+ return student;
386
+ }
387
+ if (subject !== 'assessment') {
388
+ return {
389
+ ...student,
390
+ [subject]: value
391
+ };
392
+ }
393
+ const currentMarks = [...(student.assement_marks ?? [])];
394
+ const assessmentId = scholasticExam?.assesment_type?.[assessmentIndex ?? 0]?.id;
395
+ const existingIndex = currentMarks.findIndex(mark => matchesValue(mark?.assement_id, assessmentId));
396
+ if (existingIndex >= 0) {
397
+ currentMarks[existingIndex] = {
398
+ ...currentMarks[existingIndex],
399
+ marks: value
400
+ };
401
+ } else {
402
+ currentMarks.push({
403
+ assement_id: assessmentId,
404
+ marks: value,
405
+ is_absent: false
406
+ });
407
+ }
408
+ return {
409
+ ...student,
410
+ assement_marks: currentMarks
411
+ };
412
+ }));
413
+ }, [scholasticExam?.assesment_type]);
414
+ const handleScholasticAbsentChange = (0, _react.useCallback)((studentId, type, isAbsent, index) => {
415
+ setScholasticStudents(prev => prev.map(student => {
416
+ if (!matchesValue(student.id, studentId)) {
417
+ return student;
418
+ }
419
+ if (type === 'theory') {
420
+ return {
421
+ ...student,
422
+ theory_absent: isAbsent
423
+ };
424
+ }
425
+ if (type === 'practical') {
426
+ return {
427
+ ...student,
428
+ practical_absent: isAbsent
429
+ };
430
+ }
431
+ const currentMarks = [...(student.assement_marks ?? [])];
432
+ const assessmentId = scholasticExam?.assesment_type?.[index ?? 0]?.id;
433
+ const existingIndex = currentMarks.findIndex(mark => matchesValue(mark?.assement_id, assessmentId));
434
+ if (existingIndex >= 0) {
435
+ currentMarks[existingIndex] = {
436
+ ...currentMarks[existingIndex],
437
+ is_absent: isAbsent
438
+ };
439
+ } else {
440
+ currentMarks.push({
441
+ assement_id: assessmentId,
442
+ marks: '',
443
+ is_absent: isAbsent
444
+ });
445
+ }
446
+ return {
447
+ ...student,
448
+ assement_marks: currentMarks
449
+ };
450
+ }));
451
+ }, [scholasticExam?.assesment_type]);
452
+ const loadScholasticEntry = (0, _react.useCallback)(async () => {
453
+ if (!selectedClass?.value || !selectedSection?.value || !selectedExam?.value || !selectedSubject?.value) {
454
+ _reactNative.Alert.alert('Error', 'Please provide class, section, exam, and subject');
455
+ return;
456
+ }
457
+ setBusy(true);
458
+ try {
459
+ const res = await (0, _marksService.fetchScholasticEntry)(api, {
460
+ classId: selectedClass.value,
461
+ sectionId: selectedSection.value,
462
+ examId: selectedExam.value,
463
+ subjectId: selectedSubject.value
464
+ });
465
+ const response = res;
466
+ if (response?.Status && response.Status !== 'Success') {
467
+ _reactNative.Alert.alert('Failed', String(response?.msg ?? response?.Message ?? 'Could not load marks'));
468
+ return;
469
+ }
470
+ const exam = response?.exam_details?.[0] ?? response?.data?.exam_details?.[0] ?? null;
471
+ const rawStudents = normalizeList(response?.data ?? response);
472
+ const initialized = rawStudents.map(student => ({
473
+ ...student,
474
+ theory_absent: student?.main_subject_marks === 'AB' || student?.main_subject_marks === '-1',
475
+ practical_absent: student?.practical_subject_marks === 'AB' || student?.practical_subject_marks === '-1',
476
+ assement_marks: (student?.assement_marks ?? []).map(mark => ({
477
+ ...mark,
478
+ is_absent: String(mark?.status ?? '').toLowerCase() === 'absent' || mark?.marks === 'AB' || mark?.marks === '-1'
479
+ }))
480
+ }));
481
+ setScholasticStudents(initialized);
482
+ setScholasticExam(exam);
483
+ setScholasticGrades(normalizeGradeOptions(response?.exam_grade ?? []));
484
+ setEntryMode('scholastic');
485
+ } catch (error) {
486
+ _reactNative.Alert.alert('Error', String(error?.message ?? 'Could not load marks entry'));
487
+ } finally {
488
+ setBusy(false);
489
+ }
490
+ }, [api, selectedClass?.value, selectedExam?.value, selectedSection?.value, selectedSubject?.value]);
491
+ const loadCoScholasticEntry = (0, _react.useCallback)(async () => {
492
+ if (!selectedClass?.value || !selectedSection?.value || !selectedExam?.value || !selectedSubject?.value) {
493
+ _reactNative.Alert.alert('Error', 'Please provide class, section, exam, and category');
494
+ return;
495
+ }
496
+ setBusy(true);
497
+ try {
498
+ const [gradesRes, entryRes] = await Promise.all([(0, _marksService.fetchCoScholasticGrades)(api), (0, _marksService.fetchCoScholasticEntry)(api, {
499
+ classId: selectedClass.value,
500
+ sectionId: selectedSection.value,
501
+ examId: selectedExam.value,
502
+ categoryId: selectedSubject.value
503
+ })]);
504
+ const entryResponse = entryRes;
505
+ if (entryResponse?.Status && entryResponse.Status !== 'Success') {
506
+ _reactNative.Alert.alert('Failed', String(entryResponse?.msg ?? entryResponse?.Message ?? 'Could not load co-scholastic entry'));
507
+ return;
508
+ }
509
+ const students = normalizeList(entryResponse?.data ?? entryResponse);
510
+ const areas = entryResponse?.exam_details ?? entryResponse?.data?.exam_details ?? [];
511
+ const formData = students.map(student => {
512
+ const row = {
513
+ studentid: student.id
514
+ };
515
+ areas.forEach(area => {
516
+ const existing = (student.marks_data ?? []).find(mark => matchesValue(mark?.fk_co_scholasticarea_id, area.id));
517
+ row[String(area.id ?? '')] = existing && !matchesValue(existing.marks_grade_id, '0') ? String(existing.marks_grade_id) : '0';
518
+ });
519
+ return row;
520
+ });
521
+ setCoGrades(normalizeOptions(gradesRes));
522
+ setCoStudents(students);
523
+ setCoAreas(areas);
524
+ setCoFormData(formData);
525
+ setEntryMode('coscholastic');
526
+ } catch (error) {
527
+ _reactNative.Alert.alert('Error', String(error?.message ?? 'Could not load co-scholastic entry'));
528
+ } finally {
529
+ setBusy(false);
530
+ }
531
+ }, [api, selectedClass?.value, selectedExam?.value, selectedSection?.value, selectedSubject?.value]);
532
+ const loadRemarksEntry = (0, _react.useCallback)(async () => {
533
+ if (!selectedClass?.value || !selectedSection?.value || !selectedExam?.value) {
534
+ _reactNative.Alert.alert('Error', 'Please provide class, section, and exam');
535
+ return;
536
+ }
537
+ setBusy(true);
538
+ try {
539
+ const res = await (0, _marksService.fetchStudentRemarks)(api, {
540
+ classId: selectedClass.value,
541
+ sectionId: selectedSection.value,
542
+ examId: selectedExam.value
543
+ });
544
+ const response = res;
545
+ if (response?.Status && response.Status !== 'Success') {
546
+ _reactNative.Alert.alert('Failed', String(response?.msg ?? response?.Message ?? 'Could not load remarks'));
547
+ return;
548
+ }
549
+ setRemarkStudents(normalizeList(response));
550
+ setEntryMode('remarks');
551
+ } catch (error) {
552
+ _reactNative.Alert.alert('Error', String(error?.message ?? 'Could not load remarks entry'));
553
+ } finally {
554
+ setBusy(false);
555
+ }
556
+ }, [api, selectedClass?.value, selectedExam?.value, selectedSection?.value]);
557
+ const startEntry = (0, _react.useCallback)(() => {
558
+ if (sessionId === undefined) {
559
+ _reactNative.Alert.alert('Error', 'Pass sessionId to MarksScreen');
560
+ return;
561
+ }
562
+ if (flow === 'scholastic') {
563
+ loadScholasticEntry().catch(() => {});
564
+ return;
565
+ }
566
+ if (flow === 'coscholastic') {
567
+ loadCoScholasticEntry().catch(() => {});
568
+ return;
569
+ }
570
+ loadRemarksEntry().catch(() => {});
571
+ }, [flow, loadCoScholasticEntry, loadRemarksEntry, loadScholasticEntry, sessionId]);
572
+ const submitScholastic = (0, _react.useCallback)(async () => {
573
+ if (!selectedClass?.value || !selectedSection?.value || !selectedExam?.value || !selectedSubject?.value || !scholasticExam) {
574
+ _reactNative.Alert.alert('Error', 'Missing scholastic filters');
575
+ return;
576
+ }
577
+ setBusy(true);
578
+ try {
579
+ const data = scholasticStudents.map(student => {
580
+ const row = {
581
+ student_id: student.id,
582
+ attendance_status: scholasticExam?.is_theory === 'yes' && student?.theory_absent ? 'Absent' : 'Present'
583
+ };
584
+ if (scholasticExam?.is_theory === 'yes') {
585
+ row.main_marks = student?.theory_absent ? 'AB' : student.main_subject_marks || '0';
586
+ }
587
+ if (scholasticExam?.is_practical === 'yes') {
588
+ row.practical_marks = student?.practical_absent ? 'AB' : student.practical_subject_marks || '0';
589
+ }
590
+ if (Array.isArray(scholasticExam?.assesment_type) && scholasticExam.assesment_type.length) {
591
+ row.assesment_coloum = scholasticExam.assesment_type.map((assessment, index) => {
592
+ const currentMark = (student.assement_marks ?? []).find(mark => matchesValue(mark?.assement_id, assessment.id));
593
+ if (currentMark?.is_absent) {
594
+ return {
595
+ assement_id: assessment.id ?? index,
596
+ marks: 'AB',
597
+ status: 'Absent'
598
+ };
599
+ }
600
+ return {
601
+ assement_id: assessment.id ?? index,
602
+ marks: currentMark?.marks || '0',
603
+ status: 'Present'
604
+ };
605
+ });
606
+ }
607
+ return row;
608
+ });
609
+ const payload = {
610
+ exam_id: selectedExam.value,
611
+ subject_id: selectedSubject.value,
612
+ class_id: selectedClass.value,
613
+ section_id: selectedSection.value,
614
+ exam_schedule_id: scholasticExam?.id,
615
+ Isassessment: scholasticExam?.Isassessment,
616
+ assesment_type_id: scholasticExam?.template_details?.assessment_type === 'Exam_wise' ? scholasticExam?.assesment_type?.[0]?.fk_assesment_id : scholasticExam?.assesment_type?.[0]?.assesment_type_id,
617
+ assessment_type: scholasticExam?.template_details?.assessment_type,
618
+ isFinalExam: false,
619
+ data
620
+ };
621
+ const res = await (0, _marksService.submitExamMarks)(api, payload);
622
+ const response = res;
623
+ if (response?.Status && response.Status !== 'Success') {
624
+ _reactNative.Alert.alert('Failed', String(response?.msg ?? response?.Message ?? 'Marks submission failed'));
625
+ return;
626
+ }
627
+ _reactNative.Alert.alert('Success', 'Marks submitted successfully');
628
+ } catch (error) {
629
+ _reactNative.Alert.alert('Error', String(error?.message ?? 'Failed to submit marks'));
630
+ } finally {
631
+ setBusy(false);
632
+ }
633
+ }, [api, scholasticExam, scholasticStudents, selectedClass?.value, selectedExam?.value, selectedSection?.value, selectedSubject?.value]);
634
+ const submitCoScholastic = (0, _react.useCallback)(async () => {
635
+ if (!selectedClass?.value || !selectedSection?.value || !selectedExam?.value || !selectedSubject?.value) {
636
+ _reactNative.Alert.alert('Error', 'Missing co-scholastic filters');
637
+ return;
638
+ }
639
+ setBusy(true);
640
+ try {
641
+ const res = await (0, _marksService.submitCoScholasticMarks)(api, {
642
+ formData: coFormData,
643
+ examdetails: {
644
+ class_id: selectedClass.value,
645
+ section_id: selectedSection.value,
646
+ exam_id: selectedExam.value,
647
+ subject_id: selectedSubject.value,
648
+ parentVal: selectedExam?.parent
649
+ }
650
+ });
651
+ const response = res;
652
+ if (response?.Status && response.Status !== 'Success') {
653
+ _reactNative.Alert.alert('Failed', String(response?.msg ?? response?.Message ?? 'Marks submission failed'));
654
+ return;
655
+ }
656
+ _reactNative.Alert.alert('Success', 'Marks submitted successfully');
657
+ } catch (error) {
658
+ _reactNative.Alert.alert('Error', String(error?.message ?? 'Failed to submit co-scholastic marks'));
659
+ } finally {
660
+ setBusy(false);
661
+ }
662
+ }, [api, coFormData, selectedClass?.value, selectedExam?.parent, selectedExam?.value, selectedSection?.value, selectedSubject?.value]);
663
+ const openRemarksEditor = (0, _react.useCallback)(student => {
664
+ setSelectedRemarkStudent(student);
665
+ setRemarkForm(buildRemarkForm(student));
666
+ setRemarkModalVisible(true);
667
+ }, []);
668
+ const saveRemarks = (0, _react.useCallback)(async () => {
669
+ if (!selectedRemarkStudent?.student_id && !selectedRemarkStudent?.id) {
670
+ _reactNative.Alert.alert('Error', 'Student is missing');
671
+ return;
672
+ }
673
+ if (!selectedExam?.value) {
674
+ _reactNative.Alert.alert('Error', 'Exam is missing');
675
+ return;
676
+ }
677
+ const payload = {
678
+ studentId: selectedRemarkStudent.student_id ?? selectedRemarkStudent.id,
679
+ examId: selectedExam.value,
680
+ exam_remarks: remarkForm.remarks,
681
+ metting_date_1: remarkForm.metting_date_1,
682
+ attended_1: remarkForm.attended_1,
683
+ metting_date_2: remarkForm.metting_date_2,
684
+ attended_2: remarkForm.attended_2,
685
+ metting_date_3: remarkForm.metting_date_3,
686
+ attended_3: remarkForm.attended_3,
687
+ working_days: remarkForm.working_days,
688
+ days_present: remarkForm.days_present
689
+ };
690
+ setBusy(true);
691
+ try {
692
+ const res = await (0, _marksService.submitExamRemark)(api, payload);
693
+ const response = res;
694
+ if (response?.Status && response.Status !== 'Success') {
695
+ _reactNative.Alert.alert('Failed', String(response?.msg ?? response?.Message ?? 'Could not save remarks'));
696
+ return;
697
+ }
698
+ _reactNative.Alert.alert('Success', 'Remarks saved successfully');
699
+ setRemarkModalVisible(false);
700
+ setSelectedRemarkStudent(null);
701
+ await loadRemarksEntry();
702
+ } catch (error) {
703
+ _reactNative.Alert.alert('Error', String(error?.message ?? 'Could not save remarks'));
704
+ } finally {
705
+ setBusy(false);
706
+ }
707
+ }, [api, loadRemarksEntry, remarkForm, selectedExam?.value, selectedRemarkStudent]);
708
+ const selectedFlowLabel = (0, _react.useMemo)(() => {
709
+ if (flow === 'scholastic') return 'Marks';
710
+ if (flow === 'coscholastic') return 'Co-Scholastic';
711
+ return 'Exam Remarks';
712
+ }, [flow]);
713
+ if (loadingFilters) {
714
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_LoadingState.LoadingState, {});
715
+ }
716
+ const renderFilters = () => {
717
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
718
+ contentContainerStyle: styles.content,
719
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
720
+ style: styles.card,
721
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
722
+ style: styles.cardTitle,
723
+ children: selectedFlowLabel
724
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
725
+ style: styles.tabRow,
726
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(FlowTab, {
727
+ title: "Marks",
728
+ active: flow === 'scholastic',
729
+ onPress: () => setFlow('scholastic')
730
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(FlowTab, {
731
+ title: "Co-Scholastic",
732
+ active: flow === 'coscholastic',
733
+ onPress: () => setFlow('coscholastic')
734
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(FlowTab, {
735
+ title: "Exam Remarks",
736
+ active: flow === 'remarks',
737
+ onPress: () => setFlow('remarks')
738
+ })]
739
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(SelectField, {
740
+ label: "Class",
741
+ value: selectedClass,
742
+ options: classes,
743
+ placeholder: "Select class",
744
+ onChange: next => {
745
+ setSelectedClass(next);
746
+ setSelectedSection(null);
747
+ setSelectedExam(null);
748
+ setSelectedSubject(null);
749
+ setSections([]);
750
+ setExams([]);
751
+ setSubjects([]);
752
+ }
753
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(SelectField, {
754
+ label: "Section",
755
+ value: selectedSection,
756
+ options: sections,
757
+ placeholder: "Select section",
758
+ onChange: next => {
759
+ setSelectedSection(next);
760
+ setSelectedSubject(null);
761
+ }
762
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(SelectField, {
763
+ label: "Exam",
764
+ value: selectedExam,
765
+ options: exams,
766
+ placeholder: "Select exam",
767
+ onChange: next => {
768
+ setSelectedExam(next);
769
+ setSelectedSubject(null);
770
+ }
771
+ }), flow !== 'remarks' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(SelectField, {
772
+ label: flow === 'scholastic' ? 'Subject' : 'Category',
773
+ value: selectedSubject,
774
+ options: subjects,
775
+ placeholder: flow === 'scholastic' ? 'Select subject' : 'Select category',
776
+ onChange: setSelectedSubject
777
+ }) : null, sessionId === undefined ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
778
+ style: styles.helperText,
779
+ children: "Pass `sessionId` to `MarksScreen` to load exams and marks entry."
780
+ }) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
781
+ onPress: startEntry,
782
+ style: styles.primaryBtn,
783
+ disabled: busy,
784
+ children: busy ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
785
+ color: "#FFFFFF"
786
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
787
+ style: styles.primaryBtnText,
788
+ children: flow === 'remarks' ? 'Open Remarks' : 'Open Entry'
789
+ })
790
+ })]
791
+ })
792
+ });
793
+ };
794
+ const renderScholasticEntry = () => {
795
+ if (!scholasticExam) {
796
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_EmptyState.EmptyState, {
797
+ title: "No Data Found"
798
+ });
799
+ }
800
+ const isAdditional = scholasticExam?.subject_type === 'Additional';
801
+ const isMinorMarks = scholasticExam?.template_details?.minor_sub_marks_type === 'MARKS';
802
+ const useGradeForSubject = isAdditional && !isMinorMarks;
803
+ const useGradeForAssessment = scholasticExam?.assessment_type === 'only_assessment';
804
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.FlatList, {
805
+ data: scholasticStudents,
806
+ keyExtractor: (item, index) => String(item?.id ?? index),
807
+ contentContainerStyle: styles.content,
808
+ ListHeaderComponent: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
809
+ style: styles.card,
810
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
811
+ style: styles.cardTitle,
812
+ children: "Scholastic Entry"
813
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
814
+ style: styles.infoRow,
815
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
816
+ style: styles.infoText,
817
+ children: ["Class: ", selectedClass?.label]
818
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
819
+ style: styles.infoText,
820
+ children: ["Section: ", selectedSection?.label]
821
+ })]
822
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
823
+ style: styles.infoRow,
824
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
825
+ style: styles.infoText,
826
+ children: ["Exam: ", selectedExam?.label]
827
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
828
+ style: styles.infoText,
829
+ children: ["Subject: ", selectedSubject?.label]
830
+ })]
831
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
832
+ style: styles.actionRow,
833
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
834
+ onPress: () => setEntryMode('filters'),
835
+ style: styles.secondaryBtn,
836
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
837
+ style: styles.secondaryBtnText,
838
+ children: "Back"
839
+ })
840
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
841
+ onPress: submitScholastic,
842
+ style: styles.primaryBtnCompact,
843
+ children: busy ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
844
+ color: "#FFFFFF"
845
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
846
+ style: styles.primaryBtnText,
847
+ children: "Submit Marks"
848
+ })
849
+ })]
850
+ })]
851
+ }),
852
+ renderItem: ({
853
+ item
854
+ }) => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
855
+ style: styles.studentCard,
856
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
857
+ style: styles.studentHeader,
858
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
859
+ style: styles.studentName,
860
+ children: [String(item?.firstname ?? ''), " ", String(item?.lastname ?? '')]
861
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
862
+ style: styles.rollText,
863
+ children: ["Roll No: ", String(item?.roll_no ?? '-')]
864
+ })]
865
+ }), scholasticExam?.is_theory === 'yes' && scholasticExam?.assessment_type !== 'only_assessment' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(MarksInput, {
866
+ label: "Theory",
867
+ value: String(item?.main_subject_marks ?? ''),
868
+ fullMarks: scholasticExam?.full_marks,
869
+ absent: Boolean(item?.theory_absent),
870
+ useSelect: useGradeForSubject,
871
+ onTextChange: value => handleScholasticMarkChange(item.id, 'main_subject_marks', value),
872
+ onPick: () => openGradePicker('Select Theory Grade', scholasticGrades, value => handleScholasticMarkChange(item.id, 'main_subject_marks', value)),
873
+ onAbsentChange: value => handleScholasticAbsentChange(item.id, 'theory', value)
874
+ }) : null, scholasticExam?.is_practical === 'yes' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(MarksInput, {
875
+ label: "Practical",
876
+ value: String(item?.practical_subject_marks ?? ''),
877
+ fullMarks: scholasticExam?.practical_full_marks,
878
+ absent: Boolean(item?.practical_absent),
879
+ useSelect: useGradeForSubject,
880
+ onTextChange: value => handleScholasticMarkChange(item.id, 'practical_subject_marks', value),
881
+ onPick: () => openGradePicker('Select Practical Grade', scholasticGrades, value => handleScholasticMarkChange(item.id, 'practical_subject_marks', value)),
882
+ onAbsentChange: value => handleScholasticAbsentChange(item.id, 'practical', value)
883
+ }) : null, scholasticExam?.subject_type !== 'Additional' ? scholasticExam?.assesment_type?.map((assessment, index) => {
884
+ const currentMark = (item.assement_marks ?? []).find(mark => matchesValue(mark?.assement_id, assessment.id));
885
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(MarksInput, {
886
+ label: String(assessment?.title ?? `Assessment ${index + 1}`),
887
+ value: String(currentMark?.marks ?? ''),
888
+ fullMarks: assessment?.max_marks,
889
+ absent: Boolean(currentMark?.is_absent),
890
+ useSelect: useGradeForAssessment,
891
+ onTextChange: value => handleScholasticMarkChange(item.id, 'assessment', value, index),
892
+ onPick: () => openGradePicker(`Select ${String(assessment?.title ?? 'Assessment')} Grade`, scholasticGrades, value => handleScholasticMarkChange(item.id, 'assessment', value, index)),
893
+ onAbsentChange: value => handleScholasticAbsentChange(item.id, 'assessment', value, index)
894
+ }, `${item.id}-${assessment.id ?? index}`);
895
+ }) : null]
896
+ }),
897
+ ListEmptyComponent: /*#__PURE__*/(0, _jsxRuntime.jsx)(_EmptyState.EmptyState, {
898
+ title: "No students found"
899
+ })
900
+ });
901
+ };
902
+ const renderCoScholasticEntry = () => {
903
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.FlatList, {
904
+ data: coStudents,
905
+ keyExtractor: (item, index) => String(item?.id ?? index),
906
+ contentContainerStyle: styles.content,
907
+ ListHeaderComponent: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
908
+ style: styles.card,
909
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
910
+ style: styles.cardTitle,
911
+ children: "Co-Scholastic Entry"
912
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
913
+ style: styles.infoRow,
914
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
915
+ style: styles.infoText,
916
+ children: ["Class: ", selectedClass?.label]
917
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
918
+ style: styles.infoText,
919
+ children: ["Section: ", selectedSection?.label]
920
+ })]
921
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
922
+ style: styles.infoRow,
923
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
924
+ style: styles.infoText,
925
+ children: ["Exam: ", selectedExam?.label]
926
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
927
+ style: styles.infoText,
928
+ children: ["Category: ", selectedSubject?.label]
929
+ })]
930
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
931
+ style: styles.actionRow,
932
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
933
+ onPress: () => setEntryMode('filters'),
934
+ style: styles.secondaryBtn,
935
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
936
+ style: styles.secondaryBtnText,
937
+ children: "Back"
938
+ })
939
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
940
+ onPress: submitCoScholastic,
941
+ style: styles.primaryBtnCompact,
942
+ children: busy ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
943
+ color: "#FFFFFF"
944
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
945
+ style: styles.primaryBtnText,
946
+ children: "Submit Marks"
947
+ })
948
+ })]
949
+ })]
950
+ }),
951
+ renderItem: ({
952
+ item
953
+ }) => {
954
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
955
+ style: styles.studentCard,
956
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
957
+ style: styles.studentHeader,
958
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
959
+ style: styles.studentName,
960
+ children: [String(item?.firstname ?? ''), " ", String(item?.lastname ?? '')]
961
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
962
+ style: styles.rollText,
963
+ children: ["Roll No: ", String(item?.roll_no ?? '-')]
964
+ })]
965
+ }), Array.from({
966
+ length: Math.ceil(coAreas.length / 3)
967
+ }, (_, rowIndex) => {
968
+ const rowItems = coAreas.slice(rowIndex * 3, rowIndex * 3 + 3);
969
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
970
+ style: styles.criteriaRow,
971
+ children: rowItems.map(area => {
972
+ const row = coFormData.find(form => matchesValue(form.studentid, item.id));
973
+ const currentValue = String(row?.[String(area.id ?? '')] ?? '0');
974
+ const currentGrade = findOption(coGrades, currentValue)?.label ?? 'Select Grade';
975
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
976
+ style: styles.criteriaCol,
977
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
978
+ style: styles.criteriaLabel,
979
+ children: String(area?.skill ?? '-')
980
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
981
+ style: styles.markSelectBtn,
982
+ onPress: () => openGradePicker(`Select Grade for ${String(area?.skill ?? '')}`, coGrades, value => setCoFormData(prev => prev.map(form => matchesValue(form.studentid, item.id) ? {
983
+ ...form,
984
+ [String(area.id ?? '')]: value
985
+ } : form))),
986
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
987
+ style: styles.markSelectText,
988
+ children: currentGrade
989
+ })
990
+ })]
991
+ }, String(area.id ?? ''));
992
+ })
993
+ }, rowIndex);
994
+ })]
995
+ });
996
+ },
997
+ ListEmptyComponent: /*#__PURE__*/(0, _jsxRuntime.jsx)(_EmptyState.EmptyState, {
998
+ title: "No students found"
999
+ })
1000
+ });
1001
+ };
1002
+ const renderRemarksEntry = () => {
1003
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.FlatList, {
1004
+ data: remarkStudents,
1005
+ keyExtractor: (item, index) => String(item?.student_id ?? item?.id ?? index),
1006
+ contentContainerStyle: styles.content,
1007
+ ListHeaderComponent: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
1008
+ style: styles.card,
1009
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
1010
+ style: styles.cardTitle,
1011
+ children: "Exam Remarks"
1012
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
1013
+ style: styles.infoRow,
1014
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
1015
+ style: styles.infoText,
1016
+ children: ["Class: ", selectedClass?.label]
1017
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
1018
+ style: styles.infoText,
1019
+ children: ["Section: ", selectedSection?.label]
1020
+ })]
1021
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
1022
+ style: styles.infoRow,
1023
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
1024
+ style: styles.infoText,
1025
+ children: ["Exam: ", selectedExam?.label]
1026
+ })
1027
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
1028
+ onPress: () => setEntryMode('filters'),
1029
+ style: styles.secondaryBtn,
1030
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
1031
+ style: styles.secondaryBtnText,
1032
+ children: "Back"
1033
+ })
1034
+ })]
1035
+ }),
1036
+ renderItem: ({
1037
+ item
1038
+ }) => {
1039
+ const hasRemarks = String(item?.exam_remarks ?? '').trim().length > 0;
1040
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
1041
+ style: [styles.studentCard, hasRemarks ? styles.successBorder : styles.errorBorderLeft],
1042
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
1043
+ style: styles.remarkTopRow,
1044
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
1045
+ style: {
1046
+ flex: 1
1047
+ },
1048
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
1049
+ style: styles.studentName,
1050
+ children: [String(item?.firstname ?? ''), " ", String(item?.lastname ?? '')]
1051
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
1052
+ style: styles.rollText,
1053
+ children: ["Roll No: ", String(item?.roll_no ?? '-')]
1054
+ }), hasRemarks ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
1055
+ style: styles.remarkText,
1056
+ children: ["Remarks: ", String(item?.exam_remarks ?? '')]
1057
+ }) : null]
1058
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
1059
+ style: styles.primaryBtnSmall,
1060
+ onPress: () => openRemarksEditor(item),
1061
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
1062
+ style: styles.primaryBtnSmallText,
1063
+ children: "Add Remarks"
1064
+ })
1065
+ })]
1066
+ })
1067
+ });
1068
+ },
1069
+ ListEmptyComponent: /*#__PURE__*/(0, _jsxRuntime.jsx)(_EmptyState.EmptyState, {
1070
+ title: "No students found"
1071
+ })
1072
+ });
1073
+ };
1074
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.SafeAreaView, {
1075
+ style: styles.root,
1076
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
1077
+ style: styles.screenHeader,
1078
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
1079
+ style: styles.screenTitle,
1080
+ children: "Marks"
1081
+ })
1082
+ }), entryMode === 'filters' ? renderFilters() : null, entryMode === 'scholastic' ? renderScholasticEntry() : null, entryMode === 'coscholastic' ? renderCoScholasticEntry() : null, entryMode === 'remarks' ? renderRemarksEntry() : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Modal, {
1083
+ visible: gradeModal.visible,
1084
+ transparent: true,
1085
+ animationType: "fade",
1086
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
1087
+ style: styles.modalOverlay,
1088
+ onPress: closeGradePicker,
1089
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Pressable, {
1090
+ style: styles.modalCard,
1091
+ onPress: () => {},
1092
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
1093
+ style: styles.modalTitle,
1094
+ children: gradeModal.title
1095
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.FlatList, {
1096
+ data: gradeModal.options,
1097
+ keyExtractor: (item, index) => `${item.value}-${index}`,
1098
+ renderItem: ({
1099
+ item
1100
+ }) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
1101
+ style: styles.optionRow,
1102
+ onPress: () => {
1103
+ gradeModal.onSelect?.(String(item.value));
1104
+ closeGradePicker();
1105
+ },
1106
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
1107
+ style: styles.optionText,
1108
+ children: item.label
1109
+ })
1110
+ })
1111
+ })]
1112
+ })
1113
+ })
1114
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Modal, {
1115
+ visible: remarkModalVisible,
1116
+ transparent: true,
1117
+ animationType: "slide",
1118
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
1119
+ style: styles.modalOverlay,
1120
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
1121
+ style: styles.remarkModalCard,
1122
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
1123
+ style: styles.remarkHeader,
1124
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
1125
+ style: styles.modalTitle,
1126
+ children: "Remarks and Others"
1127
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
1128
+ onPress: () => {
1129
+ setRemarkModalVisible(false);
1130
+ setSelectedRemarkStudent(null);
1131
+ },
1132
+ style: styles.secondaryBtn,
1133
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
1134
+ style: styles.secondaryBtnText,
1135
+ children: "Close"
1136
+ })
1137
+ })]
1138
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.ScrollView, {
1139
+ showsVerticalScrollIndicator: false,
1140
+ children: [selectedRemarkStudent ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
1141
+ style: styles.field,
1142
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
1143
+ style: styles.studentName,
1144
+ children: [String(selectedRemarkStudent?.firstname ?? ''), ' ', String(selectedRemarkStudent?.lastname ?? '')]
1145
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
1146
+ style: styles.rollText,
1147
+ children: ["Roll No: ", String(selectedRemarkStudent?.roll_no ?? '-')]
1148
+ })]
1149
+ }) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(SelectField, {
1150
+ label: "Remark",
1151
+ value: remarkForm.selectedRemark ? {
1152
+ label: remarkForm.selectedRemark,
1153
+ value: remarkForm.selectedRemark
1154
+ } : null,
1155
+ options: REMARK_OPTIONS.map(item => ({
1156
+ label: item,
1157
+ value: item
1158
+ })),
1159
+ placeholder: "Select a remark",
1160
+ onChange: next => {
1161
+ const selected = String(next.value);
1162
+ setRemarkForm(prev => ({
1163
+ ...prev,
1164
+ selectedRemark: selected,
1165
+ remarks: selected === 'Others' ? '' : selected
1166
+ }));
1167
+ }
1168
+ }), remarkForm.selectedRemark === 'Others' ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
1169
+ style: styles.field,
1170
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
1171
+ style: styles.label,
1172
+ children: "Custom Remark"
1173
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
1174
+ value: remarkForm.remarks,
1175
+ onChangeText: value => setRemarkForm(prev => ({
1176
+ ...prev,
1177
+ remarks: value
1178
+ })),
1179
+ placeholder: "Enter custom remark",
1180
+ placeholderTextColor: "#9CA3AF",
1181
+ multiline: true,
1182
+ style: [styles.input, styles.textarea]
1183
+ })]
1184
+ }) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
1185
+ style: styles.sectionTitle,
1186
+ children: "Meeting Dates"
1187
+ }), [['metting_date_1', 'attended_1'], ['metting_date_2', 'attended_2'], ['metting_date_3', 'attended_3']].map((pair, index) => {
1188
+ const dateKey = pair[0];
1189
+ const attendedKey = pair[1];
1190
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
1191
+ style: styles.doubleRow,
1192
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
1193
+ style: styles.doubleCol,
1194
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
1195
+ style: styles.label,
1196
+ children: ["Date ", index + 1]
1197
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
1198
+ value: remarkForm[dateKey],
1199
+ onChangeText: value => setRemarkForm(prev => ({
1200
+ ...prev,
1201
+ [dateKey]: value
1202
+ })),
1203
+ placeholder: "Date",
1204
+ placeholderTextColor: "#9CA3AF",
1205
+ style: styles.input
1206
+ })]
1207
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
1208
+ style: styles.doubleCol,
1209
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
1210
+ style: styles.label,
1211
+ children: ["Attended ", index + 1]
1212
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
1213
+ value: remarkForm[attendedKey],
1214
+ onChangeText: value => setRemarkForm(prev => ({
1215
+ ...prev,
1216
+ [attendedKey]: value
1217
+ })),
1218
+ placeholder: "Attended",
1219
+ placeholderTextColor: "#9CA3AF",
1220
+ style: styles.input
1221
+ })]
1222
+ })]
1223
+ }, String(dateKey));
1224
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
1225
+ style: styles.sectionTitle,
1226
+ children: "Attendance Detailed"
1227
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
1228
+ style: styles.doubleRow,
1229
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
1230
+ style: styles.doubleCol,
1231
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
1232
+ style: styles.label,
1233
+ children: "Total Working Days"
1234
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
1235
+ value: remarkForm.working_days,
1236
+ onChangeText: value => setRemarkForm(prev => ({
1237
+ ...prev,
1238
+ working_days: value
1239
+ })),
1240
+ placeholder: "Total working days",
1241
+ placeholderTextColor: "#9CA3AF",
1242
+ keyboardType: "numeric",
1243
+ style: styles.input
1244
+ })]
1245
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
1246
+ style: styles.doubleCol,
1247
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
1248
+ style: styles.label,
1249
+ children: "Days Present"
1250
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
1251
+ value: remarkForm.days_present,
1252
+ onChangeText: value => setRemarkForm(prev => ({
1253
+ ...prev,
1254
+ days_present: value
1255
+ })),
1256
+ placeholder: "Number of days present",
1257
+ placeholderTextColor: "#9CA3AF",
1258
+ keyboardType: "numeric",
1259
+ style: styles.input
1260
+ })]
1261
+ })]
1262
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
1263
+ onPress: saveRemarks,
1264
+ style: styles.primaryBtn,
1265
+ children: busy ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
1266
+ color: "#FFFFFF"
1267
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
1268
+ style: styles.primaryBtnText,
1269
+ children: "Save"
1270
+ })
1271
+ })]
1272
+ })]
1273
+ })
1274
+ })
1275
+ })]
1276
+ });
1277
+ }
1278
+ const styles = _reactNative.StyleSheet.create({
1279
+ root: {
1280
+ flex: 1,
1281
+ backgroundColor: '#F8FAFC'
1282
+ },
1283
+ screenHeader: {
1284
+ paddingHorizontal: 16,
1285
+ paddingVertical: 14,
1286
+ borderBottomWidth: 1,
1287
+ borderBottomColor: '#E5E7EB',
1288
+ backgroundColor: '#FFFFFF'
1289
+ },
1290
+ screenTitle: {
1291
+ fontSize: 18,
1292
+ fontWeight: '700',
1293
+ color: '#111827'
1294
+ },
1295
+ content: {
1296
+ padding: 16,
1297
+ gap: 12
1298
+ },
1299
+ card: {
1300
+ backgroundColor: '#FFFFFF',
1301
+ borderWidth: 1,
1302
+ borderColor: '#E5E7EB',
1303
+ borderRadius: 16,
1304
+ padding: 16
1305
+ },
1306
+ cardTitle: {
1307
+ fontSize: 17,
1308
+ fontWeight: '700',
1309
+ color: '#111827',
1310
+ marginBottom: 12
1311
+ },
1312
+ field: {
1313
+ marginTop: 10,
1314
+ gap: 6
1315
+ },
1316
+ label: {
1317
+ fontSize: 12,
1318
+ fontWeight: '600',
1319
+ color: '#6B7280'
1320
+ },
1321
+ select: {
1322
+ borderWidth: 1,
1323
+ borderColor: '#E5E7EB',
1324
+ borderRadius: 12,
1325
+ paddingHorizontal: 12,
1326
+ paddingVertical: 12,
1327
+ backgroundColor: '#FFFFFF'
1328
+ },
1329
+ selectText: {
1330
+ fontSize: 14,
1331
+ color: '#111827'
1332
+ },
1333
+ helperText: {
1334
+ marginTop: 10,
1335
+ fontSize: 12,
1336
+ color: '#6B7280'
1337
+ },
1338
+ tabRow: {
1339
+ flexDirection: 'row',
1340
+ gap: 8,
1341
+ flexWrap: 'wrap',
1342
+ marginBottom: 8
1343
+ },
1344
+ tabBtn: {
1345
+ flexGrow: 1,
1346
+ minWidth: '30%',
1347
+ borderWidth: 1,
1348
+ borderColor: '#CBD5E1',
1349
+ borderRadius: 999,
1350
+ paddingVertical: 10,
1351
+ paddingHorizontal: 12,
1352
+ alignItems: 'center',
1353
+ backgroundColor: '#FFFFFF'
1354
+ },
1355
+ tabBtnActive: {
1356
+ backgroundColor: '#2563EB',
1357
+ borderColor: '#2563EB'
1358
+ },
1359
+ tabBtnText: {
1360
+ fontSize: 12,
1361
+ fontWeight: '700',
1362
+ color: '#111827'
1363
+ },
1364
+ tabBtnTextActive: {
1365
+ color: '#FFFFFF'
1366
+ },
1367
+ primaryBtn: {
1368
+ marginTop: 16,
1369
+ backgroundColor: '#2563EB',
1370
+ borderRadius: 12,
1371
+ paddingVertical: 14,
1372
+ alignItems: 'center',
1373
+ justifyContent: 'center'
1374
+ },
1375
+ primaryBtnCompact: {
1376
+ flex: 1,
1377
+ backgroundColor: '#2563EB',
1378
+ borderRadius: 12,
1379
+ paddingVertical: 14,
1380
+ alignItems: 'center',
1381
+ justifyContent: 'center'
1382
+ },
1383
+ primaryBtnText: {
1384
+ color: '#FFFFFF',
1385
+ fontSize: 14,
1386
+ fontWeight: '700'
1387
+ },
1388
+ secondaryBtn: {
1389
+ minWidth: 88,
1390
+ paddingVertical: 12,
1391
+ paddingHorizontal: 16,
1392
+ borderRadius: 12,
1393
+ backgroundColor: '#E5E7EB',
1394
+ alignItems: 'center',
1395
+ justifyContent: 'center'
1396
+ },
1397
+ secondaryBtnText: {
1398
+ color: '#111827',
1399
+ fontSize: 14,
1400
+ fontWeight: '700'
1401
+ },
1402
+ actionRow: {
1403
+ marginTop: 12,
1404
+ flexDirection: 'row',
1405
+ gap: 10
1406
+ },
1407
+ infoRow: {
1408
+ flexDirection: 'row',
1409
+ justifyContent: 'space-between',
1410
+ gap: 8,
1411
+ marginTop: 6
1412
+ },
1413
+ infoText: {
1414
+ fontSize: 12,
1415
+ color: '#4B5563',
1416
+ flex: 1
1417
+ },
1418
+ studentCard: {
1419
+ backgroundColor: '#FFFFFF',
1420
+ borderWidth: 1,
1421
+ borderColor: '#E5E7EB',
1422
+ borderRadius: 16,
1423
+ padding: 16,
1424
+ marginBottom: 12
1425
+ },
1426
+ studentHeader: {
1427
+ paddingBottom: 12,
1428
+ marginBottom: 12,
1429
+ borderBottomWidth: 1,
1430
+ borderBottomColor: '#E5E7EB'
1431
+ },
1432
+ studentName: {
1433
+ fontSize: 16,
1434
+ fontWeight: '700',
1435
+ color: '#111827'
1436
+ },
1437
+ rollText: {
1438
+ marginTop: 4,
1439
+ fontSize: 13,
1440
+ color: '#6B7280'
1441
+ },
1442
+ markField: {
1443
+ marginTop: 10,
1444
+ padding: 12,
1445
+ borderWidth: 1,
1446
+ borderColor: '#E5E7EB',
1447
+ borderRadius: 12,
1448
+ backgroundColor: '#F9FAFB'
1449
+ },
1450
+ markHeader: {
1451
+ flexDirection: 'row',
1452
+ justifyContent: 'space-between',
1453
+ marginBottom: 8,
1454
+ gap: 8
1455
+ },
1456
+ markLabel: {
1457
+ fontSize: 13,
1458
+ fontWeight: '700',
1459
+ color: '#111827',
1460
+ flex: 1
1461
+ },
1462
+ markMax: {
1463
+ fontSize: 12,
1464
+ color: '#6B7280'
1465
+ },
1466
+ input: {
1467
+ borderWidth: 1,
1468
+ borderColor: '#D1D5DB',
1469
+ borderRadius: 10,
1470
+ paddingHorizontal: 12,
1471
+ paddingVertical: 10,
1472
+ backgroundColor: '#FFFFFF',
1473
+ color: '#111827'
1474
+ },
1475
+ textarea: {
1476
+ minHeight: 90,
1477
+ textAlignVertical: 'top'
1478
+ },
1479
+ markSelectBtn: {
1480
+ borderWidth: 1,
1481
+ borderColor: '#D1D5DB',
1482
+ borderRadius: 10,
1483
+ paddingHorizontal: 12,
1484
+ paddingVertical: 12,
1485
+ backgroundColor: '#FFFFFF'
1486
+ },
1487
+ markSelectText: {
1488
+ fontSize: 14,
1489
+ color: '#111827'
1490
+ },
1491
+ disabledInput: {
1492
+ opacity: 0.55
1493
+ },
1494
+ toggleLine: {
1495
+ marginTop: 10,
1496
+ flexDirection: 'row',
1497
+ alignItems: 'center',
1498
+ justifyContent: 'space-between'
1499
+ },
1500
+ toggleText: {
1501
+ fontSize: 12,
1502
+ color: '#4B5563',
1503
+ fontWeight: '600'
1504
+ },
1505
+ errorText: {
1506
+ marginTop: 6,
1507
+ fontSize: 12,
1508
+ color: '#DC2626'
1509
+ },
1510
+ errorBorder: {
1511
+ borderColor: '#DC2626'
1512
+ },
1513
+ criteriaRow: {
1514
+ flexDirection: 'row',
1515
+ gap: 8,
1516
+ marginTop: 10
1517
+ },
1518
+ criteriaCol: {
1519
+ flex: 1
1520
+ },
1521
+ criteriaLabel: {
1522
+ minHeight: 36,
1523
+ fontSize: 12,
1524
+ fontWeight: '700',
1525
+ color: '#2563EB',
1526
+ textAlign: 'center',
1527
+ marginBottom: 6
1528
+ },
1529
+ primaryBtnSmall: {
1530
+ paddingHorizontal: 12,
1531
+ paddingVertical: 10,
1532
+ borderRadius: 10,
1533
+ backgroundColor: '#2563EB',
1534
+ alignItems: 'center',
1535
+ justifyContent: 'center'
1536
+ },
1537
+ primaryBtnSmallText: {
1538
+ color: '#FFFFFF',
1539
+ fontSize: 12,
1540
+ fontWeight: '700'
1541
+ },
1542
+ remarkTopRow: {
1543
+ flexDirection: 'row',
1544
+ alignItems: 'center',
1545
+ gap: 12
1546
+ },
1547
+ remarkText: {
1548
+ marginTop: 8,
1549
+ fontSize: 12,
1550
+ color: '#16A34A'
1551
+ },
1552
+ successBorder: {
1553
+ borderLeftWidth: 4,
1554
+ borderLeftColor: '#16A34A'
1555
+ },
1556
+ errorBorderLeft: {
1557
+ borderLeftWidth: 4,
1558
+ borderLeftColor: '#DC2626'
1559
+ },
1560
+ modalOverlay: {
1561
+ flex: 1,
1562
+ backgroundColor: 'rgba(0,0,0,0.45)',
1563
+ justifyContent: 'center',
1564
+ padding: 16
1565
+ },
1566
+ modalCard: {
1567
+ backgroundColor: '#FFFFFF',
1568
+ borderRadius: 16,
1569
+ maxHeight: '80%',
1570
+ overflow: 'hidden'
1571
+ },
1572
+ modalTitle: {
1573
+ paddingHorizontal: 16,
1574
+ paddingTop: 16,
1575
+ paddingBottom: 8,
1576
+ fontSize: 16,
1577
+ fontWeight: '700',
1578
+ color: '#111827'
1579
+ },
1580
+ optionRow: {
1581
+ paddingHorizontal: 16,
1582
+ paddingVertical: 12,
1583
+ borderTopWidth: 1,
1584
+ borderTopColor: '#F3F4F6'
1585
+ },
1586
+ optionText: {
1587
+ fontSize: 14,
1588
+ color: '#111827'
1589
+ },
1590
+ optionEmpty: {
1591
+ paddingHorizontal: 16,
1592
+ paddingVertical: 12,
1593
+ color: '#6B7280'
1594
+ },
1595
+ remarkModalCard: {
1596
+ backgroundColor: '#FFFFFF',
1597
+ borderRadius: 16,
1598
+ maxHeight: '88%',
1599
+ padding: 16
1600
+ },
1601
+ remarkHeader: {
1602
+ flexDirection: 'row',
1603
+ justifyContent: 'space-between',
1604
+ alignItems: 'center',
1605
+ marginBottom: 8
1606
+ },
1607
+ sectionTitle: {
1608
+ marginTop: 16,
1609
+ fontSize: 15,
1610
+ fontWeight: '700',
1611
+ color: '#111827'
1612
+ },
1613
+ doubleRow: {
1614
+ flexDirection: 'row',
1615
+ gap: 10,
1616
+ marginTop: 10
1617
+ },
1618
+ doubleCol: {
1619
+ flex: 1
1620
+ }
1621
+ });