native_convex_CRM/app/features/leadDetails/leadDetails.screen.tsx
2026-07-22 13:33:19 +05:30

207 lines
7.4 KiB
TypeScript

import React, { useEffect } from 'react';
import { View, Text, ScrollView, TouchableOpacity } from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import { RouteProp, useRoute, useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { useTheme } from '@theme';
import { useAppDispatch, useAppSelector, RootState } from '@store';
import { getLeadDetails } from './thunk';
import { getStyles } from './leadDetails.styles';
import { LeadsStackParamList } from '../../navigation/leadsStack';
import { Loader, LeadDetailHeader, ActionCard } from '@components';
import { handleEmailPress, handlePhonePress, handleWebsitePress, formatDate, route as routes } from '@utils';
type LeadDetailsRouteProp = RouteProp<LeadsStackParamList, 'leadDetails'>;
type LeadDetailsNavigationProp = NativeStackNavigationProp<LeadsStackParamList, 'leadDetails'>;
export const LeadDetailsScreen = () => {
const route = useRoute<LeadDetailsRouteProp>();
const navigation = useNavigation<LeadDetailsNavigationProp>();
const dispatch = useAppDispatch();
const { theme: colors } = useTheme();
const styles = getStyles(colors);
const leadId = route.params?.lead?.id;
const { item: lead, loading, error } = useAppSelector((state: RootState) => state.leadDetails);
const user_data = useAppSelector((state: RootState) => state.auth.user_data);
useEffect(() => {
if (leadId && user_data?.staffid) {
dispatch(getLeadDetails({ leadId, staffid: user_data.staffid }));
}
}, [dispatch, leadId, user_data]);
if (loading) return <Loader message="Loading lead details..." />;
if (error) {
return (
<View style={styles.container}>
<View style={styles.errorContainer}>
<Text style={styles.errorText}>{error}</Text>
</View>
</View>
);
}
if (!lead) {
return (
<View style={styles.container}>
<View style={styles.errorContainer}>
<Text style={styles.infoValue}>No lead data available</Text>
</View>
</View>
);
}
const addressString = [lead.address, lead.city, lead.state, lead.country]
.filter(Boolean)
.join(', ');
return (
<ScrollView style={styles.container} contentContainerStyle={styles.scrollContent}>
<LeadDetailHeader
name={lead.name}
company={lead.company}
email={lead.email}
phonenumber={lead.phonenumber}
statusName={lead.status_name || lead.status}
statusColor={lead.color}
onEmailPress={() => handleEmailPress(lead.email)}
onPhonePress={() => handlePhonePress(lead.phonenumber)}
/>
<View style={styles.statsRow}>
<View style={styles.statCard}>
<Text style={styles.statLabel}>Lead Value</Text>
<Text style={styles.statValue}>
{lead.lead_value ? `$${lead.lead_value}` : 'N/A'}
</Text>
</View>
<View style={styles.statCard}>
<Text style={styles.statLabel}>Source</Text>
<Text style={styles.statValue} numberOfLines={1}>
{lead.source_name || lead.source || 'Direct'}
</Text>
</View>
<View style={styles.statCard}>
<Text style={styles.statLabel}>Created</Text>
<Text style={styles.statValue} numberOfLines={1}>
{formatDate(lead.dateadded) || 'N/A'}
</Text>
</View>
</View>
<Text style={styles.sectionTitle}>Lead Information</Text>
<View style={styles.infoCard}>
{lead.email ? (
<>
<TouchableOpacity
style={styles.infoRow}
onPress={() => handleEmailPress(lead.email)}
activeOpacity={0.7}>
<View style={styles.infoIconWrap}>
<Icon name="mail-outline" size={15} color={colors.icon} />
</View>
<View style={styles.infoMeta}>
<Text style={styles.infoLabel}>Email</Text>
<Text style={styles.infoValue}>{lead.email}</Text>
</View>
</TouchableOpacity>
<View style={styles.divider} />
</>
) : null}
{lead.phonenumber ? (
<>
<TouchableOpacity
style={styles.infoRow}
onPress={() => handlePhonePress(lead.phonenumber)}
activeOpacity={0.7}>
<View style={styles.infoIconWrap}>
<Icon name="call-outline" size={15} color={colors.icon} />
</View>
<View style={styles.infoMeta}>
<Text style={styles.infoLabel}>Phone</Text>
<Text style={styles.infoValue}>{lead.phonenumber}</Text>
</View>
</TouchableOpacity>
<View style={styles.divider} />
</>
) : null}
{lead.website ? (
<>
<TouchableOpacity
style={styles.infoRow}
onPress={() => handleWebsitePress(lead.website)}
activeOpacity={0.7}>
<View style={styles.infoIconWrap}>
<Icon name="globe-outline" size={15} color={colors.icon} />
</View>
<View style={styles.infoMeta}>
<Text style={styles.infoLabel}>Website</Text>
<Text style={styles.infoValue}>{lead.website}</Text>
</View>
</TouchableOpacity>
<View style={styles.divider} />
</>
) : null}
{addressString ? (
<>
<View style={styles.infoRow}>
<View style={styles.infoIconWrap}>
<Icon name="location-outline" size={15} color={colors.icon} />
</View>
<View style={styles.infoMeta}>
<Text style={styles.infoLabel}>Address</Text>
<Text style={styles.infoValue}>{addressString}</Text>
</View>
</View>
<View style={styles.divider} />
</>
) : null}
{lead.assigned ? (
<View style={styles.infoRow}>
<View style={styles.infoIconWrap}>
<Icon name="person-outline" size={15} color={colors.icon} />
</View>
<View style={styles.infoMeta}>
<Text style={styles.infoLabel}>Assigned Staff</Text>
<Text style={styles.infoValue}>{lead.assigned}</Text>
</View>
</View>
) : null}
</View>
<Text style={styles.sectionTitle}>Activity & Management</Text>
<View style={styles.cardsContainer}>
<ActionCard
title="Proposals"
icon="document-text-outline"
count={0}
onAddPress={() => navigation.navigate(routes.leadProposals, { leadId: lead.id })}
onViewAllPress={() => navigation.navigate(routes.leadProposals, { leadId: lead.id })}
/>
<ActionCard
title="Tasks"
icon="checkbox-outline"
count={0}
onAddPress={() => navigation.navigate(routes.leadTasks, { leadId: lead.id })}
onViewAllPress={() => navigation.navigate(routes.leadTasks, { leadId: lead.id })}
/>
<ActionCard
title="Notes"
icon="create-outline"
count={0}
onAddPress={() => navigation.navigate(routes.leadNotes, { leadId: lead.id })}
onViewAllPress={() => navigation.navigate(routes.leadNotes, { leadId: lead.id })}
/>
</View>
</ScrollView>
);
};