native_convex_CRM/app/features/customerDetails/customerDetails.screen.tsx

210 lines
6.9 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 } from '@react-navigation/native';
import { useTheme } from '@theme';
import { useAppDispatch, useAppSelector, RootState } from '@store';
import { getCustomerDetails } from './thunk';
import { getStyles } from './customerDetails.styles';
import { CustomersStackParamList } from '../../navigation/customersStack';
import { Loader, CustomerDetailHeader } from '@components';
import {
handleEmailPress,
handlePhonePress,
handleWebsitePress,
} from '@utils';
type CustomerDetailsRouteProp = RouteProp<
CustomersStackParamList,
'customerDetails'
>;
export const CustomerDetailsScreen = () => {
const route = useRoute<CustomerDetailsRouteProp>();
const dispatch = useAppDispatch();
const { theme: colors } = useTheme();
const styles = getStyles(colors);
const userid = route.params?.userid || route.params?.customer?.userid;
const initialCustomer = route.params?.customer;
const { item: customerState, loading, error } = useAppSelector(
(state: RootState) => state.customerDetails,
);
useEffect(() => {
if (userid) {
dispatch(getCustomerDetails({ userid }));
}
}, [dispatch, userid]);
const customer = customerState || initialCustomer;
if (loading && !customer) {
return <Loader message="Loading customer details..." />;
}
if (error && !customer) {
return (
<View style={styles.centered}>
<Icon name="alert-circle-outline" size={40} color="#EF4444" />
<Text style={styles.errorText}>{error}</Text>
</View>
);
}
if (!customer) {
return (
<View style={styles.centered}>
<Icon name="person-outline" size={40} color={colors.textMuted} />
<Text style={styles.infoValue}>No customer details found.</Text>
</View>
);
}
const billingAddress = [
customer.billing_street || customer.address,
customer.billing_city || customer.city,
customer.billing_state || customer.state,
customer.billing_zip || customer.zip,
customer.billing_country || customer.country,
]
.filter(Boolean)
.join(', ');
const shippingAddress = [
customer.shipping_street,
customer.shipping_city,
customer.shipping_state,
customer.shipping_zip,
customer.shipping_country,
]
.filter(Boolean)
.join(', ');
return (
<ScrollView style={styles.container} contentContainerStyle={styles.scrollContent}>
{/* Top Header & Quick Actions */}
<CustomerDetailHeader
company={customer.company}
fullname={customer.fullname}
active={customer.active}
datecreated={customer.datecreated}
email={customer.email}
phonenumber={customer.phonenumber}
website={customer.website}
onEmailPress={() => handleEmailPress(customer.email)}
onPhonePress={() => handlePhonePress(customer.phonenumber)}
onWebsitePress={() => handleWebsitePress(customer.website)}
/>
{/* Contact Details */}
<Text style={styles.sectionTitle}>Contact Details</Text>
<View style={styles.infoCard}>
{customer.email ? (
<>
<TouchableOpacity
style={styles.infoRow}
onPress={() => handleEmailPress(customer.email)}
activeOpacity={0.7}>
<View style={styles.infoIconWrap}>
<Icon name="mail-outline" size={16} color={colors.icon} />
</View>
<View style={styles.infoMeta}>
<Text style={styles.infoLabel}>Email</Text>
<Text style={styles.infoValue}>{customer.email}</Text>
</View>
</TouchableOpacity>
<View style={styles.divider} />
</>
) : null}
{customer.phonenumber ? (
<>
<TouchableOpacity
style={styles.infoRow}
onPress={() => handlePhonePress(customer.phonenumber)}
activeOpacity={0.7}>
<View style={styles.infoIconWrap}>
<Icon name="call-outline" size={16} color={colors.icon} />
</View>
<View style={styles.infoMeta}>
<Text style={styles.infoLabel}>Phone</Text>
<Text style={styles.infoValue}>{customer.phonenumber}</Text>
</View>
</TouchableOpacity>
<View style={styles.divider} />
</>
) : null}
{customer.website ? (
<>
<TouchableOpacity
style={styles.infoRow}
onPress={() => handleWebsitePress(customer.website)}
activeOpacity={0.7}>
<View style={styles.infoIconWrap}>
<Icon name="globe-outline" size={16} color={colors.icon} />
</View>
<View style={styles.infoMeta}>
<Text style={styles.infoLabel}>Website</Text>
<Text style={styles.infoValue}>{customer.website}</Text>
</View>
</TouchableOpacity>
<View style={styles.divider} />
</>
) : null}
{customer.vat ? (
<View style={styles.infoRow}>
<View style={styles.infoIconWrap}>
<Icon name="receipt-outline" size={16} color={colors.icon} />
</View>
<View style={styles.infoMeta}>
<Text style={styles.infoLabel}>VAT Number</Text>
<Text style={styles.infoValue}>{customer.vat}</Text>
</View>
</View>
) : null}
</View>
{/* Address Information */}
<Text style={styles.sectionTitle}>Address Information</Text>
<View style={styles.infoCard}>
{billingAddress ? (
<>
<View style={styles.infoRow}>
<View style={styles.infoIconWrap}>
<Icon name="location-outline" size={16} color={colors.icon} />
</View>
<View style={styles.infoMeta}>
<Text style={styles.infoLabel}>Billing Address</Text>
<Text style={styles.infoValue}>{billingAddress}</Text>
</View>
</View>
{shippingAddress ? <View style={styles.divider} /> : null}
</>
) : null}
{shippingAddress ? (
<View style={styles.infoRow}>
<View style={styles.infoIconWrap}>
<Icon name="navigate-outline" size={16} color={colors.icon} />
</View>
<View style={styles.infoMeta}>
<Text style={styles.infoLabel}>Shipping Address</Text>
<Text style={styles.infoValue}>{shippingAddress}</Text>
</View>
</View>
) : null}
{!billingAddress && !shippingAddress ? (
<Text style={styles.infoValue}>No address information provided.</Text>
) : null}
</View>
</ScrollView>
);
};