first commit

This commit is contained in:
2021-03-12 11:38:47 +01:00
commit b16d70314b
86 changed files with 23019 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
import React, { useState } from 'react';
import { StyleSheet, TouchableOpacity, View, Text, TextInput } from 'react-native';
//themes
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import { COLORS } from '../../themes/Colors';
//modals
import AddItemModal from './modals/AddItemModal';
//redux
import { useDispatch, useSelector } from 'react-redux';
import { toggleVisibility } from '../../redux/slices/groceryList/toggleSlice';
import { removeCheckedItems } from '../../redux/slices/groceryList/itemsSlice';
export const AddItemButton = () => {
const dispatch = useDispatch();
return (
<TouchableOpacity style={[styles.buttonContainer, styles.addItem]}
onPress={()=>dispatch(toggleVisibility('addItemModalVisible'))}>
<MaterialCommunityIcons name="cart-plus" color={COLORS.dp00} size={35} />
{/* pop-up screen */}
<AddItemModal/>
</TouchableOpacity>
);
}
export const AddNewRecipeButton = () => {
return (
<TouchableOpacity style={[styles.buttonContainer, styles.AddNewProduct, { backgroundColor: COLORS.primaryVar2 }]}
onPress={() => alert('hello')}>
<MaterialCommunityIcons name="file-document-edit-outline" color={COLORS.dp00} size={40} />
</TouchableOpacity>
);
}
export const PushItemsToStorageButton = () => {
return (
<TouchableOpacity style={[styles.buttonContainer, styles.AddNewRecipe, { backgroundColor: COLORS.actionSend }]}
onPress={() => alert('lol')}>
<MaterialCommunityIcons name="cloud-download-outline" color={COLORS.dp00} size={40} />
</TouchableOpacity>
);
}
export const RemoveItemsButton = () => {
const dispatch = useDispatch();
return (
<TouchableOpacity style={[styles.buttonContainer, styles.downloadList, { backgroundColor: COLORS.actionCancel }]}
onPress={() => dispatch(removeCheckedItems())}>
<MaterialCommunityIcons name="delete-forever-outline" color={COLORS.dp00} size={40} />
</TouchableOpacity>
);
}
const styles = StyleSheet.create({
buttonContainer: {
height: 60,
width: 60,
borderRadius: 60 / 2,
elevation: 10,
alignItems: 'center',
justifyContent: 'center',
},
addItem: {
backgroundColor: COLORS.primary,
},
AddNewProduct: {
backgroundColor: COLORS.primary,
},
AddNewRecipe: {
backgroundColor: COLORS.primary,
},
downloadList: {
backgroundColor: COLORS.primary,
},
});

View File

