enh
This commit is contained in:
parent
83e733fdd1
commit
da47a0a014
10 changed files with 96 additions and 31 deletions
8
.expo/README.md
Normal file
8
.expo/README.md
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
> Why do I have a folder named ".expo" in my project?
|
||||
The ".expo" folder is created when an Expo project is started using "expo start" command.
|
||||
> What do the files contain?
|
||||
- "devices.json": contains information about devices that have recently opened this project. This is used to populate the "Development sessions" list in your development builds.
|
||||
- "settings.json": contains the server configuration that is used to serve the application manifest.
|
||||
> Should I commit the ".expo" folder?
|
||||
No, you should not share the ".expo" folder. It does not contain any information that is relevant for other developers working on the project, it is specific to your machine.
|
||||
Upon project creation, the ".expo" folder is already added to your ".gitignore" file.
|
||||
3
.expo/devices.json
Normal file
3
.expo/devices.json
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"devices": []
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useState } from 'react';
|
||||
import { View, Alert } from 'react-native';
|
||||
import { useRouter } from 'expo-router';
|
||||
import { AppContainer, MyText, tw, useMarkDataFetchers, MyFlatList, MyTouchableOpacity, BottomDialog } from 'common-ui';
|
||||
import { AppContainer, MyText, tw, useMarkDataFetchers, MyFlatList, MyTouchableOpacity, BottomDialog, RawBottomDialog } from 'common-ui';
|
||||
import { trpc } from '@/src/trpc-client';
|
||||
import MaterialIcons from '@expo/vector-icons/MaterialIcons';
|
||||
import AddressForm from '@/src/components/AddressForm';
|
||||
|
|
@ -242,20 +242,7 @@ export default function Addresses() {
|
|||
showsVerticalScrollIndicator={false}
|
||||
/>
|
||||
|
||||
<BottomDialog open={modalVisible} onClose={() => setModalVisible(false)}>
|
||||
<View style={tw`pt-4`}>
|
||||
<View style={tw`flex-row justify-between items-center pb-4 border-b border-gray-100`}>
|
||||
<MyText weight="semibold" style={tw`text-lg text-gray-800`}>
|
||||
{editingAddress ? 'Edit Address' : 'Add Address'}
|
||||
</MyText>
|
||||
<MyTouchableOpacity
|
||||
onPress={() => setModalVisible(false)}
|
||||
style={tw`p-1`}
|
||||
>
|
||||
<MaterialIcons name="close" size={24} color="#6B7280" />
|
||||
</MyTouchableOpacity>
|
||||
</View>
|
||||
<View style={tw`pt-4`}>
|
||||
<RawBottomDialog open={modalVisible} onClose={() => setModalVisible(false)}>
|
||||
<AddressForm
|
||||
onSuccess={handleAddressSubmit}
|
||||
initialValues={editingAddress ? {
|
||||
|
|
@ -274,9 +261,7 @@ export default function Addresses() {
|
|||
} : undefined}
|
||||
isEdit={!!editingAddress}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</BottomDialog>
|
||||
</RawBottomDialog>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { View, Text, TouchableOpacity, ScrollView } from 'react-native';
|
||||
import { tw, BottomDialog } from 'common-ui';
|
||||
import { tw, BottomDialog, RawBottomDialog } from 'common-ui';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import AddressForm from '@/src/components/AddressForm';
|
||||
import MaterialIcons from '@expo/vector-icons/MaterialIcons';
|
||||
|
|
@ -128,7 +128,9 @@ const CheckoutAddressSelector: React.FC<AddressSelectorProps> = ({
|
|||
)}
|
||||
</View>
|
||||
|
||||
<BottomDialog open={showAddAddress} onClose={() => setShowAddAddress(false)}>
|
||||
{/* <BottomDialog open={showAddAddress} onClose={() => setShowAddAddress(false)}> */}
|
||||
<RawBottomDialog open={showAddAddress} onClose={() => setShowAddAddress(false)}>
|
||||
|
||||
<AddressForm
|
||||
onSuccess={(addressId) => {
|
||||
setShowAddAddress(false);
|
||||
|
|
@ -139,7 +141,8 @@ const CheckoutAddressSelector: React.FC<AddressSelectorProps> = ({
|
|||
queryClient.invalidateQueries();
|
||||
}}
|
||||
/>
|
||||
</BottomDialog>
|
||||
</RawBottomDialog>
|
||||
{/* </BottomDialog> */}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -370,6 +370,14 @@ const PaymentAndOrderComponent: React.FC<PaymentAndOrderProps> = ({
|
|||
|
||||
{/* Bottom Action Bar */}
|
||||
<View style={tw`bg-white p-5 rounded-2xl shadow-sm mb-4 border border-gray-100`}>
|
||||
{!selectedAddress && (
|
||||
<View style={tw`bg-red-50 p-3 rounded-lg mb-3 flex-row items-center`}>
|
||||
<MaterialIcons name="error-outline" size={16} color="#EF4444" style={tw`mr-2`} />
|
||||
<MyText style={tw`text-red-600 text-sm font-medium`}>
|
||||
Please select a delivery address to place order
|
||||
</MyText>
|
||||
</View>
|
||||
)}
|
||||
<MyTouchableOpacity
|
||||
style={tw`bg-brand500 py-4 rounded-xl items-center shadow-md ${!selectedAddress ? 'opacity-50' : ''}`}
|
||||
disabled={!selectedAddress}
|
||||
|
|
|
|||
|
|
@ -757,7 +757,7 @@ export default function CartPage({ isFlashDelivery = false }: CartPageProps) {
|
|||
label="Available Coupons"
|
||||
options={dropdownData}
|
||||
value={selectedCouponId || ""}
|
||||
disabled={eligibleCoupons.length === 0}
|
||||
// disabled={eligibleCoupons.length === 0}
|
||||
onValueChange={(value) => {
|
||||
setSelectedCouponId(value ? Number(value) : null);
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useState, useMemo } from 'react';
|
||||
import { View, ScrollView } from 'react-native';
|
||||
import { useLocalSearchParams, useRouter } from 'expo-router';
|
||||
import { tw, useMarkDataFetchers , BottomDialog, MyText, MyTouchableOpacity } from 'common-ui';
|
||||
import { tw, useMarkDataFetchers , BottomDialog, MyText, MyTouchableOpacity, RawBottomDialog } from 'common-ui';
|
||||
import MaterialIcons from '@expo/vector-icons/MaterialIcons';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import AddressForm from '@/src/components/AddressForm';
|
||||
|
|
@ -256,7 +256,7 @@ const CheckoutPage: React.FC<CheckoutPageProps> = ({ isFlashDelivery = false })
|
|||
|
||||
|
||||
|
||||
<BottomDialog open={showAddAddress} onClose={() => setShowAddAddress(false)}>
|
||||
<RawBottomDialog open={showAddAddress} onClose={() => setShowAddAddress(false)}>
|
||||
<AddressForm
|
||||
onSuccess={(addressId) => {
|
||||
setShowAddAddress(false);
|
||||
|
|
@ -267,7 +267,7 @@ const CheckoutPage: React.FC<CheckoutPageProps> = ({ isFlashDelivery = false })
|
|||
queryClient.invalidateQueries();
|
||||
}}
|
||||
/>
|
||||
</BottomDialog>
|
||||
</RawBottomDialog>
|
||||
|
||||
</View>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import React, { useState } from 'react';
|
||||
import { View, ScrollView } from 'react-native';
|
||||
import { View, ScrollView, Dimensions } from 'react-native';
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import { Formik } from 'formik';
|
||||
import * as Yup from 'yup';
|
||||
import { tw, MyText, MyTouchableOpacity , Checkbox , MyTextInput , LoadingDialog } from 'common-ui';
|
||||
import { trpc } from '../trpc-client';
|
||||
import LocationAttacher from './LocationAttacher';
|
||||
import KeyBoardAwareScrollView from 'react-native-keyboard-aware-scroll-view';
|
||||
|
||||
interface AddressFormProps {
|
||||
onSuccess: (addressId?: number) => void;
|
||||
|
|
@ -74,8 +75,8 @@ const AddressForm: React.FC<AddressFormProps> = ({ onSuccess, initialValues, isE
|
|||
|
||||
return (
|
||||
<ScrollView
|
||||
style={tw`p-4`}
|
||||
keyboardShouldPersistTaps="handled"
|
||||
style={[tw`px-4 pt-4 pb-32 bg-white`, {height: Dimensions.get('window').height * 0.5}]}
|
||||
keyboardShouldPersistTaps="always"
|
||||
keyboardDismissMode="on-drag"
|
||||
>
|
||||
<MyText style={tw`text-xl font-bold mb-4`}>{isEdit ? 'Edit Address' : 'Add Address'}</MyText>
|
||||
|
|
@ -252,6 +253,7 @@ const AddressForm: React.FC<AddressFormProps> = ({ onSuccess, initialValues, isE
|
|||
{isSubmitting ? (isEdit ? 'Updating...' : 'Adding...') : (isEdit ? 'Update Address' : 'Add Address')}
|
||||
</MyText>
|
||||
</MyTouchableOpacity>
|
||||
<View style={tw`h-8`}></View>
|
||||
</View>
|
||||
)}
|
||||
</Formik>
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import { theme } from "./src/theme";
|
|||
import MyButton, { MyTextButton } from "./src/components/button";
|
||||
import { useTheme, Theme } from "./hooks/theme-context";
|
||||
import MyTextInput from "./src/components/textinput";
|
||||
import BottomDialog, { ConfirmationDialog } from "./src/components/dialog";
|
||||
import BottomDialog, { ConfirmationDialog, RawBottomDialog } from "./src/components/dialog";
|
||||
import LoadingDialog from "./src/components/loading-dialog";
|
||||
import DatePicker from "./src/components/date-picker";
|
||||
import MyText from "./src/components/text";
|
||||
|
|
@ -91,6 +91,7 @@ export {
|
|||
MyText,
|
||||
MyTouchableOpacity,
|
||||
ConfirmationDialog,
|
||||
RawBottomDialog,
|
||||
DatePicker,
|
||||
BottomDropdown,
|
||||
ImageViewerURI,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import React, { ReactNode, useState } from 'react';
|
|||
import { Modal, View, TouchableOpacity, StyleSheet, Animated, Easing, Dimensions, TextInput, KeyboardAvoidingView, Platform, ScrollView } from 'react-native';
|
||||
import MyText from './text';
|
||||
import { MyButton } from 'common-ui';
|
||||
import tw from "../lib/tailwind";
|
||||
|
||||
interface DialogProps {
|
||||
open: boolean;
|
||||
|
|
@ -72,6 +73,60 @@ export const BottomDialog: React.FC<DialogProps> = ({ open, onClose, children, e
|
|||
);
|
||||
};
|
||||
|
||||
export const RawBottomDialog: React.FC<DialogProps> = ({ open, onClose, children, enableDismiss = true }) => {
|
||||
const [slideAnim] = useState(new Animated.Value(SCREEN_HEIGHT));
|
||||
|
||||
React.useEffect(() => {
|
||||
if (open) {
|
||||
Animated.timing(slideAnim, {
|
||||
toValue: 0,
|
||||
duration: 300,
|
||||
easing: Easing.out(Easing.cubic),
|
||||
useNativeDriver: true,
|
||||
}).start();
|
||||
} else {
|
||||
Animated.timing(slideAnim, {
|
||||
toValue: SCREEN_HEIGHT,
|
||||
duration: 200,
|
||||
useNativeDriver: true,
|
||||
}).start();
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
visible={open}
|
||||
transparent
|
||||
animationType="none"
|
||||
onRequestClose={enableDismiss ? onClose : undefined}
|
||||
>
|
||||
{enableDismiss ? (
|
||||
<TouchableOpacity style={tw`flex-1 bg-black/30`} activeOpacity={1} onPress={onClose} />
|
||||
) : (
|
||||
<View style={[tw`flex-1 bg-black/30`, { pointerEvents: 'none' }]} />
|
||||
)}
|
||||
|
||||
{children}
|
||||
{/* <Animated.View
|
||||
style={[
|
||||
tw`absolute left-0 right-0 bottom-0 bg-white rounded-t-[18px] px-5 pb-0 shadow-lg`,
|
||||
{
|
||||
maxHeight: SCREEN_HEIGHT * 0.85,
|
||||
transform: [{ translateY: slideAnim }],
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: -2 },
|
||||
shadowOpacity: 0.2,
|
||||
shadowRadius: 8,
|
||||
elevation: 8,
|
||||
},
|
||||
]}
|
||||
>
|
||||
{children}
|
||||
</Animated.View> */}
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
backdrop: {
|
||||
flex: 1,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue