bug fixes and homestudy, calendar

This commit is contained in:
Menaka 2024-11-07 10:09:13 +05:30
parent e220baad72
commit 7c050e94d2
73 changed files with 3287 additions and 291 deletions

View File

@ -86,7 +86,7 @@ android {
applicationId "com.tedqu"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 2
versionCode 4
versionName "1.0"
}
signingConfigs {

View File

@ -64,7 +64,7 @@
"BASE_URL": "https://dev.wizdomwaves.in",
"AUTH_BASE_URL": "https://dev-auth.wizdomwaves.in/auth",
"APP_BASE_URL": "https://dev-api.wizdomwaves.in/api",
"LICENSE_BASE_URL": "http://213.210.36.103",
"LICENSE_BASE_URL": "http://admin.wizdomedge.in",
"APP_VERSION": "2.0",
"APP_DATE" : "27-03-2023"
}

View File

@ -1120,6 +1120,10 @@ PODS:
- React-debug
- react-native-artag-module (0.1.2):
- React-Core
- react-native-audio-waveform (2.0.0):
- glog
- RCT-Folly (= 2022.05.16.00)
- React-Core
- react-native-charts-wrapper (0.6.0):
- DGCharts (= 5.0.0)
- React
@ -1322,6 +1326,8 @@ PODS:
- React-jsi (= 0.73.5)
- React-logger (= 0.73.5)
- React-perflogger (= 0.73.5)
- RNAudioRecorderPlayer (3.6.11):
- React-Core
- RNCAsyncStorage (1.23.1):
- React-Core
- RNCPicker (2.4.10):
@ -1435,6 +1441,7 @@ DEPENDENCIES:
- React-logger (from `../node_modules/react-native/ReactCommon/logger`)
- React-Mapbuffer (from `../node_modules/react-native/ReactCommon`)
- react-native-artag-module (from `../node_modules/react-native-artag-module`)
- "react-native-audio-waveform (from `../node_modules/@simform_solutions/react-native-audio-waveform`)"
- react-native-charts-wrapper (from `../node_modules/react-native-charts-wrapper`)
- react-native-document-scanner-plugin (from `../node_modules/react-native-document-scanner-plugin`)
- react-native-get-random-values (from `../node_modules/react-native-get-random-values`)
@ -1466,6 +1473,7 @@ DEPENDENCIES:
- React-runtimescheduler (from `../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`)
- React-utils (from `../node_modules/react-native/ReactCommon/react/utils`)
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
- RNAudioRecorderPlayer (from `../node_modules/react-native-audio-recorder-player`)
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
- "RNCPicker (from `../node_modules/@react-native-picker/picker`)"
- "RNDateTimePicker (from `../node_modules/@react-native-community/datetimepicker`)"
@ -1598,6 +1606,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon"
react-native-artag-module:
:path: "../node_modules/react-native-artag-module"
react-native-audio-waveform:
:path: "../node_modules/@simform_solutions/react-native-audio-waveform"
react-native-charts-wrapper:
:path: "../node_modules/react-native-charts-wrapper"
react-native-document-scanner-plugin:
@ -1660,6 +1670,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/react/utils"
ReactCommon:
:path: "../node_modules/react-native/ReactCommon"
RNAudioRecorderPlayer:
:path: "../node_modules/react-native-audio-recorder-player"
RNCAsyncStorage:
:path: "../node_modules/@react-native-async-storage/async-storage"
RNCPicker:
@ -1752,6 +1764,7 @@ SPEC CHECKSUMS:
React-logger: 0331362115f0f5b392bd7ed14636d1a3ea612479
React-Mapbuffer: 7c35cd53a22d0be04d3f26f7881c7fb7dd230216
react-native-artag-module: 26e75d6c05a34c2486a9f31ac03a06dae5169ba2
react-native-audio-waveform: 33e59ae0cc4a98258f00ad9fedf76c7b5c532d97
react-native-charts-wrapper: cd83d9b1acb8e06ebd18bf297de597906e1cc87d
react-native-document-scanner-plugin: 0687a1d8eaff9dac01dd2799993590831f8f8bcb
react-native-get-random-values: dee677497c6a740b71e5612e8dbd83e7539ed5bb
@ -1783,6 +1796,7 @@ SPEC CHECKSUMS:
React-runtimescheduler: 814b644a5f456c7df1fba7bcd9914707152527c6
React-utils: 987a4526a2fc0acdfaf87888adfe0bf9d0452066
ReactCommon: 2947b0bffd82ea0e58ca7928881152d4c6dae9af
RNAudioRecorderPlayer: 0208ee1f2e19ec027552bea44b1ae682f187ed54
RNCAsyncStorage: 826b603ae9c0f88b5ac4e956801f755109fa4d5c
RNCPicker: 0bc2f0a29abcca7b7ed44a2d036aac9ab6d25700
RNDateTimePicker: 3942382593f104af226ad9c56e16166960c7ae30

View File

@ -66,6 +66,8 @@
6FA5668B2C53B56700A90A30 /* TedQu-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TedQu-Bridging-Header.h"; sourceTree = "<group>"; };
6FA566952C54163800A90A30 /* ArtagViewManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ArtagViewManager.m; sourceTree = "<group>"; };
6FA566972C54164700A90A30 /* ArtagViewManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArtagViewManager.swift; sourceTree = "<group>"; };
6FE2C3252CDBA02900023F2B /* libRNAudioRecorderPlayer.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libRNAudioRecorderPlayer.a; sourceTree = BUILT_PRODUCTS_DIR; };
6FE2C3282CDBA12E00023F2B /* libRNAudioRecorderPlayer.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libRNAudioRecorderPlayer.a; sourceTree = BUILT_PRODUCTS_DIR; };
6FE89CA92C57B989009C7421 /* CameraView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraView.swift; sourceTree = "<group>"; };
6FEDAA102C1970B7006C933B /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = TedQu/LaunchScreen.storyboard; sourceTree = "<group>"; };
@ -144,6 +146,8 @@
2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
isa = PBXGroup;
children = (
6FE2C3282CDBA12E00023F2B /* libRNAudioRecorderPlayer.a */,
6FE2C3252CDBA02900023F2B /* libRNAudioRecorderPlayer.a */,
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
F01D516ED451E6AA2CCCA8C1 /* libPods-TedQu.a */,
21D0D32D10D3A1EF94B83556 /* libPods-TedQu-TedQuTests.a */,

View File

@ -32,7 +32,16 @@
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>213.210.36.103</key>
<key>admin.wizdomedge.in</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSTemporaryExceptionMinimumTLSVersion</key>
<string>TLSv1.1</string>
</dict>
<key>127.0.0.1</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>

63
package-lock.json generated
View File

@ -24,6 +24,7 @@
"@react-navigation/native-stack": "^6.9.17",
"@react-navigation/stack": "^6.3.20",
"@reduxjs/toolkit": "^2.2.5",
"@simform_solutions/react-native-audio-waveform": "^2.0.0",
"@types/react-native-calendars": "^1.1264.7",
"@types/react-native-tags": "^2.2.5",
"@types/react-redux": "^7.1.33",
@ -54,7 +55,9 @@
"react-native": "0.73.5",
"react-native-app-intro-slider": "^4.0.4",
"react-native-artag-module": "file:../06_Installables/react-native-artag-module-0.1.4.tgz",
"react-native-audio-recorder-player": "^3.6.11",
"react-native-autoheight-webview": "^1.6.5",
"react-native-big-calendar": "^4.15.0",
"react-native-calendars": "^1.1303.0",
"react-native-chart-kit": "^6.12.0",
"react-native-charts-wrapper": "^0.6.0",
@ -7562,6 +7565,18 @@
"resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz",
"integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ=="
},
"node_modules/@simform_solutions/react-native-audio-waveform": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@simform_solutions/react-native-audio-waveform/-/react-native-audio-waveform-2.0.0.tgz",
"integrity": "sha512-ImkFXoOoec6rgrx0Bo1j/ag1/eXiUKbs2QK7oLBQ8BSRO5BGXJLIMc6OcV4bA//2ggK3UiTSxaRW9y0avnE5nQ==",
"dependencies": {
"lodash": "^4.17.21"
},
"peerDependencies": {
"react": "*",
"react-native": "*"
}
},
"node_modules/@sinclair/typebox": {
"version": "0.27.8",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
@ -9227,6 +9242,14 @@
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"node_modules/calendarize": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/calendarize/-/calendarize-1.1.1.tgz",
"integrity": "sha512-C2JyBAtNp2NG4DX4fA1EILggLt/5PlYzvQR0crHktoAPBc9TlIfdhzg7tWekCbe+pH6+9qoK+FhPbi+vYJJlqw==",
"engines": {
"node": ">=8"
}
},
"node_modules/call-bind": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
@ -10125,9 +10148,9 @@
"integrity": "sha512-+LSAiGFwQ9dRnRdOeaj7g47ZFJcOUPukAP8J3A3fuZ1g9Y44BG+P1sgApjLXTQPOzC4+7S9Wr8kXsfpINM4jpw=="
},
"node_modules/dayjs": {
"version": "1.11.10",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz",
"integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ=="
"version": "1.11.13",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
"integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg=="
},
"node_modules/debug": {
"version": "4.3.4",
@ -10554,6 +10577,15 @@
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/dooboolab-welcome": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/dooboolab-welcome/-/dooboolab-welcome-1.3.2.tgz",
"integrity": "sha512-2NbMaIIURElxEf/UAoVUFlXrO+7n/FRhLCiQlk4fkbGRh9cJ3/f8VEMPveR9m4Ug2l2Zey+UCXjd6EcBqHJ5bw==",
"hasInstallScript": true,
"bin": {
"dooboolab-welcome": "bin/hello.js"
}
},
"node_modules/dotenv": {
"version": "16.0.3",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz",
@ -18740,6 +18772,18 @@
"react-native": "*"
}
},
"node_modules/react-native-audio-recorder-player": {
"version": "3.6.11",
"resolved": "https://registry.npmjs.org/react-native-audio-recorder-player/-/react-native-audio-recorder-player-3.6.11.tgz",
"integrity": "sha512-IHr0PWbwDKCPnTuzlXSAZhejFdtoAV6gyhRxli7aHH1tDT+9akIAToCzVdZxdmbg+vN5vFp4PNYJ30hg3pFV1w==",
"dependencies": {
"dooboolab-welcome": "^1.3.2"
},
"peerDependencies": {
"react": "*",
"react-native": "*"
}
},
"node_modules/react-native-autoheight-webview": {
"version": "1.6.5",
"resolved": "https://registry.npmjs.org/react-native-autoheight-webview/-/react-native-autoheight-webview-1.6.5.tgz",
@ -18764,6 +18808,19 @@
"prop-types": "*"
}
},
"node_modules/react-native-big-calendar": {
"version": "4.15.0",
"resolved": "https://registry.npmjs.org/react-native-big-calendar/-/react-native-big-calendar-4.15.0.tgz",
"integrity": "sha512-hMsC3dG3LqatnJ375bXNhQDSPbWk8/v4oGG003DcqLlTDRu33f7/2MhgF8+9hD6+GgCN+1JYdtQuABL8bhSd0A==",
"dependencies": {
"calendarize": "^1.1.1",
"dayjs": "^1.11.13"
},
"peerDependencies": {
"react": "*",
"react-native": "*"
}
},
"node_modules/react-native-button": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/react-native-button/-/react-native-button-2.4.0.tgz",

View File

@ -26,6 +26,7 @@
"@react-navigation/native-stack": "^6.9.17",
"@react-navigation/stack": "^6.3.20",
"@reduxjs/toolkit": "^2.2.5",
"@simform_solutions/react-native-audio-waveform": "^2.0.0",
"@types/react-native-calendars": "^1.1264.7",
"@types/react-native-tags": "^2.2.5",
"@types/react-redux": "^7.1.33",
@ -56,7 +57,9 @@
"react-native": "0.73.5",
"react-native-app-intro-slider": "^4.0.4",
"react-native-artag-module": "file:../06_Installables/react-native-artag-module-0.1.4.tgz",
"react-native-audio-recorder-player": "^3.6.11",
"react-native-autoheight-webview": "^1.6.5",
"react-native-big-calendar": "^4.15.0",
"react-native-calendars": "^1.1303.0",
"react-native-chart-kit": "^6.12.0",
"react-native-charts-wrapper": "^0.6.0",

View File

@ -0,0 +1,84 @@
import {
GET_HOME_STUDY_LIST_REQUEST, GET_HOME_STUDY_LIST_SUCCESS, GET_HOME_STUDY_LIST_FAILURE,
GET_HOME_STUDY_TRANSACTION_DETAILS_REQUEST, GET_HOME_STUDY_TRANSACTION_DETAILS_SUCCESS, GET_HOME_STUDY_TRANSACTION_DETAILS_FAILURE,
GET_HOME_STUDY_STUDENTS_LIST_REQUEST, GET_HOME_STUDY_STUDENTS_LIST_SUCCESS, GET_HOME_STUDY_STUDENTS_LIST_FAILURE,
GENERATE_HOME_STUDY_RANDOM_QUESTION_REQUEST, GENERATE_HOME_STUDY_RANDOM_QUESTION_SUCCESS, GENERATE_HOME_STUDY_RANDOM_QUESTION_FAILURE,
ADD_HOME_STUDY_TRANSACTION_REQUEST, ADD_HOME_STUDY_TRANSACTION_SUCCESS, ADD_HOME_STUDY_TRANSACTION_FAILURE
} from './type'
/** Diary Actions */
export const getHomeStudyListAction = (data: any) => ({
type: GET_HOME_STUDY_LIST_REQUEST,
data
})
export const getHomeStudyListSuccess = (data: any) => ({
type: GET_HOME_STUDY_LIST_SUCCESS,
data
})
export const getHomeStudyListFailure = (error: any) => ({
type: GET_HOME_STUDY_LIST_FAILURE,
error
})
export const getHomeStudyTransactionDetailsAction = (data: any) => ({
type: GET_HOME_STUDY_TRANSACTION_DETAILS_REQUEST,
data
})
export const getHomeStudyTransactionDetailsSuccess = (data: any) => ({
type: GET_HOME_STUDY_TRANSACTION_DETAILS_SUCCESS,
data
})
export const getHomeStudyTransactionDetailsFailure = (error: any) => ({
type: GET_HOME_STUDY_TRANSACTION_DETAILS_FAILURE,
error
})
export const getHomeStudyStudentsListAction = (data: any) => ({
type: GET_HOME_STUDY_STUDENTS_LIST_REQUEST,
data
})
export const getHomeStudyStudentsListSuccess = (data: any) => ({
type: GET_HOME_STUDY_STUDENTS_LIST_SUCCESS,
data
})
export const getHomeStudyStudentsListFailure = (error: any) => ({
type: GET_HOME_STUDY_STUDENTS_LIST_FAILURE,
error
})
export const generateHomeStudyRandomQuestionAction = (data: any) => ({
type: GENERATE_HOME_STUDY_RANDOM_QUESTION_REQUEST,
data
})
export const generateHomeStudyRandomQuestionSuccess = (data: any) => ({
type: GENERATE_HOME_STUDY_RANDOM_QUESTION_SUCCESS,
data
})
export const generateHomeStudyRandomQuestionFailure = (error: any) => ({
type: GENERATE_HOME_STUDY_RANDOM_QUESTION_FAILURE,
error
})
export const addHomeStudyTransactionAction = (data: any) => ({
type: ADD_HOME_STUDY_TRANSACTION_REQUEST,
data
})
export const addHomeStudyTransactionSuccess = (data: any) => ({
type: ADD_HOME_STUDY_TRANSACTION_SUCCESS,
data
})
export const addHomeStudyTransactionFailure = (error: any) => ({
type: ADD_HOME_STUDY_TRANSACTION_FAILURE,
error
})

View File

@ -14,6 +14,7 @@ import * as Quizzes from './quizzes.action'
import * as Psychometric from './psychometric.action'
import * as License from './license.action'
import * as QuestionBank from './questionbank.action'
import * as HomeStudy from './homestudy.action'
export const ActionCreators = {
...Users,
@ -30,5 +31,6 @@ export const ActionCreators = {
...Quizzes,
...Psychometric,
...License,
...QuestionBank
...QuestionBank,
...HomeStudy
}

View File

@ -11,7 +11,8 @@ import {
CREATE_ASSESSMENT_SCAN_ANSWERS_REQUEST,CREATE_ASSESSMENT_SCAN_ANSWERS_SUCCESS, CREATE_ASSESSMENT_SCAN_ANSWERS_FALURE,
GET_BLUEPRINT_LESSON_DROPDOWN_REQUEST, GET_BLUEPRINT_LESSON_DROPDOWN_SUCCESS, GET_BLUEPRINT_LESSON_DROPDOWN_FAILURE,
GET_BLUEPRINT_DIFFICULTY_LEVEL_DROPDOWN_REQUEST, GET_BLUEPRINT_DIFFICULTY_LEVEL_DROPDOWN_SUCCESS, GET_BLUEPRINT_DIFFICULTY_LEVEL_DROPDOWN_FAILURE,
GET_QUIZ_RANDOM_QUESTION_REQUEST, GET_QUIZ_RANDOM_QUESTION_SUCCESS, GET_QUIZ_RANDOM_QUESTION_FAILURE
GET_QUIZ_RANDOM_QUESTION_REQUEST, GET_QUIZ_RANDOM_QUESTION_SUCCESS, GET_QUIZ_RANDOM_QUESTION_FAILURE,
GET_BLUEPRINT_SUBJECT_DROPDOWN_REQUEST, GET_BLUEPRINT_SUBJECT_DROPDOWN_SUCCESS, GET_BLUEPRINT_SUBJECT_DROPDOWN_FAILURE
} from './type'
export const initAssessmentAction = () => ({
@ -153,6 +154,21 @@ import {
error
})
export const getBlueprintSubjectDropdownAction = (data: any) => ({
type: GET_BLUEPRINT_SUBJECT_DROPDOWN_REQUEST,
data
})
export const getBlueprintSubjectDropdownSuccess = (data: any) => ({
type: GET_BLUEPRINT_SUBJECT_DROPDOWN_SUCCESS,
data
})
export const getBlueprintSubjectDropdownFailure = (error: any) => ({
type: GET_BLUEPRINT_SUBJECT_DROPDOWN_FAILURE,
error
})
export const getBlueprintLessonDropdownAction = (data: any) => ({
type: GET_BLUEPRINT_LESSON_DROPDOWN_REQUEST,
data

View File

@ -1,5 +1,6 @@
import { GET_SCHOOL_DETAILS, GET_SCHOOL_DETAILS_SUCCESS, GET_SCHOOL_DETAILS_FAILURE, UPDATE_SCHOOL_INFO,
UPDATE_SCHOOL_INFO_SUCCESS, UPDATE_SCHOOL_INFO_FAILURE, GET_SCHOOL_CATEGORY, GET_SCHOOL_CATEGORY_SUCCESS, GET_SCHOOL_CATEGORY_FAILURE } from './type'
UPDATE_SCHOOL_INFO_SUCCESS, UPDATE_SCHOOL_INFO_FAILURE, GET_SCHOOL_CATEGORY, GET_SCHOOL_CATEGORY_SUCCESS, GET_SCHOOL_CATEGORY_FAILURE,
GET_CALENDAR_REQUEST, GET_CALENDAR_SUCCESS, GET_CALENDAR_FAILURE, GET_GREETINGS_SUCCESS, GET_GREETINGS_REQUEST, GET_GREETINGS_FAILURE} from './type'
/** School Type Action */
export const getSchoolInfoAction = (data: any) => ({
@ -46,3 +47,33 @@ export const getSchoolCategoryFailure = (error: any) => ({
type: GET_SCHOOL_CATEGORY_FAILURE,
error
})
export const getCalendarAction = (data: any) => ({
type: GET_CALENDAR_REQUEST,
data
})
export const getCalendarSuccess = (data: any) => ({
type: GET_CALENDAR_SUCCESS,
data
})
export const getCalendarFailure = (error: any) => ({
type: GET_CALENDAR_FAILURE,
error
})
export const getGreetingsAction = (data: any) => ({
type: GET_GREETINGS_REQUEST,
data
})
export const getGreetingSuccess = (data: any) => ({
type: GET_GREETINGS_SUCCESS,
data
})
export const getGreetingFailure = (error: any) => ({
type: GET_GREETINGS_FAILURE,
error
})

View File

@ -64,6 +64,14 @@ export const GET_SCHOOL_CATEGORY = 'GET_SCHOOL_CATEGORY'
export const GET_SCHOOL_CATEGORY_SUCCESS = 'GET_SCHOOL_CATEGORY_SUCCESS'
export const GET_SCHOOL_CATEGORY_FAILURE = 'GET_SCHOOL_CATEGORY_FAILURE'
export const GET_CALENDAR_REQUEST = 'GET_CALENDAR_REQUEST'
export const GET_CALENDAR_SUCCESS = 'GET_CALENDAR_SUCCESS'
export const GET_CALENDAR_FAILURE = 'GET_CALENDAR_FAILURE'
export const GET_GREETINGS_REQUEST = 'GET_GREETINGS_REQUEST'
export const GET_GREETINGS_SUCCESS = 'GET_GREETINGS_SUCCESS'
export const GET_GREETINGS_FAILURE = 'GET_GREETINGS_FAILURE'
/** Class Type Action */
export const INIT_CLASS_MODULE = 'INIT_CLASS_MODULE'
export const GET_GRADE_REQUEST = 'GET_GRADE_REQUEST'
@ -426,6 +434,10 @@ export const CREATE_ASSESSMENT_SCAN_ANSWERS_REQUEST = 'CREATE_ASSESSMENT_SCAN_AN
export const CREATE_ASSESSMENT_SCAN_ANSWERS_SUCCESS = 'CREATE_ASSESSMENT_SCAN_ANSWERS_SUCCESS'
export const CREATE_ASSESSMENT_SCAN_ANSWERS_FALURE = 'CREATE_ASSESSMENT_SCAN_ANSWERS_FALURE'
export const GET_BLUEPRINT_SUBJECT_DROPDOWN_REQUEST = 'GET_BLUEPRINT_SUBJECT_DROPDOWN_REQUEST'
export const GET_BLUEPRINT_SUBJECT_DROPDOWN_SUCCESS = 'GET_BLUEPRINT_SUBJECT_DROPDOWN_SUCCESS'
export const GET_BLUEPRINT_SUBJECT_DROPDOWN_FAILURE = 'GET_BLUEPRINT_SUBJECT_DROPDOWN_FAILURE'
export const GET_BLUEPRINT_LESSON_DROPDOWN_REQUEST = 'GET_BLUEPRINT_LESSON_DROPDOWN_REQUEST'
export const GET_BLUEPRINT_LESSON_DROPDOWN_SUCCESS = 'GET_BLUEPRINT_LESSON_DROPDOWN_SUCCESS'
export const GET_BLUEPRINT_LESSON_DROPDOWN_FAILURE = 'GET_BLUEPRINT_LESSON_DROPDOWN_FAILURE'
@ -437,3 +449,23 @@ export const GET_BLUEPRINT_DIFFICULTY_LEVEL_DROPDOWN_FAILURE = 'GET_BLUEPRINT_DI
export const GET_QUIZ_RANDOM_QUESTION_REQUEST = 'GET_QUIZ_RANDOM_QUESTION_REQUEST'
export const GET_QUIZ_RANDOM_QUESTION_SUCCESS = 'GET_QUIZ_RANDOM_QUESTION_SUCCESS'
export const GET_QUIZ_RANDOM_QUESTION_FAILURE = 'GET_QUIZ_RANDOM_QUESTION_FAILURE'
export const GET_HOME_STUDY_LIST_REQUEST = 'GET_HOME_STUDY_LIST_REQUEST'
export const GET_HOME_STUDY_LIST_SUCCESS = 'GET_HOME_STUDY_LIST_SUCCESS'
export const GET_HOME_STUDY_LIST_FAILURE = 'GET_HOME_STUDY_LIST_FAILURE'
export const GET_HOME_STUDY_TRANSACTION_DETAILS_REQUEST = 'GET_HOME_STUDY_TRANSACTION_DETAILS_REQUEST'
export const GET_HOME_STUDY_TRANSACTION_DETAILS_SUCCESS = 'GET_HOME_STUDY_TRANSACTION_DETAILS_SUCCESS'
export const GET_HOME_STUDY_TRANSACTION_DETAILS_FAILURE = 'GET_HOME_STUDY_TRANSACTION_DETAILS_FAILURE'
export const GET_HOME_STUDY_STUDENTS_LIST_REQUEST = 'GET_HOME_STUDY_STUDENTS_LIST_REQUEST'
export const GET_HOME_STUDY_STUDENTS_LIST_SUCCESS = 'GET_HOME_STUDY_STUDENTS_LIST_SUCCESS'
export const GET_HOME_STUDY_STUDENTS_LIST_FAILURE = 'GET_HOME_STUDY_STUDENTS_LIST_FAILURE'
export const GENERATE_HOME_STUDY_RANDOM_QUESTION_REQUEST = 'GENERATE_HOME_STUDY_RANDOM_QUESTION_REQUEST'
export const GENERATE_HOME_STUDY_RANDOM_QUESTION_SUCCESS = 'GENERATE_HOME_STUDY_RANDOM_QUESTION_SUCCESS'
export const GENERATE_HOME_STUDY_RANDOM_QUESTION_FAILURE = 'GENERATE_HOME_STUDY_RANDOM_QUESTION_FAILURE'
export const ADD_HOME_STUDY_TRANSACTION_REQUEST = 'ADD_HOME_STUDY_TRANSACTION_REQUEST'
export const ADD_HOME_STUDY_TRANSACTION_SUCCESS = 'ADD_HOME_STUDY_TRANSACTION_SUCCESS'
export const ADD_HOME_STUDY_TRANSACTION_FAILURE = 'ADD_HOME_STUDY_TRANSACTION_FAILURE'

49
src/api/homestudy.api.tsx Normal file
View File

@ -0,0 +1,49 @@
import { HOME_STUDY_API } from '@config/Config' //NOSONAR
import { apiConfig, fetchAppBase } from '@constants/Constants' //NOSONAR
export const getHomeStudyList = async ({token, academic_year, student_id, page_no, class_id, search}: any) => {
const requestOptions = {
method: 'GET',
headers: { 'Content-Type': apiConfig.contentTypeJSON, 'Authorization': token },
}
const url = `${HOME_STUDY_API.GET_HOME_STUDY_LIST}/?academic_year=${academic_year}&class_id=${class_id}&student_id=${student_id}&page_no=${page_no}&search=${search}`
return fetchAppBase(url, requestOptions)
}
export const getHomeStudyTransactionDetails = async ({token, academic_year, uid}: any) => {
const requestOptions = {
method: 'GET',
headers: { 'Content-Type': apiConfig.contentTypeJSON, 'Authorization': token },
}
const url = `${HOME_STUDY_API.GET_TRANSACTION_DETAILS}/?uid=${uid}`
return fetchAppBase(url, requestOptions)
}
export const getHomeStudyStudentsList = async ({token, academic_year, class_id, subject_id}: any) => {
const requestOptions = {
method: 'GET',
headers: { 'Content-Type': apiConfig.contentTypeJSON, 'Authorization': token },
}
const url = `${HOME_STUDY_API.GET_HOME_STUDY_STUDENTS_LIST}/?academic_year=${academic_year}&class_id=${class_id}&subject_id=${subject_id}`
return fetchAppBase(url, requestOptions)
}
export const generateHomeStudyRandomQuestion = async ({token, data}: any) => {
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': apiConfig.contentTypeJSON, 'Authorization': token },
body: JSON.stringify(data)
}
const url = `${HOME_STUDY_API.GENERATE_HOME_STUDY_RANDOM_QUESTION}/`
return fetchAppBase(url, requestOptions)
}
export const addHomeStudyTransaction = async ({token, data}: any) => {
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': apiConfig.contentTypeJSON, 'Authorization': token },
body: JSON.stringify(data)
}
const url = `${HOME_STUDY_API.ADD_TRANSACTION}/`
return fetchAppBase(url, requestOptions)
}

View File

@ -22,14 +22,11 @@ export const getAllAssessmentList = async ({token, academic_year, question_paper
}
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)
}
@ -57,7 +54,6 @@ export const getAssessmentStudentList = async ({token, academic_year, question_p
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)
}
@ -88,8 +84,16 @@ export const createAssessmentScanAnswer = ({ data, token }: any) => {
headers: { 'Content-Type': 'multipart/form-data; ', 'Authorization': token },
body: data
}
console.log(data)
const url = `${QUESTION_BANK_API.ASSESSMENT_SCAN_ANSWERS}`
const url = `${QUESTION_BANK_API.ASSESSMENT_SCAN_ANSWERS}/`
return fetchAppBase(url, requestOptions)
}
export const getBlueprintSubjectDropdown = async ({token, academic_year, internal_grade_id}: any) => {
const requestOptions = {
method: 'GET',
headers: { 'Content-Type': apiConfig.contentTypeJSON, 'Authorization': token },
}
const url = `${QUESTION_BANK_API.GET_BLUEPRINT_SUBJECT_DROPDOWN}/?academic_year=${academic_year}&internal_grade_id=${internal_grade_id}`
return fetchAppBase(url, requestOptions)
}

View File

@ -34,3 +34,22 @@ export const getSchoolCategorys = ({token}: any) => {
const url = SCHOOLAPI.GET_SCHOOL_CATEGORY
return fetchAppBase(url, requestOptions)
}
export const getCalendarEvents = ({token, data={}}: any) => {
const requestOptions = {
method: 'PATCH',
headers: { 'Content-Type': apiConfig.contentTypeJSON, 'Authorization': token },
body: JSON.stringify(data)
}
const url = `${SCHOOLAPI.GET_SCHOOL_CALENDAR}?academic_year=${data.academic_year}&grade=${data.grade}`
return fetchAppBase(url, requestOptions)
}
export const getGreetings = ({token, academic_year}: any) => {
const requestOptions = {
method: 'GET',
headers: { 'Content-Type': apiConfig.contentTypeJSON, 'Authorization': token },
}
const url = `${SCHOOLAPI.GET_GREETINGS}?academic_year=${academic_year}`
return fetchAppBase(url, requestOptions)
}

View File

@ -48,7 +48,8 @@ export const getTeacherPerfomanceBySubject = ({ token, teacher_id, academic_year
method: 'GET',
headers: { 'Content-Type': apiConfig.contentTypeJSON, 'Authorization': token }
}
const url = `${TEACHERAPI.TEACHER_PERFOMANCE_BY_SUBJECT}?academic_year=${academic_year}&teacher_id=${teacher_id}`
const url = `${TEACHERAPI.TEACHER_PERFOMANCE_BY_SUBJECT}/?academic_year=${academic_year}&teacher_id=${teacher_id}`
return fetchAppBase(url, requestOptions)
}
@ -57,7 +58,7 @@ export const getTeacherPerfomanceByTopic = ({ token, teacher_id, academic_year }
method: 'GET',
headers: { 'Content-Type': apiConfig.contentTypeJSON, 'Authorization': token }
}
const url = `${TEACHERAPI.TEACHER_PERFOMANCE_BY_TOPIC}?academic_year=${academic_year}&teacher_id=${teacher_id}`
const url = `${TEACHERAPI.TEACHER_PERFOMANCE_BY_TOPIC}/?academic_year=${academic_year}&teacher_id=${teacher_id}`
return fetchAppBase(url, requestOptions)
}

