before merge

This commit is contained in:
Abin Toppo
2026-01-12 15:21:14 +05:30
parent ed11bb479e
commit 360097da70
28 changed files with 4821 additions and 177 deletions
+211 -27
View File
@@ -1,40 +1,224 @@
import { View, Text } from 'react-native';
import React, { useEffect } from 'react';
import FontsFamily from '../../Constant/FontsFamily';
import { useNavigation } from '@react-navigation/native';
import NavigationString from '../../Constant/NavigationString';
import React, { useEffect, useRef, useState, useCallback } from 'react';
import { Animated, StyleSheet, View } from 'react-native';
import { useNavigation, useIsFocused } from '@react-navigation/native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { useSelector } from 'react-redux';
import { useStore } from 'react-redux'; // For hydration check
const Splash = () => {
const navigation: any = useNavigation();
const Token = useSelector((state: any) => state.token.token)
import { showToast } from '../../Constant/ShowDailog';
import { useRagistrationState } from '../../Services/BBPS/Hooks';
import NavigationString from '../../Constant/NavigationString';
const handleSplashNavigation = async () => {
try {
const isOnboardingDone = await AsyncStorage.getItem('onBoarding');
if (isOnboardingDone != 'true') {
navigation.replace(NavigationString.Onboarding);
} else if (Token.token) {
navigation.replace(NavigationString.Home);
} else {
navigation.replace(NavigationString.Login);
}
} catch (error) {
navigation.replace(NavigationString.Onboarding);
}
};
// Navigation type
export type Navigation = {
reset(arg0: {
index: number;
routes: { name: string; }[];
}): unknown;
navigate: (route: string, params?: { [key: string]: any }) => void;
replace: (route: string, params?: { [key: string]: any }) => void;
};
const Splash: React.FC = () => {
const navigation = useNavigation() as Navigation;
const isFocused = useIsFocused();
const fadeAnim = useRef(new Animated.Value(0)).current;
const reduxToken = useSelector((state: any) => state.token?.token);
const store = useStore();
const { mutateAsync: registrationStateMutate } = useRagistrationState();
const [isHydrated, setIsHydrated] = useState(false);
const [isLoading, setIsLoading] = useState(true);
// Wait for Redux hydration (works with/without redux-persist)
useEffect(() => {
handleSplashNavigation()
let unsubscribe: any;
const checkHydration = () => {
const token = (store.getState() as any).token?.token;
if (token !== undefined) { // Defined = hydrated (null/empty/string ok)
setIsHydrated(true);
unsubscribe?.();
}
};
unsubscribe = store.subscribe(checkHydration);
checkHydration(); // Check immediately
return () => unsubscribe?.();
}, []);
const getToken = useCallback(async (): Promise<string | null> => {
try {
// Redux first (post-hydration), then AsyncStorage fallback
let token = reduxToken;
if (token === undefined) {
token = await AsyncStorage.getItem('token');
}
return token || null;
} catch (error) {
console.error('Token fetch error:', error);
return null;
}
}, [reduxToken]);
const routeByOrgType = (params: { otherId: any; orgType: any }) => {
const orgType = String(params.orgType);
if (orgType === '4' || orgType === '5' || orgType === '6') {
navigation.replace('StageThree', params);
return;
}
if (orgType === '7') {
navigation.replace('PartnerShip', params);
return;
}
navigation.replace('Dashboard');
};
const handleGetData = async () => {
try {
const res = await registrationStateMutate();
console.log('Registration status response:', res?.statusCode);
if (res?.statusCode === 404 || res?.statusCode === 401) {
navigation.replace('Registration');
return;
}
if (res?.statusCode === 200 && res?.data) {
const { registrationStatus, contOtherId, contOrganization } = res.data;
const params = { otherId: contOtherId, orgType: contOrganization };
console.log('Registration status:', registrationStatus);
switch (registrationStatus) {
case null:
case undefined:
navigation.replace(NavigationString.Registration);
break;
case 'Pending':
routeByOrgType(params);
break;
case 'Complete':
case 'Completed':
navigation.replace(NavigationString.Home);
break;
default:
navigation.replace(NavigationString.Registration);
break;
}
return;
}
console.error('API error:', res);
showToast(res?.message || 'Something went wrong');
navigation.replace('Registration');
} catch (error: any) {
console.error('Registration status error:', error);
showToast(error?.message || 'Something went wrong');
if (error?.response?.status === 404) {
navigation.replace('Registration');
} else {
await AsyncStorage.removeItem('token');
navigation.replace('Signin');
}
}
};
useEffect(() => {
if (!isFocused || !isHydrated) return;
const runSplash = async () => {
try {
setIsLoading(true);
Animated.timing(fadeAnim, {
toValue: 1,
duration: 500,
useNativeDriver: true,
}).start();
const token = await getToken();
console.log("Token after hydration -", token, typeof token, !!token);
if (!token) {
console.log('No valid token, navigating to Login');
navigation.reset({
index: 0,
routes: [{ name: NavigationString.Login || 'Signin' }], // Fallback
});
return;
}
console.log('Valid token, fetching registration data');
await handleGetData();
} catch (error) {
console.error('Splash Error:', error);
navigation.reset({
index: 0,
routes: [{ name: NavigationString.Login || 'Signin' }],
});
} finally {
setIsLoading(false);
}
};
// Small delay ensures hydration + native animation complete
const timeoutId = setTimeout(runSplash, 200);
return () => clearTimeout(timeoutId);
}, [isFocused, isHydrated, getToken]);
if (!isHydrated) {
return (
<View style={styles.loadingContainer}>
<Animated.Image
source={require('../../Images/logo.png')}
style={[styles.logo, { opacity: fadeAnim }]}
resizeMode="contain"
/>
</View>
);
}
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text style={{ fontFamily: FontsFamily.poppinsBlack }}>
Splash
</Text>
<View style={styles.appView}>
<View style={styles.container}>
<Animated.Image
source={require('../../Images/logo.png')}
style={[styles.logo, { opacity: fadeAnim }]}
resizeMode="contain"
/>
{isLoading && (
<View style={{ marginTop: 20 }}>
{/* Optional spinner */}
</View>
)}
</View>
</View>
);
};
export default Splash;
const styles = StyleSheet.create({
appView: {
flex: 1,
backgroundColor: '#fff',
},
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
logo: {
width: 160,
height: 160,
marginBottom: 20,
},
loadingContainer: {
flex: 1,
backgroundColor: '#fff',
justifyContent: 'center',
alignItems: 'center',
},
});