This commit is contained in:
shafi54 2026-02-01 14:01:22 +05:30
parent ca8297af9b
commit 001dd62aa5
2 changed files with 75 additions and 16 deletions

View file

@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { View, Alert, ScrollView } from 'react-native';
import { View, ScrollView } from 'react-native';
import { useMutation } from '@tanstack/react-query';
import { Formik } from 'formik';
import * as Yup from 'yup';
@ -30,39 +30,44 @@ const AddressForm: React.FC<AddressFormProps> = ({ onSuccess, initialValues, isE
const [locationLoading, setLocationLoading] = useState(false);
const [locationError, setLocationError] = useState<string | null>(null);
const [isSubmitting, setIsSubmitting] = useState(false);
const [submitError, setSubmitError] = useState<string | null>(null);
const [showGoogleMapsField, setShowGoogleMapsField] = useState(!!initialValues?.googleMapsUrl);
const [currentLocation, setCurrentLocation] = useState<{ latitude: number; longitude: number } | null>(
initialValues?.latitude && initialValues?.longitude
? { latitude: initialValues.latitude, longitude: initialValues.longitude }
: null
);
const [locationSuccess, setLocationSuccess] = useState(false);
const createAddressMutation = trpc.user.address.createAddress.useMutation({
onSuccess: (data) => {
setIsSubmitting(false);
const addressId = data?.data?.id;
setTimeout(() => onSuccess(addressId), 100);
// Delay to allow modal to close animation
setTimeout(() => onSuccess(addressId), 350);
},
onError: (error: any) => {
setIsSubmitting(false);
Alert.alert('Error', error.message || 'Failed to save address');
setSubmitError(error.message || 'Failed to save address');
},
});
const updateAddressMutation = trpc.user.address.updateAddress.useMutation({
onSuccess: () => {
setIsSubmitting(false);
setTimeout(() => onSuccess(), 100);
// Delay to allow modal to close animation
setTimeout(() => onSuccess(), 350);
},
onError: (error: any) => {
setIsSubmitting(false);
Alert.alert('Error', error.message || 'Failed to update address');
setSubmitError(error.message || 'Failed to update address');
},
});
const attachCurrentLocation = async () => {
setLocationLoading(true);
setLocationError(null);
setLocationSuccess(false);
try {
const { status } = await Location.requestForegroundPermissionsAsync();
@ -78,7 +83,9 @@ const AddressForm: React.FC<AddressFormProps> = ({ onSuccess, initialValues, isE
const { latitude, longitude } = location.coords;
setCurrentLocation({ latitude, longitude });
Alert.alert('Success', 'Location attached successfully');
setLocationSuccess(true);
// Clear success message after 3 seconds
setTimeout(() => setLocationSuccess(false), 3000);
} catch (error) {
setLocationError('Unable to fetch location. Please check your GPS settings.');
} finally {
@ -98,8 +105,19 @@ const AddressForm: React.FC<AddressFormProps> = ({ onSuccess, initialValues, isE
});
return (
<ScrollView style={tw`p-4`}>
<ScrollView
style={tw`p-4`}
keyboardShouldPersistTaps="handled"
keyboardDismissMode="on-drag"
>
<MyText style={tw`text-xl font-bold mb-4`}>{isEdit ? 'Edit Address' : 'Add Address'}</MyText>
{/* Submit Error Message */}
{submitError && (
<View style={tw`bg-red-50 border border-red-200 rounded-lg p-3 mb-4`}>
<MyText style={tw`text-red-600 text-sm`}>{submitError}</MyText>
</View>
)}
<Formik
initialValues={initialValues || {
name: '',
@ -117,6 +135,7 @@ const AddressForm: React.FC<AddressFormProps> = ({ onSuccess, initialValues, isE
validationSchema={validationSchema}
onSubmit={(values) => {
setIsSubmitting(true);
setSubmitError(null);
const payload = {
...values,
latitude: currentLocation?.latitude,
@ -203,9 +222,24 @@ const AddressForm: React.FC<AddressFormProps> = ({ onSuccess, initialValues, isE
<MyText style={tw`text-blue-500 text-sm mb-2`}>Fetching location...</MyText>
) : locationError ? (
<MyText style={tw`text-red-500 text-sm mb-2`}>{locationError}</MyText>
) : locationSuccess ? (
<View style={tw`flex-row items-center mb-4`}>
<View style={tw`bg-green-100 px-3 py-1 rounded-full`}>
<MyText style={tw`text-green-600 text-sm font-medium`}> Location Attached</MyText>
</View>
<MyTouchableOpacity
onPress={() => attachCurrentLocation()}
disabled={locationLoading}
style={tw`ml-4`}
>
<MyText style={tw`text-blue-500 text-sm font-medium`}>Attach Current</MyText>
</MyTouchableOpacity>
</View>
) : currentLocation ? (
<View style={tw`flex-row items-center mb-4`}>
<MyText style={tw`text-green-600 text-sm font-medium`}>Location Attached</MyText>
<View style={tw`bg-green-100 px-3 py-1 rounded-full`}>
<MyText style={tw`text-green-600 text-sm font-medium`}> Location Attached</MyText>
</View>
<MyTouchableOpacity
onPress={() => attachCurrentLocation()}
disabled={locationLoading}

View file

@ -1,5 +1,5 @@
import React, { ReactNode, useState } from 'react';
import { Modal, View, TouchableOpacity, StyleSheet, Animated, Easing, Dimensions, TextInput } from 'react-native';
import { Modal, View, TouchableOpacity, StyleSheet, Animated, Easing, Dimensions, TextInput, KeyboardAvoidingView, Platform, ScrollView } from 'react-native';
import MyText from './text';
import { MyButton } from 'common-ui';
@ -53,7 +53,20 @@ export const BottomDialog: React.FC<DialogProps> = ({ open, onClose, children, e
]}
>
<View style={styles.handle} />
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={styles.keyboardAvoidingContainer}
keyboardVerticalOffset={Platform.OS === 'ios' ? 0 : 0}
>
<ScrollView
style={styles.scrollContainer}
contentContainerStyle={styles.scrollContent}
keyboardShouldPersistTaps="handled"
showsVerticalScrollIndicator={true}
>
{children}
</ScrollView>
</KeyboardAvoidingView>
</Animated.View>
</Modal>
);
@ -71,19 +84,18 @@ const styles = StyleSheet.create({
position: 'absolute',
left: 0,
right: 0,
// top: SCREEN_HEIGHT * 0.3,
bottom: 0,
backgroundColor: '#fff',
borderTopLeftRadius: 18,
borderTopRightRadius: 18,
paddingHorizontal: 20,
// paddingTop: 16,
paddingBottom: 0,
elevation: 8,
shadowColor: '#000',
shadowOffset: { width: 0, height: -2 },
shadowOpacity: 0.2,
shadowRadius: 8,
maxHeight: SCREEN_HEIGHT * 0.85, // Limit max height so it doesn't cover entire screen
},
handle: {
width: 40,
@ -91,7 +103,20 @@ const styles = StyleSheet.create({
borderRadius: 3,
backgroundColor: '#ccc',
alignSelf: 'center',
// marginBottom: 12,
marginTop: 12,
marginBottom: 8,
},
keyboardAvoidingContainer: {
flex: 1,
width: '100%',
},
scrollContainer: {
flex: 1,
width: '100%',
},
scrollContent: {
flexGrow: 1,
paddingBottom: Platform.OS === 'ios' ? 40 : 20, // Extra padding for iOS keyboard
},
});