Assessment intial commit

This commit is contained in:
Menaka 2024-08-23 11:27:41 +05:30
parent 3b4afdcef2
commit eb2f78248c
25 changed files with 2161 additions and 30 deletions

View File

@ -28,6 +28,16 @@ allprojects {
force "com.facebook.react:react-native:" + REACT_NATIVE_VERSION
}
}
repositories {
// * Your other repositories here *
// * Add a new maven block after other repositories / blocks *
maven {
// expo-camera bundles a custom com.google.android:cameraview
url "$rootDir/../node_modules/expo-camera/android/maven"
}
}
// ...
}

View File

@ -2,6 +2,7 @@ rootProject.name = 'TedQu'
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
include ':app'
includeBuild('../node_modules/@react-native/gradle-plugin')
include ':expo-modules-core'
include ':react-native-vector-icons'
project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')

60
package-lock.json generated
View File

@ -34,7 +34,7 @@
"crypto-ts": "^1.0.2",
"deprecated-react-native-prop-types": "^5.0.0",
"expo": "^50.0.7",
"expo-camera": "^15.0.14",
"expo-camera": "^14.1.3",
"expo-constants": "~15.4.6",
"expo-file-system": "~16.0.9",
"expo-firebase-analytics": "^8.0.0",
@ -58,8 +58,10 @@
"react-native-calendars": "^1.1303.0",
"react-native-chart-kit": "^6.12.0",
"react-native-charts-wrapper": "^0.6.0",
"react-native-document-scanner-plugin": "^0.9.1",
"react-native-document-scanner-plugin": "^1.0.0",
"react-native-fetch-polyfill": "^1.1.3",
"react-native-flash-message": "^0.4.2",
"react-native-fs": "^2.20.0",
"react-native-gesture-handler": "^2.15.0",
"react-native-get-random-values": "~1.9.0",
"react-native-gifted-charts": "^1.4.16",
@ -91,6 +93,7 @@
"redux-persist": "^6.0.0",
"redux-saga": "^1.2.3",
"victory-native": "^35.3.2",
"whatwg-fetch-timeout": "^2.0.2-timeout",
"yup": "^1.3.3"
},
"devDependencies": {
@ -8951,6 +8954,11 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"node_modules/base-64": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz",
"integrity": "sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA=="
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
@ -11485,9 +11493,9 @@
}
},
"node_modules/expo-camera": {
"version": "15.0.14",
"resolved": "https://registry.npmjs.org/expo-camera/-/expo-camera-15.0.14.tgz",
"integrity": "sha512-O4uvVywGsQ3a89d0BX4lq6mDuGYGukx1PYY4QrC9zw1yzD2W9BVTl8lanFRPC5h4PRniekfeWUVH1a0jJmkLIw==",
"version": "14.1.3",
"resolved": "https://registry.npmjs.org/expo-camera/-/expo-camera-14.1.3.tgz",
"integrity": "sha512-JodpVjOY8JDuSp/RkphS8Bxqaj/gwg0h0UbQB9MLr1LoxbL9brvJt7IZnmTf7+ON8jRKUx9E5o/F02pRNbmSbQ==",
"dependencies": {
"invariant": "^2.2.4"
},
@ -18832,9 +18840,9 @@
}
},
"node_modules/react-native-document-scanner-plugin": {
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/react-native-document-scanner-plugin/-/react-native-document-scanner-plugin-0.9.1.tgz",
"integrity": "sha512-iHqd/ZEHmKnPsA0X2DoSZ7B324WSDQO45I22busHHfc2vSRMHozP9fcIP34YTuNvfbvjJFhziCIw66YcGWLotA==",
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/react-native-document-scanner-plugin/-/react-native-document-scanner-plugin-1.0.0.tgz",
"integrity": "sha512-dDsSclFpxl4U0Bnz/oEE0OEEqEjA6zNCu/2lmls4lslq3JqgHacI8xEl5DygMHd4AlDj3X4g1yKUacllfaC+UA==",
"peerDependencies": {
"expo": ">=47.0.0",
"react": "*",
@ -18846,6 +18854,14 @@
}
}
},
"node_modules/react-native-fetch-polyfill": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/react-native-fetch-polyfill/-/react-native-fetch-polyfill-1.1.3.tgz",
"integrity": "sha512-zr5yXQftuGq+ABGa3n4ZE+vkL1lBsMSePkRINm3/6vlpbwnLXYoijwazTO/W8GjsV4LAgGmzuieZxKO/NxW19A==",
"peerDependencies": {
"react-native": ">=0.27"
}
},
"node_modules/react-native-flash-message": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/react-native-flash-message/-/react-native-flash-message-0.4.2.tgz",
@ -18860,6 +18876,24 @@
"react-native": "*"
}
},
"node_modules/react-native-fs": {
"version": "2.20.0",
"resolved": "https://registry.npmjs.org/react-native-fs/-/react-native-fs-2.20.0.tgz",
"integrity": "sha512-VkTBzs7fIDUiy/XajOSNk0XazFE9l+QlMAce7lGuebZcag5CnjszB+u4BdqzwaQOdcYb5wsJIsqq4kxInIRpJQ==",
"dependencies": {
"base-64": "^0.1.0",
"utf8": "^3.0.0"
},
"peerDependencies": {
"react-native": "*",
"react-native-windows": "*"
},
"peerDependenciesMeta": {
"react-native-windows": {
"optional": true
}
}
},
"node_modules/react-native-gesture-handler": {
"version": "2.15.0",
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.15.0.tgz",
@ -21693,6 +21727,11 @@
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/utf8": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz",
"integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ=="
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@ -22265,6 +22304,11 @@
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz",
"integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg=="
},
"node_modules/whatwg-fetch-timeout": {
"version": "2.0.2-timeout",
"resolved": "https://registry.npmjs.org/whatwg-fetch-timeout/-/whatwg-fetch-timeout-2.0.2-timeout.tgz",
"integrity": "sha512-1y8WJdP1DaBXbAp9Ez8Um2Ft7iTVopOwUgnyiJPYIsWir1HuJBBxSYdvEtskQx+r/L1WMWQQxbcS8lHubCHtBw=="
},
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",

View File

