manage user credancial

This commit is contained in:
Jaanu423
2025-09-23 13:25:09 +05:30
parent bcd41f81e6
commit 64282654f0
11 changed files with 299 additions and 105 deletions
+8 -8
View File
@@ -150,17 +150,17 @@ export default function GroupScreen() {
const handleJoinGroup = async (groupId: string, userId: string) => {
console.log("Joining group:", groupId, "User:", userId);
try {
const url = `${JOIN_GROUP_URL}/groups/${groupId}/join/0`;
const url = `${JOIN_GROUP_URL}groups/${groupId}/join/10`;
console.log("Joining group URL:", url);
const res = await apiCall(url, "POST") as { statusCode?: number; message?: string };
const res = await apiCall(url, "POST");
console.log("JOIN_GROUP_URL response:", res);
if (res.statusCode === 200) {
Alert.alert("Success", "You requested to join the group.");
} else {
Alert.alert("Error", res.message || "Failed to join group.");
}
// if (res.statusCode === 200) {
// Alert.alert("Success", "You requested to join the group.");
// } else {
// Alert.alert("Error", res.message || "Failed to join group.");
// }
} catch (error) {
console.error("Join Group Error:", error);
Alert.alert("Error", "An unexpected error occurred.");
@@ -264,7 +264,7 @@ export default function GroupScreen() {
refreshControl={
<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
}
ListFooterComponent={<ActivityIndicator size={'large'} color={colors.Group} />}
// ListFooterComponent={<ActivityIndicator size={'large'} color={colors.Group} />}
/>
);
};
+31 -18
View File
@@ -77,26 +77,39 @@ export default function OtpVerificationScreen() {
const onSubmit = async (otp: string, mobile: string) => {
try {
const payload = { mobile, otp };
const res = await axios.post(
VARIFY_OTP_URL,
payload,
{ headers: { "Content-Type": "application/json", Accept: "*/*" } }
);
console.log("✅ OTP Verified:", res.data);
if (res.data.statusCode === 200) {
saveToken(res.data.data);
fetchUserProfile()
navigation.navigate("Home", { refreshProfile: true });
ToastAndroid.show("OTP Verified Successfully!", ToastAndroid.SHORT);
try {
const payload = { mobile, otp };
const res = await axios.post(
VARIFY_OTP_URL,
payload,
{
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
}
} catch (err: any) {
console.error("❌ OTP Verification Error:", err?.response?.data || err.message);
ToastAndroid.show(err.message || "Invalid OTP. Please try again.", ToastAndroid.SHORT);
);
console.log("✅ OTP Verified:", res.data);
if (res.data?.statusCode === 200) {
const { jwt, role } = res.data?.data || {};
saveToken(jwt);
navigation.navigate("Home");
ToastAndroid.show("OTP Verified Successfully!", ToastAndroid.SHORT);
}
};
} catch (err: any) {
console.error("❌ OTP Verification Error:", err?.response?.data || err.message);
ToastAndroid.show(
err?.response?.data?.message || "Invalid OTP. Please try again.",
ToastAndroid.SHORT
);
}
};
const resendOtp = async () => {
try {
+35 -11
View File
@@ -7,21 +7,27 @@ import {
UIManager,
Platform,
Image,
Alert,
} from "react-native";
import AppView from "../../components/AppView";
import UserProfileStatus from "./UserProfileStatus";
import colors from "../../components/colors";
import GroupsTabs from "./GroupsTabs";
import { useSelector } from "react-redux";
import { useFocusEffect, useNavigation, useRoute } from "@react-navigation/native";
import { useDispatch, useSelector } from "react-redux";
import { RouteProp, useFocusEffect, useNavigation, useRoute } from "@react-navigation/native";
import UserHome from "./user-home/UserHome";
import { PROFILE_URL } from "../../utils/ApiUrls";
import *as Keychain from "react-native-keychain"
import { setUserData } from "../../redux/userSlice";
// Enable animation for Android
if (Platform.OS === "android" && UIManager.setLayoutAnimationEnabledExperimental) {
UIManager.setLayoutAnimationEnabledExperimental(true);
}
type RootStackParamList = {
Home: { refreshProfile: boolean; role: string };
};
type UserProfile = {
id: string;
userId: number;
@@ -33,9 +39,8 @@ type UserProfile = {
const Home = () => {
const user = useSelector((state: any) => state.user);
const navigation = useNavigation();
const route = useRoute();
const dispatch = useDispatch()
console.log("route asf : ", route?.params)
const [apiUser, setApiUser] = useState<UserProfile | null | any>(null)
const fetchUserProfile = async () => {
@@ -60,7 +65,29 @@ const Home = () => {
console.log("👤 Profile Response:", result);
if (result.status === "success") {
setApiUser(result.data);
dispatch(
setUserData({
id: result.data.id,
userId: result.data.userId,
username: result.data.username,
firstName: result.data.firstName,
lastName: result.data.lastName,
gender: result.data.gender,
mobile: result.data.mobile,
email: result.data.email,
address: result.data.address,
bankAccountNumber: result.data.bankAccountNumber,
bankName: result.data.bankName,
branchCode: result.data.branchCode,
profilePicture: result.data.filePath,
filePath: result.data.filePath,
imageBlob: result.data.imageBlob,
role: result.data.role,
organizerId: result.data.organizerId,
organizerStatus: result.data.organizerStatus,
profileStatus: true,
})
);
}
} catch (error) {
console.error("❌ Error fetching profile:", error);
@@ -68,10 +95,8 @@ const Home = () => {
};
useEffect(() => {
if (route.params) {
fetchUserProfile();
}
}, [route.params]);
fetchUserProfile();
}, []);
return (
<AppView barStyle="dark-content" style={styles.container}>
@@ -91,6 +116,7 @@ const Home = () => {
</View>
{/* Status */}
<UserProfileStatus />
{/* <UserHome /> */}
{user?.role === "USER" || apiUser?.role === "USER" ? <UserHome /> :
<GroupsTabs />}
</AppView>
@@ -110,6 +136,4 @@ const styles = StyleSheet.create({
marginBottom: 12,
},
greeting: { fontSize: 22, fontWeight: "600", color: colors.Home },
});
+1 -1
View File
@@ -54,7 +54,7 @@ const UserProfileStatus: React.FC = () => {
const json: ApiResponse = await response.json();
console.log("👤 Profile Status Response:", json);
console.log("Profile Status :", json);
if (json.status === "success") {
setStatusData(json.data);
+33 -54
View File
@@ -14,86 +14,45 @@ import {
import { useNavigation, useFocusEffect } from "@react-navigation/native";
import { StackNavigationProp } from "@react-navigation/stack";
import { RootStackParamList } from "../../navigation/AppNavigator";
import { APPROVE_REQUEST_URL, BASE_URL, DECLINE_REQUEST_URL, GET_JOINED_GROUP_URL, JOIN_GROUP_URL, MY_GROUPS_URL, REQUESTS_URL } from "../../utils/ApiUrls";
import { APPROVE_REQUEST_URL, BASE_URL, DECLINE_REQUEST_URL, GET_JOINED_GROUP_URL, JOIN_GROUP_URL, MY_GROUPS_URL, REQUESTS_URL, USER_REQUEST } from "../../utils/ApiUrls";
import colors from "../../components/colors";
import AppView from "../../components/AppView";
import { apiCall } from "../../utils/ApiHelper";
import * as Keychain from "react-native-keychain";
import { MyGroup, JoinedGroup, JoinRequest, ApiResponse } from '../../types';
import { MyGroup, JoinedGroup, JoinRequest, ApiResponse, UserJoinRequest } from '../../types';
import { MyGroupCard } from "../../components/MyGroupCard";
import { JoinedGroupCard } from "../../components/JoinedGroupCard";
import { RequestCard } from "../../components/RequestCard";
import { useSelector } from "react-redux";
import Ionicons from "@react-native-vector-icons/ionicons";
import { UserRequested } from "../../components/UserRequested";
type GroupManagementNavProp = StackNavigationProp<RootStackParamList>;
type ActiveTab = "My Groups" | "Joined Groups" | "Requests" | "Your Requests";
const ManagementScreen: FC = () => {
const user = useSelector((state:any) => state.user)
const [activeTab, setActiveTab] = useState<ActiveTab>("My Groups");
const userRole = useSelector((state: any) => state.user)
const [activeTab, setActiveTab] = useState<ActiveTab>(userRole.role === "USER" ? "Joined Groups" : "My Groups");
const navigation = useNavigation<GroupManagementNavProp>();
const [myGroups, setMyGroups] = useState<MyGroup[]>([]);
const [joinedGroups, setJoinedGroups] = useState<JoinedGroup[]>([]);
const [requests, setRequests] = useState<JoinRequest[]>([]);
const [loading, setLoading] = useState<boolean>(false);
const [error, setError] = useState<string | null>(null);
const [userRole,setUserRole] = useState<string | null>(null)
const userStatus = async () => {
try {
const credentials = await Keychain.getGenericPassword();
if (!credentials) {
Alert.alert("Error", "You are not logged in");
return;
}
const token = credentials.password;
setLoading(true);
setError(null);
const response = await fetch(`${BASE_URL}user/profile/status`, {
method: "GET",
headers: {
Accept: "*/*",
Authorization: `Bearer ${token}`,
},
});
const json = await response.json();
console.log("👤 Profile Status Response:", json.data.role);
if (json.status === "success") {
setUserRole(json.data.role);
if (json.data.profileStatus === false) {
}
} else {
setError(json.message || "Failed to fetch status");
}
} catch (err) {
setError("Something went wrong. Please try again.");
} finally {
setLoading(false);
}
};
useFocusEffect(
useCallback(() => {
userStatus();
}, [])
);
const [userRequest, setUserRequest] = useState<UserJoinRequest[]>([])
const fetchData = useCallback(async () => {
if (loading) return;
setLoading(true);
setError(null);
try {
console.log(" abin user : ", userRole)
if (userRole === "ORGANIZER") {
console.log(" abin user : ", userRole)
if (userRole.role === "ORGANIZER") {
// Fetch all data concurrently
const [myGroupsRes, joinedGroupsRes, requestsRes] = await Promise.all([
apiCall(MY_GROUPS_URL, "GET") as Promise<ApiResponse<MyGroup[]>>,
apiCall(GET_JOINED_GROUP_URL, "GET") as Promise<ApiResponse<JoinedGroup[]>>, // Assuming this is also needed
apiCall(GET_JOINED_GROUP_URL, "GET") as Promise<ApiResponse<JoinedGroup[]>>,
apiCall(REQUESTS_URL, "GET") as Promise<ApiResponse<JoinRequest[]>>,
]);
@@ -105,10 +64,14 @@ const ManagementScreen: FC = () => {
setRequests(requestsRes.data || []);
} else {
// Fetch only joined groups for non-organizers
const [joinedGroupsRes] = await Promise.all([
const [joinedGroupsRes, userRequest] = await Promise.all([
apiCall(GET_JOINED_GROUP_URL, "GET") as Promise<ApiResponse<JoinedGroup[]>>, // Assuming this is also needed
apiCall(USER_REQUEST, "GET") as Promise<ApiResponse<UserJoinRequest[]>>, // Assuming this is also needed
]);
setJoinedGroups(joinedGroupsRes.data || []);
setJoinedGroups(joinedGroupsRes.data || []);
setUserRequest(userRequest?.data || []);
console.log("joinedGroupsRes data : ", joinedGroupsRes)
console.log("user request data : ", userRequest)
}
} catch (e) {
console.error("Fetch Data Error:", e);
@@ -197,12 +160,28 @@ const ManagementScreen: FC = () => {
contentContainerStyle={{ paddingBottom: 100 }}
/>
);
case "Your Requests":
if (loading && requests.length === 0) {
return <ActivityIndicator size="large" color={colors.primary} style={styles.loader} />;
}
return (
<FlatList
data={userRequest}
renderItem={({ item }: ListRenderItemInfo<UserJoinRequest>) => <UserRequested item={item} />}
keyExtractor={(item) => item.requestId}
ListEmptyComponent={<Text style={styles.emptyText}>No pending join requests.</Text>}
onRefresh={fetchData}
refreshing={loading} // This handles the "continuing loading" on pull-to-refresh
contentContainerStyle={{ paddingBottom: 100 }}
/>
);
default: return null;
}
};
const tabs: ActiveTab[] = userRole === 'ORGANIZER' ? ["My Groups", "Joined Groups", "Requests"] : ["Joined Groups", "Your Requests"];
const tabs: ActiveTab[] = userRole.role === 'ORGANIZER' ? ["My Groups", "Joined Groups", "Requests"] : ["Joined Groups", "Your Requests"];
console.log("user request : ", userRequest)
return (
<AppView style={styles.container} paddingHorizontal={0}>
<View style={styles.header}>