app integraded :)😈
This commit is contained in:
@@ -15,13 +15,14 @@
|
||||
"@react-navigation/stack": "^6.0.11",
|
||||
"@reduxjs/toolkit": "^1.6.2",
|
||||
"expo": "~43.0.0",
|
||||
"expo-image-picker": "^11.0.3",
|
||||
"expo-status-bar": "~1.1.0",
|
||||
"react": "17.0.1",
|
||||
"react-dom": "17.0.1",
|
||||
"react-native": "0.64.2",
|
||||
"react-native-animatable": "^1.3.3",
|
||||
"react-native-gesture-handler": "~1.10.2",
|
||||
"react-native-modal": "^13.0.0",
|
||||
"react-native-reanimated": "~2.2.0",
|
||||
"react-native-safe-area-context": "3.3.2",
|
||||
"react-native-screens": "~3.8.0",
|
||||
"react-native-vector-icons": "^9.0.0",
|
||||
|
||||
@@ -54,6 +54,7 @@ function App() {
|
||||
<Stack.Screen name="Groceries" component={GroceryListPage} />
|
||||
<Stack.Screen name="Recipes" component={RecipePage} />
|
||||
<Stack.Screen name="Recipe" component={Recipe} />
|
||||
<Stack.Screen name="AddRecipe" component={AddRecipe} />
|
||||
</Stack.Navigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
@@ -48,7 +48,7 @@ const Dropdown = (props) => {
|
||||
)
|
||||
})
|
||||
return (
|
||||
<WrapperDropdown keyboardShouldPersistTaps={'always'}>
|
||||
<WrapperDropdown keyboardShouldPersistTaps={'always'} nestedScrollEnabled = {true}>
|
||||
{dropdownList}
|
||||
</WrapperDropdown>
|
||||
)
|
||||
|
||||
@@ -88,7 +88,7 @@ export default React.memo((props) => {
|
||||
< WrapperList listLength={items.length} onLayout={(event) => { HandleAnimation(event) }}>
|
||||
{list.open &&
|
||||
<FlatList style={{ width: '100%' }}
|
||||
initialNumToRender={5}
|
||||
initialNumToRender={10}
|
||||
maxToRenderPerBatch={5}
|
||||
ListFooterComponent={filteredItems.length === 0 && <ListSubtitle style={{ fontSize: 22, width: '100%', height: 30, alignSelf: 'center' }} >Add a grocery</ListSubtitle>}
|
||||
data={filteredItems}
|
||||
|
||||
@@ -7,18 +7,19 @@ import { CheckButton } from '../../../styles/componentBlueprints';
|
||||
import { useSelector, useDispatch, shallowEqual } from 'react-redux';
|
||||
import { selectItemById, checkToggle, modalToggle } from '../../../redux/slices/groceryList/itemsSlice'
|
||||
import { findTag } from '../../../redux/slices/groceryList/tagsSlice'
|
||||
import { toggleOffAnim, toggleOnAnim } from '../../../styles/animations';
|
||||
|
||||
const ListedItem = React.memo((props) => {
|
||||
const dispatch = useDispatch()
|
||||
const item = useSelector(state => selectItemById(state, props.item._id), shallowEqual)
|
||||
const tag = useSelector(state => findTag(state, item.tag))
|
||||
return (
|
||||
<Wrapper>
|
||||
<DarkLayer>
|
||||
<Wrapper >
|
||||
<DarkLayer animation={item.checked ? toggleOnAnim: toggleOffAnim}>
|
||||
<WrapperItem person={item.person} color={tag.color} checked={item.checked} onPress={() => { props.setVisible(true); return dispatch(modalToggle(item._id)) }}>
|
||||
<TextProductName >{item.productName}</TextProductName>
|
||||
{item.details != "" && <TextDetails>{item.details}</TextDetails>}
|
||||
<TextAmount>{item.amount.am}{item.amount.qt && " " + item.amount.qt}</TextAmount>
|
||||
<TextAmount>{item.amount.am}{item.amount.qt && " x (" + item.amount.qt + ")"}</TextAmount>
|
||||
{item.person != "" && <TextPerson>{item.person}</TextPerson>}
|
||||
</WrapperItem>
|
||||
</DarkLayer>
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import * as Animatable from 'react-native-animatable';
|
||||
|
||||
import { Text, View, Image, TouchableOpacity} from 'react-native'
|
||||
|
||||
import styled, { css } from 'styled-components'
|
||||
|
||||
export const Wrapper = styled(View)`
|
||||
@@ -8,7 +11,7 @@ export const Wrapper = styled(View)`
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
`
|
||||
export const DarkLayer = styled(View)`
|
||||
export const DarkLayer = styled(Animatable.View)`
|
||||
background-color: ${({ theme }) => theme.colors.dp00};
|
||||
display: flex;
|
||||
flex: 1;
|
||||
@@ -31,7 +34,7 @@ export const WrapperItem = styled(TouchableOpacity)`
|
||||
background-color: ${props => props.checked ? props.theme.colors.itemSelected : props.color + '66'};
|
||||
`
|
||||
export const WrapperButton = styled(TouchableOpacity)`
|
||||
height: 30px;
|
||||
min-height: 40px;
|
||||
width: 40px;
|
||||
`
|
||||
export const TextProductName = styled(Text)`
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React from 'react'
|
||||
import * as Animatable from 'react-native-animatable';
|
||||
//components
|
||||
//styling
|
||||
import { Wrapper, WrapperProduct, WrapperButton, WrapperText, TextProductName, TextTag, TextPrice, StyledImage, IconCheck } from './styles/listedProduct'
|
||||
@@ -7,6 +8,7 @@ import { useSelector, useDispatch, shallowEqual } from 'react-redux';
|
||||
import { selectProductById, checkToggle, modalToggle } from '../../../redux/slices/groceryList/productsSlice'
|
||||
import { findTag } from '../../../redux/slices/groceryList/tagsSlice'
|
||||
import { CheckButton } from '../../../styles/componentBlueprints';
|
||||
import { toggleOffAnim, toggleOnAnim } from '../../../styles/animations';
|
||||
|
||||
const ListedProduct = React.memo((props) => {
|
||||
const dispatch = useDispatch()
|
||||
@@ -14,14 +16,16 @@ const ListedProduct = React.memo((props) => {
|
||||
const tag = useSelector(state => findTag(state, product.tag))
|
||||
return (
|
||||
<Wrapper>
|
||||
<WrapperProduct color={tag.color} checked={product.checked} onPress={() => { props.setVisible(true); return dispatch(modalToggle(product._id)) }}>
|
||||
<WrapperText>
|
||||
<TextProductName >{product.productName}</TextProductName>
|
||||
<TextTag color={tag.color}>{tag.tagName}</TextTag>
|
||||
{product.price !== 0 && <TextPrice>€ {product.price}</TextPrice>}
|
||||
</WrapperText>
|
||||
{product.image != "" && <StyledImage source={{ uri: product.image }} />}
|
||||
</WrapperProduct>
|
||||
<Animatable.View style={{ flex: 1 }} animation={product.checked ? toggleOnAnim : toggleOffAnim} >
|
||||
<WrapperProduct color={tag.color} checked={product.checked} onPress={() => { props.setVisible(true); return dispatch(modalToggle(product._id)) }}>
|
||||
<WrapperText>
|
||||
<TextProductName >{product.productName}</TextProductName>
|
||||
<TextTag color={tag.color}>{tag.tagName}</TextTag>
|
||||
{product.price !== 0 && <TextPrice>€ {product.price}</TextPrice>}
|
||||
</WrapperText>
|
||||
{product.image != "" && <StyledImage source={{ uri: product.image }} />}
|
||||
</WrapperProduct>
|
||||
</Animatable.View>
|
||||
<WrapperButton onPress={() => dispatch(checkToggle(product._id))} >
|
||||
<CheckButton checked={product.checked}>
|
||||
<IconCheck checked={product.checked} />
|
||||
|
||||
@@ -17,8 +17,7 @@ export const Wrapper = styled(View)`
|
||||
export const WrapperProduct = styled(TouchableOpacity)`
|
||||
box-shadow: ${({theme})=> theme.colors.shadow};
|
||||
display: flex;
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
width: 98%;
|
||||
min-height: 70px;
|
||||
position: relative;
|
||||
flex-direction: row;
|
||||
@@ -30,7 +29,7 @@ export const WrapperProduct = styled(TouchableOpacity)`
|
||||
background-color: ${props => props.checked ? props.theme.colors.itemSelected : props.color + '66'};
|
||||
`
|
||||
export const WrapperButton = styled(TouchableOpacity)`
|
||||
height: 60px;
|
||||
height: 70px;
|
||||
width: 40px;
|
||||
`
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useHeaderHeight } from '@react-navigation/elements';
|
||||
const HeaderPadding = (props) => {
|
||||
const headerHeight = useHeaderHeight();
|
||||
return (
|
||||
<View style={{ height: headerHeight + 10 }} />
|
||||
<View style={{ opacity: 0, height: headerHeight + 10 }} />
|
||||
)
|
||||
}
|
||||
export default HeaderPadding;
|
||||
@@ -61,7 +61,7 @@ const ModalAddItem = (props) => {
|
||||
let product = products.find((product) => product.productName === pName);
|
||||
setProductName(product.productName)
|
||||
setTag(product.tag)
|
||||
setPrice(product.price)
|
||||
setPrice(product.price && product.price.toString())
|
||||
}
|
||||
return (
|
||||
<StyledModal isVisible={props.visible} animationIn={'slideInUp'} animationOut={'slideOutDown'}
|
||||
|
||||
@@ -81,7 +81,7 @@ const ModalEditProduct = (props) => {
|
||||
</WrapperDropdown>}
|
||||
<WrapperInput>
|
||||
<IconDollar />
|
||||
<Input type={"number-pad"}
|
||||
<Input keyboardType={"number-pad"}
|
||||
value={price}
|
||||
onChangeText={(text) => setPrice(text)}
|
||||
placeholder="Price" />
|
||||
|
||||
@@ -84,7 +84,7 @@ const ModalAddIngredients = (props) => {
|
||||
<IconMeal />
|
||||
<Input
|
||||
style={{ fontSize: 20, width: 100 }}
|
||||
type="number-pad"
|
||||
keyboardType={"number-pad"}
|
||||
value={servings}
|
||||
onChangeText={(text) => setServings(text)}
|
||||
min={amountOfServings}
|
||||
|
||||
@@ -22,7 +22,7 @@ export const WrapperInput = styled(View)`
|
||||
margin-bottom:5px;
|
||||
`
|
||||
export const WrapperDropdown = styled(View)`
|
||||
margin-left: 16px;
|
||||
margin-left: 42px;
|
||||
margin-top: -5px;
|
||||
margin-bottom: 5px;
|
||||
`
|
||||
@@ -68,7 +68,7 @@ export const Button = styled(TouchableOpacity)`
|
||||
export const ButtonText = styled(Text)`
|
||||
color: ${props => props.theme.colors.primary};
|
||||
font-weight: bold;
|
||||
font-size: ${({ theme }) => theme.fontSizes.fontS}px;
|
||||
font-size: ${({ theme }) => theme.fontSizes.fontM}px;
|
||||
`
|
||||
|
||||
export const ModalHeader = styled(Text)`
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { View } from 'react-native'
|
||||
import { TouchableOpacity, View } from 'react-native'
|
||||
import styled from "styled-components"
|
||||
|
||||
import { Ingredient } from "./addRecipe/Ingredient"
|
||||
@@ -14,7 +14,7 @@ export const Wrapper = styled(View)`
|
||||
border-bottom-color: ${props => props.theme.colors.dp01};
|
||||
border-bottom-width: 1px;
|
||||
border-radius: 20px;
|
||||
${props => props.checked === true && css`background-color: ` + props.theme.colors.selected + '33'};
|
||||
${props => props.checked === true && "background-color:" + props.theme.colors.selected + '33'};
|
||||
`
|
||||
|
||||
const IngredientButton = (props) => {
|
||||
@@ -23,9 +23,9 @@ const IngredientButton = (props) => {
|
||||
return (
|
||||
<Wrapper checked={ingredient.checked}>
|
||||
<Ingredient ingredient={ingredient} multiplier={props.multiplier}/>
|
||||
<View onClick={() => dispatch(ingredientCheckToggle({ id: props.recipeId, productName: ingredient.productName }))} >
|
||||
<TouchableOpacity onPress={() => dispatch(ingredientCheckToggle({ id: props.recipeId, productName: ingredient.productName }))} >
|
||||
<CheckButton checked={ingredient.checked} />
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</Wrapper>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -11,22 +11,22 @@ import { removeRecipe } from "../../../redux/slices/recipesSlice"
|
||||
import { PlusIcon, WrapperAddItem } from "../../GroceryList/groceries/styles/buttons"
|
||||
import ModalAddIngredients from "../../modals/recipes/ModalAddIngredients"
|
||||
import { Alert } from "react-native"
|
||||
import { useNavigation } from "@react-navigation/core";
|
||||
import { TouchableOpacity } from "react-native-gesture-handler";
|
||||
|
||||
export const AddRecipeButton = () => {
|
||||
|
||||
let navigation = useNavigation()
|
||||
return (
|
||||
// < Link to="/recipes/addRecipe">
|
||||
<WrapperAddRecipe>
|
||||
<IconPlus />
|
||||
</WrapperAddRecipe>
|
||||
// </Link>
|
||||
<WrapperAddRecipe onPress={() => navigation.navigate('AddRecipe', {id: ""})}>
|
||||
<IconPlus />
|
||||
</WrapperAddRecipe>
|
||||
)
|
||||
}
|
||||
|
||||
export const AddIngredientsButton = (props) => {
|
||||
const [visible, setVisible] = useState(false)
|
||||
return (<>
|
||||
<WrapperAddItem style={{ bottom: 10 }} onPress={()=>setVisible(true)}>
|
||||
<WrapperAddItem style={{ bottom: 10 }} onPress={() => setVisible(true)}>
|
||||
<PlusIcon />
|
||||
</WrapperAddItem>
|
||||
<ModalAddIngredients id={props.id} visible={visible} closeModal={() => setVisible(false)} />
|
||||
@@ -37,6 +37,7 @@ export const AddIngredientsButton = (props) => {
|
||||
export const OptionsButtonRecipe = (props) => {
|
||||
const dispatch = useDispatch()
|
||||
const [toggled, setToggled] = useState(false)
|
||||
const navigation = useNavigation()
|
||||
const handleRemove = () => {
|
||||
Alert.alert(
|
||||
"Warning",
|
||||
@@ -45,6 +46,7 @@ export const OptionsButtonRecipe = (props) => {
|
||||
{ text: "Cancel", },
|
||||
{
|
||||
text: "Remove", onPress: () => {
|
||||
navigation.goBack()
|
||||
dispatch(removeRecipe(props.id))
|
||||
}
|
||||
}
|
||||
@@ -54,11 +56,12 @@ export const OptionsButtonRecipe = (props) => {
|
||||
}
|
||||
return (
|
||||
<WrapperOptions toggled={toggled} >
|
||||
<IconOptions toggled={toggled} onClick={() => setToggled(!toggled)} />
|
||||
<WrapperOptionButtons toggled={toggled}>
|
||||
<IconRemove onClick={() => handleRemove()} />
|
||||
<IconEdit onClick={() => history.push("/recipes/addRecipe/" + props.id)} />
|
||||
</WrapperOptionButtons>
|
||||
<TouchableOpacity onPress={() => handleRemove()} >
|
||||
<IconRemove />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity onPress={() => navigation.navigate("AddRecipe", { id: props.id })} >
|
||||
<IconEdit />
|
||||
</TouchableOpacity>
|
||||
</WrapperOptions>
|
||||
)
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { View } from "react-native"
|
||||
import { TouchableOpacity, View } from "react-native"
|
||||
import { useSelector } from "react-redux"
|
||||
|
||||
import { WrapperIngredient, WrapperIngredientLeft, TagCircle, IngredientName, IngredientPortion, IngredientAmount, IconEdit, IconRemove } from './styles/ingredient'
|
||||
@@ -12,12 +12,11 @@ export const Ingredient = (props) => {
|
||||
<WrapperIngredient>
|
||||
<WrapperIngredientLeft>
|
||||
<TagCircle tagColor={tag.color} />
|
||||
<IngredientPortion>{ingredient.portion}</IngredientPortion>
|
||||
<IngredientPortion>{ingredient.amount * multiplier} x ({ingredient.portion})</IngredientPortion>
|
||||
<IngredientName>{ingredient.productName}</IngredientName>
|
||||
</WrapperIngredientLeft>
|
||||
<IngredientAmount>{ingredient.amount*multiplier}</IngredientAmount>
|
||||
{props.EditIngredient && <IconEdit onClick={() => props.EditIngredient(props.index)} />}
|
||||
{props.RemoveIngredient && <IconRemove onClick={() => props.RemoveIngredient(props.index)} />}
|
||||
{props.EditIngredient && <TouchableOpacity onPress={() => props.EditIngredient(props.index)} ><IconEdit /></TouchableOpacity>}
|
||||
{props.RemoveIngredient && <TouchableOpacity onPress={() => props.RemoveIngredient(props.index)} ><IconRemove /></TouchableOpacity>}
|
||||
</WrapperIngredient>
|
||||
)
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
import React from 'react';
|
||||
import { useState } from "react"
|
||||
import { View } from "react-native"
|
||||
import { Text, View } from "react-native"
|
||||
import { useSelector } from "react-redux"
|
||||
import { selectAllProducts } from "../../../redux/slices/groceryList/productsSlice"
|
||||
import Dropdown from "../../Dropdown"
|
||||
import { Input } from "../../modals/styles/modal"
|
||||
import { ButtonText, Input } from "../../modals/styles/modal"
|
||||
import { Ingredient } from "./Ingredient"
|
||||
import {
|
||||
WrapperIngredients, InputIngredientName, InputAmount, InputPortion, Button
|
||||
WrapperIngredients, InputIngredientName, InputAmount, InputPortion, Button, Row, TitleIngredients, WrapperDropdown
|
||||
} from "./styles/inputs"
|
||||
export const Ingredients = (props) => {
|
||||
let ingredients = props.ingredients
|
||||
@@ -67,54 +67,56 @@ export const Ingredients = (props) => {
|
||||
let product = products.find((product) => product.productName === pName);
|
||||
setIngredientName(product.productName)
|
||||
setTag(product.tag)
|
||||
setPrice(product.price)
|
||||
setPrice(product.price && product.price.toString())
|
||||
}
|
||||
return (
|
||||
<WrapperIngredients>
|
||||
<h2>Ingredients</h2>
|
||||
<View id="row">
|
||||
<TitleIngredients>Ingredients</TitleIngredients>
|
||||
<Row>
|
||||
<View style={{ width: '100%' }}>
|
||||
{IngredientList}
|
||||
<InputIngredientName onFocus={() => setFocused(true)} onBlur={() => { setTimeout(() => { setFocused(false) }, 100) }}
|
||||
type="text"
|
||||
<InputIngredientName onFocus={() => setFocused(true)} onEndEditing={() => setFocused(false)}
|
||||
value={ingredientName}
|
||||
onChange={(text) => setIngredientName(text.target.value)}
|
||||
onChangeText={(text) => setIngredientName(text)}
|
||||
placeholder="Name ingredient" />
|
||||
{focused &&
|
||||
<Dropdown array={products.map(product => product.productName)} text={ingredientName} setElement={handleDropdownPress} />}
|
||||
<View id="row">
|
||||
<View>
|
||||
<Input
|
||||
onFocus={() => setFocusedTag(true)} onBlur={() => { setTimeout(() => { setFocusedTag(false) }, 100) }}
|
||||
style={{ marginLeft: 0 }}
|
||||
type="text"
|
||||
value={tag}
|
||||
onChange={(text) => setTag(text.target.value)}
|
||||
placeholder="tag" />
|
||||
{focusedTag &&
|
||||
<Dropdown array={tags.map(t => t.tagName)} text={tag} setElement={setTag} />}
|
||||
</View>
|
||||
|
||||
<WrapperDropdown>
|
||||
{focused &&
|
||||
<Dropdown array={products.map(product => product.productName)} text={ingredientName} setElement={handleDropdownPress} />}
|
||||
</WrapperDropdown>
|
||||
<Row>
|
||||
<Input
|
||||
type="number"
|
||||
onFocus={() => setFocusedTag(true)} onEndEditing={() => setFocusedTag(false)}
|
||||
style={{ marginLeft: 0 }}
|
||||
type="text"
|
||||
value={tag}
|
||||
onChangeText={(text) => setTag(text)}
|
||||
placeholder="tag" />
|
||||
<Input
|
||||
keyboardType={"number-pad"}
|
||||
value={price}
|
||||
onChange={(text) => setPrice(text.target.value)}
|
||||
onChangeText={(text) => setPrice(text)}
|
||||
placeholder="Price" />
|
||||
</Row>
|
||||
<View style={{marginTop: 0}}>
|
||||
{focusedTag &&
|
||||
<Dropdown array={tags.map(t => t.tagName)} text={tag} setElement={setTag} />}
|
||||
</View>
|
||||
<View id="row">
|
||||
<Row>
|
||||
<InputAmount
|
||||
type="number"
|
||||
keyboardType={"number-pad"}
|
||||
value={amount}
|
||||
onChange={(text) => setAmount(text.target.value)}
|
||||
onChangeText={(text) => setAmount(text)}
|
||||
placeholder="amt." />
|
||||
<InputPortion
|
||||
type="text"
|
||||
value={portion}
|
||||
onChange={(text) => setPortion(text.target.value)}
|
||||
onChangeText={(text) => setPortion(text)}
|
||||
placeholder="Portion (1/2 teaspoon, ...)" />
|
||||
<Button onClick={submitIngredient} >{index === -1 ? 'Add' : 'Edit'}</Button>
|
||||
</View>
|
||||
<Button onPress={submitIngredient} ><ButtonText>{index === -1 ? 'Add' : 'Edit'}</ButtonText></Button>
|
||||
</Row>
|
||||
</View>
|
||||
</View>
|
||||
</WrapperIngredients>
|
||||
</Row >
|
||||
</WrapperIngredients >
|
||||
)
|
||||
}
|
||||
@@ -15,30 +15,8 @@ export const WrapperAddRecipe = styled(Button)`
|
||||
export const IconPlus = () => <MaterialCommunityIcons name="plus" color={theme.colors.textB2} size={60} />
|
||||
|
||||
export const WrapperOptions = styled(View)`
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
`
|
||||
|
||||
export const WrapperOptionButtons = styled(View)`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
align-items: center;
|
||||
top: 60px;
|
||||
width: 55px;
|
||||
right: 0px;
|
||||
height: ${props => props.toggled ? css`100px` : css`0px` };
|
||||
background-color: ${({theme}) => theme.colors.dp00 +'bb'};
|
||||
border-bottom-left-radius: 8px;
|
||||
overflow: hidden;
|
||||
`
|
||||
const Options = () => <MaterialCommunityIcons name="cog-outline" color={theme.colors.textW2} size={40} />
|
||||
|
||||
export const IconOptions = styled(Options)`
|
||||
margin-right: 5px;
|
||||
margin-top: 10px;
|
||||
transform: rotate(${props => props.toggled ? css`135deg` : css`0deg` });
|
||||
flex-direction: row;
|
||||
`
|
||||
|
||||
const Remove = () => <MaterialCommunityIcons name="trash-can-outline" color={theme.colors.error} size={40} />
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import React from 'react';
|
||||
import { Text, View } from "react-native"
|
||||
import styled from 'styled-components'
|
||||
|
||||
@@ -9,7 +10,7 @@ export const WrapperIngredient = styled(View)`
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
`
|
||||
export const WrapperIngredientLeft = styled(View)`
|
||||
@@ -29,32 +30,25 @@ export const TagCircle = styled(View)`
|
||||
export const IngredientName = styled(Text)`
|
||||
margin-left: 10px;
|
||||
width: 60%;
|
||||
font-size: ${({ theme }) => theme.fontSizes.fontS}px;
|
||||
font-size: 18px;
|
||||
/* overflow-wrap: break-word; */
|
||||
color: ${props => props.theme.colors.textW4};
|
||||
`
|
||||
export const IngredientPortion = styled(Text)`
|
||||
width: 35%;
|
||||
font-size: ${({ theme }) => theme.fontSizes.fontS}px;
|
||||
font-size: 18px;
|
||||
font-weight: 900;
|
||||
/* word-break: break-all; */
|
||||
/* overflow-wrap: break-word; */
|
||||
color: ${props => props.theme.colors.textW5};
|
||||
`
|
||||
export const IngredientAmount = styled(Text)`
|
||||
max-width: 12%;
|
||||
margin-right: 48px;
|
||||
font-size: ${({theme}) => theme.fontSizes.fontS}px;
|
||||
/* overflow-wrap: break-word; */
|
||||
color: ${props => props.theme.colors.textW5};
|
||||
`
|
||||
const Remove = () => <MaterialCommunityIcons name="trash-can-outline" color={theme.colors.error + 'aa'} size={theme.fontSizes.fontS} />
|
||||
const Remove = () => <MaterialCommunityIcons name="trash-can-outline" color={theme.colors.error + 'aa'} size={theme.fontSizes.fontM} />
|
||||
|
||||
export const IconRemove = styled(Remove)`
|
||||
position:absolute;
|
||||
right: 0px;
|
||||
`
|
||||
const Edit = () => <MaterialCommunityIcons name="pencil-outline" color={theme.colors.textW5} size={theme.fontSizes.fontS} />
|
||||
const Edit = () => <MaterialCommunityIcons name="pencil-outline" color={theme.colors.textW5} size={theme.fontSizes.fontM} />
|
||||
|
||||
export const IconEdit = styled(Edit)`
|
||||
position:absolute;
|
||||
|
||||
@@ -1,34 +1,49 @@
|
||||
import { Text, TextInput, View } from "react-native"
|
||||
import styled from "styled-components"
|
||||
import { Input } from "../../../modals/styles/modal"
|
||||
export const WrapperIngredients = styled(View)`
|
||||
margin-top: 10px;
|
||||
width:100%;
|
||||
border-left: solid ${props => props.theme.colors.primary + '55'} 1px;
|
||||
border-left-color: ${props => props.theme.colors.primary + '55'} ;
|
||||
border-left-width: 1px;
|
||||
padding-left: 5px;
|
||||
/* #row{
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex:1;
|
||||
width:100%;
|
||||
} */
|
||||
`
|
||||
export const InputIngredientName = styled(TextInput)`
|
||||
margin-top: 10px;
|
||||
font-size: ${({theme}) => theme.fontSizes.fontS}px;
|
||||
border-bottom-color: ${props => props.theme.colors.primary + 'aa'};
|
||||
export const Row = styled(View)`
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width:100%;
|
||||
`
|
||||
export const WrapperDropdown = styled(View)`
|
||||
margin-top: -10px;
|
||||
margin-bottom: 10px;
|
||||
`
|
||||
export const TitleIngredients = styled(Text)`
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
color: ${props => props.theme.colors.textW2};
|
||||
`
|
||||
export const InputIngredientName = styled(Input)`
|
||||
margin-left: 0px;
|
||||
padding-right: 0px;
|
||||
|
||||
margin: 10px 0px;
|
||||
border-bottom-width: 1px;
|
||||
width:100%;
|
||||
`
|
||||
export const InputAmount = styled(TextInput)`
|
||||
font-size: ${({theme}) => theme.fontSizes.fontS}px;
|
||||
border-bottom-color: ${props => props.theme.colors.primary + 'aa'};
|
||||
export const InputAmount = styled(Input)`
|
||||
margin-left: 0px;
|
||||
padding-right: 0px;
|
||||
margin-top: 10px;
|
||||
|
||||
border-bottom-width: 1px;
|
||||
width: 50px;
|
||||
`
|
||||
export const InputPortion = styled(TextInput)`
|
||||
font-size: ${({theme}) => theme.fontSizes.fontS}px;
|
||||
border-bottom-color: ${props => props.theme.colors.primary + 'aa'};
|
||||
export const InputPortion = styled(Input)`
|
||||
margin-left: 0px;
|
||||
padding-right: 0px;
|
||||
margin-top: 10px;
|
||||
|
||||
border-bottom-width: 1px;
|
||||
width: 60%;
|
||||
margin-left: 10px;
|
||||
@@ -39,5 +54,5 @@ export const Button = styled(Text)`
|
||||
bottom: -8px;
|
||||
color: ${props => props.theme.colors.primary + 'bb'};
|
||||
font-weight: bold;
|
||||
font-size: ${({theme}) => theme.fontSizes.fontS}px;
|
||||
font-size: ${({ theme }) => theme.fontSizes.fontS}px;
|
||||
`
|
||||
@@ -13,6 +13,7 @@ export const WrapperRecipeCard = styled(TouchableOpacity)`
|
||||
width: 48%;
|
||||
background-color: ${props => props.theme.colors.dp01 + 'dd'};
|
||||
border-radius: 20px;
|
||||
margin-bottom: 4px;
|
||||
`
|
||||
|
||||
export const RecipeName = styled(Text)`
|
||||
|
||||
@@ -1,57 +1,66 @@
|
||||
import React from 'react';
|
||||
import { Text, View } from 'react-native'
|
||||
import { Button, ScrollView, Text, View } from 'react-native'
|
||||
import * as ImagePicker from 'expo-image-picker';
|
||||
//components
|
||||
import Header from "../../components/Header"
|
||||
import { ArrowBack } from "../styles/page";
|
||||
import { Ingredients } from "../../components/recipes/addRecipe/Inputs";
|
||||
//styling
|
||||
import { Wrapper, WrapperRecipe, Input, InputInstructions, IconRecipe, IconPot, IconMeal, IconImage, IconCheck } from "./styles/addRecipe"
|
||||
import { Wrapper, WrapperRecipe, Input, InputInstructions, IconRecipe, IconPot, IconMeal, IconImage, IconCheck, AddImageButton, ButtonText, SubmitButton } from "./styles/addRecipe"
|
||||
import { useState } from "react";
|
||||
import { addRecipe, findRecipeById, updateRecipe } from "../../redux/slices/recipesSlice";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { StyledImage } from "./styles/recipe";
|
||||
import HeaderPadding from '../../components/Header';
|
||||
import { Row } from '../../components/recipes/addRecipe/styles/inputs';
|
||||
import { useNavigation } from '@react-navigation/core';
|
||||
|
||||
const AddRecipe = (props) => {
|
||||
const id = props.route.params.id
|
||||
|
||||
const navigation = useNavigation()
|
||||
|
||||
const AddRecipe = () => {
|
||||
let { id } = useParams()
|
||||
const foundRecipe = useSelector(state => findRecipeById(state, id))
|
||||
let recipe = foundRecipe ? foundRecipe : { name: '', prepTime: '', servings: '', image: '', ingredients: [], instructions: '' }
|
||||
const dispatch = useDispatch()
|
||||
|
||||
const [name, setName] = useState(recipe.name)
|
||||
const [prepTime, setPrepTime] = useState(recipe.prepTime)
|
||||
const [servings, setServings] = useState(recipe.servings)
|
||||
const [prepTime, setPrepTime] = useState(recipe.prepTime && recipe.prepTime.toString())
|
||||
const [servings, setServings] = useState(recipe.servings && recipe.servings.toString())
|
||||
const [image, setImage] = useState(recipe.image)
|
||||
const [ingredients, setIngredients] = useState(recipe.ingredients)
|
||||
const [instructions, setInstructions] = useState(recipe.instructions)
|
||||
|
||||
const handleImageInput = (input) => {
|
||||
if (input.target.files && input.target.files[0] && input.target.files[0].size < 1000000) {
|
||||
let reader = new FileReader()
|
||||
reader.onload = function (e) {
|
||||
setImage(e.target.result)
|
||||
};
|
||||
reader.readAsDataURL(input.target.files[0])
|
||||
const pickImage = async () => {
|
||||
let result = await ImagePicker.launchImageLibraryAsync({
|
||||
mediaTypes: ImagePicker.MediaTypeOptions.All,
|
||||
allowsEditing: true,
|
||||
aspect: [4, 3],
|
||||
quality: 1,
|
||||
});
|
||||
|
||||
console.log(result);
|
||||
|
||||
if (!result.cancelled) {
|
||||
setImage(result.uri);
|
||||
}
|
||||
else {
|
||||
alert("That file is too big! Choose an image with a size lower than 1MB")
|
||||
}
|
||||
}
|
||||
};
|
||||
const submitRecipe = () => {
|
||||
if (name && ingredients && instructions) {
|
||||
foundRecipe ? dispatch(updateRecipe({ _id: foundRecipe._id, name, prepTime: Number(prepTime), servings: Number(servings), image, ingredients, instructions }))
|
||||
: dispatch(addRecipe({ name, prepTime: Number(prepTime), servings: Number(servings), image, ingredients, instructions }))
|
||||
console.log(typeof (image))
|
||||
navigation.goBack()
|
||||
}
|
||||
else {
|
||||
alert("You should add a name, at least one ingredient and the instructions")
|
||||
}
|
||||
}
|
||||
const handleInput = (event) => {
|
||||
let lastChar = event.target.value.substr(-1).charCodeAt(0);
|
||||
let penultimateChar = event.target.value.substr(-2).charCodeAt(0);
|
||||
const handleInput = (text) => {
|
||||
let lastChar = text.substr(-1).charCodeAt(0);
|
||||
let penultimateChar = text.substr(-2).charCodeAt(0);
|
||||
|
||||
if (instructions === '') {
|
||||
setInstructions("- " + event.target.value)
|
||||
setInstructions("- " + text)
|
||||
return
|
||||
}
|
||||
else if (penultimateChar === 10 && lastChar === 45) {
|
||||
@@ -59,55 +68,56 @@ const AddRecipe = () => {
|
||||
return
|
||||
}
|
||||
else if (lastChar === 10) {
|
||||
setInstructions(event.target.value + "- ")
|
||||
setInstructions(text + "- ")
|
||||
return
|
||||
}
|
||||
setInstructions(event.target.value)
|
||||
setInstructions(text)
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<HeaderPadding/>
|
||||
return (<>
|
||||
<ScrollView nestedScrollEnabled={true} keyboardShouldPersistTaps={'always'}>
|
||||
<HeaderPadding />
|
||||
{image != "" && <StyledImage source={{ uri: image }} alt="Recipe" />}
|
||||
<Wrapper >
|
||||
{image && <StyledImage source={image} alt="Recipe" />}
|
||||
<WrapperRecipe>
|
||||
<View id="row">
|
||||
<Row>
|
||||
<IconRecipe />
|
||||
<Input
|
||||
type="text"
|
||||
value={name}
|
||||
onChange={(text) => setName(text.target.value)}
|
||||
onChangeText={(text) => setName(text)}
|
||||
placeholder="Recipe name" />
|
||||
</View>
|
||||
<View id="row">
|
||||
</Row>
|
||||
<Row>
|
||||
<IconPot />
|
||||
<Input
|
||||
type="number"
|
||||
keyboardType={"number-pad"}
|
||||
value={prepTime}
|
||||
onChange={(text) => setPrepTime(text.target.value)}
|
||||
onChangeText={(text) => setPrepTime(text)}
|
||||
placeholder="Prep time (min)" />
|
||||
<IconMeal />
|
||||
<Input
|
||||
type="number"
|
||||
keyboardType={"number-pad"}
|
||||
value={servings}
|
||||
onChange={(text) => setServings(text.target.value)}
|
||||
onChangeText={(text) => setServings(text)}
|
||||
placeholder="Servings" />
|
||||
</View>
|
||||
<View id="row">
|
||||
<IconImage />
|
||||
<Input
|
||||
style={{ borderBottom: 'none' }}
|
||||
type="file" accept="image/*"
|
||||
onChange={input => handleImageInput(input)} />
|
||||
</View>
|
||||
</Row>
|
||||
<AddImageButton onPress={pickImage}
|
||||
style={{ borderBottom: 'none' }} >
|
||||
<ButtonText>Add Image</ButtonText>
|
||||
</AddImageButton>
|
||||
<Ingredients ingredients={ingredients} setIngredients={setIngredients} />
|
||||
<InputInstructions
|
||||
type="text"
|
||||
minHeight={40}
|
||||
multiline={true}
|
||||
value={instructions}
|
||||
onChange={(text) => handleInput(text)}
|
||||
onChangeText={(text) => handleInput(text)}
|
||||
placeholder='Instructions' />
|
||||
</WrapperRecipe>
|
||||
</Wrapper>
|
||||
</>
|
||||
</ScrollView>
|
||||
{name != "" && ingredients != "" && instructions != "" && <SubmitButton onPress={submitRecipe} >
|
||||
<IconCheck />
|
||||
</SubmitButton>}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ import { OptionsButtonRecipe, AddIngredientsButton } from "../../components/reci
|
||||
import { ScrollView, Text, View } from "react-native"
|
||||
import HeaderPadding from "../../components/Header"
|
||||
|
||||
const Recipe = (props) => {
|
||||
const id = props.route.params.id
|
||||
const Recipe = ({route, navigation}) => {
|
||||
const id = route.params.id
|
||||
const recipe = useSelector(state => findRecipeById(state, id))
|
||||
const IngredientList = recipe.ingredients.map((ingredient, index) => {
|
||||
return (<Ingredient ingredient={ingredient} index={index} key={index} />)
|
||||
@@ -25,12 +25,21 @@ const Recipe = (props) => {
|
||||
<InstructionText>{instruction}</InstructionText>
|
||||
</InstructionWrapper>)
|
||||
})
|
||||
|
||||
React.useLayoutEffect(() => {
|
||||
navigation.setOptions({
|
||||
headerRight: () => (
|
||||
<OptionsButtonRecipe id={id} />
|
||||
),
|
||||
});
|
||||
}, [navigation]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<HeaderPadding/>
|
||||
{recipe.image != "" && <StyledImage source={{ uri: recipe.image }} />}
|
||||
<ScrollView>
|
||||
|
||||
<Wrapper >
|
||||
{recipe.image != "" && <StyledImage source={{ uri: recipe.image }} />}
|
||||
<WrapperRecipe>
|
||||
<Title>{recipe.name}</Title>
|
||||
<Hr />
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import React from 'react';
|
||||
import { Image, Text, TextInput, View } from "react-native"
|
||||
import { Image, Text, TextInput, TouchableOpacity, View } from "react-native"
|
||||
import styled from 'styled-components'
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import theme from "../../../styles/theme";
|
||||
import { Button } from '../../../styles/componentBlueprints';
|
||||
|
||||
export const Wrapper = styled(View)`
|
||||
display: flex;
|
||||
@@ -38,35 +39,49 @@ export const Input = styled(TextInput)`
|
||||
color: ${props => props.theme.colors.textW1};
|
||||
border-bottom-color: ${props => props.theme.colors.primary + 'aa'};
|
||||
border-bottom-width: 1px;
|
||||
font-size: ${({theme}) => theme.fontSizes.fontS}px;
|
||||
font-size: ${({theme}) => theme.fontSizes.fontM}px;
|
||||
|
||||
width: 100%;
|
||||
`
|
||||
|
||||
export const InputInstructions = styled(Text)`
|
||||
export const InputInstructions = styled(TextInput)`
|
||||
margin-top: 30px;
|
||||
padding: 5px;
|
||||
|
||||
color: ${props => props.theme.colors.textW1};
|
||||
border-bottom-color: ${props => props.theme.colors.primary + 'aa'};
|
||||
border-bottom-width: 1px;
|
||||
font-size: ${({theme}) => theme.fontSizes.fontS}px;
|
||||
min-height: 600px;
|
||||
font-size: ${({theme}) => theme.fontSizes.fontM}px;
|
||||
width: 100%;
|
||||
`
|
||||
export const StyledImage = styled(Image)`
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
export const AddImageButton = styled(TouchableOpacity)`
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
align-self: center;
|
||||
margin: 10px;
|
||||
width: 140px;
|
||||
height: 40px;
|
||||
background-color:${props => props.theme.colors.primary};
|
||||
border-radius: 15px;
|
||||
`
|
||||
export const IconRecipe = () => <MaterialCommunityIcons name="pasta" color={theme.colors.primaryVar} size={theme.fontSizes.fontM} />
|
||||
export const ButtonText = styled(Text)`
|
||||
color: ${props => props.theme.colors.textB1};
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
`
|
||||
export const SubmitButton = styled(Button)`
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
bottom: 10px;
|
||||
background-color: ${({theme}) => theme.colors.primary};
|
||||
`
|
||||
export const IconRecipe = () => <MaterialCommunityIcons name="pasta" color={theme.colors.primaryVar} size={theme.fontSizes.fontL} />
|
||||
|
||||
export const IconPot = () => <MaterialCommunityIcons name="pot-steam" color={theme.colors.primaryVar} size={theme.fontSizes.fontM} />
|
||||
export const IconPot = () => <MaterialCommunityIcons name="pot-steam" color={theme.colors.primaryVar} size={theme.fontSizes.fontL} />
|
||||
|
||||
export const IconMeal = () => <MaterialCommunityIcons name="pot-steam" color={theme.colors.primaryVar} size={theme.fontSizes.fontM} />
|
||||
export const IconMeal = () => <MaterialCommunityIcons name="pot-steam" color={theme.colors.primaryVar} size={theme.fontSizes.fontL} />
|
||||
|
||||
export const IconImage = () => <MaterialCommunityIcons name="food" color={theme.colors.primaryVar} size={theme.fontSizes.fontM} />
|
||||
|
||||
const Check = () => <MaterialCommunityIcons name="check" color={theme.colors.textB3} size={theme.fontSizes.fontL} />
|
||||
const Check = () => <MaterialCommunityIcons name="check" color={theme.colors.textB3} size={50} />
|
||||
|
||||
export const IconCheck = styled(Check)`
|
||||
margin-right: 10px;
|
||||
|
||||
@@ -47,6 +47,7 @@ export const InstructionNumber = styled(Text)`
|
||||
`
|
||||
|
||||
export const StyledImage = styled(Image)`
|
||||
margin-top: -110px;
|
||||
height: 200px;
|
||||
width: 100%;
|
||||
`
|
||||
|
||||
@@ -14,8 +14,8 @@ export const fetchRecipes = createAsyncThunk('recipes/fetchRecipes', async () =>
|
||||
})
|
||||
|
||||
export const addRecipe = createAsyncThunk('recipes/addRecipe', async (payload) => {
|
||||
const size = new TextEncoder().encode(JSON.stringify(payload)).length
|
||||
console.log(size)
|
||||
// const size = new TextEncoder().encode(JSON.stringify(payload)).length
|
||||
// console.log(size)
|
||||
const requestOptions = {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
|
||||
40
src/styles/animations.js
Normal file
40
src/styles/animations.js
Normal file
@@ -0,0 +1,40 @@
|
||||
export const toggleOnAnim = {
|
||||
0.0: {
|
||||
scale: 1
|
||||
},
|
||||
0.2: {
|
||||
scale: 0.94
|
||||
},
|
||||
0.4: {
|
||||
scale: 1.02
|
||||
},
|
||||
0.6: {
|
||||
scale: 0.99
|
||||
},
|
||||
0.8: {
|
||||
scale: 1.005
|
||||
},
|
||||
1: {
|
||||
scale: 1
|
||||
}
|
||||
};
|
||||
export const toggleOffAnim = {
|
||||
0.0: {
|
||||
scale: 1
|
||||
},
|
||||
0.2: {
|
||||
scale: 0.94
|
||||
},
|
||||
0.4: {
|
||||
scale: 1.02
|
||||
},
|
||||
0.6: {
|
||||
scale: 0.99
|
||||
},
|
||||
0.8: {
|
||||
scale: 1.0051
|
||||
},
|
||||
1: {
|
||||
scale: 1
|
||||
}
|
||||
};
|
||||
@@ -5,6 +5,8 @@ import styled, { css } from 'styled-components'
|
||||
import LightenDarken from '../functions'
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import theme from "./theme";
|
||||
import * as Animatable from 'react-native-animatable'
|
||||
import { toggleOffAnim, toggleOnAnim } from "./animations";
|
||||
//standard button layout
|
||||
export const Button = styled(TouchableOpacity)`
|
||||
box-shadow: ${({ theme }) => theme.colors.shadow};
|
||||
@@ -15,7 +17,7 @@ export const Button = styled(TouchableOpacity)`
|
||||
width: 65px;
|
||||
border-radius: 35px;
|
||||
`
|
||||
const CheckButtonWrapper = styled(View)`
|
||||
const CheckButtonWrapper = styled(Animatable.View)`
|
||||
display:flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@@ -29,14 +31,14 @@ const CheckButtonWrapper = styled(View)`
|
||||
`
|
||||
|
||||
export const CheckButton = (props) => {
|
||||
return (
|
||||
<CheckButtonWrapper checked={props.checked} >
|
||||
return (
|
||||
<CheckButtonWrapper animation={props.checked ? toggleOnAnim : toggleOffAnim} checked={props.checked} >
|
||||
<MaterialCommunityIcons name="check" color={theme.colors.dp00} size={25} />
|
||||
</CheckButtonWrapper>
|
||||
)
|
||||
</CheckButtonWrapper>
|
||||
)
|
||||
}
|
||||
|
||||
//load anim
|
||||
export const LoadAnimation = () => {
|
||||
return (<View style={{ backgroundColor: "red", width: 100, height: 100 }} />)
|
||||
return (<View style={{ backgroundColor: "red", width: 100, height: 100 }} />)
|
||||
}
|
||||
43
yarn.lock
43
yarn.lock
@@ -719,7 +719,7 @@
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.14.5"
|
||||
|
||||
"@babel/plugin-transform-object-assign@^7.0.0", "@babel/plugin-transform-object-assign@^7.10.4":
|
||||
"@babel/plugin-transform-object-assign@^7.0.0":
|
||||
version "7.14.5"
|
||||
resolved "https://registry.npmjs.org/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.14.5.tgz"
|
||||
integrity sha512-lvhjk4UN9xJJYB1mI5KC0/o1D5EcJXdbhVe+4fSk08D6ZN+iuAIs7LJC+71h8av9Ew4+uRq9452v9R93SFmQlQ==
|
||||
@@ -2605,6 +2605,15 @@ expo-font@~10.0.3:
|
||||
expo-modules-core "~0.4.4"
|
||||
fontfaceobserver "^2.1.0"
|
||||
|
||||
expo-image-picker@^11.0.3:
|
||||
version "11.0.3"
|
||||
resolved "https://registry.yarnpkg.com/expo-image-picker/-/expo-image-picker-11.0.3.tgz#c0b6cb9b5fa027f1bd1879a879fe13157f31ac94"
|
||||
integrity sha512-s7nXB+hop5htcETlSvtPhEGE6RM4BX0G2e6mhr2SjJdJPAFn+hY7R3vCGBFMtxV11Gjzr0D1w2y9gDqhOj0GKg==
|
||||
dependencies:
|
||||
"@expo/config-plugins" "^4.0.2"
|
||||
expo-modules-core "~0.4.4"
|
||||
uuid "7.0.2"
|
||||
|
||||
expo-keep-awake@~10.0.0:
|
||||
version "10.0.0"
|
||||
resolved "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-10.0.0.tgz"
|
||||
@@ -4147,11 +4156,6 @@ mkdirp@^0.5.1:
|
||||
dependencies:
|
||||
minimist "^1.2.5"
|
||||
|
||||
mockdate@^3.0.2:
|
||||
version "3.0.5"
|
||||
resolved "https://registry.yarnpkg.com/mockdate/-/mockdate-3.0.5.tgz#789be686deb3149e7df2b663d2bc4392bc3284fb"
|
||||
integrity sha512-iniQP4rj1FhBdBYS/+eQv7j1tadJ9lJtdzgOpvsOHng/GbcDh2Fhdeq+ZRldrPYdXvCyfFUmFeEwEGXZB5I/AQ==
|
||||
|
||||
ms@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz"
|
||||
@@ -4662,6 +4666,13 @@ react-native-animatable@1.3.3:
|
||||
dependencies:
|
||||
prop-types "^15.7.2"
|
||||
|
||||
react-native-animatable@^1.3.3:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/react-native-animatable/-/react-native-animatable-1.3.3.tgz#a13a4af8258e3bb14d0a9d839917e9bb9274ec8a"
|
||||
integrity sha512-2ckIxZQAsvWn25Ho+DK3d1mXIgj7tITkrS4pYDvx96WyOttSvzzFeQnM2od0+FUMzILbdHDsDEqZvnz1DYNQ1w==
|
||||
dependencies:
|
||||
prop-types "^15.7.2"
|
||||
|
||||
react-native-codegen@^0.0.6:
|
||||
version "0.0.6"
|
||||
resolved "https://registry.npmjs.org/react-native-codegen/-/react-native-codegen-0.0.6.tgz"
|
||||
@@ -4690,16 +4701,6 @@ react-native-modal@^13.0.0:
|
||||
prop-types "^15.6.2"
|
||||
react-native-animatable "1.3.3"
|
||||
|
||||
react-native-reanimated@~2.2.0:
|
||||
version "2.2.3"
|
||||
resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-2.2.3.tgz#edecfe477ad9efac6f006f7e1194e8c9aa4fc6d5"
|
||||
integrity sha512-d+BV39Jp4Om0ZkgVjop672/004ytlTfDT01EloO3HFZs9wR2QTuCjekq8yi3xl0G2xGZKd4DXhvqabIa7OnMYA==
|
||||
dependencies:
|
||||
"@babel/plugin-transform-object-assign" "^7.10.4"
|
||||
fbjs "^3.0.0"
|
||||
mockdate "^3.0.2"
|
||||
string-hash-64 "^1.0.3"
|
||||
|
||||
react-native-safe-area-context@3.3.2:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/react-native-safe-area-context/-/react-native-safe-area-context-3.3.2.tgz#9549a2ce580f2374edb05e49d661258d1b8bcaed"
|
||||
@@ -5357,11 +5358,6 @@ strict-uri-encode@^2.0.0:
|
||||
resolved "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz"
|
||||
integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY=
|
||||
|
||||
string-hash-64@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/string-hash-64/-/string-hash-64-1.0.3.tgz#0deb56df58678640db5c479ccbbb597aaa0de322"
|
||||
integrity sha512-D5OKWKvDhyVWWn2x5Y9b+37NUllks34q1dCDhk/vYcso9fmhs+Tl3KR/gE4v5UNj2UA35cnX4KdVVGkG1deKqw==
|
||||
|
||||
string-width@^4.1.0, string-width@^4.2.0:
|
||||
version "4.2.3"
|
||||
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
|
||||
@@ -5667,6 +5663,11 @@ utils-merge@1.0.1:
|
||||
resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz"
|
||||
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
|
||||
|
||||
uuid@7.0.2:
|
||||
version "7.0.2"
|
||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.2.tgz#7ff5c203467e91f5e0d85cfcbaaf7d2ebbca9be6"
|
||||
integrity sha512-vy9V/+pKG+5ZTYKf+VcphF5Oc6EFiu3W8Nv3P3zIh0EqVI80ZxOzuPfe9EHjkFNvf8+xuTHVeei4Drydlx4zjw==
|
||||
|
||||
uuid@^3.3.2, uuid@^3.4.0:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz"
|
||||
|
||||
Reference in New Issue
Block a user