View File

@ -41,7 +41,7 @@ class Sidebar extends React.Component<any, any> {
roles: [UserRoles.teacher]
},
{
name: "Manage Classes",
name: "My Classes",
action: "TeacherProfile",
icon: "ios-person",
roles: [UserRoles.teacher]
@ -53,7 +53,7 @@ class Sidebar extends React.Component<any, any> {
roles: [UserRoles.schoolAdmin]
},
{
name: "Manage Class",
name: "Manage Classes",
action: "Class",
icon: "ios-people",
roles: [UserRoles.schoolAdmin]

View File

@ -25,13 +25,15 @@ export const CLASSAPI: any = {
// doubt
GET_CLASS_STANDARDS: "/lovs/standard/",
// doubt
GET_MY_CLASS_GRADES: "/classes/get-my-grades/",
GET_MY_CLASS_SECTIONS: "/classes/get-my-sections/"
GET_MY_CLASS_GRADES: "/classes/get-my-grades",
GET_MY_CLASS_SECTIONS: "/classes/get-my-sections"
}
export const SCHOOLAPI: any = {
GET_SCHOOL_COMMON_URL: "/school",
GET_SCHOOL_CATEGORY: "/lovs/school_category/"
GET_SCHOOL_CATEGORY: "/lovs/school_category/",
GET_SCHOOL_CALENDAR: "/school-calendar/",
GET_GREETINGS: "/school/greetings/"
// doubt
}
@ -140,8 +142,17 @@ export const QUESTION_BANK_API: any = {
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/",
GET_BLUEPRINT_LESSON_DROPDOWN: '/questionbank-module/blueprint-lesson-dropdown/',
GET_BLUEPRINT_DIFFICULTY_LEVEL_DROPDOWN: '/questionbank-module/blueprint-level-dropdown/',
GET_QUIZ_RANDOM_QUESTION: '/questionbank-module/generate-quiz-random-question/'
ASSESSMENT_SCAN_ANSWERS:"/questionbank-module/assessment-answers",
GET_BLUEPRINT_SUBJECT_DROPDOWN: '/questionbank-module/blueprint-subject-dropdown',
GET_BLUEPRINT_LESSON_DROPDOWN: '/questionbank-module/blueprint-lesson-dropdown',
GET_BLUEPRINT_DIFFICULTY_LEVEL_DROPDOWN: '/questionbank-module/blueprint-level-dropdown',
GET_QUIZ_RANDOM_QUESTION: '/questionbank-module/generate-quiz-random-question'
}
export const HOME_STUDY_API: any = {
GENERATE_HOME_STUDY_RANDOM_QUESTION: "/questionbank-module/generate-homestudy-random-question",
ADD_TRANSACTION: "/questionbank-module/add-transaction",
GET_HOME_STUDY_LIST: "/questionbank-module/view-homestudy-list",
GET_TRANSACTION_DETAILS: "/questionbank-module/get-transaction-details",
GET_HOME_STUDY_STUDENTS_LIST: "/questionbank-module/view-homestudy-students",
}

View File

@ -8,7 +8,7 @@ import * as Analytics from 'expo-firebase-analytics'
import * as Location from 'expo-location'
import * as SplashScreen from 'expo-splash-screen'
import NetInfo, { NetInfoState } from '@react-native-community/netinfo'
import { ActivityIndicator, SafeAreaView, StyleSheet, View, StatusBar, KeyboardAvoidingView } from 'react-native'
import { ActivityIndicator, SafeAreaView, StyleSheet, View, StatusBar, KeyboardAvoidingView, Alert } from 'react-native'
import FlashMessage from 'react-native-flash-message'
import * as Font from 'expo-font'
import { connect } from 'react-redux'
@ -102,7 +102,7 @@ class ExpoBare extends React.Component<any, any> {
try {
await this.performAPICalls()
await this.downloadAssets()
await this.performLocation()
await this.showDisclosureAlert()
await this.performCameraPermission()
await this.performMediaPermission()
await this.requestUserNotificationPermission()
@ -131,6 +131,29 @@ class ExpoBare extends React.Component<any, any> {
this.setState({ assetsLoaded: true })
}
async showDisclosureAlert () {
const { status } = await Location.getForegroundPermissionsAsync();
if (status == 'granted') {
return
}
Alert.alert(
"Location Access Required",
"This app collects location data to take attendance when the app in use. We use this data to automatically verify your location at the time of take attendance. Please allow background location access to ensure take attendance.",
[
{
text: "Deny",
onPress: () => console.log("Permission Denied"),
style: "cancel"
},
{
text: "Allow",
onPress: () => this.performLocation(), // If user allows, request location permission
}
],
{ cancelable: false }
);
};
async performLocation() {
try {
const { status } = await Location.requestForegroundPermissionsAsync()

View File

@ -9,6 +9,7 @@ import DiaryView from '@screens/Diary/DiaryView' //NOSONAR
import InstantFeedbackView from '@screens/InstantFeedback/InstantFeedbackView' //NOSONAR
import QuizzesView from '@screens/Quizzes/QuizzesView' //NOSONAR
import QuizzesSummaryView from '@screens/Quizzes/QuizzesSummaryView' //NOSONAR
import SchoolCalendar from '@screens/SchoolCalendar/SchoolCalendar' //NOSONAR
const Tab = createMaterialTopTabNavigator();
@ -69,9 +70,10 @@ const AdminTabNavigator = ({route, navigation} : any) => {
component={InstantFeedbackView}
initialParams={route.params}
options={{
tabBarLabel: 'Instant Feedbacks',
tabBarLabel: 'Instant Feedback',
}}/>
<Tab.Screen name="AttendanceView" component={AttendanceView} initialParams={route.params} options={{ tabBarLabel: 'Attendances'}} />
<Tab.Screen name="schoolCalendar" component={SchoolCalendar} initialParams={route.params} options={{ tabBarLabel: 'Calendar'}} />
<Tab.Screen name="Diary" component={DiaryView} initialParams={route.params} options={{ tabBarLabel: 'Diary'}} />
<Tab.Screen name="NoticeBoard" component={NoticeBoardView} initialParams={route.params} options={{ tabBarLabel: 'Notice Board'}} />
<Tab.Screen name="Quizzes" component={QuizzesView} initialParams={route.params} options={{ tabBarLabel: 'Quizzes'}} />

View File

@ -48,6 +48,9 @@ import Assessment from "@screens/QuestionBank/Assessment"
import AssessmentCreate from "@screens/QuestionBank/AssessmentCreate"
import AssessmentEdit from "@screens/QuestionBank/AssessmentEdit"
import AssessmentScanner from "@screens/QuestionBank/AssessmentScanner"
import HomeStudyGenerateQuestions from "@screens/HomeStudy/HomeStudyGenerateQuestions"
import HomeStudyQuestionList from "@screens/HomeStudy/HomeStudyQuestionList"
import HomeStudyQuestionTransation from "@screens/HomeStudy/HomeStudyQuestionTransation"
const navigationOptions = ({ navigation, screenProps }: any) => ({
headerStyle: {
@ -58,6 +61,7 @@ const navigationOptions = ({ navigation, screenProps }: any) => ({
fontFamily: 'Quicksand_700Bold',
color: BaseColors.headerTintColor,
},
headerTitleAlign:'left',
headerBackTitleVisible: false,
// headerLeft: () => (
// <TouchableOpacity
@ -96,6 +100,7 @@ const AppNavigator = () => {
// //headerShown: false
// }}
>
{/* <Stack.Screen name="Greetings" component={Greetings} options={navigationOptions}/> */}
<Stack.Screen
name="DrawerNavigator"
component={DrawerNavigator}
@ -119,7 +124,8 @@ const AppNavigator = () => {
headerTitleStyle: {
fontFamily: 'Quicksand_700Bold',
color: BaseColors.headerTintColor,
}
},
headerTitleAlign:'left'
})}
/>
@ -135,7 +141,8 @@ const AppNavigator = () => {
headerTitleStyle: {
fontFamily: 'Quicksand_700Bold',
color: BaseColors.headerTintColor,
}
},
headerTitleAlign:'left',
})}
/>
@ -151,7 +158,8 @@ const AppNavigator = () => {
headerTitleStyle: {
fontFamily: 'Quicksand_700Bold',
color: BaseColors.headerTintColor,
}
},
headerTitleAlign:'left',
})}
/>
@ -205,11 +213,11 @@ const AppNavigator = () => {
<Stack.Screen name="MapClassUpdate" component={MapClassUpdate} />
<Stack.Screen name="StudentReport" component={StudentReport} />
<Stack.Screen name="ArTagScanner" component={ArTagScanner} options={navigationOptions}/>
<Stack.Screen name="TeacherAttendance" component={TeacherAttendance} />
{/* <Stack.Screen name="TeacherAttendance" component={TeacherAttendance} /> */}
<Stack.Screen name="QuestionSetCreate" component={QuestionSetCreate} />
<Stack.Screen name="QuestionSet" component={QuestionSet} />
<Stack.Screen name="QuestionSetImport" component={QuestionSetImport} />
<Stack.Screen name="Pscyometric" component={HomePsychometric} options={navigationOptions}/>
{/* <Stack.Screen name="Pscyometric" component={HomePsychometric} options={navigationOptions}/> */}
<Stack.Screen name="ClassListPsychometric" component={ClassListPsychometric} options={navigationOptions}/>
<Stack.Screen name="StudentListPsychometric" component={StudentListPsychometric} options={navigationOptions}/>
<Stack.Screen name="QuestionListPsychometric" component={QuestionListPsychometric} options={navigationOptions}/>
@ -220,6 +228,9 @@ const AppNavigator = () => {
<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.Screen name="HomeStudyGenerateQuestions" component={HomeStudyGenerateQuestions} options={navigationOptions}/>
<Stack.Screen name="HomeStudyQuestionList" component={HomeStudyQuestionList} options={navigationOptions}/>
<Stack.Screen name="HomeStudyQuestionTransation" component={HomeStudyQuestionTransation} options={navigationOptions}/>
</Stack.Navigator>
);
};

View File

@ -19,6 +19,9 @@ import TeacherView from '@screens/Teacher/TeacherView' //NOSONAR
import TeacherCreate from '@screens/Teacher/TeacherCreate' //NOSONAR
import TeacherUpdate from '@screens/Teacher/TeacherUpdate' //NOSONAR
import TeacherInfo from '@screens/Teacher/TeacherInfo' //NOSONAR
import TeacherAttendance from "@screens/Teacher/TeacherAttendance" //NOSONAR
import HomePsychometric from "@screens/Pscyometric/HomePsychometric"
import Greetings from "@screens/Greetings" //NOSONAR
const Drawer = createDrawerNavigator();
@ -47,12 +50,14 @@ const DrawerNavigator = () => {
screenOptions={({navigation}) => ({
headerTitle: 'TedQu',
headerStyle: {
//height:60,
backgroundColor: BaseColors.headerStyleBackgroundColor,
},
headerTintColor: BaseColors.headerTintColor,
headerTitleStyle: {
color: BaseColors.headerTintColor,
},
headerTitleAlign:'left',
headerLeft: () => <Header openDrawer={navigation} />,
headerRight: () => (
<View style={styles.iconContainer}>
@ -65,12 +70,15 @@ const DrawerNavigator = () => {
drawerContent={(props:any) => <Sidebar {...props} />}
>
<Drawer.Screen name="Home" component={Home} />
<Drawer.Screen name="Greetings" component={Greetings} options={{headerShown: false}}/>
<Drawer.Screen name="Profile" component={Profile} />
<Drawer.Screen name="Settings" component={Settings} />
<Drawer.Screen name="ChangePassword" component={ChangePassword} />
<Drawer.Screen name="School" component={SchoolView} />
<Drawer.Screen name="SchoolUpdate" component={SchoolUpdate} />
<Drawer.Screen name="Class" component={ClassStackNavigator} />
<Drawer.Screen name="TeacherAttendance" component={TeacherAttendance} />
<Drawer.Screen name="Pscyometric" component={HomePsychometric} />
{/* <Drawer.Screen name="ClassCreate" component={ClassCreate} /> */}
{/* <Drawer.Screen name="ClassUpdate" component={ClasslUpdate} /> */}
<Drawer.Screen name="TeacherView" component={TeeacherStackNavigator} />

View File

@ -8,6 +8,8 @@ import DiaryView from '@screens/Diary/DiaryView' //NOSONAR
import StudentAttendanceView from '@screens/Attendance/StudentAttendanceView' //NOSONAR
import QuizzesView from '@screens/Quizzes/QuizzesView' //NOSONAR
import StudentProfile from '@screens/Student/StudentProfile' //NOSONAR
import HomeStudyList from '@screens/HomeStudy/HomeStudyList'
import SchoolCalendar from '@screens/SchoolCalendar/SchoolCalendar' //NOSONAR
// const ParentTabNavigator = createMaterialTopTabNavigator(
// {
@ -122,9 +124,11 @@ const ParentTabNavigator = ({route, navigation} : any) => {
>
<Tab.Screen name="studentProfile" component={StudentProfile} initialParams={route.params} options={{ tabBarLabel: 'Profile'}}/>
<Tab.Screen name="studentAttendance" component={StudentAttendanceView} initialParams={route.params} options={{ tabBarLabel: 'Attendances'}}/>
<Tab.Screen name="schoolCalendar" component={SchoolCalendar} initialParams={route.params} options={{ tabBarLabel: 'Calendar'}} />
<Tab.Screen name="studentDiary" component={DiaryView} initialParams={route.params} options={{ tabBarLabel: 'Diary'}} />
<Tab.Screen name="studentNoticeBoard" component={NoticeBoardView} initialParams={route.params} options={{ tabBarLabel: 'Notice Board'}} />
<Tab.Screen name="studentQuizzes" component={QuizzesView} initialParams={route.params} options={{ tabBarLabel: 'Quizz'}}/>
<Tab.Screen name="homestudy" component={HomeStudyList} initialParams={route.params} options={{ tabBarLabel: 'Home Study'}}/>
</Tab.Navigator>
);
};

View File

@ -60,7 +60,9 @@ export const classes = (state = defaultState, action: any) => {
return { ...state, loading: true, data: defaultObj }
case CREATE_CLASS_REQUEST_SUCCESS:
if (response.hasOwnProperty('status')) {
if(response.message) {
if(response.status && response.message) {
Toast.show(response.message, Toast.SHORT)
}else if(!response.status && !response.hasOwnProperty('show_message')) {
Toast.show(response.message, Toast.SHORT)
}
}

View File

@ -0,0 +1,66 @@
import {
GET_HOME_STUDY_LIST_REQUEST, GET_HOME_STUDY_LIST_SUCCESS, GET_HOME_STUDY_LIST_FAILURE,
GET_HOME_STUDY_TRANSACTION_DETAILS_REQUEST, GET_HOME_STUDY_TRANSACTION_DETAILS_SUCCESS, GET_HOME_STUDY_TRANSACTION_DETAILS_FAILURE,
GET_HOME_STUDY_STUDENTS_LIST_REQUEST, GET_HOME_STUDY_STUDENTS_LIST_SUCCESS, GET_HOME_STUDY_STUDENTS_LIST_FAILURE,
GENERATE_HOME_STUDY_RANDOM_QUESTION_REQUEST, GENERATE_HOME_STUDY_RANDOM_QUESTION_SUCCESS, GENERATE_HOME_STUDY_RANDOM_QUESTION_FAILURE,
ADD_HOME_STUDY_TRANSACTION_REQUEST, ADD_HOME_STUDY_TRANSACTION_SUCCESS, ADD_HOME_STUDY_TRANSACTION_FAILURE
} from '@actions/type' //NOSONAR
import Toast from 'react-native-simple-toast'
const defaultObj: any = {}
const defaultState = {
loading: false,
records: [],
list: {},
total: 0,
page: 1,
per_page: 10,
search: "",
sort_by: null,
order_by: null,
refreshing: false,
data: {},
students: {},
categories: {},
file_info: {},
reply_data: {},
random_question:{},
home_study_list:{},
home_study_records: [],
home_study_details:{},
home_study_add_transaction:{}
}
export const homestudy = (state = defaultState, action: any) => {
const response = action.data
switch (action.type) {
case GET_HOME_STUDY_LIST_REQUEST:
case GENERATE_HOME_STUDY_RANDOM_QUESTION_REQUEST:
case GET_HOME_STUDY_TRANSACTION_DETAILS_REQUEST:
case ADD_HOME_STUDY_TRANSACTION_REQUEST:
return { ...state, loading: true,random_question:{} }
case GET_HOME_STUDY_LIST_SUCCESS:
if (response.data.page === 1) {
state.home_study_records = []
}
return {
...state, loading: false, home_study_list: response, home_study_records: [...state.home_study_records, ...response.data.records]
}
case GET_HOME_STUDY_LIST_FAILURE:
return { ...state, loading: false, error: action.error }
case GENERATE_HOME_STUDY_RANDOM_QUESTION_SUCCESS:
return { ...state, loading: false, random_question: response }
case GET_HOME_STUDY_TRANSACTION_DETAILS_SUCCESS:
return { ...state, loading: false, home_study_details: response }
case ADD_HOME_STUDY_TRANSACTION_SUCCESS:
return { ...state, loading: false, home_study_add_transaction: response }
case ADD_HOME_STUDY_TRANSACTION_FAILURE:
return { ...state, loading: false, home_study_add_transaction: {} }
case GET_HOME_STUDY_TRANSACTION_DETAILS_FAILURE:
case GENERATE_HOME_STUDY_RANDOM_QUESTION_FAILURE:
return { ...state, loading: false }
default:
return state
}
}

View File

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

View File

@ -9,6 +9,7 @@ import {
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,
GET_BLUEPRINT_SUBJECT_DROPDOWN_REQUEST, GET_BLUEPRINT_SUBJECT_DROPDOWN_SUCCESS, GET_BLUEPRINT_SUBJECT_DROPDOWN_FAILURE,
GET_BLUEPRINT_LESSON_DROPDOWN_REQUEST, GET_BLUEPRINT_LESSON_DROPDOWN_SUCCESS, GET_BLUEPRINT_LESSON_DROPDOWN_FAILURE,
GET_BLUEPRINT_DIFFICULTY_LEVEL_DROPDOWN_REQUEST, GET_BLUEPRINT_DIFFICULTY_LEVEL_DROPDOWN_SUCCESS, GET_BLUEPRINT_DIFFICULTY_LEVEL_DROPDOWN_FAILURE,
GET_QUIZ_RANDOM_QUESTION_REQUEST, GET_QUIZ_RANDOM_QUESTION_SUCCESS, GET_QUIZ_RANDOM_QUESTION_FAILURE
@ -36,6 +37,7 @@ const defaultState = {
assessment_update: {},
assessment_student_list: {},
assessment_answer: {},
bluprint_subject_dropdown:{},
bluprint_lesson_dropdown:{},
bluprint_difficulty_level_dropdown:{},
quiz_random_question:{},
@ -56,6 +58,7 @@ export const questionbank = (state = defaultState, action: any) => {
case DELETE_ASSESSMENT_REQUEST:
case GET_ASSESSMENT_STUDENT_LIST_REQUEST:
case CREATE_ASSESSMENT_SCAN_ANSWERS_REQUEST:
case GET_BLUEPRINT_SUBJECT_DROPDOWN_REQUEST:
case GET_BLUEPRINT_LESSON_DROPDOWN_REQUEST:
case GET_BLUEPRINT_DIFFICULTY_LEVEL_DROPDOWN_REQUEST:
case GET_QUIZ_RANDOM_QUESTION_REQUEST:
@ -90,8 +93,18 @@ export const questionbank = (state = defaultState, action: any) => {
...state, loading: false, question_details: response?.data?.question_details
}
case CREATE_ASSESSMENT_SUCCESS:
if (response.hasOwnProperty('status')) {
if (response.message) {
Toast.show('Assessment created successfully', Toast.SHORT)
}
}
return { ...state, loading: false, assessment_create: response }
case UPDATE_ASSESSMENT_SUCCESS:
if (response.hasOwnProperty('status')) {
if (response.message) {
Toast.show('Assessment updated successfully', Toast.SHORT)
}
}
return { ...state, loading: false, assessment_update: response }
case GET_ASSESSMENT_SUCCESS:
if (response.hasOwnProperty('status')) {
@ -104,6 +117,8 @@ export const questionbank = (state = defaultState, action: any) => {
return { ...state, loading: false, assessment_student_list: response }
case CREATE_ASSESSMENT_SCAN_ANSWERS_SUCCESS:
return { ...state, loading: false, assessment_answer: response }
case GET_BLUEPRINT_SUBJECT_DROPDOWN_SUCCESS:
return { ...state, loading: false, bluprint_subject_dropdown: response }
case GET_BLUEPRINT_LESSON_DROPDOWN_SUCCESS:
return { ...state, loading: false, bluprint_lesson_dropdown: response }
case GET_BLUEPRINT_DIFFICULTY_LEVEL_DROPDOWN_SUCCESS:
@ -118,6 +133,7 @@ export const questionbank = (state = defaultState, action: any) => {
case GET_QUESTION_PAPER_PAGINATION_FAILURE:
case GET_ASSESSMENT_PAGINATION_FALURE:
case GET_ASSESSMENT_FALURE:
case GET_BLUEPRINT_SUBJECT_DROPDOWN_FAILURE:
return { ...state, loading: false }
case CREATE_ASSESSMENT_FALURE:
return { ...state, loading: false, assessment_create: {} }

View File

@ -1,5 +1,6 @@
import { GET_SCHOOL_DETAILS, GET_SCHOOL_DETAILS_SUCCESS, GET_SCHOOL_DETAILS_FAILURE, UPDATE_SCHOOL_INFO, UPDATE_SCHOOL_INFO_SUCCESS, UPDATE_SCHOOL_INFO_FAILURE, //NOSONAR
GET_SCHOOL_CATEGORY, GET_SCHOOL_CATEGORY_FAILURE, GET_SCHOOL_CATEGORY_SUCCESS } from '@actions/type' //NOSONAR
GET_SCHOOL_CATEGORY, GET_SCHOOL_CATEGORY_FAILURE, GET_SCHOOL_CATEGORY_SUCCESS,
GET_CALENDAR_REQUEST,GET_CALENDAR_FAILURE,GET_CALENDAR_SUCCESS, GET_GREETINGS_REQUEST, GET_GREETINGS_SUCCESS, GET_GRADE_REQUEST_FAILURE, GET_GREETINGS_FAILURE} from '@actions/type' //NOSONAR
import Toast from 'react-native-simple-toast'
const defaultObj:any = {}
@ -12,7 +13,9 @@ const defaultState = {
refreshing: false,
data: {},
info: {},
category: {}
category: {},
calendar: {},
greetings:{}
}
export const school = (state = defaultState, action: any) => {
@ -52,6 +55,29 @@ export const school = (state = defaultState, action: any) => {
return { ...state, loading: false, data: response }
case UPDATE_SCHOOL_INFO_FAILURE:
return { ...state, loading: false, error: action.error }
case GET_CALENDAR_REQUEST:
return { ...state, loading: true, calendar: defaultObj }
case GET_CALENDAR_SUCCESS:
if (response.hasOwnProperty('status')) {
if(!response.message) {
Toast.show(response.message, Toast.SHORT)
}
}
return { ...state, loading: false, calendar: response }
case GET_CALENDAR_FAILURE:
return { ...state, loading: false, error: action.error }
case GET_GREETINGS_REQUEST:
return { ...state, loading: true, greetings: defaultObj }
case GET_GREETINGS_SUCCESS:
if (response.hasOwnProperty('status')) {
if(!response.message) {
Toast.show(response.message, Toast.SHORT)
}
}
return { ...state, loading: false, greetings: response }
case GET_GREETINGS_FAILURE:
return { ...state, loading: false, error: action.error }
default:
return state
}

View File

@ -18,7 +18,9 @@ import { //NOSONAR
import Toast from 'react-native-simple-toast'
const defaultObj: any = {
const defaultObj: any = {}
const defaultObjdata: any = {
data:{
status: false
}
@ -52,7 +54,7 @@ export const teachers = (state = defaultState, action: any) => {
switch (action.type) {
case INIT_TEACHER_MODULE:
return { ...state, loading: false, data: defaultObj }
return { ...state, loading: false, data: defaultObjdata }
case INIT_TEACHER_TODAYS_ATTENDANCE:
return { ...state, loading: false, attendance_info: defaultObj, attendance_data: defaultObj }
case GET_TEACHER_TODAYS_ATTENDANCE_REQUEST:

View File

@ -0,0 +1,72 @@
import { takeEvery, call, put } from 'redux-saga/effects'
import {
GET_HOME_STUDY_LIST_REQUEST, GET_HOME_STUDY_TRANSACTION_DETAILS_REQUEST, GET_HOME_STUDY_STUDENTS_LIST_REQUEST,
GENERATE_HOME_STUDY_RANDOM_QUESTION_REQUEST, ADD_HOME_STUDY_TRANSACTION_REQUEST
} from '@actions/type' //NOSONAR
import { getHomeStudyList, getHomeStudyTransactionDetails, getHomeStudyStudentsList, generateHomeStudyRandomQuestion, addHomeStudyTransaction} from '@api/homestudy.api' //NOSONAR
import { ActionCreators } from '@actions' //NOSONAR
export const watchGetHomeStudyList = function* () {
yield takeEvery(GET_HOME_STUDY_LIST_REQUEST, workerGetHomeStudyList)
}
function* workerGetHomeStudyList(action: any) {
try {
const response = yield call(getHomeStudyList, action.data)
yield put(ActionCreators.getHomeStudyListSuccess(response))
} catch (e) {
yield put(ActionCreators.getHomeStudyListFailure(e))
}
}
export const watchGetHomeStudyTransactionDetails = function* () {
yield takeEvery(GET_HOME_STUDY_TRANSACTION_DETAILS_REQUEST, workerGetHomeStudyTransactionDetails)
}
function* workerGetHomeStudyTransactionDetails(action: any) {
try {
const response = yield call(getHomeStudyTransactionDetails, action.data)
yield put(ActionCreators.getHomeStudyTransactionDetailsSuccess(response))
} catch (e) {
yield put(ActionCreators.getHomeStudyTransactionDetailsFailure(e))
}
}
export const watchGetHomeStudyStudentsList = function* () {
yield takeEvery(GET_HOME_STUDY_STUDENTS_LIST_REQUEST, workerGetHomeStudyStudentsList)
}
function* workerGetHomeStudyStudentsList(action: any) {
try {
const response = yield call(getHomeStudyStudentsList, action.data)
yield put(ActionCreators.getHomeStudyStudentsListSuccess(response))
} catch (e) {
yield put(ActionCreators.getHomeStudyStudentsListFailure(e))
}
}
export const watchGenerateHomeStudyRandomQuestion = function* () {
yield takeEvery(GENERATE_HOME_STUDY_RANDOM_QUESTION_REQUEST, workerGenerateHomeStudyRandomQuestion)
}
function* workerGenerateHomeStudyRandomQuestion(action: any) {
try {
const response = yield call(generateHomeStudyRandomQuestion, action.data)
yield put(ActionCreators.generateHomeStudyRandomQuestionSuccess(response))
} catch (e) {
yield put(ActionCreators.generateHomeStudyRandomQuestionFailure(e))
}
}
export const watchAddHomeStudyTransaction = function* () {
yield takeEvery(ADD_HOME_STUDY_TRANSACTION_REQUEST, workerAddHomeStudyTransaction)
}
function* workerAddHomeStudyTransaction(action: any) {
try {
const response = yield call(addHomeStudyTransaction, action.data)
yield put(ActionCreators.addHomeStudyTransactionSuccess(response))
} catch (e) {
yield put(ActionCreators.addHomeStudyTransactionFailure(e))
}
}

View File

@ -4,7 +4,7 @@ import {
watchGetLogout
} from "./auth.sagas"
import { watchGetUserProfile, watchGetArTagRequest } from "./users.sagas"
import { watchGetSchool, watchGetSchoolCategory, watchUpdateSchool } from './school.sagas'
import { watchGetCalendar, watchGetSchool, watchGetSchoolCategory, watchUpdateSchool, watchGetGreetings } from './school.sagas'
import { watchCreateClass, watchGetClass, watchGetAllClass, watchUpdateClass, watchDeleteClass, watchGetClassGrades, watchGetClassStandards, watchGetMyClassStandards } from './class.sagas'
import {
watchCreateTeacher, watchGetTeacher, watchGetAllTeacher, watchUpdateTeacher, watchDeleteTeacher, watchGetAllTeacherSubjects,
@ -37,7 +37,11 @@ import { watchGetPsychometricClassList, watchGetPsychometricStudentListByClass,w
import {
watchGetAllQuestionPaper, watchGetAllAssessmentList, watchGetQuestionPaper, watchCreateAssessment, watchUpdateAssessment, watchDeleteAssessment,
watchGetAssessment, watchGetAssessmentStudentList, watchCreateAssessmentScanAnswer, watchGetBlueprintLessonDropdown ,watchGetBlueprintDifficultyLevelDropdown , watchGetQuizRandomQuestion} from './questionbank.saga'
watchGetAssessment, watchGetAssessmentStudentList, watchCreateAssessmentScanAnswer, watchGetBlueprintLessonDropdown ,watchGetBlueprintDifficultyLevelDropdown , watchGetQuizRandomQuestion, watchGetBlueprintSubjectDropdown} from './questionbank.saga'
import { watchGetHomeStudyList, watchGetHomeStudyTransactionDetails, watchGetHomeStudyStudentsList,
watchGenerateHomeStudyRandomQuestion, watchAddHomeStudyTransaction } from './homestudy.saga'
export default function* root() {
yield all([
watchGetLogin(),
@ -50,6 +54,8 @@ export default function* root() {
watchForgotUser(),
watchGetUserProfile(),
watchGetSchool(),
watchGetCalendar(),
watchGetGreetings(),
watchGetSchoolCategory(),
watchUpdateSchool(),
watchCreateClass(),
@ -143,8 +149,14 @@ export default function* root() {
watchUpdateAssessment(),
watchDeleteAssessment(),
watchCreateAssessmentScanAnswer(),
watchGetBlueprintSubjectDropdown(),
watchGetBlueprintLessonDropdown(),
watchGetBlueprintDifficultyLevelDropdown(),
watchGetQuizRandomQuestion()
watchGetQuizRandomQuestion(),
watchGetHomeStudyList(),
watchGetHomeStudyTransactionDetails(),
watchGetHomeStudyStudentsList(),
watchGenerateHomeStudyRandomQuestion(),
watchAddHomeStudyTransaction()
])
}

View File

@ -4,9 +4,9 @@ import {
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, GET_BLUEPRINT_LESSON_DROPDOWN_REQUEST, GET_BLUEPRINT_DIFFICULTY_LEVEL_DROPDOWN_REQUEST,
GET_QUIZ_RANDOM_QUESTION_REQUEST,
GET_QUIZ_RANDOM_QUESTION_REQUEST, GET_BLUEPRINT_SUBJECT_DROPDOWN_REQUEST
} from '@actions/type' //NOSONAR
import { getAllQuestionPaper, getAllAssessmentList, getQuestionPaper,createAssessment, updateAssessment, getAssessment, getAssessmentStudentList, deleteAssessment, createAssessmentScanAnswer, getBlueprintLessonDropdown, getBlueprintDifficultyLevelDropdown, getQuizRandomQuestion } from '@api/questionbank.api' //NOSONAR
import { getAllQuestionPaper, getAllAssessmentList, getQuestionPaper,createAssessment, updateAssessment, getAssessment, getAssessmentStudentList, deleteAssessment, createAssessmentScanAnswer, getBlueprintLessonDropdown, getBlueprintDifficultyLevelDropdown, getQuizRandomQuestion, getBlueprintSubjectDropdown } from '@api/questionbank.api' //NOSONAR
import { ActionCreators } from '@actions' //NOSONAR
export const watchGetAllQuestionPaper = function* () {
@ -18,7 +18,7 @@ function* workerGetAllQuestionPaper(action: any) {
const response = yield call(getAllQuestionPaper, action.data)
yield put(ActionCreators.getQuestionPaperPaginationSuccess(response))
} catch (e) {
yield put(ActionCreators.getQuestionPaperPaginationSuccess(e))
yield put(ActionCreators.getQuestionPaperPaginationFailure(e))
}
}
@ -130,6 +130,19 @@ function* workerCreateAssessmentScanAnswer(action: any) {
}
}
export const watchGetBlueprintSubjectDropdown = function* () {
yield takeEvery(GET_BLUEPRINT_SUBJECT_DROPDOWN_REQUEST, workerGetBlueprintSubjectDropdown)
}
function* workerGetBlueprintSubjectDropdown(action: any) {
try {
const response = yield call(getBlueprintSubjectDropdown, action.data)
yield put(ActionCreators.getBlueprintSubjectDropdownSuccess(response))
} catch (e) {
yield put(ActionCreators.getBlueprintSubjectDropdownFailure(e))
}
}
export const watchGetBlueprintLessonDropdown = function* () {
yield takeEvery(GET_BLUEPRINT_LESSON_DROPDOWN_REQUEST, workerGetBlueprintLessonDropdown)
}

View File

@ -1,6 +1,6 @@
import { takeEvery, call, put } from 'redux-saga/effects'
import { GET_SCHOOL_DETAILS, UPDATE_SCHOOL_INFO, GET_SCHOOL_CATEGORY } from '@actions/type' //NOSONAR
import { getSchoolDetails, getSchoolCategorys, setSchoolDetails } from '@api/school.api' //NOSONAR
import { GET_SCHOOL_DETAILS, UPDATE_SCHOOL_INFO, GET_SCHOOL_CATEGORY, GET_CALENDAR_REQUEST, GET_GREETINGS_REQUEST } from '@actions/type' //NOSONAR
import { getSchoolDetails, getSchoolCategorys, setSchoolDetails, getCalendarEvents, getGreetings } from '@api/school.api' //NOSONAR
import { ActionCreators } from '@actions' //NOSONAR
export const watchGetSchool = function* () {
@ -15,6 +15,14 @@ export const watchUpdateSchool = function* () {
yield takeEvery(UPDATE_SCHOOL_INFO, workerUpdateSchool)
}
export const watchGetCalendar= function* () {
yield takeEvery(GET_CALENDAR_REQUEST, workerSchoolGetCalendar)
}
export const watchGetGreetings= function* () {
yield takeEvery(GET_GREETINGS_REQUEST, workerSchoolGetGreetings)
}
function* workerGetSchool(action: any) {
try {
@ -42,3 +50,21 @@ function* workerUpdateSchool(action: any) {
yield put(ActionCreators.setSchoolInfoFailure(e))
}
}
function* workerSchoolGetCalendar(action: any) {
try {
const response = yield call(getCalendarEvents, action.data)
yield put(ActionCreators.getCalendarSuccess(response))
} catch (e){
yield put(ActionCreators.getCalendarFailure(e))
}
}
function* workerSchoolGetGreetings(action: any) {
try {
const response = yield call(getGreetings, action.data)
yield put(ActionCreators.getGreetingSuccess(response))
} catch (e){
yield put(ActionCreators.getGreetingFailure(e))
}
}

View File

@ -26,7 +26,7 @@ class ArTagScanner extends React.Component<any, any>{
attendanceLabel: this.props.route.params?.label,
isAttendanceLabel: true,
attendanceTextSize: 9,
standardLabel: 'Standard',
standardLabel: 'Class',
isStandardLabel: true,
standardNameTextSize: 9,
fillRectangleBackgroundColor: false, // fill reactangle color true | false

View File

@ -1,5 +1,5 @@
import React from "react"
import { StyleSheet, View, ActivityIndicator } from 'react-native'
import { StyleSheet, View, ActivityIndicator,Text } from 'react-native'
import { AppStyles, BaseStyles } from "@theme/BaseStyles" //NOSONAR
import AsyncStorage from "@react-native-async-storage/async-storage"
import { connect } from "react-redux"
@ -8,6 +8,7 @@ import PropTypes from 'prop-types'
import { currentYear, currentAcademicYear } from "@constants/Constants" //NOSONAR
import { CalendarList } from 'react-native-calendars'
import moment from "moment"
import { VictoryLegend } from "victory-native"
class StudentAttendanceView extends React.Component<any, any>{
static propTypes = {};
@ -100,6 +101,18 @@ class StudentAttendanceView extends React.Component<any, any>{
: <View style={[BaseStyles.marVertical50, { flex: 1, justifyContent: 'center' }]}>
<ActivityIndicator size="large" color="#7165e3" />
</View>}
<View style={styles.bottomView}>
<VictoryLegend x={30} y={20}
centerTitle
orientation="horizontal"
height={50}
data={[
{ name: "Present ", symbol: { fill: 'green', } },
{ name: "Absent ", symbol: { fill: 'red'} },
{ name: "Non Working Day ", symbol: { fill: 'gray' } }
]}
/>
</View>
</View>
</View>)
@ -130,7 +143,28 @@ const styles = StyleSheet.create({
justifyContent: "center",
marginLeft: 10
},
bottomView: {
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
backgroundColor: '#f8f8f8',
padding: 0,
alignItems: 'center',
justifyContent: 'center',
borderTopWidth: 1,
borderTopColor: '#ddd',
},
button: {
backgroundColor: '#007BFF',
paddingVertical: 10,
paddingHorizontal: 20,
borderRadius: 5,
},
buttonText: {
color: '#fff',
fontSize: 16,
},
})

View File

@ -221,6 +221,21 @@ class DiaryView extends React.PureComponent<any, any>{
},
}
const tagsStyles = {
table: {
borderBottomWidth: 1,
borderRightWidth: 1,
borderColor: '#bfbfbf'
},
td: {
borderWidth: 1,
borderRightWidth: 0,
borderBottomWidth: 0,
borderColor: '#bfbfbf',
padding: 10,
},
};
return (
<View style={[AppStyles.diaryCard]}>
<View style={[AppStyles.diaryHeaderContainer, BaseStyles.padHorizontal10]}>
@ -254,6 +269,7 @@ class DiaryView extends React.PureComponent<any, any>{
<RenderHtml
source={{ html: `<div class="html-format">${item?.message}</div>` }}
contentWidth={contentWidth-40}
tagsStyles={tagsStyles}
classesStyles={{
'html-format': {
fontFamily: "Quicksand_500Medium", color: BaseColors.black,
@ -310,21 +326,21 @@ class DiaryView extends React.PureComponent<any, any>{
(this.signedUserId === replyInfo?.parent_id) ?
<View key={index} style={[BaseStyles.padHorizontal10, AppStyles.studentCard, { flexDirection: 'row-reverse', padding: 7, marginBottom: 0 }]}>
<View style={[{ backgroundColor: BaseColors.headerStyleBackgroundColor, alignSelf: 'center', justifyContent: 'center' }, styles.listViewImage, BaseStyles.marRight10]}>
<Text style={{ fontSize: 14, color: BaseColors.white, textAlign: 'center' }}>{replyInfo?.username && replyInfo?.username.charAt(0) || 'NA'}</Text>
<Text style={{ fontSize: 14, color: BaseColors.white, textAlign: 'center' }}>{replyInfo?.username && replyInfo?.username.charAt(0).toUpperCase() || 'NA'}</Text>
</View>
<View style={[BaseStyles.marRight10, BaseStyles.padding10, { flexDirection: 'column', width: '85%', backgroundColor: "#f5f7f7", borderRadius: 20 }]}>
<Text style={[AppStyles.nameLabel, BaseStyles.marLeft10, { fontSize: 15, fontFamily: "Quicksand_700Bold", color: "#000", alignItems: 'flex-end' }]}>
{replyInfo?.username || 'NA'}
{replyInfo?.username.charAt(0).toUpperCase() + replyInfo?.username.slice(1) || 'NA'}
<Text style={{ fontSize: 11, color: "#bab8b8" }}> {moment(replyInfo?.reply_date).fromNow()}</Text></Text>
<Text style={[AppStyles.stdLabel, BaseStyles.marLeft10,]}>{replyInfo?.message}</Text>
</View>
</View> :
<View key={index} style={[BaseStyles.padHorizontal10, AppStyles.studentCard, BaseStyles.marTop5, { padding: 7, marginBottom: 0 }]}>
<View style={[{ backgroundColor: BaseColors.headerStyleBackgroundColor, alignSelf: 'center', justifyContent: 'center' }, styles.listViewImage, BaseStyles.marRight10]}>
<Text style={{ fontSize: 14, color: BaseColors.white, textAlign: 'center' }}>{replyInfo?.username && replyInfo?.username.charAt(0) || 'NA'}</Text>
<Text style={{ fontSize: 14, color: BaseColors.white, textAlign: 'center' }}>{replyInfo?.username && replyInfo?.username.charAt(0).toUpperCase() || 'NA'}</Text>
</View>
<View style={[BaseStyles.padding10, { flexDirection: 'column', width: '85%', backgroundColor: "#f5f7f7", borderRadius: 10 }]}>
<Text style={[AppStyles.nameLabel, { fontSize: 15, fontFamily: "Quicksand_700Bold", color: "#000", }]}>{replyInfo?.username || 'NA'}
<Text style={[AppStyles.nameLabel, { fontSize: 15, fontFamily: "Quicksand_700Bold", color: "#000", }]}>{replyInfo?.username.charAt(0).toUpperCase() + replyInfo?.username.slice(1) || 'NA'}
<Text style={{ fontSize: 11, color: "#bab8b8" }}> {moment(replyInfo?.reply_date).fromNow()}</Text></Text>
<Text style={[AppStyles.stdLabel]}>{replyInfo?.message}</Text>
</View>
@ -332,24 +348,51 @@ class DiaryView extends React.PureComponent<any, any>{
))
:
<View>
<View style={[BaseStyles.marHorizontal10, BaseStyles.padding10, BaseStyles.marTop5, { flexDirection: 'column', borderWidth:2, borderColor: "#bab8b8" }]}>
<Text>No of Students: {item.class_list[0].no_of_assessments}</Text>
<Text>No of completed: {item.class_list[0].no_of_completed}</Text>
<Text>No of incompleted: {item.class_list[0].no_of_incompleted}</Text>
<View style={[BaseStyles.marVertical2, BaseStyles.marTop10, BaseStyles.marHorizontal10, BaseStyles.padHorizontal10, { flexDirection: 'row'}]}>
<View style={[AppStyles.tagLabelWoBorder, AppStyles.weakGoodColor11, {borderRadius: 16, paddingRight: 40, minWidth:'35%', Width:'35%'}]}>
<Text style={{ color: BaseColors.white }}>Students</Text>
</View>
<View style={[AppStyles.tagLabelWoBorder,
{ backgroundColor: BaseColors.white, borderWidth: 1, borderRadius: 16, borderColor:"rgb(248, 201, 124)", position: 'relative', right: 28 }]}>
<Text style={{ color:"rgb(248, 201, 124)" }}> {item.class_list[0].no_of_assessments}</Text>
</View>
</View>
<View style={[BaseStyles.marVertical2, BaseStyles.marHorizontal10, BaseStyles.padHorizontal10, { flexDirection: 'row', }]}>
<View style={[AppStyles.tagLabelWoBorder, { backgroundColor:"#00B200", borderRadius: 16, paddingRight: 40, minWidth:'35%', Width:'35%' }]}>
<Text style={{ color: BaseColors.white }}>Completed</Text>
</View>
<View style={[AppStyles.tagLabelWoBorder,
{ backgroundColor: BaseColors.white, borderWidth: 1, borderRadius: 16, borderColor:"#00B200", position: 'relative', right: 28 }]}>
<Text style={{ color:"#00B200" }}> {item.class_list[0].no_of_completed}</Text>
</View>
</View>
<View style={[BaseStyles.marVertical2, BaseStyles.marHorizontal10, BaseStyles.padHorizontal10, { flexDirection: 'row', }]}>
<View style={[AppStyles.tagLabelWoBorder, { backgroundColor:"#ff4d01", borderRadius: 16, paddingRight: 40, minWidth:'35%', Width:'35%' }]}>
<Text style={{ color: BaseColors.white }}>Incompleted</Text>
</View>
<View style={[AppStyles.tagLabelWoBorder,
{ backgroundColor: BaseColors.white, borderWidth: 1, borderRadius: 16, borderColor:"#ff4d01", position: 'relative', right: 28 }]}>
<Text style={{ color:"#ff4d01" }}> {item.class_list[0].no_of_incompleted}</Text>
</View>
</View>
{item?.student_list.map((student: any, index: any) => (
<View key={index} style={[BaseStyles.padHorizontal10, AppStyles.studentCard, { flexDirection: 'row-reverse', padding: 7, marginBottom: 0 }]}>
<View style={[{ backgroundColor: BaseColors.headerStyleBackgroundColor, alignSelf: 'center', justifyContent: 'center' }, styles.listViewImage, BaseStyles.marRight10]}>
<Text style={{ fontSize: 14, color: BaseColors.white, textAlign: 'center' }}>{student?.student_name && student?.student_name.charAt(0) || 'NA'}</Text>
<Text style={{ fontSize: 14, color: BaseColors.white, textAlign: 'center' }}>{student?.student_name && student?.student_name.charAt(0).toUpperCase() || 'NA'}</Text>
</View>
<View style={[BaseStyles.marRight10, BaseStyles.padding10, { flexDirection: 'column', width: '85%', backgroundColor: "#f5f7f7", borderRadius: 20 }]}>
<Text style={[AppStyles.nameLabel, BaseStyles.marLeft10, { fontSize: 15, fontFamily: "Quicksand_700Bold", color: "#000", alignItems: 'flex-end' }]}>
{student.student_name}
<Text style={[AppStyles.nameLabel, BaseStyles.marLeft10, BaseStyles.marBottom5, { fontSize: 15, fontFamily: "Quicksand_700Bold", color: "#000", alignItems: 'flex-end' }]}>
{student.student_name.charAt(0).toUpperCase() + student.student_name.slice(1)}
<Text style={{ fontSize: 11, color: "#bab8b8" }}> {student?.reply_date && moment(student?.reply_date).fromNow()}</Text></Text>
<Text style={[AppStyles.stdLabel, BaseStyles.marLeft10, { alignItems: 'flex-end' }]}>
<View style={[BaseStyles.marLeft10, {display:'flex', flexDirection:'row'}]}>
<Text style={[ AppStyles.diaryTypeLabel, AppStyles.diaryHomeWork, { alignItems: 'flex-end' }]}>
{student.is_completed ? "Completed" : "Incompleted"}
<Text style={{ fontSize: 11, color: "#bab8b8" }}> {student?.reply && student?.reply}</Text></Text>
</Text>
<Text style={[AppStyles.stdLabel, { fontSize: 11, color: "#bab8b8" }]}> {student?.reply && student?.reply}</Text>
</View>
</View>
</View>
))}
@ -357,21 +400,21 @@ class DiaryView extends React.PureComponent<any, any>{
(this.signedUserId === replyInfo?.parent_id) ?
<View key={index} style={[BaseStyles.padHorizontal10, AppStyles.studentCard, { flexDirection: 'row-reverse', padding: 7, marginBottom: 0 }]}>
<View style={[{ backgroundColor: BaseColors.headerStyleBackgroundColor, alignSelf: 'center', justifyContent: 'center' }, styles.listViewImage, BaseStyles.marRight10]}>
<Text style={{ fontSize: 14, color: BaseColors.white, textAlign: 'center' }}>{replyInfo?.username && replyInfo?.username.charAt(0) || 'NA'}</Text>
<Text style={{ fontSize: 14, color: BaseColors.white, textAlign: 'center' }}>{replyInfo?.username && replyInfo?.username.charAt(0).toUpperCase() || 'NA'}</Text>
</View>
<View style={[BaseStyles.marRight10, BaseStyles.padding10, { flexDirection: 'column', width: '85%', backgroundColor: "#f5f7f7", borderRadius: 20 }]}>
<Text style={[AppStyles.nameLabel, BaseStyles.marLeft10, { fontSize: 15, fontFamily: "Quicksand_700Bold", color: "#000", alignItems: 'flex-end' }]}>
{replyInfo?.username || 'NA'}
{replyInfo?.username.charAt(0).toUpperCase() + replyInfo?.username.slice(1) || 'NA'}
<Text style={{ fontSize: 11, color: "#bab8b8" }}> {moment(replyInfo?.reply_date).fromNow()}</Text></Text>
<Text style={[AppStyles.stdLabel, BaseStyles.marLeft10,]}>{replyInfo?.message}</Text>
</View>
</View> :
<View key={index} style={[BaseStyles.padHorizontal10, AppStyles.studentCard, BaseStyles.marTop5, { padding: 7, marginBottom: 0 }]}>
<View style={[{ backgroundColor: BaseColors.headerStyleBackgroundColor, alignSelf: 'center', justifyContent: 'center' }, styles.listViewImage, BaseStyles.marRight10]}>
<Text style={{ fontSize: 14, color: BaseColors.white, textAlign: 'center' }}>{replyInfo?.username && replyInfo?.username.charAt(0) || 'NA'}</Text>
<Text style={{ fontSize: 14, color: BaseColors.white, textAlign: 'center' }}>{replyInfo?.username && replyInfo?.username.charAt(0).toUpperCase() || 'NA'}</Text>
</View>
<View style={[BaseStyles.padding10, { flexDirection: 'column', width: '85%', backgroundColor: "#f5f7f7", borderRadius: 10 }]}>
<Text style={[AppStyles.nameLabel, { fontSize: 15, fontFamily: "Quicksand_700Bold", color: "#000", }]}>{replyInfo?.username || 'NA'}
<Text style={[AppStyles.nameLabel, { fontSize: 15, fontFamily: "Quicksand_700Bold", color: "#000", }]}>{replyInfo?.username.charAt(0).toUpperCase() + replyInfo?.username.slice(1) || 'NA'}
<Text style={{ fontSize: 11, color: "#bab8b8" }}> {moment(replyInfo?.reply_date).fromNow()}</Text></Text>
<Text style={[AppStyles.stdLabel]}>{replyInfo?.message}</Text>
</View>
@ -420,7 +463,7 @@ class DiaryView extends React.PureComponent<any, any>{
keyExtractor={(item, index) => index.toString()}
onEndReached={this.hasLoadMore}
onEndReachedThreshold={0.1}
removeClippedSubviews
removeClippedSubviews={false}
initialNumToRender={2}
onRefresh={() => this.onRefresh()}
refreshing={this.state.isFetching}

173
src/screens/Greetings.tsx Normal file
View File

@ -0,0 +1,173 @@
import React from "react"
import { StyleSheet, Text, View, TouchableOpacity, Image, ActivityIndicator, Animated, Easing } from 'react-native'
import BaseStyles, { AuthStyles } from "@theme/BaseStyles" //NOSONAR
import { connect } from "react-redux"
import PropTypes from 'prop-types'
import AsyncStorage from '@react-native-async-storage/async-storage'
import { ActionCreators } from "@actions" //NOSONAR
import { currentAcademicYear } from '@constants/Constants';
class Greetings extends React.Component<any, any>{
static propTypes = {};
state = {
greetingsData: '',
academicYear: '',
};
token: any;
dotAnimation = new Animated.Value(0);
animatedValues = [
new Animated.Value(0),
new Animated.Value(0),
new Animated.Value(0),
];
constructor(props: any) {
super(props)
}
async componentDidMount() {
this.token = await AsyncStorage.getItem('token')
await this.getCurrentAcademicYearData();
if (this.token && this.state.academicYear) {
await this.props.getSchoolGreetings({ token: this.token, academic_year: this.state.academicYear });
}
}
componentDidUpdate(prevProps: any) {
if (prevProps.schoolGreetings !== this.props.schoolGreetings) {
console.log(this.props.schoolGreetings)
this.animateDots();
this.setState({ greetingsData: this.props.schoolGreetings.data });
setTimeout(() => {
this.props.navigation.navigate('Home')
}, 5000);
}
}
getCurrentAcademicYearData = async () => {
try {
const userInfo = await currentAcademicYear();
if (userInfo) {
const academicYear = userInfo.current_academic_year;
this.setState({ academicYear });
}
} catch (error) {
console.log(error);
}
};
animateDots = () => {
const animations = this.animatedValues.map((animatedValue) => {
return Animated.loop(
Animated.sequence([
Animated.timing(animatedValue, {
toValue: 1,
duration: 500,
easing: Easing.linear,
useNativeDriver: true,
}),
Animated.timing(animatedValue, {
toValue: 0,
duration: 500,
easing: Easing.linear,
useNativeDriver: true,
}),
])
);
});
Animated.stagger(250, animations).start();
};
render() {
const { loading } = this.props;
const { greetingsData } = this.state;
const dotStyles = this.animatedValues.map((animatedValue, index) => {
const opacity = animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [0.3, 1],
});
return <Animated.Text key={index} style={[styles.dot, { opacity }]}></Animated.Text>;
});
if (loading) {
return (
<View style={AuthStyles.container}>
<ActivityIndicator size="large" color="#7165e3" />
</View>
);
}
return (<View style={AuthStyles.container}>
<View style={styles.circle}>
<Text style={styles.proverbText}>{greetingsData?.title}</Text>
<View style={styles.loadingContainer}>{dotStyles}</View>
</View>
</View>)
}
}
const styles = StyleSheet.create({
circle: {
width: 300,
height: 300,
borderRadius: 100,
backgroundColor: '#7165e3',
justifyContent: 'center',
alignItems: 'center',
padding: 20,
shadowColor: '#000',
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.3,
shadowRadius: 5,
elevation: 10,
},
loadingText: {
position: 'absolute',
bottom: 10,
fontSize: 16,
color: '#fff',
textAlign: 'center',
},
proverbText: {
fontSize: 18,
fontStyle: 'italic',
textAlign: 'center',
color: '#fff',
},
dot: {
fontSize: 30,
marginHorizontal: 5,
},
loadingContainer: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
marginTop: 50,
},
})
const mapStateToProps = (state: any) => ({
loading: state.school.loading,
error: state.school.error,
schoolGreetings: state.school.greetings,
})
const mapDispatchToProps = (dispatch: any) => ({
getSchoolGreetings: (data: any) => {
dispatch(ActionCreators.getGreetingsAction(data))
},
})
Greetings.propTypes = {
loading: PropTypes.bool,
loginUser: PropTypes.func,
checkUser: PropTypes.func,
token: PropTypes.any,
}
export default connect(mapStateToProps, mapDispatchToProps)(Greetings)

View File

@ -271,7 +271,7 @@ class Home extends React.Component<any, any>{
}
<View style={[BaseStyles.flexColum, BaseStyles.padding10]}>
<Text style={[BaseStyles.marBottom5, BaseStyles.font18, AppStyles.nameLabel]}>{item?.student_name}</Text>
<Text style={[BaseStyles.marBottom5, AppStyles.stdLabel]}>Card Id {item?.card_id}</Text>
<Text style={[BaseStyles.marBottom5, AppStyles.stdLabel]}>Card ID {item?.card_id}</Text>
<Text style={[BaseStyles.marBottom5, AppStyles.stdLabel]}>Attendance {item?.attendance}%</Text>
</View>
</TouchableOpacity>
@ -283,7 +283,7 @@ class Home extends React.Component<any, any>{
if (this.props.dashboardList.data.total) {
if (Math.ceil(this.props.dashboardList.data.total / this.props.dashboardList.data.per_page) > this.props.dashboardList.data.page) {
this.setState(
{ page: this.state.page + 1 },
{ page: this.props.dashboardList.data.page + 1 },
this.fetchAdminDashboardList
)
}

View File

@ -0,0 +1,269 @@
import React from "react"
import { StyleSheet, Text, View, TouchableOpacity, ActivityIndicator, Dimensions, 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 { ScrollView } from "react-native-gesture-handler"
import * as ScreenOrientation from 'expo-screen-orientation'
import { FontAwesome, Ionicons } from "@expo/vector-icons"
import { Formik, FieldArray } from 'formik'
import * as yup from 'yup'
import RNPickerSelect from "react-native-picker-select"
class HomeStudyGenerateQuestions 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 = 'Generate Questions';
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 data: any = this.props.route.params.info
console.log(data)
await this.props.getBlueprintSubjectDropdown({ token: this.token, academic_year: userDetails.current_academic_year, internal_grade_id: data.grade_id })
}
} else {
this.props.navigation.navigate('signin')
}
}
componentDidUpdate(prevProps: any) {
if (prevProps.randomQuestion != this.props.randomQuestion) {
if (this.props.randomQuestion.hasOwnProperty('status')) {
if (this.props.randomQuestion.status) {
this.props.navigation.navigate("HomeStudyQuestionList", { info: this.props.route.params.info })
}
}
}
}
/** 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()
}
onSelectChange = (event: any, action: any, setFieldValue: any) => {
setFieldValue(action, event)
}
onSubjectChange = async (event: any, action: any, setFieldValue: any) => {
setFieldValue(action, event)
await this.props.getBlueprintLessonDropdown({ token: this.token, academic_year: this.state.academicYear.toString(), internal_grade_id: this.props.route.params.info.grade_id, internal_subject_id: event })
}
getDataOptions = (data: any) => {
const options = data && data.map((item: any, index: any) => ({
key: index,
label: `${item?.internal_subject_name}`,
inputLabel: `${item?.internal_subject_name}`,
value: item.internal_subject_id
}))
if (options && options.length >= 0) {
return options
}
return []
}
getLessonDataOptions = (data: any) => {
const options = data && data.map((item: any, index: any) => ({
key: index,
label: `${item?.name}`,
inputLabel: `${item?.name}`,
value: item.uid
}))
if (options && options.length >= 0) {
return options
}
return []
}
onRandomFormSubmit = async (data: any, actions: any) => {
let formdata: any = {};
formdata['internal_grade_id'] = this.props.route.params.info.grade_id
formdata['internal_subject_id'] = data.subject
formdata['wizdomwaves_lesson_id'] = data.lesson
formdata['class_id'] = this.props.route.params.info.class_id
formdata['student_id'] = this.props.route.params.info.student_id.toString()
formdata['academic_year'] = this.state.academicYear.toString()
await this.props.generateHomeStudyRandomQuestion({ data: formdata, token: this.token })
}
render() {
return (<View style={[AppStyles.containerWoPadding, {}]}>
<ScrollView>
<View>
<Formik
enableReinitialize={true}
// validationSchema={generateFormvalidationSchema}
initialValues={{
subject: '',
lesson: '',
}}
onSubmit={(values, actions) => this.onRandomFormSubmit(values, actions)}>
{({
handleChange,
handleBlur,
handleSubmit,
values,
errors,
touched,
setFieldValue,
}: any) => (
<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
}}>
<View style={[AppStyles.inputView, BaseStyles.marTop5]}>
<RNPickerSelect
style={PickerStyle}
value={values.subject}
onValueChange={(itemValue, itemIndex) =>
this.onSubjectChange(itemValue, 'subject', setFieldValue)
}
placeholder={{
label: '--Select Subject--',
value: null,
}}
useNativeAndroidPickerStyle={false}
items={this.getDataOptions(this.props.blueprintSubject?.data)}
Icon={() => <Ionicons name="caret-down" size={14} color="gray" />}
/>
</View>
{errors.subject && touched.subject && (
<Text style={styles.error}>{errors.subject}</Text>
)}
<View style={[AppStyles.inputView, BaseStyles.marTop5]}>
<RNPickerSelect
style={PickerStyle}
value={values.lesson}
textInputProps={{ multiline: true, verticalAlign: 'middle', textAlignVertical: 'center' }}
//pickerProps={{numberOfLines: 1}}
onValueChange={(itemValue, itemIndex) =>
this.onSelectChange(itemValue, 'lesson', setFieldValue)
}
placeholder={{
label: '--Select Lesson--',
value: null,
}}
useNativeAndroidPickerStyle={false}
items={this.getLessonDataOptions(this.props.blueprintLesson?.data)}
Icon={() => <Ionicons name="caret-down" size={14} color="gray" />}
/>
</View>
{errors.lesson && touched.lesson && (
<Text style={styles.error}>{errors.lesson}</Text>
)}
{this.state.question_bank_lesson && this.props.blueprintLesson && !this.props.blueprintLesson?.data && (
<Text style={styles.error}>No Lesson</Text>
)}
<View>
<TouchableOpacity style={[AppStyles.primaryBtn, { alignSelf: 'center' }]}
onPress={handleSubmit} activeOpacity={0.8}>
<Text style={AppStyles.btnText}>Get questions</Text>
</TouchableOpacity>
</View>
</View>
</ScrollView>
</View>
)}
</Formik>
</View>
</ScrollView>
</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,
blueprintSubject: state.questionbank.bluprint_subject_dropdown,
blueprintLesson: state.questionbank.bluprint_lesson_dropdown,
records: state.questionbank.assessmentrecords,
randomQuestion: state.homestudy.random_question,
})
const mapDispatchToProps = (dispatch: any) => ({
getBlueprintSubjectDropdown: (data: any) => {
dispatch(ActionCreators.getBlueprintSubjectDropdownAction(data))
},
getBlueprintLessonDropdown: (data: any) => {
dispatch(ActionCreators.getBlueprintLessonDropdownAction(data))
},
generateHomeStudyRandomQuestion: (data: any) => {
dispatch(ActionCreators.generateHomeStudyRandomQuestionAction(data))
},
})
HomeStudyGenerateQuestions.propTypes = {
loading: PropTypes.bool,
error: PropTypes.object,
info: PropTypes.object,
}
export default connect(mapStateToProps, mapDispatchToProps)(HomeStudyGenerateQuestions)

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 * as ScreenOrientation from 'expo-screen-orientation'
import { FontAwesome, Ionicons } from "@expo/vector-icons"
class HomeStudyList extends React.Component<any, any>{
static propTypes = {};
isLoggedinAs: any;
scrollView: any;
token: any;
state: any = {
page: 1,
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.info
this.props.getHomeStudyList({ token: this.token, academic_year: this.state.academicYear.toString(), student_id: dataParams.student_id, class_id: dataParams.class_id, page_no: this.state.page, search: '' })
} else {
this.props.navigation.navigate('signin')
}
}
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()
}
toHomeStudyQuestionList = (item: any, val: any,) => {
this.props.navigation.navigate("HomeStudyQuestionList", { item: item, data: this.props.route.params.data, isFrom: 'homelist' })
}
toGenerateQuestion = () => {
this.props.navigation.navigate("HomeStudyGenerateQuestions", { info: this.props.route.params.info })
}
renderRow = ({ item }: any) => (
<View style={{ padding: 0, }}>
<TouchableOpacity style={styles.item}
onPress={this.toHomeStudyQuestionList.bind(this, item)}>
<View style={{ flexDirection: 'column', margin: 10 }}>
<Text style={[AppStyles.nameLabel, BaseStyles.font14, BaseStyles.font600SemiBold, BaseStyles.marBottom5,]}>{item?.name} </Text>
</View>
</TouchableOpacity>
</View>
)
fetchHomeStudyList = async () => {
const dataParams: any = this.props.route.params.info
this.props.getHomeStudyList({
token: this.token,
academic_year: this.state.academicYear.toString(),
student_id: dataParams.student_id,
class_id: dataParams.class_id,
page_no: this.state.page, search: ''
})
}
hasLoadMore = () => {
if (this.props.homeStudyList.hasOwnProperty('status')) {
if (this.props.homeStudyList.data.total) {
if (Math.ceil(this.props.homeStudyList.data.total / this.props.homeStudyList.data.per_page) > this.props.homeStudyList.data.page) {
this.setState(
{ page: this.state.page + 1 },
this.fetchHomeStudyList
)
}
}
}
}
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()}
onEndReached={this.hasLoadMore}
/>
}
{/* {this.props.loading && <View style={[BaseStyles.marVertical20, { flex: 1, justifyContent: 'center' }]}>
<ActivityIndicator size="large" color="#7165e3" />
</View>} */}
<TouchableOpacity style={[AppStyles.btnRound, AppStyles.btnPositionBtmRight]}
onPress={this.toGenerateQuestion} 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,
records: state.homestudy.home_study_records,
homeStudyList: state.homestudy.home_study_list,
})
const mapDispatchToProps = (dispatch: any) => ({
getHomeStudyList: (user: any) => {
dispatch(ActionCreators.getHomeStudyListAction(user))
},
})
HomeStudyList.propTypes = {
loading: PropTypes.bool,
error: PropTypes.object,
info: PropTypes.object,
}
export default connect(mapStateToProps, mapDispatchToProps)(HomeStudyList)

View File

@ -0,0 +1,154 @@
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 * as ScreenOrientation from 'expo-screen-orientation'
class HomeStudyQuestionList extends React.Component<any, any>{
static propTypes = {};
isLoggedinAs: any;
scrollView: any;
token: any;
state: any = {
academicYear: '',
questionData:[]
};
constructor(props: any) {
super(props)
}
async componentDidMount() {
const { navigation, route } = this.props;
const title = 'Question List';
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
// this.props.getAssessmentPagination({ token: this.token, academic_year: this.state.academicYear.toString(), question_paper_id: dataParams.uid, page_no: 1 })
if (this.props.route.params.hasOwnProperty('isFrom')) {
this.setState({ questionData: this.props.route.params.item.homestudy_details })
}else{
this.setState({ questionData: this.props.randomQuestion.data })
}
} 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()
}
toQuestionTransation = (item: any, val: any,) => {
const isfromhome = this.props.route.params.hasOwnProperty('isFrom') ? true : false;
this.props.navigation.navigate("HomeStudyQuestionTransation", { item: item, data:this.props.route.params.data, isfromhome: isfromhome })
}
renderRow = ({ item }: any) => (
<View style={{ padding: 0, }}>
<TouchableOpacity style={styles.item}
onPress={this.toQuestionTransation.bind(this, item)}>
<View style={{ flexDirection: 'column', margin: 10 }}>
<Text style={[AppStyles.nameLabel, BaseStyles.font14, BaseStyles.font600SemiBold, BaseStyles.marBottom5,]}>{item?.question} </Text>
</View>
</TouchableOpacity>
</View>
)
render() {
return (<View style={[AppStyles.containerWoPadding, {}]}>
{!this.props.loading && this.props.records && <FlatList
style={{ marginVertical: 12, marginHorizontal: 16 }}
data={this.state.questionData}
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,
},
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,
randomQuestion: state.homestudy.random_question,
})
const mapDispatchToProps = (dispatch: any) => ({
getAssessmentPagination: (user: any) => {
dispatch(ActionCreators.getAssessmentPaginationAction(user))
},
})
HomeStudyQuestionList.propTypes = {
loading: PropTypes.bool,
error: PropTypes.object,
info: PropTypes.object,
}
export default connect(mapStateToProps, mapDispatchToProps)(HomeStudyQuestionList)

View File

@ -0,0 +1,689 @@
import React, { Component, createRef } from "react"
import { StyleSheet, Pressable, Text, View, Image, TouchableOpacity, ActivityIndicator, Dimensions, FlatList, Button, PermissionsAndroid, Platform } 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 { ScrollView } from "react-native-gesture-handler"
import * as ScreenOrientation from 'expo-screen-orientation'
import { Ionicons } from "@expo/vector-icons"
import AudioRecorderPlayer from 'react-native-audio-recorder-player';
import RNFS from 'react-native-fs';
import { Waveform, IWaveformRef, FinishMode, UpdateFrequency, RecorderState, } from '@simform_solutions/react-native-audio-waveform';
import axios from 'axios';
class HomeStudyQuestionTransation extends React.Component<any, any>{
static propTypes = {};
isLoggedinAs: any;
scrollView: any;
audioPath: any;
token: any;
waveformRef: any = [];
//waveformRef = createRef<IWaveformRef>();
audioRecorderPlayer: any = new AudioRecorderPlayer();
state: any = {
academicYear: '',
conversations: [
//{ user_type: 'assistant', text: 'Please select a subject:' },
],
selectedSubject: '',
showOptions: true,
currentQuestionIndex: 0,
isRecording: false,
pauseRecording: false,
recordedAudioPath: null,
recordedAudios: {}, // To store audio paths for each question
hasPermission: false,
recordingIndex: 0,
currentPlayingIndex: 0,
};
constructor(props: any) {
super(props)
}
async componentDidMount() {
const { navigation, route } = this.props;
const title = 'Question Transaction';
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
this.audioPath = `${RNFS.DocumentDirectoryPath}/audio`;
RNFS.mkdir(this.audioPath);
const dataParams: any = this.props.route.params.data
const item: any = this.props.route.params.item
console.log(this.props.route.params)
if (this.props.route.params.isfromhome) {
await this.props.getHomeStudyTransactionDetails({ token: this.token, academic_year: userDetails.current_academic_year, uid: item.uid })
} else {
const initialConversations = [
{ user_type: 'bot', message_type: 'text', message: item.question },
{ user_type: 'user', message_type: 'audio_create', message: '' }
];
this.setState({ conversations: initialConversations })
}
}
} else {
this.props.navigation.navigate('signin')
}
}
componentDidUpdate(prevProps: any) {
if (prevProps.homeStudyDetails != this.props.homeStudyDetails) {
const homeStudyDetails = this.props.homeStudyDetails
const initialConversations = [
{ user_type: 'bot', message_type: 'text', message: homeStudyDetails.homestudy_details_data[0].question },
];
const values = [...initialConversations, ...homeStudyDetails.data]
const retryConversations = [
{ user_type: 'user', message_type: 'audio_create', message: '' }
];
const updatevalues = [...values, ...retryConversations]
this.setState({ conversations: updatevalues })
}
}
/** 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()
}
requestPermission = async () => {
if (Platform.OS === 'android') {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
{
title: 'Microphone Permission',
message: 'We need access to your microphone to record audio.',
buttonNeutral: 'Ask Me Later',
buttonNegative: 'Cancel',
buttonPositive: 'OK',
},
);
this.setState({ hasPermission: granted === PermissionsAndroid.RESULTS.GRANTED });
return granted === PermissionsAndroid.RESULTS.GRANTED
} catch (err) {
console.warn(err);
}
} else {
this.setState({ hasPermission: true });
return true;
}
return false;
};
startRecordingS = (conversationIndex: any) => {
this.waveformRef.current
?.startRecord({
updateFrequency: UpdateFrequency.low,
})
.then((e: any) => { console.log(e) })
.catch((e: any) => { console.log(e) });
};
startRecording = async (conversationIndex: any) => {
const { hasPermission, isRecording, conversations } = this.state;
const permission = !hasPermission ? await this.requestPermission() : hasPermission;
if (permission && !isRecording) {
const path = `${this.audioPath}/question_${conversationIndex}_${Date.now()}.mp3`;
this.setState(prevState => ({
recordedAudios: {
...prevState.recordedAudios,
[conversationIndex]: path,
},
recordingIndex: conversationIndex,
pauseRecording: false
}));
try {
await this.audioRecorderPlayer.startRecorder(path);
this.setState({ isRecording: true });
let current = this.waveformRef.current
this.audioRecorderPlayer.addRecordBackListener((e) => {
console.log('Recording...', e.currentPosition);
});
} catch (error) {
console.error('Failed to start recording:', error);
}
} else if (isRecording) {
this.stopRecording(conversationIndex);
}
};
stopRecording = async (conversationIndex: any) => {
const { isRecording } = this.state;
if (isRecording) {
console.log('stopo1')
try {
const audioPath = await this.audioRecorderPlayer.stopRecorder();
this.setState({ isRecording: false });
this.setState(prevState => ({
recordedAudios: {
...prevState.recordedAudios,
[conversationIndex]: audioPath,
},
recordingIndex: 0
}));
const formData = new FormData();
formData.append('file', {
uri: audioPath,
name: 'audio.m4a',
type: 'audio/m4a'
});
formData.append('model', 'whisper-1');
const responsetranscriptions = await axios.post('https://api.openai.com/v1/audio/transcriptions',
formData
, {
headers: {
'Authorization': `Bearer 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`,
'Content-Type': 'multipart/form-data'
}
});
// console.log(responsetranscriptions)
let answer = ''
const item: any = this.props.route.params.item
if (this.props.route.params.isfromhome) {
const homeStudyDetails = this.props.homeStudyDetails
answer = homeStudyDetails.homestudy_details_data[0].answer
} else {
answer = item.answer
}
console.log("item.answer")
console.log(answer)
const data: any = { "homestudydetails_id": item.uid, "user_type": "user", "message_type": "audio", "message": responsetranscriptions.data.text, "audio_path": audioPath, "score": 0 }
await this.props.addHomeStudyTransaction({ data: data, token: this.token })
const useraudiodata: any = { "homestudydetails_id": item.uid, "user_type": "user", "message_type": "text", "message": responsetranscriptions.data.text, "audio_path": "", "score": 0 }
await this.props.addHomeStudyTransaction({ data: useraudiodata, token: this.token })
var prompt = `You are a teacher evaluating a student's answer based on the exact answer provided.
I will give you two answers:
1. Exact Answer: The correct, full answer that students are expected to provide.
2. Student Answer: The answer written by the student.
Your task is to:
1. Compare the Student Answer with the Exact Answer & Highlight any mistakes, missing points, or inaccuracies in the Student Answer. Provide in bullet points.
2. If the provided answer is incorrect or incomplete, please suggest areas for improvement to enhance accuracy and clarity. Provide in bullet points.
3. Format should be Score: x/10, where 10 means the Student Answer perfectly matches the Exact Answer, and 0 means the Student Answer is completely incorrect. Score should not be in bullet points.
Here are the answers:
Exact Answer: ${answer}
Student Answer: ${responsetranscriptions.data.text}
`;
const response: any = await axios.post('https://api.openai.com/v1/chat/completions', {
model: 'gpt-4o',
messages: [{
"role": "system",
"content": "You are a helpful teacher."
},
{
"role": "user",
"content": prompt
},
],
}, {
headers: {
'Authorization': `Bearer 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`,
'Content-Type': 'application/json'
}
});
this.setState(prevState => ({
conversations: [
...prevState.conversations,
{ user_type: 'user', message_type: 'text', message: responsetranscriptions.data.text },
{ user_type: 'bot', message_type: 'score_card', message: response.data.choices[0].message.content },
{ user_type: 'user', message_type: 'audio_create', message: '' }
],
currentQuestionIndex: prevState.currentQuestionIndex + 1,
recordedAudioPath: null, // Clear previous audio response
}));
const score = await this.renderScore(response.data.choices[0].message.content)
const formdata: any = { "homestudydetails_id": item.uid, "user_type": "bot", "message_type": "score_card", "message": response.data.choices[0].message.content, "audio_path": "", "score": score }
await this.props.addHomeStudyTransaction({ data: formdata, token: this.token })
console.log('Recorded Audio Path:', audioPath);
} catch (error) {
console.error('Failed to stop recording:', error);
}
}
};
playAudio = async (questionIndex: any) => {
const { recordedAudios, currentPlayingIndex } = this.state;
const audioPath = recordedAudios[questionIndex];
try {
if (audioPath) {
this.waveformRef[questionIndex]?.startPlayer({ finishMode: FinishMode.stop });
this.setState({ currentPlayingIndex: questionIndex });
}
} catch (error) {
console.error('Failed to play audio:', error);
}
};
onPausePlay = async (index: any) => {
const { isRecording, pauseRecording } = this.state;
if (pauseRecording) {
await this.audioRecorderPlayer.resumeRecorder();
this.setState({ pauseRecording: false });
} else {
await this.audioRecorderPlayer.pauseRecorder();
this.setState({ pauseRecording: true });
}
};
playRecordAudio = async (audio: any, index: any) => {
const { recordedAudios, currentPlayingIndex } = this.state;
const audioPath = audio;
try {
if (audioPath) {
this.waveformRef[index]?.startPlayer({ finishMode: FinishMode.stop });
this.setState({ currentPlayingIndex: index });
}
} catch (error) {
console.error('Failed to play audio:', error);
}
};
extractParagraphs = (text: any) => {
const regex = /(\d+\..*?)(?=\d+\.)/gs;
const matches = text.split('\n\n').filter((text: any) => !text.startsWith('Score:'));
return matches ? matches.map((match: any, index: any) => {
const cleanedMatch = match.trim();
if (cleanedMatch.startsWith('3. Provide a score')) {
return null;
}
return {
id: `${index + 1}`,
content: cleanedMatch
};
}).filter(Boolean) : [];
};
renderScore = (score_card: any) => {
const scoreRegex = /Score:\s*(\d+)\/10/;
const match = score_card.match(scoreRegex);
const score = match ? parseInt(match[1], 10) / 10 : 0;
return score
}
renderScoreCard = (score_card: any) => {
const scoreRegex = /Score:\s*(\d+)\/10/;
const match = score_card.match(scoreRegex);
const score = match ? parseInt(match[1], 10) : 0;
const cards = this.extractParagraphs(score_card)
return (
<View>
<Text style={styles.score}>Score:{score}</Text>
{cards && cards.length > 0 && <View style={styles.scoreView}>
{cards && cards.map((message, index) => (
<View
key={index}
style={styles.scoreCard}
>
<Text>{message.content} </Text>
</View>
))}
</View>}
</View>
);
};
render() {
const { isRecording, conversations, showOptions, recordedAudios, currentQuestionIndex, recordingIndex, pauseRecording } = this.state;
return (<View style={styles.container}>
<ScrollView contentContainerStyle={styles.scrollContent}>
<View style={styles.innerContainer}>
{conversations && conversations.map((message, index) => (
<View
key={index}
style={[
styles.messageContainer,
message.user_type === 'bot'
? styles.assistantContainer
: styles.userContainer
]}
>
{message.message_type === 'text' ?
<Text
style={[
styles.message,
message.user_type === 'bot'
? styles.assistantMessage
: styles.userMessage
]}
>
{message.message}
</Text> : null}
{message.message_type === 'score_card' ?
<View
style={[
styles.message,
message.user_type === 'bot'
? styles.assistantScoreMessage
: styles.userMessage
]}
>
{this.renderScoreCard(message.message)}
</View> : null}
{message.message_type === 'audio' && (
<View style={styles.listItemWidth}>
<View style={styles.buttonContainer}>
<TouchableOpacity onPress={() => this.playRecordAudio(message.audio_path, index)} style={styles.playBackControlPressable}>
{/* <Text style={styles.audioIconText}>Play Recording</Text> */}
<Ionicons
name={'play'}
size={24}
color="#fff"
/>
</TouchableOpacity>
{recordingIndex !== index && <Waveform
mode="static"
//ref={this.waveformRef[index]}
ref={(ref) => (this.waveformRef[index] = ref)}
path={message.audio_path}
candleSpace={2}
containerStyle={styles.waveform}
candleWidth={4}
scrubColor="gray"
waveColor="white"
onPlayerStateChange={playerState => console.log(playerState)}
onPanStateChange={isMoving => console.log(isMoving)}
onCurrentProgressChange={(currentProgress, songDuration) => {
console.log(
'currentProgress ',
currentProgress,
'songDuration ',
songDuration
);
}}
/>}
</View>
</View>
)}
{message.message_type === 'audio_create' && (
<View style={styles.audioControl}>
{recordedAudios[index] == undefined && (<View>
<TouchableOpacity onPress={() => this.startRecording(index)} style={styles.audioIcon} disabled={isRecording && recordingIndex !== index}>
<Text style={styles.audioIconText}>{recordingIndex === index ? 'Stop Recording' : 'Record Audio'}</Text>
</TouchableOpacity>
</View>)}
{recordingIndex == index && (<View>
<TouchableOpacity onPress={() => this.startRecording(index)} style={styles.audioIcon} disabled={isRecording && recordingIndex !== index}>
<Text style={styles.audioIconText}>{recordingIndex === index ? 'Stop Recording' : 'Record Audio'}</Text>
</TouchableOpacity>
</View>)}
{recordedAudios[index] && recordingIndex == index && (
<View>
<TouchableOpacity onPress={() => this.onPausePlay(index)} style={styles.audioIcon} disabled={isRecording && recordingIndex !== index}>
<Text style={styles.audioIconText}>{pauseRecording ? 'Resume Audio' : 'Pause Audio'}</Text>
</TouchableOpacity>
</View>)}
{recordedAudios[index] && recordingIndex !== index && (
<View style={styles.listItemWidth}>
<View style={styles.buttonContainer}>
<TouchableOpacity onPress={() => this.playAudio(index)} style={styles.playBackControlPressable}>
<Ionicons
name={'play'}
size={24}
color="#fff"
/>
</TouchableOpacity>
{recordingIndex !== index && <Waveform
mode="static"
//ref={this.waveformRef[index]}
ref={(ref) => (this.waveformRef[index] = ref)}
path={recordedAudios[index]}
candleSpace={2}
candleWidth={4}
containerStyle={styles.waveform}
scrubColor="gray"
waveColor="white"
onPlayerStateChange={playerState => console.log(playerState)}
onPanStateChange={isMoving => console.log(isMoving)}
onCurrentProgressChange={(currentProgress, songDuration) => {
console.log(
'currentProgress ',
currentProgress,
'songDuration ',
songDuration
);
}}
/>}
</View>
</View>
)}
</View>
)}
</View>
))}
</View>
</ScrollView>
{this.props.loading && <View style={[BaseStyles.marVertical20, { flex: 1, justifyContent: 'center' }]}>
<ActivityIndicator size="large" color="#7165e3" />
</View>}
</View>)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
scrollContent: {
},
innerContainer: {
flex: 1,
},
messageContainer: {
marginVertical: 5,
},
assistantContainer: {
alignItems: 'flex-start',
},
userContainer: {
alignItems: 'flex-end',
},
message: {
fontSize: 15,
padding: 10,
margin: 10,
maxWidth: '90%',
},
assistantMessage: {
backgroundColor: '#dcdcdc',
color: '#000',
borderTopRightRadius: 95,
borderBottomRightRadius: 95,
borderBottomLeftRadius: 95,
},
assistantScoreMessage: {
backgroundColor: '#dcdcdc',
color: '#000',
borderTopRightRadius: 30,
borderBottomRightRadius: 30,
borderBottomLeftRadius: 30,
},
userMessage: {
borderRadius: 10,
backgroundColor: '#7165e3',
color: '#ffffff',
borderTopLeftRadius: 15,
borderTopRightRadius: 15,
borderBottomRightRadius: 15,
borderBottomLeftRadius: 15,
},
optionContainer: {
marginTop: 20,
},
audioIcon: {
padding: 10,
backgroundColor: '#f0f0f0',
borderRadius: 50,
marginHorizontal: 5,
},
audioIconText: {
fontSize: 16,
color: '#333',
},
audioControl: {
flexDirection: 'row',
marginTop: 5,
},
scoreCard: {
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,
},
score: {
backgroundColor: '#dcdcdc',
color: '#000',
},
scoreView: {
marginTop: 10
},
recordAudioContainer: {
padding: 10,
backgroundColor: '#f7f7f7',
borderRadius: 15,
marginVertical: 5,
width: 200,
},
playPauseButton: {
width: 50,
height: 50,
borderRadius: 25,
backgroundColor: '#25D366',
justifyContent: 'center',
alignItems: 'center',
},
waveform: {
flex: 1,
height: 100,
},
listItemWidth: {
width: '80%',
maxWidth: '80%',
minWidth: '80%',
},
buttonContainer: {
flexDirection: 'row',
alignItems: 'center',
overflow: 'hidden',
columnGap: 10,
paddingHorizontal: 10,
borderRadius: 10,
margin: 10,
backgroundColor: '#7165e3',
color: '#ffffff',
borderTopLeftRadius: 15,
borderTopRightRadius: 15,
borderBottomRightRadius: 15,
borderBottomLeftRadius: 15,
height: 80,
},
playBackControlPressable: {
height: 30,
width: 30,
justifyContent: 'center',
},
buttonImage: {
height: 30,
width: 30,
alignSelf: 'flex-end',
},
staticWaveformView: {
flex: 1,
},
})
const mapStateToProps = (state: any) => ({
loading: state.questionbank.loading,
randomQuestion: state.homestudy.random_question,
homeStudyDetails: state.homestudy.home_study_details,
})
const mapDispatchToProps = (dispatch: any) => ({
getHomeStudyTransactionDetails: (user: any) => {
dispatch(ActionCreators.getHomeStudyTransactionDetailsAction(user))
},
addHomeStudyTransaction: (user: any) => {
dispatch(ActionCreators.addHomeStudyTransactionAction(user))
},
})
HomeStudyQuestionTransation.propTypes = {
loading: PropTypes.bool,
error: PropTypes.object,
info: PropTypes.object,
}
export default connect(mapStateToProps, mapDispatchToProps)(HomeStudyQuestionTransation)

View File

@ -26,7 +26,7 @@ class InstantFeedbackView extends React.Component<any, any>{
async componentDidMount() {
const { navigation, route } = this.props;
const title = 'Instant Feedbacks';
const title = 'Instant Feedback';
navigation.setOptions({ title });
this.getCurrentAcademicYearData() //fetch the Current Academic year from Login Response
this.token = await AsyncStorage.getItem('token')

View File

@ -154,6 +154,21 @@ class NoticeBoardView extends React.Component<any, any>{
)
},
}
const tagsStyles = {
table: {
borderBottomWidth: 1,
borderRightWidth: 1,
borderColor: '#bfbfbf', },
td: {
borderWidth: 1,
borderRightWidth: 0,
borderBottomWidth: 0,
borderColor: '#bfbfbf',
padding: 10,
},
};
return (
<View style={[BaseStyles.padHorizontal10, AppStyles.diaryCard]}>
<View style={AppStyles.diaryHeaderContainer}>
@ -187,6 +202,7 @@ class NoticeBoardView extends React.Component<any, any>{
<RenderHtml
source={{ html: `<div class="html-format">${item?.message}</div>` }}
contentWidth={contentWidth-40}
tagsStyles={tagsStyles}
classesStyles={{
'html-format': {
fontFamily: "Quicksand_500Medium", color: BaseColors.black,

View File

@ -200,7 +200,8 @@ class OTPVerification extends React.Component<any, any>{
</View>
<Text style={[AuthStyles.subTextMsg, AuthStyles.stepMsg]}>STEP 2/3</Text>
<Text style={[BaseStyles.headerLabel, BaseStyles.font700Bold,]}>{isEmailAuth ? "Verify your Email" : "Verify your number"}</Text>
<Text style={[AuthStyles.subTextMsg, BaseStyles.font500Medium]}>We'll text you on {this.state.username}</Text>
<Text style={[AuthStyles.subTextMsg, BaseStyles.font500Medium, {marginBottom:0, marginTop:10, lineHeight:20, paddingVertical: 2,}]}>We'll text you on</Text>
<Text style={[AuthStyles.subTextMsg, BaseStyles.font500Medium, {lineHeight:20, paddingVertical: 2}]}> {this.state.username}</Text>
<View style={{ flexDirection: 'row', }}>
{Array.from({ length: 6 }).map((_, index) => (

View File

@ -241,6 +241,14 @@ class QuestionScreen extends React.Component<any, any>{
]).start()
};
quickSubmit = async () => {
const { questionnaire_details } = this.props.questionDetails
this.setState({ currentQuestion: questionnaire_details.length })
const { unique_id, class_id, student_id } = this.props.questionDetails
await this.props.createPsychometricAnswer({ data: { academic_year: this.state.academicYear.toString(), unique_id: unique_id, student_id: student_id, class_id: class_id,quick_submit: true}, token: this.token })
}
render() {
const { currentQuestion, starCount } = this.state
// const { questionnaire_details } = this.props.questionDetails
@ -269,6 +277,14 @@ class QuestionScreen extends React.Component<any, any>{
/>
</View>
<View style={[styles.container]}>
{ this.state.currentQuestion > 2 && <View style={[styles.innercontainer, { alignSelf: 'center' }]}>
<View style={styles.btnItem}>
<TouchableOpacity disabled={this.props.loading}
style={[AppStyles.primaryBtn, { alignSelf: 'center' }]} onPress={this.quickSubmit} activeOpacity={0.8}>
<Text style={AppStyles.btnText} > Quick Submit</Text>
</TouchableOpacity>
</View>
</View>}
<View style={[styles.innercontainer]}>
<View style={styles.btnItem}>
{this.state.currentQuestion != 0 ? (<TouchableOpacity style={[AppStyles.defaultBtn, { alignSelf: 'center' }]} onPress={this.handlePrevious} activeOpacity={0.8}>

View File

@ -108,6 +108,7 @@ class ReportPsychometric extends React.Component<any, any>{
colors: processedColors,
valueTextSize: 10, // Increase the font size for the values
// valueFormatter: "###.###'%'",
valueTextColor: processColor('#282313'),
},
},
],
@ -121,17 +122,20 @@ class ReportPsychometric extends React.Component<any, any>{
position: 'BOTTOM',
labelRotationAngle: -60, // Rotate the labels to make them vertical
drawLabels: true,
textColor: processColor('#282313'),
}}
yAxis={{
left: {
axisMinimum: 0,
textColor: processColor('#282313'),
},
right: {
enabled: false,
},
}}
animation={{ durationX: 1000 }}
legend={{ enabled: true }}
legend={{ enabled: false }}
marker={{
enabled: false,
}}
@ -176,6 +180,7 @@ class ReportPsychometric extends React.Component<any, any>{
//form: "CIRCLE",
position: 'BELOW_CHART_CENTER',
wordWrapEnabled: true,
textColor: processColor('#282313'),
};
return (
@ -199,7 +204,7 @@ class ReportPsychometric extends React.Component<any, any>{
data={data}
legend={legend}
entryLabelColor={processColor('white')}
entryLabelTextSize={14}
entryLabelTextSize={8}
rotationEnabled={true}
rotationAngle={45}
drawEntryLabels={true}

View File

@ -82,12 +82,14 @@ class Assessment extends React.Component<any, any>{
this.props.navigation.navigate("AssessmentScanner", { data: this.props.route.params.data })
}
renderRow = ({ item }: any) => (
<View style={{ padding: 0, }}>
renderRow = ({ item }: any) => {
return(
<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>
<Text style={[AppStyles.nameLabel, BaseStyles.font16, BaseStyles.font600SemiBold, BaseStyles.marBottom5,]}>{item?.class_name} </Text>
</View>
<View style={styles.actions}>
<TouchableOpacity style={styles.iconButton} onPress={this.toAssessmentEdit.bind(this, item)} activeOpacity={0.8}>
@ -99,7 +101,7 @@ class Assessment extends React.Component<any, any>{
</View>
</TouchableOpacity>
</View>
)
)}
render() {
return (<View style={[AppStyles.containerWoPadding, {}]}>

View File

@ -15,6 +15,15 @@ import * as yup from 'yup'
import RNPickerSelect from "react-native-picker-select"
import { Ionicons } from "@expo/vector-icons"
const assessmentValidationSchema = yup.object().shape({
class_id: yup
.string()
.required('Grade is required'),
student_id: yup
.string()
.required('Section is required'),
})
class AssessmentCreate extends React.Component<any, any>{
static propTypes = {};
isLoggedinAs: any;
@ -27,7 +36,8 @@ class AssessmentCreate extends React.Component<any, any>{
question_update: false,
grade_id: '',
grade_name: '',
student_list: []
student_list: [],
totalRating: 0
};
constructor(props: any) {
@ -71,12 +81,13 @@ class AssessmentCreate extends React.Component<any, any>{
const sortedQuestions = questionRecords.sort((a: any, b: any) => {
return order[a.question_type_name] - order[b.question_type_name];
});
let questionCounter = 1;
const initializedData = sortedQuestions.map((group: any) => ({
...group,
question: group.question.map((q: any) => ({
question: group.question.map((q: any,index:any) => ({
...q,
currentRating: 0, // Default rating set to 0
question_number: questionCounter++,
})),
}));
@ -90,10 +101,10 @@ class AssessmentCreate extends React.Component<any, any>{
}
}
else if (prevProps.assessmentStudentList != this.props.assessmentStudentList) {
if(this.props.assessmentStudentList.status){
const filterStudents = this.props.studentList.data.filter((student: any) => !this.props.assessmentStudentList.includes(student.student_id.toString()));
if(this.props.assessmentStudentList.status && this.props.studentList.data){
const filterStudents = this.props.studentList.data.filter((student: any) => !this.props.assessmentStudentList.data.includes(student.student_id.toString()));
this.setState({ student_list: filterStudents })
}else{
}else if(this.props.studentList.data){
this.setState({ student_list: this.props.studentList.data })
}
}
@ -128,12 +139,71 @@ class AssessmentCreate extends React.Component<any, any>{
this.setState({ question_details: updatedQuestions })
}
calculateTotalMarks = (updatedQuestions: any) =>{
const totalRating = updatedQuestions.reduce((sum: number, question: any) => {
return (
sum +
question.question.reduce((questionSum: number, q: any) => {
return questionSum + q.currentRating;
}, 0)
);
}, 0);
this.setState({totalRating: totalRating })
}
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.calculateTotalMarks(updatedQuestions)
this.setState({ question_details: updatedQuestions, })
};
renderStarRows = (item:any) => {
// console.log(item)
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: any) => this.handleStarPress(newRating, i,item?.question_id)}
fullStarColor={'orange'}
starSize={35} // Adjust the size of each star
halfStarEnabled={true}
/>
);
}
return starRows;
};
renderRow = (item: any, index:any) => {
return (
<View style={{ padding: 0, }}>
<View style={styles.item}>
<Text>{index+1} </Text>
<StarRating
<Text>{item.question_number} </Text>
{/* <Text>{item.question}</Text> */}
{/* <StarRating
disabled={false}
maxStars={item?.question_type_marks}
rating={item?.currentRating}
@ -146,7 +216,8 @@ class AssessmentCreate extends React.Component<any, any>{
//starSize={35}
halfStarEnabled={true}
containerStyle={styles.starRating}
/>
/> */}
<View>{this.renderStarRows(item)}</View>
</View>
</View>
)
@ -198,8 +269,7 @@ class AssessmentCreate extends React.Component<any, any>{
}
render() {
const { grade_id, grade_name } = this.state
const { grade_id, grade_name, totalRating } = this.state
return (<View style={[AppStyles.containerWoPadding, {}]}>
{grade_name && this.props.class_standard?.data &&
<ScrollView style={{ marginVertical: 8, marginHorizontal: 8 }}>
@ -210,6 +280,7 @@ class AssessmentCreate extends React.Component<any, any>{
<Formik
enableReinitialize={true}
validationSchema={assessmentValidationSchema}
initialValues={{
class_id: '',
student_id: ''
@ -220,12 +291,12 @@ class AssessmentCreate extends React.Component<any, any>{
<>
<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"
<TextInput style={AppStyles.inputText} name="firstname" placeholder="Enter the Class"
onChangeText={handleChange('firstname')} onBlur={handleBlur('firstname')}
value={grade_name} keyboardType="default" maxLength={50} />
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]}>Section</Text>
<Text style={[AppStyles.cardHeader, BaseStyles.marTop5]}>Section<Text style={AppStyles.required}> *</Text></Text>
<View style={[AppStyles.inputView, BaseStyles.marTop5, { width: '100%' }]}>
<RNPickerSelect
style={PickerStyle}
@ -242,7 +313,7 @@ class AssessmentCreate extends React.Component<any, any>{
Icon={() => <Ionicons name="caret-down" size={14} color="gray" />}
/>
</View>
{(errors.lastname && touched.lastname) && <Text style={AppStyles.error}>{errors.lastname}</Text>}
{(errors.class_id && touched.class_id) && <Text style={AppStyles.error}>{errors.class_id}</Text>}
<Text style={[AppStyles.cardHeader, BaseStyles.marTop5]}>Student<Text style={AppStyles.required}> *</Text></Text>
<View style={[AppStyles.inputView, BaseStyles.marTop5, { width: '100%' }]}>
<RNPickerSelect
@ -260,7 +331,7 @@ class AssessmentCreate extends React.Component<any, any>{
Icon={() => <Ionicons name="caret-down" size={14} color="gray" />}
/>
</View>
{(errors.phone_number && touched.phone_number) && <Text style={AppStyles.error}>{errors.phone_number}</Text>}
{(errors.student_id && touched.student_id) && <Text style={AppStyles.error}>{errors.student_id}</Text>}
{!this.props.loading && this.state.question_details && this.state.question_details.map((item: any, index: any) => (
<View style={[ BaseStyles.marBottom5,BaseStyles.marTop10]}>
@ -273,6 +344,8 @@ class AssessmentCreate extends React.Component<any, any>{
))}
</View>
))}
<Text style={[AppStyles.nameLabel, BaseStyles.font18, BaseStyles.font700Bold, BaseStyles.marBottom5, {alignSelf:'flex-end'}]}>Total Marks: {totalRating}</Text>
<View style={[styles.container]}>
<View style={styles.btnItem}>
<TouchableOpacity style={[AppStyles.defaultBtn, { alignSelf: 'center' }]} onPress={this.onCancel} activeOpacity={0.8}>
@ -295,9 +368,6 @@ class AssessmentCreate extends React.Component<any, any>{
</View>}
</View>
</ScrollView>}
</View>)
}
}

View File

@ -28,7 +28,8 @@ class AssessmentEdit extends React.Component<any, any>{
grade_id:'',
grade_name:'',
student_list:[],
studentName:''
studentName:'',
totalRating: 0
};
constructor(props: any) {
@ -72,15 +73,16 @@ class AssessmentEdit extends React.Component<any, any>{
const sortedQuestions = questionRecords.sort((a:any, b:any) => {
return order[a.question_type_name] - order[b.question_type_name];
});
let questionCounter = 1;
const initializedData = sortedQuestions.map((group:any) => ({
...group,
question: group.question.map((q:any) => ({
...q,
currentRating: this.props.assessment.data.assessment_details[q.uid], // Default rating set to 0
question_number: questionCounter++,
})),
}));
this.calculateTotalMarks(initializedData)
this.setState({ question_details: initializedData, question_update:true})
}
@ -98,6 +100,7 @@ class AssessmentEdit extends React.Component<any, any>{
if (this.props.assessmentUpdate.status) {
const question_paper_id: any = this.props.route.params.data.uid
this.props.getAssessmentPagination({ token: this.token, academic_year: this.state.academicYear.toString(), question_paper_id:question_paper_id,page_no:1})
await this.props.initAssessment({})
this.props.navigation.navigate("Assessment", { data: this.props.route.params.data})
}
}
@ -124,19 +127,31 @@ class AssessmentEdit extends React.Component<any, any>{
await ScreenOrientation.unlockAsync()
}
onStarRatingPress = (rating: number, questionId:any) => {
// 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;
}),
}));
// 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 })
// this.setState({ question_details: updatedQuestions })
// }
calculateTotalMarks = (updatedQuestions: any) =>{
const totalRating = updatedQuestions.reduce((sum: number, question: any) => {
return (
sum +
question.question.reduce((questionSum: number, q: any) => {
return questionSum + q.currentRating;
}, 0)
);
}, 0);
this.setState({totalRating: totalRating })
}
handleStarPress = (newRating:any, rowIndex:any, questionId:any) => {
@ -152,8 +167,8 @@ class AssessmentEdit extends React.Component<any, any>{
return q;
}),
}));
this.setState({ question_details: updatedQuestions })
this.calculateTotalMarks(updatedQuestions)
this.setState({ question_details: updatedQuestions, })
};
@ -188,7 +203,7 @@ class AssessmentEdit extends React.Component<any, any>{
return (
<View style={{ padding: 0, }}>
<View style={styles.item}>
<Text>{index+1} </Text>
<Text>{item.question_number} </Text>
{/* <StarRating
disabled={false}
maxStars={item?.question_type_marks}
@ -242,7 +257,7 @@ class AssessmentEdit extends React.Component<any, any>{
}
render() {
const { grade_id , grade_name , studentName} = this.state
const { grade_id , grade_name , studentName, totalRating} = this.state
return (<View style={[AppStyles.containerWoPadding, {}]}>
{
@ -262,7 +277,7 @@ class AssessmentEdit extends React.Component<any, any>{
<>
<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"
<TextInput style={AppStyles.inputText} name="firstname" placeholder="Enter the Class"
onChangeText={handleChange('firstname')} onBlur={handleBlur('firstname')}
value={grade_name} keyboardType="default" maxLength={50} editable={false}/>
</View>
@ -285,6 +300,8 @@ class AssessmentEdit extends React.Component<any, any>{
</View>
)) }
<Text style={[AppStyles.nameLabel, BaseStyles.font18, BaseStyles.font700Bold, BaseStyles.marBottom5, {alignSelf:'flex-end'}]}>Total Marks: {totalRating}</Text>
<View style={[styles.container]}>
<View style={styles.btnItem}>
<TouchableOpacity style={[AppStyles.defaultBtn, { alignSelf: 'center' }]} onPress={this.onCancel} activeOpacity={0.8}>

View File

@ -1,5 +1,5 @@
import React, { Component } from 'react';
import { Alert, Image, ImageStyle, StyleSheet, View, ViewStyle, TouchableOpacity, Text } from 'react-native';
import { Alert, Image, ImageStyle, StyleSheet, View, ViewStyle, TouchableOpacity, Text, ActivityIndicator } 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"
@ -9,6 +9,9 @@ import { AppStyles, BaseStyles, PickerStyle } from "@theme/BaseStyles" //NOSONA
import RNPickerSelect from "react-native-picker-select"
import { Ionicons } from "@expo/vector-icons"
import RNFS from 'react-native-fs';
import { UserRoles, currentYear, common, currentAcademicYear } from "@constants/Constants" //NOSONAR
import { ScrollView } from "react-native-gesture-handler"
import Toast from 'react-native-simple-toast'
interface State {
scannedImage: string | null;
@ -24,6 +27,11 @@ class AssessmentScanner extends React.Component<any, any> {
state: any = {
scannedImage: null,
class_id: '',
academicYear: '',
question_details: [],
question_update: false,
scan_answer_details: {},
answerCapture: false
};
@ -37,6 +45,7 @@ class AssessmentScanner extends React.Component<any, any> {
const { navigation, route } = this.props;
const title = 'Assessment Scanner';
navigation.setOptions({ title });
this.getCurrentAcademicYearData()
this.token = await AsyncStorage.getItem('token')
const userInfo = await AsyncStorage.getItem('userInfo')
@ -44,6 +53,8 @@ class AssessmentScanner extends React.Component<any, any> {
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 })
const question_paper_id: any = this.props.route.params.data.uid
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')
@ -52,31 +63,101 @@ class AssessmentScanner extends React.Component<any, any> {
async componentDidUpdate(prevProps: any) {
console.log('assessmentAnswer')
console.log(this.props.assessmentAnswer)
if (prevProps.assessmentAnswer != 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))
const data = this.props.assessmentAnswer?.data
//console.log(JSON.stringify(data))
const initializedData = data?.result_table_data ? this.state.question_details.map((group: any) => ({
...group,
question: group.question.map((q: any) => ({
...q,
currentRating: data.result_table_data[q.uid]?.correct_answer,
question_number: data.result_table_data[q.uid]?.question_number, // Default rating set to 0
status: data.result_table_data[q.uid]?.status,
})),
})) : this.state.question_details;
this.setState({ scan_answer_details: data, question_details: initializedData, answerCapture: true })
//Alert.alert('Required', JSON.stringify(data))
}
if (this.props.assessmentAnswer.hasOwnProperty('message')) {
else if (this.props.assessmentAnswer.hasOwnProperty('message')) {
const message = this.props.assessmentAnswer?.message
await this.props.initAssessment({})
//await this.props.initAssessment({})
Alert.alert('Required', JSON.stringify(message))
}
if (this.props.assessmentAnswer.hasOwnProperty('something_wrong')) {
else if (this.props.assessmentAnswer.hasOwnProperty('something_wrong')) {
const message = this.props.assessmentAnswer?.something_wrong
await this.props.initAssessment({})
//await this.props.initAssessment({})
Alert.alert('Required', JSON.stringify(message))
}
}
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 (this.props.assessmentCreate?.is_exists == true) {
const uid = this.props.assessmentCreate?.uid
const { scannedImage, scan_answer_details } = this.state;
let data: any = {}
data['class_id'] = scan_answer_details?.class_id.toString()
data['student_id'] = scan_answer_details?.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.updateAssessment({ data, uid:uid, token: this.token })
}
}
if (this.props.assessmentUpdate.hasOwnProperty('status')) {
if (this.props.assessmentUpdate.status) {
const question_paper_id: any = this.props.route.params.data.uid
await this.props.initAssessment({})
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})
}
}
}
scanDocument = async () => {
const result = await DocumentScanner.scanDocument();
const result = await DocumentScanner.scanDocument({
maxNumDocuments: 1,
croppedImageQuality:100
});
const scannedImages = await result.scannedImages;
if (scannedImages && scannedImages.length > 0) {
@ -84,19 +165,38 @@ class AssessmentScanner extends React.Component<any, any> {
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())
formData.append("academic_year", this.state.academicYear.toString())
formData.append('omr_sheet', {
uri: scannedImages[0],
type: 'image/jpeg',
name: 'scanned_image.jpg',
});
const audioPath = `${RNFS.ExternalStorageDirectoryPath}/Pictures`;
const destinationPath = `${audioPath}/scanned_image_${Date.now()}.jpg`;
// Ensure the directory exists
await RNFS.copyFile(scannedImages[0], destinationPath);
console.log('Image saved successfully at:', destinationPath);
await this.props.createAssessmentScanAnswer({ data: formData, token: this.token })
await this.setState({ scannedImage: scannedImages[0] });
}
}
getCurrentAcademicYearData = () => {
currentAcademicYear().then((userInfo) => {
if (userInfo) {
const academicYear = userInfo.current_academic_year
this.setState({ academicYear: academicYear })
}
}).catch(error => {
console.log(error)
})
}
onSelectChange = async (id: any) => {
if (id) {
this.setState({ class_id: id })
@ -118,20 +218,108 @@ class AssessmentScanner extends React.Component<any, any> {
}
toScan = async () => {
const { class_id } = this.state
if(class_id){
await this.scanDocument();
}else{
Toast.show("Please select the section", Toast.SHORT)
}
}
renderRow = (item: any, index: any) => {
return (
<View style={{ padding: 0, }}>
<View style={[styles.item, item.status == false ? { borderWidth: 1, borderColor: 'red', borderRadius: 10} : {} ]}>
<Text>{item.question_number} </Text>
<Text>{item.currentRating} </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 = () => {
const { scannedImage, scan_answer_details } = this.state;
let data: any = {}
data['class_id'] = scan_answer_details?.class_id.toString()
data['student_id'] = scan_answer_details?.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: data, token: this.token })
}
onCancel = () => {
this.props.navigation.navigate("Assessment", { data: this.props.route.params.data })
}
render() {
const { scannedImage } = this.state;
const { scannedImage, scan_answer_details, answerCapture } = this.state;
return (
<View style={styles.container}>
{scannedImage ? (
<ScrollView style={{ marginVertical: 8, marginHorizontal: 8 }}>
<View style={{
margin: 2, padding: 16, backgroundColor: 'white', shadowColor: "#8D81F8",
shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.01, shadowRadius: 16, elevation: 3, zIndex: 10
}}>
{scannedImage && answerCapture ? <>
{/*
<Image
resizeMode="contain"
style={styles.image}
source={{ uri: scannedImage }}
/>
) : (
source={{uri:scannedImage}} /> */}
<View>
<Text>Name : {scan_answer_details?.student_name}</Text>
<Text>Class : {scan_answer_details?.class_name}</Text>
</View>
{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, index)}
</View>
))}
</View>
))
}
<View style={[styles.btnContainer]}>
<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={this.onAssessmentSubmit} activeOpacity={0.8}>
<Text style={AppStyles.btnText}>Submit</Text>
</TouchableOpacity>
</View>
</View>
</> : (
<View>
<View style={[AppStyles.inputView, BaseStyles.marTop5, { width: '100%' }]}>
<RNPickerSelect
@ -149,13 +337,18 @@ class AssessmentScanner extends React.Component<any, any> {
Icon={() => <Ionicons name="caret-down" size={14} color="gray" />}
/>
</View>
<TouchableOpacity style={BaseStyles.loginBtn} onPress={this.toScan} activeOpacity={0.8}>
<TouchableOpacity disabled={this.props.loading} style={[BaseStyles.loginBtn, { alignSelf: 'center' }]} onPress={this.toScan} activeOpacity={0.8}>
<Text style={BaseStyles.loginText} >Scan</Text>
</TouchableOpacity>
</View>
)}
</View>
</ScrollView>
{this.props.loading && <View style={[BaseStyles.marVertical20, { flex: 1, justifyContent: 'center' }]}>
<ActivityIndicator size="large" color="#7165e3" />
</View>}
</View>
);
}
}
@ -176,6 +369,30 @@ const styles = StyleSheet.create({
justifyContent: 'center',
alignItems: 'center',
} as ViewStyle,
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,
},
btnContainer: {
flex: 1,
flexDirection: 'row',
alignItems: 'flex-start'
//justifyContent: 'center',
// alignItems: 'center',
},
btnItem: {
width: '50%', // is 50% of whole width
},
});
const mapStateToProps = (state: any) => ({
@ -185,6 +402,9 @@ const mapStateToProps = (state: any) => ({
records: state.questionbank.assessmentrecords,
class_standard: state.classes.class_standard,
assessmentAnswer: state.questionbank.assessment_answer,
assessmentCreate: state.questionbank.assessment_create,
question_details: state.questionbank.question_details,
assessmentUpdate: state.questionbank.assessment_update,
})
const mapDispatchToProps = (dispatch: any) => ({
@ -199,7 +419,16 @@ const mapDispatchToProps = (dispatch: any) => ({
},
createAssessmentScanAnswer: (user: any) => {
dispatch(ActionCreators.createAssessmentScanAnswerAction(user))
}
},
getQuestionPaper: (user: any) => {
dispatch(ActionCreators.getQuestionPaperAction(user))
},
createAssessment: (user: any) => {
dispatch(ActionCreators.createAssessmentAction(user))
},
updateAssessment: (user: any) => {
dispatch(ActionCreators.updateAssessmentAction(user))
},
})
AssessmentScanner.propTypes = {

View File

@ -18,8 +18,8 @@ const Sepator = ({ style }: any) => <View style={[BaseStyles.borderSeparator, st
const validationSchema = yup.object().shape({
question_name: yup
.string()
.min(3, ({ min }) => `Question Name must be at least ${min} characters`)
.max(50, ({ max }) => `Question Name cannot more than ${max} characters`)
.min(3, ({ min }) => `The Question Name must be at least ${min} characters`)
.max(50, ({ max }) => `The Question Name cannot be more than ${max} characters`)
.required('Question Name is required'),
questions: yup
.array()
@ -330,7 +330,7 @@ class QuestionSetCreate extends React.Component<any, any>{
</Text>
)}
<Text style={[BaseStyles.font16,BaseStyles.font700Bold,BaseStyles.marTop10]}>
Answers
Options :
</Text>
{errors.questions &&
errors.questions[index] &&

View File

@ -21,8 +21,8 @@ const Sepator = ({ style }: any) => <View style={[BaseStyles.borderSeparator, st
const generateFormvalidationSchema = yup.object().shape({
question_name: yup
.string()
.min(3, ({ min }) => `Question Name must be at least ${min} characters`)
.max(50, ({ max }) => `Question Name cannot more than ${max} characters`)
.min(3, ({ min }) => `The Question Name must be at least ${min} characters`)
.max(50, ({ max }) => `The Question Name cannot be more than ${max} characters`)
.required('Question Name is required'),
question_count: yup
.number()
@ -248,11 +248,7 @@ class QuestionSetImport extends React.Component<any, any>{
formdata['academic_year'] = this.state.academicYear.toString()
formdata['school_id'] = this.props.profileInfo.data.school_id
if(this.isLoggedinAs == UserRoles.schoolAdmin){
formdata['internal_grade_id'] = this.props.route.params.info.grade_id
}else{
formdata['internal_grade_id'] = this.props.route.params.info.class_id
}
formdata['internal_subject_id'] = Number(this.props.route.params.info.subject_id)
formdata['question_count'] = Number(data.question_count)
@ -515,7 +511,7 @@ class QuestionSetImport extends React.Component<any, any>{
</Text>
)}
<Text style={[BaseStyles.font16,BaseStyles.font700Bold,BaseStyles.marTop10]}>
Answers
Options :
</Text>
{errors.questions &&
errors.questions[index] &&

View File

@ -204,60 +204,60 @@ class QuizSummaryDetails extends React.Component<any, any>{
summaryDetails && <View style={[styles.studentCard, BaseStyles.primaryShadow, BaseStyles.marHorizontal5]}>
<View style={[{ flexDirection: 'row' }, BaseStyles.marVertical10, BaseStyles.marHorizontal5]}>
<View style={[{ flexDirection: 'column', width: '50%' }, BaseStyles.marHorizontal5]}>
<Text style={[BaseStyles.font500Medium, BaseStyles.font15, BaseStyles.marVertical2]}>Average :
<Text style={[BaseStyles.font400Regular, BaseStyles.font15, BaseStyles.marHorizontal2]}> {summaryDetails?.average}</Text>
<Text style={[BaseStyles.font700Bold, BaseStyles.font15, BaseStyles.marVertical2]}>Average :
<Text style={[BaseStyles.font700Bold, BaseStyles.font15, BaseStyles.marHorizontal2]}> {summaryDetails?.average}</Text>
</Text>
<Text style={[BaseStyles.font500Medium, BaseStyles.font15, BaseStyles.marVertical2]}>Lowest :
<Text style={[BaseStyles.font400Regular, BaseStyles.font15, BaseStyles.marHorizontal2]}> {summaryDetails?.lowest}</Text>
<Text style={[BaseStyles.font700Bold, BaseStyles.font15, BaseStyles.marVertical2]}>Lowest :
<Text style={[BaseStyles.font700Bold, BaseStyles.font15, BaseStyles.marHorizontal2]}> {summaryDetails?.lowest}</Text>
</Text>
<Text style={[BaseStyles.font500Medium, BaseStyles.font15, BaseStyles.marVertical2]}>Participant Count :
<Text style={[BaseStyles.font400Regular, BaseStyles.font15, BaseStyles.marHorizontal2]}> {summaryDetails?.participants}</Text>
<Text style={[BaseStyles.font700Bold, BaseStyles.font15, BaseStyles.marVertical2]}>Participant Count :
<Text style={[BaseStyles.font700Bold, BaseStyles.font15, BaseStyles.marHorizontal2]}> {summaryDetails?.participants}</Text>
</Text>
{(summaryDetails?.easiest_topics && summaryDetails?.easiest_topics.length !== 0) && <View style={BaseStyles.marVertical2}>
<Text style={[BaseStyles.font500Medium, BaseStyles.font15]}>Easy Topics : </Text>
<Text style={[BaseStyles.font400Regular, BaseStyles.font15, BaseStyles.marHorizontal2]}>{summaryDetails?.easiest_topics.toString()}</Text>
<Text style={[BaseStyles.font700Bold, BaseStyles.font15]}>Easy Topics : </Text>
<Text style={[BaseStyles.font700Bold, BaseStyles.font15, BaseStyles.marHorizontal2]}>{summaryDetails?.easiest_topics.toString()}</Text>
</View>}
</View>
<View style={[{ flexDirection: 'column', width: '48%' }, BaseStyles.marRight10]}>
<Text style={[BaseStyles.font500Medium, BaseStyles.font15, BaseStyles.marVertical2]}>Highest :
<Text style={[BaseStyles.font400Regular, BaseStyles.font15, BaseStyles.marHorizontal2]}> {summaryDetails?.highest}</Text>
<Text style={[BaseStyles.font700Bold, BaseStyles.font15, BaseStyles.marVertical2]}>Highest :
<Text style={[BaseStyles.font700Bold, BaseStyles.font15, BaseStyles.marHorizontal2]}> {summaryDetails?.highest}</Text>
</Text>
<Text style={[BaseStyles.font500Medium, BaseStyles.font15, BaseStyles.marVertical2]}>Median :
<Text style={[BaseStyles.font400Regular, BaseStyles.font15, BaseStyles.marHorizontal2]}> {summaryDetails?.median}</Text>
<Text style={[BaseStyles.font700Bold, BaseStyles.font15, BaseStyles.marVertical2]}>Median :
<Text style={[BaseStyles.font700Bold, BaseStyles.font15, BaseStyles.marHorizontal2]}> {summaryDetails?.median}</Text>
</Text>
<Text style={[BaseStyles.font500Medium, BaseStyles.font15, BaseStyles.marVertical2]}>Question Count :
<Text style={[BaseStyles.font400Regular, BaseStyles.font15, BaseStyles.marHorizontal2]}> {summaryDetails?.total_questions}</Text>
<Text style={[BaseStyles.font700Bold, BaseStyles.font15, BaseStyles.marVertical2]}>Question Count :
<Text style={[BaseStyles.font700Bold, BaseStyles.font15, BaseStyles.marHorizontal2]}> {summaryDetails?.total_questions}</Text>
</Text>
{(summaryDetails?.difficult_topics && summaryDetails?.difficult_topics.length !== 0) && <View style={BaseStyles.marVertical2}>
<Text style={[BaseStyles.font500Medium, BaseStyles.font15]}>Difficult Topics : </Text>
<Text style={[BaseStyles.font400Regular, BaseStyles.font15, BaseStyles.marHorizontal2]}>{summaryDetails?.difficult_topics.toString()}</Text>
<Text style={[BaseStyles.font700Bold, BaseStyles.font15]}>Difficult Topics : </Text>
<Text style={[BaseStyles.font700Bold, BaseStyles.font15, BaseStyles.marHorizontal2]}>{summaryDetails?.difficult_topics.toString()}</Text>
</View>}
</View>
</View>
</View> : <View style={[styles.studentCard, BaseStyles.primaryShadow, BaseStyles.marHorizontal5]}>
<View style={[{ flexDirection: 'row' }, BaseStyles.marVertical10, BaseStyles.marHorizontal5]}>
<View style={[{ flexDirection: 'column', width: '50%' }, BaseStyles.marHorizontal5]}>
<Text style={[BaseStyles.font500Medium, BaseStyles.font15, BaseStyles.marVertical2]}>Attempted :
<Text style={[BaseStyles.font400Regular, BaseStyles.font15, BaseStyles.marHorizontal2]}> {summaryDetails?.attempted}</Text>
<Text style={[BaseStyles.font700Bold, BaseStyles.font15, BaseStyles.marVertical2]}>Attempted :
<Text style={[BaseStyles.font700Bold, BaseStyles.font15, BaseStyles.marHorizontal2]}> {summaryDetails?.attempted}</Text>
</Text>
<Text style={[BaseStyles.font500Medium, BaseStyles.font15, BaseStyles.marVertical2]}>Correct :
<Text style={[BaseStyles.font400Regular, BaseStyles.font15, BaseStyles.marHorizontal2]}> {summaryDetails?.correct}</Text>
<Text style={[BaseStyles.font700Bold, BaseStyles.font15, BaseStyles.marVertical2]}>Correct :
<Text style={[BaseStyles.font700Bold, BaseStyles.font15, BaseStyles.marHorizontal2]}> {summaryDetails?.correct}</Text>
</Text>
{(summaryDetails?.easy_topic && summaryDetails?.easy_topic.length !== 0) && <View style={BaseStyles.marVertical2}>
<Text style={[BaseStyles.font500Medium, BaseStyles.font15]}>Easy Topics : </Text>
<Text style={[BaseStyles.font400Regular, BaseStyles.font15, BaseStyles.marHorizontal2]}>{summaryDetails?.easy_topic.toString()}</Text>
<Text style={[BaseStyles.font700Bold, BaseStyles.font15]}>Easy Topics : </Text>
<Text style={[BaseStyles.font700Bold, BaseStyles.font15, BaseStyles.marHorizontal2]}>{summaryDetails?.easy_topic.toString()}</Text>
</View>}
</View>
<View style={[{ flexDirection: 'column', width: '48%' }, BaseStyles.marRight10]}>
<Text style={[BaseStyles.font500Medium, BaseStyles.font15, BaseStyles.marVertical2]}>Percentile :
{/* <Text style={[BaseStyles.font500Medium, BaseStyles.font15, BaseStyles.marVertical2]}>Percentile :
<Text style={[BaseStyles.font400Regular, BaseStyles.font15, BaseStyles.marHorizontal2]}> {summaryDetails?.percentile}</Text>
</Text>
<Text style={[BaseStyles.font500Medium, BaseStyles.font15, BaseStyles.marVertical2]}>Percentage :
<Text style={[BaseStyles.font400Regular, BaseStyles.font15, BaseStyles.marHorizontal2]}> {summaryDetails?.percentage}</Text>
</Text> */}
<Text style={[BaseStyles.font700Bold, BaseStyles.font15, BaseStyles.marVertical2]}>Percentage :
<Text style={[BaseStyles.font700Bold, BaseStyles.font15, BaseStyles.marHorizontal2]}> {summaryDetails?.percentage}</Text>
</Text>
{(summaryDetails?.difficult_topic && summaryDetails?.difficult_topic.length !== 0) && <View style={BaseStyles.marVertical2}>
<Text style={[BaseStyles.font500Medium, BaseStyles.font15]}>Difficult Topics : </Text>
<Text style={[BaseStyles.font400Regular, BaseStyles.font15, BaseStyles.marHorizontal2]}>{summaryDetails?.difficult_topic.toString()}</Text>
<Text style={[BaseStyles.font700Bold, BaseStyles.font15]}>Difficult Topics : </Text>
<Text style={[BaseStyles.font700Bold, BaseStyles.font15, BaseStyles.marHorizontal2]}>{summaryDetails?.difficult_topic.toString()}</Text>
</View>}
</View>
</View>

View File

@ -96,14 +96,15 @@ class QuizzesDetailView extends React.Component<any, any>{
quizzesInfo && <View>
<View style={[styles.studentCard, BaseStyles.primaryShadow]}>
<View style={[{ flexDirection: 'row' }]}>
<Text style={[BaseStyles.font600SemiBold, BaseStyles.font16, BaseStyles.padding10]}>{quizzesInfo?.question_name}</Text>
<Text style={[BaseStyles.font600SemiBold, BaseStyles.font16, BaseStyles.padding10]}>Quizz : {quizzesInfo?.question_name}</Text>
</View>
<Sepator />
<View style={[BaseStyles.marVertical10, BaseStyles.marHorizontal10, { flexDirection: 'row', alignSelf: 'center', justifyContent: 'center' }]}>
<View style={[{ flexDirection: 'column', width: '20%' }]}>
<View style={[BaseStyles.marVertical10, BaseStyles.marHorizontal10, { flexDirection: 'row' }]}>
{/* <View style={[{ flexDirection: 'column', width: '20%' }]}>
<Text style={[BaseStyles.font600SemiBold, BaseStyles.font15]}>Subject :</Text>
</View> */}
<View style={[{ flexDirection: 'row' }]}>
<Text style={[BaseStyles.font600SemiBold, BaseStyles.font15]}>Subject : </Text>
</View>
<View style={[{ flexDirection: 'column', width: '80%', }]}>
<Text style={[BaseStyles.font700Bold, BaseStyles.font15, { color: BaseColors.mainColor }]}>{quizzesInfo?.subject_name || 'NA'}</Text>
</View>
</View>

View File

@ -110,7 +110,7 @@ class QuizzesView extends React.Component<any, any>{
if (this.props.quizzesList.data.total) {
if (Math.ceil(this.props.quizzesList.data.total / this.props.quizzesList.data.per_page) > this.props.quizzesList.data.page) {
this.setState(
{ page: this.state.page + 1 },
{ page: this.props.quizzesList.data.page + 1 },
this.fetchAdminQuizzesDetailList
)
}
@ -123,7 +123,7 @@ class QuizzesView extends React.Component<any, any>{
if (this.props.quizzesList.data.total) {
if (Math.ceil(this.props.quizzesList.data.total / this.props.quizzesList.data.per_page) > this.props.quizzesList.data.page) {
this.setState(
{ page: this.state.page + 1 },
{ page: this.props.quizzesList.data.page + 1 },
this.fetchQuizzesDetailList
)
}
@ -172,7 +172,7 @@ class QuizzesView extends React.Component<any, any>{
{this.isLoggedinAs && ((this.isLoggedinAs === UserRoles.schoolAdmin) || this.isLoggedinAs === UserRoles.teacher) ?
<View style={{ flex: 1, flexDirection: "column", justifyContent: 'center', alignItems: 'center' }}>
<Text style={[AppStyles.nameLabel, BaseStyles.font20, BaseStyles.font700Bold]}>{item?.question_count}</Text>
<Text style={[AppStyles.stdLabel]}>Question</Text>
<Text style={[AppStyles.stdLabel]}>{item?.question_count > 1 ? 'Questions' : 'Question'}</Text>
</View> :
<View style={{ flex: 1, flexDirection: "column", justifyContent: 'center', alignItems: 'center' }}>
<Text style={[AppStyles.nameLabel, BaseStyles.font20, BaseStyles.font700Bold]}>{item?.student_performance}</Text>

View File

@ -39,7 +39,7 @@ class Register extends React.Component<any, any>{
if (this.props.checkuser_data.hasOwnProperty('status')) {
if (this.props.checkuser_data.status) {
if (!this.props.isRedirected) {
this.props.navigation.navigate("otp", { action: 'register', username: this.state.username.value })
this.props.navigation.navigate("otp", { action: 'register', username: this.state.username.value, isEmailAuth: this.state.isEmailAuth })
}
}
}

View File

@ -0,0 +1,332 @@
import { ActionCreators } from '@actions';
import { currentAcademicYear } from '@constants/Constants';
import { Ionicons } from '@expo/vector-icons';
import AsyncStorage from '@react-native-async-storage/async-storage';
import React, { Component } from 'react';
import { View, StyleSheet, Dimensions, Text, TouchableWithoutFeedback, Modal } from 'react-native';
import { Calendar } from 'react-native-big-calendar';
import { connect } from 'react-redux';
interface MyEvent {
title: string;
start: Date;
end: Date;
allDay?: boolean;
color?: string;
}
class SchoolCalendar extends Component<any, any> {
token: any;
constructor(props: {}) {
super(props);
this.state = {
academicYear: '',
currentDate: new Date(2024, 9, 1),
eventsData: [],
tooltipVisible: false,
hoveredEvent: null,
modalVisible: false,
selectedEvent: null,
};
}
async componentDidMount() {
const { navigation } = this.props;
const title = 'Noticeboard';
navigation.setOptions({ title });
await this.getCurrentAcademicYearData();
this.token = await AsyncStorage.getItem('token');
console.log("this.props.route.params.info.grade_id")
console.log(this.props.route.params.info.grade_id)
if (this.token && this.state.academicYear) {
this.props.getSchoolCalendar({
token: this.token,
data: { academic_year: this.state.academicYear, grade: this.props.route.params.info.grade_id },
});
}
this.setEventsFromCalendarDetails();
}
componentDidUpdate(prevProps: any) {
if (prevProps.schoolCalender !== this.props.schoolCalender) {
this.setEventsFromCalendarDetails();
}
}
getCurrentAcademicYearData = async () => {
try {
const userInfo = await currentAcademicYear();
if (userInfo) {
const academicYear = userInfo.current_academic_year;
this.setState({ academicYear });
}
} catch (error) {
console.log(error);
}
};
handleNavigate = (direction: 'prev' | 'next') => {
this.setState((prevState: any) => {
const newDate = new Date(prevState.currentDate);
newDate.setMonth(
direction === 'next' ? prevState.currentDate.getMonth() + 1 : prevState.currentDate.getMonth() - 1
);
return { currentDate: newDate };
});
};
setEventsFromCalendarDetails = () => {
const { schoolCalender } = this.props;
if (schoolCalender && schoolCalender.data) {
const events = schoolCalender.data.map((detail: any) => {
const startDate = new Date(`${detail.start_date}`);
const endDate = new Date(`${detail.end_date}`);
return {
title: detail.event_desc,
start: startDate,
end: endDate,
allDay: true,
color: detail.is_working_day ? 'blue' : 'red',
};
}).reverse();
this.setState({ eventsData: events });
}else {
this.setState({ eventsData: [] });
}
};
renderHeaderForMonthView = ({ date, onNavigate }: any) => {
const {currentDate} = this.state
const monthNames = [
'January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December',
];
return (
<View style={styles.header}>
<TouchableWithoutFeedback onPress={() => this.handleNavigate('prev')}>
<Ionicons name="chevron-back" size={24} color="gray" style={styles.navButtonIcon} />
</TouchableWithoutFeedback>
<Text style={styles.monthHeader}>
{`${monthNames[currentDate.getMonth()]} ${currentDate.getFullYear()}`}
</Text>
<TouchableWithoutFeedback onPress={() => this.handleNavigate('next')}>
<Ionicons name="chevron-forward" size={24} color="gray" style={styles.navButtonIcon} />
</TouchableWithoutFeedback>
</View>
);
};
handleCellPress = (event: any) => {
this.setState({ selectedEvent: event, modalVisible: true });
};
handleOutsideClick = () => {
this.setState({ tooltipVisible: false, hoveredEvent: null });
};
render() {
const { currentDate, eventsData, modalVisible, selectedEvent } = this.state;
return (
<TouchableWithoutFeedback onPress={this.handleOutsideClick}>
{eventsData && (
<View style={styles.container}>
<Calendar
events={eventsData}
date={currentDate}
height={Dimensions.get('window').height - 100}
renderHeaderForMonthView={(event) => this.renderHeaderForMonthView(event)}
mode="month"
swipeEnabled={false}
onPressEvent={(event) => this.handleCellPress(event)}
onPressCell={(event)=> console.log(event)}
eventCellStyle={(event: MyEvent) => ({
backgroundColor: event.color || 'blue',
borderRadius: 5,
zIndex:1000,
borderWidth: 0,
alignItems: 'center'
})}
calendarCellTextStyle={{fontSize: 13, textAlign:'left', fontWeight: 'bold'}}
onPressMoreLabel={(event)=> this.handleCellPress(event)}
moreLabel='+{moreCount} More'
calendarCellStyle={{
borderStartColor: 'transparent'
}}
showAdjacentMonths={true}
sortedMonthView={true}
/>
<Modal
visible={modalVisible}
transparent={true}
animationType="slide"
onRequestClose={() => this.setState({ modalVisible: false })}
>
<View style={styles.modalContainer}>
<View style={styles.modalContent}>
{Array.isArray(selectedEvent) ?(
selectedEvent?.length > 0 ? (
selectedEvent.map((event: any, index: number) => (
<View key={index} style={styles.eventDetails}>
<Text style={styles.modalTitle}>Event Name: {event.title}</Text>
<Text style={styles.modalDescription}>
{new Date(event.start).toLocaleDateString()} - {new Date(event.end).toLocaleDateString()}
</Text>
</View>
))
) : (
<Text style={styles.noEventText}>No Events Selected</Text>
)
)
:
(
selectedEvent &&
<View style={styles.eventDetails}>
<Text style={styles.modalTitle}>Event Name: {selectedEvent.title}</Text>
<Text style={styles.modalDescription}>
{new Date(selectedEvent.start).toLocaleDateString()} - {new Date(selectedEvent.end).toLocaleDateString()}
</Text>
</View>
)}
<TouchableWithoutFeedback onPress={() => this.setState({ modalVisible: false })}>
<View style={styles.closeButtonContainer}>
<View style={styles.closeButton}>
<Text style={styles.closeButtonText}>Close</Text>
</View>
</View>
</TouchableWithoutFeedback>
</View>
</View>
</Modal>
</View>
)}
</TouchableWithoutFeedback>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
padding: 10,
},
header: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingVertical: 10,
marginBottom: 10,
},
monthHeader: {
fontSize: 20,
fontWeight: '600',
textAlign: 'center',
flex: 1,
},
navButtonIcon: {
paddingHorizontal: 10,
},
eventContainer: {
padding: 5,
borderRadius: 5,
marginBottom: 2,
},
eventTitle: {
fontSize: 10,
fontWeight: 'bold',
color: '#fff',
},
tooltipWrapper: {
position: 'absolute',
top: -50,
left: '50%',
transform: [{ translateX: -50 }],
zIndex: 100,
width: 'auto',
maxWidth: 200,
overflow: 'visible',
alignItems: 'center',
},
tooltipContainer: {
backgroundColor: 'black',
paddingVertical: 5,
paddingHorizontal: 10,
borderRadius: 5,
minWidth: 100,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 10,
},
tooltipText: {
color: 'white',
fontSize: 12,
textAlign: 'center',
},
eventDetails: {
marginBottom: 10,
},
noEventText: {
fontSize: 16,
fontStyle: 'italic',
},
// Modal
modalContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0, 0, 0, 0.5)',
},
modalContent: {
width: 300,
padding: 20,
borderRadius: 10,
backgroundColor: '#fff',
justifyContent: 'center',
},
modalTitle: {
fontSize: 16,
fontWeight: 'bold',
color:'#000',
marginBottom: 5,
},
modalDescription: {
fontSize: 14,
marginBottom: 5,
},
closeButtonContainer: {
marginTop: 10,
alignItems: 'center',
},
closeButton: {
backgroundColor: "#7165e3",
alignItems: 'center',
width: 80,
borderRadius: 5,
padding: 10,
},
closeButtonText: {
color: '#fff',
fontSize: 12,
},
});
const mapStateToProps = (state: any) => ({
loading: state.school.loading,
error: state.school.error,
schoolCalender: state.school.calendar,
});
const mapDispatchToProps = (dispatch: any) => ({
getSchoolCalendar: (academicYear: any) =>
dispatch(ActionCreators.getCalendarAction(academicYear)),
});
export default connect(mapStateToProps, mapDispatchToProps)(SchoolCalendar);

View File

@ -92,7 +92,7 @@ class SignIn extends React.Component<any, any>{
routes: [{ name: 'app' }],
})
);
//this.props.navigation.navigate("Home")
this.props.navigation.navigate("Greetings")
}
}
}

View File

@ -45,6 +45,7 @@ const StudentCreateValidationSchema = yup.object().shape({
.matches(formValidationPatten.emailPatten, 'Please enter valid Email Id')
.required('Email Id is Required'),
gender: yup.string().required('Gender is required'),
date_of_birth: yup.string().required('Date if birth is required'),
})
@ -304,8 +305,8 @@ class StudentCreate extends React.Component<any, any>{
<>
<Text style={[AppStyles.cardHeader, BaseStyles.marTop5]}>Student Name<Text style={AppStyles.required}> *</Text></Text>
<View style={[AppStyles.inputView, BaseStyles.marTop5]} >
<TextInput style={AppStyles.inputText} name="student_name" placeholder="Enter the Student Name"
onChangeText={handleChange('student_name')} onBlur={handleBlur('student_name')}
<TextInput style={AppStyles.inputText} name="student_name" placeholder="Enter the Student Name" placeholderTextColor="#003f5c"
onChangeText={(text) => handleChange('student_name')(text.charAt(0).toUpperCase() + text.slice(1))} onBlur={handleBlur('student_name')}
value={values.student_name} keyboardType="default" maxLength={50}/>
</View>
{(errors.student_name && touched.student_name) && <Text style={AppStyles.error}>{errors.student_name}</Text>}
@ -332,32 +333,32 @@ class StudentCreate extends React.Component<any, any>{
<View style={[AppStyles.inputView, BaseStyles.marTop5,]} >
<TextInput style={AppStyles.inputText} name="phone_number" placeholder="Enter the Phone Number"
onChangeText={handleChange('phone_number')} onBlur={handleBlur('phone_number')}
value={values.phone_number} keyboardType="phone-pad" maxLength={10} />
value={values.phone_number} keyboardType="phone-pad" maxLength={10} placeholderTextColor="#003f5c"/>
</View>
{(errors.phone_number && touched.phone_number) && <Text style={AppStyles.error}>{errors.phone_number}</Text>}
<Text style={[AppStyles.cardHeader, BaseStyles.marTop5]}>Email Id<Text style={AppStyles.required}> *</Text></Text>
<View style={[AppStyles.inputView, BaseStyles.marTop5]} >
<TextInput style={AppStyles.inputText} name="email_id" placeholder="Enter the Email Id" onChangeText={handleChange('email_id')} onBlur={handleBlur('email_id')}
value={values.email_id} keyboardType="default" />
value={values.email_id} keyboardType="default" placeholderTextColor="#003f5c"/>
</View>
{(errors.email_id && touched.email_id) && <Text style={AppStyles.error}>{errors.email_id}</Text>}
<Text style={[AppStyles.cardHeader, BaseStyles.marTop5]}>Parent First Name<Text style={AppStyles.required}> *</Text></Text>
<View style={[AppStyles.inputView, BaseStyles.marTop5,]} >
<TextInput style={AppStyles.inputText} name="parent_firstname" placeholder="Enter the Parent First Name"
onChangeText={handleChange('parent_firstname')} onBlur={handleBlur('parent_firstname')}
value={values.parent_firstname} keyboardType="default" maxLength={50} />
value={values.parent_firstname} keyboardType="default" maxLength={50} placeholderTextColor="#003f5c"/>
</View>
{(errors.parent_firstname && touched.parent_firstname) && <Text style={AppStyles.error}>{errors.parent_firstname}</Text>}
<Text style={[AppStyles.cardHeader, BaseStyles.marTop5]}>Parent Last Name</Text>
<View style={[AppStyles.inputView, BaseStyles.marTop5,]} >
<TextInput style={AppStyles.inputText} name="parent_lastname" placeholder="Enter the Parent last Name"
onChangeText={handleChange('parent_lastname')} onBlur={handleBlur('parent_lastname')}
value={values.parent_lastname} keyboardType="default" maxLength={50} />
value={values.parent_lastname} keyboardType="default" maxLength={50} placeholderTextColor="#003f5c"/>
</View>
{(errors.parent_lastname && touched.parent_lastname) && <Text style={AppStyles.error}>{errors.parent_lastname}</Text>}
<Text style={[AppStyles.cardHeader, BaseStyles.marTop5]}> Date of Birth </Text>
<Text style={[AppStyles.cardHeader, BaseStyles.marTop5]}> Date of Birth <Text style={AppStyles.required}> *</Text></Text>
<TouchableOpacity onPress={this.showDatePicker} style={[AppStyles.inputView, BaseStyles.marTop5]}>
<Text style={AppStyles.inputText}>

View File

@ -1,5 +1,5 @@
import React from "react"
import { StyleSheet, Text, View, TouchableOpacity, ScrollView, Image, ActivityIndicator, Linking, Modal } from 'react-native'
import { StyleSheet, Text, View, TouchableOpacity, ScrollView, Image, ActivityIndicator, Linking, Modal, Dimensions } from 'react-native'
import { AppStyles, BaseStyles } from "@theme/BaseStyles" //NOSONAR
import Images from "@assets/Assets" //NOSONAR
@ -11,13 +11,13 @@ import AsyncStorage from "@react-native-async-storage/async-storage"
import { common, currentYear, currentAcademicYear, fetchBaseUrl } from "@constants/Constants" //NOSONAR
import Constants from "expo-constants"
import BaseColors from "@theme/Colors" //NOSONAR
import { VictoryLine, VictoryChart, VictoryPie, createContainer,VictoryAxis, VictoryLabel } from "victory-native"
import { VictoryLine, VictoryChart, VictoryPie, createContainer,VictoryAxis, VictoryLabel ,VictoryLegend } from "victory-native"
import moment, { Moment } from 'moment'
const Sepator = ({ style }: any) => <View style={[BaseStyles.separator, style]} />
const VictoryZoomVoronoiContainer: any = createContainer("zoom", "voronoi")
const { width } = Dimensions.get('window')
class StudentProfile extends React.Component<any, any>{
static propTypes = {};
isLoggedinAs: any;
@ -157,7 +157,7 @@ class StudentProfile extends React.Component<any, any>{
perfomanceInfo['weak_topics_visible'] = false
perfomanceInfo.percentage.map((topicData: any, topicIndex: any) => {
const performanceObj: any = {}
performanceObj['x'] = `${topicData}%`
performanceObj['x'] = `${topicData}% (${perfomanceInfo.percentage_label[topicIndex]})`
performanceObj['y'] = topicData
performanceObj['color'] = perfomanceInfo.color_code[topicIndex]
performanceDataSet.push(performanceObj)
@ -226,7 +226,7 @@ class StudentProfile extends React.Component<any, any>{
<Text style={[{ paddingLeft: 5, fontWeight: 'bold', color: '#5952d6' }]}>Performance</Text>
</TouchableOpacity>
<TouchableOpacity style={[BaseStyles.padVertical10, BaseStyles.padHorizontal10, { alignItems: 'center', backgroundColor: '#b0faff', width: '50%' }]} activeOpacity={0.8}>
<Text style={[{ paddingLeft: 5, fontWeight: 'bold', color: '#189199' }]}>{studentProfile?.attendance || '0%'}</Text>
<Text style={[{ paddingLeft: 5, fontWeight: 'bold', color: '#189199' }]}>{'88%' || '0%'}</Text>
<Text style={[{ paddingLeft: 5, fontWeight: 'bold', color: '#189199' }]}>Attendance</Text>
</TouchableOpacity>
</View>
@ -235,8 +235,9 @@ class StudentProfile extends React.Component<any, any>{
<VictoryChart
minDomain={{ y: 0 }}
maxDomain={{ y: 100 }}
width={350}
width={width - 20}
height={300}
domainPadding={50}
scale={{ x: "time" }}
containerComponent={
<VictoryZoomVoronoiContainer
@ -252,19 +253,37 @@ class StudentProfile extends React.Component<any, any>{
style={{
data: { stroke: "red" }
}}
interpolation="natural"
// interpolation="monotoneX"
data={attendanceDataset}
/>}
{perfomanceDataset && <VictoryLine
style={{
data: { stroke: "blue" }
}}
interpolation="natural"
//interpolation="natural"
data={perfomanceDataset}
/>}
</VictoryChart>
<View style={{ flex: 1, alignItems: 'center' }}>
<VictoryLegend x={20} y={20}
centerTitle
orientation="horizontal"
height={50}
gutter={30}
style={{
parent: {
justifyContent: 'center', // Center horizontally
alignItems: 'center', // Center vertically (if needed)
}
}}
data={[
{ name: "Attendance", symbol: { fill: 'red', } },
{ name: "Perfomance", symbol: { fill: 'blue', } }
]}
/>
</View>
</View>
<View style={[BaseStyles.padding10, AppStyles.diaryCard, BaseStyles.marTop20]}>
@ -327,13 +346,17 @@ class StudentProfile extends React.Component<any, any>{
))}
{studentPerfomanceInfo && studentPerfomanceInfo.map((subjectItem: any, subjectIndex: any) => (
<View key={subjectIndex} style={[BaseStyles.padding10, AppStyles.diaryCard, BaseStyles.marTop5]}>
<View key={subjectIndex} style={[BaseStyles.padding10, AppStyles.diaryCard, BaseStyles.marTop5,{ flex: 1, flexDirection: "column", width: "100%", justifyContent: "center", alignContent: "center" }]}>
<Text style={[AppStyles.studentHeader, BaseStyles.marBottom10]}>{subjectItem?.subject_name}</Text>
<View style={[{ flex: 1, flexDirection: "row", width: "100%", justifyContent: "center", alignContent: "center" }, BaseStyles.marBottom10, BaseStyles.marLeft10]}>
<Text style={[AppStyles.nameLabel, BaseStyles.marBottom10]}>No of Questions : {subjectItem?.total_count}</Text>
<View style={[{ flex: 1, flexDirection: "row", width: "100%", justifyContent: "center", alignContent: "center" }]}>
<VictoryPie
width={280}
width={width-20}
height={280}
cornerRadius={({ datum }) => 3}
startAngle={40}
endAngle={400}
//labelRadius={({ innerRadius }:any) => innerRadius + 100 }
cornerRadius={({ datum }) => 1}
data={subjectItem.chart_info}
style={{
data: {
@ -342,9 +365,30 @@ class StudentProfile extends React.Component<any, any>{
}}
/>
</View>
{/* <View style={[{ marginBottom:10,alignItems:'center' }]}> */}
<View >
<VictoryLegend x={20} y={20}
centerTitle
orientation="horizontal"
height={50}
gutter={30}
style={{
parent: {
justifyContent: 'center', // Center horizontally
alignItems: 'center', // Center vertically (if needed)
}
}}
data={[
{ name: "Correct", symbol: { fill: subjectItem?.correct_answer_color, } },
{ name: "Incorrect", symbol: { fill: subjectItem?.wrong_answer_color} },
{ name: "Not Attempted", symbol: { fill: subjectItem?.not_attempted_color } }
]}
/>
</View>
<View style={{ flex: 1, flexDirection: "row", width: "100%", justifyContent: common.spaceBetween }}>
<View style={[{ flex: 1, flexDirection: "column" }, BaseStyles.marBottom10, BaseStyles.marHorizontal5]}>
<Text style={[AppStyles.nameLabel, { textAlign: "center" }]}>Easy</Text>
<Text style={[AppStyles.nameLabel, { textAlign: "center",fontFamily: "Quicksand_700Bold",color: 'black', }]}>Easy</Text>
<View style={[{ flex: 1, flexDirection: "row", flexWrap: "wrap", alignItems: "center", justifyContent: "center" }, BaseStyles.marVertical10]}>
{subjectItem?.good_topics && subjectItem?.good_topics.map((goodTopic: any, goodTopicIndex: any) => (
(goodTopicIndex < 4) && <Text key={goodTopicIndex} style={[AppStyles.subjectLink, BaseStyles.marHorizontal2, BaseStyles.marVertical2]}>{goodTopic}</Text>
@ -394,7 +438,7 @@ class StudentProfile extends React.Component<any, any>{
</View>
<View style={[{ flex: 1, flexDirection: "column" }, BaseStyles.marBottom10, BaseStyles.marHorizontal5]}>
<Text style={[AppStyles.nameLabel, { textAlign: "center" }]}>Difficult</Text>
<Text style={[AppStyles.nameLabel, { textAlign: "center",fontFamily: "Quicksand_700Bold", color: 'black',}]}>Difficult</Text>
<View style={[{ flex: 1, flexDirection: "row", flexWrap: "wrap", alignItems: "center", justifyContent: "center" }, BaseStyles.marVertical10]}>
{subjectItem?.weak_topics && subjectItem?.weak_topics.map((weakTopic: any, weakTopicIndex: any) => (
(weakTopicIndex < 4) && <Text key={weakTopicIndex} style={[AppStyles.subjectLink, BaseStyles.marHorizontal2, BaseStyles.marVertical2]}>{weakTopic}</Text>
@ -444,7 +488,7 @@ class StudentProfile extends React.Component<any, any>{
</View>
</View>
<View style={{ flex: 1, flexDirection: "row", justifyContent: "space-evenly", alignItems: 'baseline' }}>
{/* <View style={{ flex: 1, flexDirection: "row", justifyContent: "space-evenly", alignItems: 'baseline' }}>
<TouchableOpacity style={[BaseStyles.padVertical10, BaseStyles.padHorizontal10, {
alignItems: 'center', backgroundColor: subjectItem?.correct_answer_color, width: "33%"
}]} activeOpacity={0.8}>
@ -463,7 +507,7 @@ class StudentProfile extends React.Component<any, any>{
<Text style={[{ paddingLeft: 5, fontWeight: 'bold', color: BaseColors.white }]}>{subjectItem?.not_attempted}</Text>
<Text style={[BaseStyles.font11, { paddingLeft: 5, fontWeight: 'bold', color: BaseColors.white }]}>Not Attempted</Text>
</TouchableOpacity>
</View>
</View> */}
</View>
))}

View File

@ -1,5 +1,5 @@
import React from "react"
import { StyleSheet, Text, View, TouchableOpacity, ScrollView, ActivityIndicator } from 'react-native'
import { StyleSheet, Text, View, TouchableOpacity, ScrollView, ActivityIndicator, Dimensions } from 'react-native'
import { AppStyles, BaseStyles, PickerStyle } from "@theme/BaseStyles" //NOSONAR
import { Picker } from '@react-native-picker/picker'
@ -23,7 +23,7 @@ const perfomanceReportValidationSchema = yup.object().shape({
const Sepator = ({ style }: any) => <View style={[BaseStyles.separator, style]} />
const VictoryZoomVoronoiContainer: any = createContainer("zoom", "voronoi")
const { width } = Dimensions.get('window')
class StudentReport extends React.Component<any, any>{
static propTypes = {};
isLoggedinAs: any;
@ -286,7 +286,7 @@ class StudentReport extends React.Component<any, any>{
<View style={[AppStyles.diaryCard, BaseStyles.marTop20, { marginBottom: 0, padding: 0 }]}>
<VictoryChart
domainPadding={20}
width={350}
width={width - 50}
height={300}
containerComponent={
<VictoryZoomVoronoiContainer
@ -299,7 +299,7 @@ class StudentReport extends React.Component<any, any>{
}}
>
<VictoryBar
barWidth={20}
style={{ data: { fill: ({ datum }) => datum.color } }}
data={topicResultData}
/>

View File

@ -45,6 +45,7 @@ const StudentUpdateValidationSchema = yup.object().shape({
.matches(formValidationPatten.emailPatten, 'Please enter valid Email Id')
.required('Email Id is Required'),
gender: yup.string().required('Gender is required'),
date_of_birth: yup.string().required('Date if birth is required'),
})
@ -311,7 +312,7 @@ class StudentUpdate extends React.Component<any, any>{
<View style={[AppStyles.inputView, BaseStyles.marTop5]} >
<TextInput style={AppStyles.inputText} name="student_name" placeholder="Enter the Student Name"
onChangeText={handleChange('student_name')} onBlur={handleBlur('student_name')}
value={values.student_name} keyboardType="default" maxLength={50} />
value={values.student_name} keyboardType="default" maxLength={50} placeholderTextColor="#003f5c"/>
</View>
{(errors.student_name && touched.student_name) && <Text style={AppStyles.error}>{errors.student_name}</Text>}
@ -337,32 +338,32 @@ class StudentUpdate extends React.Component<any, any>{
<View style={[AppStyles.inputView, BaseStyles.marTop5,BaseStyles.disabledLight]} >
<TextInput style={AppStyles.inputText} name="phone_number" placeholder="Enter the Phone Number"
onChangeText={handleChange('phone_number')} onBlur={handleBlur('phone_number')}
value={values.phone_number} keyboardType="phone-pad" maxLength={10} editable={false} />
value={values.phone_number} keyboardType="phone-pad" maxLength={10} editable={false} placeholderTextColor="#003f5c"/>
</View>
{(errors.phone_number && touched.phone_number) && <Text style={AppStyles.error}>{errors.phone_number}</Text>}
<Text style={[AppStyles.cardHeader, BaseStyles.marTop5]}>Email Id<Text style={AppStyles.required}> *</Text></Text>
<View style={[AppStyles.inputView, BaseStyles.marTop5,BaseStyles.disabledLight]} >
<TextInput style={AppStyles.inputText} name="email_id" placeholder="Enter the Email Id" onChangeText={handleChange('email_id')} onBlur={handleBlur('email_id')}
value={values.email_id} keyboardType="default" editable={false} />
value={values.email_id} keyboardType="default" editable={false} placeholderTextColor="#003f5c"/>
</View>
{(errors.email_id && touched.email_id) && <Text style={AppStyles.error}>{errors.email_id}</Text>}
<Text style={[AppStyles.cardHeader, BaseStyles.marTop5]}>Parent First Name<Text style={AppStyles.required}> *</Text></Text>
<View style={[AppStyles.inputView, BaseStyles.marTop5,]} >
<TextInput style={AppStyles.inputText} name="parent_firstname" placeholder="Enter the Parent First Name"
onChangeText={handleChange('parent_firstname')} onBlur={handleBlur('parent_firstname')}
value={values.parent_firstname} keyboardType="default" maxLength={50} />
value={values.parent_firstname} keyboardType="default" maxLength={50} placeholderTextColor="#003f5c" />
</View>
{(errors.parent_firstname && touched.parent_firstname) && <Text style={AppStyles.error}>{errors.parent_firstname}</Text>}
<Text style={[AppStyles.cardHeader, BaseStyles.marTop5]}>Parent Last Name</Text>
<View style={[AppStyles.inputView, BaseStyles.marTop5,]} >
<TextInput style={AppStyles.inputText} name="parent_lastname" placeholder="Enter the Parent last Name"
onChangeText={handleChange('parent_lastname')} onBlur={handleBlur('parent_lastname')}
value={values.parent_lastname} keyboardType="default" maxLength={50} />
value={values.parent_lastname} keyboardType="default" maxLength={50} placeholderTextColor="#003f5c"/>
</View>
{(errors.parent_lastname && touched.parent_lastname) && <Text style={AppStyles.error}>{errors.parent_lastname}</Text>}
<Text style={[AppStyles.cardHeader, BaseStyles.marTop5]}> Date of Birth </Text>
<Text style={[AppStyles.cardHeader, BaseStyles.marTop5]}> Date of Birth <Text style={AppStyles.required}> *</Text></Text>
<TouchableOpacity onPress={this.showDatePicker} style={[AppStyles.inputView, BaseStyles.marTop5]}>
<Text style={AppStyles.inputText}>

View File

@ -198,9 +198,9 @@ class StudentView extends React.Component<any, any>{
<View style={{ flexDirection: 'column', width: '52%' }}>
<Text style={[AppStyles.nameLabel]}>{item?.student_name}</Text>
<Text style={[AppStyles.stdLabel]}>Card No {item?.studentclass_details?.card_id}</Text>
<Text style={[AppStyles.stdLabel]}>Card ID {item?.studentclass_details?.card_id}</Text>
<Text style={[AppStyles.stdLabel]}>{item?.phone_number}</Text>
<Text style={[AppStyles.stdLabel]}>{item?.email_id}</Text>
<Text style={[AppStyles.stdLabel]} numberOfLines={1} ellipsizeMode="tail">{item?.email_id}</Text>
</View>
<View style={{ flexDirection: 'column', width: '28%' }}>
{this.isLoggedinAs && ((this.isLoggedinAs === UserRoles.schoolAdmin)) &&

View File

@ -27,7 +27,8 @@ class MapClassUpdate extends React.Component<any, any>{
teacherInfo: {},
selectedItems: [],
classId: [],
academicYear: ''
academicYear: '',
showForm:false,
};
token: any;
@ -70,7 +71,8 @@ class MapClassUpdate extends React.Component<any, any>{
this.setState({
teacherInfo: this.props.route.params.teacher_info,
selectedItems: this.props.route.params.class_id,
classId: this.props.route.params.class_id
classId: this.props.route.params.class_id,
showForm:true
})
}
}
@ -153,7 +155,7 @@ class MapClassUpdate extends React.Component<any, any>{
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
{this.state.showForm == true && itemData.length > 0 && <Formik
enableReinitialize={true}
validationSchema={classValidationSchema}
initialValues={{
@ -215,7 +217,7 @@ class MapClassUpdate extends React.Component<any, any>{
{this.props.loading && <ActivityIndicator size="large" color="#7165e3" />}
</>
)}
</Formik>
</Formik>}
</View>

View File

@ -13,6 +13,7 @@ import Assets from "@assets/Assets" //NOSONAR
import { StackActions, NavigationActions } from 'react-navigation'
import { CommonActions } from "@react-navigation/native"
const { width, height } = Dimensions.get('window')
class TeacherAttendance extends React.Component<any, any>{
static propTypes = {};
map: any;
@ -328,7 +329,7 @@ const styles = StyleSheet.create({
},
map: {
width: '100%',
height: 500,
height: height - 290,
}
})

View File

@ -9,6 +9,7 @@ import { ActionCreators } from "@actions" //NOSONAR
import PropTypes from 'prop-types'
import AsyncStorage from "@react-native-async-storage/async-storage"
import DateTimePickerModal from 'react-native-modal-datetime-picker';
import { RadioButton } from 'react-native-paper'
const teacherCreateValidationSchema = yup.object().shape({
firstname: yup
@ -22,6 +23,7 @@ const teacherCreateValidationSchema = yup.object().shape({
.min(1, ({ min }) => `Last Name must be at least ${min} characters`)
.max(50, ({ max }) => `Last Name should not be more than ${max} characters`)
.matches(formValidationPatten.namePatten, 'Enter a valid last Name and avoid trailing spaces'),
gender: yup.string().required('Gender is required'),
phone_number: yup
.string()
.matches(formValidationPatten.numberPatten, 'Enter a valid Phone Number')
@ -29,7 +31,8 @@ const teacherCreateValidationSchema = yup.object().shape({
email_id: yup
.string()
.matches(formValidationPatten.emailPatten, 'Please enter valid Email Id')
.required('Email Id is Required')
.required('Email Id is Required'),
date_of_birth: yup.string().required('date of birth is required'),
})
@ -107,6 +110,7 @@ class TeacherCreate extends React.Component<any, any>{
initialValues={{
firstname: '',
lastname: '',
gender:'',
phone_number: '',
email_id: '',
date_of_birth: ''
@ -128,6 +132,25 @@ class TeacherCreate extends React.Component<any, any>{
value={values.lastname} keyboardType="default" maxLength={50} />
</View>
{(errors.lastname && touched.lastname) && <Text style={AppStyles.error}>{errors.lastname}</Text>}
<Text style={[AppStyles.cardHeader, BaseStyles.marTop5]}>Gender<Text style={AppStyles.required}> *</Text></Text>
<RadioButton.Group onValueChange={(value) => setFieldValue('gender', value)}
value={values.gender}>
<View style={styles.radioContainer}>
<RadioButton.Android value="M" />
<Text style={styles.radioLabel}>Male</Text>
</View>
<View style={styles.radioContainer}>
<RadioButton.Android value="F" />
<Text style={styles.radioLabel}>Female</Text>
</View>
<View style={styles.radioContainer}>
<RadioButton.Android value="O" />
<Text style={styles.radioLabel}>Others</Text>
</View>
</RadioButton.Group>
{(errors.gender && touched.gender) && <Text style={AppStyles.error}>{errors.gender}</Text>}
<Text style={[AppStyles.cardHeader, BaseStyles.marTop5]}>Phone Number<Text style={AppStyles.required}> *</Text></Text>
<View style={[AppStyles.inputView, BaseStyles.marTop5,]} >
<TextInput style={AppStyles.inputText} name="phone_number" placeholder="Enter the Phone number"
@ -196,7 +219,15 @@ const styles = StyleSheet.create({
},
btnItem: {
width: '50%', // is 50% of whole width
}
},
radioContainer: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 10,
},
radioLabel: {
marginLeft: 8,
},
})

View File

@ -1,5 +1,5 @@
import React from "react"
import { StyleSheet, Text, View, TouchableOpacity, ScrollView, ActivityIndicator, Modal } from 'react-native'
import { StyleSheet, Text, View, TouchableOpacity, ScrollView, ActivityIndicator, Modal,Dimensions } from 'react-native'
import { AppStyles, BaseStyles } from "@theme/BaseStyles" //NOSONAR
import { connect } from "react-redux"
@ -7,11 +7,12 @@ import { ActionCreators } from "@actions" //NOSONAR
import PropTypes from 'prop-types'
import AsyncStorage from "@react-native-async-storage/async-storage"
import { common, currentYear, currentAcademicYear } from "@constants/Constants" //NOSONAR
import { VictoryPie } from "victory-native"
import { VictoryPie,VictoryLegend } from "victory-native"
import BaseColors from "@theme/Colors" //NOSONAR
import { FontAwesome } from "@expo/vector-icons"
const Sepator = ({ style }: any) => <View style={[BaseStyles.separator, style]} />
const { width } = Dimensions.get('window')
class TeacherInfo extends React.Component<any, any>{
static propTypes = {};
@ -157,7 +158,7 @@ class TeacherInfo extends React.Component<any, any>{
<Text style={[AppStyles.nameLabel, BaseStyles.marBottom20, BaseStyles.padding5, { textAlign: "center" }]}>
Performance based on how your student perform on question asked by you </Text>
<View style={[{ flex: 1, flexDirection: "row", justifyContent: 'center' }, BaseStyles.marBottom20]}>
<Text style={[AppStyles.weakGoodTextColor1, BaseStyles.marRight10]}> Week 0%</Text>
<Text style={[AppStyles.weakGoodTextColor1, BaseStyles.marRight10]}> Weak 0%</Text>
<Text style={[AppStyles.performanceWidth, AppStyles.weakGoodColor1]}></Text>
<Text style={[AppStyles.performanceWidth, AppStyles.weakGoodColor3]}></Text>
<Text style={[AppStyles.performanceWidth, AppStyles.weakGoodColor5]}></Text>
@ -199,10 +200,10 @@ class TeacherInfo extends React.Component<any, any>{
{teacherPerfomanceInfo && teacherPerfomanceInfo.map((subjectItem: any, subjectIndex: any) => (
<View key={subjectIndex} style={[BaseStyles.padding10, AppStyles.diaryCard, BaseStyles.marTop5]}>
<Text style={[AppStyles.studentHeader, BaseStyles.marBottom10]}>{subjectItem?.subject_name}</Text>
<View style={[{ flex: 1, flexDirection: "row", width: "100%", justifyContent: "center", alignContent: "center" }, BaseStyles.marBottom10, BaseStyles.marLeft10]}>
{subjectItem.percentage && subjectItem.percentage.length > 0 && <View style={[{ flex: 1, flexDirection: "row", width: "100%", justifyContent: "center", alignContent: "center" }, BaseStyles.marBottom10, BaseStyles.marLeft10]}>
<VictoryPie
width={280}
height={150}
width={width-20}
height={280}
cornerRadius={({ datum }) => 3}
data={subjectItem.chart_info}
style={{
@ -211,7 +212,7 @@ class TeacherInfo extends React.Component<any, any>{
}
}}
/>
</View>
</View>}
<View style={{ flex: 1, flexDirection: "row", width: "100%", justifyContent: common.spaceBetween }}>
<View style={[{ flex: 1, flexDirection: "column" }, BaseStyles.marBottom10, BaseStyles.marHorizontal5]}>
<Text style={[AppStyles.nameLabel, { textAlign: "center" }]}>Easy</Text>

View File

@ -9,6 +9,7 @@ import { ActionCreators } from "@actions" //NOSONAR
import PropTypes from 'prop-types'
import AsyncStorage from "@react-native-async-storage/async-storage"
import DateTimePickerModal from 'react-native-modal-datetime-picker';
import { RadioButton } from 'react-native-paper'
const teacherUpdateValidationSchema = yup.object().shape({
firstname: yup
@ -22,6 +23,7 @@ const teacherUpdateValidationSchema = yup.object().shape({
.min(1, ({ min }) => `Last Name must be at least ${min} characters`)
.max(50, ({ max }) => `Last Name should not be more than ${max} characters`)
.matches(formValidationPatten.namePatten, 'Enter a valid last Name and avoid trailing spaces'),
gender: yup.string().required('Gender is required'),
phone_number: yup
.string()
.matches(formValidationPatten.numberPatten, 'Enter a valid Phone Number')
@ -29,7 +31,8 @@ const teacherUpdateValidationSchema = yup.object().shape({
email_id: yup
.string()
.matches(formValidationPatten.emailPatten, 'Please enter valid Email Id')
.required('Email Id is Required')
.required('Email Id is Required'),
date_of_birth: yup.string().required('date of birth is required'),
})
@ -100,6 +103,7 @@ class TeacherUpdate extends React.Component<any, any>{
let firstname: any
let lastname: any
let gender: any
let phoneNumber: any
let emailId: any
let imageInput: any
@ -109,6 +113,7 @@ class TeacherUpdate extends React.Component<any, any>{
if (this.props.info.status) {
firstname = this.props.route.params.data.firstname
lastname = this.props.route.params.data.lastname
gender= this.props.route.params.data.gender,
phoneNumber = this.props.route.params.data.phone_number
emailId = this.props.route.params.data.email_id
imageInput = this.props.route.params.data.image,
@ -132,6 +137,7 @@ class TeacherUpdate extends React.Component<any, any>{
initialValues={{
firstname: firstname,
lastname: lastname,
gender: gender,
phone_number: phoneNumber,
email_id: emailId,
image:imageInput,
@ -154,6 +160,25 @@ class TeacherUpdate extends React.Component<any, any>{
value={values.lastname} keyboardType="default" maxLength={50} />
</View>
{(errors.lastname && touched.lastname) && <Text style={AppStyles.error}>{errors.lastname}</Text>}
<Text style={[AppStyles.cardHeader, BaseStyles.marTop5]}>Gender<Text style={AppStyles.required}> *</Text></Text>
<RadioButton.Group onValueChange={(value) => setFieldValue('gender', value)}
value={values.gender}>
<View style={styles.radioContainer}>
<RadioButton.Android value="M" />
<Text style={styles.radioLabel}>Male</Text>
</View>
<View style={styles.radioContainer}>
<RadioButton.Android value="F" />
<Text style={styles.radioLabel}>Female</Text>
</View>
<View style={styles.radioContainer}>
<RadioButton.Android value="O" />
<Text style={styles.radioLabel}>Others</Text>
</View>
</RadioButton.Group>
{(errors.gender && touched.gender) && <Text style={AppStyles.error}>{errors.gender}</Text>}
<Text style={[AppStyles.cardHeader, BaseStyles.marTop5]}>Phone Number<Text style={AppStyles.required}> *</Text></Text>
<View style={[AppStyles.inputView, BaseStyles.marTop5,]} >
<TextInput style={AppStyles.inputText} name="phone_number" placeholder="Enter the Phone number"
@ -223,8 +248,15 @@ const styles = StyleSheet.create({
},
btnItem: {
width: '50%', // is 50% of whole width
}
},
radioContainer: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 10,
},
radioLabel: {
marginLeft: 8,
},
})

View File

@ -145,7 +145,11 @@ class TeacherView extends React.Component<any, any>{
<View style={{ flexDirection: 'column', width: '50%' }}>
<Text style={[AppStyles.nameLabel]}>{item.firstname} {item.lastname}</Text>
<Text style={[AppStyles.stdLabel]}>{item.phone_number}</Text>
<Text style={[AppStyles.stdLabel]}>{item.email_id}</Text>
<Text
style={[AppStyles.stdLabel]}
numberOfLines={1}
ellipsizeMode='tail'
>{item.email_id}</Text>
</View>
<View>
<View style={{ flex: 1, flexDirection: "row", justifyContent: 'center', alignItems: 'center' }}>

View File

@ -837,7 +837,7 @@ export const AppStyles = StyleSheet.create({
},
tagLabelBorder: {
fontSize: 14,
height: 30,
height: 35,
borderRadius: 5,
padding: 5,
paddingHorizontal: 5,
@ -846,7 +846,7 @@ export const AppStyles = StyleSheet.create({
},
tagLabelWoBorder: {
fontSize: 14,
height: 30,
height: 35,
borderRadius: 5,
padding: 5,
paddingLeft: 10,

View File

@ -3075,6 +3075,13 @@
resolved "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz"
integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==
"@simform_solutions/react-native-audio-waveform@^2.0.0":
version "2.0.0"
resolved "https://registry.npmjs.org/@simform_solutions/react-native-audio-waveform/-/react-native-audio-waveform-2.0.0.tgz"
integrity sha512-ImkFXoOoec6rgrx0Bo1j/ag1/eXiUKbs2QK7oLBQ8BSRO5BGXJLIMc6OcV4bA//2ggK3UiTSxaRW9y0avnE5nQ==
dependencies:
lodash "^4.17.21"
"@sinclair/typebox@^0.27.8":
version "0.27.8"
resolved "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz"
@ -4087,6 +4094,11 @@ cacache@^15.3.0:
tar "^6.0.2"
unique-filename "^1.1.1"
calendarize@^1.1.1:
version "1.1.1"
resolved "https://registry.npmjs.org/calendarize/-/calendarize-1.1.1.tgz"
integrity sha512-C2JyBAtNp2NG4DX4fA1EILggLt/5PlYzvQR0crHktoAPBc9TlIfdhzg7tWekCbe+pH6+9qoK+FhPbi+vYJJlqw==
call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7:
version "1.0.7"
resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz"
@ -4734,10 +4746,10 @@ dag-map@~1.0.0:
resolved "https://registry.npmjs.org/dag-map/-/dag-map-1.0.2.tgz"
integrity sha512-+LSAiGFwQ9dRnRdOeaj7g47ZFJcOUPukAP8J3A3fuZ1g9Y44BG+P1sgApjLXTQPOzC4+7S9Wr8kXsfpINM4jpw==
dayjs@^1.8.15:
version "1.11.10"
resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz"
integrity sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==
dayjs@^1.11.13, dayjs@^1.8.15:
version "1.11.13"
resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz"
integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==
debug@^2.2.0:
version "2.6.9"
@ -5012,6 +5024,11 @@ domutils@^3.0.1:
domelementtype "^2.3.0"
domhandler "^5.0.3"
dooboolab-welcome@^1.3.2:
version "1.3.2"
resolved "https://registry.npmjs.org/dooboolab-welcome/-/dooboolab-welcome-1.3.2.tgz"
integrity sha512-2NbMaIIURElxEf/UAoVUFlXrO+7n/FRhLCiQlk4fkbGRh9cJ3/f8VEMPveR9m4Ug2l2Zey+UCXjd6EcBqHJ5bw==
dotenv-expand@~10.0.0:
version "10.0.0"
resolved "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz"
@ -9034,6 +9051,13 @@ react-native-app-intro-slider@^4.0.4:
resolved "file:../06_Installables/react-native-artag-module-0.1.4.tgz"
integrity sha512-PCLkgTS8MHITcG+UIdPhMnCfakVdj9esTlRiMcVSTVgLVv/Mqg0+ZGueXPZi5TUHZZum+zqe9Xsfy2D/UPADrg==
react-native-audio-recorder-player@^3.6.11:
version "3.6.11"
resolved "https://registry.npmjs.org/react-native-audio-recorder-player/-/react-native-audio-recorder-player-3.6.11.tgz"
integrity sha512-IHr0PWbwDKCPnTuzlXSAZhejFdtoAV6gyhRxli7aHH1tDT+9akIAToCzVdZxdmbg+vN5vFp4PNYJ30hg3pFV1w==
dependencies:
dooboolab-welcome "^1.3.2"
react-native-autoheight-webview@^1.6.5:
version "1.6.5"
resolved "https://registry.npmjs.org/react-native-autoheight-webview/-/react-native-autoheight-webview-1.6.5.tgz"
@ -9042,6 +9066,14 @@ react-native-autoheight-webview@^1.6.5:
deprecated-react-native-prop-types "^2.3.0"
prop-types "^15.7.2"
react-native-big-calendar@^4.15.0:
version "4.15.0"
resolved "https://registry.npmjs.org/react-native-big-calendar/-/react-native-big-calendar-4.15.0.tgz"
integrity sha512-hMsC3dG3LqatnJ375bXNhQDSPbWk8/v4oGG003DcqLlTDRu33f7/2MhgF8+9hD6+GgCN+1JYdtQuABL8bhSd0A==
dependencies:
calendarize "^1.1.1"
dayjs "^1.11.13"
react-native-button@^2.3.0:
version "2.4.0"
resolved "https://registry.npmjs.org/react-native-button/-/react-native-button-2.4.0.tgz"