@@ -0,0 +1,219 @@
import React, { useRef, useEffect, useState } from 'react';
import { StyleSheet, Text, TouchableOpacity, View, Animated } from 'react-native';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
//themes
import { COLORS } from '../../themes/Colors';
//redux
import { useDispatch, useSelector } from 'react-redux';
import { checkToggle } from '../.././redux/slices/groceryList/itemsSlice';
export const ListedItem = (props) => {
//redux
const dispatch = useDispatch()
const products = useSelector(state => state.products)
const items = useSelector(state => state.items)
const tags = useSelector(state => state.tags)
let product;
const item = items.find((item) => item.productId === props.id);
if (products.find((product) => product.id === item.productId)) {
product = products.find((product) => product.id === item.productId);
}
else {
product = {
productName: props.id,
tag:'no-tag',
}
}
const dispatchAnim = () => {
dispatch(checkToggle(item.productId));
}
const tag = tags.find((tag)=>tag.tagName === product.tag);
const scaleAnimValue = useRef(new Animated.Value(0)).current; // animation start value
const colorAnimValue = useRef(new Animated.Value(0)).current; // animation start value
const checkAnimValue = useRef(new Animated.Value(0)).current; // animation start value
//animation:
useEffect(() => {
Animated.sequence([
Animated.timing(scaleAnimValue, {
toValue: 0.9,
duration: 150,
useNativeDriver: false,
}
),
Animated.spring(scaleAnimValue, {
toValue: 1,
friction: 4,
useNativeDriver: false,
},
)
]).start()
}, [item.checked])
//colors
useEffect(() => {
item.checked ? Animated.timing(colorAnimValue, {
toValue: 1,
duration: 200,
useNativeDriver: false,
}
).start()
:
Animated.timing(colorAnimValue, {
toValue: 0,
duration: 200,
useNativeDriver: false,
}
).start()
}, [item.checked])
//checkmark
useEffect(() => {
item.checked ? Animated.sequence([
Animated.delay(200),
Animated.spring(checkAnimValue, {
toValue: 1,
friction: 4,
useNativeDriver: true,
}),
]).start()
:
Animated.sequence([
Animated.delay(150),
Animated.timing(checkAnimValue, {
toValue: 0,
duration: 150,
useNativeDriver: true,
}),
]).start()
}, [item.checked])
const interpolateColor = colorAnimValue.interpolate({
inputRange: [0, 1],
outputRange: ['rgb(22, 26, 30)', 'rgb(62, 131, 98)']
});
return (
<View style={{ flex: 1, paddingLeft: 8, paddingRight: 8, flexDirection: 'row', alignItems: 'flex-start', justifyContent: 'space-between' }}>
<Animated.View style={[styles.listedItemStyle, {backgroundColor: tag.color + '33'},item.checked ? styles.listedItemChecked : {}, {
transform: [{
scaleX: scaleAnimValue
},
{
scaleY: scaleAnimValue
}
]
}]} >
<TouchableOpacity style={{}}
onPress={() => console.log(item.checked)}
onLongPress={() => dispatchAnim()}>
<Text style={styles.textItem}>{product.productName}</Text>
<View style={{ flex: 1, flexDirection: 'row', alignItems: 'flex-end' }}>
<Text style={styles.textAmount}>Amount: {item.amount}</Text>
<Text style={styles.textPerson}>For: {item.person}</Text>
</View>
{item.details ? <Text style={styles.textDetails}>Details: {item.details}</Text> : <View />}
</TouchableOpacity>
</Animated.View>
<TouchableOpacity style={[styles.checkButton, { flex: 1 }]} onPress={() => dispatchAnim()}>
<Animated.View style={[styles.checkmark, item.checked ? {
borderWidth: 0,
} : {}, {
backgroundColor: interpolateColor,
transform: [{
scaleX: scaleAnimValue
},
{
scaleY: scaleAnimValue
}
]
},]} >
<Animated.View style={[{
transform: [{
scaleX: checkAnimValue
},
{
scaleY: checkAnimValue
}
]
}]}>
<MaterialCommunityIcons name="check" color={COLORS.dp00} size={25} />
</Animated.View>
</Animated.View>
</TouchableOpacity>
</View>
);
}
const height = 30;
const styles = StyleSheet.create({
listedItemStyle: {
width: '90%',
marginBottom: height / 7,
borderRadius: height / 2,
padding: 2,
paddingBottom: 3,
backgroundColor: COLORS.dp03,
},
listedItemChecked: {
backgroundColor: '#253f34',
},
textItem: {
flex: 1,
left: 8,
fontFamily: 'Roboto',
fontSize: height * 0.65,
color: COLORS.textW0 + 'cc',
},
textAmount: {
flex: 1,
left: 30,
fontFamily: 'Roboto',
fontSize: height * 0.5,
color: COLORS.textW1,
},
textPerson: {
flex: 1,
left: 25,
fontFamily: 'Roboto',
fontSize: height * 0.5,
color: COLORS.textW1,
},
textDetails: {
flex: 1,
marginBottom: 3,
left: 8,
fontFamily: 'Roboto',
fontSize: height * 0.5,
color: COLORS.primary + 'aa',
},
checkmark: {
height: 30,
width: 30,
borderRadius: 15,
borderWidth: 1.5,
borderColor: '#ffffff' + '12',
justifyContent: 'center',
alignItems: 'center',
},
checkButton: {
height: '100%',
justifyContent: 'flex-start',
alignItems: 'flex-end',
},
});

