192 lines
6.9 KiB
TypeScript
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'
|
|
},
|
|
});
|