From f83d31cd908e6abd18041fbb3fa19f801aa7192d Mon Sep 17 00:00:00 2001 From: Joaquin Vidal Date: Wed, 15 Nov 2023 11:44:58 -0300 Subject: [PATCH 01/11] drawer navigator --- package-lock.json | 70 ++++++++++++++++++++++ package.json | 1 + src/application/App.tsx | 38 ++++++++++-- src/features/purchases/PurchasesScreen.tsx | 19 ++++++ src/features/purchases/index.ts | 0 5 files changed, 122 insertions(+), 6 deletions(-) create mode 100644 src/features/purchases/PurchasesScreen.tsx create mode 100644 src/features/purchases/index.ts diff --git a/package-lock.json b/package-lock.json index cbc977b..56f5178 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@react-native-async-storage/async-storage": "^1.19.5", "@react-native-community/masked-view": "^0.1.11", "@react-native-community/netinfo": "^9.4.1", + "@react-navigation/drawer": "^6.6.6", "@react-navigation/native": "^6.1.9", "@react-navigation/native-stack": "^6.9.16", "@reduxjs/toolkit": "^1.9.7", @@ -4216,6 +4217,25 @@ "react": "*" } }, + "node_modules/@react-navigation/drawer": { + "version": "6.6.6", + "resolved": "https://registry.npmjs.org/@react-navigation/drawer/-/drawer-6.6.6.tgz", + "integrity": "sha512-DW/oNRisSOGOqvZfCzfhKBxnzT97Teqtg1Gal85g+K3gnVbM1jOBE2PdnYsKU0fULfFtDwvp/QZSbcgjDpr12A==", + "dependencies": { + "@react-navigation/elements": "^1.3.21", + "color": "^4.2.3", + "warn-once": "^0.1.0" + }, + "peerDependencies": { + "@react-navigation/native": "^6.0.0", + "react": "*", + "react-native": "*", + "react-native-gesture-handler": ">= 1.0.0", + "react-native-reanimated": ">= 1.0.0", + "react-native-safe-area-context": ">= 3.0.0", + "react-native-screens": ">= 3.0.0" + } + }, "node_modules/@react-navigation/elements": { "version": "1.3.21", "resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.21.tgz", @@ -6186,6 +6206,18 @@ "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", "dev": true }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -6199,6 +6231,31 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/color/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, "node_modules/colorette": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", @@ -14015,6 +14072,19 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", diff --git a/package.json b/package.json index 6cfe13d..d62f439 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@react-native-async-storage/async-storage": "^1.19.5", "@react-native-community/masked-view": "^0.1.11", "@react-native-community/netinfo": "^9.4.1", + "@react-navigation/drawer": "^6.6.6", "@react-navigation/native": "^6.1.9", "@react-navigation/native-stack": "^6.9.16", "@reduxjs/toolkit": "^1.9.7", diff --git a/src/application/App.tsx b/src/application/App.tsx index 3ea4f22..fcba86b 100644 --- a/src/application/App.tsx +++ b/src/application/App.tsx @@ -1,3 +1,4 @@ +import {createDrawerNavigator} from '@react-navigation/drawer'; import {NavigationContainer} from '@react-navigation/native'; import { createNativeStackNavigator, @@ -12,6 +13,7 @@ import {Provider} from 'react-redux'; import {PersistGate} from 'redux-persist/integration/react'; import CartScreen from '../features/cart/CartScreen'; import ProductsScreen from '../features/products/ProductsScreen'; +import PurchasesScreen from '../features/purchases/PurchasesScreen'; import {colors} from '../features/shared/colors'; import {QueryProvider} from '../infrastructure/query'; import store, {persistor} from '../infrastructure/store/store'; @@ -21,8 +23,32 @@ type AppStackParamList = { Cart: undefined; }; +type PurchasesParamList = { + Purchases: undefined; +}; + +const StoreNavigator = createNativeStackNavigator(); +const PurchasesNavigator = createNativeStackNavigator(); +const AppNavigator = createDrawerNavigator(); + +const StoreFlow = () => { + return ( + + + + + ); +}; + +const PurchasesFlow = () => { + return ( + + + + ); +}; + export type NavigationProp = NativeStackNavigationProp; -const appNavigator = createNativeStackNavigator(); function App(): JSX.Element { const isDarkMode = useColorScheme() === 'dark'; @@ -33,11 +59,11 @@ function App(): JSX.Element { return ( - - - - + + + + ); } diff --git a/src/features/purchases/PurchasesScreen.tsx b/src/features/purchases/PurchasesScreen.tsx new file mode 100644 index 0000000..08e4828 --- /dev/null +++ b/src/features/purchases/PurchasesScreen.tsx @@ -0,0 +1,19 @@ +import {useNavigation} from '@react-navigation/native'; +import React from 'react'; +import {StyleSheet, Text} from 'react-native'; +import {SafeAreaView} from 'react-native-safe-area-context'; +import {NavigationProp} from '../../application/App'; + +const PurchaseScreen = () => { + const navigation = useNavigation(); + + return ( + + PURCHASES + + ); +}; + +const styles = StyleSheet.create({}); + +export default PurchaseScreen; diff --git a/src/features/purchases/index.ts b/src/features/purchases/index.ts new file mode 100644 index 0000000..e69de29 From 50b698ee0fd70ace6ebfa69d29602a9713b725cf Mon Sep 17 00:00:00 2001 From: Joaquin Vidal Date: Wed, 15 Nov 2023 12:17:59 -0300 Subject: [PATCH 02/11] get purchases query --- src/application/App.tsx | 8 +++++++- src/features/purchases/queries.ts | 11 +++++++++++ src/infrastructure/api/endpoints.ts | 16 ++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 src/features/purchases/queries.ts diff --git a/src/application/App.tsx b/src/application/App.tsx index fcba86b..5a1f68a 100644 --- a/src/application/App.tsx +++ b/src/application/App.tsx @@ -32,8 +32,14 @@ const PurchasesNavigator = createNativeStackNavigator(); const AppNavigator = createDrawerNavigator(); const StoreFlow = () => { + const isDarkMode = useColorScheme() === 'dark'; + + const backgroundStyle = { + backgroundColor: isDarkMode ? Colors.darker : colors.backgroundColor, + }; return ( - + diff --git a/src/features/purchases/queries.ts b/src/features/purchases/queries.ts new file mode 100644 index 0000000..22f8b9e --- /dev/null +++ b/src/features/purchases/queries.ts @@ -0,0 +1,11 @@ +import {useQuery} from '@tanstack/react-query'; +import {getPurchases} from '../../infrastructure/api'; + +const purchasesKeys = ['all']; + +export const usePurchases = () => { + return useQuery({ + queryKey: purchasesKeys, + queryFn: getPurchases, + }); +}; diff --git a/src/infrastructure/api/endpoints.ts b/src/infrastructure/api/endpoints.ts index 3ae989c..da64333 100644 --- a/src/infrastructure/api/endpoints.ts +++ b/src/infrastructure/api/endpoints.ts @@ -44,6 +44,22 @@ export const makeCheckout = (cart: CartProduct[]) => { }); }; +export const getPurchases = () => { + return instance + .get('/purchases') + .then(response => { + if (response.status === 200) { + return response.data; + } else { + throw new Error('Error fetching products'); + } + }) + .catch(error => { + console.log(error); + throw error; + }); +}; + export interface Banner { id: number; name: string; From 1dcfa6836039e6a526159f28979e6576d497d943 Mon Sep 17 00:00:00 2001 From: Joaquin Vidal Date: Wed, 15 Nov 2023 12:25:28 -0300 Subject: [PATCH 03/11] invalidate query when posting new purchase --- src/features/cart/queries.ts | 13 ++++++++++--- src/features/purchases/queries.ts | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/features/cart/queries.ts b/src/features/cart/queries.ts index d65b769..4f42af4 100644 --- a/src/features/cart/queries.ts +++ b/src/features/cart/queries.ts @@ -1,7 +1,14 @@ -import {useMutation} from '@tanstack/react-query'; +import {useMutation, useQueryClient} from '@tanstack/react-query'; import {makeCheckout} from '../../infrastructure/api'; +import {purchasesKeys} from '../purchases/queries'; -export const useCheckoutMutation = () => - useMutation({ +export const useCheckoutMutation = () => { + const queryClient = useQueryClient(); + + return useMutation({ mutationFn: makeCheckout, + onSuccess: () => { + queryClient.invalidateQueries({queryKey: purchasesKeys}); + }, }); +}; diff --git a/src/features/purchases/queries.ts b/src/features/purchases/queries.ts index 22f8b9e..7c7542c 100644 --- a/src/features/purchases/queries.ts +++ b/src/features/purchases/queries.ts @@ -1,7 +1,7 @@ import {useQuery} from '@tanstack/react-query'; import {getPurchases} from '../../infrastructure/api'; -const purchasesKeys = ['all']; +export const purchasesKeys = ['all']; export const usePurchases = () => { return useQuery({ From 9a0f1711ba2c9bf76be9a97e959aa534079b13fa Mon Sep 17 00:00:00 2001 From: Joaquin Vidal Date: Wed, 15 Nov 2023 13:25:33 -0300 Subject: [PATCH 04/11] fixed navigators name --- src/application/App.tsx | 4 ++-- src/features/products/ProductsScreen.tsx | 2 +- src/features/purchases/PurchasesScreen.tsx | 8 +++++++- src/features/purchases/types/Purchase.ts | 6 ++++++ src/infrastructure/api/endpoints.ts | 3 ++- 5 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 src/features/purchases/types/Purchase.ts diff --git a/src/application/App.tsx b/src/application/App.tsx index 5a1f68a..777e57a 100644 --- a/src/application/App.tsx +++ b/src/application/App.tsx @@ -67,8 +67,8 @@ function App(): JSX.Element { - - + + ); diff --git a/src/features/products/ProductsScreen.tsx b/src/features/products/ProductsScreen.tsx index 25b93ab..a46557a 100644 --- a/src/features/products/ProductsScreen.tsx +++ b/src/features/products/ProductsScreen.tsx @@ -54,7 +54,7 @@ const styles = StyleSheet.create({ }, cartButton: { marginEnd: 29, - marginVertical: 16, + marginBottom: 16, alignSelf: 'flex-end', }, searchBar: { diff --git a/src/features/purchases/PurchasesScreen.tsx b/src/features/purchases/PurchasesScreen.tsx index 08e4828..a25af74 100644 --- a/src/features/purchases/PurchasesScreen.tsx +++ b/src/features/purchases/PurchasesScreen.tsx @@ -1,15 +1,21 @@ import {useNavigation} from '@react-navigation/native'; import React from 'react'; import {StyleSheet, Text} from 'react-native'; +import {FlatList} from 'react-native-gesture-handler'; import {SafeAreaView} from 'react-native-safe-area-context'; import {NavigationProp} from '../../application/App'; +import {usePurchases} from './queries'; const PurchaseScreen = () => { const navigation = useNavigation(); + const {data: purchases} = usePurchases(); return ( - PURCHASES + {item.date}} + /> ); }; diff --git a/src/features/purchases/types/Purchase.ts b/src/features/purchases/types/Purchase.ts new file mode 100644 index 0000000..29e673a --- /dev/null +++ b/src/features/purchases/types/Purchase.ts @@ -0,0 +1,6 @@ +import {Product} from '../../products/types/Product'; + +export interface Purchase { + date: string; + items: Product[]; +} diff --git a/src/infrastructure/api/endpoints.ts b/src/infrastructure/api/endpoints.ts index da64333..7fe7cca 100644 --- a/src/infrastructure/api/endpoints.ts +++ b/src/infrastructure/api/endpoints.ts @@ -1,3 +1,4 @@ +import {Purchase} from '../../features/purchases/types/Purchase'; import {CartProduct} from '../store/cartSlice'; import {instance} from './instance'; @@ -44,7 +45,7 @@ export const makeCheckout = (cart: CartProduct[]) => { }); }; -export const getPurchases = () => { +export const getPurchases = (): Promise => { return instance .get('/purchases') .then(response => { From ff69970028a089bafa340bf18079d74049e82f95 Mon Sep 17 00:00:00 2001 From: Joaquin Vidal Date: Mon, 20 Nov 2023 13:25:27 -0300 Subject: [PATCH 05/11] purchases list --- src/application/App.tsx | 5 ++- src/features/cart/components/CartItem.tsx | 2 +- src/features/products/ProductsScreen.tsx | 2 +- .../products/components/ProductsList.tsx | 7 +-- src/features/purchases/PurchasesScreen.tsx | 23 +++++++--- .../purchases/components/PurchaseListItem.tsx | 44 +++++++++++++++++++ src/features/purchases/queries.ts | 15 +++++++ src/features/purchases/types/Purchase.ts | 4 +- .../shared/components/ProductsSeparator.tsx | 9 ++++ 9 files changed, 94 insertions(+), 17 deletions(-) create mode 100644 src/features/purchases/components/PurchaseListItem.tsx create mode 100644 src/features/shared/components/ProductsSeparator.tsx diff --git a/src/application/App.tsx b/src/application/App.tsx index 777e57a..16a4131 100644 --- a/src/application/App.tsx +++ b/src/application/App.tsx @@ -39,7 +39,10 @@ const StoreFlow = () => { }; return ( + screenOptions={{ + headerShown: false, + contentStyle: backgroundStyle, + }}> diff --git a/src/features/cart/components/CartItem.tsx b/src/features/cart/components/CartItem.tsx index 97a29ad..5d98232 100644 --- a/src/features/cart/components/CartItem.tsx +++ b/src/features/cart/components/CartItem.tsx @@ -23,7 +23,7 @@ const CartItem = ({ {product.name} - {'$' + product.price.toFixed(2)} + {'$' + product.price?.toFixed(2) || '0'} {product.quantity + ' units'} diff --git a/src/features/products/ProductsScreen.tsx b/src/features/products/ProductsScreen.tsx index a46557a..8dae5f8 100644 --- a/src/features/products/ProductsScreen.tsx +++ b/src/features/products/ProductsScreen.tsx @@ -27,7 +27,7 @@ const ProductsScreen = () => { ); return ( - + {cartImage} diff --git a/src/features/products/components/ProductsList.tsx b/src/features/products/components/ProductsList.tsx index f1719d8..d61286b 100644 --- a/src/features/products/components/ProductsList.tsx +++ b/src/features/products/components/ProductsList.tsx @@ -6,6 +6,7 @@ import { } from '../../../infrastructure/store/cartSlice'; import {useAppDispatch} from '../../../infrastructure/store/hooks/hooks'; import {colors} from '../../shared/colors'; +import {productsSeparator} from '../../shared/components/ProductsSeparator'; import {useDisplayList} from '../hooks/useDisplayList'; import {Product} from '../types/Product'; import HeaderListItem from './HeaderListItem'; @@ -48,12 +49,6 @@ export const ProductsList = ({query}: {query: string}) => { ); }; -const productsSeparator = () => { - return ( - - ); -}; - const styles = StyleSheet.create({ productContainer: { marginHorizontal: 16, diff --git a/src/features/purchases/PurchasesScreen.tsx b/src/features/purchases/PurchasesScreen.tsx index a25af74..0447160 100644 --- a/src/features/purchases/PurchasesScreen.tsx +++ b/src/features/purchases/PurchasesScreen.tsx @@ -1,20 +1,31 @@ import {useNavigation} from '@react-navigation/native'; import React from 'react'; -import {StyleSheet, Text} from 'react-native'; -import {FlatList} from 'react-native-gesture-handler'; +import {SectionList, StyleSheet} from 'react-native'; import {SafeAreaView} from 'react-native-safe-area-context'; import {NavigationProp} from '../../application/App'; +import HeaderListItem from '../products/components/HeaderListItem'; +import {productsSeparator} from '../shared/components/ProductsSeparator'; +import {PurchaseListItem} from './components/PurchaseListItem'; import {usePurchases} from './queries'; const PurchaseScreen = () => { const navigation = useNavigation(); const {data: purchases} = usePurchases(); + const purchasesList = purchases ?? []; return ( - - {item.date}} + + } + ItemSeparatorComponent={productsSeparator} + keyExtractor={item => item.date} + renderSectionHeader={({ + section: {title}, + }: { + section: {title: string}; + }) => } /> ); diff --git a/src/features/purchases/components/PurchaseListItem.tsx b/src/features/purchases/components/PurchaseListItem.tsx new file mode 100644 index 0000000..2ab7b9e --- /dev/null +++ b/src/features/purchases/components/PurchaseListItem.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import {FlatList, StyleSheet, View} from 'react-native'; +import {MARGIN_BETWEEN_COLUMNS, MARGIN_HORIZONTAL} from '../../cart/CartScreen'; +import CartItem from '../../cart/components/CartItem'; +import {colors} from '../../shared/colors'; +import {Purchase} from '../types/Purchase'; + +export const PurchaseListItem = ({purchase}: {purchase: Purchase}) => { + const newLocal = 'stretch'; + return ( + + { + return {...purchaseItem.product, quantity: purchaseItem.quantity}; + })} + contentContainerStyle={{ + paddingTop: 24, + alignItems: newLocal, + marginHorizontal: MARGIN_HORIZONTAL, + }} + renderItem={({item, index}) => ( + {}} + /> + )} + /> + + ); +}; + +const styles = StyleSheet.create({ + container: { + borderColor: colors.purple, + marginBottom: 16, + borderWidth: 2, + }, +}); diff --git a/src/features/purchases/queries.ts b/src/features/purchases/queries.ts index 7c7542c..7f45569 100644 --- a/src/features/purchases/queries.ts +++ b/src/features/purchases/queries.ts @@ -1,5 +1,6 @@ import {useQuery} from '@tanstack/react-query'; import {getPurchases} from '../../infrastructure/api'; +import {Purchase} from './types/Purchase'; export const purchasesKeys = ['all']; @@ -7,5 +8,19 @@ export const usePurchases = () => { return useQuery({ queryKey: purchasesKeys, queryFn: getPurchases, + select: data => { + const datesPurchasesMap = data.reduce((acc, purchase) => { + const date = purchase.date.split('T')[0]; + const group = acc.get(date) || []; + group.push(purchase); + acc.set(date, group); + return acc; + }, new Map()); + + return Array.from(datesPurchasesMap, ([date, purchases]) => ({ + title: date, + data: purchases, + })).reverse(); + }, }); }; diff --git a/src/features/purchases/types/Purchase.ts b/src/features/purchases/types/Purchase.ts index 29e673a..ef2bf15 100644 --- a/src/features/purchases/types/Purchase.ts +++ b/src/features/purchases/types/Purchase.ts @@ -1,6 +1,6 @@ -import {Product} from '../../products/types/Product'; +import {ApiProduct} from '../../../infrastructure/api'; export interface Purchase { date: string; - items: Product[]; + items: {product: ApiProduct; quantity: number}[]; } diff --git a/src/features/shared/components/ProductsSeparator.tsx b/src/features/shared/components/ProductsSeparator.tsx new file mode 100644 index 0000000..b9e2a28 --- /dev/null +++ b/src/features/shared/components/ProductsSeparator.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import {View} from 'react-native'; +import {colors} from '../colors'; + +export const productsSeparator = () => { + return ( + + ); +}; From 0254d6db046b79c4ac4281792d5dd316ce761aec Mon Sep 17 00:00:00 2001 From: Joaquin Vidal Date: Tue, 21 Nov 2023 15:02:15 -0300 Subject: [PATCH 06/11] showing correct icons in header --- package-lock.json | 83 ++++++++++++++++++- package.json | 4 +- res/menu_black_24dp.svg | 1 + src/application/App.tsx | 82 ++++++++++++++---- src/application/RootNavigation.ts | 12 +++ src/features/products/ProductsScreen.tsx | 27 +----- .../products/components/CartButton.tsx | 31 +++++++ 7 files changed, 195 insertions(+), 45 deletions(-) create mode 100644 res/menu_black_24dp.svg create mode 100644 src/application/RootNavigation.ts create mode 100644 src/features/products/components/CartButton.tsx diff --git a/package-lock.json b/package-lock.json index 56f5178..8c3d90e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "axios": "^1.6.0", "react": "18.2.0", "react-native": "0.72.6", + "react-native-elements": "^3.4.3", "react-native-gesture-handler": "^2.9.0", "react-native-modal": "^13.0.1", "react-native-reanimated": "^3.5.4", @@ -28,7 +29,7 @@ "react-native-simple-toast": "^3.0.2", "react-native-svg": "^13.14.0", "react-native-svg-transformer": "^1.1.0", - "react-native-vector-icons": "^10.0.1", + "react-native-vector-icons": "^10.0.2", "react-query": "^3.39.3", "react-redux": "^8.1.3", "redux": "^4.2.1", @@ -42,6 +43,7 @@ "@react-native/metro-config": "^0.72.11", "@tsconfig/react-native": "^3.0.0", "@types/react": "^18.0.24", + "@types/react-native-vector-icons": "^6.4.18", "@types/react-redux": "^7.1.28", "@types/react-test-renderer": "^18.0.0", "babel-jest": "^29.2.1", @@ -4858,6 +4860,23 @@ "csstype": "^3.0.2" } }, + "node_modules/@types/react-native": { + "version": "0.70.18", + "resolved": "https://registry.npmjs.org/@types/react-native/-/react-native-0.70.18.tgz", + "integrity": "sha512-M06e2opOY8PyLVfVSWd70X2yrIDZrgiOw677HsOrI/fT27aqvKGuFE44tDUBLEvQ8XEPC+T5pW2h5Az6gX7hdA==", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-native-vector-icons": { + "version": "6.4.18", + "resolved": "https://registry.npmjs.org/@types/react-native-vector-icons/-/react-native-vector-icons-6.4.18.tgz", + "integrity": "sha512-YGlNWb+k5laTBHd7+uZowB9DpIK3SXUneZqAiKQaj1jnJCZM0x71GDim5JCTMi4IFkhc9m8H/Gm28T5BjyivUw==", + "dependencies": { + "@types/react": "*", + "@types/react-native": "^0.70" + } + }, "node_modules/@types/react-redux": { "version": "7.1.30", "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.30.tgz", @@ -11122,6 +11141,11 @@ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -12523,6 +12547,14 @@ "node": ">=8" } }, + "node_modules/opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", + "bin": { + "opencollective-postinstall": "index.js" + } + }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -13147,6 +13179,35 @@ "prop-types": "^15.7.2" } }, + "node_modules/react-native-elements": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/react-native-elements/-/react-native-elements-3.4.3.tgz", + "integrity": "sha512-VtZc25EecPZyUBER85zFK9ZbY6kkUdcm1ZwJ9hdoGSCr1R/GFgxor4jngOcSYeMvQ+qimd5No44OVJW3rSJECA==", + "hasInstallScript": true, + "dependencies": { + "@types/react-native-vector-icons": "^6.4.6", + "color": "^3.1.2", + "deepmerge": "^4.2.2", + "hoist-non-react-statics": "^3.3.2", + "lodash.isequal": "^4.5.0", + "opencollective-postinstall": "^2.0.3", + "react-native-ratings": "8.0.4", + "react-native-size-matters": "^0.3.1" + }, + "peerDependencies": { + "react-native-safe-area-context": ">= 3.0.0", + "react-native-vector-icons": ">7.0.0" + } + }, + "node_modules/react-native-elements/node_modules/color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "dependencies": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, "node_modules/react-native-gesture-handler": { "version": "2.13.4", "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.13.4.tgz", @@ -13176,6 +13237,18 @@ "react-native": ">=0.65.0" } }, + "node_modules/react-native-ratings": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/react-native-ratings/-/react-native-ratings-8.0.4.tgz", + "integrity": "sha512-Xczu5lskIIRD6BEdz9A0jDRpEck/SFxRqiglkXi0u67yAtI1/pcJC76P4MukCbT8K4BPVl+42w83YqXBoBRl7A==", + "dependencies": { + "lodash": "^4.17.15" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, "node_modules/react-native-reanimated": { "version": "3.5.4", "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.5.4.tgz", @@ -13231,6 +13304,14 @@ "react-native": ">=0.71.0" } }, + "node_modules/react-native-size-matters": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/react-native-size-matters/-/react-native-size-matters-0.3.1.tgz", + "integrity": "sha512-mKOfBLIBFBcs9br1rlZDvxD5+mAl8Gfr5CounwJtxI6Z82rGrMO+Kgl9EIg3RMVf3G855a85YVqHJL2f5EDRlw==", + "peerDependencies": { + "react-native": "*" + } + }, "node_modules/react-native-svg": { "version": "13.14.0", "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-13.14.0.tgz", diff --git a/package.json b/package.json index d62f439..1e12dd7 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "axios": "^1.6.0", "react": "18.2.0", "react-native": "0.72.6", + "react-native-elements": "^3.4.3", "react-native-gesture-handler": "^2.9.0", "react-native-modal": "^13.0.1", "react-native-reanimated": "^3.5.4", @@ -30,7 +31,7 @@ "react-native-simple-toast": "^3.0.2", "react-native-svg": "^13.14.0", "react-native-svg-transformer": "^1.1.0", - "react-native-vector-icons": "^10.0.1", + "react-native-vector-icons": "^10.0.2", "react-query": "^3.39.3", "react-redux": "^8.1.3", "redux": "^4.2.1", @@ -44,6 +45,7 @@ "@react-native/metro-config": "^0.72.11", "@tsconfig/react-native": "^3.0.0", "@types/react": "^18.0.24", + "@types/react-native-vector-icons": "^6.4.18", "@types/react-redux": "^7.1.28", "@types/react-test-renderer": "^18.0.0", "babel-jest": "^29.2.1", diff --git a/res/menu_black_24dp.svg b/res/menu_black_24dp.svg new file mode 100644 index 0000000..16fbd60 --- /dev/null +++ b/res/menu_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/application/App.tsx b/src/application/App.tsx index 16a4131..b8dc0dd 100644 --- a/src/application/App.tsx +++ b/src/application/App.tsx @@ -5,20 +5,25 @@ import { NativeStackNavigationProp, } from '@react-navigation/native-stack'; import React from 'react'; -import {Text, useColorScheme} from 'react-native'; +import {Text, TouchableOpacity, useColorScheme} from 'react-native'; import {GestureHandlerRootView} from 'react-native-gesture-handler'; import {SafeAreaProvider} from 'react-native-safe-area-context'; import {Colors} from 'react-native/Libraries/NewAppScreen'; import {Provider} from 'react-redux'; import {PersistGate} from 'redux-persist/integration/react'; +import ArrowBack from '../../res/arrow_back.svg'; +import MenuIcon from '../../res/menu_black_24dp.svg'; import CartScreen from '../features/cart/CartScreen'; +import CartButton from '../features/products/components/CartButton'; import ProductsScreen from '../features/products/ProductsScreen'; import PurchasesScreen from '../features/purchases/PurchasesScreen'; import {colors} from '../features/shared/colors'; import {QueryProvider} from '../infrastructure/query'; +import {useAppSelector} from '../infrastructure/store/hooks/hooks'; import store, {persistor} from '../infrastructure/store/store'; +import {navigationRef} from './RootNavigation'; -type AppStackParamList = { +export type AppStackParamList = { Products: undefined; Cart: undefined; }; @@ -66,29 +71,70 @@ function App(): JSX.Element { backgroundColor: isDarkMode ? Colors.darker : colors.backgroundColor, }; + const isCartEmpty = useAppSelector(state => state.cart.cart.length === 0); + return ( - - - - - - + + { + const state = navigation.getState(); + + // Encuentra el estado del StackNavigator anidado + const stackState = state.routes.find(route => route.state)?.state; + const currentScreen = stackState?.routes[stackState?.index]?.name; + + const isCartScreen = currentScreen === 'Cart'; + + return { + headerRight: () => ( + navigation.navigate('Cart')} + isEnabled={isCartEmpty} + /> + ), + headerLeft: () => + isCartScreen ? ( + { + navigation.goBack(); + }}> + + + ) : ( + { + navigation.openDrawer(); + }}> + + + ), + }; + }} + /> + + ); } export default () => { return ( - - - Loading...} persistor={persistor}> - - - - - - + + + + Loading...} + persistor={persistor}> + + + + + + + ); }; diff --git a/src/application/RootNavigation.ts b/src/application/RootNavigation.ts new file mode 100644 index 0000000..24fc0d2 --- /dev/null +++ b/src/application/RootNavigation.ts @@ -0,0 +1,12 @@ +// import {NavigationContainerRef} from '@react-navigation/native'; +// import React from 'react'; +// import {AppStackParamList} from './App'; + +// export const navigationRef = +// React.createRef>(); + +// export function navigate(name: string, params) { +// if (navigationRef.current?.isReady()) { +// navigationRef.current.navigate(name, params); +// } +// } diff --git a/src/features/products/ProductsScreen.tsx b/src/features/products/ProductsScreen.tsx index 8dae5f8..45debfa 100644 --- a/src/features/products/ProductsScreen.tsx +++ b/src/features/products/ProductsScreen.tsx @@ -1,35 +1,16 @@ -import {useNavigation} from '@react-navigation/native'; import React, {useState} from 'react'; -import {StyleSheet, TouchableOpacity, View} from 'react-native'; +import {StyleSheet, View} from 'react-native'; import {SafeAreaView} from 'react-native-safe-area-context'; -import EnabledShoppingCart from '../../../res/shopping-cart-enabled.svg'; -import ShoppingCart from '../../../res/shopping-cart.svg'; -import {NavigationProp} from '../../application/App'; -import {useAppSelector} from '../../infrastructure/store/hooks/hooks'; import Carrousel from './components/Carrousel'; import {ProductsList} from './components/ProductsList'; import SearchBar from './components/SearchBar'; const ProductsScreen = () => { - const isEmpty = useAppSelector(state => state.cart.cart.length === 0); const [query, setQuery] = useState(''); - const navigation = useNavigation(); - - const cartImage = isEmpty ? ( - - ) : ( - { - navigation.navigate('Cart'); - }}> - - - ); return ( - {cartImage} { const styles = StyleSheet.create({ container: { flex: 1, + marginTop: 12, }, carrousel: { width: '100%', height: 250, }, - cartButton: { - marginEnd: 29, - marginBottom: 16, - alignSelf: 'flex-end', - }, searchBar: { marginTop: 24, }, diff --git a/src/features/products/components/CartButton.tsx b/src/features/products/components/CartButton.tsx new file mode 100644 index 0000000..d950e41 --- /dev/null +++ b/src/features/products/components/CartButton.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import {StyleSheet, TouchableOpacity, View} from 'react-native'; +import EnabledShoppingCart from '../../../../res/shopping-cart-enabled.svg'; +import ShoppingCart from '../../../../res/shopping-cart.svg'; + +const CartButton = ({ + isEnabled, + onPress, +}: { + isEnabled: boolean; + onPress: () => void; +}) => { + const cartImage = isEnabled ? ( + + ) : ( + + + + ); + + return {cartImage}; +}; + +const styles = StyleSheet.create({ + cartButton: { + marginEnd: 29, + marginBottom: 16, + }, +}); + +export default CartButton; From b3ca43cd17815b8aaa396fab3180c9bcdf556f66 Mon Sep 17 00:00:00 2001 From: Joaquin Vidal Date: Wed, 22 Nov 2023 13:20:34 -0300 Subject: [PATCH 07/11] fixes --- src/application/App.tsx | 16 ++++++++++---- src/application/RootNavigation.ts | 12 ----------- src/features/cart/CartScreen.tsx | 21 +------------------ .../products/components/CartButton.tsx | 1 - src/features/purchases/PurchasesScreen.tsx | 13 ++++++------ 5 files changed, 20 insertions(+), 43 deletions(-) delete mode 100644 src/application/RootNavigation.ts diff --git a/src/application/App.tsx b/src/application/App.tsx index b8dc0dd..c166efe 100644 --- a/src/application/App.tsx +++ b/src/application/App.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react/no-unstable-nested-components */ import {createDrawerNavigator} from '@react-navigation/drawer'; import {NavigationContainer} from '@react-navigation/native'; import { @@ -5,7 +6,7 @@ import { NativeStackNavigationProp, } from '@react-navigation/native-stack'; import React from 'react'; -import {Text, TouchableOpacity, useColorScheme} from 'react-native'; +import {StyleSheet, Text, TouchableOpacity, useColorScheme} from 'react-native'; import {GestureHandlerRootView} from 'react-native-gesture-handler'; import {SafeAreaProvider} from 'react-native-safe-area-context'; import {Colors} from 'react-native/Libraries/NewAppScreen'; @@ -13,7 +14,7 @@ import {Provider} from 'react-redux'; import {PersistGate} from 'redux-persist/integration/react'; import ArrowBack from '../../res/arrow_back.svg'; import MenuIcon from '../../res/menu_black_24dp.svg'; -import CartScreen from '../features/cart/CartScreen'; +import CartScreen, {MARGIN_HORIZONTAL} from '../features/cart/CartScreen'; import CartButton from '../features/products/components/CartButton'; import ProductsScreen from '../features/products/ProductsScreen'; import PurchasesScreen from '../features/purchases/PurchasesScreen'; @@ -21,7 +22,6 @@ import {colors} from '../features/shared/colors'; import {QueryProvider} from '../infrastructure/query'; import {useAppSelector} from '../infrastructure/store/hooks/hooks'; import store, {persistor} from '../infrastructure/store/store'; -import {navigationRef} from './RootNavigation'; export type AppStackParamList = { Products: undefined; @@ -98,6 +98,7 @@ function App(): JSX.Element { headerLeft: () => isCartScreen ? ( { navigation.goBack(); }}> @@ -105,6 +106,7 @@ function App(): JSX.Element { ) : ( { navigation.openDrawer(); }}> @@ -119,10 +121,16 @@ function App(): JSX.Element { ); } +const styles = StyleSheet.create({ + headerButton: { + marginHorizontal: MARGIN_HORIZONTAL, + }, +}); + export default () => { return ( - + >(); - -// export function navigate(name: string, params) { -// if (navigationRef.current?.isReady()) { -// navigationRef.current.navigate(name, params); -// } -// } diff --git a/src/features/cart/CartScreen.tsx b/src/features/cart/CartScreen.tsx index c218ded..1fa61b4 100644 --- a/src/features/cart/CartScreen.tsx +++ b/src/features/cart/CartScreen.tsx @@ -1,16 +1,8 @@ import {BottomSheetModal, BottomSheetModalProvider} from '@gorhom/bottom-sheet'; import {useNavigation} from '@react-navigation/native'; import React, {useEffect, useMemo, useRef, useState} from 'react'; -import { - Platform, - SafeAreaView, - StyleSheet, - Text, - TouchableOpacity, - View, -} from 'react-native'; +import {Platform, SafeAreaView, StyleSheet, Text, View} from 'react-native'; import Toast from 'react-native-simple-toast'; -import ArrowBack from '../../../res/arrow_back.svg'; import {NavigationProp} from '../../application/App'; import {cleanCart, editQuantity} from '../../infrastructure/store/cartSlice'; import { @@ -90,13 +82,6 @@ const CartScreen = () => { - { - navigation.goBack(); - }}> - - Shopping Cart { - const navigation = useNavigation(); const {data: purchases} = usePurchases(); const purchasesList = purchases ?? []; return ( - + } ItemSeparatorComponent={productsSeparator} - keyExtractor={item => item.date} + keyExtractor={(item, index) => item.date + index} renderSectionHeader={({ section: {title}, }: { @@ -31,6 +28,10 @@ const PurchaseScreen = () => { ); }; -const styles = StyleSheet.create({}); +const styles = StyleSheet.create({ + container: { + flex: 1, + }, +}); export default PurchaseScreen; From f1ebbda5ff324d7b302fad9628e75085d03a9bbc Mon Sep 17 00:00:00 2001 From: Joaquin Vidal Date: Wed, 22 Nov 2023 16:02:19 -0300 Subject: [PATCH 08/11] only background in app --- src/application/App.tsx | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src/application/App.tsx b/src/application/App.tsx index c166efe..e51c90f 100644 --- a/src/application/App.tsx +++ b/src/application/App.tsx @@ -36,23 +36,15 @@ const StoreNavigator = createNativeStackNavigator(); const PurchasesNavigator = createNativeStackNavigator(); const AppNavigator = createDrawerNavigator(); -const StoreFlow = () => { - const isDarkMode = useColorScheme() === 'dark'; - - const backgroundStyle = { - backgroundColor: isDarkMode ? Colors.darker : colors.backgroundColor, - }; - return ( - - - - - ); -}; +const StoreFlow = () => ( + + + + +); const PurchasesFlow = () => { return ( From 1404158c496043c9e7f8bd901a15309d4b764e96 Mon Sep 17 00:00:00 2001 From: Joaquin Vidal Date: Wed, 22 Nov 2023 16:05:15 -0300 Subject: [PATCH 09/11] extracted line style --- src/features/shared/components/ProductsSeparator.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/features/shared/components/ProductsSeparator.tsx b/src/features/shared/components/ProductsSeparator.tsx index b9e2a28..1d03327 100644 --- a/src/features/shared/components/ProductsSeparator.tsx +++ b/src/features/shared/components/ProductsSeparator.tsx @@ -1,9 +1,11 @@ import React from 'react'; -import {View} from 'react-native'; +import {StyleSheet, View} from 'react-native'; import {colors} from '../colors'; export const productsSeparator = () => { - return ( - - ); + return ; }; + +const styles = StyleSheet.create({ + lineStyle: {height: 1, width: '90%', backgroundColor: colors.gray}, +}); From fab3cad26e9c70d100e21b0c3e45557c24180f70 Mon Sep 17 00:00:00 2001 From: Joaquin Vidal Date: Wed, 22 Nov 2023 16:14:07 -0300 Subject: [PATCH 10/11] not showing cart when in cartScreen --- src/application/App.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/application/App.tsx b/src/application/App.tsx index e51c90f..a12d22b 100644 --- a/src/application/App.tsx +++ b/src/application/App.tsx @@ -74,19 +74,19 @@ function App(): JSX.Element { options={({navigation}) => { const state = navigation.getState(); - // Encuentra el estado del StackNavigator anidado const stackState = state.routes.find(route => route.state)?.state; const currentScreen = stackState?.routes[stackState?.index]?.name; const isCartScreen = currentScreen === 'Cart'; return { - headerRight: () => ( - navigation.navigate('Cart')} - isEnabled={isCartEmpty} - /> - ), + headerRight: () => + !isCartScreen && ( + navigation.navigate('Cart')} + isEnabled={isCartEmpty} + /> + ), headerLeft: () => isCartScreen ? ( Date: Wed, 22 Nov 2023 16:50:51 -0300 Subject: [PATCH 11/11] redefined arguments in cartItem --- src/application/App.tsx | 77 +++++++++---------- src/features/cart/components/CartItem.tsx | 12 ++- .../purchases/components/PurchaseListItem.tsx | 13 ++-- 3 files changed, 49 insertions(+), 53 deletions(-) diff --git a/src/application/App.tsx b/src/application/App.tsx index a12d22b..09f6d2a 100644 --- a/src/application/App.tsx +++ b/src/application/App.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react/no-unstable-nested-components */ import {createDrawerNavigator} from '@react-navigation/drawer'; import {NavigationContainer} from '@react-navigation/native'; import { @@ -56,6 +55,43 @@ const PurchasesFlow = () => { export type NavigationProp = NativeStackNavigationProp; +const StoreFlowNavigationOptions = ({navigation}) => { + const state = navigation.getState(); + const isCartEmpty = useAppSelector(state => state.cart.cart.length === 0); + + const stackState = state.routes.find(route => route.state)?.state; + const currentScreen = stackState?.routes[stackState?.index]?.name; + console.log('currentScreen: ', currentScreen); + const isCartScreen = currentScreen === 'Cart'; + return { + headerRight: () => + !isCartScreen && ( + navigation.navigate('Cart')} + isEnabled={isCartEmpty} + /> + ), + headerLeft: () => + isCartScreen ? ( + { + navigation.goBack(); + }}> + + + ) : ( + { + navigation.openDrawer(); + }}> + + + ), + }; +}; + function App(): JSX.Element { const isDarkMode = useColorScheme() === 'dark'; @@ -63,50 +99,13 @@ function App(): JSX.Element { backgroundColor: isDarkMode ? Colors.darker : colors.backgroundColor, }; - const isCartEmpty = useAppSelector(state => state.cart.cart.length === 0); - return ( { - const state = navigation.getState(); - - const stackState = state.routes.find(route => route.state)?.state; - const currentScreen = stackState?.routes[stackState?.index]?.name; - - const isCartScreen = currentScreen === 'Cart'; - - return { - headerRight: () => - !isCartScreen && ( - navigation.navigate('Cart')} - isEnabled={isCartEmpty} - /> - ), - headerLeft: () => - isCartScreen ? ( - { - navigation.goBack(); - }}> - - - ) : ( - { - navigation.openDrawer(); - }}> - - - ), - }; - }} + options={StoreFlowNavigationOptions} /> diff --git a/src/features/cart/components/CartItem.tsx b/src/features/cart/components/CartItem.tsx index 5d98232..932e2b4 100644 --- a/src/features/cart/components/CartItem.tsx +++ b/src/features/cart/components/CartItem.tsx @@ -4,15 +4,13 @@ import {StyleProps} from 'react-native-reanimated'; import {Product} from '../../products/components/ProductsList'; import {colors} from '../../shared/colors'; -const CartItem = ({ - product, - style, - onPress, -}: { +export type Props = { product: Product; style: StyleProps; - onPress: () => void; -}) => { + onPress?: () => void; +}; + +const CartItem: React.FC = ({product, style, onPress}) => { return ( { - const newLocal = 'stretch'; return ( { data={purchase.items.map(purchaseItem => { return {...purchaseItem.product, quantity: purchaseItem.quantity}; })} - contentContainerStyle={{ - paddingTop: 24, - alignItems: newLocal, - marginHorizontal: MARGIN_HORIZONTAL, - }} + contentContainerStyle={styles.contentContainer} renderItem={({item, index}) => ( { ? {marginEnd: MARGIN_BETWEEN_COLUMNS} : {} } - onPress={() => {}} /> )} /> @@ -41,4 +35,9 @@ const styles = StyleSheet.create({ marginBottom: 16, borderWidth: 2, }, + contentContainer: { + paddingTop: 24, + alignItems: 'stretch', + marginHorizontal: MARGIN_HORIZONTAL, + }, });