@ -36,7 +36,7 @@
"crypto-ts": "^1.0.2",
"deprecated-react-native-prop-types": "^5.0.0",
"expo": "^50.0.7",
"expo-camera": "^15.0.14",
"expo-camera": "^14.1.3",
"expo-constants": "~15.4.6",
"expo-file-system": "~16.0.9",
"expo-firebase-analytics": "^8.0.0",
@ -60,8 +60,10 @@
"react-native-calendars": "^1.1303.0",
"react-native-chart-kit": "^6.12.0",
"react-native-charts-wrapper": "^0.6.0",
"react-native-document-scanner-plugin": "^0.9.1",
"react-native-document-scanner-plugin": "^1.0.0",
"react-native-fetch-polyfill": "^1.1.3",
"react-native-flash-message": "^0.4.2",
"react-native-fs": "^2.20.0",
"react-native-gesture-handler": "^2.15.0",
"react-native-get-random-values": "~1.9.0",
"react-native-gifted-charts": "^1.4.16",
@ -93,6 +95,7 @@
"redux-persist": "^6.0.0",
"redux-saga": "^1.2.3",
"victory-native": "^35.3.2",
"whatwg-fetch-timeout": "^2.0.2-timeout",
"yup": "^1.3.3"
},
"devDependencies": {

View File

@ -2,7 +2,10 @@ import {
CREATE_CLASS_REQUEST, CREATE_CLASS_REQUEST_SUCCESS, CREATE_CLASS_REQUEST_FAILURE, GET_CLASS_DETAILS, GET_CLASS_DETAILS_SUCCESS, GET_CLASS_DETAILS_FAILURE,
GET_CLASS_PAGINATION_REQUEST, GET_CLASS_PAGINATION_REQUEST_SUCCESS, GET_CLASS_PAGINATION_REQUEST_FAILURE, UPDATE_CLASS_REQUEST, UPDATE_CLASS_REQUEST_SUCCESS,
UPDATE_CLASS_REQUEST_FAILURE, DELETE_CLASS_REQUEST, DELETE_CLASS_REQUEST_FAILURE, DELETE_CLASS_REQUEST_SUCCESS, GET_GRADE_REQUEST, GET_GRADE_REQUEST_SUCCESS,
GET_GRADE_REQUEST_FAILURE, GET_STANDARD_REQUEST, GET_STANDARD_REQUEST_FAILURE, GET_STANDARD_REQUEST_SUCCESS, INIT_CLASS_MODULE } from './type'
GET_GRADE_REQUEST_FAILURE, GET_STANDARD_REQUEST, GET_STANDARD_REQUEST_FAILURE, GET_STANDARD_REQUEST_SUCCESS, INIT_CLASS_MODULE,
GET_CLASS_GRADE_REQUEST, GET_CLASS_GRADE_REQUEST_SUCCESS, GET_CLASS_GRADE_REQUEST_FAILURE,
GET_CLASS_STANDARD_REQUEST, GET_CLASS_STANDARD_REQUEST_SUCCESS, GET_CLASS_STANDARD_REQUEST_FAILURE
} from './type'
/** Class Type Action */
export const initClassAction = () => ({
@ -114,3 +117,33 @@ export const deleteClassRequestFailure = (error: any) => ({
error
})
export const getMyClassGradesAction = (data: any) => ({
type: GET_CLASS_GRADE_REQUEST,
data
})
export const getMyClassGradesSuccess = (data: any) => ({
type: GET_CLASS_GRADE_REQUEST_SUCCESS,
data
})
export const getMyClassGradesFailure = (error: any) => ({
type: GET_CLASS_GRADE_REQUEST_FAILURE,
error
})
export const getMyClassStandardAction = (data: any) => ({
type: GET_CLASS_STANDARD_REQUEST,
data
})
export const getMyClassStandardSuccess = (data: any) => ({
type: GET_CLASS_STANDARD_REQUEST_SUCCESS,
data
})
export const getMyClassStandardFailure = (error: any) => ({
type: GET_CLASS_STANDARD_REQUEST_FAILURE,
error
})

View File

@ -13,6 +13,7 @@ import * as Attendance from './attendance.action'
import * as Quizzes from './quizzes.action'
import * as Psychometric from './psychometric.action'
import * as License from './license.action'
import * as QuestionBank from './questionbank.action'
export const ActionCreators = {
...Users,
@ -28,5 +29,6 @@ export const ActionCreators = {
...Attendance,
...Quizzes,
...Psychometric,
...License
...License,
...QuestionBank
}

View File

@ -0,0 +1,154 @@
import {
INIT_ASSESSMENT_MODULE,
GET_QUESTION_PAPER_PAGINATION_REQUEST, GET_QUESTION_PAPER_PAGINATION_SUCCESS, GET_QUESTION_PAPER_PAGINATION_FAILURE,
GET_ASSESSMENT_PAGINATION_REQUEST, GET_ASSESSMENT_PAGINATION_SUCCESS, GET_ASSESSMENT_PAGINATION_FALURE,
GET_QUESTION_PAPER_REQUEST, GET_QUESTION_PAPER_SUCCESS, GET_QUESTION_PAPER_FAILURE,
CREATE_ASSESSMENT_REQUEST, CREATE_ASSESSMENT_SUCCESS, CREATE_ASSESSMENT_FALURE,
GET_ASSESSMENT_REQUEST, GET_ASSESSMENT_SUCCESS, GET_ASSESSMENT_FALURE,
UPDATE_ASSESSMENT_REQUEST, UPDATE_ASSESSMENT_SUCCESS, UPDATE_ASSESSMENT_FALURE,
DELETE_ASSESSMENT_REQUEST, DELETE_ASSESSMENT_SUCCESS, DELETE_ASSESSMENT_FALURE,
GET_ASSESSMENT_STUDENT_LIST_REQUEST, GET_ASSESSMENT_STUDENT_LIST_SUCCESS, GET_ASSESSMENT_STUDENT_LIST_FAILURE,
CREATE_ASSESSMENT_SCAN_ANSWERS_REQUEST,CREATE_ASSESSMENT_SCAN_ANSWERS_SUCCESS, CREATE_ASSESSMENT_SCAN_ANSWERS_FALURE
} from './type'
export const initAssessmentAction = () => ({
type: INIT_ASSESSMENT_MODULE
})
export const getQuestionPaperPaginationAction = (data: any) => ({
type: GET_QUESTION_PAPER_PAGINATION_REQUEST,
data
})
export const getQuestionPaperPaginationSuccess = (data: any) => ({
type: GET_QUESTION_PAPER_PAGINATION_SUCCESS,
data
})
export const getQuestionPaperPaginationFailure = (error: any) => ({
type: GET_QUESTION_PAPER_PAGINATION_FAILURE,
error
})
export const getAssessmentPaginationAction = (data: any) => ({
type: GET_ASSESSMENT_PAGINATION_REQUEST,
data
})
export const getAssessmentPaginationSuccess = (data: any) => ({
type: GET_ASSESSMENT_PAGINATION_SUCCESS,
data
})
export const getAssessmentPaginationFailure = (error: any) => ({
type: GET_ASSESSMENT_PAGINATION_FALURE,
error
})
export const getQuestionPaperAction = (data: any) => ({
type: GET_QUESTION_PAPER_REQUEST,
data
})
export const getQuestionPaperSuccess = (data: any) => ({
type: GET_QUESTION_PAPER_SUCCESS,
data
})
export const getQuestionPaperFailure = (error: any) => ({
type: GET_QUESTION_PAPER_FAILURE,
error
})
export const createAssessmentAction = (data: any) => ({
type: CREATE_ASSESSMENT_REQUEST,
data
})
export const createAssessmentSuccess = (data: any) => ({
type: CREATE_ASSESSMENT_SUCCESS,
data
})
export const createAssessmentFailure = (error: any) => ({
type: CREATE_ASSESSMENT_FALURE,
error
})
export const getAssessmentAction = (data: any) => ({
type: GET_ASSESSMENT_REQUEST,
data
})
export const getAssessmentSuccess = (data: any) => ({
type: GET_ASSESSMENT_SUCCESS,
data
})
export const getAssessmentFailure = (error: any) => ({
type: GET_ASSESSMENT_FALURE,
error
})
export const getAssessmentStudentListAction = (data: any) => ({
type: GET_ASSESSMENT_STUDENT_LIST_REQUEST,
data
})
export const getAssessmentStudentListSuccess = (data: any) => ({
type: GET_ASSESSMENT_STUDENT_LIST_SUCCESS,
data
})
export const getAssessmentStudentListFailure = (error: any) => ({
type: GET_ASSESSMENT_STUDENT_LIST_FAILURE,
error
})
export const updateAssessmentAction = (data: any) => ({
type: UPDATE_ASSESSMENT_REQUEST,
data
})
export const updateAssessmentSuccess = (data: any) => ({
type: UPDATE_ASSESSMENT_SUCCESS,
data
})
export const updateAssessmentFailure = (error: any) => ({
type: UPDATE_ASSESSMENT_FALURE,
error
})
export const deleteAssessmentAction = (data: any) => ({
type: DELETE_ASSESSMENT_REQUEST,
data
})
export const deleteAssessmentSuccess = (data: any) => ({
type: DELETE_ASSESSMENT_SUCCESS,
data
})
export const deleteAssessmentFailure = (error: any) => ({
type: DELETE_ASSESSMENT_FALURE,
error
})
export const createAssessmentScanAnswerAction = (data: any) => ({
type: CREATE_ASSESSMENT_SCAN_ANSWERS_REQUEST,
data
})
export const createAssessmentScanAnswerSuccess = (data: any) => ({
type: CREATE_ASSESSMENT_SCAN_ANSWERS_SUCCESS,
data
})
export const createAssessmentScanAnswerFailure = (error: any) => ({
type:CREATE_ASSESSMENT_SCAN_ANSWERS_FALURE,
error
})

View File

@ -87,6 +87,12 @@ export const DELETE_CLASS_REQUEST_FAILURE = 'DELETE_CLASS_REQUEST_FAILURE'
export const GET_CLASS_PAGINATION_REQUEST = 'GET_CLASS_PAGINATION_REQUEST'
export const GET_CLASS_PAGINATION_REQUEST_SUCCESS = 'GET_CLASS_PAGINATION_REQUEST_SUCCESS'
export const GET_CLASS_PAGINATION_REQUEST_FAILURE = 'GET_CLASS_PAGINATION_REQUEST_FAILURE'
export const GET_CLASS_GRADE_REQUEST = 'GET_CLASS_GRADE_REQUEST'
export const GET_CLASS_GRADE_REQUEST_SUCCESS = 'GET_CLASS_GRADE_REQUEST_SUCCESS'
export const GET_CLASS_GRADE_REQUEST_FAILURE = 'GET_CLASS_GRADE_REQUEST_FAILURE'
export const GET_CLASS_STANDARD_REQUEST = 'GET_CLASS_STANDARD_REQUEST'
export const GET_CLASS_STANDARD_REQUEST_SUCCESS = 'GET_CLASS_STANDARD_REQUEST_SUCCESS'
export const GET_CLASS_STANDARD_REQUEST_FAILURE = 'GET_CLASS_STANDARD_REQUEST_FAILURE'
/** Teacher Type Action */
export const INIT_TEACHER_MODULE = 'INIT_TEACHER_MODULE'
@ -381,3 +387,41 @@ export const GET_LICENSE_SCHOOLS_FAILURE = 'GET_LICENSE_SCHOOLS_FAILURE'
export const GET_LICENSE_SCHOOL_DOMAIN = 'GET_LICENSE_SCHOOL_DOMAIN'
export const GET_LICENSE_SCHOOL_DOMAIN_SUCCESS = 'GET_LICENSE_SCHOOL_DOMAIN_SUCCESS'
export const GET_LICENSE_SCHOOL_DOMAIN_FAILURE = 'GET_LICENSE_SCHOOL_DOMAIN_FAILURE'
export const GET_QUESTION_PAPER_PAGINATION_REQUEST = 'GET_QUESTION_PAPER_PAGINATION_REQUEST'
export const GET_QUESTION_PAPER_PAGINATION_SUCCESS = 'GET_QUESTION_PAPER_PAGINATION_SUCCESS'
export const GET_QUESTION_PAPER_PAGINATION_FAILURE = 'GET_QUESTION_PAPER_FAILURE'
export const INIT_ASSESSMENT_MODULE = 'INIT_ASSESSMENT_MODULE'
export const GET_ASSESSMENT_PAGINATION_REQUEST = 'GET_ASSESSMENT_PAGINATION_REQUEST'
export const GET_ASSESSMENT_PAGINATION_SUCCESS = 'GET_ASSESSMENT_PAGINATION_SUCCESS'
export const GET_ASSESSMENT_PAGINATION_FALURE = 'GET_ASSESSMENT_PAGINATION_FALURE'
export const GET_QUESTION_PAPER_REQUEST = 'GET_QUESTION_PAPER_REQUEST'
export const GET_QUESTION_PAPER_SUCCESS = 'GET_QUESTION_PAPER_SUCCESS'
export const GET_QUESTION_PAPER_FAILURE = 'GET_QUESTION_PAPER_FAILURE'
export const CREATE_ASSESSMENT_REQUEST = 'CREATE_ASSESSMENT_REQUEST'
export const CREATE_ASSESSMENT_SUCCESS = 'CREATE_ASSESSMENT_SUCCESS'
export const CREATE_ASSESSMENT_FALURE = 'CREATE_ASSESSMENT_FALURE'
export const GET_ASSESSMENT_REQUEST = 'GET_ASSESSMENT_REQUEST'
export const GET_ASSESSMENT_SUCCESS = 'GET_ASSESSMENT_SUCCESS'
export const GET_ASSESSMENT_FALURE = 'GET_ASSESSMENT_FALURE'
export const UPDATE_ASSESSMENT_REQUEST = 'UPDATE_ASSESSMENT_REQUEST'
export const UPDATE_ASSESSMENT_SUCCESS = 'UPDATE_ASSESSMENT_SUCCESS'
export const UPDATE_ASSESSMENT_FALURE = 'UPDATE_ASSESSMENT_FALURE'
export const GET_ASSESSMENT_STUDENT_LIST_REQUEST = 'GET_ASSESSMENT_STUDENT_LIST_REQUEST'
export const GET_ASSESSMENT_STUDENT_LIST_SUCCESS = 'GET_ASSESSMENT_STUDENT_LIST_SUCCESS'
export const GET_ASSESSMENT_STUDENT_LIST_FAILURE = 'GET_ASSESSMENT_STUDENT_LIST_FAILURE'
export const DELETE_ASSESSMENT_REQUEST = 'DELETE_ASSESSMENT_REQUEST'
export const DELETE_ASSESSMENT_SUCCESS = 'DELETE_ASSESSMENT_SUCCESS'
export const DELETE_ASSESSMENT_FALURE = 'DELETE_ASSESSMENT_FALURE'
export const CREATE_ASSESSMENT_SCAN_ANSWERS_REQUEST = 'CREATE_ASSESSMENT_SCAN_ANSWERS_REQUEST'
export const CREATE_ASSESSMENT_SCAN_ANSWERS_SUCCESS = 'CREATE_ASSESSMENT_SCAN_ANSWERS_SUCCESS'
export const CREATE_ASSESSMENT_SCAN_ANSWERS_FALURE = 'CREATE_ASSESSMENT_SCAN_ANSWERS_FALURE'

View File

@ -72,3 +72,21 @@ export const getClassStandards = ({token}: any) => {
const url = CLASSAPI.GET_CLASS_STANDARDS
return fetchAppBase(url, requestOptions)
}
export const getMyClassGrades = ({token}: any) => {
const requestOptions = {
method: 'GET',
headers: { 'Content-Type': apiConfig.contentTypeJSON, 'Authorization': token }
}
const url = CLASSAPI.GET_MY_CLASS_GRADES
return fetchAppBase(url, requestOptions)
}
export const getMyClassStandards = ({token, grade_id}: any) => {
const requestOptions = {
method: 'GET',
headers: { 'Content-Type': apiConfig.contentTypeJSON, 'Authorization': token }
}
const url = `${CLASSAPI.GET_MY_CLASS_SECTIONS}/?grade=${grade_id}`
return fetchAppBase(url, requestOptions)
}

View File

@ -0,0 +1,94 @@
import { QUESTION_BANK_API } from '@config/Config' //NOSONAR
import { apiConfig, fetchAppBase } from '@constants/Constants' //NOSONAR
export const getAllQuestionPaper = async ({token, academic_year, page_no}: any) => {
const requestOptions = {
method: 'PATCH',
headers: { 'Content-Type': apiConfig.contentTypeJSON, 'Authorization': token },
//body: JSON.stringify(data)
}
const url = `${QUESTION_BANK_API.GET_QUESTION_BANK}/?page_no=${page_no}&search=&order_by=&sort_by=`
return fetchAppBase(url, requestOptions)
}
export const getAllAssessmentList = async ({token, academic_year, question_paper_id,page_no}: any) => {
const requestOptions = {
method: 'PATCH',
headers: { 'Content-Type': apiConfig.contentTypeJSON, 'Authorization': token },
//body: JSON.stringify(data)
}
const url = `${QUESTION_BANK_API.GET_ASSESSMENT}/?page_no=${page_no}&question_paper_id=${question_paper_id}&search=&order_by=&sort_by=`
return fetchAppBase(url, requestOptions)
}
export const getQuestionPaper = async ({token, academic_year, question_paper_id,page_no}: any) => {
console.log('getQuestionPaper')
const requestOptions = {
method: 'GET',
headers: { 'Content-Type': apiConfig.contentTypeJSON, 'Authorization': token },
}
const url = `${QUESTION_BANK_API.GET_QUESTION_PAPER}/?question_paper_id=${question_paper_id}`
console.log(url)
console.log(token)
return fetchAppBase(url, requestOptions)
}
export const createAssessment = async ({token, data}: any) => {
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': apiConfig.contentTypeJSON, 'Authorization': token },
body: JSON.stringify(data)
}
const url = `${QUESTION_BANK_API.GET_ASSESSMENT}/`
return fetchAppBase(url, requestOptions)
}
export const getAssessment = async ({token, academic_year, uid}: any) => {
const requestOptions = {
method: 'GET',
headers: { 'Content-Type': apiConfig.contentTypeJSON, 'Authorization': token },
}
const url = `${QUESTION_BANK_API.GET_ASSESSMENT}/?uid=${uid}`
return fetchAppBase(url, requestOptions)
}
export const getAssessmentStudentList = async ({token, academic_year, question_paper_id,class_id}: any) => {
const requestOptions = {
method: 'GET',
headers: { 'Content-Type': apiConfig.contentTypeJSON, 'Authorization': token },
}
console.log(token)
const url = `${QUESTION_BANK_API.VIEW_ASSESSMENT_STUDENT_LIST}/?question_paper_id=${question_paper_id}&class_id=${class_id}`
return fetchAppBase(url, requestOptions)
}
export const updateAssessment = async ({token, academic_year, uid,data}: any) => {
const requestOptions = {
method: 'PUT',
headers: { 'Content-Type': apiConfig.contentTypeJSON, 'Authorization': token },
body: JSON.stringify(data)
}
const url = `${QUESTION_BANK_API.GET_ASSESSMENT}/?uid=${uid}`
return fetchAppBase(url, requestOptions)
}
export const deleteAssessment = async ({token, academic_year, uid}: any) => {
const requestOptions = {
method: 'DELETE',
headers: { 'Content-Type': apiConfig.contentTypeJSON, 'Authorization': token },
}
const url = `${QUESTION_BANK_API.GET_ASSESSMENT}/?uid=${uid}`
return fetchAppBase(url, requestOptions)
}
export const createAssessmentScanAnswer = ({ data, token }: any) => {
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'multipart/form-data; ', 'Authorization': token },
body: data
}
console.log(data)
const url = `${QUESTION_BANK_API.ASSESSMENT_SCAN_ANSWERS}`
return fetchAppBase(url, requestOptions)
}