View File

@@ -0,0 +1,214 @@
import React, { useRef, useEffect } from 'react';
import { Image, StyleSheet, Text, TouchableOpacity, View, Animated } from 'react-native';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
//themes
import { COLORS } from '../../themes/Colors';
//redux
import { useDispatch, useSelector } from 'react-redux';
import { checkToggle } from '../.././redux/slices/groceryList/productsSlice';
export const ListedProduct = (props) => {
const products = useSelector(state => state.products)
const product = products.find((product) => product.id === props.id);
const tags = useSelector(state => state.tags)
const tag = tags.find((tag) => tag.tagName === product.tag);
const scaleAnimValue = useRef(new Animated.Value(0)).current; // animation start value
const colorAnimValue = useRef(new Animated.Value(0)).current; // animation start value
const checkAnimValue = useRef(new Animated.Value(0)).current; // animation start value
//animation:
useEffect(() => {
Animated.sequence([
Animated.timing(scaleAnimValue, {
toValue: 0.9,
duration: 150,
useNativeDriver: false,
}
),
Animated.spring(scaleAnimValue, {
toValue: 1,
friction: 4,
useNativeDriver: false,
},
)
]).start()
}, [product.checked])
//colors
useEffect(() => {
product.checked ? Animated.timing(colorAnimValue, {
toValue: 1,
duration: 200,
useNativeDriver: false,
}
).start()
:
Animated.timing(colorAnimValue, {
toValue: 0,
duration: 200,
useNativeDriver: false,
}
).start()
}, [product.checked])
//checkmark
useEffect(() => {
product.checked ? Animated.sequence([
Animated.delay(200),
Animated.spring(checkAnimValue, {
toValue: 1,
friction: 4,
useNativeDriver: true,
}),
]).start()
:
Animated.sequence([
Animated.delay(150),
Animated.timing(checkAnimValue, {
toValue: 0,
duration: 150,
useNativeDriver: true,
}),
]).start()
}, [product.checked])
//redux
const dispatch = useDispatch()
const dispatchAnim = () => {
dispatch(checkToggle(product.id));
}
const interpolateColor = colorAnimValue.interpolate({
inputRange: [0, 1],
outputRange: ['rgb(22, 26, 30)', 'rgb(62, 131, 98)']
});
return (
<View style={{ flex: 1, paddingLeft: 8, paddingRight: 8, flexDirection: 'row', alignItems: 'flex-start', justifyContent: 'space-between' }}>
<Animated.View style={[styles.listedItemStyle, { backgroundColor: tag.color + '33' }, product.checked ? styles.listedItemChecked : {}, {
transform: [{
scaleX: scaleAnimValue
},
{
scaleY: scaleAnimValue
}
]
}]} >
<TouchableOpacity style={[styles.listedItemButton]}
onPress={() => alert('Not ready yet!!')}
onLongPress={() => dispatchAnim()}>
<View style={{ flex: 1 }}>
<Text style={styles.textItem}>{product.productName}</Text>
<View style={{ flexDirection: 'row' }}>
<Text style={[styles.textTags]}>Tag: </Text>
<Text style={[styles.textTags, { color: tag.color, }]}>{tag.tagName}</Text>
</View>
<View style={{ flexDirection: 'row' }}>
{product.price ? <Text style={styles.textPrice}>Price: </Text> : <View />}
{product.price ? <Text style={[styles.textPrice, { color: '#C6A337', }]}>{product.price}</Text> : <View />}
</View>
</View>
<Image source={{ uri: product.image }} style={styles.image} />
</TouchableOpacity>
</Animated.View>
<TouchableOpacity style={[styles.checkButton, { flex: 1 }]} onPress={() => dispatchAnim()}>
<Animated.View style={[styles.checkmark, product.checked ? {
borderWidth: 0,
} : {}, {
backgroundColor: interpolateColor,
transform: [{
scaleX: scaleAnimValue
},
{
scaleY: scaleAnimValue
}
]
},]} >
<Animated.View style={[{
transform: [{
scaleX: checkAnimValue
},
{
scaleY: checkAnimValue
}
]
}]}>
<MaterialCommunityIcons name="check" color={COLORS.dp00} size={25} />
</Animated.View>
</Animated.View>
</TouchableOpacity>
</View>
);
}
const height = 30;
const styles = StyleSheet.create({
listedItemStyle: {
width: '90%',
marginBottom: height / 7,
minHeight: 80,
borderRadius: height / 2,
backgroundColor: COLORS.dp03,
},
listedItemButton: {
flex: 1,
padding: 2,
paddingBottom: 3,
alignItems: 'flex-start',
flexDirection: 'row',
},
listedItemChecked: {
backgroundColor: '#253f34',
},
textItem: {
flex: 1,
left: 8,
width: '60%',
fontFamily: 'Roboto',
fontSize: height * 0.65,
color: COLORS.textW0 + 'cc',
},
textTags: {
left: 8,
fontFamily: 'Roboto',
fontSize: height * 0.5,
color: COLORS.textW1,
},
textPrice: {
left: 8,
fontFamily: 'Roboto',
fontSize: height * 0.5,
color: COLORS.textW1,
},
image: {
position: 'absolute',
right: 0,
top: 0,
bottom:0,
width: 80,
borderRadius: 15,
opacity: 0.8,
},
checkmark: {
height: 30,
width: 30,
borderRadius: 15,
borderWidth: 1.5,
borderColor: '#ffffff' + '12',
justifyContent: 'center',
alignItems: 'center',
},
checkButton: {
height: '100%',
justifyContent: 'flex-start',
alignItems: 'flex-end',
},
});

