diff --git a/src/Routes/Public/StackScreen.js b/src/Routes/Public/StackScreen.js index 22f33866..44b8dfe9 100644 --- a/src/Routes/Public/StackScreen.js +++ b/src/Routes/Public/StackScreen.js @@ -32,6 +32,8 @@ import DashboardStack from './DashboardStack'; import SCPUserTabScreen from '../SCPUser/SCPUserTabScreen'; import YouthNetTabScreen from '../Youthnet/YouthNetTabScreen'; import UnauthorizedScreen from '../../screens/Unauthorized/UnauthorizedScreen'; +import PlpWebViewScreen from '../../screens/PlpWebViewScreen/PlpWebViewScreen'; +import ProgramsScreen from '../../screens/ProgramsScreen/ProgramsScreen'; const StackScreen = () => { const Stack = createNativeStackNavigator(); @@ -270,6 +272,16 @@ const StackScreen = () => { component={UnauthorizedScreen} options={{ headerShown: false, lazy: true }} /> + + ); }; diff --git a/src/Routes/Public/TabScreen.js b/src/Routes/Public/TabScreen.js index f2473658..f95ac227 100644 --- a/src/Routes/Public/TabScreen.js +++ b/src/Routes/Public/TabScreen.js @@ -8,6 +8,7 @@ import { Platform, } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; +import { useFocusEffect } from '@react-navigation/native'; import { useTranslation } from '../../context/LanguageContext'; import { useTabBarStyle, @@ -35,12 +36,14 @@ import explore_UNFILLED from '@src/assets/images/png/explore_UNFILLED.png'; const Tab = createBottomTabNavigator(); const WalkthroughableView = walkthroughable(View); // Wrap Image component -const TabScreen = () => { + const TabScreen = () => { + console.log('###### TabScreen----yyyyy'); const { t } = useTranslation(); const [contentShow, setContentShow] = useState(true); const [CopilotStarted, setCopilotStarted] = useState(false); const [CopilotStopped, setCopilotStopped] = useState(false); const [isVolunteer, setIsVolunteer] = useState(false); + const [userType, setUserType] = useState(''); const { start, goToNth, unregisterStep, copilotEvents } = useCopilot(); const insets = useSafeAreaInsets(); const tabBarStyle = useTabBarStyle(); @@ -58,28 +61,48 @@ const TabScreen = () => { // copilotEvents.on('stop', () => setCopilotStopped(true)); // }, [start, copilotEvents]); - useEffect(() => { - const fetchData = async () => { - let userType = await getDataFromStorage('userType'); - const result = JSON.parse(await getDataFromStorage('profileData')); - console.log( - '########## getUserDetails', - result?.getUserDetails?.[0]?.customFields - ); - const volunteer = result?.getUserDetails?.[0]?.customFields.filter( - (item) => item?.label === 'IS_VOLUNTEER' - ); - console.log('###### volunteer', volunteer); - const isVolunteer = volunteer?.[0]?.selectedValues?.[0]; - console.log('###### isVolunteer', isVolunteer); - setIsVolunteer(isVolunteer); - if (userType === 'youthnet') { - setContentShow(false); - } - }; + // Use useFocusEffect to re-run when screen comes into focus + // This will trigger when userType changes in storage + useFocusEffect( + React.useCallback(() => { + const fetchData = async () => { + try { + let currentUserType = await getDataFromStorage('userType'); + console.log('###### Fetched userType:', currentUserType); + + const result = JSON.parse(await getDataFromStorage('profileData')); + console.log( + '########## getUserDetails', + result?.getUserDetails?.[0]?.customFields + ); + + const volunteer = result?.getUserDetails?.[0]?.customFields.filter( + (item) => item?.label === 'IS_VOLUNTEER' + ); + console.log('###### volunteer', volunteer); + + const isVolunteerValue = volunteer?.[0]?.selectedValues?.[0]; + console.log('###### isVolunteer', isVolunteerValue); + + setIsVolunteer(isVolunteerValue); + setUserType(currentUserType); + + // Update contentShow based on userType + if (currentUserType === 'youthnet') { + console.log('###### youthnetTab - hiding content, showing explore'); + setContentShow(false); + } else { + console.log('###### regularTab - showing content, hiding explore'); + setContentShow(true); + } + } catch (error) { + console.error('###### Error fetching data:', error); + } + }; - fetchData(); - }, []); + fetchData(); + }, []) + ); return ( { const navigation = useNavigation(); const { setLanguage, language, t } = useTranslation(); const [selectedIndex, setSelectedIndex] = useState(); const [value, setValue] = useState(); + const [userType, setUserType] = useState(''); + const [userId, setUserId] = useState(''); + const [showProgramSwitch, setShowProgramSwitch] = useState(false); useEffect(() => { // Set the initial value based on the current language @@ -30,8 +38,32 @@ const SecondaryHeader = ({ logo }) => { setSelectedIndex(new IndexPath(currentLanguageIndex)); setValue(language); } + + // Fetch userType and userId from AsyncStorage + fetchUserTypeAndId(); }, [language]); // Include language as a dependency + // Add focus effect to refresh data when returning from other screens + useFocusEffect( + React.useCallback(() => { + // Reset modal state when screen comes into focus + setShowProgramSwitch(false); + // Refresh user data + fetchUserTypeAndId(); + }, []) + ); + + const fetchUserTypeAndId = async () => { + try { + const storedUserType = await getDataFromStorage('userType'); + const storedUserId = await getDataFromStorage('userId'); + setUserType(storedUserType || ''); + setUserId(storedUserId || ''); + } catch (error) { + console.error('Error fetching userType or userId:', error); + } + }; + const onSelect = (index) => { //setSelectedIndex(index); const selectedValue = languages[index.row].value; @@ -39,6 +71,16 @@ const SecondaryHeader = ({ logo }) => { setLanguage(selectedValue); }; + const handleProgramSwitchToggle = () => { + setShowProgramSwitch(!showProgramSwitch); + }; + + const handleProgramSwitchClose = () => { + setShowProgramSwitch(false); + // Refresh userType after switching + fetchUserTypeAndId(); + }; + return ( { /> ) : ( - + + {userType && ( + + + {userType ==="scp" ? "Second Chance Program" : userType ==="youthnet" ? "Vocational Traning" : userType } + + + + + )} )} + + {/* ProgramSwitch Modal */} + + + + + + Switch Program + + + + + + {showProgramSwitch && ( + { + console.log('Program switched successfully:', userData); + // handleProgramSwitchClose(); + }} + onError={(error) => { + console.error('Program switch error:', error); + }} + onClose={handleProgramSwitchClose} + /> + )} + + + ); }; @@ -105,16 +199,63 @@ const styles = StyleSheet.create({ select: { width: 100, }, - center: { + centerContainer: { alignItems: 'center', + flexDirection: 'row', }, image: { height: 50, width: 50, }, + userTypeContainer: { + flexDirection: 'row', + alignItems: 'center', + marginLeft: 12, + paddingHorizontal: 12, + paddingVertical: 6, + backgroundColor: '#F5F5F5', + borderRadius: 20, + borderWidth: 1, + borderColor: '#E5E5E5', + }, + userTypeText: { + fontSize: 14, + color: '#4D4639', + fontFamily: 'Poppins-Medium', + marginRight: 4, + }, + dropdownIcon: { + marginLeft: 2, + }, icon: { marginLeft: 20, }, + modalOverlay: { + flex: 1, + backgroundColor: 'rgba(0, 0, 0, 0.5)', + justifyContent: 'flex-end', + }, + modalContainer: { + backgroundColor: '#FFFFFF', + borderTopLeftRadius: 20, + borderTopRightRadius: 20, + height: '90%', + }, + modalHeader: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + paddingHorizontal: 20, + paddingVertical: 15, + borderBottomWidth: 1, + borderBottomColor: '#E5E5E5', + }, + modalTitle: { + fontSize: 20, + color: '#000', + fontFamily: 'Poppins-Bold', + fontWeight: '600', + }, }); SecondaryHeader.propTypes = { diff --git a/src/components/ProgramSwitch/ProgramSwitch.js b/src/components/ProgramSwitch/ProgramSwitch.js new file mode 100644 index 00000000..86bedb22 --- /dev/null +++ b/src/components/ProgramSwitch/ProgramSwitch.js @@ -0,0 +1,809 @@ +import React, { useState, useEffect } from 'react'; +import { + View, + StyleSheet, + ActivityIndicator, + Alert, + TouchableOpacity, + ScrollView, +} from 'react-native'; +import PropTypes from 'prop-types'; +import GlobalText from '@components/GlobalText/GlobalText'; +import Ionicons from 'react-native-vector-icons/Ionicons'; +import { useNavigation, useFocusEffect, CommonActions } from '@react-navigation/native'; + +import { + getCohort, + getProfileDetails, + getProgramDetails, + getUserDetails, + setAcademicYear, + notificationSubscribe, + telemetryTrackingData, +} from '../../utils/API/AuthService'; +import { + deleteSavedItem, + getActiveCohortData, + getActiveCohortIds, + getDataFromStorage, + getDeviceId, + getuserDetails, + logEventFunction, + saveAccessToken, + saveRefreshToken, + setDataInStorage, + storeUsername, +} from '../../utils/JsHelper/Helper'; +import moment from 'moment'; +import { TENANT_DATA } from '../../utils/Constants/app-constants'; +import { NotificationUnsubscribe } from '../../utils/Helper/JSHelper'; +const ProgramSwitch = ({ userId, onSuccess, onError, onClose }) => { + const [loading, setLoading] = useState(false); + const [currentUserType, setCurrentUserType] = useState(''); + const [enrolledPrograms, setEnrolledPrograms] = useState([]); + const [tenantData, setTenantData] = useState([]); + const navigation = useNavigation(); + + useEffect(() => { + if (userId) { + fetchUserDetails(); + getCurrentUserType(); + } + }, [userId]); + + // Refetch data when component comes into focus (e.g., after program switch) + useFocusEffect( + React.useCallback(() => { + if (userId) { + getCurrentUserType(); + fetchUserDetails(); + } + }, [userId]) + ); + + const getCurrentUserType = async () => { + try { + const userType = await getDataFromStorage('userType'); + setCurrentUserType(userType || ''); + } catch (error) { + console.error('Error getting userType:', error); + } + }; + + const fetchUserDetails = async () => { + try { + setLoading(true); + + // Get current tenant ID to exclude it from the list + const currentTenantId = await getDataFromStorage('userTenantid'); + console.log('Current tenant ID:', currentTenantId); + + // Call getUserDetails API + const response = await getUserDetails({ user_id: userId }); + console.log( + 'User details fetched successfully:', + JSON.stringify(response?.userData?.tenantData) + ); + + if (response?.userData?.tenantData) { + const allTenantData = response.userData.tenantData; + setTenantData(allTenantData); + + // Filter tenants where role is "Learner" and status is "active" or "pending" + // AND exclude the current program + const filteredPrograms = allTenantData.filter((tenant) => { + const hasLearnerRole = tenant.roles?.some( + (role) => role.roleName?.toLowerCase() === 'learner' + ); + const isActiveOrPending = + tenant.tenantStatus === 'active' || tenant.tenantStatus === 'pending'; + const isNotCurrentProgram = tenant.tenantId !== currentTenantId; + + return hasLearnerRole && isActiveOrPending && isNotCurrentProgram; + }); + + setEnrolledPrograms(filteredPrograms); + + // Store userId in localStorage (AsyncStorage) + await setDataInStorage('userId', userId); + + console.log('Current program excluded. Other enrolled programs:', filteredPrograms); + + // Call success callback if provided + if (onSuccess) { + onSuccess(response.userData); + } + } else { + throw new Error('Failed to fetch user details'); + } + } catch (error) { + console.error('Error fetching user details:', error); + Alert.alert('Error', 'Failed to fetch user details. Please try again.'); + + // Call error callback if provided + if (onError) { + onError(error); + } + } finally { + setLoading(false); + } + }; + const handleProgramLogin = async(tenant) => { + try { + setLoading(true); + const tenantId = tenant?.tenantId; + const tenantName = tenant?.tenantName; + + console.log('#### Starting program switch for:', tenantName, tenantId); + + // Get user_id from storage + const user_id = await getDataFromStorage('userId'); + + if (!user_id) { + Alert.alert('Error', 'User ID not found. Please login again.'); + setLoading(false); + return; + } + + // Get user details from storage + const userDetails = await getuserDetails(); + + if (!userDetails || !userDetails.tenantData) { + Alert.alert('Error', 'User details not found. Please login again.'); + setLoading(false); + return; + } + + const selectedTenantData = [ + userDetails?.tenantData?.find((t) => t.tenantId === tenantId), + ]; + const uiConfig = selectedTenantData?.[0]?.params?.uiConfig; + await setDataInStorage('uiConfig', JSON.stringify(uiConfig)); + console.log('#### loginmultirole uiConfig', JSON.stringify(uiConfig)); + console.log('#### loginmultirole selectedTenantData', selectedTenantData); + + if (!selectedTenantData[0]) { + Alert.alert('Error', 'Program data not found. Please try again.'); + setLoading(false); + return; + } + + const enrollmentId = userDetails?.enrollmentId; + await setDataInStorage('tenantData', JSON.stringify(selectedTenantData || {})); + await setDataInStorage('userId', user_id || ''); + await setDataInStorage('enrollmentId', enrollmentId || ''); + + //store dynamic templateId + const templateId = selectedTenantData?.[0]?.templateId; + await setDataInStorage('templateId', templateId || ''); + + const academicyear = await setAcademicYear({ tenantid: tenantId }); + const academicYearId = academicyear?.[0]?.id; + await setDataInStorage('academicYearId', academicYearId || ''); + await setDataInStorage('userTenantid', tenantId || ''); + + const cohort = await getCohort({ + user_id, + tenantid: tenantId, + academicYearId, + }); + console.log('#### loginmultirole cohort', cohort); + + let cohort_id; + if (cohort.params?.status !== 'failed') { + const getActiveCohort = await getActiveCohortData(cohort); + const getActiveCohortId = await getActiveCohortIds(cohort); + await setDataInStorage( + 'cohortData', + JSON.stringify(getActiveCohort?.[0]) || '' + ); + cohort_id = getActiveCohortId?.[0]; + } + + const profileData = await getProfileDetails({ + userId: user_id, + }); + console.log('#### loginmultirole profileData', profileData); + + await setDataInStorage('profileData', JSON.stringify(profileData)); + await setDataInStorage( + 'Username', + profileData?.getUserDetails?.[0]?.username || '' + ); + await storeUsername(profileData?.getUserDetails?.[0]?.username); + + await setDataInStorage( + 'cohortId', + cohort_id || '00000000-0000-0000-0000-000000000000' + ); + + const tenantDetails = (await getProgramDetails()) || []; + + const MatchedTenant = tenantDetails.filter( + (item) => item?.tenantId === tenantId + ); + + await setDataInStorage( + 'contentFilter', + JSON.stringify(MatchedTenant?.[0]?.contentFilter || {}) + ); + + // Get tenant IDs for each program type + const youthnetTenantIds = tenantDetails + ?.filter((item) => item?.name === TENANT_DATA.YOUTHNET) + ?.map((item) => item?.tenantId); + + const scpTenantIds = tenantDetails + ?.filter((item) => item?.name === TENANT_DATA.SECOND_CHANCE_PROGRAM) + ?.map((item) => item?.tenantId); + + const campToClubTenantIds = tenantDetails + ?.filter((item) => item?.name === TENANT_DATA.CAMP_TO_CLUB) + ?.map((item) => item?.tenantId); + + console.log('#### All tenant details:', JSON.stringify(tenantDetails)); + console.log('#### Tenant IDs - SCP:', scpTenantIds, 'Youthnet:', youthnetTenantIds, 'Camp to Club:', campToClubTenantIds); + console.log('#### Selected Tenant Name:', selectedTenantData?.[0]?.tenantName); + console.log('#### Looking for tenant with ID:', tenantId); + + // Also check by tenant name directly from selectedTenantData + const selectedTenantName = selectedTenantData?.[0]?.tenantName; + console.log('#### Comparing tenant name:', selectedTenantName, 'with constants'); + + // Device notification subscription + try { + const deviceId = await getDeviceId(); + const action = 'add'; + await notificationSubscribe({ deviceId, user_id, action }); + } catch (notifError) { + console.log('#### Notification subscribe error (non-critical):', notifError); + } + + // Telemetry tracking + try { + const now = moment(); + const telemetryPayloadData = { + event: 'login', + type: 'click', + ets: now.unix(), + }; + await telemetryTrackingData({ + telemetryPayloadData, + }); + } catch (telemetryError) { + console.log('#### Telemetry tracking error (non-critical):', telemetryError); + } + + // Close the modal BEFORE navigation + if (onClose && typeof onClose === 'function') { + onClose(); + } + + // Small delay to ensure modal closes and storage is written + await new Promise(resolve => setTimeout(resolve, 200)); + + // Navigate based on program type + setLoading(false); + + // Use selectedTenantName already declared above + if (scpTenantIds?.includes(tenantId)) { + console.log('#### Navigating to SCP (matched by tenant ID)'); + await setDataInStorage('userType', 'scp'); + navigation.reset({ + index: 0, + routes: [{ name: 'SCPUserTabScreen' }], + }); + } else if (selectedTenantName === TENANT_DATA.SECOND_CHANCE_PROGRAM) { + console.log('#### Navigating to SCP (matched by tenant name)'); + await setDataInStorage('userType', 'scp'); + navigation.reset({ + index: 0, + routes: [{ name: 'SCPUserTabScreen' }], + }); + } else if (youthnetTenantIds?.includes(tenantId)) { + console.log('#### Navigating to Youthnet/Vocational Training (matched by tenant ID)'); + await setDataInStorage('userType', 'youthnet'); + navigation.reset({ + index: 0, + routes: [{ name: 'Dashboard' }], + }); + } else if (selectedTenantName === TENANT_DATA.YOUTHNET) { + console.log('#### Navigating to Youthnet/Vocational Training (matched by tenant name)'); + await setDataInStorage('userType', 'youthnet'); + navigation.reset({ + index: 0, + routes: [{ name: 'Dashboard' }], + }); + } else if (campToClubTenantIds?.includes(tenantId)) { + console.log('#### Navigating to Camp to Club (matched by tenant ID)'); + await setDataInStorage('userType', TENANT_DATA.CAMP_TO_CLUB); + navigation.reset({ + index: 0, + routes: [{ name: 'Dashboard' }], + }); + } else if (selectedTenantName === TENANT_DATA.CAMP_TO_CLUB) { + console.log('#### Navigating to Camp to Club (matched by tenant name)'); + await setDataInStorage('userType', TENANT_DATA.CAMP_TO_CLUB); + navigation.reset({ + index: 0, + routes: [{ name: 'Dashboard' }], + }); + } else { + // Default: use tenant name as userType + console.log('#### Navigating to Default Dashboard with userType:', selectedTenantName); + await setDataInStorage('userType', selectedTenantName || 'default'); + navigation.reset({ + index: 0, + routes: [{ name: 'Dashboard' }], + }); + } + + } catch (error) { + console.error('#### Error in handleProgramLogin:', error); + console.error('#### Error details:', JSON.stringify(error)); + setLoading(false); + + // Close modal on error too + if (onClose && typeof onClose === 'function') { + onClose(); + } + + Alert.alert( + 'Error', + `Failed to switch program: ${error.message || 'Please try again.'}`, + [ + { + text: 'OK', + onPress: () => { + if (onError && typeof onError === 'function') { + onError(error); + } + } + } + ] + ); + } + }; + // const handleProgramLogin = async(tenant) => { + // try { + // setLoading(true); + // const tenantId = tenant?.tenantId; + + // // Get user details from storage + // const userDetails = await getuserDetails(); + // const roleName = "Learner"; + + // // Get userId properly from storage (await the promise) + // const user_id = await getDataFromStorage('userId'); + + // if (!user_id) { + // Alert.alert('Error', 'User ID not found. Please login again.'); + // setLoading(false); + // return; + // } + + // const selectedTenantData = [ + // userDetails?.tenantData?.find((t) => t.tenantId === tenantId), + // ]; + // console.log('#### loginmultirole selectedTenantData', selectedTenantData); + + // if (!selectedTenantData[0]) { + // Alert.alert('Error', 'Program data not found. Please try again.'); + // setLoading(false); + // return; + // } + + // const enrollmentId = userDetails?.enrollmentId; + // await setDataInStorage('tenantData', JSON.stringify(selectedTenantData || {})); + // await setDataInStorage('userId', user_id || ''); + // await setDataInStorage('enrollmentId', enrollmentId || ''); + + // //store dynamic templateId + // const templateId = selectedTenantData?.[0]?.templateId; + // await setDataInStorage('templateId', templateId || ''); + + // const academicyear = await setAcademicYear({ tenantid: tenantId }); + // const academicYearId = academicyear?.[0]?.id; + // await setDataInStorage('academicYearId', academicYearId || ''); + // await setDataInStorage('userTenantid', tenantId || ''); + + // const cohort = await getCohort({ + // user_id, + // tenantid: tenantId, + // academicYearId, + // }); + // console.log('#### loginmultirole cohort', cohort); + + // let cohort_id; + // if (cohort.params?.status !== 'failed') { + // const getActiveCohort = await getActiveCohortData(cohort); + // const getActiveCohortId = await getActiveCohortIds(cohort); + // await setDataInStorage( + // 'cohortData', + // JSON.stringify(getActiveCohort?.[0]) || '' + // ); + // cohort_id = getActiveCohortId?.[0]; + // } + + // const profileData = await getProfileDetails({ + // userId: user_id, + // }); + // console.log('#### loginmultirole profileData', profileData); + + // await setDataInStorage('profileData', JSON.stringify(profileData)); + // await setDataInStorage( + // 'Username', + // profileData?.getUserDetails?.[0]?.username || '' + // ); + // await storeUsername(profileData?.getUserDetails?.[0]?.username); + + // await setDataInStorage( + // 'cohortId', + // cohort_id || '00000000-0000-0000-0000-000000000000' + // ); + + // const tenantDetails = (await getProgramDetails()) || []; + + // const MatchedTenant = tenantDetails.filter( + // (item) => item?.tenantId === tenantId + // ); + + // await setDataInStorage( + // 'contentFilter', + // JSON.stringify(MatchedTenant?.[0]?.contentFilter || {}) + // ); + + // // Get tenant IDs for each program type + // const youthnetTenantIds = tenantDetails + // ?.filter((item) => item?.name === TENANT_DATA.YOUTHNET) + // ?.map((item) => item?.tenantId); + + // const scpTenantIds = tenantDetails + // ?.filter((item) => item?.name === TENANT_DATA.SECOND_CHANCE_PROGRAM) + // ?.map((item) => item?.tenantId); + + // const campToClubTenantIds = tenantDetails + // ?.filter((item) => item?.name === TENANT_DATA.CAMP_TO_CLUB) + // ?.map((item) => item?.tenantId); + + // console.log('#### Tenant IDs - SCP:', scpTenantIds, 'Youthnet:', youthnetTenantIds, 'Camp to Club:', campToClubTenantIds); + // console.log('#### Selected Tenant Name:', selectedTenantData?.[0]?.tenantName); + + // // Navigate based on program type + // if (scpTenantIds?.includes(tenantId)) { + // console.log('#### Navigating to SCP'); + // await setDataInStorage('userType', 'scp'); + // setLoading(false); + // navigation.navigate('SCPUserTabScreen'); + // } else if (youthnetTenantIds?.includes(tenantId)) { + // console.log('#### Navigating to Youthnet/Vocational Training'); + // await setDataInStorage('userType', 'youthnet'); + // setLoading(false); + // navigation.navigate('Dashboard'); + // } else if (campToClubTenantIds?.includes(tenantId)) { + // console.log('#### Navigating to Camp to Club'); + // await setDataInStorage('userType', TENANT_DATA.CAMP_TO_CLUB); + // setLoading(false); + // navigation.navigate('Dashboard'); + // } else { + // // Default: use tenant name as userType + // console.log('#### Navigating to Default Dashboard with userType:', selectedTenantData?.[0]?.tenantName); + // await setDataInStorage('userType', selectedTenantData?.[0]?.tenantName || 'default'); + // setLoading(false); + // navigation.navigate('Dashboard'); + // } + + // // Close the modal/dialog if onClose is provided + // if (onClose) { + // onClose(); + // } + + // } catch (error) { + // console.error('Error in handleProgramLogin:', error); + // setLoading(false); + // Alert.alert( + // 'Error', + // 'Failed to switch program. Please try again.', + // [ + // { + // text: 'OK', + // onPress: () => { + // if (onError) { + // onError(error); + // } + // } + // } + // ] + // ); + // } + // }; + const handleProgramSwitch = async (tenant) => { + try { + // Store the selected tenant information + await setDataInStorage('userTenantid', tenant.tenantId); + await setDataInStorage('userType', tenant.tenantName); + + console.log('Switched to program:', tenant.tenantName); + Alert.alert('Success', `Switched to ${tenant.tenantName}`, [ + { + text: 'OK', + onPress: () => { + if (onSuccess) { + onSuccess(tenant); + } + }, + }, + ]); + } catch (error) { + console.error('Error switching program:', error); + Alert.alert('Error', 'Failed to switch program. Please try again.'); + } + }; + + const handleShowAllPrograms = () => { + console.log('All tenant data:', tenantData); + // Navigate to Programs screen + navigation.navigate('ProgramsScreen'); + }; + const logoutEvent = async () => { + const obj = { + eventName: 'logout_Event', + method: 'button-click', + screenName: 'ProgramSwitch', + }; + await logEventFunction(obj); + }; + const handleLogout = () => { + Alert.alert('Logout', 'Are you sure you want to logout?', [ + { text: 'Cancel', style: 'cancel' }, + { + text: 'Logout', + style: 'destructive', + onPress: async() => { + const fetchData = async () => { + await NotificationUnsubscribe(); + await deleteSavedItem('refreshToken'); + await deleteSavedItem('Accesstoken'); + await deleteSavedItem('userId'); + await deleteSavedItem('cohortId'); + await deleteSavedItem('cohortData'); + await deleteSavedItem('weightedProgress'); + await deleteSavedItem('courseTrackData'); + await deleteSavedItem('profileData'); + await deleteSavedItem('tenantData'); + await deleteSavedItem('academicYearId'); + await deleteSavedItem('userType'); + logoutEvent(); + // Reset the navigation stack and navigate to LoginSignUpScreen + navigation.dispatch( + CommonActions.reset({ + index: 0, + routes: [{ name: 'LoginScreen' }], + }) + ); + const now = moment(); + const telemetryPayloadData = { + event: 'logout', + type: 'click', + ets: now.unix(), + }; + await telemetryTrackingData({ + telemetryPayloadData, + }); + }; + + fetchData(); // Add your logout logic here + }, + }, + ]); + }; + + + + + + return ( + + {loading ? ( + + + Loading programs... + + ) : ( + + {/* Current Program Header */} + + + {currentUserType ==="scp" ? "Second Chance Program" : currentUserType ==="youthnet" ? "Vocational Traning" : currentUserType } + + + + {/* Other Programs Section */} + + + Other programs you are enrolled in + + + {enrolledPrograms.length > 0 ? ( + enrolledPrograms.map((program, index) => ( + handleProgramLogin(program)} + > + + {program.tenantName} + + + + )) + ) : ( + + No other programs available + + )} + + + {/* Action Buttons */} + + + + Home + + + + + Show All Programs + + + + + + Logout + + + + + + )} + + ); +}; + +ProgramSwitch.propTypes = { + userId: PropTypes.string.isRequired, + onSuccess: PropTypes.func, + onError: PropTypes.func, + onClose: PropTypes.func, +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: '#FFFFFF', + }, + scrollContent: { + paddingBottom: 20, + }, + loadingContainer: { + justifyContent: 'center', + alignItems: 'center', + padding: 40, + }, + loadingText: { + marginTop: 10, + fontSize: 16, + color: '#4D4639', + fontFamily: 'Poppins-Regular', + }, + headerContainer: { + paddingVertical: 20, + paddingHorizontal: 20, + backgroundColor: '#FFFFFF', + borderBottomWidth: 1, + borderBottomColor: '#E5E5E5', + }, + currentProgramTitle: { + fontSize: 22, + color: '#000', + fontFamily: 'Poppins-Bold', + fontWeight: '600', + }, + sectionContainer: { + paddingTop: 20, + paddingHorizontal: 20, + }, + sectionTitle: { + fontSize: 14, + color: '#666', + fontFamily: 'Poppins-Regular', + marginBottom: 15, + }, + programCard: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + paddingVertical: 18, + paddingHorizontal: 15, + backgroundColor: '#FFFFFF', + borderRadius: 12, + borderWidth: 1, + borderColor: '#E5E5E5', + marginBottom: 12, + shadowColor: '#000', + shadowOffset: { + width: 0, + height: 1, + }, + shadowOpacity: 0.05, + shadowRadius: 2, + elevation: 1, + }, + programName: { + fontSize: 16, + color: '#000', + fontFamily: 'Poppins-Medium', + flex: 1, + }, + buttonContainer: { + paddingHorizontal: 20, + paddingTop: 30, + paddingBottom: 20, + }, + button: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + paddingVertical: 14, + paddingHorizontal: 20, + backgroundColor: '#FFFFFF', + borderRadius: 25, + borderWidth: 1, + borderColor: '#D0C5B4', + marginBottom: 12, + shadowColor: '#000', + shadowOffset: { + width: 0, + height: 1, + }, + shadowOpacity: 0.05, + shadowRadius: 2, + elevation: 1, + }, + logoutButton: { + borderColor: '#F6931E', + borderWidth: 1.5, + }, + buttonText: { + fontSize: 16, + color: '#000', + fontFamily: 'Poppins-Medium', + marginHorizontal: 8, + }, + logoutText: { + color: '#F6931E', + }, + emptyText: { + fontSize: 14, + color: '#999', + fontFamily: 'Poppins-Regular', + textAlign: 'center', + paddingVertical: 20, + }, +}); + +export default ProgramSwitch; + diff --git a/src/components/ProgramSwitch/index.js b/src/components/ProgramSwitch/index.js new file mode 100644 index 00000000..336b9a33 --- /dev/null +++ b/src/components/ProgramSwitch/index.js @@ -0,0 +1,2 @@ +export { default } from './ProgramSwitch'; + diff --git a/src/components/ZoomWebView/index.ts b/src/components/ZoomWebView/index.ts new file mode 100644 index 00000000..89fb4f55 --- /dev/null +++ b/src/components/ZoomWebView/index.ts @@ -0,0 +1,2 @@ +export { default } from './ZoomWebView'; +export { default as ZoomWebView } from './ZoomWebView'; diff --git a/src/context/Languages.js b/src/context/Languages.js index f343fcd9..e98dc821 100644 --- a/src/context/Languages.js +++ b/src/context/Languages.js @@ -11,30 +11,30 @@ export const languages = [ title: 'marathi', value: 'ma', }, - // { - // title: 'odia', - // value: 'odia', - // }, + { + title: 'odia', + value: 'odia', + }, // { // title: 'bengali', // value: 'ba', // }, - // { - // title: 'telugu', - // value: 'te', - // }, - // { - // title: 'kannada', - // value: 'ka', - // }, - // { - // title: 'tamil', - // value: 'ta', - // }, - // { - // title: 'gujarati', - // value: 'gu', - // }, + { + title: 'telugu', + value: 'te', + }, + { + title: 'kannada', + value: 'ka', + }, + { + title: 'tamil', + value: 'ta', + }, + { + title: 'gujarati', + value: 'gu', + }, // { // title: 'urdu', // value: 'ur', diff --git a/src/screens/LanguageScreen/LanguageScreen.js b/src/screens/LanguageScreen/LanguageScreen.js index 948ffe6a..9d0733b7 100644 --- a/src/screens/LanguageScreen/LanguageScreen.js +++ b/src/screens/LanguageScreen/LanguageScreen.js @@ -295,7 +295,7 @@ const LanguageScreen = () => { ); const handlethis = () => { - navigation.navigate('LoginSignUpScreen'); + navigation.navigate('PlpWebViewScreen'); }; if (loading) { diff --git a/src/screens/LoginScreen/LoginScreen.js b/src/screens/LoginScreen/LoginScreen.js index 3f8169a5..ffa2f28d 100644 --- a/src/screens/LoginScreen/LoginScreen.js +++ b/src/screens/LoginScreen/LoginScreen.js @@ -1,24 +1,455 @@ -import { - View, - TouchableOpacity, - StyleSheet, - Image, - // SafeAreaView, - Pressable, - ScrollView, - StatusBar, -} from 'react-native'; +// import { +// View, +// TouchableOpacity, +// StyleSheet, +// Image, +// // SafeAreaView, +// Pressable, +// ScrollView, +// StatusBar, +// } from 'react-native'; +// import SafeAreaWrapper from '../../components/SafeAreaWrapper/SafeAreaWrapper'; +// import { useState, React, useEffect } from 'react'; +// import PrimaryButton from '../../components/PrimaryButton/PrimaryButton'; +// import { useNavigation } from '@react-navigation/native'; +// import { +// getCohort, +// getProfileDetails, +// getProgramDetails, +// login, +// notificationSubscribe, +// setAcademicYear, +// telemetryTrackingData, +// } from '../../utils/API/AuthService'; +// import { +// getActiveCohortData, +// getActiveCohortIds, +// getDataFromStorage, +// getDeviceId, +// getuserDetails, +// saveAccessToken, +// saveRefreshToken, +// setDataInStorage, +// storeUsername, +// } from '../../utils/JsHelper/Helper'; +// import LoginTextField from '../../components/LoginTextField/LoginTextField'; +// import UserNameField from '../../components/LoginTextField/UserNameField'; +// import { useTranslation } from '../../context/LanguageContext'; +// import ActiveLoading from '../LoadingScreen/ActiveLoading'; +// import Logo from '../../assets/images/png/logo.png'; +// import globalStyles from '../../utils/Helper/Style'; +// import { useInternet } from '../../context/NetworkContext'; +// import NetworkAlert from '../../components/NetworkError/NetworkAlert'; +// import GlobalText from '@components/GlobalText/GlobalText'; +// import moment from 'moment'; +// import { TENANT_DATA } from '../../utils/Constants/app-constants'; +// import SwitchAccountDialog from '../../utils/SwitchAccount/SwitchAccount'; + +// const LoginScreen = () => { +// const navigation = useNavigation(); +// const { t } = useTranslation(); +// const { isConnected } = useInternet(); +// const [userName, setUserName] = useState(''); +// const [password, setPassword] = useState(''); +// const [acceptTerms] = useState(false); +// const [isDisabled, setIsDisabled] = useState(true); +// const [errmsg, setErrmsg] = useState(''); +// const [loading, setLoading] = useState(false); +// const [networkstatus, setNetworkstatus] = useState(true); +// const [usernames, setUsernames] = useState([]); + +// const onChangeText = (e) => { +// setUserName(e.trim()); +// }; +// const onChangePassword = (e) => { +// setPassword(e.trim()); +// }; + +// const handleLogin = async () => { +// if (isConnected) { +// setNetworkstatus(true); +// setLoading(true); +// const payload = { +// username: userName, +// password: password, +// }; +// const data = await login(payload); + +// if (data?.access_token) { +// await saveRefreshToken(data?.refresh_token || ''); +// await saveAccessToken(data?.access_token || ''); + +// const userDetails = await getuserDetails(); + +// console.log('#### loginmultirole userDetails', userDetails); + +// setUserDetails(userDetails); + +// setSwitchDialogOpen(true); + +// setLoading(false); +// } else { +// setLoading(false); +// setErrmsg(data?.params?.errmsg.toLowerCase().replace(/ /g, '_')); +// } +// } else { +// setNetworkstatus(false); +// } +// }; + +// const [switchDialogOpen, setSwitchDialogOpen] = useState(false); +// const [userDetails, setUserDetails] = useState(null); +// const [tenantId, setTenantId] = useState(''); +// const [tenantName, setTenantName] = useState(''); +// const [roleId, setRoleId] = useState(''); +// const [roleName, setRoleName] = useState(''); + +// const callBackSwitchDialog = async ( +// tenantId, +// tenantName, +// roleId, +// roleName +// ) => { +// setLoading(true); +// setSwitchDialogOpen(false); + +// // Set the state values +// setTenantId(tenantId); +// setTenantName(tenantName); +// setRoleId(roleId); +// setRoleName(roleName); + +// const tenantid = tenantId; + +// console.log('#### loginmultirole tenantId', tenantId); +// console.log('#### loginmultirole tenantName', tenantName); +// console.log('#### loginmultirole roleId', roleId); +// console.log('#### loginmultirole roleName', roleName); + +// console.log('#### loginmultirole userDetails', userDetails); +// const user_id = userDetails?.userId; +// const tenantData = [ +// userDetails?.tenantData?.find((tenant) => tenant.tenantId === tenantId), +// ]; +// console.log('#### loginmultirole tenantData', tenantData); + +// const enrollmentId = userDetails?.enrollmentId; +// await setDataInStorage('tenantData', JSON.stringify(tenantData || {})); +// await setDataInStorage('userId', user_id || ''); +// await setDataInStorage('enrollmentId', enrollmentId || ''); + +// //store dynamci templateId +// const templateId = tenantData?.[0]?.templateId; +// await setDataInStorage('templateId', templateId || ''); + +// const academicyear = await setAcademicYear({ tenantid }); +// const academicYearId = academicyear?.[0]?.id; +// await setDataInStorage('academicYearId', academicYearId || ''); +// await setDataInStorage('userTenantid', tenantId || ''); +// const cohort = await getCohort({ user_id, tenantid, academicYearId }); +// console.log('#### loginmultirole cohort', cohort); +// let cohort_id; +// if (cohort.params?.status !== 'failed') { +// const getActiveCohort = await getActiveCohortData(cohort); +// const getActiveCohortId = await getActiveCohortIds(cohort); +// await setDataInStorage( +// 'cohortData', +// JSON.stringify(getActiveCohort?.[0]) || '' +// ); +// cohort_id = getActiveCohortId?.[0]; +// } + +// const profileData = await getProfileDetails({ +// userId: user_id, +// }); +// console.log('#### loginmultirole profileData', profileData); + +// await setDataInStorage('profileData', JSON.stringify(profileData)); +// await setDataInStorage( +// 'Username', +// profileData?.getUserDetails?.[0]?.username || '' +// ); +// await storeUsername(profileData?.getUserDetails?.[0]?.username); + +// await setDataInStorage( +// 'cohortId', +// cohort_id || '00000000-0000-0000-0000-000000000000' +// ); +// const tenantDetails = (await getProgramDetails()) || []; + +// const MatchedTenant = tenantDetails.filter( +// (item) => item?.tenantId === tenantId +// ); + +// // console.log('tenantDetails===>', JSON.stringify(tenantDetails)); +// // console.log( +// // 'MatchedTenant===>', +// // JSON.stringify(MatchedTenant?.[0]?.contentFilter) +// // ); + +// await setDataInStorage( +// 'contentFilter', +// JSON.stringify(MatchedTenant?.[0]?.contentFilter || {}) +// ); + +// const youthnetTenantIds = tenantDetails +// ?.filter((item) => item?.name === TENANT_DATA.YOUTHNET) +// ?.map((item) => item?.tenantId); + +// const scp = tenantDetails +// ?.filter((item) => item.name === 'Second Chance Program') +// ?.map((item) => item.tenantId); + +// const role = roleName; + +// if (role == 'Learner' || role == 'Student') { +// console.log('#### loginmultirole role', role); + +// if (tenantId === scp?.[0]) { +// console.log('####loginintoscp', scp); +// await setDataInStorage('userType', 'scp'); +// navigation.navigate('SCPUserTabScreen'); + +// // if (cohort_id) { +// // navigation.navigate('SCPUserTabScreen'); +// // } else { +// // navigation.navigate('Dashboard'); +// // } +// } else { +// if (tenantId === youthnetTenantIds?.[0]) { +// await setDataInStorage('userType', 'youthnet'); +// // navigation.navigate('YouthNetTabScreen'); +// navigation.navigate('Dashboard'); +// } else { +// // await setDataInStorage('userType', 'pragyanpath'); +// await setDataInStorage('userType', tenantData?.[0]?.tenantName); +// navigation.navigate('Dashboard'); +// } +// } +// const deviceId = await getDeviceId(); +// const action = 'add'; + +// await notificationSubscribe({ deviceId, user_id, action }); +// } else { +// setErrmsg('invalid_username_or_password'); +// } +// const now = moment(); + +// const telemetryPayloadData = { +// event: 'login', +// type: 'click', +// ets: now.unix(), +// }; +// await telemetryTrackingData({ +// telemetryPayloadData, +// }); + +// setLoading(false); +// }; + +// const callBackError = () => { +// setErrmsg('invalid_username_or_password'); +// }; + +// // const handleLogin = async () => { +// // navigation.navigate('Dashboard'); +// // }; + +// useEffect(() => { +// if (userName.length > 0 && password.length > 0 && acceptTerms) { +// setIsDisabled(false); +// } else { +// setIsDisabled(true); +// } +// }, [userName, password, acceptTerms]); + +// useEffect(() => { +// const fetchData = async () => { +// const data = JSON.parse(await getDataFromStorage('usernames')) || []; +// const filteredSuggestions = data.filter((item) => item != null); + +// setUsernames(filteredSuggestions); +// }; +// fetchData(); +// }, []); + +// return ( +// +// {loading ? ( +// +// ) : ( +// +// +// + +// {/* { +// navigation.navigate('LoginSignUpScreen'); +// }} +// > +// +// +// {t('back')} +// +// */} +// +// +// {t('login')} +// +// {/* +// {t('login_with_the_cred')} +// */} +// +// +// +// +// +// + +// {errmsg !== '' && ( +// +// {t(errmsg || 'invalid_username_or_password')} +// +// )} +// +// { +// navigation.navigate('ForgotPassword', { enableLogin: true }); +// }} +// style={{ paddingLeft: 20, marginBottom: 30, zIndex: -1 }} +// > +// +// {t('forgot_password')}? +// +// +// {/* +// +// +// {t('remember_me')} +// +// */} +// {/* +// +// +// +// +// +// {t('Read_T_&_C')} +// +// { +// navigation.navigate('TermsAndCondition'); +// }} +// > +// +// {t('terms_and_conditions2')} +// +// +// +// */} +// +// +// +// { +// navigation.navigate('RegisterStart'); +// }} +// style={{ alignItems: 'center', padding: 20 }} +// > +// +// {t('dont_have_account')} +// +// +// +// )} + +// { +// setNetworkstatus(!networkstatus); +// }} +// /> +// setSwitchDialogOpen(false)} +// callbackFunction={callBackSwitchDialog} +// authResponse={userDetails?.tenantData} +// callBackError={callBackError} +// /> +// +// ); +// }; +// const styles = StyleSheet.create({ +// scrollView: { +// flex: 1, +// }, +// textfieldbox: { +// marginTop: 20, +// }, +// }); +// export default LoginScreen; +import React, { useState, useRef, useEffect } from 'react'; +import { View, ActivityIndicator, StyleSheet, Alert, BackHandler } from 'react-native'; +import WebView from 'react-native-webview'; import SafeAreaWrapper from '../../components/SafeAreaWrapper/SafeAreaWrapper'; -import { useState, React, useEffect } from 'react'; -import PrimaryButton from '../../components/PrimaryButton/PrimaryButton'; -import { useNavigation } from '@react-navigation/native'; +import BackHeader from '../../components/Layout/BackHeader'; +import { useNavigation, useIsFocused } from '@react-navigation/native'; import { getCohort, getProfileDetails, getProgramDetails, - login, - notificationSubscribe, setAcademicYear, + notificationSubscribe, telemetryTrackingData, } from '../../utils/API/AuthService'; import { @@ -32,409 +463,348 @@ import { setDataInStorage, storeUsername, } from '../../utils/JsHelper/Helper'; -import LoginTextField from '../../components/LoginTextField/LoginTextField'; -import UserNameField from '../../components/LoginTextField/UserNameField'; -import { useTranslation } from '../../context/LanguageContext'; -import ActiveLoading from '../LoadingScreen/ActiveLoading'; -import Logo from '../../assets/images/png/logo.png'; -import globalStyles from '../../utils/Helper/Style'; -import { useInternet } from '../../context/NetworkContext'; -import NetworkAlert from '../../components/NetworkError/NetworkAlert'; -import GlobalText from '@components/GlobalText/GlobalText'; import moment from 'moment'; import { TENANT_DATA } from '../../utils/Constants/app-constants'; -import SwitchAccountDialog from '../../utils/SwitchAccount/SwitchAccount'; +import Config from 'react-native-config'; const LoginScreen = () => { - const navigation = useNavigation(); - const { t } = useTranslation(); - const { isConnected } = useInternet(); - const [userName, setUserName] = useState(''); - const [password, setPassword] = useState(''); - const [acceptTerms] = useState(false); - const [isDisabled, setIsDisabled] = useState(true); + const [loading, setLoading] = useState(true); const [errmsg, setErrmsg] = useState(''); - const [loading, setLoading] = useState(false); - const [networkstatus, setNetworkstatus] = useState(true); - const [usernames, setUsernames] = useState([]); - - const onChangeText = (e) => { - setUserName(e.trim()); - }; - const onChangePassword = (e) => { - setPassword(e.trim()); - }; - - const handleLogin = async () => { - if (isConnected) { - setNetworkstatus(true); - setLoading(true); - const payload = { - username: userName, - password: password, - }; - const data = await login(payload); - - if (data?.access_token) { - await saveRefreshToken(data?.refresh_token || ''); - await saveAccessToken(data?.access_token || ''); - - const userDetails = await getuserDetails(); - - console.log('#### loginmultirole userDetails', userDetails); + const [canGoBack, setCanGoBack] = useState(false); + const navigation = useNavigation(); + const isFocused = useIsFocused(); + const webViewRef = useRef(null); + const url = `${Config.LEARNER_PLP_LINK}/login` - setUserDetails(userDetails); + // Handle hardware back button + useEffect(() => { + const backAction = () => { + if (canGoBack && webViewRef.current) { + // Navigate back in WebView + webViewRef.current.goBack(); + return true; // Prevent default behavior (exit app) + } + // Let default behavior happen (go back in navigation) + return false; + }; - setSwitchDialogOpen(true); + const backHandler = BackHandler.addEventListener( + 'hardwareBackPress', + backAction + ); - setLoading(false); - } else { - setLoading(false); - setErrmsg(data?.params?.errmsg.toLowerCase().replace(/ /g, '_')); + return () => backHandler.remove(); + }, [canGoBack]); + + // Injected JavaScript to set isAndroidApp in localStorage + // This runs before page content loads + const injectedJavaScriptBeforeContentLoaded = ` + (function() { + try { + window.localStorage.setItem('isAndroidApp', 'yes'); + console.log('[BeforeLoad] isAndroidApp set to yes in localStorage'); + } catch (error) { + console.error('[BeforeLoad] Error setting isAndroidApp:', error); } - } else { - setNetworkstatus(false); - } - }; - - const [switchDialogOpen, setSwitchDialogOpen] = useState(false); - const [userDetails, setUserDetails] = useState(null); - const [tenantId, setTenantId] = useState(''); - const [tenantName, setTenantName] = useState(''); - const [roleId, setRoleId] = useState(''); - const [roleName, setRoleName] = useState(''); - - const callBackSwitchDialog = async ( - tenantId, - tenantName, - roleId, - roleName - ) => { - setLoading(true); - setSwitchDialogOpen(false); - - // Set the state values - setTenantId(tenantId); - setTenantName(tenantName); - setRoleId(roleId); - setRoleName(roleName); - - const tenantid = tenantId; - - console.log('#### loginmultirole tenantId', tenantId); - console.log('#### loginmultirole tenantName', tenantName); - console.log('#### loginmultirole roleId', roleId); - console.log('#### loginmultirole roleName', roleName); - - console.log('#### loginmultirole userDetails', userDetails); - const user_id = userDetails?.userId; - const tenantData = [ - userDetails?.tenantData?.find((tenant) => tenant.tenantId === tenantId), - ]; - console.log('#### loginmultirole tenantData', tenantData); - - const enrollmentId = userDetails?.enrollmentId; - await setDataInStorage('tenantData', JSON.stringify(tenantData || {})); - await setDataInStorage('userId', user_id || ''); - await setDataInStorage('enrollmentId', enrollmentId || ''); - - //store dynamci templateId - const templateId = tenantData?.[0]?.templateId; - await setDataInStorage('templateId', templateId || ''); - - const academicyear = await setAcademicYear({ tenantid }); + })(); + true; + `; + + // This runs after page content loads + const injectedJavaScript = ` + (function() { + try { + window.localStorage.setItem('isAndroidApp', 'yes'); + console.log('[AfterLoad] isAndroidApp set to yes in localStorage'); + + // Send confirmation back to React Native + if (window.ReactNativeWebView) { + window.ReactNativeWebView.postMessage(JSON.stringify({ + type: 'ANDROID_APP_FLAG_SET', + value: window.localStorage.getItem('isAndroidApp') + })); + } + } catch (error) { + console.error('[AfterLoad] Error setting isAndroidApp:', error); + } + })(); + true; + `; + + const handleProgramLogin = async(tenantId, userId, token, refreshToken) => { + await saveAccessToken(token || ''); + await saveRefreshToken(refreshToken || '') + const userDetails = await getuserDetails(); + const roleName = "Learner"; + + const user_id = userId; + const tenantData = [ + userDetails?.tenantData?.find((tenant) => tenant.tenantId === tenantId), + ]; + const uiConfig = tenantData?.[0]?.params?.uiConfig; + await setDataInStorage('uiConfig', JSON.stringify(uiConfig)); + console.log('#### loginmultirole uiConfig', JSON.stringify(uiConfig)); + console.log('#### loginmultirole tenantData', tenantData); + + const enrollmentId = userDetails?.enrollmentId; + await setDataInStorage('tenantData', JSON.stringify(tenantData || {})); + await setDataInStorage('userId', user_id || ''); + await setDataInStorage('enrollmentId', enrollmentId || ''); + + //store dynamic templateId + const templateId = tenantData?.[0]?.templateId; + await setDataInStorage('templateId', templateId || ''); + + const academicyear = await setAcademicYear({ tenantid: tenantId }); const academicYearId = academicyear?.[0]?.id; await setDataInStorage('academicYearId', academicYearId || ''); await setDataInStorage('userTenantid', tenantId || ''); - const cohort = await getCohort({ user_id, tenantid, academicYearId }); - console.log('#### loginmultirole cohort', cohort); - let cohort_id; - if (cohort.params?.status !== 'failed') { - const getActiveCohort = await getActiveCohortData(cohort); - const getActiveCohortId = await getActiveCohortIds(cohort); - await setDataInStorage( - 'cohortData', - JSON.stringify(getActiveCohort?.[0]) || '' - ); - cohort_id = getActiveCohortId?.[0]; - } - - const profileData = await getProfileDetails({ - userId: user_id, + const cohort = await getCohort({ + user_id, + tenantid: tenantId, + academicYearId, }); - console.log('#### loginmultirole profileData', profileData); - - await setDataInStorage('profileData', JSON.stringify(profileData)); + console.log('#### loginmultirole cohort', cohort); + let cohort_id; + if (cohort.params?.status !== 'failed') { + const getActiveCohort = await getActiveCohortData(cohort); + const getActiveCohortId = await getActiveCohortIds(cohort); await setDataInStorage( - 'Username', - profileData?.getUserDetails?.[0]?.username || '' + 'cohortData', + JSON.stringify(getActiveCohort?.[0]) || '' ); - await storeUsername(profileData?.getUserDetails?.[0]?.username); + cohort_id = getActiveCohortId?.[0]; + } + + const profileData = await getProfileDetails({ + userId: user_id, + }); + console.log('#### loginmultirole profileData', profileData); + + await setDataInStorage('profileData', JSON.stringify(profileData)); + await setDataInStorage( + 'Username', + profileData?.getUserDetails?.[0]?.username || '' + ); + await storeUsername(profileData?.getUserDetails?.[0]?.username); - await setDataInStorage( - 'cohortId', - cohort_id || '00000000-0000-0000-0000-000000000000' - ); - const tenantDetails = (await getProgramDetails()) || []; + await setDataInStorage( + 'cohortId', + cohort_id || '00000000-0000-0000-0000-000000000000' + ); + const tenantDetails = (await getProgramDetails()) || []; - const MatchedTenant = tenantDetails.filter( - (item) => item?.tenantId === tenantId - ); + const MatchedTenant = tenantDetails.filter( + (item) => item?.tenantId === tenantId + ); - // console.log('tenantDetails===>', JSON.stringify(tenantDetails)); - // console.log( - // 'MatchedTenant===>', - // JSON.stringify(MatchedTenant?.[0]?.contentFilter) - // ); + // console.log('tenantDetails===>', JSON.stringify(tenantDetails)); + // console.log( + // 'MatchedTenant===>', + // JSON.stringify(MatchedTenant?.[0]?.contentFilter) + // ); - await setDataInStorage( - 'contentFilter', - JSON.stringify(MatchedTenant?.[0]?.contentFilter || {}) - ); + await setDataInStorage( + 'contentFilter', + JSON.stringify(MatchedTenant?.[0]?.contentFilter || {}) + ); - const youthnetTenantIds = tenantDetails - ?.filter((item) => item?.name === TENANT_DATA.YOUTHNET) - ?.map((item) => item?.tenantId); + const youthnetTenantIds = tenantDetails + ?.filter((item) => item?.name === TENANT_DATA.YOUTHNET) + ?.map((item) => item?.tenantId); - const scp = tenantDetails - ?.filter((item) => item.name === 'Second Chance Program') - ?.map((item) => item.tenantId); + const scp = tenantDetails + ?.filter((item) => item.name === 'Second Chance Program') + ?.map((item) => item.tenantId); - const role = roleName; + // const role = roleName; - if (role == 'Learner' || role == 'Student') { - console.log('#### loginmultirole role', role); + { + // console.log('#### loginmultirole role', role); - if (tenantId === scp?.[0]) { - console.log('####loginintoscp', scp); - await setDataInStorage('userType', 'scp'); - navigation.navigate('SCPUserTabScreen'); + if (tenantId === scp?.[0]) { + console.log('####loginintoscp', scp); + await setDataInStorage('userType', 'scp'); + navigation.navigate('SCPUserTabScreen'); - // if (cohort_id) { - // navigation.navigate('SCPUserTabScreen'); - // } else { - // navigation.navigate('Dashboard'); - // } + // if (cohort_id) { + // navigation.navigate('SCPUserTabScreen'); + // } else { + // navigation.navigate('Dashboard'); + // } + } else { + if (tenantId === youthnetTenantIds?.[0]) { + await setDataInStorage('userType', 'youthnet'); + // navigation.navigate('YouthNetTabScreen'); + navigation.navigate('Dashboard'); } else { - if (tenantId === youthnetTenantIds?.[0]) { - await setDataInStorage('userType', 'youthnet'); - // navigation.navigate('YouthNetTabScreen'); - navigation.navigate('Dashboard'); - } else { - // await setDataInStorage('userType', 'pragyanpath'); - await setDataInStorage('userType', tenantData?.[0]?.tenantName); - navigation.navigate('Dashboard'); - } + // await setDataInStorage('userType', 'pragyanpath'); + await setDataInStorage('userType', tenantData?.[0]?.tenantName); + navigation.navigate('Dashboard'); } - const deviceId = await getDeviceId(); - const action = 'add'; - - await notificationSubscribe({ deviceId, user_id, action }); - } else { - setErrmsg('invalid_username_or_password'); } - const now = moment(); - - const telemetryPayloadData = { - event: 'login', - type: 'click', - ets: now.unix(), - }; - await telemetryTrackingData({ - telemetryPayloadData, - }); - - setLoading(false); + const deviceId = await getDeviceId(); + const action = 'add'; + + await notificationSubscribe({ deviceId, user_id, action }); + } + + const now = moment(); + + const telemetryPayloadData = { + event: 'login', + type: 'click', + ets: now.unix(), }; + await telemetryTrackingData({ + telemetryPayloadData, + }); - const callBackError = () => { - setErrmsg('invalid_username_or_password'); }; - // const handleLogin = async () => { - // navigation.navigate('Dashboard'); - // }; - - useEffect(() => { - if (userName.length > 0 && password.length > 0 && acceptTerms) { - setIsDisabled(false); - } else { - setIsDisabled(true); + const handleWebViewMessage = async (event) => { + try { + const message = JSON.parse(event.nativeEvent.data); + console.log('Received from web:', message); + + // Log when Android flag is confirmed set + if (message.type === 'ANDROID_APP_FLAG_SET') { + console.log('✓ isAndroidApp confirmed in localStorage:', message.value); + return; + } + + if (message.type === 'ENROLL_PROGRAM_EVENT') { + const tenantId = message.data.tenantId; + const userId = message.data.userId; + const token = message.data.token; + const refreshToken = message.data.refreshToken; + await handleProgramLogin(tenantId, userId, token, refreshToken); + + // Handle the event + console.log('User data:', message.data); + } + + if (message.type === 'ACCESS_PROGRAM_EVENT') { + console.log("Hellooooo") + const tenantId = message.data.tenantId; + const userId = message.data.userId; + const token = message.data.token; + const refreshToken = message.data.refreshToken; + await handleProgramLogin(tenantId, userId, token, refreshToken); + + console.log('Access Program data:', message.data); + } + + if (message.type === 'LOGIN_INTO_ONLY_ONE_PROGRAM_EVENT') { + const tenantId = message.data.tenantId; + const userId = message.data.userId; + const token = message.data.token; + const refreshToken = message.data.refreshToken; + console.log('Login into Only One Program data:', message.data); + + + + await handleProgramLogin(tenantId, userId, token, refreshToken); + // const refreshToken = "" + } + } catch (error) { + console.error('Error handling WebView message:', error); } - }, [userName, password, acceptTerms]); - - useEffect(() => { - const fetchData = async () => { - const data = JSON.parse(await getDataFromStorage('usernames')) || []; - const filteredSuggestions = data.filter((item) => item != null); - - setUsernames(filteredSuggestions); - }; - fetchData(); - }, []); + }; return ( - - {loading ? ( - - ) : ( - - - - - {/* { - navigation.navigate('LoginSignUpScreen'); + + + + {loading && ( + + + + )} + { + setLoading(false); + // Re-inject the localStorage value after page loads + if (webViewRef.current) { + webViewRef.current.injectJavaScript(injectedJavaScript); + } }} - > - - - {t('back')} - - */} - - - {t('login')} - - {/* { + // Update canGoBack state + setCanGoBack(navState.canGoBack); - style={[globalStyles.subHeading, { marginVertical: 5 }]} - > - {t('login_with_the_cred')} - */} - - - - - - - - {errmsg !== '' && ( - - {t(errmsg || 'invalid_username_or_password')} - - )} - - { - navigation.navigate('ForgotPassword', { enableLogin: true }); + // Re-inject on every navigation to ensure it persists + if (webViewRef.current) { + webViewRef.current.injectJavaScript(injectedJavaScript); + } + console.log('WebView Path Changed:', navState.url); + console.log('Can Go Back:', navState.canGoBack); + // if (navState.url === 'https://qa-plp.prathamdigital.org/login') { + // // Only navigate when screen is focused to prevent redirect loop + // if (isFocused) { + // navigation.navigate('LoginScreen'); + // // Go back in WebView history so it's not on /login when user returns + // if (navState.canGoBack && webViewRef.current) { + // webViewRef.current.goBack(); + // } + // } + // } }} - style={{ paddingLeft: 20, marginBottom: 30, zIndex: -1 }} - > - - {t('forgot_password')}? - - - {/* - - - {t('remember_me')} - - */} - {/* - - - - - - {t('Read_T_&_C')} - - { - navigation.navigate('TermsAndCondition'); - }} - > - - {t('terms_and_conditions2')} - - - - */} - - - - { - navigation.navigate('RegisterStart'); + onShouldStartLoadWithRequest={(request) => { + // if (request.url === 'https://qa-plp.prathamdigital.org/login') { + // if (isFocused) { + // navigation.navigate('LoginScreen'); + // } + // return false; + // } + return true; }} - style={{ alignItems: 'center', padding: 20 }} - > - - {t('dont_have_account')} - - - - )} - - { - setNetworkstatus(!networkstatus); - }} - /> - setSwitchDialogOpen(false)} - callbackFunction={callBackSwitchDialog} - authResponse={userDetails?.tenantData} - callBackError={callBackError} - /> - + onMessage={handleWebViewMessage} + style={styles.webview} + startInLoadingState={true} + domStorageEnabled={true} + javaScriptEnabled={true} + renderLoading={() => ( + + + + )} + /> + + + ); }; + const styles = StyleSheet.create({ - scrollView: { + container: { flex: 1, + backgroundColor: 'white', + marginTop: 40, }, - textfieldbox: { - marginTop: 20, + webviewContainer: { + flex: 1, + }, + loader: { + position: 'absolute', + top: 0, + left: 0, + right: 0, + bottom: 0, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: 'white', + zIndex: 1, + }, + webview: { + flex: 1, }, }); + export default LoginScreen; + + diff --git a/src/screens/PlpWebViewScreen/PlpWebViewScreen.js b/src/screens/PlpWebViewScreen/PlpWebViewScreen.js new file mode 100644 index 00000000..8999d143 --- /dev/null +++ b/src/screens/PlpWebViewScreen/PlpWebViewScreen.js @@ -0,0 +1,431 @@ +import React, { useState, useRef, useEffect } from 'react'; +import { View, ActivityIndicator, StyleSheet, Alert, BackHandler } from 'react-native'; +import WebView from 'react-native-webview'; +import SafeAreaWrapper from '../../components/SafeAreaWrapper/SafeAreaWrapper'; +import BackHeader from '../../components/Layout/BackHeader'; +import { useNavigation, useIsFocused } from '@react-navigation/native'; +import { + getCohort, + getProfileDetails, + getProgramDetails, + setAcademicYear, + notificationSubscribe, + telemetryTrackingData, +} from '../../utils/API/AuthService'; +import { + getActiveCohortData, + getActiveCohortIds, + getDataFromStorage, + getDeviceId, + getuserDetails, + saveAccessToken, + saveRefreshToken, + setDataInStorage, + storeUsername, +} from '../../utils/JsHelper/Helper'; +import moment from 'moment'; +import { TENANT_DATA } from '../../utils/Constants/app-constants'; +import Config from 'react-native-config'; +import { useTranslation } from '../../context/LanguageContext'; + +const PlpWebViewScreen = () => { + const [loading, setLoading] = useState(true); + const [errmsg, setErrmsg] = useState(''); + const [canGoBack, setCanGoBack] = useState(false); + const navigation = useNavigation(); + const isFocused = useIsFocused(); + const webViewRef = useRef(null); + const { t, setLanguage, language } = useTranslation(); + console.log("#### language", language); + + const url = Config.LEARNER_PLP_LINK + + // Handle hardware back button + useEffect(() => { + const backAction = () => { + if (canGoBack && webViewRef.current) { + // Navigate back in WebView + webViewRef.current.goBack(); + return true; // Prevent default behavior (exit app) + } + // Let default behavior happen (go back in navigation) + return false; + }; + + const backHandler = BackHandler.addEventListener( + 'hardwareBackPress', + backAction + ); + + return () => backHandler.remove(); + }, [canGoBack]); + + // Injected JavaScript to set isAndroidApp in localStorage + // This runs before page content loads + const injectedJavaScriptBeforeContentLoaded = ` + (function() { + try { + window.localStorage.setItem('isAndroidApp', 'yes'); + if('${language}' === 'ma') + { + window.localStorage.setItem('lang', 'mr'); + } + else if('${language}' === 'te') + { + window.localStorage.setItem('lang', 'tel'); + + } + else if('${language}' === 'gu') + { + window.localStorage.setItem('lang', 'guj'); + } + else if('${language}' === 'ta') + { + window.localStorage.setItem('lang', 'tam'); + } + else if('${language}' === 'ka') + { + window.localStorage.setItem('lang', 'kan'); + } + else if('${language}' === 'odia') + { + window.localStorage.setItem('lang', 'odi'); + } + else + { + window.localStorage.setItem('lang', '${language}'); + } + console.log('[BeforeLoad] isAndroidApp set to yes in localStorage'); + } catch (error) { + console.error('[BeforeLoad] Error setting isAndroidApp:', error); + } + })(); + true; + `; + + // This runs after page content loads + const injectedJavaScript = ` + (function() { + try { + window.localStorage.setItem('isAndroidApp', 'yes'); + console.log('[AfterLoad] isAndroidApp set to yes in localStorage'); + + // Send confirmation back to React Native + if (window.ReactNativeWebView) { + window.ReactNativeWebView.postMessage(JSON.stringify({ + type: 'ANDROID_APP_FLAG_SET', + value: window.localStorage.getItem('isAndroidApp') + })); + } + } catch (error) { + console.error('[AfterLoad] Error setting isAndroidApp:', error); + } + })(); + true; + `; + + const handleProgramLogin = async(tenantId, userId, token, refreshToken) => { + await saveAccessToken(token || ''); + await saveRefreshToken(refreshToken || '') + const userDetails = await getuserDetails(); + const roleName = "Learner"; + + const user_id = userId; + const tenantData = [ + userDetails?.tenantData?.find((tenant) => tenant.tenantId === tenantId), + ]; + const uiConfig = tenantData?.[0]?.params?.uiConfig; + await setDataInStorage('uiConfig', JSON.stringify(uiConfig)); + console.log('#### loginmultirole uiConfig', JSON.stringify(uiConfig)); + console.log('#### loginmultirole tenantData', tenantData); + + const enrollmentId = userDetails?.enrollmentId; + await setDataInStorage('tenantData', JSON.stringify(tenantData || {})); + await setDataInStorage('userId', user_id || ''); + await setDataInStorage('enrollmentId', enrollmentId || ''); + + //store dynamic templateId + const templateId = tenantData?.[0]?.templateId; + await setDataInStorage('templateId', templateId || ''); + + const academicyear = await setAcademicYear({ tenantid: tenantId }); + const academicYearId = academicyear?.[0]?.id; + await setDataInStorage('academicYearId', academicYearId || ''); + await setDataInStorage('userTenantid', tenantId || ''); + const cohort = await getCohort({ + user_id, + tenantid: tenantId, + academicYearId, + }); + console.log('#### loginmultirole cohort', cohort); + let cohort_id; + if (cohort.params?.status !== 'failed') { + const getActiveCohort = await getActiveCohortData(cohort); + const getActiveCohortId = await getActiveCohortIds(cohort); + await setDataInStorage( + 'cohortData', + JSON.stringify(getActiveCohort?.[0]) || '' + ); + cohort_id = getActiveCohortId?.[0]; + } + + const profileData = await getProfileDetails({ + userId: user_id, + }); + console.log('#### loginmultirole profileData', profileData); + + await setDataInStorage('profileData', JSON.stringify(profileData)); + await setDataInStorage( + 'Username', + profileData?.getUserDetails?.[0]?.username || '' + ); + await storeUsername(profileData?.getUserDetails?.[0]?.username); + + await setDataInStorage( + 'cohortId', + cohort_id || '00000000-0000-0000-0000-000000000000' + ); + const tenantDetails = (await getProgramDetails()) || []; + + const MatchedTenant = tenantDetails.filter( + (item) => item?.tenantId === tenantId + ); + + // console.log('tenantDetails===>', JSON.stringify(tenantDetails)); + // console.log( + // 'MatchedTenant===>', + // JSON.stringify(MatchedTenant?.[0]?.contentFilter) + // ); + + await setDataInStorage( + 'contentFilter', + JSON.stringify(MatchedTenant?.[0]?.contentFilter || {}) + ); + + const youthnetTenantIds = tenantDetails + ?.filter((item) => item?.name === TENANT_DATA.YOUTHNET) + ?.map((item) => item?.tenantId); + + const scp = tenantDetails + ?.filter((item) => item.name === 'Second Chance Program') + ?.map((item) => item.tenantId); + + // const role = roleName; + + { + // console.log('#### loginmultirole role', role); + + if (tenantId === scp?.[0]) { + console.log('####loginintoscp', scp); + await setDataInStorage('userType', 'scp'); + navigation.navigate('SCPUserTabScreen'); + + // if (cohort_id) { + // navigation.navigate('SCPUserTabScreen'); + // } else { + // navigation.navigate('Dashboard'); + // } + } else { + if (tenantId === youthnetTenantIds?.[0]) { + await setDataInStorage('userType', 'youthnet'); + // navigation.navigate('YouthNetTabScreen'); + navigation.navigate('Dashboard'); + } else { + // await setDataInStorage('userType', 'pragyanpath'); + await setDataInStorage('userType', tenantData?.[0]?.tenantName); + navigation.navigate('Dashboard'); + } + } + const deviceId = await getDeviceId(); + const action = 'add'; + + await notificationSubscribe({ deviceId, user_id, action }); + } + + const now = moment(); + + const telemetryPayloadData = { + event: 'login', + type: 'click', + ets: now.unix(), + }; + await telemetryTrackingData({ + telemetryPayloadData, + }); + + }; + + const handleWebViewMessage = async (event) => { + try { + const message = JSON.parse(event.nativeEvent.data); + console.log('Received from web:', message); + + // Log when Android flag is confirmed set + if (message.type === 'ANDROID_APP_FLAG_SET') { + console.log('✓ isAndroidApp confirmed in localStorage:', message.value); + return; + } + if (message.type === 'LANGUAGE_CHANGE_EVENT') { + console.log("Language changed to:", message.data); + if(message.data.language === 'mr') + { + setLanguage('ma'); + } + else if(message.data.language === 'tel') + { + setLanguage('te'); + } + else if(message.data.language === 'guj') + { + setLanguage('gu'); + } + else if(message.data.language === 'tam') + { + setLanguage('ta'); + } + else if(message.data.language === 'kan') + { + setLanguage('ka'); + } + else if(message.data.language === 'odi') + { + setLanguage('odia'); + } + else + setLanguage(message.data.language); + } + + if (message.type === 'ENROLL_PROGRAM_EVENT') { + const tenantId = message.data.tenantId; + const userId = message.data.userId; + const token = message.data.token; + const refreshToken = message.data.refreshToken; + await handleProgramLogin(tenantId, userId, token, refreshToken); + + // Handle the event + console.log('User data:', message.data); + } + + if (message.type === 'ACCESS_PROGRAM_EVENT') { + console.log("Hellooooo") + const tenantId = message.data.tenantId; + const userId = message.data.userId; + const token = message.data.token; + const refreshToken = message.data.refreshToken; + await handleProgramLogin(tenantId, userId, token, refreshToken); + + console.log('Access Program data:', message.data); + } + + if (message.type === 'LOGIN_INTO_ONLY_ONE_PROGRAM_EVENT') { + const tenantId = message.data.tenantId; + const userId = message.data.userId; + const token = message.data.token; + const refreshToken = message.data.refreshToken; + console.log('Login into Only One Program data:', message.data); + + + + await handleProgramLogin(tenantId, userId, token, refreshToken); + // const refreshToken = "" + } + } catch (error) { + console.error('Error handling WebView message:', error); + } + }; + + return ( + + + + {loading && ( + + + + )} + { + setLoading(false); + // Re-inject the localStorage value after page loads + if (webViewRef.current) { + webViewRef.current.injectJavaScript(injectedJavaScript); + } + }} + onNavigationStateChange={(navState) => { + // Update canGoBack state + setCanGoBack(navState.canGoBack); + + // Re-inject on every navigation to ensure it persists + if (webViewRef.current) { + webViewRef.current.injectJavaScript(injectedJavaScript); + } + console.log('WebView Path Changed:', navState.url); + console.log('Can Go Back:', navState.canGoBack); + // if (navState.url === 'https://qa-plp.prathamdigital.org/login') { + // // Only navigate when screen is focused to prevent redirect loop + // if (isFocused) { + // navigation.navigate('LoginScreen'); + // // Go back in WebView history so it's not on /login when user returns + // if (navState.canGoBack && webViewRef.current) { + // webViewRef.current.goBack(); + // } + // } + // } + }} + onShouldStartLoadWithRequest={(request) => { + // if (request.url === 'https://qa-plp.prathamdigital.org/login') { + // if (isFocused) { + // navigation.navigate('LoginScreen'); + // } + // return false; + // } + return true; + }} + onMessage={handleWebViewMessage} + style={styles.webview} + startInLoadingState={true} + domStorageEnabled={true} + javaScriptEnabled={true} + renderLoading={() => ( + + + + )} + /> + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: 'white', + marginTop: 40, + }, + webviewContainer: { + flex: 1, + }, + loader: { + position: 'absolute', + top: 0, + left: 0, + right: 0, + bottom: 0, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: 'white', + zIndex: 1, + }, + webview: { + flex: 1, + }, +}); + +export default PlpWebViewScreen; + diff --git a/src/screens/Profile/OtherSettings.js b/src/screens/Profile/OtherSettings.js index 13ef0ce3..43146e25 100644 --- a/src/screens/Profile/OtherSettings.js +++ b/src/screens/Profile/OtherSettings.js @@ -45,6 +45,7 @@ const OtherSettings = ({ route }) => { const [isModalVisible, setModalVisible] = useState(false); const [userType, setUserType] = useState(); const [cohortId, setCohortId] = useState(); + const [isEditProfileEnabled, setIsEditProfileEnabled] = useState(false); const { isConnected } = useInternet(); const { t } = useTranslation(); @@ -53,10 +54,38 @@ const OtherSettings = ({ route }) => { const fetchData = async () => { const userTypes = await getDataFromStorage('userType'); const getCohortId = await getDataFromStorage('cohortId'); + // Try both possible keys for uiConfig + let uiConfig = await getDataFromStorage('uiConfig'); + if (!uiConfig) { + uiConfig = await getDataFromStorage('uiconfig'); + } + + console.log('uiConfig from storage:', uiConfig); + console.log('uiConfig type:', typeof uiConfig); + setUserType(userTypes); setCohortId(getCohortId); + + // Parse uiconfig and check if isEditProfile is true + if (uiConfig) { + try { + const parsedConfig = typeof uiConfig === 'string' ? JSON.parse(uiConfig) : uiConfig; + console.log('Parsed uiConfig:', parsedConfig); + console.log('isEditProfile value:', parsedConfig?.isEditProfile); + const shouldShowEditProfile = parsedConfig?.isEditProfile === true; + console.log('Should show edit profile:', shouldShowEditProfile); + setIsEditProfileEnabled(shouldShowEditProfile); + } catch (error) { + console.log('Error parsing uiconfig:', error); + setIsEditProfileEnabled(false); + } + } else { + console.log('uiConfig is null or undefined'); + setIsEditProfileEnabled(false); + } }; console.log('cohortId', cohortId); + console.log('isEditProfileEnabled state:', isEditProfileEnabled); useFocusEffect( useCallback(() => { @@ -187,98 +216,91 @@ const OtherSettings = ({ route }) => { /> - {(userType === 'scp' && - cohortId !== '00000000-0000-0000-0000-000000000000') || - !isConnected ? ( - <> - ) : ( - <> - {userType !== 'pragyanpath' && ( - { - navigation.navigate('ProfileUpdateScreen'); - }} + + {isEditProfileEnabled && ( + { + navigation.navigate('ProfileUpdateScreen'); + }} + > + + - - - {t('edit_profile')} - - - - - )} + {t('edit_profile')} + + + + + )} {/* - { - navigation.navigate('ResetUsername'); - }} + { + navigation.navigate('ResetUsername'); + }} + > + + - - - {t('change_username')} - - - - */} - { - navigation.navigate('ResetPassword'); - }} + {t('change_username')} + + + + */} + { + navigation.navigate('ResetPassword'); + }} + > + + - - - {t('change_password')} - - - - - - )} + {t('change_password')} + + + + { + const [loading, setLoading] = useState(true); + const [errmsg, setErrmsg] = useState(''); + const [canGoBack, setCanGoBack] = useState(false); + const navigation = useNavigation(); + const isFocused = useIsFocused(); + const webViewRef = useRef(null); + const url = `${Config.LEARNER_PLP_LINK}/programs` + + // Handle hardware back button + useEffect(() => { + const backAction = () => { + if (canGoBack && webViewRef.current) { + // Navigate back in WebView + webViewRef.current.goBack(); + return true; // Prevent default behavior (exit app) + } + // Let default behavior happen (go back in navigation) + return false; + }; + + const backHandler = BackHandler.addEventListener( + 'hardwareBackPress', + backAction + ); + + return () => backHandler.remove(); + }, [canGoBack]); + + // Injected JavaScript to set isAndroidApp in localStorage + // This runs before page content loads + const injectedJavaScriptBeforeContentLoaded = ` + (function() { + try { + window.localStorage.setItem('isAndroidApp', 'yes'); + console.log('[BeforeLoad] isAndroidApp set to yes in localStorage'); + } catch (error) { + console.error('[BeforeLoad] Error setting isAndroidApp:', error); + } + })(); + true; + `; + + // This runs after page content loads + const injectedJavaScript = ` + (function() { + try { + window.localStorage.setItem('isAndroidApp', 'yes'); + console.log('[AfterLoad] isAndroidApp set to yes in localStorage'); + + // Send confirmation back to React Native + if (window.ReactNativeWebView) { + window.ReactNativeWebView.postMessage(JSON.stringify({ + type: 'ANDROID_APP_FLAG_SET', + value: window.localStorage.getItem('isAndroidApp') + })); + } + } catch (error) { + console.error('[AfterLoad] Error setting isAndroidApp:', error); + } + })(); + true; + `; + + + const handleProgramLogin = async(tenantId, userId, token, refreshToken) => { + await saveAccessToken(token || ''); + await saveRefreshToken(refreshToken || '') + const userDetails = await getuserDetails(); + const roleName = "Learner"; + + const user_id = userId; + const tenantData = [ + userDetails?.tenantData?.find((tenant) => tenant.tenantId === tenantId), + ]; + const uiConfig = tenantData[0]?.params?.uiConfig; + await setDataInStorage('uiConfig', JSON.stringify(uiConfig)); + console.log('#### loginmultirole uiConfig', JSON.stringify(uiConfig)); + console.log('#### loginmultirole tenantData', tenantData); + + const enrollmentId = userDetails?.enrollmentId; + await setDataInStorage('tenantData', JSON.stringify(tenantData || {})); + await setDataInStorage('userId', user_id || ''); + await setDataInStorage('enrollmentId', enrollmentId || ''); + + //store dynamic templateId + const templateId = tenantData?.[0]?.templateId; + await setDataInStorage('templateId', templateId || ''); + + const academicyear = await setAcademicYear({ tenantid: tenantId }); + const academicYearId = academicyear?.[0]?.id; + await setDataInStorage('academicYearId', academicYearId || ''); + await setDataInStorage('userTenantid', tenantId || ''); + const cohort = await getCohort({ + user_id, + tenantid: tenantId, + academicYearId, + }); + console.log('#### loginmultirole cohort', cohort); + let cohort_id; + if (cohort.params?.status !== 'failed') { + const getActiveCohort = await getActiveCohortData(cohort); + const getActiveCohortId = await getActiveCohortIds(cohort); + await setDataInStorage( + 'cohortData', + JSON.stringify(getActiveCohort?.[0]) || '' + ); + cohort_id = getActiveCohortId?.[0]; + } + + const profileData = await getProfileDetails({ + userId: user_id, + }); + console.log('#### loginmultirole profileData', profileData); + + await setDataInStorage('profileData', JSON.stringify(profileData)); + await setDataInStorage( + 'Username', + profileData?.getUserDetails?.[0]?.username || '' + ); + await storeUsername(profileData?.getUserDetails?.[0]?.username); + + await setDataInStorage( + 'cohortId', + cohort_id || '00000000-0000-0000-0000-000000000000' + ); + const tenantDetails = (await getProgramDetails()) || []; + + const MatchedTenant = tenantDetails.filter( + (item) => item?.tenantId === tenantId + ); + + // console.log('tenantDetails===>', JSON.stringify(tenantDetails)); + // console.log( + // 'MatchedTenant===>', + // JSON.stringify(MatchedTenant?.[0]?.contentFilter) + // ); + + await setDataInStorage( + 'contentFilter', + JSON.stringify(MatchedTenant?.[0]?.contentFilter || {}) + ); + + const youthnetTenantIds = tenantDetails + ?.filter((item) => item?.name === TENANT_DATA.YOUTHNET) + ?.map((item) => item?.tenantId); + + const scp = tenantDetails + ?.filter((item) => item.name === 'Second Chance Program') + ?.map((item) => item.tenantId); + + // const role = roleName; + + { + // console.log('#### loginmultirole role', role); + + if (tenantId === scp?.[0]) { + console.log('####loginintoscp', scp); + await setDataInStorage('userType', 'scp'); + navigation.navigate('SCPUserTabScreen'); + + // if (cohort_id) { + // navigation.navigate('SCPUserTabScreen'); + // } else { + // navigation.navigate('Dashboard'); + // } + } else { + if (tenantId === youthnetTenantIds?.[0]) { + // console.log('#### loginintodefault tenant@@@@@@@', tenantData?.[0]?.tenantName); + + await setDataInStorage('userType', 'youthnet'); + // navigation.navigate('YouthNetTabScreen'); + navigation.navigate('Dashboard'); + } else { + console.log('#### loginintodefault tenant??????', tenantData?.[0]?.tenantName); + // await setDataInStorage('userType', 'pragyanpath'); + await setDataInStorage('userType', tenantData?.[0]?.tenantName); + navigation.navigate('Dashboard'); + } + } + const deviceId = await getDeviceId(); + const action = 'add'; + + await notificationSubscribe({ deviceId, user_id, action }); + } + + const now = moment(); + + const telemetryPayloadData = { + event: 'login', + type: 'click', + ets: now.unix(), + }; + await telemetryTrackingData({ + telemetryPayloadData, + }); + + }; + + const handleWebViewMessage = async (event) => { + try { + const message = JSON.parse(event.nativeEvent.data); + console.log('Received from web:', message); + + // Log when Android flag is confirmed set + if (message.type === 'ANDROID_APP_FLAG_SET') { + console.log('✓ isAndroidApp confirmed in localStorage:', message.value); + return; + } + + if (message.type === 'ENROLL_PROGRAM_EVENT') { + const tenantId = message.data.tenantId; + const userId = message.data.userId; + const token = message.data.token; + const refreshToken = message.data.refreshToken; + await handleProgramLogin(tenantId, userId, token, refreshToken); + + // Handle the event + console.log('User data:', message.data); + } + + if (message.type === 'ACCESS_PROGRAM_EVENT') { + console.log("Hellooooo") + const tenantId = message.data.tenantId; + const userId = message.data.userId; + const token = message.data.token; + const refreshToken = message.data.refreshToken; + await handleProgramLogin(tenantId, userId, token, refreshToken); + + console.log('Access Program data:', message.data); + } + + if (message.type === 'LOGIN_INTO_ONLY_ONE_PROGRAM_EVENT') { + const tenantId = message.data.tenantId; + const userId = message.data.userId; + const token = message.data.token; + const refreshToken = message.data.refreshToken; + console.log('Login into Only One Program data:', message.data); + + + + await handleProgramLogin(tenantId, userId, token, refreshToken); + // const refreshToken = "" + } + } catch (error) { + console.error('Error handling WebView message:', error); + } + }; + + return ( + + + + {loading && ( + + + + )} + { + setLoading(false); + // Re-inject the localStorage value after page loads + if (webViewRef.current) { + webViewRef.current.injectJavaScript(injectedJavaScript); + } + }} + onNavigationStateChange={(navState) => { + // Update canGoBack state + setCanGoBack(navState.canGoBack); + + // Re-inject on every navigation to ensure it persists + if (webViewRef.current) { + webViewRef.current.injectJavaScript(injectedJavaScript); + } + console.log('WebView Path Changed:', navState.url); + console.log('Can Go Back:', navState.canGoBack); + // if (navState.url === 'https://qa-plp.prathamdigital.org/login') { + // // Only navigate when screen is focused to prevent redirect loop + // if (isFocused) { + // navigation.navigate('LoginScreen'); + // // Go back in WebView history so it's not on /login when user returns + // if (navState.canGoBack && webViewRef.current) { + // webViewRef.current.goBack(); + // } + // } + // } + }} + onShouldStartLoadWithRequest={(request) => { + // if (request.url === 'https://qa-plp.prathamdigital.org/login') { + // if (isFocused) { + // navigation.navigate('LoginScreen'); + // } + // return false; + // } + return true; + }} + onMessage={handleWebViewMessage} + style={styles.webview} + startInLoadingState={true} + domStorageEnabled={true} + javaScriptEnabled={true} + renderLoading={() => ( + + + + )} + /> + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: 'white', + marginTop: 40, + }, + webviewContainer: { + flex: 1, + }, + loader: { + position: 'absolute', + top: 0, + left: 0, + right: 0, + bottom: 0, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: 'white', + zIndex: 1, + }, + webview: { + flex: 1, + }, +}); + +export default PlpWebViewScreen; + diff --git a/src/screens/ProgramsScreen/index.js b/src/screens/ProgramsScreen/index.js new file mode 100644 index 00000000..f069e37a --- /dev/null +++ b/src/screens/ProgramsScreen/index.js @@ -0,0 +1,2 @@ +export { default } from './ProgramsScreen'; + diff --git a/src/utils/API/AuthService.js b/src/utils/API/AuthService.js index 23d4cee5..88f52d42 100644 --- a/src/utils/API/AuthService.js +++ b/src/utils/API/AuthService.js @@ -982,6 +982,25 @@ export const getProfileDetails = async (params = {}) => { } }; +export const getUserDetails = async (params = {}) => { + try { + const url = `${EndUrls.userDetails}/${params?.user_id}`; // Define the URL + const headers = await getHeaders(); + const result = await get(url, { + headers: headers || {}, + }); + if (result) { + return result?.data?.result; + } else { + return {}; + } + } + catch (e) { + console.log(e) + } +}; + + export const getAssessmentStatus = async (params = {}) => { try { const url = `${EndUrls.AssessmentStatus}`; // Define the URL diff --git a/src/utils/API/EndUrls.js b/src/utils/API/EndUrls.js index d4902cfb..4c4dae41 100644 --- a/src/utils/API/EndUrls.js +++ b/src/utils/API/EndUrls.js @@ -87,6 +87,7 @@ const EndUrls = { //ATM atmAssessment: `${API_URL}/interface/v1/tracking/ai-assessment/search`, atmAssessment_status: `${API_URL}/interface/v1/tracking/assessment/offline-assessment-status`, + userDetails: `${API_URL}/interface/v1/user/read`, };