Files
circle-collect/src/screens/home/Home.tsx
T
2025-10-16 15:23:46 +05:30

192 lines
6.9 KiB
TypeScript

import React, { useEffect, useState } from "react";
import {
StyleSheet,
Text,
View,
TouchableOpacity,
UIManager,
Platform,
Image,
Alert,
FlatList,
ListRenderItem,
ToastAndroid,
} from "react-native";
import AppView from "../../components/AppView";
import colors from "../../components/colors";
import { useDispatch, useSelector } from "react-redux";
import { useNavigation } from "@react-navigation/native";
import { PROFILE_URL } from "../../utils/ApiUrls";
import { setUserData } from "../../redux/userSlice";
import { TabNavigationProp } from "../../navigation/BottomTabs";
import UserProfileStatus from "./UserProfileStatus";
import AnimatedCard from "../../components/common/AnimatedCard";
import { Ionicons, IoniconsIconName } from "@react-native-vector-icons/ionicons";
import { apiCall } from "../../utils/ApiHelper";
if (Platform.OS === "android" && UIManager.setLayoutAnimationEnabledExperimental) {
UIManager.setLayoutAnimationEnabledExperimental(true);
}
type UserProfile = {
id: string;
userId: number;
firstName: string | null;
lastName: string | null;
imageBlob: string | null;
role?: string;
};
interface ActionItem {
id: string;
title: string;
action: string;
tab?: "My Groups" | "Joined Groups" | "Requests" | "Your Requests";
iconName?: IoniconsIconName;
backOne?: string;
backTwo?: string;
subtitle?: string;
}
// Updated action items with a prettier pastel palette
const organizerActions: ActionItem[] = [
{ id: "1", title: "My Groups", subtitle: "Manage your groups", action: "NAVIGATE_MANAGEMENT", tab: "My Groups", iconName: "people-circle-outline", backOne: '#decbfcff', backTwo: '#B799FF' },
{ id: "2", title: "Joined Groups", subtitle: "View member groups", action: "NAVIGATE_MANAGEMENT", tab: "Joined Groups", iconName: "people-outline", backOne: '#D7E9F7', backTwo: '#82AAE3' },
{ id: "3", title: "Requests", subtitle: "Check new requests", action: "NAVIGATE_MANAGEMENT", tab: "Requests", iconName: "notifications-outline", backOne: '#DFF6DD', backTwo: '#88D18A' },
{ id: "4", title: "Create Group", subtitle: "Create a new group", action: "NAVIGATE_CREATE_GROUP", tab: "Requests", iconName: "people-outline", backOne: '#DFF6DD', backTwo: '#88D18A' },
];
const userActions: ActionItem[] = [
{ id: "1", title: "Joined Groups", subtitle: "See your groups", action: "NAVIGATE_MANAGEMENT", tab: "Joined Groups", iconName: "person-outline", backOne: '#D7E9F7', backTwo: '#82AAE3' },
{ id: "2", title: "Your Requests", subtitle: "Track your requests", action: "NAVIGATE_MANAGEMENT", tab: "Your Requests", iconName: "mail-open-outline", backOne: '#FFF4D2', backTwo: '#FFB344' },
{ id: "3", title: "Transactions", subtitle: "View your history", action: "TRANSACTION", iconName: "receipt-outline", backOne: '#decbfcff', backTwo: '#B799FF' },
{ id: "4", title: "Create Group", subtitle: "Create a new group", action: "NAVIGATE_CREATE_GROUP", tab: "Requests", iconName: "people-outline", backOne: '#DFF6DD', backTwo: '#88D18A' },
];
const Home: React.FC = () => {
const user = useSelector((state: any) => state.user);
const notifications = useSelector(
(state: any) => state.notifications.notifications
);
const navigation = useNavigation<TabNavigationProp>();
const dispatch = useDispatch();
const actions = user.role === 'ORGANIZER' ? organizerActions : userActions;
const [apiUser, setApiUser] = useState<UserProfile | null>(null);
useEffect(() => {
const fetchUserProfile = async () => {
try {
const result = await apiCall(PROFILE_URL, "GET") as any;
if (result.status === "success") {
setApiUser(result.data);
dispatch(setUserData({ ...result.data, profileStatus: true }));
}
} catch (error) {
console.error("❌ Error fetching profile:", error);
}
};
const unsubscribe = navigation.addListener('focus', fetchUserProfile);
fetchUserProfile();
return unsubscribe;
}, [navigation, dispatch]);
const handleActionPress = (item: ActionItem) => {
if (item.action === "NAVIGATE_MANAGEMENT" && item.tab) {
navigation.navigate('Management', { actionTab: item.tab });
} else if (item.action === "TRANSACTION") {
navigation.navigate("TransactionList" as never);
} else if (item.action === "NAVIGATE_CREATE_GROUP") {
navigation.navigate("GroupCreation" as never);
} else {
ToastAndroid.show(`Unknown action: ${item.title}`, ToastAndroid.SHORT);
}
};
const unreadCount = notifications.filter((item: any) => !item.read).length;
const renderGridItem: ListRenderItem<ActionItem> = ({ item }) => (
<View style={styles.cardWrapper}>
<AnimatedCard
key={item.id}
title={item.title}
subtitle={item.subtitle}
iconName={item.iconName}
backOne={item.backOne}
backTwo={item.backTwo}
onPress={() => handleActionPress(item)}
/>
</View>
);
const getProfileImageUri = () => {
const blob = user.imageBlob || apiUser?.imageBlob;
return blob ? { uri: `data:image/jpeg;base64,${blob}` } : require('../../assets/images/placeholder.png');
};
return (
<AppView barStyle="dark-content" style={styles.container}>
<View style={styles.header}>
<View>
<Text style={styles.greeting}>Hello,</Text>
<Text style={styles.userName}>{user.firstName || apiUser?.firstName || 'User'}</Text>
</View>
<TouchableOpacity onPress={() => navigation.navigate("Notification" as never)}>
<Text style={{ position: 'absolute', right: -6, top: -4, backgroundColor: colors.danger, color: colors.white, borderRadius: 8, width: 16, height: 16, textAlign: 'center', fontSize: 10, fontWeight: 'bold', lineHeight: 16, zIndex: 1 }}>{unreadCount > 0 ? unreadCount : ''}</Text>
<Ionicons name="notifications-outline" size={30} color={colors.textDark} />
</TouchableOpacity>
</View>
<UserProfileStatus profileImage={getProfileImageUri()} />
<Text style={styles.sectionTitle}>Quick Actions</Text>
<FlatList
data={actions}
renderItem={renderGridItem}
keyExtractor={(item) => item.id}
numColumns={2}
contentContainerStyle={{ paddingHorizontal: 8 }}
/>
</AppView>
);
};
export default Home;
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: colors.white, // Set background to white
},
header: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingHorizontal: 20,
paddingTop: 24,
paddingBottom: 16,
},
greeting: {
fontSize: 22,
color: colors.textDark,
},
userName: {
fontSize: 28,
fontWeight: 'bold',
color: colors.textDark,
},
sectionTitle: {
fontSize: 20,
fontWeight: '600',
color: colors.textDark,
paddingHorizontal: 20,
marginBottom: 8,
},
cardWrapper: {
flex: 1,
// marginHorizontal: 8,
// backgroundColor:'red'
},
});