View File

@@ -0,0 +1,42 @@
import React from 'react';
import { StyleSheet, TouchableOpacity, View, Text, TextInput, Image } from 'react-native';
//components
import AddProductModal from './modals/AddProductModal';
//themes
import { COLORS } from '../../themes/Colors';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
//redux
import { useDispatch } from 'react-redux';
import { toggleVisibility } from '../../redux/slices/groceryList/toggleSlice';
export const AddProductButton = () => {
const dispatch = useDispatch();
return (
<TouchableOpacity style={[styles.buttonContainer, styles.AddNewProduct]}
onPress={() => dispatch(toggleVisibility('addProductModalVisible'))}>
<MaterialCommunityIcons name="tag-plus-outline" color={COLORS.dp00} size={40} />
{/* pop-up screen */}
<AddProductModal/>
</TouchableOpacity>
);
}
const styles = StyleSheet.create({
buttonContainer: {
height: 60,
width: 60,
borderRadius: 60 / 2,
elevation: 10,
alignItems: 'center',
justifyContent: 'center',
},
AddNewProduct: {
backgroundColor: COLORS.primary,
},
});

View File

@@ -0,0 +1,246 @@
import React, { useState } from 'react';
import { StyleSheet, TouchableOpacity, View, Text, TextInput, Image, ScrollView, TouchableOpacityComponent } from 'react-native';
import Modal from 'react-native-modal';
//themes
import { COLORS } from '../../../themes/Colors';
//redux
import { useDispatch, useSelector } from 'react-redux';
import { itemAdded, amountUp } from '../../../redux/slices/groceryList/itemsSlice';
import { toggleVisibility } from '../../../redux/slices/groceryList/toggleSlice';
export default AddItemModal = () => {
//redux
const modalVisible = useSelector(state => state.toggle.addItemModalVisible);
const products = useSelector(state => state.products);
const items = useSelector(state => state.items);
const dispatch = useDispatch();
let newProductsList = [];
for (let i = 0; i < products.length; i++) {
newProductsList.push(products[i].productName);
}
const [item, setItem] = useState('');
const [focussed, setFocussed] = useState(false);
const [amount, setAmount] = useState('');
const [person, setPerson] = useState('');
const [details, setDetails] = useState('');
const [productsList, setProductsList] = useState(newProductsList);
const filterProductsList = (text) => {
let regex = new RegExp(text);
let newProductsList = products.filter((product) =>
regex.test(product.productName)
)
text !== '' ? newProductsList = newProductsList.map((product) => product.productName) : newProductsList = products.map((product) => product.productName)
if (newProductsList.length === 1 && newProductsList[0] === text) {
setProductsList([]);
}
else {
setProductsList(newProductsList);
}
setItem(text);
};
const toggleModal = () => {
if (modalVisible && item !== '' && amount !== '') {
if (products.find((product) => product.productName === item)) { //find if item is in products , else create unregistered item
const productId = products.find((product) => product.productName === item).id;
if(!items.find((itemObj) => itemObj.productId === productId)){ //check if amount up needed
dispatch(itemAdded(productId, amount, person, details));
}
else{
}
}
else if (!items.find((itemObj) => itemObj.productId === item)) //unregistered item check for amount up
{
dispatch(itemAdded(item, amount, person, details));
}
else{
dispatch(amountUp(item,amount));
}
setItem('');
setAmount();
setPerson('');
setDetails('');
setProductsList(products.map((product) => product.productName));
}
else {
alert('You should give both a product and an amount');
}
dispatch(toggleVisibility('addItemModalVisible'));
};
const closeModal = () => {
setItem('');
setAmount();
setPerson('');
setDetails('');
dispatch(toggleVisibility('addItemModalVisible'));
setProductsList(products.map((product) => product.productName));
};
return (
<Modal isVisible={modalVisible} animationIn={'slideInUp'} animationOut={'slideOutDown'}
onBackdropPress={closeModal}
onBackButtonPress={closeModal}
useNativeDriverForBackdrop
style={styles.modalAddItem} >
<View style={{
borderRadius: 10,
padding: 5,
backgroundColor: COLORS.dp01,
}}>
<Text style={styles.modalHeaderText}>Add item</Text>
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-start' }}>
<TextInput
placeholder={'Product name'}
placeholderTextColor={'grey'}
style={styles.textInput}
offFocus={() => setProductsList([])}
onChangeText={text => filterProductsList(text)}
value={item}
onFocus={() => setFocussed(true)}
onEndEditing={() => setFocussed(false)}
/>
<ScrollView style={styles.dropdown} keyboardShouldPersistTaps={'always'}>
{focussed ? productsList.map((product, index) =>
<TouchableOpacity key={index} onPress={() => filterProductsList(product)} style={styles.dropdownProduct}>
<Text style={styles.dropdownText}>{product}</Text>
</TouchableOpacity>
) : <View />}
</ScrollView>
</View>
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-start' }}>
<TextInput
placeholder={'Amount'}
placeholderTextColor={'grey'}
style={[styles.textInput]}
onChangeText={text => setAmount(text)}
value={amount}
keyboardType={'number-pad'}
/>
</View>
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-start' }}>
<TextInput
placeholder={'For'}
placeholderTextColor={'grey'}
style={styles.textInput}
onChangeText={text => setPerson(text)}
value={person}
/>
</View>
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-start' }}>
<TextInput
placeholder={'Additional details'}
placeholderTextColor={'grey'}
style={styles.textInput}
onChangeText={text => setDetails(text)}
value={details}
/>
</View>
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-evenly', marginTop: 20, marginBottom: 10, }}>
<TouchableOpacity title="Hide modal" style={styles.modalCloseButton} onPress={closeModal} >
<Text style={styles.modalCloseButtonText}>Cancel</Text>
</TouchableOpacity>
<View style={{
borderRadius: 10,
backgroundColor: COLORS.dp01,
borderLeftWidth: 1,
borderColor: COLORS.dp08,
height: '80%',
}} />
<TouchableOpacity title="Hide modal" style={styles.modalAddButton} onPress={toggleModal} >
<Text style={styles.modalAddButtonText}>Add item</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
)
}
const styles = StyleSheet.create({
//modals
modalAddItem: {
margin: 0,
},
modalHeaderText: {
opacity: 0.9,
fontSize: 23,
alignSelf: 'center',
color: COLORS.textW0 + 'de',
},
modalText: {
left: 10,
opacity: 0.9,
fontSize: 18,
color: COLORS.textB0,
},
modalAddButtonText: {
opacity: 0.8,
fontSize: 16,
color: COLORS.primary,
fontWeight: 'bold',
},
modalCloseButtonText: {
opacity: 0.8,
fontSize: 16,
color: COLORS.primary,
fontWeight: 'bold',
},
textInput: {
height: 25,
width: '80%',
left: 10,
borderBottomColor: COLORS.primary + 'aa',
borderBottomWidth: 1,
borderRadius: 3,
marginTop: 10,
padding: 0,
paddingLeft: 5,
paddingRight: 5,
color: COLORS.textW0,
fontSize: 18
},
dropdown: {
zIndex: 1,
position: 'absolute',
maxHeight: 100,
width: 150,
top: 40,
left: 10,
borderRadius: 10,
backgroundColor: COLORS.dp16 + 'ee',
},
dropdownProduct: {
zIndex: 1,
width: 150,
minHeight: 20,
borderBottomWidth: 1.2,
borderColor: '#666' + 'e',
},
dropdownText: {
zIndex: 1,
left: 10,
fontSize: 17,
color: COLORS.textW0 + 'ee',
}
});

