diff --git a/src/components/BackButton.tsx b/src/components/BackButton.tsx
index eb8b307..04131c5 100644
--- a/src/components/BackButton.tsx
+++ b/src/components/BackButton.tsx
@@ -1,11 +1,8 @@
-import React from 'react';
+import HeaderButton from './HeaderButton';
import { useNavigation } from '@react-navigation/native';
-import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome';
import { faArrowLeft } from '@fortawesome/free-solid-svg-icons';
-import { Button, useTheme } from 'tamagui';
const BackButton = ({ ...props }) => {
- const theme = useTheme();
const navigation = useNavigation();
const { onPress } = props;
@@ -17,13 +14,7 @@ const BackButton = ({ ...props }) => {
}
};
- return (
-
- );
+ return ;
};
export default BackButton;
diff --git a/src/components/ExpandableSelect.tsx b/src/components/ExpandableSelect.tsx
index 8f87e4b..350ddfd 100644
--- a/src/components/ExpandableSelect.tsx
+++ b/src/components/ExpandableSelect.tsx
@@ -1,6 +1,6 @@
import React, { useState, useRef, useEffect } from 'react';
import { Animated, Easing } from 'react-native';
-import { XStack, YStack, Text, Button, Separator, useTheme } from 'tamagui';
+import { Spinner, XStack, YStack, Text, Button, Separator, useTheme } from 'tamagui';
import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome';
import { faChevronUp, faChevronDown } from '@fortawesome/free-solid-svg-icons';
import { isNone } from '../utils';
@@ -28,8 +28,8 @@ const ExpandableSelect = ({ value, optionValue, options = [], onSelect }) => {
const dropdownAnimation = useRef(new Animated.Value(0)).current;
// Animated values for the dropdown toggle
- const toggleScale = useRef(new Animated.Value(0)).current;
- const toggleOpacity = useRef(new Animated.Value(0)).current;
+ const toggleScale = useRef(new Animated.Value(selectedOption ? 1 : 0)).current;
+ const toggleOpacity = useRef(new Animated.Value(selectedOption ? 1 : 0)).current;
useEffect(() => {
// Initialize optionAnimations when options change
@@ -260,7 +260,7 @@ const ExpandableSelect = ({ value, optionValue, options = [], onSelect }) => {
// Ensure optionAnimations are ready before rendering
if (optionAnimations.length !== options.length) {
- return null; // or render a loading indicator
+ return ; // or render a loading indicator
}
// Render options or dropdown toggle based on state
@@ -274,7 +274,6 @@ const ExpandableSelect = ({ value, optionValue, options = [], onSelect }) => {
return (
- {/* Selected Option */}
{
onPressIn={onPressIn}
onPressOut={onPressOut}
size='$5'
+ flex={1}
+ width='100%'
justifyContent='space-between'
bg='white'
borderWidth={1}
@@ -315,7 +316,6 @@ const ExpandableSelect = ({ value, optionValue, options = [], onSelect }) => {
- {/* Dropdown Options */}
{shouldRenderDropdown && (
{
+ const theme = useTheme();
+
+ const handlePress = function () {
+ if (typeof onPress === 'function') {
+ onPress();
+ }
+ };
+
+ return (
+
+ );
+};
+
+export default HeaderButton;
diff --git a/src/components/PlaceMapView.tsx b/src/components/PlaceMapView.tsx
new file mode 100644
index 0000000..a72ed7a
--- /dev/null
+++ b/src/components/PlaceMapView.tsx
@@ -0,0 +1,37 @@
+import React, { useState } from 'react';
+import { TouchableOpacity, StyleSheet } from 'react-native';
+import MapView, { Marker } from 'react-native-maps';
+import { YStack, useTheme } from 'tamagui';
+import { restoreFleetbasePlace, getCoordinates } from '../utils/location';
+
+const PlaceMapView = ({ place: _place, height = 200, onPress, mapViewProps = {}, ...props }) => {
+ const place = restoreFleetbasePlace(_place);
+ const [latitude, longitude] = getCoordinates(place);
+ const [mapRegion, setMapRegion] = useState({
+ latitude,
+ longitude,
+ latitudeDelta: 0.0005,
+ longitudeDelta: 0.0005,
+ });
+
+ return (
+
+
+ setMapRegion(region)}
+ scrollEnabled={false}
+ zoomEnabled={false}
+ pitchEnabled={false}
+ rotateEnabled={false}
+ {...mapViewProps}
+ >
+
+
+
+
+ );
+};
+
+export default PlaceMapView;
diff --git a/src/components/ProductCard.tsx b/src/components/ProductCard.tsx
index 56b8432..6d98da2 100644
--- a/src/components/ProductCard.tsx
+++ b/src/components/ProductCard.tsx
@@ -85,6 +85,7 @@ const ProductCard = ({
sliderWidth={cardWidth}
sliderHeight={sliderHeight}
sliderStyle={{ borderTopRightRadius: 10, borderTopLeftRadius: 10 }}
+ onImagePress={handlePress}
autoplay
/>
@@ -106,7 +107,7 @@ const ProductCard = ({
{product.getAttribute('on_sale') ? (
-
+
{formatCurrency(product.getAttribute('sale_price'), product.getAttribute('currency'))}
@@ -114,7 +115,7 @@ const ProductCard = ({
) : (
-
+
{formatCurrency(product.getAttribute('price'), product.getAttribute('currency'))}
)}
@@ -133,11 +134,11 @@ const ProductCard = ({
color='white'
width='100%'
hoverStyle={{
- scale: 0.75,
+ scale: 0.95,
opacity: 0.5,
}}
pressStyle={{
- scale: 0.75,
+ scale: 0.95,
opacity: 0.5,
}}
>
diff --git a/src/components/QuantityButton.tsx b/src/components/QuantityButton.tsx
index 6ee2bcf..95ccc98 100644
--- a/src/components/QuantityButton.tsx
+++ b/src/components/QuantityButton.tsx
@@ -65,11 +65,11 @@ const QuantityButton = ({
disabled={currentQuantity <= min || disabled}
theme={currentQuantity > min ? 'primary' : 'gray'}
hoverStyle={{
- scale: 0.75,
+ scale: 0.95,
opacity: 0.5,
}}
pressStyle={{
- scale: 0.75,
+ scale: 0.95,
opacity: 0.5,
}}
{...incrementButtonProps}
@@ -88,11 +88,11 @@ const QuantityButton = ({
disabled={currentQuantity >= max || disabled}
theme={currentQuantity < max ? 'primary' : 'gray'}
hoverStyle={{
- scale: 0.75,
+ scale: 0.95,
opacity: 0.5,
}}
pressStyle={{
- scale: 0.75,
+ scale: 0.95,
opacity: 0.5,
}}
{...decrementButtonProps}
diff --git a/src/hooks/use-current-location.ts b/src/hooks/use-current-location.ts
index 6f84ea5..f7497c9 100644
--- a/src/hooks/use-current-location.ts
+++ b/src/hooks/use-current-location.ts
@@ -78,6 +78,20 @@ const useCurrentLocation = () => {
}
};
+ // Update current location/default location as a promise
+ const updateDefaultLocationPromise = (instance) => {
+ return new Promise(async (resolve) => {
+ await updateDefaultLocation(instance);
+ resolve(instance);
+ });
+ };
+
+ // Update current location/default location as a promise
+ const updateDefaultLocation = (instance) => {
+ updateCurrentLocation(instance);
+ setCustomerDefaultLocation(instance);
+ };
+
// Set initial current location
useEffect(() => {
initializeLiveLocation();
@@ -93,6 +107,8 @@ const useCurrentLocation = () => {
liveLocation: restoreFleetbasePlace(liveLocation),
updateCurrentLocation,
setCurrentLocation,
+ updateDefaultLocationPromise,
+ updateDefaultLocation,
getCurrentLocationCoordinates,
setCustomerDefaultLocation,
initializeCurrentLocation,
diff --git a/src/hooks/use-saved-locations.ts b/src/hooks/use-saved-locations.ts
index 32aea10..b6a75f9 100644
--- a/src/hooks/use-saved-locations.ts
+++ b/src/hooks/use-saved-locations.ts
@@ -1,6 +1,6 @@
import { useState, useEffect } from 'react';
import { restoreFleetbasePlace } from '../utils/location';
-import { isResource } from '../utils';
+import { isResource, isEmpty } from '../utils';
import { useAuth } from '../contexts/AuthContext';
import useStorage from './use-storage';
import useFleetbase from './use-fleetbase';
@@ -38,11 +38,44 @@ const useSavedLocations = () => {
}
};
+ // Handle location update
+ const updateLocation = async (attributes = {}) => {
+ const place = restoreFleetbasePlace(attributes);
+
+ try {
+ const updatedPlace = await place.save();
+ setCustomerLocations((prevLocations) => prevLocations.map((location) => (location.id === place.id ? place.serialize() : location)));
+ return updatedPlace;
+ } catch (err) {
+ setError(err);
+ }
+ };
+
+ // Handle delete location by ID
+ const deleteLocationById = async (placeId) => {
+ try {
+ const place = restoreFleetbasePlace({ id: placeId });
+ const deletedPlace = await place.destroy();
+ setCustomerLocations((prevLocations) => prevLocations.filter((location) => location.id !== deletedPlace.id));
+ } catch (err) {
+ setError(err);
+ }
+ };
+
+ // Handle delete location
+ const deleteLocation = async (place) => {
+ try {
+ const deletedPlace = await place.destroy();
+ setCustomerLocations((prevLocations) => prevLocations.filter((location) => location.id !== deletedPlace.id));
+ } catch (err) {
+ setError(err);
+ }
+ };
+
// Add location
const addLocation = async (attributes = {}) => {
- console.log('[addLocation isAuthenticated]', isAuthenticated);
if (isAuthenticated) {
- return addCustomerLocation(attributes);
+ return isEmpty(attributes.id) ? addCustomerLocation(attributes) : updateLocation(attributes);
}
return addLocalLocationPromise(attributes);
@@ -86,6 +119,9 @@ const useSavedLocations = () => {
addCustomerLocation,
addLocalLocation,
addLocalLocationPromise,
+ updateLocation,
+ deleteLocation,
+ deleteLocationById,
isLoadingSavedLocations: loading,
savedLocationsError: error,
};
diff --git a/src/navigation/stacks/LocationStack.tsx b/src/navigation/stacks/LocationStack.tsx
index c0c2761..cdbbc69 100644
--- a/src/navigation/stacks/LocationStack.tsx
+++ b/src/navigation/stacks/LocationStack.tsx
@@ -5,6 +5,8 @@ import AddNewLocationScreen from '../../screens/AddNewLocationScreen';
import EditLocationScreen from '../../screens/EditLocationScreen';
import AddressBookScreen from '../../screens/AddressBookScreen';
import BackButton from '../../components/BackButton';
+import HeaderButton from '../../components/HeaderButton';
+import { faPlus } from '@fortawesome/free-solid-svg-icons';
import { getTheme } from '../../utils';
export const LocationPermission = {
@@ -28,6 +30,7 @@ export const AddressBook = {
title: 'Address Book',
headerTransparent: true,
headerLeft: () => navigation.goBack()} size={40} />,
+ headerRight: () => navigation.navigate('AddNewLocation', { redirectTo: 'AddressBook' })} size={40} />,
headerBlurEffect: 'light',
};
},
diff --git a/src/screens/AddNewLocationScreen.tsx b/src/screens/AddNewLocationScreen.tsx
index 8cb47b8..43c8700 100644
--- a/src/screens/AddNewLocationScreen.tsx
+++ b/src/screens/AddNewLocationScreen.tsx
@@ -10,9 +10,10 @@ import useStorage from '../hooks/use-storage';
import useCurrentLocation from '../hooks/use-current-location';
import BackButton from '../components/BackButton';
-const AddNewLocationScreen = () => {
+const AddNewLocationScreen = ({ route = { params: {} } }) => {
const navigation = useNavigation();
const theme = useTheme();
+ const { params } = route;
const { liveLocation: currentLocation, getCurrentLocationCoordinates } = useCurrentLocation();
const [inputFocused, setInputFocused] = useState(false);
const [inputValue, setInputValue] = useState('');
@@ -32,7 +33,7 @@ const AddNewLocationScreen = () => {
try {
const details = await getPlaceDetails(location.place_id);
const place = createFleetbasePlaceFromDetails(details);
- navigation.navigate('EditLocation', { place: place.serialize() });
+ navigation.navigate('EditLocation', { place: place.serialize(), redirectTo: params.redirectTo });
} catch (error) {
toast.error(error.message);
}
@@ -40,12 +41,17 @@ const AddNewLocationScreen = () => {
const handleUseCurrentLocation = async () => {
try {
- navigation.navigate('EditLocation', { place: currentLocation.serialize() });
+ navigation.navigate('EditLocation', { place: currentLocation.serialize(), redirectTo: params.redirectTo });
} catch (error) {
toast.error(error.message);
}
};
+ const handleUseMapLocation = () => {
+ console.log('[handleUseMapLocation triggered!]');
+ navigation.navigate('LocationPicker');
+ };
+
const searchPlaces = useCallback(async () => {
if (inputValue.trim() === '') {
setSearchResults([]);
@@ -195,7 +201,7 @@ const AddNewLocationScreen = () => {
))}
- navigation.navigate('LocationPicker')}>
+
diff --git a/src/screens/AddressBookScreen.tsx b/src/screens/AddressBookScreen.tsx
index 99a3dd1..7ca1590 100644
--- a/src/screens/AddressBookScreen.tsx
+++ b/src/screens/AddressBookScreen.tsx
@@ -1,49 +1,129 @@
-import React, { useEffect, useState } from 'react';
+import React, { useEffect, useState, useRef } from 'react';
import { useNavigation } from '@react-navigation/native';
-import { SafeAreaView, FlatList, Pressable } from 'react-native';
-import { Avatar, Text, YStack, XStack, Separator, useTheme } from 'tamagui';
+import { Animated, SafeAreaView, TouchableOpacity, FlatList, Pressable, LayoutAnimation, UIManager, Platform } from 'react-native';
+import { Spinner, Avatar, Text, YStack, XStack, Separator, useTheme } from 'tamagui';
import { toast, ToastPosition } from '@backpackapp-io/react-native-toast';
import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome';
-import { faChevronRight } from '@fortawesome/free-solid-svg-icons';
+import { faChevronRight, faPencilAlt, faTrash, faStar } from '@fortawesome/free-solid-svg-icons';
import { formattedAddressFromPlace } from '../utils/location';
+import Swipeable from 'react-native-gesture-handler/Swipeable';
import useCurrentLocation from '../hooks/use-current-location';
import useSavedLocations from '../hooks/use-saved-locations';
+import usePromiseWithLoading from '../hooks/use-promise-with-loading';
+
+if (Platform.OS === 'android' && UIManager.setLayoutAnimationEnabledExperimental) {
+ UIManager.setLayoutAnimationEnabledExperimental(true);
+}
const AddressBookScreen = () => {
const theme = useTheme();
const navigation = useNavigation();
- const { currentLocation, setCustomerDefaultLocation } = useCurrentLocation();
- const { savedLocations } = useSavedLocations();
-
- const renderSavedLocation = ({ item }) => (
- navigation.navigate('EditLocation', { place: item.serialize() })}
- style={({ pressed }) => ({
- flexDirection: 'row',
- alignItems: 'center',
- justifyContent: 'space-between',
- })}
- >
-
-
- {item.getAttribute('name')}
-
- {formattedAddressFromPlace(item)}
-
-
+ const { runWithLoading, isLoading } = usePromiseWithLoading();
+ const { currentLocation, updateDefaultLocationPromise } = useCurrentLocation();
+ const { savedLocations, deleteLocation } = useSavedLocations();
+ const rowRefs = useRef({});
+
+ const handleEdit = (place) => {
+ navigation.navigate('EditLocation', { place: place.serialize(), redirectTo: 'AddressBook' });
+ };
+
+ const handleDelete = async (place) => {
+ // In case deleting place is current location get the next place and make it the default location using `handleMakeDefaultLocation`
+ const isCurrentLocation = currentLocation?.id === place.id;
+ const nextPlace = savedLocations.find((loc) => loc.id !== place.id);
+ const placeName = place.getAttribute('name');
+
+ try {
+ await runWithLoading(deleteLocation(place), 'deleting');
+
+ // If the deleted place was the current location and there’s another saved location, make it the default
+ if (isCurrentLocation && nextPlace) {
+ handleMakeDefaultLocation(nextPlace);
+ }
+
+ toast.success(`${placeName} was deleted.`);
+ } catch (error) {
+ console.error('Error deleting saved place: ', error);
+ toast.error(error.message);
+ }
+ };
+
+ const handleMakeDefaultLocation = async (place) => {
+ try {
+ await runWithLoading(updateDefaultLocationPromise(place), 'defaulting');
+ toast.success(`${place.getAttribute('name')} is now your default location.`);
+ } catch (error) {
+ console.log('Error making address default location:', error);
+ toast.error(error.message);
+ }
+ };
+
+ const renderRightActions = (place) => (
+
+ handleDelete(place)}>
+
+ {isLoading('deleting') ? : }
+
+
+ handleEdit(place)}>
+
+
+
+
+ handleMakeDefaultLocation(place)}
+ opacity={currentLocation.id === place.id ? 0.5 : 1}
+ disabled={currentLocation.id === place.id}
+ >
+
+ {isLoading('defaulting') ? : }
+
+
+
);
+ const renderItem = ({ item: place, index }) => {
+ const opacity = new Animated.Value(1);
+ const translateX = new Animated.Value(0);
+ rowRefs.current[place.id || index] = { opacity, translateX };
+
+ return (
+
+ renderRightActions(place)}>
+ handleEdit(place)} style={{ flex: 1 }}>
+
+
+ {place.getAttribute('name')}
+
+ {formattedAddressFromPlace(place)}
+
+
+
+
+ );
+ };
+
return (
-
-
- item.id || index}
- renderItem={renderSavedLocation}
- ItemSeparatorComponent={() => }
- />
-
+
+ item.id || index}
+ contentContainerStyle={{ paddingBottom: 16 }}
+ ItemSeparatorComponent={() => }
+ />
);
diff --git a/src/screens/BootScreen.tsx b/src/screens/BootScreen.tsx
index ac3850d..62799d6 100644
--- a/src/screens/BootScreen.tsx
+++ b/src/screens/BootScreen.tsx
@@ -15,6 +15,8 @@ const BootScreen = () => {
const [info, setInfo] = useStorage('info', {});
const navigation = useNavigation();
+ console.log('[BootScreen]');
+
useEffect(() => {
const checkLocationPermission = async () => {
const permission = Platform.OS === 'ios' ? PERMISSIONS.IOS.LOCATION_WHEN_IN_USE : PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION;
diff --git a/src/screens/CartScreen.tsx b/src/screens/CartScreen.tsx
index c374b34..d069dd5 100644
--- a/src/screens/CartScreen.tsx
+++ b/src/screens/CartScreen.tsx
@@ -1,5 +1,4 @@
import React, { useRef, useState, useEffect } from 'react';
-import Swipeable from 'react-native-gesture-handler/Swipeable';
import { useNavigation } from '@react-navigation/native';
import { Animated, SafeAreaView, TouchableOpacity, StyleSheet, LayoutAnimation, UIManager, Platform } from 'react-native';
import { Spinner, View, Image, Text, YStack, XStack, Button, useTheme } from 'tamagui';
@@ -9,6 +8,7 @@ import { toast, ToastPosition } from '@backpackapp-io/react-native-toast';
import { formatCurrency } from '../utils/format';
import { delay, loadPersistedResource } from '../utils';
import { calculateCartTotal } from '../utils/cart';
+import Swipeable from 'react-native-gesture-handler/Swipeable';
import useCart from '../hooks/use-cart';
import usePromiseWithLoading from '../hooks/use-promise-with-loading';
@@ -20,9 +20,9 @@ const CartScreen = () => {
const theme = useTheme();
const navigation = useNavigation();
const { runWithLoading, isLoading, isAnyLoading } = usePromiseWithLoading();
- const rowRefs = useRef({});
const [cart, updateCart] = useCart();
const [displayedItems, setDisplayedItems] = useState(cart ? cart.contents() : []);
+ const rowRefs = useRef({});
// Make sure cart items is latest
useEffect(() => {
diff --git a/src/screens/EditLocationScreen.tsx b/src/screens/EditLocationScreen.tsx
index f5cd21a..97c9d08 100644
--- a/src/screens/EditLocationScreen.tsx
+++ b/src/screens/EditLocationScreen.tsx
@@ -1,19 +1,21 @@
-import React, { useEffect, useState } from 'react';
+import React, { useEffect, useState, useMemo } from 'react';
import { useNavigation } from '@react-navigation/native';
import { SafeAreaView, ScrollView } from 'react-native';
import { Spinner, Text, YStack, XStack, Button, Input, useTheme } from 'tamagui';
import { toast, ToastPosition } from '@backpackapp-io/react-native-toast';
import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome';
-import { faBuildingUser, faHouse, faBuilding, faHotel, faHospital, faSchool, faChair } from '@fortawesome/free-solid-svg-icons';
+import { faBuildingUser, faHouse, faBuilding, faHotel, faHospital, faSchool, faChair, faAsterisk } from '@fortawesome/free-solid-svg-icons';
import { Place } from '@fleetbase/sdk';
import { adapter } from '../hooks/use-storefront';
import { useAuth } from '../contexts/AuthContext';
-import { formattedAddressFromSerializedPlace } from '../utils/location';
+import { formattedAddressFromSerializedPlace, restoreFleetbasePlace } from '../utils/location';
import { isEmpty } from '../utils';
import usePromiseWithLoading from '../hooks/use-promise-with-loading';
import useStorefront from '../hooks/use-storefront';
+import useCurrentLocation from '../hooks/use-current-location';
import useSavedLocations from '../hooks/use-saved-locations';
import ExpandableSelect from '../components/ExpandableSelect';
+import PlaceMapView from '../components/PlaceMapView';
const LocationPropertyInput = ({ value, onChange, placeholder }) => {
return (
@@ -36,22 +38,41 @@ const LocationPropertyInput = ({ value, onChange, placeholder }) => {
);
};
-const EditLocationScreen = ({ route }) => {
+const EditLocationScreen = ({ route = { params: {} } }) => {
const navigation = useNavigation();
const theme = useTheme();
+ const { params } = route;
const { customer, isAuthenticated } = useAuth();
const { storefront } = useStorefront();
- const { runWithLoading, isLoading } = usePromiseWithLoading();
- const { addLocation } = useSavedLocations();
- const [place, setPlace] = useState({ ...route.params.place });
+ const { runWithLoading, isLoading, isAnyLoading } = usePromiseWithLoading();
+ const { currentLocation, updateDefaultLocationPromise } = useCurrentLocation();
+ const { savedLocations, addLocation, deleteLocation } = useSavedLocations();
+ const [place, setPlace] = useState({ ...params.place });
const [name, setName] = useState(place.name);
const [street1, setStreet1] = useState(place.street1);
const [street2, setStreet2] = useState(place.street2);
const [neighborhood, setNeighborhood] = useState(place.neighborhood);
const [city, setCity] = useState(place.city);
const [postalCode, setPostalCode] = useState(place.postal_code);
- const [instructions, setInstructions] = useState('');
- const ready = !isEmpty(place.type) && !isEmpty(place.name) && !isEmpty(place.street1);
+ const [instructions, setInstructions] = useState(place.meta.instructions);
+ const redirectTo = route.params.redirectTo ?? 'StoreHome';
+ const isDefaultLocation = currentLocation?.id === place?.id;
+
+ const isReady = useMemo(() => {
+ if (isEmpty(place.id)) {
+ return !isEmpty(place.type) && !isEmpty(place.name) && !isEmpty(place.street1);
+ }
+
+ return (
+ name !== place.name ||
+ street1 !== place.street1 ||
+ street2 !== place.street2 ||
+ neighborhood !== place.neighborhood ||
+ city !== place.city ||
+ postalCode !== place.postal_code ||
+ instructions !== place.meta?.instructions
+ );
+ }, [place.type, name, street1, street2, neighborhood, city, postalCode, instructions]);
useEffect(() => {
setPlace({
@@ -61,20 +82,69 @@ const EditLocationScreen = ({ route }) => {
});
}, [name, street1]);
+ const handleRedirect = () => {
+ navigation.reset({
+ index: 0,
+ routes: [
+ {
+ name: redirectTo,
+ },
+ ],
+ });
+ };
+
const handleSavePlace = async () => {
- if (!ready) {
+ if (!isReady) {
return;
}
try {
- await runWithLoading(addLocation({ ...place, street1, street2, neighborhood, city, postal_code: postalCode, meta: { instructions } }));
+ await runWithLoading(addLocation({ ...place, street1, street2, neighborhood, city, postal_code: postalCode, meta: { instructions } }), 'saving');
toast.success('Address saved.');
- navigation.navigate('StoreHome');
+ handleRedirect();
} catch (error) {
+ console.log('Error saving address details:', error);
toast.error(error.message);
}
};
+ const handleMakeDefaultLocation = async () => {
+ const restoredInstance = restoreFleetbasePlace(place);
+ if (restoredInstance && restoredInstance.isSaved) {
+ try {
+ await runWithLoading(updateDefaultLocationPromise(restoredInstance), 'defaulting');
+ toast.success(`${restoredInstance.getAttribute('name')} is now your default location.`);
+ handleRedirect();
+ } catch (error) {
+ console.log('Error making address default location:', error);
+ toast.error(error.message);
+ }
+ }
+ };
+
+ const handleDelete = async () => {
+ const isCurrentLocation = currentLocation?.id === place.id;
+ const nextPlace = savedLocations.find((loc) => loc.id !== place.id);
+ const restoredInstance = restoreFleetbasePlace(place);
+
+ if (restoredInstance && restoredInstance.isSaved) {
+ try {
+ await runWithLoading(deleteLocation(restoredInstance), 'deleting');
+ toast.success(`${restoredInstance.getAttribute('name')} was deleted.`);
+
+ // If the deleted place was the current location and there’s another saved location, make it the default
+ if (isCurrentLocation && nextPlace) {
+ handleMakeDefaultLocation(nextPlace);
+ }
+
+ handleRedirect();
+ } catch (error) {
+ console.error('Error deleting saved address: ', error);
+ toast.error(error.message);
+ }
+ }
+ };
+
const handleTypeSelection = ({ type }) => {
try {
setPlace({ ...place, type });
@@ -131,15 +201,21 @@ const EditLocationScreen = ({ route }) => {
-
- Address label or name
-
+
+
+ Address label or name
+
+
+
-
- Street address or P.O. Box
-
+
+
+ Street address or P.O. Box
+
+
+
@@ -187,17 +263,91 @@ const EditLocationScreen = ({ route }) => {
Optional
-
+
+
+
+ Where exactly is the location?
+
+
+
+
+
+ {place.id && (
+
+ {!isDefaultLocation && (
+
+ )}
+
+
+ )}
+
)}
- {ready && (
-
-