feat: implement core architecture, Redux store, product interfaces, and foundational UI components for Home and Login screens
This commit is contained in:
parent
0183e2694e
commit
c7dbdd3b8a
3
.env
Normal file
3
.env
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
STRIPE_SECRET_KEY=sk_test_51Ox04DSHlFQYe8R5HXy6nj0eQqtqAP4ynF7ODFg71ork78B38MPsDV3gQEo2EYaFL9OG75L8tG7bKxptsmVeONrS00ji44eUIl
|
||||||
|
RAZORPAY_KEY_ID=rzp_test_TCxbW8AxcXgMCj
|
||||||
|
RAZORPAY_KEY_SECRET=rLlM87yFehhsVNSqjCE2qRz5
|
||||||
@ -6,3 +6,4 @@ export * from './cartApi';
|
|||||||
export * from './paymentMethodsApi';
|
export * from './paymentMethodsApi';
|
||||||
export * from './customerDetailsApi';
|
export * from './customerDetailsApi';
|
||||||
export * from './orderApi';
|
export * from './orderApi';
|
||||||
|
export * from './offerApi';
|
||||||
|
|||||||
9
app/api/offerApi.ts
Normal file
9
app/api/offerApi.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { apiClient } from '@services';
|
||||||
|
import { PromotionResponse } from '@interfaces';
|
||||||
|
|
||||||
|
export const fetchOffers = async (): Promise<PromotionResponse> => {
|
||||||
|
const response = await apiClient.get<PromotionResponse>(
|
||||||
|
'/promotions/customer/offers',
|
||||||
|
);
|
||||||
|
return response;
|
||||||
|
};
|
||||||
@ -1,4 +1,9 @@
|
|||||||
import { Products, PaginationMeta, Product } from '@interfaces';
|
import {
|
||||||
|
Products,
|
||||||
|
PaginationMeta,
|
||||||
|
Product,
|
||||||
|
CategoriesResponse,
|
||||||
|
} from '@interfaces';
|
||||||
import { apiClient } from '@services';
|
import { apiClient } from '@services';
|
||||||
|
|
||||||
export interface GetProductsResponse {
|
export interface GetProductsResponse {
|
||||||
@ -15,3 +20,7 @@ export const getProductDetailsApi = async (
|
|||||||
): Promise<Product> => {
|
): Promise<Product> => {
|
||||||
return await apiClient.get<Product>(`/products/${productId}`);
|
return await apiClient.get<Product>(`/products/${productId}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getCategoriesApi = async (): Promise<CategoriesResponse> => {
|
||||||
|
return await apiClient.get<CategoriesResponse>(`/categories/selected`);
|
||||||
|
};
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
useNavigation,
|
useNavigation,
|
||||||
CompositeNavigationProp,
|
CompositeNavigationProp,
|
||||||
|
useFocusEffect,
|
||||||
} from '@react-navigation/native';
|
} from '@react-navigation/native';
|
||||||
import { BottomTabNavigationProp } from '@react-navigation/bottom-tabs';
|
import { BottomTabNavigationProp } from '@react-navigation/bottom-tabs';
|
||||||
import { StackNavigationProp } from '@react-navigation/stack';
|
import { StackNavigationProp } from '@react-navigation/stack';
|
||||||
@ -22,8 +23,13 @@ import { useAppTheme } from '@theme';
|
|||||||
import { Product } from '../../../interfaces';
|
import { Product } from '../../../interfaces';
|
||||||
import { AppStackParamList } from '../../../navigation/appStack';
|
import { AppStackParamList } from '../../../navigation/appStack';
|
||||||
import { MainTabParamList } from '../../../navigation/mainTabNavigator';
|
import { MainTabParamList } from '../../../navigation/mainTabNavigator';
|
||||||
import { fetchCustomerDetails, useAppDispatch, useAppSelector } from '@store';
|
import {
|
||||||
import { getAllProductsThunk } from './thunk';
|
fetchCustomerDetails,
|
||||||
|
getAllOffersThunk,
|
||||||
|
useAppDispatch,
|
||||||
|
useAppSelector,
|
||||||
|
} from '@store';
|
||||||
|
import { getAllCategoriesThunk, getAllProductsThunk } from './thunk';
|
||||||
|
|
||||||
type NavProp = CompositeNavigationProp<
|
type NavProp = CompositeNavigationProp<
|
||||||
BottomTabNavigationProp<MainTabParamList, 'HomeScreen'>,
|
BottomTabNavigationProp<MainTabParamList, 'HomeScreen'>,
|
||||||
@ -76,7 +82,9 @@ export const HomeScreen: React.FC = () => {
|
|||||||
const navigation = useNavigation<NavProp>();
|
const navigation = useNavigation<NavProp>();
|
||||||
|
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const { products, isLoading } = useAppSelector(state => state.home);
|
const { products, isLoading, categories } = useAppSelector(
|
||||||
|
state => state.home,
|
||||||
|
);
|
||||||
|
|
||||||
const [selectedCategory, setSelectedCategory] = useState('all');
|
const [selectedCategory, setSelectedCategory] = useState('all');
|
||||||
const [activeBanner, setActiveBanner] = useState(0);
|
const [activeBanner, setActiveBanner] = useState(0);
|
||||||
@ -84,7 +92,13 @@ export const HomeScreen: React.FC = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(getAllProductsThunk());
|
dispatch(getAllProductsThunk());
|
||||||
dispatch(fetchCustomerDetails());
|
dispatch(fetchCustomerDetails());
|
||||||
|
dispatch(getAllCategoriesThunk());
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
dispatch(getAllOffersThunk());
|
||||||
|
}, [dispatch]),
|
||||||
|
);
|
||||||
|
|
||||||
const filteredProducts =
|
const filteredProducts =
|
||||||
selectedCategory === 'all'
|
selectedCategory === 'all'
|
||||||
|
|||||||
@ -1,17 +1,19 @@
|
|||||||
import { createReducer } from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import { Product, Products } from '@interfaces';
|
import { Categories, Product, Products } from '@interfaces';
|
||||||
import { getAllProductsThunk } from './thunk';
|
import { getAllCategoriesThunk, getAllProductsThunk } from './thunk';
|
||||||
|
|
||||||
export interface HomeState {
|
export interface HomeState {
|
||||||
products: Products[];
|
products: Products[];
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
error: string | null;
|
error: string | null;
|
||||||
|
categories: Categories[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState: HomeState = {
|
const initialState: HomeState = {
|
||||||
products: [],
|
products: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
error: null,
|
error: null,
|
||||||
|
categories: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const homeReducer = createReducer(initialState, builder => {
|
const homeReducer = createReducer(initialState, builder => {
|
||||||
@ -30,6 +32,14 @@ const homeReducer = createReducer(initialState, builder => {
|
|||||||
.addCase(getAllProductsThunk.rejected, (state, action) => {
|
.addCase(getAllProductsThunk.rejected, (state, action) => {
|
||||||
state.isLoading = false;
|
state.isLoading = false;
|
||||||
state.error = action.payload || 'Failed to fetch products';
|
state.error = action.payload || 'Failed to fetch products';
|
||||||
|
})
|
||||||
|
.addCase(getAllCategoriesThunk.fulfilled, (state, action) => {
|
||||||
|
state.categories = action.payload || [];
|
||||||
|
state.isLoading = false;
|
||||||
|
})
|
||||||
|
.addCase(getAllCategoriesThunk.rejected, (state, action) => {
|
||||||
|
state.isLoading = false;
|
||||||
|
state.error = (action.payload as string) || 'Failed to fetch categories';
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { createAsyncThunk } from '@reduxjs/toolkit';
|
import { createAsyncThunk } from '@reduxjs/toolkit';
|
||||||
import { getProductsApi, GetProductsResponse } from '@api';
|
import { getCategoriesApi, getProductsApi, GetProductsResponse } from '@api';
|
||||||
|
|
||||||
export const getAllProductsThunk = createAsyncThunk<
|
export const getAllProductsThunk = createAsyncThunk<
|
||||||
GetProductsResponse,
|
GetProductsResponse,
|
||||||
@ -15,3 +15,15 @@ export const getAllProductsThunk = createAsyncThunk<
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const getAllCategoriesThunk = createAsyncThunk(
|
||||||
|
'categories/getAll',
|
||||||
|
async (_, { rejectWithValue }) => {
|
||||||
|
try {
|
||||||
|
const response = await getCategoriesApi();
|
||||||
|
return response;
|
||||||
|
} catch (error) {
|
||||||
|
return rejectWithValue(error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|||||||
@ -3,29 +3,49 @@ import { View, Text, FlatList, TouchableOpacity } from 'react-native';
|
|||||||
import { getStyles } from './offersScreen.styles';
|
import { getStyles } from './offersScreen.styles';
|
||||||
import { Header } from '@components';
|
import { Header } from '@components';
|
||||||
import { useAppTheme } from '@theme';
|
import { useAppTheme } from '@theme';
|
||||||
|
import { useAppSelector } from '@store';
|
||||||
|
|
||||||
const OFFERS = [
|
// const OFFERS = [
|
||||||
{ id: '1', code: 'WELCOME50', description: '50% off on your first order', expiry: '30 Jul 2026' },
|
// {
|
||||||
{ id: '2', code: 'FLAT20', description: 'Flat ₹20 off on orders above ₹199', expiry: '15 Aug 2026' },
|
// id: '1',
|
||||||
{ id: '3', code: 'FREEDEL', description: 'Free delivery on orders above ₹299', expiry: '31 Jul 2026' },
|
// code: 'WELCOME50',
|
||||||
];
|
// description: '50% off on your first order',
|
||||||
|
// expiry: '30 Jul 2026',
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// id: '2',
|
||||||
|
// code: 'FLAT20',
|
||||||
|
// description: 'Flat ₹20 off on orders above ₹199',
|
||||||
|
// expiry: '15 Aug 2026',
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// id: '3',
|
||||||
|
// code: 'FREEDEL',
|
||||||
|
// description: 'Free delivery on orders above ₹299',
|
||||||
|
// expiry: '31 Jul 2026',
|
||||||
|
// },
|
||||||
|
// ];
|
||||||
|
|
||||||
export const OffersScreen: React.FC = () => {
|
export const OffersScreen: React.FC = () => {
|
||||||
const { colors } = useAppTheme();
|
const { colors } = useAppTheme();
|
||||||
const styles = getStyles(colors);
|
const styles = getStyles(colors);
|
||||||
|
const { offers } = useAppSelector(state => state.offer);
|
||||||
|
// console.log(offers);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<Header title="Offers" />
|
<Header title="Offers" />
|
||||||
<FlatList
|
<FlatList
|
||||||
data={OFFERS}
|
data={offers}
|
||||||
keyExtractor={(item) => item.id}
|
keyExtractor={item => item.id}
|
||||||
renderItem={({ item }) => (
|
renderItem={({ item }) => (
|
||||||
<View style={styles.offerCard}>
|
<View style={styles.offerCard}>
|
||||||
<View style={styles.offerInfo}>
|
<View style={styles.offerInfo}>
|
||||||
<Text style={styles.offerCode}>{item.code}</Text>
|
<Text style={styles.offerCode}>{item?.title}</Text>
|
||||||
<Text style={styles.offerDescription}>{item.description}</Text>
|
<Text style={styles.offerDescription}>{item?.description}</Text>
|
||||||
<Text style={styles.offerExpiry}>Expires: {item.expiry}</Text>
|
{/* <Text style={styles.offerExpiry}>
|
||||||
|
Expires: {new Date(item?.).toLocaleDateString()}
|
||||||
|
</Text> */}
|
||||||
</View>
|
</View>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={styles.copyButton}
|
style={styles.copyButton}
|
||||||
|
|||||||
@ -96,3 +96,4 @@ export * from './cart';
|
|||||||
export * from './paymentMethods';
|
export * from './paymentMethods';
|
||||||
export * from './customerProfile';
|
export * from './customerProfile';
|
||||||
export * from './order';
|
export * from './order';
|
||||||
|
export * from './offers';
|
||||||
|
|||||||
33
app/interfaces/offers.ts
Normal file
33
app/interfaces/offers.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
export interface PromotionResponse {
|
||||||
|
promotions: Promotion[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Promotion {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
badgeText: string;
|
||||||
|
promotionType: PromotionType;
|
||||||
|
discountValue: number;
|
||||||
|
minimumOrderAmount: number;
|
||||||
|
maximumDiscount: number | null;
|
||||||
|
merchantId: string | null;
|
||||||
|
applicableProducts: ApplicableProduct[];
|
||||||
|
applicableCategories: ApplicableCategory[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type PromotionType =
|
||||||
|
| 'PERCENTAGE_DISCOUNT'
|
||||||
|
| 'FLAT_DISCOUNT'
|
||||||
|
| 'BUY_ONE_GET_ONE'
|
||||||
|
| 'FREE_DELIVERY';
|
||||||
|
|
||||||
|
export interface ApplicableProduct {
|
||||||
|
id: string;
|
||||||
|
name?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ApplicableCategory {
|
||||||
|
id: string;
|
||||||
|
name?: string;
|
||||||
|
}
|
||||||
@ -141,3 +141,16 @@ export enum MediaType {
|
|||||||
IMAGE = 'IMAGE',
|
IMAGE = 'IMAGE',
|
||||||
VIDEO = 'VIDEO',
|
VIDEO = 'VIDEO',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//catagories
|
||||||
|
export type CategoriesResponse = Categories[];
|
||||||
|
|
||||||
|
export interface Categories {
|
||||||
|
id: string;
|
||||||
|
parentId: string | null;
|
||||||
|
name: string;
|
||||||
|
slug: string;
|
||||||
|
imageUrl: string | null;
|
||||||
|
isActive: boolean;
|
||||||
|
// children: Categories[];
|
||||||
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ const STORAGE_KEYS = {
|
|||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
// ─── Config ──────────────────────────────────────────────────────────────────
|
// ─── Config ──────────────────────────────────────────────────────────────────
|
||||||
const BASE_URL = 'https://db1d-202-8-116-13.ngrok-free.app'; // TODO: replace with your actual base URL
|
const BASE_URL = 'https://157a-202-8-116-13.ngrok-free.app'; // TODO: replace with your actual base URL
|
||||||
|
|
||||||
// ─── Token Helpers ───────────────────────────────────────────────────────────
|
// ─── Token Helpers ───────────────────────────────────────────────────────────
|
||||||
export const tokenManager = {
|
export const tokenManager = {
|
||||||
|
|||||||
2
app/store/commonreducers/offer/index.ts
Normal file
2
app/store/commonreducers/offer/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from './reducer';
|
||||||
|
export * from './thunk';
|
||||||
29
app/store/commonreducers/offer/reducer.ts
Normal file
29
app/store/commonreducers/offer/reducer.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { Promotion } from '@interfaces';
|
||||||
|
import { getAllOffersThunk } from './thunk';
|
||||||
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
|
export interface OfferState {
|
||||||
|
offers: Promotion[];
|
||||||
|
isLoading: boolean;
|
||||||
|
error: string | null;
|
||||||
|
}
|
||||||
|
const initialState: OfferState = {
|
||||||
|
offers: [],
|
||||||
|
isLoading: false,
|
||||||
|
error: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const offerReducer = createReducer(initialState, builder => {
|
||||||
|
builder
|
||||||
|
.addCase(getAllOffersThunk.fulfilled, (state, action) => {
|
||||||
|
state.offers = action.payload?.promotions;
|
||||||
|
state.isLoading = false;
|
||||||
|
})
|
||||||
|
.addCase(getAllOffersThunk.pending, state => {
|
||||||
|
state.isLoading = true;
|
||||||
|
})
|
||||||
|
.addCase(getAllOffersThunk.rejected, (state, action) => {
|
||||||
|
state.isLoading = false;
|
||||||
|
state.error = action.payload as string;
|
||||||
|
});
|
||||||
|
});
|
||||||
14
app/store/commonreducers/offer/thunk.ts
Normal file
14
app/store/commonreducers/offer/thunk.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { fetchOffers } from '@api';
|
||||||
|
import { createAsyncThunk } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
|
export const getAllOffersThunk = createAsyncThunk(
|
||||||
|
'offers/getAll',
|
||||||
|
async (_, { rejectWithValue }) => {
|
||||||
|
try {
|
||||||
|
const response = await fetchOffers();
|
||||||
|
return response;
|
||||||
|
} catch (error) {
|
||||||
|
return rejectWithValue(error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
@ -10,6 +10,7 @@ import homeReducer from '@features/screens/homeScreen/reducer';
|
|||||||
import providerDetailsReducer from '@features/screens/providerDetailsScreen/reducer';
|
import providerDetailsReducer from '@features/screens/providerDetailsScreen/reducer';
|
||||||
import paymentMethodsReducer from '@features/screens/checkoutPaymentScreen/reducer';
|
import paymentMethodsReducer from '@features/screens/checkoutPaymentScreen/reducer';
|
||||||
import customerProfileReducer from './commonreducers/customerProfile/reducer';
|
import customerProfileReducer from './commonreducers/customerProfile/reducer';
|
||||||
|
import { offerReducer } from './commonreducers/offer';
|
||||||
|
|
||||||
const rootReducer = combineReducers({
|
const rootReducer = combineReducers({
|
||||||
auth: authReducer,
|
auth: authReducer,
|
||||||
@ -22,6 +23,7 @@ const rootReducer = combineReducers({
|
|||||||
providerDetails: providerDetailsReducer,
|
providerDetails: providerDetailsReducer,
|
||||||
paymentMethods: paymentMethodsReducer,
|
paymentMethods: paymentMethodsReducer,
|
||||||
customerProfile: customerProfileReducer,
|
customerProfile: customerProfileReducer,
|
||||||
|
offer: offerReducer,
|
||||||
});
|
});
|
||||||
|
|
||||||
export type RootState = ReturnType<typeof rootReducer>;
|
export type RootState = ReturnType<typeof rootReducer>;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
export const getFullUrl = (url?: string) => {
|
export const getFullUrl = (url?: string) => {
|
||||||
const BASE_URL = 'https://db1d-202-8-116-13.ngrok-free.app';
|
const BASE_URL = 'https://157a-202-8-116-13.ngrok-free.app';
|
||||||
if (!url) return '';
|
if (!url) return '';
|
||||||
return url.startsWith('/') ? `${BASE_URL}${url}` : url;
|
return url.startsWith('/') ? `${BASE_URL}${url}` : url;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -17,12 +17,14 @@
|
|||||||
"@react-navigation/native": "^7.3.4",
|
"@react-navigation/native": "^7.3.4",
|
||||||
"@react-navigation/stack": "^7.10.6",
|
"@react-navigation/stack": "^7.10.6",
|
||||||
"@reduxjs/toolkit": "^2.12.0",
|
"@reduxjs/toolkit": "^2.12.0",
|
||||||
|
"@stripe/stripe-react-native": "^0.68.0",
|
||||||
"axios": "^1.18.1",
|
"axios": "^1.18.1",
|
||||||
"react": "19.2.3",
|
"react": "19.2.3",
|
||||||
"react-native": "0.86.0",
|
"react-native": "0.86.0",
|
||||||
"react-native-geolocation-service": "^5.3.1",
|
"react-native-geolocation-service": "^5.3.1",
|
||||||
"react-native-gesture-handler": "^2.32.0",
|
"react-native-gesture-handler": "^2.32.0",
|
||||||
"react-native-maps": "^1.29.0",
|
"react-native-maps": "^1.29.0",
|
||||||
|
"react-native-razorpay": "^3.0.0",
|
||||||
"react-native-reanimated": "^4.5.0",
|
"react-native-reanimated": "^4.5.0",
|
||||||
"react-native-safe-area-context": "^5.8.0",
|
"react-native-safe-area-context": "^5.8.0",
|
||||||
"react-native-screens": "^4.25.2",
|
"react-native-screens": "^4.25.2",
|
||||||
|
|||||||
10
yarn.lock
10
yarn.lock
@ -1847,6 +1847,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@standard-schema/utils/-/utils-0.3.0.tgz#3d5e608f16c2390c10528e98e59aef6bf73cae7b"
|
resolved "https://registry.yarnpkg.com/@standard-schema/utils/-/utils-0.3.0.tgz#3d5e608f16c2390c10528e98e59aef6bf73cae7b"
|
||||||
integrity sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==
|
integrity sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==
|
||||||
|
|
||||||
|
"@stripe/stripe-react-native@^0.68.0":
|
||||||
|
version "0.68.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@stripe/stripe-react-native/-/stripe-react-native-0.68.0.tgz#1c95930943e7538e9930dc19f75b0a5e435b94cc"
|
||||||
|
integrity sha512-5Sv0bUX9ABxttRL2qWGfxzaq5mVLNFJ3XTOmyWw0IpgrL1vXqVHzx8d6qWX8iHbosu1985x8BxbquIns+P6g3w==
|
||||||
|
|
||||||
"@types/babel__core@^7.1.14":
|
"@types/babel__core@^7.1.14":
|
||||||
version "7.20.5"
|
version "7.20.5"
|
||||||
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017"
|
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017"
|
||||||
@ -5829,6 +5834,11 @@ react-native-maps@^1.29.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/geojson" "^7946.0.13"
|
"@types/geojson" "^7946.0.13"
|
||||||
|
|
||||||
|
react-native-razorpay@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-native-razorpay/-/react-native-razorpay-3.0.0.tgz#05fca397b132be97aac3f8d6c54576b3fcf269fc"
|
||||||
|
integrity sha512-p7bcEJd8P3/FuNuV/kDvJAhF2QCHXaOwkMA7hkZV3XnmU2IJRap3dF8BYuSBAb+OEvzAm5RQbRHlZAnkr/+h+g==
|
||||||
|
|
||||||
react-native-reanimated@^4.5.0:
|
react-native-reanimated@^4.5.0:
|
||||||
version "4.5.1"
|
version "4.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-4.5.1.tgz#be81ed3a96bf70baeeccdc24d3350883099b7dd3"
|
resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-4.5.1.tgz#be81ed3a96bf70baeeccdc24d3350883099b7dd3"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user