View File

@@ -0,0 +1,249 @@
import React, { useState } from 'react';
import { StyleSheet, TouchableOpacity, View, Text, TextInput, Image, ScrollView } from 'react-native';
import Modal from 'react-native-modal';
//themes
import { COLORS } from '../../../themes/Colors';
//redux
import { useDispatch, useSelector } from 'react-redux';
import { productAdded } from '../../../redux/slices/groceryList/productsSlice';
import { toggleVisibility } from '../../../redux/slices/groceryList/toggleSlice';
export default AddProductModal = () => {
const modalVisible = useSelector(state => state.toggle.addProductModalVisible);
const dispatch = useDispatch();
const [product, setProduct] = useState('');
const [tag, setTag] = useState('');
const [price, setPrice] = useState('');
const [image, setImage] = useState('https://icons-for-free.com/iconfiles/png/512/linecon+products+round+icon-1320165923260225670.png');
//tags
const tags = useSelector(state => state.tags)
let newTagsList = [];
for (let i = 0; i < tags.length; i++) {
newTagsList.push(tags[i].tagName);
}
const [tagsList, setTagsList] = useState(newTagsList);
const [focussed, setFocussed] = useState(false);
const filterTagsList = (text) => {
let regex = new RegExp(text);
let newTagsList = tags.filter((tag) =>
regex.test(tag.tagName)
)
text !== '' ? newTagsList = newTagsList.map((tag) => tag.tagName) : newTagsList = tags.map((tag) => tag.tagName)
if (newTagsList.length === 1 && newTagsList[0] === text) {
setTagsList([]);
}
else {
setTagsList(newTagsList);
}
setTag(text);
};
//tags
const toggleModal = () => {
if (modalVisible) {
if (product !== '' && tags.find((listTag) => listTag.tagName === tag)) {
dispatch(productAdded(product, tag, price, image));
}
else {
alert('You should give both a product name and a useable tag');
}
}
setTagsList(tags.map((listTag) => listTag.tagName));
dispatch(toggleVisibility('addProductModalVisible'));
setProduct('');
setTag('');
setPrice();
setImage('https://icons-for-free.com/iconfiles/png/512/linecon+products+round+icon-1320165923260225670.png');
};
const closeModal = () => {
setTagsList(tags.map((listTag) => listTag.tagName));
setProduct('');
setTag();
setPrice();
setImage('https://icons-for-free.com/iconfiles/png/512/linecon+products+round+icon-1320165923260225670.png');
dispatch(toggleVisibility('addProductModalVisible'));
};
return (
<Modal isVisible={modalVisible} animationIn={'slideInUp'} animationOut={'slideOutDown'}
onBackdropPress={closeModal}
onBackButtonPress={closeModal}
useNativeDriverForBackdrop
style={styles.modalAddProduct} >
<View style={{
borderRadius: 10,
padding: 5,
backgroundColor: COLORS.dp01,
}}>
<Text style={styles.modalHeaderText}>Add product</Text>
<View style={{
flexDirection: 'row',
justifyContent: 'flex-start',
}}>
<View style={{
width: '60%',
}}>
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-start' }}>
<TextInput
placeholder={'Product name'}
placeholderTextColor={'grey'}
style={styles.textInput}
onChangeText={text => setProduct(text)}
/>
</View>
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-start' }}>
<TextInput
placeholder={'Tag'}
placeholderTextColor={'grey'}
style={[styles.textInput]}
value={tag}
offFocus={() => setTagsList([])}
onChangeText={text => filterTagsList(text)}
onFocus={() => setFocussed(true)}
onEndEditing={() => setFocussed(false)}
/>
<ScrollView style={styles.dropdown} keyboardShouldPersistTaps={'always'}>
{focussed ? tagsList.map((newTag, index) =>
<TouchableOpacity key={index} onPress={() => filterTagsList(newTag)} style={styles.dropdownProduct}>
<Text style={styles.dropdownText}>{newTag}</Text>
</TouchableOpacity>
) : <View />}
</ScrollView>
</View>
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-start' }}>
<Text style={styles.currencyPrefix}></Text>
<TextInput
placeholder={'Price'}
placeholderTextColor={'grey'}
style={[styles.textInput, { paddingLeft: 20 }]}
onChangeText={text => setPrice(text)}
keyboardType={'number-pad'}
/>
</View>
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-start' }}>
<TextInput
placeholder={'Image url'}
placeholderTextColor={'grey'}
style={styles.textInput}
onChangeText={text => { if (text !== '') { return setImage(text) } }}
/>
</View>
</View>
<Image source={{ uri: image }}
style={{ width: 130, height: 130, marginTop: '5%', right: 10, borderRadius: 30, }} />
</View>
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-evenly', marginTop: 20, marginBottom: 10, }}>
<TouchableOpacity title="Hide modal" style={styles.modalCloseButton} onPress={closeModal} >
<Text style={styles.modalCloseButtonText}>Cancel </Text>
</TouchableOpacity>
<View style={{
borderRadius: 10,
backgroundColor: COLORS.dp01,
borderLeftWidth: 1,
borderColor: COLORS.dp08,
height: '80%',
}} />
<TouchableOpacity title="Hide modal" style={styles.modalAddButton} onPress={toggleModal} >
<Text style={styles.modalAddButtonText}>Add product</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
)
}
const styles = StyleSheet.create({
//modals
modalAddItem: {
margin: 0,
},
modalHeaderText: {
opacity: 0.9,
fontSize: 23,
alignSelf: 'center',
color: COLORS.textW0 + 'de',
},
modalText: {
left: 10,
opacity: 0.9,
fontSize: 18,
color: COLORS.textB0,
},
modalAddButtonText: {
opacity: 0.8,
fontSize: 16,
color: COLORS.primary,
fontWeight: 'bold',
},
modalCloseButtonText: {
opacity: 0.8,
fontSize: 16,
color: COLORS.primary,
fontWeight: 'bold',
},
textInput: {
height: 25,
width: '80%',
left: 10,
borderBottomColor: COLORS.primary + 'aa',
borderBottomWidth: 1,
borderRadius: 3,
marginTop: 10,
padding: 0,
paddingLeft: 5,
paddingRight: 5,
color: COLORS.textW0,
fontSize: 18
},
currencyPrefix: {
position: 'absolute',
alignSelf: 'flex-end',
left: 15,
color: COLORS.primary + '99',
fontSize: 18,
},
dropdown: {
zIndex: 1,
position: 'absolute',
maxHeight: 100,
width: 150,
top: 40,
left: 10,
borderRadius: 10,
backgroundColor: COLORS.dp16 + 'ee',
},
dropdownProduct: {
zIndex: 1,
width: 150,
minHeight: 20
},
dropdownText: {
zIndex: 1,
left: 10,
fontSize: 17,
color: COLORS.textW0 + 'ee',
}
});