View File

@ -64,6 +64,12 @@ class Sidebar extends React.Component<any, any> {
icon: "ios-person",
roles: [UserRoles.schoolAdmin]
},
{
name: "Question Bank",
action: "QuestionBank",
icon: "ios-person",
roles: [UserRoles.schoolAdmin]
},
{
name: "Settings",
action: "Settings",

View File

@ -23,8 +23,10 @@ export const CLASSAPI: any = {
GET_COMMON_URL: "/classes",
GET_CLASS_GRADES: "/lovs/grade/",
// doubt
GET_CLASS_STANDARDS: "/lovs/standard/"
GET_CLASS_STANDARDS: "/lovs/standard/",
// doubt
GET_MY_CLASS_GRADES: "/classes/get-my-grades/",
GET_MY_CLASS_SECTIONS: "/classes/get-my-sections/"
}
export const SCHOOLAPI: any = {
@ -132,3 +134,11 @@ export const SCHOOL_LIST_API: any = {
GET_LICENSE_SCHOOLS: "/license_module/get-all-schools",
GET_LICENSE_SCHOOL_DOMAIN: "/license_module/get-domain-list",
}
export const QUESTION_BANK_API: any = {
GET_QUESTION_BANK: "/questionbank-module/create-question-paper",
GET_ASSESSMENT: "/questionbank-module/create-assessment",
GET_QUESTION_PAPER : "/questionbank-module/view-questions",
VIEW_ASSESSMENT_STUDENT_LIST: "/questionbank-module/view-assessment-studentlist",
ASSESSMENT_SCAN_ANSWERS:"/questionbank-module/assessment-answers/",
}

View File

@ -41,6 +41,11 @@ import ReportPsychometric from "@screens/Pscyometric/ReportPsychometric"
import { Ionicons } from '@expo/vector-icons'
import { StackActions, NavigationActions } from 'react-navigation'
import { CommonActions } from "@react-navigation/native"
import QuestionBank from "@screens/QuestionBank/QuestionBank"
import Assessment from "@screens/QuestionBank/Assessment"
import AssessmentCreate from "@screens/QuestionBank/AssessmentCreate"
import AssessmentEdit from "@screens/QuestionBank/AssessmentEdit"
import AssessmentScanner from "@screens/QuestionBank/AssessmentScanner"
const navigationOptions = ({ navigation, screenProps }: any) => ({
headerStyle: {
@ -206,6 +211,11 @@ const AppNavigator = () => {
<Stack.Screen name="QuestionListPsychometric" component={QuestionListPsychometric} options={navigationOptions}/>
<Stack.Screen name="QuestionScreen" component={QuestionScreen} options={navigationOptions}/>
<Stack.Screen name="ReportPsychometric" component={ReportPsychometric} options={navigationOptions}/>
<Stack.Screen name="QuestionBank" component={QuestionBank} options={navigationOptions}/>
<Stack.Screen name="Assessment" component={Assessment} options={navigationOptions}/>
<Stack.Screen name="AssessmentCreate" component={AssessmentCreate} options={navigationOptions}/>
<Stack.Screen name="AssessmentEdit" component={AssessmentEdit} options={navigationOptions}/>
<Stack.Screen name="AssessmentScanner" component={AssessmentScanner} options={navigationOptions}/>
</Stack.Navigator>
);
};

View File

@ -2,7 +2,8 @@ import { CREATE_CLASS_REQUEST, CREATE_CLASS_REQUEST_FAILURE, CREATE_CLASS_REQUES
GET_CLASS_DETAILS_SUCCESS, GET_CLASS_PAGINATION_REQUEST, GET_CLASS_PAGINATION_REQUEST_FAILURE, GET_CLASS_PAGINATION_REQUEST_SUCCESS, //NOSONAR
UPDATE_CLASS_REQUEST, UPDATE_CLASS_REQUEST_FAILURE, UPDATE_CLASS_REQUEST_SUCCESS, DELETE_CLASS_REQUEST, DELETE_CLASS_REQUEST_SUCCESS, //NOSONAR
DELETE_CLASS_REQUEST_FAILURE, GET_GRADE_REQUEST, GET_GRADE_REQUEST_SUCCESS, GET_GRADE_REQUEST_FAILURE, GET_STANDARD_REQUEST, GET_STANDARD_REQUEST_SUCCESS, //NOSONAR
GET_STANDARD_REQUEST_FAILURE, INIT_CLASS_MODULE } from '@actions/type' //NOSONAR
GET_STANDARD_REQUEST_FAILURE, INIT_CLASS_MODULE, GET_CLASS_GRADE_REQUEST, GET_CLASS_GRADE_REQUEST_SUCCESS, GET_CLASS_GRADE_REQUEST_FAILURE,
GET_CLASS_STANDARD_REQUEST, GET_CLASS_STANDARD_REQUEST_FAILURE, GET_CLASS_STANDARD_REQUEST_SUCCESS } from '@actions/type' //NOSONAR
import Toast from 'react-native-simple-toast'
@ -22,7 +23,9 @@ const defaultState = {
data: {},
deleted_info: {},
grade: {},
standard: {}
standard: {},
class_grade: {},
class_standard: {}
}
export const classes = (state = defaultState, action: any) => {
@ -113,6 +116,18 @@ export const classes = (state = defaultState, action: any) => {
return { ...state, loading: false, deleted_info: response }
case DELETE_CLASS_REQUEST_FAILURE:
return { ...state, loading: false, error: action.error }
case GET_CLASS_GRADE_REQUEST:
return { ...state, loading: true, class_grade: defaultObj }
case GET_CLASS_GRADE_REQUEST_SUCCESS:
return { ...state, loading: false, class_grade: response }
case GET_CLASS_GRADE_REQUEST_FAILURE:
return { ...state, loading: false, error: action.error }
case GET_CLASS_STANDARD_REQUEST:
return { ...state, loading: true, class_standard: defaultObj }
case GET_CLASS_STANDARD_REQUEST_SUCCESS:
return { ...state, loading: false, class_standard: response }
case GET_CLASS_STANDARD_REQUEST_FAILURE:
return { ...state, loading: false, error: action.error }
default:
return state
}

View File

@ -14,7 +14,7 @@ import { attendance } from './attendance.reducer'
import { quizzes } from './quizzes.reducer'
import { psychometric } from './psychometric.reducer'
import { license } from './license.reducer'
import { questionbank } from './questionbank.reducer'
const rootReducer = combineReducers({
users,
@ -22,7 +22,7 @@ const rootReducer = combineReducers({
school, classes,
teachers, teacherSubjectMap, teacherClassMap,
dashboard, noticeboard, diary,
students, instantfeedback, attendance, quizzes, psychometric, license
students, instantfeedback, attendance, quizzes, psychometric, license, questionbank
})
export default rootReducer

View File

@ -0,0 +1,105 @@
import {
INIT_ASSESSMENT_MODULE,
GET_QUESTION_PAPER_PAGINATION_REQUEST, GET_QUESTION_PAPER_PAGINATION_SUCCESS, GET_QUESTION_PAPER_PAGINATION_FAILURE,
GET_ASSESSMENT_PAGINATION_REQUEST, GET_ASSESSMENT_PAGINATION_SUCCESS, GET_ASSESSMENT_PAGINATION_FALURE,
GET_QUESTION_PAPER_REQUEST, GET_QUESTION_PAPER_SUCCESS, GET_QUESTION_PAPER_FAILURE,
CREATE_ASSESSMENT_REQUEST, CREATE_ASSESSMENT_SUCCESS, CREATE_ASSESSMENT_FALURE,
GET_ASSESSMENT_REQUEST, GET_ASSESSMENT_SUCCESS, GET_ASSESSMENT_FALURE,
UPDATE_ASSESSMENT_REQUEST, UPDATE_ASSESSMENT_SUCCESS, UPDATE_ASSESSMENT_FALURE,
DELETE_ASSESSMENT_REQUEST, DELETE_ASSESSMENT_SUCCESS, DELETE_ASSESSMENT_FALURE,
GET_ASSESSMENT_STUDENT_LIST_REQUEST, GET_ASSESSMENT_STUDENT_LIST_SUCCESS, GET_ASSESSMENT_STUDENT_LIST_FAILURE,
CREATE_ASSESSMENT_SCAN_ANSWERS_REQUEST, CREATE_ASSESSMENT_SCAN_ANSWERS_SUCCESS, CREATE_ASSESSMENT_SCAN_ANSWERS_FALURE
} from '@actions/type' //NOSONAR
import Toast from 'react-native-simple-toast'
const defaultObj: any = {}
const defaultState = {
loading: false,
menu_list: [],
license: {},
schoolList: [],
userinfo: {},
schoolDomain: [],
records: [],
list: {},
assessmentrecords: [],
assessmentlist: {},
question_details: [],
assessment_create: {},
assessment: {},
assessment_delete: {},
assessment_update: {},
assessment_student_list: {},
assessment_answer: {},
}
export const questionbank = (state = defaultState, action: any) => {
const response = action.data
switch (action.type) {
case INIT_ASSESSMENT_MODULE:
return { ...state, loading: true, license: defaultObj, assessment_create: {}, assessment_update: {}, assessment_answer: {} }
case GET_QUESTION_PAPER_PAGINATION_REQUEST:
case GET_ASSESSMENT_PAGINATION_REQUEST:
case GET_QUESTION_PAPER_REQUEST:
case CREATE_ASSESSMENT_REQUEST:
case GET_ASSESSMENT_REQUEST:
case UPDATE_ASSESSMENT_REQUEST:
case DELETE_ASSESSMENT_REQUEST:
case GET_ASSESSMENT_STUDENT_LIST_REQUEST:
case CREATE_ASSESSMENT_SCAN_ANSWERS_REQUEST:
return { ...state, loading: true, license: defaultObj, assessment_create: {} }
case GET_QUESTION_PAPER_PAGINATION_SUCCESS:
if (response.hasOwnProperty('status')) {
if (!response.status) {
Toast.show(response.message, Toast.SHORT)
}
}
const { records, page } = response.data
if (page === 1) {
state.records = []
}
return {
...state, loading: false, list: response, records: [...state.records, ...records]
}
case GET_ASSESSMENT_PAGINATION_SUCCESS:
if (response.hasOwnProperty('status')) {
if (!response.status) {
Toast.show(response.message, Toast.SHORT)
}
}
if (response.data.page === 1) {
state.assessmentrecords = []
}
return {
...state, loading: false, assessmentlist: response, assessmentrecords: [...state.assessmentrecords, ...response.data.records]
}
case GET_QUESTION_PAPER_SUCCESS:
return {
...state, loading: false, question_details: response.data.question_details
}
case CREATE_ASSESSMENT_SUCCESS:
return { ...state, loading: false, assessment_create: response }
case UPDATE_ASSESSMENT_SUCCESS:
return { ...state, loading: false, assessment_update: response }
case GET_ASSESSMENT_SUCCESS:
return { ...state, loading: false, assessment: response.data }
case GET_ASSESSMENT_STUDENT_LIST_SUCCESS:
return { ...state, loading: false, assessment_student_list: response.data }
case CREATE_ASSESSMENT_SCAN_ANSWERS_SUCCESS:
return { ...state, loading: false, assessment_answer: response }
case GET_QUESTION_PAPER_PAGINATION_FAILURE:
case GET_ASSESSMENT_PAGINATION_FALURE:
case GET_ASSESSMENT_FALURE:
return { ...state, loading: false }
case CREATE_ASSESSMENT_FALURE:
return { ...state, loading: false, assessment_create: {} }
case UPDATE_ASSESSMENT_FALURE:
return { ...state, loading: false, assessment_update: {} }
case CREATE_ASSESSMENT_SCAN_ANSWERS_FALURE:
return { ...state, loading: false, assessment_answer: {"something_wrong": "something_wrong"} }
default:
return state
}
}

View File

@ -1,7 +1,7 @@
import { takeEvery, call, put } from 'redux-saga/effects'
import { CREATE_CLASS_REQUEST, GET_CLASS_DETAILS, GET_CLASS_PAGINATION_REQUEST, UPDATE_CLASS_REQUEST, DELETE_CLASS_REQUEST, //NOSONAR
GET_GRADE_REQUEST, GET_STANDARD_REQUEST } from '@actions/type' //NOSONAR
import { createClassDetail, getAllClassDetails, getClassDetail, updateClassDetail, deleteClassDetail, getClassGrades, getClassStandards } from '@api/class.api' //NOSONAR
GET_GRADE_REQUEST, GET_STANDARD_REQUEST,GET_CLASS_GRADE_REQUEST, GET_CLASS_STANDARD_REQUEST } from '@actions/type' //NOSONAR
import { createClassDetail, getAllClassDetails, getClassDetail, updateClassDetail, deleteClassDetail, getClassGrades, getClassStandards, getMyClassGrades, getMyClassStandards } from '@api/class.api' //NOSONAR
import { ActionCreators } from '@actions' //NOSONAR
export const watchCreateClass = function* () {
@ -93,3 +93,16 @@ function* workerCreateClass(action: any) {
yield put(ActionCreators.createClassRequestFailure(e))
}
}
export const watchGetMyClassStandards = function* () {
yield takeEvery(GET_CLASS_STANDARD_REQUEST, workerGetMyClassStandards)
}
function* workerGetMyClassStandards(action: any) {
try {
const response = yield call(getMyClassStandards, action.data)
yield put(ActionCreators.getMyClassStandardSuccess(response))
} catch (e) {
yield put(ActionCreators.getMyClassStandardFailure(e))
}
}

View File

@ -5,7 +5,7 @@ import {
} from "./auth.sagas"
import { watchGetUserProfile, watchGetArTagRequest } from "./users.sagas"
import { watchGetSchool, watchGetSchoolCategory, watchUpdateSchool } from './school.sagas'
import { watchCreateClass, watchGetClass, watchGetAllClass, watchUpdateClass, watchDeleteClass, watchGetClassGrades, watchGetClassStandards } from './class.sagas'
import { watchCreateClass, watchGetClass, watchGetAllClass, watchUpdateClass, watchDeleteClass, watchGetClassGrades, watchGetClassStandards, watchGetMyClassStandards } from './class.sagas'
import {
watchCreateTeacher, watchGetTeacher, watchGetAllTeacher, watchUpdateTeacher, watchDeleteTeacher, watchGetAllTeacherSubjects,
watchGetAllClasses, watchGetAllSubjects, watchGetAllClassInCharge, watchMapClassIncharge, watchCreateSubjectMapping, watchUpdateSubjectMapping,
@ -35,6 +35,9 @@ import { watchGetPsychometricClassList, watchGetPsychometricStudentListByClass,w
import {
watchGetLicenseValidate, watchGetMenuList, watchGetLicenseSchoolList, watchGetLicenseSchoolDomain } from './license.saga'
import {
watchGetAllQuestionPaper, watchGetAllAssessmentList, watchGetQuestionPaper, watchCreateAssessment, watchUpdateAssessment, watchDeleteAssessment,
watchGetAssessment, watchGetAssessmentStudentList, watchCreateAssessmentScanAnswer} from './questionbank.saga'
export default function* root() {
yield all([
watchGetLogin(),
@ -56,6 +59,7 @@ export default function* root() {
watchDeleteClass(),
watchGetClassGrades(),
watchGetClassStandards(),
watchGetMyClassStandards(),
watchCreateTeacher(),
watchGetTeacher(),
watchGetAllTeacher(),
@ -129,6 +133,15 @@ export default function* root() {
watchGetLicenseValidate(),
watchGetMenuList(),
watchGetLicenseSchoolList(),
watchGetLicenseSchoolDomain()
watchGetLicenseSchoolDomain(),
watchGetAllQuestionPaper(),
watchGetAllAssessmentList(),
watchGetQuestionPaper(),
watchCreateAssessment(),
watchGetAssessment(),
watchGetAssessmentStudentList(),
watchUpdateAssessment(),
watchDeleteAssessment(),
watchCreateAssessmentScanAnswer()
])
}

View File

@ -0,0 +1,130 @@
import { takeEvery, call, put } from 'redux-saga/effects'
import {
GET_QUESTION_PAPER_PAGINATION_REQUEST, GET_ASSESSMENT_PAGINATION_REQUEST,
GET_QUESTION_PAPER_REQUEST, CREATE_ASSESSMENT_REQUEST, GET_ASSESSMENT_REQUEST,
UPDATE_ASSESSMENT_REQUEST, GET_ASSESSMENT_STUDENT_LIST_REQUEST, DELETE_ASSESSMENT_REQUEST,
CREATE_ASSESSMENT_SCAN_ANSWERS_REQUEST
} from '@actions/type' //NOSONAR
import { getAllQuestionPaper, getAllAssessmentList, getQuestionPaper,createAssessment, updateAssessment, getAssessment, getAssessmentStudentList, deleteAssessment, createAssessmentScanAnswer } from '@api/questionbank.api' //NOSONAR
import { ActionCreators } from '@actions' //NOSONAR
export const watchGetAllQuestionPaper = function* () {
yield takeEvery(GET_QUESTION_PAPER_PAGINATION_REQUEST, workerGetAllQuestionPaper)
}
function* workerGetAllQuestionPaper(action: any) {
try {
const response = yield call(getAllQuestionPaper, action.data)
yield put(ActionCreators.getQuestionPaperPaginationSuccess(response))
} catch (e) {
yield put(ActionCreators.getQuestionPaperPaginationSuccess(e))
}
}
export const watchGetAllAssessmentList = function* () {
yield takeEvery(GET_ASSESSMENT_PAGINATION_REQUEST, workerGetAllAssessmentList)
}
function* workerGetAllAssessmentList(action: any) {
try {
const response = yield call(getAllAssessmentList, action.data)
yield put(ActionCreators.getAssessmentPaginationSuccess(response))
} catch (e) {
yield put(ActionCreators.getAssessmentPaginationFailure(e))
}
}
export const watchGetQuestionPaper = function* () {
yield takeEvery(GET_QUESTION_PAPER_REQUEST, workerGetQuestionPaper)
}
function* workerGetQuestionPaper(action: any) {
try {
const response = yield call(getQuestionPaper, action.data)
yield put(ActionCreators.getQuestionPaperSuccess(response))
} catch (e) {
yield put(ActionCreators.getQuestionPaperFailure(e))
}
}
export const watchCreateAssessment = function* () {
yield takeEvery(CREATE_ASSESSMENT_REQUEST, workerCreateAssessment)
}
function* workerCreateAssessment(action: any) {
try {
const response = yield call(createAssessment, action.data)
yield put(ActionCreators.createAssessmentSuccess(response))
} catch (e) {
yield put(ActionCreators.createAssessmentFailure(e))
}
}
export const watchGetAssessment = function* () {
yield takeEvery(GET_ASSESSMENT_REQUEST, workerGetAssessment)
}
function* workerGetAssessment(action: any) {
try {
const response = yield call(getAssessment, action.data)
yield put(ActionCreators.getAssessmentSuccess(response))
} catch (e) {
yield put(ActionCreators.getAssessmentFailure(e))
}
}
export const watchGetAssessmentStudentList = function* () {
yield takeEvery(GET_ASSESSMENT_STUDENT_LIST_REQUEST, workerGetAssessmentStudentList)
}
function* workerGetAssessmentStudentList(action: any) {
try {
const response = yield call(getAssessmentStudentList, action.data)
yield put(ActionCreators.getAssessmentStudentListSuccess(response))
} catch (e) {
yield put(ActionCreators.getAssessmentStudentListFailure(e))
}
}
export const watchUpdateAssessment = function* () {
yield takeEvery(UPDATE_ASSESSMENT_REQUEST, workerUpdateAssessment)
}
function* workerUpdateAssessment(action: any) {
try {
const response = yield call(updateAssessment, action.data)
yield put(ActionCreators.updateAssessmentSuccess(response))
} catch (e) {
yield put(ActionCreators.updateAssessmentFailure(e))
}
}
export const watchDeleteAssessment = function* () {
yield takeEvery(DELETE_ASSESSMENT_REQUEST, workerDeleteAssessment)
}
function* workerDeleteAssessment(action: any) {
try {
const response = yield call(deleteAssessment, action.data)
console.log(response)
yield put(ActionCreators.deleteAssessmentSuccess(response))
} catch (e) {
yield put(ActionCreators.deleteAssessmentFailure(e))
}
}
export const watchCreateAssessmentScanAnswer = function* () {
yield takeEvery(CREATE_ASSESSMENT_SCAN_ANSWERS_REQUEST, workerCreateAssessmentScanAnswer)
}
function* workerCreateAssessmentScanAnswer(action: any) {
try {
//console.log(action.data)
const response = yield call(createAssessmentScanAnswer, action.data)
console.log(response)
yield put(ActionCreators.createAssessmentScanAnswerSuccess(response))
} catch (e) {
yield put(ActionCreators.createAssessmentScanAnswerFailure(e))
}
}

View File

@ -0,0 +1,180 @@
import React from "react"
import { StyleSheet, Text, View, TouchableOpacity, ActivityIndicator, Dimensions, FlatList } from 'react-native'
import { AppStyles, BaseStyles } from "@theme/BaseStyles" //NOSONAR
import AsyncStorage from "@react-native-async-storage/async-storage"
import { connect } from "react-redux"
import { ActionCreators } from "@actions" //NOSONAR
import PropTypes from 'prop-types'
import { UserRoles, currentYear, common, currentAcademicYear } from "@constants/Constants" //NOSONAR
import BaseColors from "@theme/Colors" //NOSONAR
import { ScrollView } from "react-native-gesture-handler"
import * as ScreenOrientation from 'expo-screen-orientation'
import { FontAwesome, Ionicons } from "@expo/vector-icons"
class Assessment extends React.Component<any, any>{
static propTypes = {};
isLoggedinAs: any;
scrollView: any;
token: any;
state: any = {
academicYear: ''
};
constructor(props: any) {
super(props)
}
async componentDidMount() {
const { navigation, route } = this.props;
const title = 'Assessment';
navigation.setOptions({ title });
this.getCurrentAcademicYearData() //fetch the Current Academic year from Login Response
this.token = await AsyncStorage.getItem('token')
const userInfo = await AsyncStorage.getItem('userInfo')
if (this.token) {
if (userInfo) {
const userDetails: any = JSON.parse(userInfo)
this.isLoggedinAs = userDetails.usertype
}
const dataParams: any = this.props.route.params.data
console.log(dataParams)
this.props.getAssessmentPagination({ token: this.token, academic_year: this.state.academicYear.toString(), question_paper_id: dataParams.uid, page_no: 1 })
} else {
this.props.navigation.navigate('signin')
}
}
changeScreenOrientation = async () => {
await ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.LANDSCAPE)
}
componentDidUpdate() {
}
/** Get the curremt Academic Year */
getCurrentAcademicYearData = () => {
currentAcademicYear().then((userInfo) => {
if (userInfo) {
const academicYear = userInfo.current_academic_year
this.setState({ academicYear: academicYear })
}
}).catch(error => {
console.log(error)
})
}
async componentWillUnmount() {
await ScreenOrientation.unlockAsync()
}
toAssessmentEdit = (data: any, val: any,) => {
const dataParams: any = this.props.route.params.data
this.props.navigation.navigate("AssessmentEdit", { data: data, question_paper_id: dataParams.uid })
}
toAssessmentCreate = () => {
this.props.navigation.navigate("AssessmentCreate", { data: this.props.route.params.data })
}
toScanner = () => {
this.props.navigation.navigate("AssessmentScanner", { data: this.props.route.params.data })
}
renderRow = ({ item }: any) => (
<View style={{ padding: 0, }}>
<TouchableOpacity style={styles.item}
onPress={this.toAssessmentEdit.bind(this, item)}>
<View style={{ flexDirection: 'column', margin: 10 }}>
<Text style={[AppStyles.nameLabel, BaseStyles.font18, BaseStyles.font700Bold, BaseStyles.marBottom5,]}>{item?.student_name} </Text>
</View>
<View style={styles.actions}>
<TouchableOpacity style={styles.iconButton} onPress={this.toAssessmentEdit.bind(this, item)} activeOpacity={0.8}>
<FontAwesome name="edit" size={18} style={[AppStyles.icon, { paddingLeft: 5, fontWeight: 'bold', color: '#5952d6' }]} />
</TouchableOpacity>
{/* <TouchableOpacity style={styles.iconButton} activeOpacity={0.8} onPress={this.toAssessmentEdit.bind(this, item)}>
<Text>View</Text>
</TouchableOpacity> */}
</View>
</TouchableOpacity>
</View>
)
render() {
return (<View style={[AppStyles.containerWoPadding, {}]}>
<View>
<TouchableOpacity
style={[AppStyles.primaryBtn, { alignSelf: 'center' }]} onPress={this.toScanner} activeOpacity={0.8}>
<Text style={AppStyles.btnText}>Scan</Text>
</TouchableOpacity>
</View>
{!this.props.loading && this.props.records && <FlatList
style={{ marginVertical: 12, marginHorizontal: 16 }}
data={this.props.records}
renderItem={this.renderRow}
keyExtractor={(item, index) => index.toString()}
/>
}
{this.props.loading && <View style={[BaseStyles.marVertical20, { flex: 1, justifyContent: 'center' }]}>
<ActivityIndicator size="large" color="#7165e3" />
</View>}
{this.isLoggedinAs && ((this.isLoggedinAs === UserRoles.schoolAdmin) || this.isLoggedinAs === UserRoles.teacher) &&
<TouchableOpacity style={[AppStyles.btnRound, AppStyles.btnPositionBtmRight]}
onPress={this.toAssessmentCreate} activeOpacity={0.8}>
<FontAwesome name="plus" size={24} style={[AppStyles.icon, { paddingLeft: 5, fontWeight: 'bold' }]} />
</TouchableOpacity>}
</View>)
}
}
const styles = StyleSheet.create({
item: {
padding: 16,
backgroundColor: '#fff',
marginBottom: 8,
borderRadius: 8,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.3,
shadowRadius: 2,
elevation: 2,
},
actions: {
flexDirection: 'row',
},
iconButton: {
marginHorizontal: 5,
},
})
const mapStateToProps = (state: any) => ({
loading: state.questionbank.loading,
isLoading: state.students.loading,
questionPaperList: state.questionbank.question_paper,
records: state.questionbank.assessmentrecords,
})
const mapDispatchToProps = (dispatch: any) => ({
getAssessmentPagination: (user: any) => {
dispatch(ActionCreators.getAssessmentPaginationAction(user))
},
})
Assessment.propTypes = {
loading: PropTypes.bool,
error: PropTypes.object,
info: PropTypes.object,
}
export default connect(mapStateToProps, mapDispatchToProps)(Assessment)

View File

@ -0,0 +1,379 @@
import React from "react"
import { StyleSheet, Text, View, TouchableOpacity, ActivityIndicator, TextInput, FlatList } from 'react-native'
import { AppStyles, BaseStyles, PickerStyle } from "@theme/BaseStyles" //NOSONAR
import AsyncStorage from "@react-native-async-storage/async-storage"
import { connect } from "react-redux"
import { ActionCreators } from "@actions" //NOSONAR
import PropTypes from 'prop-types'
import { UserRoles, currentYear, common, currentAcademicYear } from "@constants/Constants" //NOSONAR
import BaseColors from "@theme/Colors" //NOSONAR
import { ScrollView } from "react-native-gesture-handler"
import * as ScreenOrientation from 'expo-screen-orientation'
import StarRating from '../../components/StarRating'
import { Formik } from 'formik'
import * as yup from 'yup'
import RNPickerSelect from "react-native-picker-select"
import { Ionicons } from "@expo/vector-icons"
class AssessmentCreate extends React.Component<any, any>{
static propTypes = {};
isLoggedinAs: any;
scrollView: any;
token: any;
formikActions: any;
state: any = {
academicYear: '',
question_details: [],
question_update: false,
grade_id: '',
grade_name: '',
student_list: []
};
constructor(props: any) {
super(props)
}
async componentDidMount() {
const { navigation, route } = this.props;
const title = 'Assessment Create';
navigation.setOptions({ title });
this.getCurrentAcademicYearData() //fetch the Current Academic year from Login Response
this.token = await AsyncStorage.getItem('token')
const userInfo = await AsyncStorage.getItem('userInfo')
if (this.token) {
const dataParams: any = this.props.route.params.data
this.setState({ grade_id: dataParams.internal_grade_id, grade_name: dataParams.internal_grade_name })
await this.props.getQuestionPaper({ token: this.token, academic_year: this.state.academicYear.toString(), question_paper_id: dataParams.uid, page_no: 1 })
await this.props.getMyClassStandard({ token: this.token, grade_id: dataParams.internal_grade_id })
} else {
this.props.navigation.navigate('signin')
}
}
changeScreenOrientation = async () => {
await ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.LANDSCAPE)
}
async componentDidUpdate(prevProps: any) {
if (prevProps.question_details != this.props.question_details) {
const questionRecords = this.props.question_details;
const order: Record<string, number> = {
"MCQ": 1,
"FIB": 2,
"Regular-2 Marks": 3,
"Regular-5 Marks": 4,
"Regular-10 Marks": 5
};
const sortedQuestions = questionRecords.sort((a: any, b: any) => {
return order[a.question_type_name] - order[b.question_type_name];
});
const initializedData = sortedQuestions.map((group: any) => ({
...group,
question: group.question.map((q: any) => ({
...q,
currentRating: 0, // Default rating set to 0
})),
}));
this.setState({ question_details: initializedData, question_update: true })
}
if (this.props.assessmentCreate.hasOwnProperty('status')) {
if (this.props.assessmentCreate.status) {
const dataParams: any = this.props.route.params.data
this.props.getAssessmentPagination({ token: this.token, academic_year: this.state.academicYear.toString(), question_paper_id: dataParams.uid, page_no: 1 })
this.props.navigation.navigate("Assessment", { data: this.props.route.params.data })
}
}
else if (prevProps.assessmentStudentList != this.props.assessmentStudentList) {
const filterStudents = this.props.studentList.data.filter((student: any) => !this.props.assessmentStudentList.includes(student.student_id.toString()));
this.setState({ student_list: filterStudents })
}
}
/** Get the curremt Academic Year */
getCurrentAcademicYearData = () => {
currentAcademicYear().then((userInfo) => {
if (userInfo) {
const academicYear = userInfo.current_academic_year
this.setState({ academicYear: academicYear })
}
}).catch(error => {
console.log(error)
})
}
async componentWillUnmount() {
await ScreenOrientation.unlockAsync()
}
onStarRatingPress = (rating: number, questionId: any) => {
const updatedQuestions = this.state.question_details.map((question: any) => ({
...question,
question: question.question.map((q: any) => {
if (q.question_id === questionId) {
return { ...q, currentRating: rating };
}
return q;
}),
}));
this.setState({ question_details: updatedQuestions })
}
renderRow = (item: any) => {
return (
<View style={{ padding: 0, }}>
<View style={styles.item}>
<Text>{item?.uid} </Text>
<StarRating
disabled={false}
maxStars={item?.question_type_marks}
rating={item?.currentRating}
fullStar={'star'}
halfStar={'star-half'}
emptyStar={'star-outline'}
iconSet={'Ionicons'}
selectedStar={(rating: number) => this.onStarRatingPress(rating, item?.question_id)}
fullStarColor={'orange'}
//starSize={35}
halfStarEnabled={true}
containerStyle={styles.starRating}
/>
</View>
</View>
)
}
onAssessmentSubmit = (data: any, actions: any) => {
this.formikActions = actions
data['class_id'] = data.class_id.toString()
data['student_id'] = data.student_id.toString()
data['question_paper_id'] = this.props.route.params.data.uid
const finalData: any = {};
this.state.question_details.forEach((group: any) => {
group.question.forEach((item: any) => {
finalData[item.uid] = item.currentRating;
});
});
data['assessment_details'] = finalData
this.props.createAssessment({ data, token: this.token })
}
onCancel = () => {
this.props.navigation.navigate("Assessment", { data: this.props.route.params.data })
}
getDataOptions = (data: any, action: any) => {
const options = data && data.map((item: any, index: any) => ({
key: index,
label: action === "class" ? item.standard : item.student_name,
value: action === "class" ? item.id : item.student_id
}))
if (options && options.length >= 0) {
return options
}
return []
}
onSelectChange = (action: any, event: any, setFieldValue: any) => {
setFieldValue(action, event)
if (action === "class_id") {
//this.setState({ card_id: event })
this.studentList(event)
}
}
studentList = async (class_id: any) => {
const dataParams: any = this.props.route.params.data
await this.props.getStudentsList({ token: this.token, class_id: class_id, academic_year: this.state.academicYear.toString() })
await this.props.getAssessmentStudentList({ token: this.token, question_paper_id: dataParams.uid, class_id: class_id, academic_year: this.state.academicYear.toString() })
}
render() {
const { grade_id, grade_name } = this.state
return (<View style={[AppStyles.containerWoPadding, {}]}>
{grade_name && this.props.class_standard?.data &&
<ScrollView style={{ marginVertical: 8, marginHorizontal: 8 }}>
<View style={{
margin: 2, padding: 16, borderRadius: 32, backgroundColor: 'white', shadowColor: "#8D81F8",
shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.01, shadowRadius: 16, elevation: 3, zIndex: 10
}}>
<Formik
enableReinitialize={true}
initialValues={{
class_id: '',
student_id: ''
}}
onSubmit={(values, actions) => this.onAssessmentSubmit(values, actions)}
>
{({ handleChange, handleBlur, handleSubmit, values, errors, touched, isValid, dirty, setFieldValue }) => (
<>
<Text style={[AppStyles.cardHeader, BaseStyles.marTop5]}>Class<Text style={AppStyles.required}> *</Text></Text>
<View style={[AppStyles.inputView, BaseStyles.marTop5,]} >
<TextInput style={AppStyles.inputText} name="firstname" placeholder="Enter the First name"
onChangeText={handleChange('firstname')} onBlur={handleBlur('firstname')}
value={grade_name} keyboardType="default" maxLength={50} />
</View>
{(errors.firstname && touched.firstname) && <Text style={AppStyles.error}>{errors.firstname}</Text>}
<Text style={[AppStyles.cardHeader, BaseStyles.marTop5]}>Section</Text>
<View style={[AppStyles.inputView, BaseStyles.marTop5, { width: '100%' }]}>
<RNPickerSelect
style={PickerStyle}
value={values.class_id}
onValueChange={(itemValue, itemIndex) =>
this.onSelectChange('class_id', itemValue, setFieldValue)
}
placeholder={{
label: '--Select Section--',
value: null,
}}
useNativeAndroidPickerStyle={false}
items={this.getDataOptions(this.props.class_standard.data, 'class')}
Icon={() => <Ionicons name="caret-down" size={14} color="gray" />}
/>
</View>
{(errors.lastname && touched.lastname) && <Text style={AppStyles.error}>{errors.lastname}</Text>}
<Text style={[AppStyles.cardHeader, BaseStyles.marTop5]}>Student<Text style={AppStyles.required}> *</Text></Text>
<View style={[AppStyles.inputView, BaseStyles.marTop5, { width: '100%' }]}>
<RNPickerSelect
style={PickerStyle}
value={values.student_id}
onValueChange={(itemValue, itemIndex) =>
this.onSelectChange('student_id', itemValue, setFieldValue)
}
placeholder={{
label: '--Select Student--',
value: null,
}}
useNativeAndroidPickerStyle={false}
items={this.getDataOptions(this.state.student_list, 'student_id')}
Icon={() => <Ionicons name="caret-down" size={14} color="gray" />}
/>
</View>
{(errors.phone_number && touched.phone_number) && <Text style={AppStyles.error}>{errors.phone_number}</Text>}
{!this.props.loading && this.state.question_details && this.state.question_details.map((item: any, index: any) => (
<View style={[ BaseStyles.marBottom5,BaseStyles.marTop10]}>
<Text style={[AppStyles.nameLabel, BaseStyles.font18, BaseStyles.font700Bold, BaseStyles.marBottom5,]}>{item.question_type_desc}</Text>
<Text style={[AppStyles.nameLabel, BaseStyles.font18, BaseStyles.font700Bold, BaseStyles.marBottom5,]}>{item.marks}</Text>
{item.question.map((val: any, index: any) => (
<View>
{this.renderRow(val)}
</View>
))}
</View>
))}
<View style={[styles.container]}>
<View style={styles.btnItem}>
<TouchableOpacity style={[AppStyles.defaultBtn, { alignSelf: 'center' }]} onPress={this.onCancel} activeOpacity={0.8}>
<Text style={[AppStyles.btnText, { color: '#000' }]} >Cancel</Text>
</TouchableOpacity>
</View>
<View style={styles.btnItem}>
<TouchableOpacity disabled={this.props.loading}
style={[AppStyles.primaryBtn, { alignSelf: 'center' }]} onPress={handleSubmit} activeOpacity={0.8}>
<Text style={AppStyles.btnText}>Submit</Text>
</TouchableOpacity>
</View>
</View>
{this.props.loading && <ActivityIndicator size="large" color="#7165e3" />}
</>
)}
</Formik>
{this.props.loading && <View style={[BaseStyles.marVertical20, { flex: 1, justifyContent: 'center' }]}>
<ActivityIndicator size="large" color="#7165e3" />
</View>}
</View>
</ScrollView>}
</View>)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
alignItems: 'flex-start' // if you want to fill rows left to right
},
item: {
padding: 16,
backgroundColor: '#fff',
marginBottom: 8,
borderRadius: 8,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.3,
shadowRadius: 2,
elevation: 2,
},
actions: {
flexDirection: 'row',
},
btnItem: {
width: '50%', // is 50% of whole width
},
starRating: {
// marginRight: 20,
//width: '50%',
},
})
const mapStateToProps = (state: any) => ({
loading: state.questionbank.loading,
error: state.quizzes.error,
info: state.quizzes.info,
isLoading: state.students.loading,
questionPaperList: state.questionbank.question_paper,
question_details: state.questionbank.question_details,
class_standard: state.classes.class_standard,
studentList: state.students.student_list,
assessmentCreate: state.questionbank.assessment_create,
assessmentStudentList: state.questionbank.assessment_student_list,
})
const mapDispatchToProps = (dispatch: any) => ({
initQuizzes: (user: any) => {
dispatch(ActionCreators.initQuizzesAction(user))
},
getQuestionPaper: (user: any) => {
dispatch(ActionCreators.getQuestionPaperAction(user))
},
createAssessment: (user: any) => {
dispatch(ActionCreators.createAssessmentAction(user))
},
getMyClassStandard: (user: any) => {
dispatch(ActionCreators.getMyClassStandardAction(user))
},
getStudentsList: (user: any) => {
dispatch(ActionCreators.getStudentsListAction(user))
},
getAssessmentStudentList: (user: any) => {
dispatch(ActionCreators.getAssessmentStudentListAction(user))
},
getAssessmentPagination: (user: any) => {
dispatch(ActionCreators.getAssessmentPaginationAction(user))
},
})
AssessmentCreate.propTypes = {
loading: PropTypes.bool,
error: PropTypes.object,
info: PropTypes.object,
}
export default connect(mapStateToProps, mapDispatchToProps)(AssessmentCreate)

View File

@ -0,0 +1,397 @@
import React from "react"
import { StyleSheet, Text, View, TouchableOpacity, ActivityIndicator, TextInput, FlatList } from 'react-native'
import { AppStyles, BaseStyles, PickerStyle } from "@theme/BaseStyles" //NOSONAR
import AsyncStorage from "@react-native-async-storage/async-storage"
import { connect } from "react-redux"
import { ActionCreators } from "@actions" //NOSONAR
import PropTypes from 'prop-types'
import { UserRoles, currentYear, common, currentAcademicYear } from "@constants/Constants" //NOSONAR
import BaseColors from "@theme/Colors" //NOSONAR
import { ScrollView } from "react-native-gesture-handler"
import * as ScreenOrientation from 'expo-screen-orientation'
import StarRating from '../../components/StarRating'
import { Formik } from 'formik'
import * as yup from 'yup'
import RNPickerSelect from "react-native-picker-select"
import { Ionicons } from "@expo/vector-icons"
class AssessmentEdit extends React.Component<any, any>{
static propTypes = {};
isLoggedinAs: any;
scrollView: any;
token: any;
formikActions: any;
state: any = {
academicYear: '',
question_details:[],
question_update:false,
grade_id:'',
grade_name:'',
student_list:[],
studentName:''
};
constructor(props: any) {
super(props)
}
async componentDidMount() {
const { navigation, route } = this.props;
const title = 'Assessment Edit';
navigation.setOptions({ title });
this.getCurrentAcademicYearData() //fetch the Current Academic year from Login Response
this.token = await AsyncStorage.getItem('token')
const userInfo = await AsyncStorage.getItem('userInfo')
if (this.token) {
await this.props.initAssessment({})
const dataParams: any = this.props.route.params.data
this.setState({ grade_id: dataParams.internal_grade_id, grade_name:dataParams.internal_grade_name })
await this.props.getAssessment({ token: this.token, uid: dataParams.uid})
const question_paper_id: any = this.props.route.params.question_paper_id
await this.props.getQuestionPaper({ token: this.token, academic_year: this.state.academicYear.toString(), question_paper_id:question_paper_id,page_no:1})
} else {
this.props.navigation.navigate('signin')
}
}
changeScreenOrientation = async () => {
await ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.LANDSCAPE)
}
async componentDidUpdate(prevProps: any) {
if (prevProps.question_details != this.props.question_details) {
const questionRecords = this.props.question_details;
const order: Record<string, number> = {
"MCQ": 1,
"FIB": 2,
"Regular-2 Marks": 3,
"Regular-5 Marks": 4,
"Regular-10 Marks": 5
};
const sortedQuestions = questionRecords.sort((a:any, b:any) => {
return order[a.question_type_name] - order[b.question_type_name];
});
const initializedData = sortedQuestions.map((group:any) => ({
...group,
question: group.question.map((q:any) => ({
...q,
currentRating: this.props.assessment.assessment_details[q.uid], // Default rating set to 0
})),
}));
this.setState({ question_details: initializedData, question_update:true })
}
if (prevProps.assessment != this.props.assessment) {
const assessment = this.props.assessment;
this.setState({ grade_name: assessment.class_name, studentName:assessment.student_name })
}
if (this.props.assessmentUpdate.hasOwnProperty('status')) {
if (this.props.assessmentUpdate.status) {
const question_paper_id: any = this.props.route.params.question_paper_id
this.props.getAssessmentPagination({ token: this.token, academic_year: this.state.academicYear.toString(), question_paper_id:question_paper_id,page_no:1})
this.props.navigation.navigate("Assessment", { data: this.props.route.params.data })
}
}
else if (prevProps.assessmentStudentList != this.props.assessmentStudentList) {
const filterStudents = this.props.studentList.data.filter((student:any) => !this.props.assessmentStudentList.includes(student.student_id.toString()));
this.setState({ student_list:filterStudents})
}
}
/** Get the curremt Academic Year */
getCurrentAcademicYearData = () => {
currentAcademicYear().then((userInfo) => {
if (userInfo) {
const academicYear = userInfo.current_academic_year
this.setState({ academicYear: academicYear })
}
}).catch(error => {
console.log(error)
})
}
async componentWillUnmount() {
await ScreenOrientation.unlockAsync()
}
onStarRatingPress = (rating: number, questionId:any) => {
const updatedQuestions = this.state.question_details.map((question:any) => ({
...question,
question: question.question.map((q:any) => {
if (q.question_id === questionId) {
return { ...q, currentRating: rating };
}
return q;
}),
}));
this.setState({ question_details: updatedQuestions })
}
handleStarPress = (newRating:any, rowIndex:any, questionId:any) => {
const updatedRating = newRating + rowIndex * 5;
this.setState({ rating: updatedRating });
const updatedQuestions = this.state.question_details.map((question:any) => ({
...question,
question: question.question.map((q:any) => {
if (q.question_id === questionId) {
return { ...q, currentRating: updatedRating };
}
return q;
}),
}));
this.setState({ question_details: updatedQuestions })
};
renderStarRows = (item:any) => {
const rating = item?.currentRating;
const starRows = [];
const totalStars = item.question_type_marks;
const starsPerRow = item.question_type_marks <= 5 ? item.question_type_marks : 5;
for (let i = 0; i < totalStars / starsPerRow; i++) {
starRows.push(
<StarRating
key={i}
disabled={false}
maxStars={starsPerRow}
rating={Math.min(rating - i * starsPerRow, starsPerRow)}
fullStar={'star'}
halfStar={'star-half'}
emptyStar={'star-outline'}
iconSet={'Ionicons'}
selectedStar={(newRating) => this.handleStarPress(newRating, i,item?.question_id)}
fullStarColor={'orange'}
starSize={35} // Adjust the size of each star
halfStarEnabled={true}
/>
);
}
return starRows;
};
renderRow = (item: any) => {
return (
<View style={{ padding: 0, }}>
<View style={styles.item}>
<Text>{item?.uid} </Text>
{/* <StarRating
disabled={false}
maxStars={item?.question_type_marks}
rating={item?.currentRating}
fullStar={'star'}
halfStar={'star-half'}
emptyStar={'star-outline'}
iconSet={'Ionicons'}
selectedStar={(rating: number) => this.onStarRatingPress(rating, item?.question_id)}
fullStarColor={'orange'}
//starSize={35}
halfStarEnabled={true}
containerStyle={styles.starRating}
/> */}
<View>{this.renderStarRows(item)}</View>
</View>
</View>
)
}
onAssessmentSubmit = (data: any, actions: any) => {
this.formikActions = actions
data['class_id'] = this.props.assessment.class_id
data['student_id'] = this.props.assessment.student_id
data['question_paper_id'] = this.props.assessment.question_paper_id
const finalData :any = {};
this.state.question_details.forEach((group:any) => {
group.question.forEach((item:any) => {
finalData[item.uid] = item.currentRating;
});
});
data['assessment_details'] = finalData
this.props.updateAssessment({ data, uid:this.props.assessment.uid, token: this.token })
}
onCancel = () => {
this.props.navigation.navigate("Assessment", { data: this.props.route.params.data })
}
getDataOptions = (data:any, action: any) => {
const options = data && data.map((item: any, index: any) => ({
key:index,
label: action === "class" ? item.standard : item.student_name,
value: action === "class" ? item.id : item.student_id
}))
if(options && options.length >= 0){
return options
}
return []
}
render() {
const { grade_id , grade_name , studentName} = this.state
return (<View style={[AppStyles.containerWoPadding, {}]}>
{
<ScrollView style={{ marginVertical: 8, marginHorizontal: 8 }}>
<View style={{ margin: 2, padding: 16, borderRadius: 32, backgroundColor: 'white', shadowColor: "#8D81F8",
shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.01, shadowRadius: 16, elevation: 3, zIndex: 10 }}>
<Formik
enableReinitialize={true}
initialValues={{
class_id:'',
student_id:''
}}
onSubmit={(values, actions) => this.onAssessmentSubmit(values, actions)}
>
{({ handleChange, handleBlur, handleSubmit, values, errors, touched, isValid, dirty, setFieldValue }) => (
<>
<Text style={[AppStyles.cardHeader, BaseStyles.marTop5]}>Class<Text style={AppStyles.required}> *</Text></Text>
<View style={[AppStyles.inputView, BaseStyles.marTop5,]} >
<TextInput style={AppStyles.inputText} name="firstname" placeholder="Enter the First name"
onChangeText={handleChange('firstname')} onBlur={handleBlur('firstname')}
value={grade_name} keyboardType="default" maxLength={50} editable={false}/>
</View>
{(errors.firstname && touched.firstname) && <Text style={AppStyles.error}>{errors.firstname}</Text>}
<Text style={[AppStyles.cardHeader, BaseStyles.marTop5]}>Student</Text>
<View style={[AppStyles.inputView, BaseStyles.marTop5, { width: '100%' }]}>
<TextInput style={AppStyles.inputText} name="firstname" placeholder="Student name"
onChangeText={handleChange('firstname')} onBlur={handleBlur('firstname')}
value={studentName} keyboardType="default" maxLength={50} editable={false}/>
</View>
{ !this.props.loading && this.state.question_details && this.state.question_details.map((item: any, index: any) => (
<View>
<Text style={[AppStyles.nameLabel, BaseStyles.font18, BaseStyles.font700Bold, BaseStyles.marBottom5,]}>{item.question_type_desc}</Text>
<Text style={[AppStyles.nameLabel, BaseStyles.font18, BaseStyles.font700Bold, BaseStyles.marBottom5,]}>{item.marks}</Text>
{item.question.map((val: any, index: any) => (
<View>
{this.renderRow(val)}
</View>
))}
</View>
)) }
<View style={[styles.container]}>
<View style={styles.btnItem}>
<TouchableOpacity style={[AppStyles.defaultBtn, { alignSelf: 'center' }]} onPress={this.onCancel} activeOpacity={0.8}>
<Text style={[AppStyles.btnText, { color: '#000' }]} >Cancel</Text>
</TouchableOpacity>
</View>
<View style={styles.btnItem}>
<TouchableOpacity disabled={this.props.loading}
style={[AppStyles.primaryBtn, { alignSelf: 'center' }]} onPress={handleSubmit} activeOpacity={0.8}>
<Text style={AppStyles.btnText}>Submit</Text>
</TouchableOpacity>
</View>
</View>
{this.props.loading && <ActivityIndicator size="large" color="#7165e3" />}
</>
)}
</Formik>
{this.props.loading && <View style={[BaseStyles.marVertical20, { flex: 1, justifyContent: 'center' }]}>
<ActivityIndicator size="large" color="#7165e3" />
</View>}
</View>
</ScrollView> }
</View>)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
alignItems: 'flex-start' // if you want to fill rows left to right
},
item: {
padding: 16,
backgroundColor: '#fff',
marginBottom: 8,
borderRadius: 8,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.3,
shadowRadius: 2,
elevation: 2,
},
actions: {
flexDirection: 'row',
},
btnItem: {
width: '50%', // is 50% of whole width
},
starRating: {
// marginRight: 20,
//width: '50%',
},
})
const mapStateToProps = (state: any) => ({
loading: state.questionbank.loading,
error: state.quizzes.error,
info: state.quizzes.info,
isLoading: state.students.loading,
questionPaperList: state.questionbank.question_paper,
question_details: state.questionbank.question_details,
class_standard: state.classes.class_standard,
studentList: state.students.student_list,
assessmentUpdate: state.questionbank.assessment_update,
assessmentStudentList:state.questionbank.assessment_student_list,
assessment:state.questionbank.assessment,
})
const mapDispatchToProps = (dispatch: any) => ({
initAssessment: () => {
dispatch(ActionCreators.initAssessmentAction())
},
getQuestionPaper: (user: any) => {
dispatch(ActionCreators.getQuestionPaperAction(user))
},
updateAssessment: (user: any) => {
dispatch(ActionCreators.updateAssessmentAction(user))
},
getMyClassStandard: (user: any) => {
dispatch(ActionCreators.getMyClassStandardAction(user))
},
getStudentsList: (user: any) => {
dispatch(ActionCreators.getStudentsListAction(user))
},
getAssessmentStudentList: (user: any) => {
dispatch(ActionCreators.getAssessmentStudentListAction(user))
},
getAssessment: (user: any) => {
dispatch(ActionCreators.getAssessmentAction(user))
},
getAssessmentPagination: (user: any) => {
dispatch(ActionCreators.getAssessmentPaginationAction(user))
},
})
AssessmentEdit.propTypes = {
loading: PropTypes.bool,
error: PropTypes.object,
info: PropTypes.object,
}
export default connect(mapStateToProps, mapDispatchToProps)(AssessmentEdit)

View File

@ -0,0 +1,277 @@
import React, { Component } from 'react';
import { Alert, Image, ImageStyle, StyleSheet, View, ViewStyle, TouchableOpacity, Text } from 'react-native';
import DocumentScanner from 'react-native-document-scanner-plugin';
import AsyncStorage from "@react-native-async-storage/async-storage"
import { connect } from "react-redux"
import { ActionCreators } from "@actions" //NOSONAR
import PropTypes from 'prop-types'
import { AppStyles, BaseStyles, PickerStyle } from "@theme/BaseStyles" //NOSONAR
import RNPickerSelect from "react-native-picker-select"
import { Ionicons } from "@expo/vector-icons"
import RNFS from 'react-native-fs';
interface State {
scannedImage: string | null;
}
class AssessmentScanner extends React.Component<any, any> {
static propTypes = {};
isLoggedinAs: any;
scrollView: any;
token: any;
formikActions: any;
state: any = {
scannedImage: null,
class_id: '',
};
constructor(props: any) {
super(props)
}
async componentDidMount() {
const { navigation, route } = this.props;
const title = 'Assessment Scanner';
navigation.setOptions({ title });
this.token = await AsyncStorage.getItem('token')
const userInfo = await AsyncStorage.getItem('userInfo')
if (this.token) {
const dataParams: any = this.props.route.params.data
this.setState({ grade_id: dataParams.internal_grade_id, grade_name: dataParams.internal_grade_name })
await this.props.getMyClassStandard({ token: this.token, grade_id: dataParams.internal_grade_id })
} else {
this.props.navigation.navigate('signin')
}
}
async componentDidUpdate(prevProps: any) {
console.log('assessmentAnswer')
console.log(this.props.assessmentAnswer)
if (this.props.assessmentAnswer.hasOwnProperty('data')) {
const result_table_data = this.props.assessmentAnswer?.data?.result_table_data
await this.props.initAssessment({})
Alert.alert('Required', JSON.stringify(result_table_data))
}
if (this.props.assessmentAnswer.hasOwnProperty('message')) {
const message = this.props.assessmentAnswer?.message
await this.props.initAssessment({})
Alert.alert('Required', JSON.stringify(message))
}
if (this.props.assessmentAnswer.hasOwnProperty('something_wrong')) {
const message = this.props.assessmentAnswer?.something_wrong
await this.props.initAssessment({})
Alert.alert('Required', JSON.stringify(message))
}
}
scanDocument = async () => {
const result = await DocumentScanner.scanDocument();
const scannedImages = await result.scannedImages;
if (scannedImages && scannedImages.length > 0) {
console.log("scannedImages")
console.log(scannedImages)
// const fileInfo = await RNFS.stat(scannedImages[0]);
// // Convert file size to MB
// const fileSizeInMB = fileInfo.size / (1024 * 1024);
// // Print the file size in MB
// console.log(`File size: ${fileSizeInMB.toFixed(2)} MB`);
const formData: any = new FormData()
formData.append("question_paper_id", this.props.route.params.data.uid)
formData.append("class_id", this.state.class_id.toString())
// const filePath = scannedImages[0]; // Get the URI of the first scanned image
// const fileName = filePath.split('/').pop(); // Extract the file name
// const destinationPath = `${RNFS.DocumentDirectoryPath}/ScannedDocs/${fileName}`; // Destination folder path
// // Check if the source file exists
// const sourceExists = await RNFS.exists(filePath);
// if (!sourceExists) {
// console.error('Source file does not exist at:', filePath);
// return;
// }
// // Ensure the destination folder exists
// await RNFS.mkdir(`${RNFS.DocumentDirectoryPath}/ScannedDocs`);
// // Move the file to the new folder
// await RNFS.moveFile(filePath, destinationPath);
// // Check if the file was moved successfully
// const destinationExists = await RNFS.exists(destinationPath);
// if (destinationExists) {
// console.log('File successfully moved to:', destinationPath);
// } else {
// console.error('File move failed.');
// }
// formData.append('file', {
// uri: scannedImages[0],
// type: 'image/jpeg',
// name: 'scanned_image.jpg',
// });
const destinationExists = await RNFS.exists(scannedImages[0]);
if (destinationExists) {
console.log('File successfully moved to:', scannedImages[0]);
} else {
console.error('File move failed.');
}
// try {
// const response = await fetch('https://beta-api.wizdomwaves.in/api/questionbank-module/assessment-answers', {
// method: 'POST',
// body: formData,
// headers: {'Content-Type': 'multipart/form-data', 'Authorization': this.token},
// });
// if (!response.ok) {
// console.log(response)
// throw new Error(`HTTP error! Status: ${response.status}`);
// }
// const data = await response.json();
// console.log('Success:', data);
// } catch (error) {
// console.error('Error:', error);
// }
await this.props.createAssessmentScanAnswer({ data: formData, token: this.token })
await this.setState({ scannedImage: scannedImages[0] });
}
}
onSelectChange = async (id: any) => {
if (id) {
this.setState({ class_id: id })
} else {
this.setState({ class_id: '' })
}
}
getDataOptions = (data: any) => {
const options = data && data.map((item: any, index: any) => ({
key: index,
label: item.standard,
value: item.id
}))
if (options && options.length >= 0) {
return options
}
return []
}
toScan = async () => {
await this.scanDocument();
}
render() {
const { scannedImage } = this.state;
return (
<View style={styles.container}>
{scannedImage ? (
<Image
resizeMode="contain"
style={styles.image}
source={{ uri: scannedImage }}
/>
) : (
<View>
<View style={[AppStyles.inputView, BaseStyles.marTop5, { width: '100%' }]}>
<RNPickerSelect
style={PickerStyle}
value={this.state.class_id}
onValueChange={(itemValue, itemIndex) =>
this.onSelectChange(itemValue)
}
placeholder={{
label: '--Select Section--',
value: null,
}}
useNativeAndroidPickerStyle={false}
items={this.getDataOptions(this.props.class_standard.data)}
Icon={() => <Ionicons name="caret-down" size={14} color="gray" />}
/>
</View>
<TouchableOpacity style={BaseStyles.loginBtn} onPress={this.toScan} activeOpacity={0.8}>
<Text style={BaseStyles.loginText} >Scan</Text>
</TouchableOpacity>
</View>
)}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
//justifyContent: 'center',
// alignItems: 'center',
} as ViewStyle,
image: {
width: '100%',
height: '100%',
} as ImageStyle,
placeholder: {
width: '100%',
height: '100%',
justifyContent: 'center',
alignItems: 'center',
} as ViewStyle,
});
const mapStateToProps = (state: any) => ({
loading: state.questionbank.loading,
isLoading: state.students.loading,
questionPaperList: state.questionbank.question_paper,
records: state.questionbank.assessmentrecords,
class_standard: state.classes.class_standard,
assessmentAnswer: state.questionbank.assessment_answer,
})
const mapDispatchToProps = (dispatch: any) => ({
initAssessment: () => {
dispatch(ActionCreators.initAssessmentAction())
},
getAssessmentPagination: (user: any) => {
dispatch(ActionCreators.getAssessmentPaginationAction(user))
},
getMyClassStandard: (user: any) => {
dispatch(ActionCreators.getMyClassStandardAction(user))
},
createAssessmentScanAnswer: (user: any) => {
dispatch(ActionCreators.createAssessmentScanAnswerAction(user))
}
})
AssessmentScanner.propTypes = {
loading: PropTypes.bool,
error: PropTypes.object,
info: PropTypes.object,
}
export default connect(mapStateToProps, mapDispatchToProps)(AssessmentScanner)

View File

@ -0,0 +1,165 @@
import React from "react"
import { StyleSheet, Text, View, TouchableOpacity, ActivityIndicator, Dimensions, FlatList } from 'react-native'
import { AppStyles, BaseStyles } from "@theme/BaseStyles" //NOSONAR
import AsyncStorage from "@react-native-async-storage/async-storage"
import { connect } from "react-redux"
import { ActionCreators } from "@actions" //NOSONAR
import PropTypes from 'prop-types'
import { UserRoles, currentYear, common, currentAcademicYear } from "@constants/Constants" //NOSONAR
import BaseColors from "@theme/Colors" //NOSONAR
import { ScrollView } from "react-native-gesture-handler"
import * as ScreenOrientation from 'expo-screen-orientation'
import { FontAwesome } from "@expo/vector-icons"
import Toast from 'react-native-simple-toast'
const Sepator = ({ style }: any) => <View style={[BaseStyles.borderSeparator, style]} />
const { width } = Dimensions.get('window')
class QuestionBank extends React.Component<any, any>{
// static navigationOptions = ({ navigation }: any) => ({
// headerTitle: navigation.state.params?.data?.question_name || 'Quizzes',
// });
static propTypes = {};
isLoggedinAs: any;
scrollView: any;
token: any;
state: any = {
academicYear: ''
};
constructor(props: any) {
super(props)
}
async componentDidMount() {
const { navigation, route } = this.props;
const title = 'Question Bank';
navigation.setOptions({ title });
this.getCurrentAcademicYearData() //fetch the Current Academic year from Login Response
this.token = await AsyncStorage.getItem('token')
const userInfo = await AsyncStorage.getItem('userInfo')
if (this.token) {
//const dataParams: any = this.props.route.params.data
this.props.getQuestionPaperList({ token: this.token, academic_year: this.state.academicYear.toString(), page_no: 1 })
} else {
this.props.navigation.navigate('signin')
}
}
changeScreenOrientation = async () => {
await ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.LANDSCAPE)
}
componentDidUpdate() {
}
/** Get the curremt Academic Year */
getCurrentAcademicYearData = () => {
currentAcademicYear().then((userInfo) => {
if (userInfo) {
const academicYear = userInfo.current_academic_year
this.setState({ academicYear: academicYear })
}
}).catch(error => {
console.log(error)
})
}
async componentWillUnmount() {
await ScreenOrientation.unlockAsync()
}
toAssessmentScreen = (data: any, val: any) => {
this.props.navigation.navigate("Assessment", { data: data })
}
renderRow = ({ item }: any) => (
<View style={{ padding: 0, }}>
{/* <TouchableOpacity style={[AppStyles.dashboardCard, {}]}
onPress={this.toAssessmentScreen.bind(this, item)}>
<View style={{ flexDirection: 'column', margin: 10 }}>
<Text style={[AppStyles.nameLabel, BaseStyles.font18, BaseStyles.font700Bold, BaseStyles.marBottom5,]}>{item?.question_paper_name} </Text>
</View>
<View>
<TouchableOpacity style={[AppStyles.dashboardQuickLinks, { backgroundColor: BaseColors.lightRed, }]} activeOpacity={0.8} onPress={this.toAssessmentScreen.bind(this, item)}>
<Text style={[BaseStyles.font14, BaseStyles.font700Bold, { color: BaseColors.red, textAlign: 'center' }]}>View</Text>
</TouchableOpacity>
</View>
</TouchableOpacity> */}
<TouchableOpacity style={styles.item} onPress={this.toAssessmentScreen.bind(this, item)}>
<Text style={[AppStyles.nameLabel, BaseStyles.font18, BaseStyles.font700Bold, BaseStyles.marBottom5,]}>{item?.question_paper_name} </Text>
</TouchableOpacity>
</View>
)
render() {
return (<View style={[AppStyles.containerWoPadding, {}]}>
{!this.props.loading && this.props.records && <FlatList
style={{ marginVertical: 12, marginHorizontal: 16 }}
data={this.props.records}
renderItem={this.renderRow}
keyExtractor={(item, index) => index.toString()}
/>
}
{this.props.loading && <View style={[BaseStyles.marVertical20, { flex: 1, justifyContent: 'center' }]}>
<ActivityIndicator size="large" color="#7165e3" />
</View>}
</View>)
}
}
const styles = StyleSheet.create({
item: {
padding: 16,
backgroundColor: '#fff',
marginBottom: 8,
borderRadius: 8,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.3,
shadowRadius: 2,
elevation: 2,
},
})
const mapStateToProps = (state: any) => ({
loading: state.psychometric.loading,
error: state.quizzes.error,
info: state.quizzes.info,
isLoading: state.students.loading,
questionPaperList: state.questionbank.question_paper,
records: state.questionbank.records,
})
const mapDispatchToProps = (dispatch: any) => ({
initQuizzes: (user: any) => {
dispatch(ActionCreators.initQuizzesAction(user))
},
getQuestionPaperList: (user: any) => {
dispatch(ActionCreators.getQuestionPaperPaginationAction(user))
},
})
QuestionBank.propTypes = {
loading: PropTypes.bool,
error: PropTypes.object,
info: PropTypes.object,
}
export default connect(mapStateToProps, mapDispatchToProps)(QuestionBank)

View File

@ -3921,6 +3921,11 @@ balanced-match@^1.0.0:
resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
base-64@^0.1.0:
version "0.1.0"
resolved "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz"
integrity sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA==
base64-js@^1.2.3, base64-js@^1.3.1, base64-js@^1.5.1:
version "1.5.1"
resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz"
@ -5519,10 +5524,10 @@ expo-asset@~9.0.2:
invariant "^2.2.4"
md5-file "^3.2.3"
expo-camera@^15.0.14:
version "15.0.14"
resolved "https://registry.npmjs.org/expo-camera/-/expo-camera-15.0.14.tgz"
integrity sha512-O4uvVywGsQ3a89d0BX4lq6mDuGYGukx1PYY4QrC9zw1yzD2W9BVTl8lanFRPC5h4PRniekfeWUVH1a0jJmkLIw==
expo-camera@^14.1.3:
version "14.1.3"
resolved "https://registry.npmjs.org/expo-camera/-/expo-camera-14.1.3.tgz"
integrity sha512-JodpVjOY8JDuSp/RkphS8Bxqaj/gwg0h0UbQB9MLr1LoxbL9brvJt7IZnmTf7+ON8jRKUx9E5o/F02pRNbmSbQ==
dependencies:
invariant "^2.2.4"
@ -9077,10 +9082,15 @@ react-native-charts-wrapper@^0.6.0:
prop-types "^15.8.1"
react "16.13.1"
react-native-document-scanner-plugin@^0.9.1:
version "0.9.1"
resolved "https://registry.npmjs.org/react-native-document-scanner-plugin/-/react-native-document-scanner-plugin-0.9.1.tgz"
integrity sha512-iHqd/ZEHmKnPsA0X2DoSZ7B324WSDQO45I22busHHfc2vSRMHozP9fcIP34YTuNvfbvjJFhziCIw66YcGWLotA==
react-native-document-scanner-plugin@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/react-native-document-scanner-plugin/-/react-native-document-scanner-plugin-1.0.0.tgz"
integrity sha512-dDsSclFpxl4U0Bnz/oEE0OEEqEjA6zNCu/2lmls4lslq3JqgHacI8xEl5DygMHd4AlDj3X4g1yKUacllfaC+UA==
react-native-fetch-polyfill@^1.1.3:
version "1.1.3"
resolved "https://registry.npmjs.org/react-native-fetch-polyfill/-/react-native-fetch-polyfill-1.1.3.tgz"
integrity sha512-zr5yXQftuGq+ABGa3n4ZE+vkL1lBsMSePkRINm3/6vlpbwnLXYoijwazTO/W8GjsV4LAgGmzuieZxKO/NxW19A==
react-native-flash-message@^0.4.2:
version "0.4.2"
@ -9090,6 +9100,14 @@ react-native-flash-message@^0.4.2:
prop-types "^15.8.1"
react-native-iphone-screen-helper "^2.0.2"
react-native-fs@^2.20.0:
version "2.20.0"
resolved "https://registry.npmjs.org/react-native-fs/-/react-native-fs-2.20.0.tgz"
integrity sha512-VkTBzs7fIDUiy/XajOSNk0XazFE9l+QlMAce7lGuebZcag5CnjszB+u4BdqzwaQOdcYb5wsJIsqq4kxInIRpJQ==
dependencies:
base-64 "^0.1.0"
utf8 "^3.0.0"
react-native-gesture-handler@^2.15.0, "react-native-gesture-handler@>= 1.0.0", "react-native-gesture-handler@>= 1.5.0":
version "2.15.0"
resolved "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.15.0.tgz"
@ -9292,7 +9310,7 @@ react-native-webview@^13.8.1, "react-native-webview@>= 10.9.0":
escape-string-regexp "2.0.0"
invariant "2.2.4"
react-native@*, react-native@^*, "react-native@^0.0.0-0 || >=0.60 <1.0", "react-native@>= 0.30.0", "react-native@>= 0.50.0", "react-native@>= 0.60.0", "react-native@>= 0.64.3", react-native@>=0.42.0, react-native@>=0.56, react-native@>=0.57, react-native@>=0.59, react-native@>=0.61, react-native@>=0.61.3, react-native@>=0.61.5, react-native@>=0.65.0, react-native@>=0.69, react-native@>=0.71.0, react-native@>0.57.0, react-native@0.73.5:
react-native@*, react-native@^*, "react-native@^0.0.0-0 || >=0.60 <1.0", "react-native@>= 0.30.0", "react-native@>= 0.50.0", "react-native@>= 0.60.0", "react-native@>= 0.64.3", react-native@>=0.27, react-native@>=0.42.0, react-native@>=0.56, react-native@>=0.57, react-native@>=0.59, react-native@>=0.61, react-native@>=0.61.3, react-native@>=0.61.5, react-native@>=0.65.0, react-native@>=0.69, react-native@>=0.71.0, react-native@>0.57.0, react-native@0.73.5:
version "0.73.5"
resolved "https://registry.npmjs.org/react-native/-/react-native-0.73.5.tgz"
integrity sha512-iHgDArmF4CrhL0qTj+Rn+CBN5pZWUL9lUGl8ub+V9Hwu/vnzQQh8rTMVSwVd2sV6N76KjpE5a4TfIAHkpIHhKg==
@ -10874,6 +10892,11 @@ use-sync-external-store@^1.0.0:
resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz"
integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
utf8@^3.0.0:
version "3.0.0"
resolved "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz"
integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
@ -11317,6 +11340,11 @@ websocket-extensions@>=0.1.1:
resolved "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz"
integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==
whatwg-fetch-timeout@^2.0.2-timeout:
version "2.0.2-timeout"
resolved "https://registry.npmjs.org/whatwg-fetch-timeout/-/whatwg-fetch-timeout-2.0.2-timeout.tgz"
integrity sha512-1y8WJdP1DaBXbAp9Ez8Um2Ft7iTVopOwUgnyiJPYIsWir1HuJBBxSYdvEtskQx+r/L1WMWQQxbcS8lHubCHtBw==
whatwg-fetch@^3.0.0:
version "3.6.20"
resolved "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz"