sid-address-verification-react-native
Version:
A sourceID react native package for address verification
361 lines (360 loc) • 13.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _jsxRuntime = require("react/jsx-runtime");
var _react = _interopRequireWildcard(require("react"));
var _reactNative = require("react-native");
var _ApiService = require("../services/ApiService");
var _LocationService = require("../services/LocationService");
var _permissions = require("../utils/permissions");
var _helper_functions = require("../utils/helper_functions");
var _GooglePlacesService = _interopRequireDefault(require("../services/GooglePlacesService"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
const AddressVerificationField = ({
config,
onAddressSelected,
onLocationUpdate,
onError,
chooseAddressType,
addressTypes,
onAddressTypeChange,
placeholder = 'Enter your address',
showSubmitButton = true,
style
// googlePlacesApiKey, // Add this prop to pass the API key
}) => {
const [query, setQuery] = (0, _react.useState)(config.initialAddressText || '');
const [suggestions, setSuggestions] = (0, _react.useState)([]);
const [selectedAddress, setSelectedAddress] = (0, _react.useState)(null);
const [selectedType, setSelectedType] = (0, _react.useState)(null);
const [loading, setLoading] = (0, _react.useState)(true);
const [loadingSuggestions, setLoadingSuggestions] = (0, _react.useState)(false);
const [pollingInterval, setPollingInterval] = (0, _react.useState)(15);
const [sessionTimeout, setSessionTimeout] = (0, _react.useState)(60);
const [sessionToken] = (0, _react.useState)(() => (0, _helper_functions.generateSessionToken)());
const [googlePlacesService] = (0, _react.useState)(() => new _GooglePlacesService.default(_helper_functions.GOOGLE_PLACES_KEY || ''));
// Debounced search function
const debouncedSearch = (0, _react.useCallback)((0, _helper_functions.debounce)(async searchQuery => {
if (searchQuery.trim().length > 2) {
setLoadingSuggestions(true);
try {
const predictions = await googlePlacesService.getAutocompletePredictions(searchQuery, sessionToken);
console.log('predictions', predictions);
if (Array.isArray(predictions)) {
setSuggestions(predictions);
} else {
console.warn('GooglePlacesService returned non-array predictions:', predictions);
setSuggestions([]); // fallback to empty
}
} catch (error) {
console.error('Error fetching suggestions:', error);
onError?.(`Failed to fetch suggestions: ${error}`);
setSuggestions([]);
} finally {
setLoadingSuggestions(false);
}
} else {
setSuggestions([]);
}
}, 300), [googlePlacesService, sessionToken, onError]);
// Initialize API service and fetch config
(0, _react.useEffect)(() => {
const initializeService = async () => {
try {
// Validate Google Places API key
// if (!googlePlacesApiKey) {
// throw new Error('Google Places API key is required');
// }
_ApiService.ApiService.getInstance().configure(config.apiKey, config.customerID);
const configData = await _ApiService.ApiService.getInstance().fetchAddressVerificationConfig();
setPollingInterval(configData.geotaggingPollingInterval || 15);
setSessionTimeout(configData.geotaggingSessionTimeout || 60);
} catch (error) {
console.error('Error initializing service:', error);
onError?.(`Failed to initialize: ${error}`);
} finally {
setLoading(false);
}
};
initializeService();
}, [config.apiKey, config.customerID, onError]);
// Trigger search when query changes
(0, _react.useEffect)(() => {
debouncedSearch(query);
}, [query, debouncedSearch]);
const handleSuggestionSelect = (0, _react.useCallback)(async suggestion => {
try {
setLoadingSuggestions(true);
const placeDetails = await googlePlacesService.getPlaceDetails(suggestion.place_id, sessionToken);
setSelectedAddress(placeDetails);
setQuery(placeDetails.address);
setSuggestions([]);
onAddressSelected(placeDetails);
} catch (error) {
console.error('Error selecting address:', error);
onError?.(`Failed to select address: ${error}`);
_reactNative.Alert.alert('Error', 'Failed to get address details. Please try again.');
} finally {
setLoadingSuggestions(false);
}
}, [onAddressSelected, onError, googlePlacesService, sessionToken]);
const handleSubmit = (0, _react.useCallback)(async () => {
if (!selectedAddress) {
_reactNative.Alert.alert('Error', 'Please select an address first');
return;
}
if (config.verifyLocation) {
try {
const permissionResult = await (0, _permissions.requestLocationPermission)();
if (!permissionResult.granted) {
_reactNative.Alert.alert('Permission Required', 'Location permission is required for address verification');
return;
}
// Start location tracking
const locationService = _LocationService.LocationService.getInstance();
locationService.startLocationTracking(config.locationFetchIntervalSeconds || pollingInterval, config.locationFetchDurationSeconds || sessionTimeout, onLocationUpdate);
_reactNative.Alert.alert('Success', 'Address verification started. Location tracking is now active.');
} catch (error) {
console.error('Error starting location verification:', error);
onError?.(`Failed to start location verification: ${error}`);
}
} else {
_reactNative.Alert.alert('Success', 'Address selected successfully');
}
}, [selectedAddress, config, pollingInterval, sessionTimeout, onLocationUpdate, onError]);
const handleClearAddress = (0, _react.useCallback)(() => {
setSelectedAddress(null);
setQuery('');
setSuggestions([]);
}, []);
if (loading) {
return (0, _jsxRuntime.jsxs)(_reactNative.View, {
style: [styles.container, style],
children: [(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
size: "large",
color: "#0000ff"
}), (0, _jsxRuntime.jsx)(_reactNative.Text, {
style: styles.loadingText,
children: "Loading configuration..."
})]
});
}
return (0, _jsxRuntime.jsxs)(_reactNative.View, {
style: [styles.container, style],
children: [(0, _jsxRuntime.jsxs)(_reactNative.View, {
style: styles.inputContainer,
children: [chooseAddressType && addressTypes?.length > 0 && (0, _jsxRuntime.jsx)(_reactNative.View, {
style: styles.addressTypeContainer,
children: addressTypes.map(type => (0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
style: [styles.addressTypeButton, selectedType === type && styles.addressTypeButtonSelected],
onPress: () => {
setSelectedType(type);
onAddressTypeChange?.(type);
},
children: (0, _jsxRuntime.jsx)(_reactNative.Text, {
style: [styles.addressTypeText, selectedType === type && styles.addressTypeTextSelected],
children: type
})
}, type))
}), (0, _jsxRuntime.jsx)(_reactNative.TextInput, {
style: styles.textInput,
value: query,
onChangeText: setQuery,
placeholder: placeholder,
placeholderTextColor: "#999",
autoComplete: "street-address",
autoCorrect: false,
keyboardAppearance: "light"
}), selectedAddress && (0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
style: styles.clearButton,
onPress: handleClearAddress,
children: (0, _jsxRuntime.jsx)(_reactNative.Text, {
style: styles.clearButtonText,
children: "\u2715"
})
})]
}), loadingSuggestions && (0, _jsxRuntime.jsx)(_reactNative.View, {
style: styles.loadingContainer,
children: (0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
size: "small",
color: "#0000ff"
})
}), suggestions.length > 0 && (0, _jsxRuntime.jsx)(_reactNative.FlatList, {
data: suggestions,
keyExtractor: item => item.place_id,
renderItem: ({
item
}) => (0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
style: styles.suggestionItem,
onPress: () => handleSuggestionSelect(item),
children: [(0, _jsxRuntime.jsx)(_reactNative.Text, {
style: styles.suggestionMain,
children: item.structured_formatting.main_text
}), (0, _jsxRuntime.jsx)(_reactNative.Text, {
style: styles.suggestionSecondary,
children: item.structured_formatting.secondary_text
})]
}),
style: styles.suggestionsList,
nestedScrollEnabled: true,
keyboardShouldPersistTaps: "handled"
}), showSubmitButton && (0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
style: [styles.submitButton, !selectedAddress && styles.submitButtonDisabled],
onPress: handleSubmit,
disabled: !selectedAddress,
children: (0, _jsxRuntime.jsx)(_reactNative.Text, {
style: styles.submitButtonText,
children: config.verifyLocation ? 'Verify Address' : 'Submit Address'
})
}), selectedAddress && (0, _jsxRuntime.jsxs)(_reactNative.View, {
style: styles.selectedAddressContainer,
children: [(0, _jsxRuntime.jsx)(_reactNative.Text, {
style: styles.selectedAddressLabel,
children: "Selected Address:"
}), (0, _jsxRuntime.jsx)(_reactNative.Text, {
style: styles.selectedAddressText,
children: selectedAddress.address
}), (0, _jsxRuntime.jsxs)(_reactNative.Text, {
style: styles.coordinatesText,
children: ["Coordinates: ", selectedAddress.latitude.toFixed(6), ",", ' ', selectedAddress.longitude.toFixed(6)]
})]
})]
});
};
const styles = _reactNative.StyleSheet.create({
container: {
padding: 16
},
inputContainer: {
position: 'relative'
},
textInput: {
borderWidth: 1,
borderColor: '#ccc',
borderRadius: 8,
padding: 12,
paddingRight: 40,
// Make room for clear button
fontSize: 16,
backgroundColor: '#fff',
color: '#000'
},
clearButton: {
position: 'absolute',
right: 12,
top: 12,
width: 24,
height: 24,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#f0f0f0',
borderRadius: 12
},
clearButtonText: {
fontSize: 14,
color: '#666',
fontWeight: 'bold'
},
loadingContainer: {
padding: 8,
alignItems: 'center'
},
loadingText: {
marginTop: 8,
fontSize: 16,
color: '#666'
},
suggestionsList: {
maxHeight: 200,
borderWidth: 1,
borderColor: '#ccc',
borderTopWidth: 0,
backgroundColor: '#fff',
borderBottomLeftRadius: 8,
borderBottomRightRadius: 8
},
suggestionItem: {
padding: 12,
borderBottomWidth: 1,
borderBottomColor: '#eee'
},
suggestionMain: {
fontSize: 16,
fontWeight: '600',
color: '#333'
},
addressTypeContainer: {
flexDirection: 'row',
flexWrap: 'wrap',
marginBottom: 12,
gap: 8
},
addressTypeButton: {
paddingVertical: 6,
paddingHorizontal: 12,
borderRadius: 16,
borderWidth: 1,
borderColor: '#ccc',
backgroundColor: '#f0f0f0'
},
addressTypeButtonSelected: {
backgroundColor: '#007AFF',
borderColor: '#007AFF'
},
addressTypeText: {
color: '#333',
fontSize: 14
},
addressTypeTextSelected: {
color: '#fff',
fontWeight: '600'
},
suggestionSecondary: {
fontSize: 14,
color: '#666',
marginTop: 2
},
submitButton: {
backgroundColor: '#007AFF',
padding: 12,
borderRadius: 8,
alignItems: 'center',
marginTop: 16
},
submitButtonDisabled: {
backgroundColor: '#ccc'
},
submitButtonText: {
color: '#fff',
fontSize: 16,
fontWeight: '600'
},
selectedAddressContainer: {
marginTop: 16,
padding: 12,
backgroundColor: '#f8f8f8',
borderRadius: 8,
borderLeftWidth: 4,
borderLeftColor: '#007AFF'
},
selectedAddressLabel: {
fontSize: 14,
fontWeight: '600',
marginBottom: 4,
color: '#333'
},
selectedAddressText: {
fontSize: 16,
marginBottom: 4,
color: '#333'
},
coordinatesText: {
fontSize: 14,
color: '#666'
}
});
var _default = exports.default = AddressVerificationField;
//# sourceMappingURL=AddressVerificationField.js.map