213 lines
7.0 KiB
TypeScript
213 lines
7.0 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}
|
|
/>
|
|
|
|
{/* 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>
|
|
<View style={styles.actionIconButton}>
|
|
<Icon name="chevron-forward" size={14} color={colors.textMuted} />
|
|
</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>
|
|
<View style={styles.actionIconButton}>
|
|
<Icon name="chevron-forward" size={14} color={colors.textMuted} />
|
|
</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>
|
|
<View style={styles.actionIconButton}>
|
|
<Icon name="chevron-forward" size={14} color={colors.textMuted} />
|
|
</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>
|
|
);
|
|
};
|