enh
This commit is contained in:
parent
e546c52c05
commit
83e733fdd1
10 changed files with 212 additions and 1144 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
ENV_MODE=PROD
|
ENV_MODE=PROD
|
||||||
# DATABASE_URL=postgresql://postgres:meatfarmer_master_password@57.128.212.174:7447/meatfarmer #technocracy
|
DATABASE_URL=postgresql://postgres:meatfarmer_master_password@57.128.212.174:7447/meatfarmer #technocracy
|
||||||
DATABASE_URL=postgres://postgres:meatfarmer_master_password@5.223.55.14:7447/meatfarmer #hetzner
|
# DATABASE_URL=postgres://postgres:meatfarmer_master_password@5.223.55.14:7447/meatfarmer #hetzner
|
||||||
PHONE_PE_BASE_URL=https://api-preprod.phonepe.com/
|
PHONE_PE_BASE_URL=https://api-preprod.phonepe.com/
|
||||||
PHONE_PE_CLIENT_ID=TEST-M23F2IGP34ZAR_25090
|
PHONE_PE_CLIENT_ID=TEST-M23F2IGP34ZAR_25090
|
||||||
PHONE_PE_CLIENT_VERSION=1
|
PHONE_PE_CLIENT_VERSION=1
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
0
apps/backend/demo.json
Normal file
0
apps/backend/demo.json
Normal file
|
|
@ -14,7 +14,7 @@ export const computeConstants = async (): Promise<void> => {
|
||||||
for (const constant of constants) {
|
for (const constant of constants) {
|
||||||
const redisKey = `${CONST_REDIS_PREFIX}${constant.key}`;
|
const redisKey = `${CONST_REDIS_PREFIX}${constant.key}`;
|
||||||
const value = JSON.stringify(constant.value);
|
const value = JSON.stringify(constant.value);
|
||||||
console.log({redisKey, value})
|
// console.log({redisKey, value})
|
||||||
|
|
||||||
await redisClient.set(redisKey, value);
|
await redisClient.set(redisKey, value);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { db } from '../db/db_index';
|
||||||
import { deliverySlotInfo, productSlots, productInfo, units } from '../db/schema';
|
import { deliverySlotInfo, productSlots, productInfo, units } from '../db/schema';
|
||||||
import { eq, and, gt, asc } from 'drizzle-orm';
|
import { eq, and, gt, asc } from 'drizzle-orm';
|
||||||
import { generateSignedUrlsFromS3Urls } from 'src/lib/s3-client';
|
import { generateSignedUrlsFromS3Urls } from 'src/lib/s3-client';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
// Define the structure for slot with products
|
// Define the structure for slot with products
|
||||||
interface SlotWithProducts {
|
interface SlotWithProducts {
|
||||||
|
|
@ -58,6 +59,20 @@ export async function initializeSlotStore(): Promise<void> {
|
||||||
orderBy: asc(deliverySlotInfo.deliveryTime),
|
orderBy: asc(deliverySlotInfo.deliveryTime),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const allSlots = await db.query.deliverySlotInfo.findMany({
|
||||||
|
where: and(
|
||||||
|
eq(deliverySlotInfo.isActive, true),
|
||||||
|
gt(deliverySlotInfo.deliveryTime, now), // Only future slots
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log(allSlots)
|
||||||
|
|
||||||
|
slots.forEach(slot => {
|
||||||
|
console.log({id: slot.id, delivery: dayjs(slot.deliveryTime).format('MM-DD-YY hh:mm:ss a')})
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
// Transform data for storage
|
// Transform data for storage
|
||||||
const slotsWithProducts = await Promise.all(
|
const slotsWithProducts = await Promise.all(
|
||||||
slots.map(async (slot) => ({
|
slots.map(async (slot) => ({
|
||||||
|
|
|
||||||
|
|
@ -238,7 +238,7 @@ export const slotsRouter = router({
|
||||||
throw new ApiError("Delivery time and orders close time are required", 400);
|
throw new ApiError("Delivery time and orders close time are required", 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
return await db.transaction(async (tx) => {
|
const result = await db.transaction(async (tx) => {
|
||||||
// Create slot
|
// Create slot
|
||||||
const [newSlot] = await tx
|
const [newSlot] = await tx
|
||||||
.insert(deliverySlotInfo)
|
.insert(deliverySlotInfo)
|
||||||
|
|
@ -290,15 +290,17 @@ export const slotsRouter = router({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reinitialize stores to reflect changes
|
|
||||||
await initializeAllStores();
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
slot: newSlot,
|
slot: newSlot,
|
||||||
createdSnippets,
|
createdSnippets,
|
||||||
message: "Slot created successfully",
|
message: "Slot created successfully",
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Reinitialize stores to reflect changes (outside transaction)
|
||||||
|
await initializeAllStores();
|
||||||
|
|
||||||
|
return result;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
getSlots: protectedProcedure.query(async ({ ctx }) => {
|
getSlots: protectedProcedure.query(async ({ ctx }) => {
|
||||||
|
|
@ -384,7 +386,7 @@ export const slotsRouter = router({
|
||||||
validGroupIds = existingGroups.map(g => g.id);
|
validGroupIds = existingGroups.map(g => g.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return await db.transaction(async (tx) => {
|
const result = await db.transaction(async (tx) => {
|
||||||
const [updatedSlot] = await tx
|
const [updatedSlot] = await tx
|
||||||
.update(deliverySlotInfo)
|
.update(deliverySlotInfo)
|
||||||
.set({
|
.set({
|
||||||
|
|
@ -447,15 +449,17 @@ export const slotsRouter = router({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reinitialize stores to reflect changes
|
|
||||||
await initializeAllStores();
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
slot: updatedSlot,
|
slot: updatedSlot,
|
||||||
createdSnippets,
|
createdSnippets,
|
||||||
message: "Slot updated successfully",
|
message: "Slot updated successfully",
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Reinitialize stores to reflect changes (outside transaction)
|
||||||
|
await initializeAllStores();
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
catch(e) {
|
catch(e) {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
|
|
|
||||||
|
|
@ -179,7 +179,7 @@ export const storeRouter = router({
|
||||||
.mutation(async ({ input, ctx }) => {
|
.mutation(async ({ input, ctx }) => {
|
||||||
const { storeId } = input;
|
const { storeId } = input;
|
||||||
|
|
||||||
return await db.transaction(async (tx) => {
|
const result = await db.transaction(async (tx) => {
|
||||||
// First, update all products of this store to set storeId to null
|
// First, update all products of this store to set storeId to null
|
||||||
await tx
|
await tx
|
||||||
.update(productInfo)
|
.update(productInfo)
|
||||||
|
|
@ -196,12 +196,14 @@ export const storeRouter = router({
|
||||||
throw new ApiError("Store not found", 404);
|
throw new ApiError("Store not found", 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reinitialize stores to reflect changes
|
|
||||||
await initializeAllStores();
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
message: "Store deleted successfully",
|
message: "Store deleted successfully",
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Reinitialize stores to reflect changes (outside transaction)
|
||||||
|
await initializeAllStores();
|
||||||
|
|
||||||
|
return result;
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
@ -3,9 +3,9 @@ import { View, ScrollView } from 'react-native';
|
||||||
import { useMutation } from '@tanstack/react-query';
|
import { useMutation } from '@tanstack/react-query';
|
||||||
import { Formik } from 'formik';
|
import { Formik } from 'formik';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import * as Location from 'expo-location';
|
|
||||||
import { tw, MyText, MyTouchableOpacity , Checkbox , MyTextInput , LoadingDialog } from 'common-ui';
|
import { tw, MyText, MyTouchableOpacity , Checkbox , MyTextInput , LoadingDialog } from 'common-ui';
|
||||||
import { trpc } from '../trpc-client';
|
import { trpc } from '../trpc-client';
|
||||||
|
import LocationAttacher from './LocationAttacher';
|
||||||
|
|
||||||
interface AddressFormProps {
|
interface AddressFormProps {
|
||||||
onSuccess: (addressId?: number) => void;
|
onSuccess: (addressId?: number) => void;
|
||||||
|
|
@ -27,8 +27,6 @@ interface AddressFormProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
const AddressForm: React.FC<AddressFormProps> = ({ onSuccess, initialValues, isEdit = false }) => {
|
const AddressForm: React.FC<AddressFormProps> = ({ onSuccess, initialValues, isEdit = false }) => {
|
||||||
const [locationLoading, setLocationLoading] = useState(false);
|
|
||||||
const [locationError, setLocationError] = useState<string | null>(null);
|
|
||||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||||
const [submitError, setSubmitError] = useState<string | null>(null);
|
const [submitError, setSubmitError] = useState<string | null>(null);
|
||||||
const [showGoogleMapsField, setShowGoogleMapsField] = useState(!!initialValues?.googleMapsUrl);
|
const [showGoogleMapsField, setShowGoogleMapsField] = useState(!!initialValues?.googleMapsUrl);
|
||||||
|
|
@ -37,7 +35,6 @@ const AddressForm: React.FC<AddressFormProps> = ({ onSuccess, initialValues, isE
|
||||||
? { latitude: initialValues.latitude, longitude: initialValues.longitude }
|
? { latitude: initialValues.latitude, longitude: initialValues.longitude }
|
||||||
: null
|
: null
|
||||||
);
|
);
|
||||||
const [locationSuccess, setLocationSuccess] = useState(false);
|
|
||||||
|
|
||||||
const createAddressMutation = trpc.user.address.createAddress.useMutation({
|
const createAddressMutation = trpc.user.address.createAddress.useMutation({
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
|
|
@ -64,35 +61,6 @@ const AddressForm: React.FC<AddressFormProps> = ({ onSuccess, initialValues, isE
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const attachCurrentLocation = async () => {
|
|
||||||
setLocationLoading(true);
|
|
||||||
setLocationError(null);
|
|
||||||
setLocationSuccess(false);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { status } = await Location.requestForegroundPermissionsAsync();
|
|
||||||
|
|
||||||
if (status !== 'granted') {
|
|
||||||
setLocationError('Location Permission denied');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const location = await Location.getCurrentPositionAsync({
|
|
||||||
accuracy: Location.Accuracy.High,
|
|
||||||
});
|
|
||||||
|
|
||||||
const { latitude, longitude } = location.coords;
|
|
||||||
setCurrentLocation({ latitude, longitude });
|
|
||||||
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 {
|
|
||||||
setLocationLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const validationSchema = Yup.object({
|
const validationSchema = Yup.object({
|
||||||
name: Yup.string().required('Name is required'),
|
name: Yup.string().required('Name is required'),
|
||||||
phone: Yup.string().required('Phone is required').matches(/^\d{10}$/, 'Phone must be 10 digits'),
|
phone: Yup.string().required('Phone is required').matches(/^\d{10}$/, 'Phone must be 10 digits'),
|
||||||
|
|
@ -228,48 +196,16 @@ const AddressForm: React.FC<AddressFormProps> = ({ onSuccess, initialValues, isE
|
||||||
/>
|
/>
|
||||||
{touched.pincode && errors.pincode && <MyText style={tw`text-red-500 mb-2`}>{errors.pincode}</MyText>}
|
{touched.pincode && errors.pincode && <MyText style={tw`text-red-500 mb-2`}>{errors.pincode}</MyText>}
|
||||||
|
|
||||||
{locationLoading ? (
|
<LocationAttacher
|
||||||
<MyText style={tw`text-blue-500 text-sm mb-2`}>Fetching location...</MyText>
|
initialLocation={currentLocation || undefined}
|
||||||
) : locationError ? (
|
initialGoogleMapsUrl={values.googleMapsUrl}
|
||||||
<MyText style={tw`text-red-500 text-sm mb-2`}>{locationError}</MyText>
|
googleMapsUrl={values.googleMapsUrl}
|
||||||
) : locationSuccess ? (
|
onGoogleMapsUrlChange={(url) => setFieldValue('googleMapsUrl', url)}
|
||||||
<View style={tw`flex-row items-center mb-4`}>
|
onLocationChange={(location) => setCurrentLocation(location)}
|
||||||
<View style={tw`bg-green-100 px-3 py-1 rounded-full`}>
|
disabled={false}
|
||||||
<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`}>
|
|
||||||
<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>
|
|
||||||
) : (
|
|
||||||
<MyTouchableOpacity
|
|
||||||
onPress={() => attachCurrentLocation()}
|
|
||||||
disabled={locationLoading}
|
|
||||||
style={tw`mb-4`}
|
|
||||||
>
|
|
||||||
<MyText style={tw`text-blue-500 text-sm font-medium`}>
|
|
||||||
Attach Current Location
|
|
||||||
</MyText>
|
|
||||||
</MyTouchableOpacity>
|
|
||||||
)}
|
|
||||||
|
|
||||||
|
{!showGoogleMapsField && (
|
||||||
<MyTouchableOpacity
|
<MyTouchableOpacity
|
||||||
onPress={() => setShowGoogleMapsField(true)}
|
onPress={() => setShowGoogleMapsField(true)}
|
||||||
disabled={false}
|
disabled={false}
|
||||||
|
|
@ -279,6 +215,7 @@ const AddressForm: React.FC<AddressFormProps> = ({ onSuccess, initialValues, isE
|
||||||
Attach with Google Maps
|
Attach with Google Maps
|
||||||
</MyText>
|
</MyText>
|
||||||
</MyTouchableOpacity>
|
</MyTouchableOpacity>
|
||||||
|
)}
|
||||||
|
|
||||||
{showGoogleMapsField && (
|
{showGoogleMapsField && (
|
||||||
<View style={tw`mb-2`}>
|
<View style={tw`mb-2`}>
|
||||||
|
|
|
||||||
158
apps/user-ui/src/components/LocationAttacher.tsx
Normal file
158
apps/user-ui/src/components/LocationAttacher.tsx
Normal file
|
|
@ -0,0 +1,158 @@
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { View } from 'react-native';
|
||||||
|
import * as Location from 'expo-location';
|
||||||
|
import { tw, MyText, MyTouchableOpacity } from 'common-ui';
|
||||||
|
|
||||||
|
interface LocationAttacherProps {
|
||||||
|
onLocationChange?: (location: { latitude: number; longitude: number } | null) => void;
|
||||||
|
initialLocation?: { latitude: number; longitude: number };
|
||||||
|
initialGoogleMapsUrl?: string;
|
||||||
|
showGoogleMapsOption?: boolean;
|
||||||
|
googleMapsUrl?: string;
|
||||||
|
onGoogleMapsUrlChange?: (url: string) => void;
|
||||||
|
disabled?: boolean;
|
||||||
|
containerStyle?: any;
|
||||||
|
attachButtonText?: string;
|
||||||
|
googleMapsButtonText?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LocationAttacher: React.FC<LocationAttacherProps> = ({
|
||||||
|
onLocationChange,
|
||||||
|
initialLocation,
|
||||||
|
initialGoogleMapsUrl = '',
|
||||||
|
showGoogleMapsOption = true,
|
||||||
|
googleMapsUrl: controlledGoogleMapsUrl,
|
||||||
|
onGoogleMapsUrlChange,
|
||||||
|
disabled = false,
|
||||||
|
containerStyle,
|
||||||
|
attachButtonText = 'Attach Current Location',
|
||||||
|
googleMapsButtonText = 'Attach with Google Maps',
|
||||||
|
}) => {
|
||||||
|
const [locationLoading, setLocationLoading] = useState(false);
|
||||||
|
const [locationError, setLocationError] = useState<string | null>(null);
|
||||||
|
const [locationSuccess, setLocationSuccess] = useState(false);
|
||||||
|
const [currentLocation, setCurrentLocation] = useState<{ latitude: number; longitude: number } | null>(
|
||||||
|
initialLocation || null
|
||||||
|
);
|
||||||
|
const [showGoogleMapsField, setShowGoogleMapsField] = useState(!!initialGoogleMapsUrl);
|
||||||
|
const [internalGoogleMapsUrl, setInternalGoogleMapsUrl] = useState(initialGoogleMapsUrl);
|
||||||
|
|
||||||
|
// Use controlled or uncontrolled Google Maps URL
|
||||||
|
const googleMapsUrl = controlledGoogleMapsUrl !== undefined ? controlledGoogleMapsUrl : internalGoogleMapsUrl;
|
||||||
|
|
||||||
|
const handleGoogleMapsUrlChange = (url: string) => {
|
||||||
|
if (onGoogleMapsUrlChange) {
|
||||||
|
onGoogleMapsUrlChange(url);
|
||||||
|
} else {
|
||||||
|
setInternalGoogleMapsUrl(url);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const attachCurrentLocation = async () => {
|
||||||
|
if (disabled) return;
|
||||||
|
|
||||||
|
setLocationLoading(true);
|
||||||
|
setLocationError(null);
|
||||||
|
setLocationSuccess(false);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { status } = await Location.requestForegroundPermissionsAsync();
|
||||||
|
|
||||||
|
if (status !== 'granted') {
|
||||||
|
setLocationError('Location Permission denied');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const location = await Location.getCurrentPositionAsync({
|
||||||
|
accuracy: Location.Accuracy.High,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { latitude, longitude } = location.coords;
|
||||||
|
const newLocation = { latitude, longitude };
|
||||||
|
setCurrentLocation(newLocation);
|
||||||
|
setLocationSuccess(true);
|
||||||
|
onLocationChange?.(newLocation);
|
||||||
|
// Clear success message after 3 seconds
|
||||||
|
setTimeout(() => setLocationSuccess(false), 3000);
|
||||||
|
} catch (error) {
|
||||||
|
setLocationError('Unable to fetch location. Please check your GPS settings.');
|
||||||
|
} finally {
|
||||||
|
setLocationLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={containerStyle}>
|
||||||
|
{/* Location Status */}
|
||||||
|
{locationLoading ? (
|
||||||
|
<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 || disabled}
|
||||||
|
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`}>
|
||||||
|
<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 || disabled}
|
||||||
|
style={tw`ml-4`}
|
||||||
|
>
|
||||||
|
<MyText style={tw`text-blue-500 text-sm font-medium`}>Attach Current</MyText>
|
||||||
|
</MyTouchableOpacity>
|
||||||
|
</View>
|
||||||
|
) : (
|
||||||
|
<MyTouchableOpacity
|
||||||
|
onPress={() => attachCurrentLocation()}
|
||||||
|
disabled={locationLoading || disabled}
|
||||||
|
style={tw`mb-4`}
|
||||||
|
>
|
||||||
|
<MyText style={tw`text-blue-500 text-sm font-medium`}>
|
||||||
|
{attachButtonText}
|
||||||
|
</MyText>
|
||||||
|
</MyTouchableOpacity>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Google Maps Option - Only show button if not in controlled mode */}
|
||||||
|
{showGoogleMapsOption && onGoogleMapsUrlChange === undefined && (
|
||||||
|
<>
|
||||||
|
<MyTouchableOpacity
|
||||||
|
onPress={() => setShowGoogleMapsField(true)}
|
||||||
|
disabled={disabled}
|
||||||
|
style={tw`mb-1`}
|
||||||
|
>
|
||||||
|
<MyText style={tw`text-blue-500 text-sm font-medium`}>
|
||||||
|
{googleMapsButtonText}
|
||||||
|
</MyText>
|
||||||
|
</MyTouchableOpacity>
|
||||||
|
|
||||||
|
{showGoogleMapsField && (
|
||||||
|
<View style={tw`mb-2`}>
|
||||||
|
<MyText style={tw`text-gray-500 text-xs mb-2`}>
|
||||||
|
1. Open Google Maps and Find location{'\n'}
|
||||||
|
2. Long press the desired location{'\n'}
|
||||||
|
3. Click on Share and Click on Copy{'\n'}
|
||||||
|
4. Paste the copied url here in the field.
|
||||||
|
</MyText>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LocationAttacher;
|
||||||
1052
package-lock.json
generated
1052
package-lock.json
generated
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue