Edits + better layout
This commit is contained in:
@@ -14,6 +14,7 @@
|
|||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
||||||
|
android:screenOrientation="portrait"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
android:windowSoftInputMode="adjustPan">
|
android:windowSoftInputMode="adjustPan">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import AddItemModal from './modals/AddItemModal';
|
|||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import { toggleVisibility } from '../../redux/slices/groceryList/toggleSlice';
|
import { toggleVisibility } from '../../redux/slices/groceryList/toggleSlice';
|
||||||
import { removeCheckedItems } from '../../redux/slices/groceryList/itemsSlice';
|
import { removeCheckedItems } from '../../redux/slices/groceryList/itemsSlice';
|
||||||
|
import { pushItems } from '../../redux/slices/groceryList/storageSlice';
|
||||||
|
|
||||||
|
|
||||||
export const AddItemButton = () => {
|
export const AddItemButton = () => {
|
||||||
@@ -27,24 +28,32 @@ export const AddItemButton = () => {
|
|||||||
}
|
}
|
||||||
export const AddNewRecipeButton = () => {
|
export const AddNewRecipeButton = () => {
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity style={[styles.buttonContainer, styles.AddNewProduct, { backgroundColor: COLORS.primaryVar2 }]}
|
<TouchableOpacity style={[styles.buttonContainer, styles.AddNewRecipeButton, { backgroundColor: COLORS.primaryVar2 }]}
|
||||||
onPress={() => alert('hello')}>
|
onPress={() => alert('hello')}>
|
||||||
<MaterialCommunityIcons name="file-document-edit-outline" color={COLORS.dp00} size={40} />
|
<MaterialCommunityIcons name="file-document-edit-outline" color={COLORS.dp00} size={40} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
export const PushItemsToStorageButton = () => {
|
export const PushItemsToStorageButton = () => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const items = useSelector(state => state.items)
|
||||||
|
const products = useSelector(state => state.products)
|
||||||
|
const checkedItems = items.filter((item)=>item.checked && products.find((product)=>product.id === item.productId) !== undefined)
|
||||||
|
const dispatchAll = () =>{
|
||||||
|
dispatch(pushItems(checkedItems))
|
||||||
|
dispatch(removeCheckedItems())
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity style={[styles.buttonContainer, styles.AddNewRecipe, { backgroundColor: COLORS.actionSend }]}
|
<TouchableOpacity style={[styles.buttonContainer, styles.PushItemsToStorageButton, { backgroundColor: COLORS.actionSend }]}
|
||||||
onPress={() => alert('lol')}>
|
onPress={() => dispatchAll()}>
|
||||||
<MaterialCommunityIcons name="cloud-download-outline" color={COLORS.dp00} size={40} />
|
<MaterialCommunityIcons name="cart-arrow-up" color={COLORS.dp00} size={40} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
export const RemoveItemsButton = () => {
|
export const RemoveItemsButton = () => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity style={[styles.buttonContainer, styles.downloadList, { backgroundColor: COLORS.actionCancel }]}
|
<TouchableOpacity style={[styles.buttonContainer, styles.RemoveItemsButton, { backgroundColor: COLORS.actionCancel }]}
|
||||||
onPress={() => dispatch(removeCheckedItems())}>
|
onPress={() => dispatch(removeCheckedItems())}>
|
||||||
<MaterialCommunityIcons name="delete-forever-outline" color={COLORS.dp00} size={40} />
|
<MaterialCommunityIcons name="delete-forever-outline" color={COLORS.dp00} size={40} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
@@ -63,14 +72,14 @@ const styles = StyleSheet.create({
|
|||||||
addItem: {
|
addItem: {
|
||||||
backgroundColor: COLORS.primary,
|
backgroundColor: COLORS.primary,
|
||||||
},
|
},
|
||||||
AddNewProduct: {
|
AddNewRecipeButton: {
|
||||||
backgroundColor: COLORS.primary,
|
backgroundColor: COLORS.primary,
|
||||||
},
|
},
|
||||||
AddNewRecipe: {
|
PushItemsToStorageButton: {
|
||||||
backgroundColor: COLORS.primary,
|
backgroundColor: COLORS.primary,
|
||||||
|
|
||||||
},
|
},
|
||||||
downloadList: {
|
RemoveItemsButton: {
|
||||||
backgroundColor: COLORS.primary,
|
backgroundColor: COLORS.primary,
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,42 +1,31 @@
|
|||||||
import React, { useRef, useEffect, useState } from 'react';
|
import React, { useRef, useEffect, useState, Suspense } from 'react';
|
||||||
import { StyleSheet, Text, TouchableOpacity, View, Animated } from 'react-native';
|
import { StyleSheet, Text, TouchableOpacity, View, Animated } from 'react-native';
|
||||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||||
//themes
|
//themes
|
||||||
import { COLORS } from '../../themes/Colors';
|
import { COLORS } from '../../themes/Colors';
|
||||||
|
|
||||||
|
//components
|
||||||
|
import EditItemModal from './modals/EditItemModal'
|
||||||
//redux
|
//redux
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import { checkToggle } from '../.././redux/slices/groceryList/itemsSlice';
|
import { checkToggle, modalToggle } from '../.././redux/slices/groceryList/itemsSlice';
|
||||||
|
|
||||||
|
const ListedItem = (props) => {
|
||||||
export const ListedItem = (props) => {
|
|
||||||
|
|
||||||
//redux
|
//redux
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
const products = useSelector(state => state.products)
|
const item = useSelector(state => state.items.find((item) => item.productId === props.id))
|
||||||
const items = useSelector(state => state.items)
|
let product = useSelector(state => state.products.find((product) => product.id === item.productId))
|
||||||
const tags = useSelector(state => state.tags)
|
if (!product) {
|
||||||
|
|
||||||
|
|
||||||
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 = {
|
product = {
|
||||||
productName: props.id,
|
productName: props.id,
|
||||||
tag:'no-tag',
|
tag: 'uncathegorized',
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
const tag = useSelector(state => state.tags.find((tag) => tag.tagName === product.tag))
|
||||||
const dispatchAnim = () => {
|
const dispatchAnim = () => {
|
||||||
dispatch(checkToggle(item.productId));
|
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 scaleAnimValue = useRef(new Animated.Value(0)).current; // animation start value
|
||||||
const colorAnimValue = 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
|
const checkAnimValue = useRef(new Animated.Value(0)).current; // animation start value
|
||||||
@@ -106,33 +95,9 @@ export const ListedItem = (props) => {
|
|||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={{ flex: 1, paddingLeft: 8, paddingRight: 8, flexDirection: 'row', alignItems: 'flex-start', justifyContent: 'space-between' }}>
|
<Suspense fallback={<Text>Loading</Text>}>
|
||||||
<Animated.View style={[styles.listedItemStyle, {backgroundColor: tag.color + '33'},item.checked ? styles.listedItemChecked : {}, {
|
<View style={{ flex: 1, paddingLeft: 8, paddingRight: 8, flexDirection: 'row', alignItems: 'flex-start', justifyContent: 'space-between' }}>
|
||||||
transform: [{
|
<Animated.View style={[styles.listedItemStyle, { backgroundColor: tag.color + '33' }, item.checked ? styles.listedItemChecked : {}, {
|
||||||
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: [{
|
transform: [{
|
||||||
scaleX: scaleAnimValue
|
scaleX: scaleAnimValue
|
||||||
},
|
},
|
||||||
@@ -140,68 +105,119 @@ export const ListedItem = (props) => {
|
|||||||
scaleY: scaleAnimValue
|
scaleY: scaleAnimValue
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},]} >
|
}]} >
|
||||||
<Animated.View style={[{
|
<TouchableOpacity style={{ flex: 1, }}
|
||||||
|
onPress={() => dispatch(modalToggle(props.id))}
|
||||||
|
onLongPress={() => dispatchAnim()}>
|
||||||
|
<View style={styles.nameTag}>
|
||||||
|
{item.person ? <Text style={styles.textPerson}>{item.person}</Text> : <View />}
|
||||||
|
</View>
|
||||||
|
<Text style={styles.textItem}>{product.productName}</Text>
|
||||||
|
<Text style={styles.textAmount}>{item.amount}</Text>
|
||||||
|
{item.details ? <Text style={styles.textDetails}>{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: [{
|
transform: [{
|
||||||
scaleX: checkAnimValue
|
scaleX: scaleAnimValue
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
scaleY: checkAnimValue
|
scaleY: scaleAnimValue
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}]}>
|
},]} >
|
||||||
<MaterialCommunityIcons name="check" color={COLORS.dp00} size={25} />
|
<Animated.View style={[{
|
||||||
</Animated.View>
|
transform: [{
|
||||||
|
scaleX: checkAnimValue
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scaleY: checkAnimValue
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]}>
|
||||||
|
<MaterialCommunityIcons name="check" color={COLORS.dp00} size={25} />
|
||||||
|
</Animated.View>
|
||||||
|
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
|
</Suspense>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
export default React.memo(ListedItem);
|
||||||
|
|
||||||
const height = 30;
|
const height = 30;
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
|
||||||
listedItemStyle: {
|
listedItemStyle: {
|
||||||
width: '90%',
|
width: '90%',
|
||||||
|
minHeight: height + 30,
|
||||||
marginBottom: height / 7,
|
marginBottom: height / 7,
|
||||||
|
|
||||||
borderRadius: height / 2,
|
borderRadius: height / 2,
|
||||||
padding: 2,
|
|
||||||
paddingBottom: 3,
|
|
||||||
backgroundColor: COLORS.dp03,
|
backgroundColor: COLORS.dp03,
|
||||||
},
|
},
|
||||||
listedItemChecked: {
|
listedItemChecked: {
|
||||||
backgroundColor: '#253f34',
|
backgroundColor: '#253f34',
|
||||||
},
|
},
|
||||||
textItem: {
|
textItem: {
|
||||||
|
width: '80%',
|
||||||
flex: 1,
|
flex: 1,
|
||||||
left: 8,
|
marginLeft: 10,
|
||||||
|
marginTop: 5,
|
||||||
fontFamily: 'Roboto',
|
fontFamily: 'Roboto',
|
||||||
fontSize: height * 0.65,
|
fontSize: height * 0.65,
|
||||||
color: COLORS.textW0 + 'cc',
|
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: {
|
textDetails: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
left: 10,
|
||||||
|
|
||||||
marginBottom: 3,
|
marginBottom: 3,
|
||||||
left: 8,
|
|
||||||
fontFamily: 'Roboto',
|
fontFamily: 'Roboto',
|
||||||
fontSize: height * 0.5,
|
fontSize: height * 0.5,
|
||||||
color: COLORS.primary + 'aa',
|
color: COLORS.primary + 'aa',
|
||||||
},
|
},
|
||||||
|
nameTag: {
|
||||||
|
backgroundColor: '#000000' + '33',
|
||||||
|
minWidth: '30%',
|
||||||
|
position: 'absolute',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
|
||||||
|
borderTopLeftRadius: 10,
|
||||||
|
borderBottomRightRadius: height / 2,
|
||||||
|
},
|
||||||
|
textPerson: {
|
||||||
|
fontFamily: 'Roboto',
|
||||||
|
fontSize: height * 0.45,
|
||||||
|
color: COLORS.textW0 + 'cc',
|
||||||
|
padding: 5,
|
||||||
|
maxHeight: 40,
|
||||||
|
},
|
||||||
|
textAmount: {
|
||||||
|
position: 'absolute',
|
||||||
|
backgroundColor: '#000' + '3',
|
||||||
|
right: 5,
|
||||||
|
top: 5,
|
||||||
|
minWidth: 50,
|
||||||
|
borderTopRightRadius: height / 2,
|
||||||
|
borderRadius: height / 3,
|
||||||
|
|
||||||
|
paddingLeft: 5,
|
||||||
|
paddingRight: 10,
|
||||||
|
fontFamily: 'Roboto',
|
||||||
|
fontSize: height * 0.55,
|
||||||
|
color: COLORS.textW0 + 'bb',
|
||||||
|
},
|
||||||
checkmark: {
|
checkmark: {
|
||||||
height: 30,
|
height: 30,
|
||||||
width: 30,
|
width: 30,
|
||||||
|
|||||||
@@ -1,21 +1,25 @@
|
|||||||
import React, { useRef, useEffect } from 'react';
|
import React, { useRef, useEffect } from 'react';
|
||||||
import { Image, StyleSheet, Text, TouchableOpacity, View, Animated } from 'react-native';
|
import { Image, StyleSheet, Text, TouchableOpacity, View, Animated } from 'react-native';
|
||||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||||
|
//components
|
||||||
|
import EditProductModal from './modals/EditProductModal'
|
||||||
|
|
||||||
//themes
|
//themes
|
||||||
import { COLORS } from '../../themes/Colors';
|
import { COLORS } from '../../themes/Colors';
|
||||||
//redux
|
//redux
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import { checkToggle } from '../.././redux/slices/groceryList/productsSlice';
|
import { checkToggle, modalToggle } from '../.././redux/slices/groceryList/productsSlice';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const ListedProduct = (props) => {
|
const ListedProduct = (props) => {
|
||||||
|
|
||||||
const products = useSelector(state => state.products)
|
const product = useSelector(state => state.products.find((product) => product.id === props.id));
|
||||||
const product = products.find((product) => product.id === props.id);
|
|
||||||
|
|
||||||
const tags = useSelector(state => state.tags)
|
const tags = useSelector(state => state.tags)
|
||||||
const tag = tags.find((tag) => tag.tagName === product.tag);
|
const tag = tags.find((tag) => tag.tagName === product.tag);
|
||||||
|
//redux
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
|
||||||
const scaleAnimValue = useRef(new Animated.Value(0)).current; // animation start value
|
const scaleAnimValue = useRef(new Animated.Value(0)).current; // animation start value
|
||||||
const colorAnimValue = useRef(new Animated.Value(0)).current; // animation start value
|
const colorAnimValue = useRef(new Animated.Value(0)).current; // animation start value
|
||||||
@@ -78,12 +82,6 @@ export const ListedProduct = (props) => {
|
|||||||
]).start()
|
]).start()
|
||||||
|
|
||||||
}, [product.checked])
|
}, [product.checked])
|
||||||
//redux
|
|
||||||
const dispatch = useDispatch()
|
|
||||||
|
|
||||||
const dispatchAnim = () => {
|
|
||||||
dispatch(checkToggle(product.id));
|
|
||||||
}
|
|
||||||
const interpolateColor = colorAnimValue.interpolate({
|
const interpolateColor = colorAnimValue.interpolate({
|
||||||
inputRange: [0, 1],
|
inputRange: [0, 1],
|
||||||
outputRange: ['rgb(22, 26, 30)', 'rgb(62, 131, 98)']
|
outputRange: ['rgb(22, 26, 30)', 'rgb(62, 131, 98)']
|
||||||
@@ -99,24 +97,24 @@ export const ListedProduct = (props) => {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}]} >
|
}]} >
|
||||||
|
|
||||||
<TouchableOpacity style={[styles.listedItemButton]}
|
<TouchableOpacity style={[styles.listedItemButton]}
|
||||||
onPress={() => alert('Not ready yet!!')}
|
onPress={() => dispatch(modalToggle(product.id))}
|
||||||
onLongPress={() => dispatchAnim()}>
|
onLongPress={() => dispatch(checkToggle(product.id))}>
|
||||||
|
|
||||||
<View style={{ flex: 1 }}>
|
<View style={{ flex: 1 }}>
|
||||||
<Text style={styles.textItem}>{product.productName}</Text>
|
<Text style={styles.textItem}>{product.productName}</Text>
|
||||||
<View style={{ flexDirection: 'row' }}>
|
<Text style={[styles.textTags, { color: tag.color, }]}>{tag.tagName}</Text>
|
||||||
<Text style={[styles.textTags]}>Tag: </Text>
|
{product.price ? <Text style={[styles.textPrice, { color: COLORS.price, }]}>€{product.price}</Text> : <View />}
|
||||||
<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>
|
</View>
|
||||||
<Image source={{ uri: product.image }} style={styles.image} />
|
<Image source={{ uri: product.image }} style={styles.image} />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
<TouchableOpacity style={[styles.checkButton, { flex: 1 }]} onPress={() => dispatchAnim()}>
|
|
||||||
|
<TouchableOpacity style={[styles.checkButton, { flex: 1 }]} onPress={() => dispatch(checkToggle(product.id))}>
|
||||||
<Animated.View style={[styles.checkmark, product.checked ? {
|
<Animated.View style={[styles.checkmark, product.checked ? {
|
||||||
borderWidth: 0,
|
borderWidth: 0,
|
||||||
} : {}, {
|
} : {}, {
|
||||||
@@ -146,6 +144,7 @@ export const ListedProduct = (props) => {
|
|||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
export default React.memo(ListedProduct);
|
||||||
|
|
||||||
const height = 30;
|
const height = 30;
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
@@ -192,7 +191,7 @@ const styles = StyleSheet.create({
|
|||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
right: 0,
|
right: 0,
|
||||||
top: 0,
|
top: 0,
|
||||||
bottom:0,
|
bottom: 0,
|
||||||
width: 80,
|
width: 80,
|
||||||
borderRadius: 15,
|
borderRadius: 15,
|
||||||
opacity: 0.8,
|
opacity: 0.8,
|
||||||
|
|||||||
112
src/components/groceryComponents/ListedStorageItem.js
Normal file
112
src/components/groceryComponents/ListedStorageItem.js
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
import React 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 } from 'react-redux';
|
||||||
|
import { changeAmount, removeItem } from '../../redux/slices/groceryList/storageSlice';
|
||||||
|
|
||||||
|
|
||||||
|
const Hr = (props) => {
|
||||||
|
return (
|
||||||
|
<View style={{ backgroundColor: props.color, width: 1.0, height: props.height, borderRadius: 1, alignSelf: 'flex-end' }} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
let ListedStorageItem = ({product, storageItem, tag}) => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
return (
|
||||||
|
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', width: '100%' }}>
|
||||||
|
{/* delete button */}
|
||||||
|
{!storageItem.amount ? <TouchableOpacity style={[styles.deleteItem, {}]} onPress={() => dispatch(removeItem(storageItem.id))}>
|
||||||
|
<MaterialCommunityIcons name="window-close" color={COLORS.actionCancel + 'aa'} size={22} />
|
||||||
|
</TouchableOpacity> : <View style={{ width: 25 }} />}
|
||||||
|
|
||||||
|
<View style={[styles.listedItem, { backgroundColor: tag.color + '20' }]}>
|
||||||
|
|
||||||
|
<Text style={styles.textItem}>{product.productName}</Text>
|
||||||
|
<Text style={styles.textAmount}>{storageItem.amount}</Text>
|
||||||
|
|
||||||
|
<View style={styles.amountButtons}>
|
||||||
|
|
||||||
|
{/* button increment amount */}
|
||||||
|
<TouchableOpacity style={styles.amountIncrement} onPress={() => dispatch(changeAmount(storageItem.id, 1))}>
|
||||||
|
<MaterialCommunityIcons name="plus" color={COLORS.textW0 + '77'} size={20} />
|
||||||
|
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
<Hr color={COLORS.textW0 + '11'} height={'100%'} />
|
||||||
|
{/* button decrement amount */}
|
||||||
|
<TouchableOpacity style={styles.amountDecrement} onPress={() => storageItem.amount > 0 ? dispatch(changeAmount(product.id, -1)) : 0}
|
||||||
|
onLongPress={() => dispatch(changeAmount(product.id, -storageItem.amount))}>
|
||||||
|
<MaterialCommunityIcons name="minus" color={COLORS.textW0 + '77'} size={20} />
|
||||||
|
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>)
|
||||||
|
|
||||||
|
}
|
||||||
|
ListedStorageItem = React.memo(ListedStorageItem);
|
||||||
|
export default ListedStorageItem;
|
||||||
|
const height = 30;
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
listedItem: {
|
||||||
|
borderTopLeftRadius: 15,
|
||||||
|
borderBottomLeftRadius: 15,
|
||||||
|
width: '90%',
|
||||||
|
paddingLeft: 8,
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
marginTop: 2,
|
||||||
|
marginBottom: 2,
|
||||||
|
},
|
||||||
|
textItem: {
|
||||||
|
flex: 1,
|
||||||
|
left: 8,
|
||||||
|
marginTop: 2,
|
||||||
|
fontFamily: 'Roboto',
|
||||||
|
fontSize: height * 0.65,
|
||||||
|
color: COLORS.textW0 + 'bb',
|
||||||
|
},
|
||||||
|
textAmount: {
|
||||||
|
width: '10%',
|
||||||
|
backgroundColor: '#000000' + '40',
|
||||||
|
paddingLeft: 3,
|
||||||
|
borderRadius: 6,
|
||||||
|
marginTop: 3,
|
||||||
|
marginBottom: 3,
|
||||||
|
|
||||||
|
marginRight: 3,
|
||||||
|
fontFamily: 'Roboto',
|
||||||
|
fontSize: height * 0.6,
|
||||||
|
color: COLORS.textW1,
|
||||||
|
},
|
||||||
|
amountButtons: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
marginTop: 3,
|
||||||
|
marginBottom: 3,
|
||||||
|
borderTopLeftRadius: 10,
|
||||||
|
borderBottomLeftRadius: 10,
|
||||||
|
height: 25,
|
||||||
|
width: 70,
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'space-evenly',
|
||||||
|
|
||||||
|
backgroundColor: '#ffffff' + '10',
|
||||||
|
},
|
||||||
|
amountIncrement: {
|
||||||
|
},
|
||||||
|
amountDecrement: {
|
||||||
|
},
|
||||||
|
deleteItem: {
|
||||||
|
height: 27,
|
||||||
|
width: 27,
|
||||||
|
backgroundColor: '#ffffff' + '10',
|
||||||
|
borderRadius: 12.5,
|
||||||
|
marginLeft: 5,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
}
|
||||||
|
})
|
||||||
114
src/components/groceryComponents/StorageList.js
Normal file
114
src/components/groceryComponents/StorageList.js
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { StyleSheet, TouchableOpacity, View, Text } from 'react-native';
|
||||||
|
|
||||||
|
//components
|
||||||
|
import ListedStorageItem from './ListedStorageItem';
|
||||||
|
//themes
|
||||||
|
import { COLORS } from '../../themes/Colors';
|
||||||
|
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||||
|
//redux
|
||||||
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
|
export default StorageList = (props) => {
|
||||||
|
const products = useSelector(state => state.products)
|
||||||
|
const storageFiltered = useSelector(state => state.storage.filter((item) => products.find((product) => product.id === item.id).tag === props.tag))
|
||||||
|
const tag = useSelector(state => state.tags.find((tag) => tag.tagName === props.tag))
|
||||||
|
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
|
||||||
|
if (storageFiltered.length !== 0) {
|
||||||
|
return(
|
||||||
|
<View style={styles.container}>
|
||||||
|
<TouchableOpacity style={[styles.categoryButton]}
|
||||||
|
onPress={() => setVisible(!visible)}>
|
||||||
|
{visible ?
|
||||||
|
<MaterialCommunityIcons name="menu-down" color={COLORS.textW3} size={28} />
|
||||||
|
: <MaterialCommunityIcons name="menu-right" color={COLORS.textW3} size={28} />
|
||||||
|
}
|
||||||
|
<Text style={[styles.textItem, { color: tag.color + 'aa' }]}>{props.tag}</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<View style={[styles.list]}>
|
||||||
|
{visible ? storageFiltered.map((storageItem, index) => {
|
||||||
|
const product = products.find((product) => product.id === storageItem.id)
|
||||||
|
return <ListedStorageItem key={index} product = {product} storageItem = {storageItem} tag = {tag}/>
|
||||||
|
}) : <View />}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return <View />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const height = 30;
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
marginBottom: 5,
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
alignItems: 'flex-end',
|
||||||
|
},
|
||||||
|
categoryButton: {
|
||||||
|
flex: 1,
|
||||||
|
paddingLeft: 0,
|
||||||
|
paddingRight: 8,
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
},
|
||||||
|
listedItem: {
|
||||||
|
borderTopLeftRadius: 15,
|
||||||
|
borderBottomLeftRadius: 15,
|
||||||
|
width: '90%',
|
||||||
|
paddingLeft: 8,
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
marginTop: 2,
|
||||||
|
marginBottom: 2,
|
||||||
|
},
|
||||||
|
textItem: {
|
||||||
|
flex: 1,
|
||||||
|
left: 8,
|
||||||
|
fontFamily: 'Roboto',
|
||||||
|
fontSize: height * 0.65,
|
||||||
|
color: COLORS.textW0 + 'bb',
|
||||||
|
},
|
||||||
|
textAmount: {
|
||||||
|
width: '10%',
|
||||||
|
backgroundColor: '#ffffff' + '10',
|
||||||
|
paddingLeft: 3,
|
||||||
|
borderRadius: 6,
|
||||||
|
|
||||||
|
marginRight: 3,
|
||||||
|
fontFamily: 'Roboto',
|
||||||
|
fontSize: height * 0.6,
|
||||||
|
color: COLORS.textW1,
|
||||||
|
},
|
||||||
|
amountButtons: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
marginTop: 3,
|
||||||
|
marginBottom: 3,
|
||||||
|
borderTopLeftRadius: 10,
|
||||||
|
borderBottomLeftRadius: 10,
|
||||||
|
height: 25,
|
||||||
|
width: 70,
|
||||||
|
alignItems: 'center',
|
||||||
|
alignSelf: 'flex-start',
|
||||||
|
justifyContent: 'space-evenly',
|
||||||
|
|
||||||
|
backgroundColor: '#ffffff' + '10',
|
||||||
|
},
|
||||||
|
amountIncrement: {
|
||||||
|
},
|
||||||
|
amountDecrement: {
|
||||||
|
},
|
||||||
|
deleteItem: {
|
||||||
|
height: 27,
|
||||||
|
width: 27,
|
||||||
|
backgroundColor: '#ffffff' + '10',
|
||||||
|
borderRadius: 12.5,
|
||||||
|
marginLeft: 5,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -1,20 +1,21 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { StyleSheet, TouchableOpacity, View, Text, TextInput, Image, ScrollView, TouchableOpacityComponent } from 'react-native';
|
import { StyleSheet, TouchableOpacity, View, Text, TextInput, ScrollView , Image } from 'react-native';
|
||||||
import Modal from 'react-native-modal';
|
import Modal from 'react-native-modal';
|
||||||
//themes
|
//themes
|
||||||
import { COLORS } from '../../../themes/Colors';
|
import { COLORS } from '../../../themes/Colors';
|
||||||
|
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||||
|
|
||||||
//redux
|
//redux
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import { itemAdded, amountUp } from '../../../redux/slices/groceryList/itemsSlice';
|
import { itemAdded, amountUp } from '../../../redux/slices/groceryList/itemsSlice';
|
||||||
import { toggleVisibility } from '../../../redux/slices/groceryList/toggleSlice';
|
import { toggleVisibility } from '../../../redux/slices/groceryList/toggleSlice';
|
||||||
|
|
||||||
|
|
||||||
export default AddItemModal = () => {
|
export default AddItemModal = () => {
|
||||||
//redux
|
//redux
|
||||||
const modalVisible = useSelector(state => state.toggle.addItemModalVisible);
|
const modalVisible = useSelector(state => state.toggle.addItemModalVisible);
|
||||||
|
|
||||||
const products = useSelector(state => state.products);
|
const products = useSelector(state => state.products);
|
||||||
const items = useSelector(state => state.items);
|
|
||||||
|
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
@@ -23,10 +24,9 @@ export default AddItemModal = () => {
|
|||||||
newProductsList.push(products[i].productName);
|
newProductsList.push(products[i].productName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const [item, setItem] = useState('');
|
const [item, setItem] = useState('');
|
||||||
const [focussed, setFocussed] = useState(false);
|
const [focussed, setFocussed] = useState(false);
|
||||||
const [amount, setAmount] = useState('');
|
const [amount, setAmount] = useState();
|
||||||
const [person, setPerson] = useState('');
|
const [person, setPerson] = useState('');
|
||||||
const [details, setDetails] = useState('');
|
const [details, setDetails] = useState('');
|
||||||
|
|
||||||
@@ -47,39 +47,29 @@ export default AddItemModal = () => {
|
|||||||
setItem(text);
|
setItem(text);
|
||||||
};
|
};
|
||||||
const toggleModal = () => {
|
const toggleModal = () => {
|
||||||
if (modalVisible && item !== '' && amount !== '') {
|
if (modalVisible && item !== '' && 0 < amount) {
|
||||||
if (products.find((product) => product.productName === item)) { //find if item is in products , else create unregistered item
|
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;
|
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));
|
||||||
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 { //unregistered
|
||||||
|
dispatch(itemAdded(item, amount, person, details));
|
||||||
|
}
|
||||||
|
setItem('');
|
||||||
|
setAmount();
|
||||||
|
setPerson('');
|
||||||
|
setDetails('');
|
||||||
|
setFocussed(false)
|
||||||
|
setProductsList(products.map((product) => product.productName));
|
||||||
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
alert('You should give both a product and an amount');
|
alert('You should give both a product and an amount');
|
||||||
}
|
}
|
||||||
dispatch(toggleVisibility('addItemModalVisible'));
|
dispatch(toggleVisibility('addItemModalVisible'));
|
||||||
};
|
};
|
||||||
const closeModal = () => {
|
const closeModal = () => {
|
||||||
setItem('');
|
setFocussed(false)
|
||||||
setAmount();
|
|
||||||
setPerson('');
|
|
||||||
setDetails('');
|
|
||||||
dispatch(toggleVisibility('addItemModalVisible'));
|
dispatch(toggleVisibility('addItemModalVisible'));
|
||||||
setProductsList(products.map((product) => product.productName));
|
setProductsList(products.map((product) => product.productName));
|
||||||
};
|
};
|
||||||
@@ -96,19 +86,22 @@ export default AddItemModal = () => {
|
|||||||
backgroundColor: COLORS.dp01,
|
backgroundColor: COLORS.dp01,
|
||||||
|
|
||||||
}}>
|
}}>
|
||||||
|
<Image source={{ uri: products.find((product) => product.productName === item) ? products.find((product) => product.productName === item).image : 'https://icons-for-free.com/iconfiles/png/512/linecon+products+round+icon-1320165923260225670.png'}}
|
||||||
|
style={styles.image} />
|
||||||
|
|
||||||
<Text style={styles.modalHeaderText}>Add item</Text>
|
<Text style={styles.modalHeaderText}>Add item</Text>
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-start' }}>
|
<View style={styles.inputRow}>
|
||||||
|
<MaterialCommunityIcons name="food" color={COLORS.textW0 + '55'} size={30} />
|
||||||
<TextInput
|
<TextInput
|
||||||
placeholder={'Product name'}
|
placeholder={'Product name'}
|
||||||
placeholderTextColor={'grey'}
|
placeholderTextColor={'grey'}
|
||||||
style={styles.textInput}
|
style={styles.textInput}
|
||||||
offFocus={() => setProductsList([])}
|
|
||||||
onChangeText={text => filterProductsList(text)}
|
onChangeText={text => filterProductsList(text)}
|
||||||
value={item}
|
value={item}
|
||||||
onFocus={() => setFocussed(true)}
|
onFocus={() => setFocussed(true)}
|
||||||
onEndEditing={() => setFocussed(false)}
|
onEndEditing={() => setFocussed(false)}
|
||||||
/>
|
/>
|
||||||
|
{item ? <MaterialCommunityIcons style = {{right:15}}name="check" color={COLORS.primary} size={25} /> : <MaterialCommunityIcons style = {{right:10, bottom: 10,}}name="asterisk" color={COLORS.actionCancel + 'aa'} size={12} />}
|
||||||
<ScrollView style={styles.dropdown} keyboardShouldPersistTaps={'always'}>
|
<ScrollView style={styles.dropdown} keyboardShouldPersistTaps={'always'}>
|
||||||
|
|
||||||
{focussed ? productsList.map((product, index) =>
|
{focussed ? productsList.map((product, index) =>
|
||||||
@@ -119,7 +112,8 @@ export default AddItemModal = () => {
|
|||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</View>
|
</View>
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-start' }}>
|
<View style={styles.inputRow}>
|
||||||
|
<MaterialCommunityIcons name="label-percent-outline" color={COLORS.textW0 + '55'} size={30} />
|
||||||
<TextInput
|
<TextInput
|
||||||
placeholder={'Amount'}
|
placeholder={'Amount'}
|
||||||
placeholderTextColor={'grey'}
|
placeholderTextColor={'grey'}
|
||||||
@@ -128,8 +122,10 @@ export default AddItemModal = () => {
|
|||||||
value={amount}
|
value={amount}
|
||||||
keyboardType={'number-pad'}
|
keyboardType={'number-pad'}
|
||||||
/>
|
/>
|
||||||
|
{amount ? <MaterialCommunityIcons style = {{right:15}}name="check" color={COLORS.primary} size={25} /> : <MaterialCommunityIcons style = {{right:10, bottom: 10,}}name="asterisk" color={COLORS.actionCancel + 'aa'} size={12} />}
|
||||||
</View>
|
</View>
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-start' }}>
|
<View style={styles.inputRow}>
|
||||||
|
<MaterialCommunityIcons name="account-supervisor-circle" color={COLORS.textW0 + '55'} size={30} />
|
||||||
<TextInput
|
<TextInput
|
||||||
placeholder={'For'}
|
placeholder={'For'}
|
||||||
placeholderTextColor={'grey'}
|
placeholderTextColor={'grey'}
|
||||||
@@ -137,8 +133,10 @@ export default AddItemModal = () => {
|
|||||||
onChangeText={text => setPerson(text)}
|
onChangeText={text => setPerson(text)}
|
||||||
value={person}
|
value={person}
|
||||||
/>
|
/>
|
||||||
|
{person ? <MaterialCommunityIcons style = {{right:15}}name="check" color={COLORS.primary} size={25} /> : <View/>}
|
||||||
</View>
|
</View>
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-start' }}>
|
<View style={styles.inputRow}>
|
||||||
|
<MaterialCommunityIcons name="folder-information-outline" color={COLORS.textW0 + '55'} size={30} />
|
||||||
<TextInput
|
<TextInput
|
||||||
placeholder={'Additional details'}
|
placeholder={'Additional details'}
|
||||||
placeholderTextColor={'grey'}
|
placeholderTextColor={'grey'}
|
||||||
@@ -146,9 +144,10 @@ export default AddItemModal = () => {
|
|||||||
onChangeText={text => setDetails(text)}
|
onChangeText={text => setDetails(text)}
|
||||||
value={details}
|
value={details}
|
||||||
/>
|
/>
|
||||||
|
{details ? <MaterialCommunityIcons style = {{right:15}}name="check" color={COLORS.primary} size={25} /> : <View/>}
|
||||||
</View>
|
</View>
|
||||||
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-evenly', marginTop: 20, marginBottom: 10, }}>
|
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-evenly', marginTop: 20, marginBottom: 10, }}>
|
||||||
<TouchableOpacity title="Hide modal" style={styles.modalCloseButton} onPress={closeModal} >
|
<TouchableOpacity onPress={closeModal} >
|
||||||
<Text style={styles.modalCloseButtonText}>Cancel</Text>
|
<Text style={styles.modalCloseButtonText}>Cancel</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<View style={{
|
<View style={{
|
||||||
@@ -159,7 +158,7 @@ export default AddItemModal = () => {
|
|||||||
height: '80%',
|
height: '80%',
|
||||||
|
|
||||||
}} />
|
}} />
|
||||||
<TouchableOpacity title="Hide modal" style={styles.modalAddButton} onPress={toggleModal} >
|
<TouchableOpacity onPress={toggleModal} >
|
||||||
<Text style={styles.modalAddButtonText}>Add item</Text>
|
<Text style={styles.modalAddButtonText}>Add item</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
@@ -173,6 +172,18 @@ const styles = StyleSheet.create({
|
|||||||
modalAddItem: {
|
modalAddItem: {
|
||||||
margin: 0,
|
margin: 0,
|
||||||
},
|
},
|
||||||
|
image: {
|
||||||
|
position: 'absolute',
|
||||||
|
right:0,
|
||||||
|
top: 0,
|
||||||
|
bottom: 0,
|
||||||
|
opacity: 0.04,
|
||||||
|
width: 200,
|
||||||
|
|
||||||
|
|
||||||
|
borderTopLeftRadius: 150,
|
||||||
|
borderBottomLeftRadius: 150,
|
||||||
|
},
|
||||||
modalHeaderText: {
|
modalHeaderText: {
|
||||||
opacity: 0.9,
|
opacity: 0.9,
|
||||||
fontSize: 23,
|
fontSize: 23,
|
||||||
@@ -187,20 +198,20 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
modalAddButtonText: {
|
modalAddButtonText: {
|
||||||
opacity: 0.8,
|
opacity: 0.8,
|
||||||
fontSize: 16,
|
fontSize: 18,
|
||||||
color: COLORS.primary,
|
color: COLORS.primary,
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
},
|
},
|
||||||
modalCloseButtonText: {
|
modalCloseButtonText: {
|
||||||
opacity: 0.8,
|
opacity: 0.8,
|
||||||
fontSize: 16,
|
fontSize: 18,
|
||||||
color: COLORS.primary,
|
color: COLORS.primary,
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
},
|
},
|
||||||
textInput: {
|
textInput: {
|
||||||
|
|
||||||
height: 25,
|
height: 25,
|
||||||
width: '80%',
|
width: '70%',
|
||||||
left: 10,
|
left: 10,
|
||||||
|
|
||||||
borderBottomColor: COLORS.primary + 'aa',
|
borderBottomColor: COLORS.primary + 'aa',
|
||||||
@@ -209,12 +220,18 @@ const styles = StyleSheet.create({
|
|||||||
marginTop: 10,
|
marginTop: 10,
|
||||||
padding: 0,
|
padding: 0,
|
||||||
paddingLeft: 5,
|
paddingLeft: 5,
|
||||||
paddingRight: 5,
|
paddingRight: 25,
|
||||||
|
|
||||||
color: COLORS.textW0,
|
color: COLORS.textW0,
|
||||||
fontSize: 18
|
fontSize: 18
|
||||||
|
|
||||||
},
|
},
|
||||||
|
inputRow: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'flex-end',
|
||||||
|
justifyContent: 'flex-start'
|
||||||
|
},
|
||||||
|
|
||||||
dropdown: {
|
dropdown: {
|
||||||
|
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
@@ -232,8 +249,8 @@ const styles = StyleSheet.create({
|
|||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
width: 150,
|
width: 150,
|
||||||
minHeight: 20,
|
minHeight: 20,
|
||||||
borderBottomWidth: 1.2,
|
borderBottomWidth: 1.0,
|
||||||
borderColor: '#666' + 'e',
|
borderColor: '#666' + '5',
|
||||||
},
|
},
|
||||||
dropdownText: {
|
dropdownText: {
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
|
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { StyleSheet, TouchableOpacity, View, Text, TextInput, Image, ScrollView } from 'react-native';
|
import { StyleSheet, TouchableOpacity, View, Text, TextInput, Image, ScrollView } from 'react-native';
|
||||||
|
|
||||||
|
//dependencies
|
||||||
import Modal from 'react-native-modal';
|
import Modal from 'react-native-modal';
|
||||||
|
|
||||||
//themes
|
//themes
|
||||||
import { COLORS } from '../../../themes/Colors';
|
import { COLORS } from '../../../themes/Colors';
|
||||||
|
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||||
|
|
||||||
//redux
|
//redux
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
@@ -23,14 +26,10 @@ export default AddProductModal = () => {
|
|||||||
|
|
||||||
//tags
|
//tags
|
||||||
const tags = useSelector(state => state.tags)
|
const tags = useSelector(state => state.tags)
|
||||||
let newTagsList = [];
|
const [tagsList, setTagsList] = useState(tags.map((listTag) => listTag.tagName));
|
||||||
for (let i = 0; i < tags.length; i++) {
|
|
||||||
newTagsList.push(tags[i].tagName);
|
|
||||||
}
|
|
||||||
const [tagsList, setTagsList] = useState(newTagsList);
|
|
||||||
|
|
||||||
const [focussed, setFocussed] = useState(false);
|
const [focussed, setFocussed] = useState(false);
|
||||||
|
|
||||||
|
|
||||||
const filterTagsList = (text) => {
|
const filterTagsList = (text) => {
|
||||||
let regex = new RegExp(text);
|
let regex = new RegExp(text);
|
||||||
|
|
||||||
@@ -61,6 +60,7 @@ export default AddProductModal = () => {
|
|||||||
setProduct('');
|
setProduct('');
|
||||||
setTag('');
|
setTag('');
|
||||||
setPrice();
|
setPrice();
|
||||||
|
setFocussed(false)
|
||||||
setImage('https://icons-for-free.com/iconfiles/png/512/linecon+products+round+icon-1320165923260225670.png');
|
setImage('https://icons-for-free.com/iconfiles/png/512/linecon+products+round+icon-1320165923260225670.png');
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -70,7 +70,9 @@ export default AddProductModal = () => {
|
|||||||
setTag();
|
setTag();
|
||||||
setPrice();
|
setPrice();
|
||||||
setImage('https://icons-for-free.com/iconfiles/png/512/linecon+products+round+icon-1320165923260225670.png');
|
setImage('https://icons-for-free.com/iconfiles/png/512/linecon+products+round+icon-1320165923260225670.png');
|
||||||
|
setFocussed(false)
|
||||||
dispatch(toggleVisibility('addProductModalVisible'));
|
dispatch(toggleVisibility('addProductModalVisible'));
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -83,7 +85,6 @@ export default AddProductModal = () => {
|
|||||||
borderRadius: 10,
|
borderRadius: 10,
|
||||||
padding: 5,
|
padding: 5,
|
||||||
backgroundColor: COLORS.dp01,
|
backgroundColor: COLORS.dp01,
|
||||||
|
|
||||||
}}>
|
}}>
|
||||||
<Text style={styles.modalHeaderText}>Add product</Text>
|
<Text style={styles.modalHeaderText}>Add product</Text>
|
||||||
|
|
||||||
@@ -108,7 +109,6 @@ export default AddProductModal = () => {
|
|||||||
placeholderTextColor={'grey'}
|
placeholderTextColor={'grey'}
|
||||||
style={[styles.textInput]}
|
style={[styles.textInput]}
|
||||||
value={tag}
|
value={tag}
|
||||||
offFocus={() => setTagsList([])}
|
|
||||||
onChangeText={text => filterTagsList(text)}
|
onChangeText={text => filterTagsList(text)}
|
||||||
onFocus={() => setFocussed(true)}
|
onFocus={() => setFocussed(true)}
|
||||||
onEndEditing={() => setFocussed(false)}
|
onEndEditing={() => setFocussed(false)}
|
||||||
@@ -136,7 +136,7 @@ export default AddProductModal = () => {
|
|||||||
placeholder={'Image url'}
|
placeholder={'Image url'}
|
||||||
placeholderTextColor={'grey'}
|
placeholderTextColor={'grey'}
|
||||||
style={styles.textInput}
|
style={styles.textInput}
|
||||||
onChangeText={text => { if (text !== '') { return setImage(text) } }}
|
onChangeText={text => { if (text !== '') { return setImage(`https://www.googleapis.com/customsearch/v1?key=${product}&cx=017576662512468239146:omuauf_lfve&q=lectures`) } }}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
@@ -168,7 +168,7 @@ export default AddProductModal = () => {
|
|||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
//modals
|
//modals
|
||||||
modalAddItem: {
|
modalAddProduct: {
|
||||||
margin: 0,
|
margin: 0,
|
||||||
},
|
},
|
||||||
modalHeaderText: {
|
modalHeaderText: {
|
||||||
@@ -236,7 +236,9 @@ const styles = StyleSheet.create({
|
|||||||
|
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
width: 150,
|
width: 150,
|
||||||
minHeight: 20
|
minHeight: 20,
|
||||||
|
borderBottomWidth: 1.0,
|
||||||
|
borderColor: '#666' + '5',
|
||||||
},
|
},
|
||||||
dropdownText: {
|
dropdownText: {
|
||||||
|
|
||||||
|
|||||||
183
src/components/groceryComponents/modals/EditItemModal.js
Normal file
183
src/components/groceryComponents/modals/EditItemModal.js
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { StyleSheet, TouchableOpacity, View, Text, TextInput, Image, FlatList, ScrollView } from 'react-native';
|
||||||
|
//dependencies
|
||||||
|
import Modal from 'react-native-modal';
|
||||||
|
|
||||||
|
//themes
|
||||||
|
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||||
|
import { COLORS } from '../../../themes/Colors';
|
||||||
|
|
||||||
|
//redux
|
||||||
|
import { useDispatch , useSelector} from 'react-redux';
|
||||||
|
import { modalToggle, editItem } from '../../../redux/slices/groceryList/itemsSlice';
|
||||||
|
|
||||||
|
export default EditItemModal = (props) => {
|
||||||
|
|
||||||
|
const item = useSelector(state => state.items.find((item) => item.modalVisible === true));
|
||||||
|
let product = useSelector(state => state.products.find((product) => product.id === item.productId))
|
||||||
|
if (!product) {
|
||||||
|
product = {
|
||||||
|
productName: props.id,
|
||||||
|
tag: 'uncathegorized',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const tags = useSelector(state => state.tags)
|
||||||
|
let tag = tags.find(tag => tag.tagName === product.tag)
|
||||||
|
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
const [amount, setAmount] = useState(item.amount.toString());
|
||||||
|
const [person, setPerson] = useState(item.person);
|
||||||
|
const [details, setDetails] = useState(item.details);
|
||||||
|
|
||||||
|
const saveModal = () => {
|
||||||
|
dispatch(modalToggle(item.productId))
|
||||||
|
dispatch(editItem(item.productId, amount, person, details));
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Modal isVisible={item.modalVisible} animationIn={'slideInUp'} animationOut={'slideOutDown'}
|
||||||
|
onBackdropPress={saveModal}
|
||||||
|
onBackButtonPress={()=>dispatch(modalToggle(item.productId))}
|
||||||
|
swipeDirection={'down'}
|
||||||
|
onSwipeComplete={saveModal}
|
||||||
|
useNativeDriverForBackdrop
|
||||||
|
style={styles.modalEditItem} >
|
||||||
|
<View style={styles.container}>
|
||||||
|
|
||||||
|
<View style={{ width: '100%', flexDirection: 'row', alignItems: 'flex-start', justifyContent: 'flex-start', backgroundColor: tag.color + '22', borderRadius: 10, }}>
|
||||||
|
{product.price ? <Text style={[styles.textPrice, { color: COLORS.textW0 + 'de', }]}>€{product.price}</Text> : <View />}
|
||||||
|
<Image source={{ uri: product.image }}
|
||||||
|
style={styles.image} />
|
||||||
|
<Text style={[styles.textTags, { color: tag.color, }]}>{tag.tagName}</Text>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.textItem}>{product.productName}</Text>
|
||||||
|
|
||||||
|
<View style={styles.inputRow}>
|
||||||
|
<MaterialCommunityIcons name="label-percent-outline" color={COLORS.textW0 + '55'} size={30} />
|
||||||
|
<TextInput
|
||||||
|
placeholder={'Amount'}
|
||||||
|
placeholderTextColor={'grey'}
|
||||||
|
style={[styles.textInput]}
|
||||||
|
onChangeText={text => setAmount(text)}
|
||||||
|
value={amount}
|
||||||
|
keyboardType={'number-pad'}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<View style={styles.inputRow}>
|
||||||
|
<MaterialCommunityIcons name="account-supervisor-circle" color={COLORS.textW0 + '55'} size={30} />
|
||||||
|
<TextInput
|
||||||
|
placeholder={'For'}
|
||||||
|
placeholderTextColor={'grey'}
|
||||||
|
style={styles.textInput}
|
||||||
|
onChangeText={text => setPerson(text)}
|
||||||
|
value={person}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<View style={styles.inputRow}>
|
||||||
|
<MaterialCommunityIcons name="pencil-plus-outline" color={COLORS.textW0 + '55'} size={30} />
|
||||||
|
<TextInput
|
||||||
|
placeholder={'Additional details'}
|
||||||
|
placeholderTextColor={'grey'}
|
||||||
|
style={styles.textInput}
|
||||||
|
onChangeText={text => setDetails(text)}
|
||||||
|
value={details}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<TouchableOpacity style={styles.modalSaveButton} onPress={saveModal} >
|
||||||
|
<Text style={styles.modalSaveButtonText}>Save</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
|
||||||
|
</Modal >
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
borderTopLeftRadius: 10,
|
||||||
|
borderTopRightRadius: 10,
|
||||||
|
minHeight: '60%',
|
||||||
|
backgroundColor: COLORS.dp01,
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
modalEditItem: {
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
margin: 0,
|
||||||
|
padding: 0,
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
image: {
|
||||||
|
marginTop: -70,
|
||||||
|
width: '50%',
|
||||||
|
height: 180,
|
||||||
|
alignSelf: 'flex-start',
|
||||||
|
borderTopRightRadius: 20,
|
||||||
|
},
|
||||||
|
|
||||||
|
textInput: {
|
||||||
|
|
||||||
|
height: 30,
|
||||||
|
width: '85%',
|
||||||
|
borderBottomColor: COLORS.primary + 'aa',
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderRadius: 3,
|
||||||
|
marginBottom: 10,
|
||||||
|
padding: 0,
|
||||||
|
paddingLeft: 5,
|
||||||
|
paddingRight: 5,
|
||||||
|
|
||||||
|
color: COLORS.textW0 + 'dd',
|
||||||
|
fontSize: 20
|
||||||
|
|
||||||
|
},
|
||||||
|
inputRow: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
justifyContent: 'flex-start',
|
||||||
|
width: '100%',
|
||||||
|
marginLeft: 5,
|
||||||
|
},
|
||||||
|
textItem: {
|
||||||
|
width: '100%',
|
||||||
|
alignSelf: 'flex-start',
|
||||||
|
padding: 5,
|
||||||
|
paddingLeft: 15,
|
||||||
|
|
||||||
|
opacity: 0.9,
|
||||||
|
fontSize: 24,
|
||||||
|
color: COLORS.textW0 + 'ff',
|
||||||
|
backgroundColor: '#000' + '3',
|
||||||
|
},
|
||||||
|
textPrice: {
|
||||||
|
paddingLeft: '52%',
|
||||||
|
position: 'absolute',
|
||||||
|
fontSize: 18,
|
||||||
|
color: COLORS.textW1,
|
||||||
|
backgroundColor: '#000' + '5',
|
||||||
|
padding: 5,
|
||||||
|
width: '100%',
|
||||||
|
borderTopRightRadius: 10,
|
||||||
|
},
|
||||||
|
textTags: {
|
||||||
|
left: 8,
|
||||||
|
marginTop: 35,
|
||||||
|
fontFamily: 'Roboto',
|
||||||
|
fontSize: 18,
|
||||||
|
color: COLORS.textW1,
|
||||||
|
},
|
||||||
|
|
||||||
|
modalSaveButtonText: {
|
||||||
|
opacity: 0.8,
|
||||||
|
fontSize: 20,
|
||||||
|
color: COLORS.primary,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
},
|
||||||
|
modalSaveButton:{
|
||||||
|
marginTop: 10,
|
||||||
|
marginBottom: 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
171
src/components/groceryComponents/modals/EditProductModal.js
Normal file
171
src/components/groceryComponents/modals/EditProductModal.js
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { StyleSheet, TouchableOpacity, View, Text, TextInput, Image, FlatList, ScrollView } from 'react-native';
|
||||||
|
//dependencies
|
||||||
|
import Modal from 'react-native-modal';
|
||||||
|
|
||||||
|
//themes
|
||||||
|
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||||
|
import { COLORS } from '../../../themes/Colors';
|
||||||
|
|
||||||
|
//redux
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
import { modalToggle, editProduct } from '../../../redux/slices/groceryList/productsSlice';
|
||||||
|
|
||||||
|
export default EditProductModal = () => {
|
||||||
|
|
||||||
|
const product = useSelector(state => state.products.find((product) => product.modalVisible === true));
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const tags = useSelector(state => state.tags)
|
||||||
|
let tag = tags.find(tag => tag.tagName === product.tag)
|
||||||
|
|
||||||
|
const [productName, setProductName] = useState(product.productName);
|
||||||
|
const [tagName, setTagName] = useState(product.tag);
|
||||||
|
const [price, setPrice] = useState(product.price.toString());
|
||||||
|
const [imageURL, setImageURL] = useState(product.image);
|
||||||
|
|
||||||
|
const saveModal = () => {
|
||||||
|
dispatch(editProduct(product.id, productName, tagName, price, imageURL));
|
||||||
|
dispatch(modalToggle(product.id))
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Modal isVisible={product.modalVisible} animationIn={'slideInUp'} animationOut={'slideOutDown'}
|
||||||
|
onBackdropPress={saveModal}
|
||||||
|
onBackButtonPress={() => dispatch(modalToggle(product.id))}
|
||||||
|
swipeDirection={'down'}
|
||||||
|
onSwipeComplete={saveModal}
|
||||||
|
useNativeDriverForBackdrop
|
||||||
|
style={styles.modalEditItem} >
|
||||||
|
<View style={styles.container}>
|
||||||
|
<View style={{ width: '100%', flexDirection: 'row', alignItems: 'flex-start', justifyContent: 'flex-start', backgroundColor: tag.color + '22', borderRadius: 10, }}>
|
||||||
|
<Image source={{ uri: product.image }}
|
||||||
|
style={styles.image} />
|
||||||
|
</View>
|
||||||
|
<View style={styles.inputRow}>
|
||||||
|
<TextInput
|
||||||
|
placeholder={'Product'}
|
||||||
|
placeholderTextColor={'grey'}
|
||||||
|
style={[styles.textInput, styles.textItem]}
|
||||||
|
onChangeText={text => setProductName(text)}
|
||||||
|
value={productName}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</View>
|
||||||
|
<View style={styles.inputRow}>
|
||||||
|
<MaterialCommunityIcons name="tag-text-outline" color={COLORS.textW0 + '55'} size={30} />
|
||||||
|
<TextInput
|
||||||
|
placeholder={'Tag'}
|
||||||
|
placeholderTextColor={'grey'}
|
||||||
|
style={styles.textInput}
|
||||||
|
onChangeText={text => setTagName(text)}
|
||||||
|
value={tagName}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<View style={styles.inputRow}>
|
||||||
|
<MaterialCommunityIcons name="currency-usd" color={COLORS.textW0 + '55'} size={30} />
|
||||||
|
<TextInput
|
||||||
|
placeholder={'Price'}
|
||||||
|
placeholderTextColor={'grey'}
|
||||||
|
style={styles.textInput}
|
||||||
|
onChangeText={text => setPrice(text)}
|
||||||
|
keyboardType={'number-pad'}
|
||||||
|
value={price}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<TouchableOpacity style={styles.modalSaveButton} onPress={saveModal} >
|
||||||
|
<Text style={styles.modalSaveButtonText}>Save</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
|
||||||
|
</Modal >
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
borderTopLeftRadius: 10,
|
||||||
|
borderTopRightRadius: 10,
|
||||||
|
minHeight: '60%',
|
||||||
|
backgroundColor: COLORS.dp01,
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
modalEditItem: {
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
margin: 0,
|
||||||
|
padding: 0,
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
image: {
|
||||||
|
marginTop: -70,
|
||||||
|
width: '50%',
|
||||||
|
height: 180,
|
||||||
|
alignSelf: 'flex-start',
|
||||||
|
borderTopRightRadius: 20,
|
||||||
|
},
|
||||||
|
|
||||||
|
textInput: {
|
||||||
|
|
||||||
|
height: 30,
|
||||||
|
width: '85%',
|
||||||
|
borderBottomColor: COLORS.primary + 'aa',
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderRadius: 3,
|
||||||
|
marginBottom: 10,
|
||||||
|
padding: 0,
|
||||||
|
paddingLeft: 5,
|
||||||
|
paddingRight: 5,
|
||||||
|
|
||||||
|
color: COLORS.textW0 + 'dd',
|
||||||
|
fontSize: 20
|
||||||
|
|
||||||
|
},
|
||||||
|
inputRow: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
justifyContent: 'flex-start',
|
||||||
|
width: '100%',
|
||||||
|
marginLeft: 5,
|
||||||
|
},
|
||||||
|
textItem: {
|
||||||
|
width: '100%',
|
||||||
|
height: 40,
|
||||||
|
alignSelf: 'flex-start',
|
||||||
|
padding: 5,
|
||||||
|
paddingLeft: 15,
|
||||||
|
|
||||||
|
opacity: 0.9,
|
||||||
|
fontSize: 24,
|
||||||
|
color: COLORS.textW0 + 'ff',
|
||||||
|
backgroundColor: '#000' + '3',
|
||||||
|
},
|
||||||
|
textPrice: {
|
||||||
|
paddingLeft: '52%',
|
||||||
|
position: 'absolute',
|
||||||
|
fontSize: 18,
|
||||||
|
color: COLORS.textW1,
|
||||||
|
backgroundColor: '#000' + '5',
|
||||||
|
padding: 5,
|
||||||
|
width: '100%',
|
||||||
|
borderTopRightRadius: 10,
|
||||||
|
},
|
||||||
|
textTags: {
|
||||||
|
left: 8,
|
||||||
|
marginTop: 35,
|
||||||
|
fontFamily: 'Roboto',
|
||||||
|
fontSize: 18,
|
||||||
|
color: COLORS.textW1,
|
||||||
|
},
|
||||||
|
|
||||||
|
modalSaveButtonText: {
|
||||||
|
opacity: 0.8,
|
||||||
|
fontSize: 20,
|
||||||
|
color: COLORS.primary,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
},
|
||||||
|
modalSaveButton: {
|
||||||
|
marginTop: 10,
|
||||||
|
marginBottom: 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
@@ -4,10 +4,11 @@ const initialState = [
|
|||||||
{
|
{
|
||||||
amount: 5,
|
amount: 5,
|
||||||
person: 'Wolf',
|
person: 'Wolf',
|
||||||
details: 'margarita',
|
details: 'Gezout',
|
||||||
|
|
||||||
productId: '20fdc79cde62',
|
productId: '20fdc79cde62',
|
||||||
checked: false,
|
checked: false,
|
||||||
|
modalVisible: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
amount: 12,
|
amount: 12,
|
||||||
@@ -15,6 +16,7 @@ const initialState = [
|
|||||||
|
|
||||||
productId: '20fdc79cde63',
|
productId: '20fdc79cde63',
|
||||||
checked: false,
|
checked: false,
|
||||||
|
modalVisible: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
amount: 2,
|
amount: 2,
|
||||||
@@ -22,14 +24,25 @@ const initialState = [
|
|||||||
|
|
||||||
productId: '20fdc79cde64',
|
productId: '20fdc79cde64',
|
||||||
checked: false,
|
checked: false,
|
||||||
|
modalVisible: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
amount: 2,
|
amount: 4,
|
||||||
person: 'Storm',
|
person: 'Storm',
|
||||||
details: 'Gezout',
|
details: 'margarita',
|
||||||
|
|
||||||
productId: '20fdc79cde60',
|
productId: '20fdc79cde60',
|
||||||
checked: false,
|
checked: false,
|
||||||
|
modalVisible: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
amount: 3,
|
||||||
|
person: 'Wolfje',
|
||||||
|
details: 'Aardbei',
|
||||||
|
|
||||||
|
productId: 'Jam',
|
||||||
|
checked: false,
|
||||||
|
modalVisible: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
]
|
]
|
||||||
@@ -40,7 +53,13 @@ const itemsSlice = createSlice({
|
|||||||
reducers: {
|
reducers: {
|
||||||
itemAdded: {
|
itemAdded: {
|
||||||
reducer(state, action) {
|
reducer(state, action) {
|
||||||
state.push(action.payload);
|
let item = state.find((item) => item.productId === action.payload.productId)
|
||||||
|
if (item) {
|
||||||
|
item.amount += action.payload.amount;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
state.push(action.payload);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
prepare(productId, amount, person, details) {
|
prepare(productId, amount, person, details) {
|
||||||
return {
|
return {
|
||||||
@@ -50,6 +69,7 @@ const itemsSlice = createSlice({
|
|||||||
details: details,
|
details: details,
|
||||||
|
|
||||||
productId: productId,
|
productId: productId,
|
||||||
|
modalVisible: false,
|
||||||
checked: false,
|
checked: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,7 +77,8 @@ const itemsSlice = createSlice({
|
|||||||
},
|
},
|
||||||
checkToggle: {
|
checkToggle: {
|
||||||
reducer(state, action) {
|
reducer(state, action) {
|
||||||
state.find((item) => item.productId === action.payload.productId).checked = !state.find((item) => item.productId === action.payload.productId).checked;
|
let item = state.find((item) => item.productId === action.payload.productId)
|
||||||
|
item.checked = !item.checked
|
||||||
},
|
},
|
||||||
prepare(productId) {
|
prepare(productId) {
|
||||||
return {
|
return {
|
||||||
@@ -67,25 +88,48 @@ const itemsSlice = createSlice({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
amountUp: {
|
modalToggle: {
|
||||||
reducer(state, action) {
|
reducer(state, action) {
|
||||||
state.find((item) => item.productId === action.payload.id).amount += Number(action.payload.amount);
|
let item = state.find((item) => item.productId === action.payload.productId)
|
||||||
|
if (!state.find((item) => item.modalVisible === true) || item.modalVisible) {
|
||||||
|
item.modalVisible = !item.modalVisible;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
prepare(id, amount) {
|
prepare(productId) {
|
||||||
return {
|
return {
|
||||||
payload: {
|
payload: {
|
||||||
id,
|
productId: productId
|
||||||
amount,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
removeCheckedItems(state){
|
removeCheckedItems(state) {
|
||||||
return state.filter(item=>item.checked === false)
|
return state.filter(item => item.checked === false)
|
||||||
|
},
|
||||||
|
editItem: {
|
||||||
|
reducer(state, action) {
|
||||||
|
const { productId, amount, person, details } = action.payload
|
||||||
|
let item = state.find((item) => item.productId === productId)
|
||||||
|
item.productId = productId
|
||||||
|
item.amount = amount
|
||||||
|
item.person = person
|
||||||
|
item.details = details
|
||||||
|
},
|
||||||
|
prepare(productId, amount, person, details) {
|
||||||
|
return {
|
||||||
|
payload: {
|
||||||
|
amount: Number(amount),
|
||||||
|
person: person,
|
||||||
|
details: details,
|
||||||
|
|
||||||
|
productId: productId,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const { itemAdded, checkToggle, amountUp, removeCheckedItems } = itemsSlice.actions;
|
export const { itemAdded, checkToggle, modalToggle, removeCheckedItems, editItem } = itemsSlice.actions;
|
||||||
|
|
||||||
export default itemsSlice.reducer;
|
export default itemsSlice.reducer;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { createSlice } from '@reduxjs/toolkit';
|
import { createSlice, nanoid } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
const initialState = [
|
const initialState = [
|
||||||
{
|
{
|
||||||
@@ -9,6 +9,7 @@ const initialState = [
|
|||||||
nutrients: [{ calories: 120 }, { proteins: 20 }],
|
nutrients: [{ calories: 120 }, { proteins: 20 }],
|
||||||
|
|
||||||
|
|
||||||
|
modalVisible: false,
|
||||||
checked: false,
|
checked: false,
|
||||||
id: '20fdc79cde60',
|
id: '20fdc79cde60',
|
||||||
},
|
},
|
||||||
@@ -18,6 +19,7 @@ const initialState = [
|
|||||||
image: 'https://www.kitchensanctuary.com/wp-content/uploads/2020/10/Lasagne-square-FS-79.jpg',
|
image: 'https://www.kitchensanctuary.com/wp-content/uploads/2020/10/Lasagne-square-FS-79.jpg',
|
||||||
price: 1.99,
|
price: 1.99,
|
||||||
|
|
||||||
|
modalVisible: false,
|
||||||
checked: false,
|
checked: false,
|
||||||
id: '20fdc79cde64',
|
id: '20fdc79cde64',
|
||||||
},
|
},
|
||||||
@@ -28,19 +30,54 @@ const initialState = [
|
|||||||
nutrients: [{ calories: 120 }, { proteins: 20 }],
|
nutrients: [{ calories: 120 }, { proteins: 20 }],
|
||||||
price: 1.39,
|
price: 1.39,
|
||||||
|
|
||||||
|
modalVisible: false,
|
||||||
checked: false,
|
checked: false,
|
||||||
id: '20fdc79cde63',
|
id: '20fdc79cde63',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
productName: 'Gedroogde worstjes',
|
productName: 'Dried sausages',
|
||||||
tag: 'Snack',
|
tag: 'Meat',
|
||||||
image: 'https://www.aldi.be/content/aldi/belgium/promotions/source-localenhancement/2019/2019-01/2019-01-02/vast_assortiment/1308/1/0/_jcr_content/assets/imported-images/BILD_INTERNET2/1308_PRIMARY_0_nl-fr-de_Mini_sticks_100_g_Panda_GROEP.png/_jcr_content/renditions/opt.1250w.png.res/1590539744886/opt.1250w.png',
|
image: 'https://www.aldi.be/content/aldi/belgium/promotions/source-localenhancement/2019/2019-01/2019-01-02/vast_assortiment/1308/1/0/_jcr_content/assets/imported-images/BILD_INTERNET2/1308_PRIMARY_0_nl-fr-de_Mini_sticks_100_g_Panda_GROEP.png/_jcr_content/renditions/opt.1250w.png.res/1590539744886/opt.1250w.png',
|
||||||
price: 1.79,
|
price: 1.79,
|
||||||
|
|
||||||
|
|
||||||
|
modalVisible: false,
|
||||||
checked: false,
|
checked: false,
|
||||||
id: '20fdc79cde62',
|
id: '20fdc79cde62',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
productName: 'Minced meat',
|
||||||
|
tag: 'Meat',
|
||||||
|
image: 'https://www.aldi.nl/content/dam/aldi/netherlands/offers/weekactie/2020/wk19/1387_01.png/_jcr_content/renditions/opt.1250w.png.res/1587557386020/opt.1250w.png',
|
||||||
|
price: 3.99,
|
||||||
|
|
||||||
|
|
||||||
|
modalVisible: false,
|
||||||
|
checked: false,
|
||||||
|
id: '20adc79cde61',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
productName: 'Veggie soup',
|
||||||
|
tag: 'Vegetables & fruit',
|
||||||
|
image: 'https://www.cookingclassy.com/wp-content/uploads/2014/10/vegetable-soup-7.jpg',
|
||||||
|
price: 1.49,
|
||||||
|
|
||||||
|
|
||||||
|
modalVisible: false,
|
||||||
|
checked: false,
|
||||||
|
id: '20fdc29cde61',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
productName: 'Dorito\'s',
|
||||||
|
tag: 'Snack',
|
||||||
|
image: 'https://40aprons.com/wp-content/uploads/2020/09/taco-bell-nacho-cheese-sauce-recipe-4.jpg',
|
||||||
|
price: 1.12,
|
||||||
|
|
||||||
|
|
||||||
|
modalVisible: false,
|
||||||
|
checked: false,
|
||||||
|
id: '29fdc29cde61',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
productName: 'Berliner ball',
|
productName: 'Berliner ball',
|
||||||
tag: 'Snack',
|
tag: 'Snack',
|
||||||
@@ -48,8 +85,9 @@ const initialState = [
|
|||||||
price: 1.79,
|
price: 1.79,
|
||||||
|
|
||||||
|
|
||||||
|
modalVisible: false,
|
||||||
checked: false,
|
checked: false,
|
||||||
id: '20fdc79cde61',
|
id: '20fdc71cde61',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -61,24 +99,49 @@ const productsSlice = createSlice({
|
|||||||
reducer(state, action) {
|
reducer(state, action) {
|
||||||
state.push(action.payload);
|
state.push(action.payload);
|
||||||
},
|
},
|
||||||
prepare(productName, tag, price, image, nutrients) {
|
prepare(productName, tag, price, image) {
|
||||||
return {
|
return {
|
||||||
payload: {
|
payload: {
|
||||||
productName,
|
productName,
|
||||||
tag,
|
tag,
|
||||||
price,
|
price: Number(price),
|
||||||
image,
|
image,
|
||||||
nutrients,
|
|
||||||
|
|
||||||
id: Math.floor((1 + Math.random()) * 0x1000000000000).toString(16).substring(1),
|
modalVisible: false,
|
||||||
checked: false,
|
checked: false,
|
||||||
|
|
||||||
|
id: nanoid(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
editProduct: {
|
||||||
|
reducer(state, action) {
|
||||||
|
const { productId, productName, tag, price, image } = action.payload
|
||||||
|
let product = state.find((product) => product.id === productId)
|
||||||
|
|
||||||
|
product.productName = productName
|
||||||
|
product.tag = tag
|
||||||
|
product.price = price
|
||||||
|
product.image = image
|
||||||
|
},
|
||||||
|
prepare(productId, productName, tag, price, image) {
|
||||||
|
return {
|
||||||
|
payload: {
|
||||||
|
productId: productId,
|
||||||
|
|
||||||
|
productName: productName,
|
||||||
|
tag: tag,
|
||||||
|
price: price,
|
||||||
|
image: image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
checkToggle: {
|
checkToggle: {
|
||||||
reducer(state, action) {
|
reducer(state, action) {
|
||||||
state.find((product) => product.id === action.payload.id).checked = !state.find((product) => product.id === action.payload.id).checked;
|
let product = state.find((product) => product.id === action.payload.id)
|
||||||
|
product.checked = !product.checked;
|
||||||
},
|
},
|
||||||
prepare(id) {
|
prepare(id) {
|
||||||
return {
|
return {
|
||||||
@@ -88,9 +151,24 @@ const productsSlice = createSlice({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
modalToggle: {
|
||||||
|
reducer(state, action) {
|
||||||
|
let product = state.find((product) => product.id === action.payload.productId)
|
||||||
|
if (!state.find((nProduct) => nProduct.modalVisible === true) || product.modalVisible) {
|
||||||
|
product.modalVisible = !product.modalVisible;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
prepare(productId) {
|
||||||
|
return {
|
||||||
|
payload: {
|
||||||
|
productId: productId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const { productAdded, checkToggle } = productsSlice.actions;
|
export const { productAdded, editProduct, checkToggle, modalToggle } = productsSlice.actions;
|
||||||
|
|
||||||
export default productsSlice.reducer;
|
export default productsSlice.reducer;
|
||||||
@@ -1,13 +1,60 @@
|
|||||||
import {createSlice} from '@reduxjs/toolkit'
|
import { createSlice } from '@reduxjs/toolkit'
|
||||||
|
|
||||||
const initialState = [
|
const initialState = [
|
||||||
|
{ id: '20fdc79cde60', amount: 5 },
|
||||||
]
|
]
|
||||||
|
|
||||||
const storageSlice = createSlice({
|
const storageSlice = createSlice({
|
||||||
name: 'storage',
|
name: 'storage',
|
||||||
initialState,
|
initialState,
|
||||||
reducers:{
|
reducers: {
|
||||||
|
pushItems: {
|
||||||
}
|
reducer(state, action) {
|
||||||
|
action.payload.items.forEach((item) => {
|
||||||
|
let storageItem = state.find((storageItem) => storageItem.id === item.productId)
|
||||||
|
if (storageItem) {
|
||||||
|
state.find((storageItem) => storageItem.id === item.productId).amount += item.amount
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
state.push({ id: item.productId, amount: item.amount })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
prepare(items) {
|
||||||
|
return {
|
||||||
|
payload: {
|
||||||
|
items,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
changeAmount: {
|
||||||
|
reducer(state, action) {
|
||||||
|
state.find((storageItem) => storageItem.id === action.payload.id).amount += action.payload.difference
|
||||||
|
},
|
||||||
|
prepare(id, difference) {
|
||||||
|
return {
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
difference,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
removeItem: {
|
||||||
|
reducer(state, action) {
|
||||||
|
state.splice(state.findIndex((storageItem) => storageItem.id === action.payload.id),1)
|
||||||
|
},
|
||||||
|
prepare(id) {
|
||||||
|
return {
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const { pushItems, changeAmount, removeItem } = storageSlice.actions
|
||||||
|
export default storageSlice.reducer
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { createSlice } from '@reduxjs/toolkit';
|
import { createSlice } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
const initialState = [
|
const initialState = [
|
||||||
{ tagName: 'no-tag', color: '#253f34' },
|
{ tagName: 'uncathegorized', color: '#253f34' },
|
||||||
{ tagName: 'Meat', color: '#ef5350' },
|
{ tagName: 'Meat', color: '#ef5350' },
|
||||||
{ tagName: 'Vegetable', color: '#BDD684' },
|
{ tagName: 'Vegetables & fruit', color: '#BDD684' },
|
||||||
{ tagName: 'Meal', color: '#FA9600' },
|
{ tagName: 'Meal', color: '#FA9600' },
|
||||||
{ tagName: 'Snack', color: '#9575CD' },
|
{ tagName: 'Snack', color: '#9575CD' },
|
||||||
{ tagName: 'Instant', color: '#86CAC5' },
|
{ tagName: 'Instant', color: '#86CAC5' },
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { createSlice } from '@reduxjs/toolkit';
|
|||||||
const initialState = {
|
const initialState = {
|
||||||
addItemModalVisible: false,
|
addItemModalVisible: false,
|
||||||
addProductModalVisible: false,
|
addProductModalVisible: false,
|
||||||
|
|
||||||
popupVisibility: false,
|
popupVisibility: false,
|
||||||
}
|
}
|
||||||
const toggleSlice = createSlice({
|
const toggleSlice = createSlice({
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ import { configureStore } from '@reduxjs/toolkit';
|
|||||||
|
|
||||||
import itemsReducer from './slices/groceryList/itemsSlice';
|
import itemsReducer from './slices/groceryList/itemsSlice';
|
||||||
import productsReducer from './slices/groceryList/productsSlice';
|
import productsReducer from './slices/groceryList/productsSlice';
|
||||||
import toggleReducer from './slices/groceryList/toggleSlice';
|
import storageReducer from './slices/groceryList/storageSlice';
|
||||||
|
|
||||||
import tagsReducer from './slices/groceryList/tagsSlice';
|
import tagsReducer from './slices/groceryList/tagsSlice';
|
||||||
|
import toggleReducer from './slices/groceryList/toggleSlice';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -11,6 +13,8 @@ export default configureStore({
|
|||||||
reducer: {
|
reducer: {
|
||||||
items: itemsReducer,
|
items: itemsReducer,
|
||||||
products: productsReducer,
|
products: productsReducer,
|
||||||
|
storage: storageReducer,
|
||||||
|
|
||||||
tags: tagsReducer,
|
tags: tagsReducer,
|
||||||
toggle: toggleReducer,
|
toggle: toggleReducer,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
import React, { useRef, useEffect, useState } from 'react';
|
import React, { useRef, useEffect, useState } from 'react';
|
||||||
import { StyleSheet, View, ScrollView, Text, Animated, TouchableOpacity, Image } from 'react-native';
|
import { StyleSheet, View, FlatList, Text, Animated, TouchableOpacity, Image } from 'react-native';
|
||||||
|
|
||||||
import { useHeaderHeight } from '@react-navigation/stack';
|
import { useHeaderHeight } from '@react-navigation/stack';
|
||||||
//dependencies\
|
//dependencies\
|
||||||
//components
|
//components
|
||||||
import { AddItemButton, PushItemsToStorageButton, RemoveItemsButton, AddNewRecipeButton } from '../../components/groceryComponents/GroceryListButtons';
|
import { AddItemButton, PushItemsToStorageButton, RemoveItemsButton, AddNewRecipeButton } from '../../components/groceryComponents/GroceryListButtons';
|
||||||
import { ListedItem } from '../../components/groceryComponents/ListedItem';
|
import ListedItem from '../../components/groceryComponents/ListedItem';
|
||||||
|
|
||||||
//redux
|
//redux
|
||||||
|
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
//themes
|
//themes
|
||||||
@@ -98,25 +97,36 @@ const AnimButtons = () => {
|
|||||||
|
|
||||||
|
|
||||||
function GroceryList() {
|
function GroceryList() {
|
||||||
const items = useSelector(state => state.items);
|
const products = useSelector(state=> state.products)
|
||||||
|
|
||||||
const itemList = items.map((item, index) => {
|
const compareFunction = (a,b) => {
|
||||||
return <ListedItem key={index} id={item.productId} />
|
const newA = products.find((product=>product.id === a.productId))
|
||||||
});
|
let tagA
|
||||||
|
newA ? tagA = newA.tag : tagA = "uncathegorized"
|
||||||
|
const newB = products.find((product=>product.id === b.productId))
|
||||||
|
let tagB
|
||||||
|
newB ? tagB = newB.tag : tagB = "uncathegorized"
|
||||||
|
return tagA.localeCompare(tagB)
|
||||||
|
}
|
||||||
|
|
||||||
|
const items = useSelector(state => state.items).slice().sort(compareFunction);
|
||||||
return (
|
return (
|
||||||
<View style={[styles.container]}>
|
<View style={[styles.container]}>
|
||||||
{/* Scroll */}
|
<FlatList
|
||||||
<ScrollView>
|
ListHeaderComponent={<View style={{ height: useHeaderHeight() }} />}
|
||||||
<View style={{ height: useHeaderHeight() }} />
|
ListFooterComponent={<View style={{ height: 100 }} />}
|
||||||
<View style=
|
initialNumToRender={10}
|
||||||
{{
|
maxToRenderPerBatch={10}
|
||||||
top: 5,
|
data={items}
|
||||||
}}>
|
renderItem={({ item }) => (
|
||||||
{itemList}
|
<ListedItem id={item.productId} />
|
||||||
</View>
|
)}
|
||||||
<View style={{ height: 500 }}></View>
|
keyExtractor={(item, index) => {
|
||||||
</ScrollView>
|
return index.toString();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{items.find(item => item.modalVisible === true) ? <EditItemModal /> : <View />}
|
||||||
|
|
||||||
{/* buttons */}
|
{/* buttons */}
|
||||||
<View style={styles.itemLocation} >
|
<View style={styles.itemLocation} >
|
||||||
@@ -145,4 +155,4 @@ const styles = StyleSheet.create({
|
|||||||
bottom: 10,
|
bottom: 10,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
export default GroceryList;
|
export default React.memo(GroceryList);
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { StyleSheet, View, ScrollView, Text } from 'react-native';
|
import { StyleSheet, View, FlatList } from 'react-native';
|
||||||
import { useHeaderHeight } from '@react-navigation/stack';
|
import { useHeaderHeight } from '@react-navigation/stack';
|
||||||
|
|
||||||
//dependencies\
|
//dependencies\
|
||||||
//components
|
//components
|
||||||
import { AddProductButton } from '../../components/groceryComponents/ProductButtons';
|
import { AddProductButton } from '../../components/groceryComponents/ProductButtons';
|
||||||
import { ListedProduct } from '../../components/groceryComponents/ListedProduct';
|
import ListedProduct from '../../components/groceryComponents/ListedProduct';
|
||||||
|
|
||||||
import { COLORS } from '../../themes/Colors';
|
import { COLORS } from '../../themes/Colors';
|
||||||
|
|
||||||
@@ -14,23 +14,24 @@ import { useSelector } from 'react-redux';
|
|||||||
|
|
||||||
|
|
||||||
function Products() {
|
function Products() {
|
||||||
const products = useSelector(state => state.products)
|
const products = useSelector(state => state.products).slice().sort((a,b)=> a.tag.localeCompare(b.tag))
|
||||||
const productsList = products.map((product, index) => {
|
|
||||||
return <ListedProduct key={index} id={product.id}/>
|
|
||||||
});
|
|
||||||
return (
|
return (
|
||||||
<View style={[styles.container]}>
|
<View style={[styles.container]}>
|
||||||
{/* Scroll */}
|
{/* Scroll */}
|
||||||
<ScrollView>
|
<FlatList
|
||||||
<View style={{ height: useHeaderHeight() }} />
|
ListHeaderComponent={<View style={{ height: useHeaderHeight() }} />}
|
||||||
<View style=
|
ListFooterComponent={<View style={{ height: 100 }} />}
|
||||||
{{
|
initialNumToRender={10}
|
||||||
top: 5,
|
maxToRenderPerBatch={10}
|
||||||
}}>
|
data={products}
|
||||||
{productsList}
|
renderItem={({ item, index }) => {
|
||||||
</View>
|
return <ListedProduct id={item.id} />
|
||||||
<View style={{ height: 3000 }}></View>
|
}}
|
||||||
</ScrollView>
|
keyExtractor={(item, index) => {
|
||||||
|
return index.toString();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{products.find(product=>product.modalVisible === true) ? <EditProductModal /> : <View/>}
|
||||||
{/* buttons */}
|
{/* buttons */}
|
||||||
<View style={styles.addProductView} >
|
<View style={styles.addProductView} >
|
||||||
<AddProductButton />
|
<AddProductButton />
|
||||||
@@ -56,4 +57,4 @@ const styles = StyleSheet.create({
|
|||||||
bottom: 10,
|
bottom: 10,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
export default Products;
|
export default React.memo(Products);
|
||||||
@@ -1,26 +1,41 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { StyleSheet, View, ScrollView, Text } from 'react-native';
|
import { StyleSheet, View, ScrollView, Text } from 'react-native';
|
||||||
|
|
||||||
//dependencies\
|
//dependencies
|
||||||
//components
|
import { useHeaderHeight } from '@react-navigation/stack';
|
||||||
import AddItemButton from '../../components/groceryComponents/GroceryListButtons';
|
|
||||||
import { COLORS } from '../../themes/Colors';
|
|
||||||
|
|
||||||
|
//components
|
||||||
|
import StorageList from '../../components/groceryComponents/StorageList';
|
||||||
|
|
||||||
|
import { COLORS } from '../../themes/Colors';
|
||||||
|
//redux
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
function Storage() {
|
function Storage() {
|
||||||
|
const tags = useSelector(state => state.tags)
|
||||||
return (
|
return (
|
||||||
<View style={styles.dp00}>
|
<View style={styles.dp00}>
|
||||||
<View>
|
<View>
|
||||||
</View>
|
</View>
|
||||||
<ScrollView>
|
<ScrollView>
|
||||||
|
<View style={{ height: useHeaderHeight() }} />
|
||||||
|
<View style=
|
||||||
|
{{
|
||||||
|
top: 5,
|
||||||
|
}}>
|
||||||
|
{tags.map((tag, index)=>{
|
||||||
|
return <StorageList key = {index} tag={tag.tagName}/>
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
|
<View style={{ height: 500 }}></View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
background: {
|
background: {
|
||||||
flex:1,
|
flex: 1,
|
||||||
backgroundColor: COLORS.dp00,
|
backgroundColor: COLORS.dp00,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
export default Storage;
|
export default Storage;
|
||||||
@@ -12,11 +12,12 @@ export const COLORS = {
|
|||||||
secondary: '#f2aeac', //secondary
|
secondary: '#f2aeac', //secondary
|
||||||
secondaryVar: '#ffffff', //secondary variant
|
secondaryVar: '#ffffff', //secondary variant
|
||||||
|
|
||||||
|
price: '#C6A337',
|
||||||
|
|
||||||
|
|
||||||
//layout colors #DAE9FF
|
//layout colors #DAE9FF
|
||||||
dp00: '#0C0F12', //0%
|
dp00: '#0C0F12', //0%
|
||||||
dp01: '#161a1e', //5%
|
dp01: '#121518', //5%
|
||||||
dp02: '#1a1e23', //7%
|
dp02: '#1a1e23', //7%
|
||||||
dp03: '#1f2225', //8%
|
dp03: '#1f2225', //8%
|
||||||
dp04: '#1c2025', //9%
|
dp04: '#1c2025', //9%
|
||||||
|
|||||||
Reference in New Issue
Block a user