254 lines
7.6 KiB
TypeScript
254 lines
7.6 KiB
TypeScript
import React, { useEffect, useMemo, useState } from 'react';
|
|
import {
|
|
View,
|
|
Text,
|
|
TouchableOpacity,
|
|
ScrollView,
|
|
KeyboardAvoidingView,
|
|
Platform,
|
|
Alert,
|
|
} from 'react-native';
|
|
import Icon from 'react-native-vector-icons/Ionicons';
|
|
import { getStyles } from './addLead.styles';
|
|
import { useTheme } from '@theme';
|
|
import { FormInput, FormPicker } from '@components';
|
|
import { RootState, useAppDispatch, useAppSelector } from '@store';
|
|
import { addLead, resetAddLeadState } from './thunk';
|
|
|
|
export const AddLeadScreen = () => {
|
|
const { theme: colors } = useTheme();
|
|
const styles = getStyles(colors);
|
|
const dispatch = useAppDispatch();
|
|
|
|
const userData = useAppSelector((state: RootState) => state.auth.user_data);
|
|
const { loading, successMessage, error } = useAppSelector(
|
|
(state: RootState) => state.addLead,
|
|
);
|
|
const { items: sourceItems } = useAppSelector(
|
|
(state: RootState) => state.sourceList,
|
|
);
|
|
const { items: statusItems } = useAppSelector(
|
|
(state: RootState) => state.statusList,
|
|
);
|
|
const { items: countryItems } = useAppSelector(
|
|
(state: RootState) => state.countryList,
|
|
);
|
|
|
|
const [company, setCompany] = useState('');
|
|
const [fullName, setFullName] = useState('');
|
|
const [email, setEmail] = useState('');
|
|
const [phone, setPhone] = useState('');
|
|
const [website, setWebsite] = useState('');
|
|
const [source, setSource] = useState('');
|
|
const [status, setStatus] = useState('');
|
|
const [address, setAddress] = useState('');
|
|
const [city, setCity] = useState('');
|
|
const [state, setState] = useState('');
|
|
const [zip, setZip] = useState('');
|
|
const [country, setCountry] = useState('');
|
|
|
|
const sourceOptions = useMemo(
|
|
() => sourceItems.map(s => ({ label: s.name, value: s.id })),
|
|
[sourceItems],
|
|
);
|
|
const statusOptions = useMemo(
|
|
() => statusItems.map(s => ({ label: s.name, value: s.id })),
|
|
[statusItems],
|
|
);
|
|
const countryOptions = useMemo(
|
|
() => countryItems.map(c => ({ label: c.short_name, value: c.country_id })),
|
|
[countryItems],
|
|
);
|
|
|
|
useEffect(() => {
|
|
if (successMessage) {
|
|
Alert.alert('Success', successMessage);
|
|
setCompany('');
|
|
setFullName('');
|
|
setEmail('');
|
|
setPhone('');
|
|
setWebsite('');
|
|
setSource('');
|
|
setStatus('');
|
|
setAddress('');
|
|
setCity('');
|
|
setState('');
|
|
setZip('');
|
|
setCountry('');
|
|
dispatch(resetAddLeadState());
|
|
} else if (error) {
|
|
Alert.alert('Error', error);
|
|
dispatch(resetAddLeadState());
|
|
}
|
|
}, [successMessage, error, dispatch]);
|
|
|
|
const handleSubmit = () => {
|
|
if (!fullName.trim() || !email.trim() || !source || !status) {
|
|
Alert.alert('Error', 'Full Name, Email, Source and Status are required.');
|
|
return;
|
|
}
|
|
|
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
if (!emailRegex.test(email.trim())) {
|
|
Alert.alert('Error', 'Please enter a valid email address.');
|
|
return;
|
|
}
|
|
|
|
|
|
const staffId = userData?.staffid || '';
|
|
if (!staffId) {
|
|
Alert.alert('Error', 'User session invalid. Please log in again.');
|
|
return;
|
|
}
|
|
|
|
dispatch(
|
|
addLead({
|
|
staff_id: staffId,
|
|
name: fullName,
|
|
company,
|
|
email,
|
|
phonenumber: phone,
|
|
website,
|
|
source,
|
|
status,
|
|
address,
|
|
city,
|
|
state,
|
|
zip,
|
|
country,
|
|
}),
|
|
);
|
|
};
|
|
|
|
|
|
|
|
return (
|
|
<KeyboardAvoidingView
|
|
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
|
style={styles.container}>
|
|
<ScrollView
|
|
contentContainerStyle={styles.scrollContainer}
|
|
keyboardShouldPersistTaps="handled">
|
|
|
|
{/* Basic Info */}
|
|
<View style={styles.formCard}>
|
|
<Text style={styles.sectionHeader}>Basic Information</Text>
|
|
|
|
<FormInput
|
|
label="Company"
|
|
placeholder="Acme Corp"
|
|
value={company}
|
|
onChangeText={setCompany}
|
|
leftIcon={<Icon name="business-outline" size={18} color={colors.textSecondary} />}
|
|
/>
|
|
<FormInput
|
|
label="Full Name"
|
|
required
|
|
placeholder="John Doe"
|
|
value={fullName}
|
|
onChangeText={setFullName}
|
|
leftIcon={<Icon name="person-outline" size={18} color={colors.textSecondary} />}
|
|
/>
|
|
<FormInput
|
|
label="Email"
|
|
required
|
|
placeholder="john@acme.com"
|
|
value={email}
|
|
onChangeText={setEmail}
|
|
keyboardType="email-address"
|
|
autoCapitalize="none"
|
|
leftIcon={<Icon name="mail-outline" size={18} color={colors.textSecondary} />}
|
|
/>
|
|
<FormInput
|
|
label="Phone Number"
|
|
placeholder="+1 (555) 000-0000"
|
|
value={phone}
|
|
onChangeText={setPhone}
|
|
keyboardType="phone-pad"
|
|
leftIcon={<Icon name="call-outline" size={18} color={colors.textSecondary} />}
|
|
/>
|
|
<FormInput
|
|
label="Website"
|
|
placeholder="https://acme.com"
|
|
value={website}
|
|
onChangeText={setWebsite}
|
|
keyboardType="url"
|
|
autoCapitalize="none"
|
|
leftIcon={<Icon name="globe-outline" size={18} color={colors.textSecondary} />}
|
|
/>
|
|
</View>
|
|
|
|
{/* Classification */}
|
|
<View style={[styles.formCard, styles.cardSpacing]}>
|
|
<Text style={styles.sectionHeader}>Classification</Text>
|
|
|
|
<FormPicker
|
|
label="Source"
|
|
required
|
|
value={source}
|
|
onValueChange={setSource}
|
|
options={sourceOptions}
|
|
placeholder="Select source..."
|
|
/>
|
|
<FormPicker
|
|
label="Status"
|
|
required
|
|
value={status}
|
|
onValueChange={setStatus}
|
|
options={statusOptions}
|
|
placeholder="Select status..."
|
|
/>
|
|
</View>
|
|
|
|
{/* Address */}
|
|
<View style={[styles.formCard, styles.cardSpacing]}>
|
|
<Text style={styles.sectionHeader}>Address</Text>
|
|
|
|
<FormInput
|
|
label="Address"
|
|
placeholder="123 Main Street"
|
|
value={address}
|
|
onChangeText={setAddress}
|
|
leftIcon={<Icon name="location-outline" size={18} color={colors.textSecondary} />}
|
|
/>
|
|
<View style={styles.row}>
|
|
<View style={styles.rowHalf}>
|
|
<FormInput label="City" placeholder="New York" value={city} onChangeText={setCity} />
|
|
</View>
|
|
<View style={styles.rowHalf}>
|
|
<FormInput label="State" placeholder="NY" value={state} onChangeText={setState} />
|
|
</View>
|
|
</View>
|
|
<FormInput
|
|
label="ZIP / Postal Code"
|
|
placeholder="10001"
|
|
value={zip}
|
|
onChangeText={setZip}
|
|
keyboardType="number-pad"
|
|
leftIcon={<Icon name="map-outline" size={18} color={colors.textSecondary} />}
|
|
/>
|
|
<FormPicker
|
|
label="Country"
|
|
value={country}
|
|
onValueChange={setCountry}
|
|
options={countryOptions}
|
|
placeholder="Select country..."
|
|
searchable
|
|
/>
|
|
</View>
|
|
|
|
{/* Submit */}
|
|
<TouchableOpacity
|
|
style={[styles.submitButton, loading && { opacity: 0.7 }]}
|
|
activeOpacity={0.8}
|
|
disabled={loading}
|
|
onPress={handleSubmit}>
|
|
<Icon name="checkmark-circle-outline" size={20} color="#FFFFFF" style={styles.buttonIcon} />
|
|
<Text style={styles.submitButtonText}>{loading ? 'Creating Lead...' : 'Create Lead'}</Text>
|
|
</TouchableOpacity>
|
|
|
|
</ScrollView>
|
|
</KeyboardAvoidingView>
|
|
);
|
|
};
|