commit
ebd7cbc1ad
@ -1 +1,9 @@
|
|||||||
*.pbxproj -text
|
#
|
||||||
|
# https://help.github.com/articles/dealing-with-line-endings/
|
||||||
|
#
|
||||||
|
# Linux start script should use lf
|
||||||
|
/gradlew text eol=lf
|
||||||
|
|
||||||
|
# These are Windows script files and should use crlf
|
||||||
|
*.bat text eol=crlf
|
||||||
|
|
||||||
|
@ -1,63 +1,30 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {StyleSheet, View } from 'react-native';
|
import { NavigationContainer } from '@react-navigation/native';
|
||||||
import ProfileModification from './components/ProfileModification';
|
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
||||||
import ValidateButton from './components/ValidateButton';
|
|
||||||
import { LinearGradient } from 'expo-linear-gradient';
|
|
||||||
import RecipeSuggestion from './screens/RecipeSuggestion';
|
|
||||||
import RecipeDetails from './screens/RecipeDetails';
|
|
||||||
import IngredientSelection from './screens/IngredientSelection';
|
|
||||||
|
|
||||||
export default function App() {
|
import HomeStackScreen from './navigation/HomeStackScreen';
|
||||||
const all = [{value: "Mussels"}, {value: "Skimmed Milk"}, {value: "Nuts"}]
|
import ProfilesStackScreen from './navigation/ProfileStackScreen';
|
||||||
const die = [{value: "Dairy free"}, {value: "Gluten free"}, {value: "Porkless"}, {value: "Vegan"}, {value: "Vegetarian"}, {value: "Pescatarian"}]
|
import CookingStackScreen from './navigation/CookingStackScreen';
|
||||||
const ingredient = [{value: "Chocolate"}, {value: "Skimmed Milk"}, {value: "Eggs"}, , {value: "Farine"}]
|
import BottomBar from './navigation/BottomBar';
|
||||||
const ustensils = [{value: "Bol"}, {value: "Fouet"}, {value: "Casserole"}]
|
import { ThemeProvider } from './theme/ThemeContext';
|
||||||
const steps = [{value: "Chauffer chocolat"},
|
import { ColorProvider } from './theme/ColorContext';
|
||||||
{value: "1. Casser oeuf"},
|
|
||||||
{value: "2. Melanger la farine, le lait et les oeufs"},
|
|
||||||
{value: "3. Battre fort"},
|
|
||||||
{value: "4. Voler la montre de Louison"},
|
|
||||||
{value: "5. Melanger avec le chocolat"},
|
|
||||||
{value: "6. Mettre au four"},
|
|
||||||
]
|
|
||||||
|
|
||||||
function generateList() {
|
|
||||||
const list = [];
|
|
||||||
list.push("Meat");
|
|
||||||
list.push("Meat");
|
|
||||||
list.push("Meat");
|
|
||||||
list.push("Meat");
|
|
||||||
list.push("Teat");
|
|
||||||
list.push("Meat");
|
|
||||||
list.push("Meat");
|
|
||||||
list.push("Meat");
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ingredients = generateList();
|
|
||||||
|
|
||||||
return (
|
|
||||||
/*<IngredientSelection listIngredient={ingredients}></IngredientSelection>*/
|
|
||||||
/*<RecipeSuggestion list={ingredients} diets={die} allergy={all}></RecipeSuggestion>*/
|
|
||||||
<RecipeDetails id={123}></RecipeDetails>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const Tab = createBottomTabNavigator();
|
||||||
container: {
|
|
||||||
flex: 1,
|
export default function App() {
|
||||||
backgroundColor: '#3F3C42',
|
|
||||||
alignItems: 'center',
|
return (
|
||||||
justifyContent: 'center',
|
<ThemeProvider>
|
||||||
},
|
<ColorProvider>
|
||||||
linearGradient: {
|
<NavigationContainer>
|
||||||
//height: 844,
|
<Tab.Navigator initialRouteName='HOME' tabBar={ (props) => <BottomBar {...props}/> }>
|
||||||
//width: 390,
|
<Tab.Screen name='PROFILE' component={ProfilesStackScreen} options={{ headerShown: false, title: 'Profile' }} />
|
||||||
flex: 1,
|
<Tab.Screen name='HOME' component={HomeStackScreen} options={{ headerShown: false, title: 'Home' }}/>
|
||||||
padding: 10,
|
<Tab.Screen name='COOKING' component={CookingStackScreen} options={{ headerShown: false, title: 'Cooking' }}/>
|
||||||
paddingTop: 0,
|
</Tab.Navigator>
|
||||||
//backgroundColor: "#59BDCD",
|
</NavigationContainer>
|
||||||
//alignItems: 'center',
|
</ColorProvider>
|
||||||
//justifyContent: 'flex-start',
|
</ThemeProvider>
|
||||||
},
|
);
|
||||||
});
|
}
|
||||||
|
After Width: | Height: | Size: 9.0 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 11 KiB |
@ -1,100 +1,102 @@
|
|||||||
import React from 'react';
|
import React, { useContext } from 'react';
|
||||||
import {StyleSheet, Text, TextInput, View, Image, FlatList} from 'react-native';
|
import {StyleSheet, Text, TextInput, View, Image, FlatList} from 'react-native';
|
||||||
import ValidateButton from './ValidateButton';
|
import ValidateButton from './ValidateButton';
|
||||||
import HeaderFlatList from './HeaderFlatList';
|
import HeaderFlatList from './HeaderFlatList';
|
||||||
import { MultipleSelectList, SelectList } from 'react-native-dropdown-select-list'
|
import { MultipleSelectList, SelectList } from 'react-native-dropdown-select-list'
|
||||||
|
import ColorContext from '../theme/ColorContext';
|
||||||
|
|
||||||
type ListProps = {
|
type ListProps = {
|
||||||
title: string
|
title: string
|
||||||
content : list<string>
|
content : string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ListSelect(props: ListProps) {
|
export default function ListSelect(props: ListProps) {
|
||||||
const [selected, setSelected] = React.useState([]);
|
const [selected, setSelected] = React.useState([]);
|
||||||
return (
|
const { colors, toggleColors } = useContext(ColorContext);
|
||||||
<MultipleSelectList
|
|
||||||
setSelected={(val) => setSelected(val)}
|
|
||||||
data={props.content}
|
|
||||||
save="value"
|
|
||||||
search={false}
|
|
||||||
arrowicon={<Image source={require("../assets/images/arrow.png")} style={styles.arrow}></Image>}
|
|
||||||
boxStyles={styles.titleBar}
|
|
||||||
inputStyles={styles.title}
|
|
||||||
dropdownStyles={styles.itemList}
|
|
||||||
dropdownItemStyles={styles.itemCell}
|
|
||||||
dropdownTextStyles={styles.itemText}
|
|
||||||
badgeStyles={styles.badges}
|
|
||||||
badgeTextStyles={styles.badgesText}
|
|
||||||
notFoundText="All Diets Already Selected"
|
|
||||||
placeholder={props.title}
|
|
||||||
label={props.title}/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
titleBar: {
|
titleBar: {
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "stretch",
|
backgroundColor: colors.cardElementTitleBackground,
|
||||||
backgroundColor: "#F2F0E4",
|
borderTopRightRadius: 15,
|
||||||
borderTopRightRadius: 15,
|
borderTopLeftRadius: 15,
|
||||||
borderTopLeftRadius: 15,
|
borderBottomRightRadius: 0,
|
||||||
borderBottomRightRadius: 0,
|
borderBottomLeftRadius: 0,
|
||||||
borderBottomLeftRadius: 0,
|
borderWidth: 2,
|
||||||
borderWidth: 2,
|
borderColor: colors.cardElementBorder,
|
||||||
borderColor: "#ACA279",
|
minWidth: "92%",
|
||||||
minWidth: "92%",
|
maxWidth: "92%",
|
||||||
maxWidth: "92%",
|
marginBottom: 0,
|
||||||
marginBottom: 0,
|
overflow: "hidden",
|
||||||
overflow: "hidden",
|
},
|
||||||
},
|
arrow: {
|
||||||
arrow: {
|
resizeMode: 'contain',
|
||||||
resizeMode: 'contain',
|
tintColor: colors.cardElementTitle,
|
||||||
tintColor: "#3F3C42",
|
flex: 0.1,
|
||||||
flex: 0.1,
|
},
|
||||||
},
|
title: {
|
||||||
title: {
|
fontSize: 15,
|
||||||
fontSize: 15,
|
color: colors.cardElementTitle,
|
||||||
color: '#3F3C42',
|
alignItems: 'center',
|
||||||
alignItems: 'center',
|
textAlign: "left",
|
||||||
textAlign: "left",
|
flex: 0.9,
|
||||||
flex: 0.9,
|
},
|
||||||
},
|
|
||||||
|
itemList: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "flex-start",
|
||||||
|
borderWidth: 0,
|
||||||
|
borderTopRightRadius: 0,
|
||||||
|
borderTopLeftRadius: 0,
|
||||||
|
borderBottomRightRadius: 15,
|
||||||
|
borderBottomLeftRadius: 15,
|
||||||
|
backgroundColor: colors.cardElementBackground,
|
||||||
|
minWidth: "92%",
|
||||||
|
maxWidth: "92%",
|
||||||
|
},
|
||||||
|
itemCell: {
|
||||||
|
padding: 0,
|
||||||
|
paddingTop: "5%",
|
||||||
|
width: "100%",
|
||||||
|
minWidth: 250,
|
||||||
|
maxWidth: 250,
|
||||||
|
},
|
||||||
|
itemText: {
|
||||||
|
fontSize: 13,
|
||||||
|
textAlign: "left",
|
||||||
|
flex: 1,
|
||||||
|
padding: "1%",
|
||||||
|
paddingLeft: "3%",
|
||||||
|
color: colors.cardElementText,
|
||||||
|
},
|
||||||
|
|
||||||
|
badges: {
|
||||||
|
backgroundColor: colors.cardElementBackground,
|
||||||
|
},
|
||||||
|
badgesText: {
|
||||||
|
fontSize: 15,
|
||||||
|
color: colors.cardElementText,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
itemList: {
|
return (
|
||||||
flexDirection: "row",
|
<MultipleSelectList
|
||||||
alignItems: "flex-start",
|
setSelected={(val) => setSelected(val)}
|
||||||
justifyContent: "stretch",
|
data={props.content}
|
||||||
borderWidth: 0,
|
save="value"
|
||||||
borderTopRightRadius: 0,
|
search={false}
|
||||||
borderTopLeftRadius: 0,
|
arrowicon={<Image source={require("../assets/images/arrow.png")} style={styles.arrow}></Image>}
|
||||||
borderBottomRightRadius: 15,
|
boxStyles={styles.titleBar}
|
||||||
borderBottomLeftRadius: 15,
|
inputStyles={styles.title}
|
||||||
backgroundColor: "#E3DEC9",
|
dropdownStyles={styles.itemList}
|
||||||
minWidth: "92%",
|
dropdownItemStyles={styles.itemCell}
|
||||||
maxWidth: "92%",
|
dropdownTextStyles={styles.itemText}
|
||||||
},
|
badgeStyles={styles.badges}
|
||||||
itemCell: {
|
badgeTextStyles={styles.badgesText}
|
||||||
padding: 0,
|
notFoundText="All Diets Already Selected"
|
||||||
paddingTop: "5%",
|
placeholder={props.title}
|
||||||
width: "100%",
|
label={props.title}/>
|
||||||
minWidth: 250,
|
);
|
||||||
maxWidth: 250,
|
}
|
||||||
},
|
|
||||||
itemText: {
|
|
||||||
fontSize: 13,
|
|
||||||
textAlign: "left",
|
|
||||||
flex: 1,
|
|
||||||
padding: "1%",
|
|
||||||
paddingLeft: "3%",
|
|
||||||
color: "#3F3C42",
|
|
||||||
},
|
|
||||||
|
|
||||||
badges: {
|
|
||||||
backgroundColor: "#59BDCD",
|
|
||||||
},
|
|
||||||
badgesText: {
|
|
||||||
fontSize: 15,
|
|
||||||
color: "#F2F0E4",
|
|
||||||
},
|
|
||||||
});
|
|
@ -1,147 +1,152 @@
|
|||||||
import {React, useState} from 'react';
|
import React, { useContext, useState } from 'react';
|
||||||
import {StyleSheet, Text, TextInput, View, Image, Pressable} from 'react-native';
|
import { StyleSheet, Text, View, Image, Pressable } from 'react-native';
|
||||||
import ValidateButton from './ValidateButton';
|
import { useNavigation } from '@react-navigation/native';
|
||||||
|
|
||||||
import ListWithoutSelect from './ListWithoutSelect';
|
import ListWithoutSelect from './ListWithoutSelect';
|
||||||
|
import ColorContext from '../theme/ColorContext';
|
||||||
|
|
||||||
type ProfileProps = {
|
type ProfileProps = {
|
||||||
name: string
|
name: string
|
||||||
avatar: string
|
avatar: string
|
||||||
diets: list<string>
|
diets: string[]
|
||||||
allergies: list<string>
|
allergies: string[]
|
||||||
onDeleteProfile: () => void
|
onDeleteProfile: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ProfileDetails(props: ProfileProps) {
|
export default function ProfileDetails(props) {
|
||||||
const [display, setDisplay] = useState("none")
|
const { colors, toggleColors } = useContext(ColorContext)
|
||||||
const changeListVisibility = () => {
|
const navigation = useNavigation()
|
||||||
if (display == "none"){
|
const [display, setDisplay] = useState("none")
|
||||||
setDisplay("flex")
|
const changeListVisibility = () => {
|
||||||
|
if (display == "none"){
|
||||||
|
setDisplay("flex")
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
setDisplay("none")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let imageSource
|
||||||
|
|
||||||
|
if (props.avatar === "plus.png"){
|
||||||
|
imageSource = require('../assets/images/plus.png')
|
||||||
|
}
|
||||||
|
else if (props.avatar === "plus_small.png"){
|
||||||
|
imageSource = require('../assets/images/plus_small.png')
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
setDisplay("none")
|
imageSource = require('../assets/images/logo.png')
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
let imageSource
|
|
||||||
|
|
||||||
if (props.avatar == "plus.png"){
|
const styles = StyleSheet.create({
|
||||||
imageSource = require('../assets/images/plus.png')
|
background: {
|
||||||
}
|
flexDirection: 'column',
|
||||||
else if (props.avatar == "plus_small.png"){
|
alignItems: 'center',
|
||||||
imageSource = require('../assets/images/plus_small.png')
|
justifyContent: 'center',
|
||||||
}
|
borderRadius: 15,
|
||||||
else{
|
backgroundColor: colors.cardBackground,
|
||||||
imageSource = require('../assets/images/logo.png')
|
padding: "3%",
|
||||||
}
|
marginHorizontal: "3%",
|
||||||
|
},
|
||||||
|
|
||||||
|
pseudoBar: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
width: "100%",
|
||||||
|
marginHorizontal: "3%",
|
||||||
|
marginBottom: "3%",
|
||||||
|
},
|
||||||
|
avatar: {
|
||||||
|
padding: "5%",
|
||||||
|
resizeMode: 'contain',
|
||||||
|
borderWidth: 2,
|
||||||
|
borderColor: colors.cardElementBorder,
|
||||||
|
borderRadius: 45,
|
||||||
|
height: "100%",
|
||||||
|
flex: 0.03,
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
flex: 1,
|
||||||
|
fontSize: 20,
|
||||||
|
color: colors.cardElementBorder,
|
||||||
|
alignItems: 'center',
|
||||||
|
textAlign: 'left',
|
||||||
|
marginLeft: "3%",
|
||||||
|
padding: "2%",
|
||||||
|
height: "100%",
|
||||||
|
},
|
||||||
|
modify: {
|
||||||
|
height: "100%",
|
||||||
|
tintColor: colors.cardElementBorder,
|
||||||
|
resizeMode: 'contain',
|
||||||
|
flex: 0.1,
|
||||||
|
marginLeft: "3%",
|
||||||
|
},
|
||||||
|
delete: {
|
||||||
|
height: "100%",
|
||||||
|
width: "100%",
|
||||||
|
tintColor: colors.cardElementBorder,
|
||||||
|
resizeMode: 'contain',
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
|
||||||
|
filterBar: {
|
||||||
|
flexDirection: "row",
|
||||||
|
width: "85%",
|
||||||
|
paddingTop: "3%",
|
||||||
|
paddingBottom: "1%",
|
||||||
|
alignItems: "flex-end",
|
||||||
|
justifyContent: "center",
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
filters: {
|
||||||
|
fontSize: 20,
|
||||||
|
color: colors.cardElementBorder,
|
||||||
|
flex: 1,
|
||||||
|
padding: "2%",
|
||||||
|
paddingLeft: 0,
|
||||||
|
paddingBottom: 0,
|
||||||
|
},
|
||||||
|
nbSelected: {
|
||||||
|
fontSize: 11,
|
||||||
|
flex: 1,
|
||||||
|
color: colors.cardDetail,
|
||||||
|
textAlign: "right",
|
||||||
|
marginRight: "3%",
|
||||||
|
},
|
||||||
|
arrow: {
|
||||||
|
height: "100%",
|
||||||
|
resizeMode: 'contain',
|
||||||
|
tintColor: colors.cardDetail,
|
||||||
|
flex: 0.1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.background}>
|
<View style={styles.background}>
|
||||||
<View style={styles.pseudoBar}>
|
<View style={styles.pseudoBar}>
|
||||||
<Image source={imageSource} style={styles.avatar}></Image>
|
<Image source={imageSource} style={styles.avatar}></Image>
|
||||||
<Text style={styles.text}>{props.name}</Text>
|
<Text style={styles.text}>{props.name}</Text>
|
||||||
<Image source={require("../assets/images/modify.png")} style={styles.modify}></Image>
|
<Image source={require("../assets/images/modify.png")} style={styles.modify}></Image>
|
||||||
<Pressable onPress={props.onDeleteProfile} style={{flex: 0.1, marginLeft: "1%",}}>
|
<Pressable onPress={props.onDeleteProfile} style={{flex: 0.1, marginLeft: "1%",}}>
|
||||||
<Image source={require("../assets/images/delete.png")} style={styles.delete}></Image>
|
<Image source={require("../assets/images/delete.png")} style={styles.delete}></Image>
|
||||||
|
</Pressable>
|
||||||
|
</View>
|
||||||
|
<Pressable onPress={changeListVisibility} style={{height: "5%", marginTop: "6%", flex: 1, marginBottom: "3%"}}>
|
||||||
|
<View style={styles.filterBar}>
|
||||||
|
<Text style={styles.filters}>Filters</Text>
|
||||||
|
<Text style={styles.nbSelected}>{props.diets.length} selected</Text>
|
||||||
|
<Image source={require("../assets/images/arrow.png")} style={styles.arrow}></Image>
|
||||||
|
</View>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
</View>
|
<View style={{display: display === 'flex' ? 'flex' : 'none', alignItems: "center", justifyContent: "center"}}>
|
||||||
<Pressable onPress={changeListVisibility} style={{height: "5%", marginTop: "6%", flex: 1, marginBottom: "3%"}}>
|
<ListWithoutSelect title="Diets" content={props.diets}></ListWithoutSelect>
|
||||||
<View style={styles.filterBar}>
|
<View style={{marginTop: "3%"}}/>
|
||||||
<Text style={styles.filters}>Filters</Text>
|
<ListWithoutSelect title="Allergies" content={props.allergies}></ListWithoutSelect>
|
||||||
<Text style={styles.nbSelected}>{props.diets.length} selected</Text>
|
<View style={{marginTop: "3%"}}/>
|
||||||
<Image source={require("../assets/images/arrow.png")} style={styles.arrow}></Image>
|
|
||||||
</View>
|
</View>
|
||||||
</Pressable>
|
|
||||||
<View style={{display: display, alignItems: "center", justifyContent: "center"}}>
|
|
||||||
<ListWithoutSelect title="Diets" content={props.diets}></ListWithoutSelect>
|
|
||||||
<View style={{marginTop: "3%"}}/>
|
|
||||||
<ListWithoutSelect title="Allergies" content={props.allergies}></ListWithoutSelect>
|
|
||||||
<View style={{marginTop: "3%"}}/>
|
|
||||||
</View>
|
</View>
|
||||||
</View>
|
);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
background: {
|
|
||||||
flexDirection: 'column',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
borderRadius: 15,
|
|
||||||
backgroundColor: '#F2F0E4',
|
|
||||||
padding: "3%",
|
|
||||||
marginHorizontal: "3%",
|
|
||||||
},
|
|
||||||
|
|
||||||
pseudoBar: {
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
width: "100%",
|
|
||||||
marginHorizontal: "3%",
|
|
||||||
marginBottom: "3%",
|
|
||||||
},
|
|
||||||
avatar: {
|
|
||||||
padding: "5%",
|
|
||||||
resizeMode: 'contain',
|
|
||||||
borderWidth: 2,
|
|
||||||
borderColor: "#ACA279",
|
|
||||||
borderRadius: 45,
|
|
||||||
height: "100%",
|
|
||||||
flex: 0.03,
|
|
||||||
},
|
|
||||||
text: {
|
|
||||||
flex: 1,
|
|
||||||
fontSize: 20,
|
|
||||||
color: '#ACA279',
|
|
||||||
alignItems: 'center',
|
|
||||||
textAlign: 'left',
|
|
||||||
marginLeft: "3%",
|
|
||||||
padding: "2%",
|
|
||||||
height: "100%",
|
|
||||||
},
|
|
||||||
modify: {
|
|
||||||
height: "100%",
|
|
||||||
tintColor: "#ACA279",
|
|
||||||
resizeMode: 'contain',
|
|
||||||
flex: 0.1,
|
|
||||||
marginLeft: "3%",
|
|
||||||
},
|
|
||||||
delete: {
|
|
||||||
height: "100%",
|
|
||||||
width: "100%",
|
|
||||||
tintColor: "#ACA279",
|
|
||||||
resizeMode: 'contain',
|
|
||||||
flex: 1,
|
|
||||||
},
|
|
||||||
|
|
||||||
filterBar: {
|
|
||||||
flexDirection: "row",
|
|
||||||
width: "85%",
|
|
||||||
paddingTop: "3%",
|
|
||||||
paddingBottom: "1%",
|
|
||||||
alignItems: "flex-end",
|
|
||||||
justifyContent: "center",
|
|
||||||
flex: 1,
|
|
||||||
},
|
|
||||||
filters: {
|
|
||||||
fontSize: 20,
|
|
||||||
color: '#ACA279',
|
|
||||||
flex: 1,
|
|
||||||
padding: "2%",
|
|
||||||
paddingLeft: 0,
|
|
||||||
paddingBottom: 0,
|
|
||||||
},
|
|
||||||
nbSelected: {
|
|
||||||
fontSize: 11,
|
|
||||||
flex: 1,
|
|
||||||
color: "#3F3C42",
|
|
||||||
textAlign: "right",
|
|
||||||
marginRight: "3%",
|
|
||||||
},
|
|
||||||
arrow: {
|
|
||||||
height: "100%",
|
|
||||||
resizeMode: 'contain',
|
|
||||||
tintColor: "#3F3C42",
|
|
||||||
flex: 0.1,
|
|
||||||
},
|
|
||||||
});
|
|
@ -1,124 +1,127 @@
|
|||||||
import {React, useState} from 'react';
|
import React, { useContext, useState } from 'react';
|
||||||
import {StyleSheet,Pressable, Text, View, Image} from 'react-native';
|
import {StyleSheet,Pressable, Text, View, Image} from 'react-native';
|
||||||
|
import ColorContext from '../theme/ColorContext';
|
||||||
|
|
||||||
type Profile = {
|
type Profile = {
|
||||||
name: string
|
name: string
|
||||||
avatar: string
|
avatar: string
|
||||||
isActive: string
|
isActive: string
|
||||||
disableSelection: boolean
|
disableSelection: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ProfileElement(props : Profile) {
|
export default function ProfileElement(props : Profile) {
|
||||||
const [waiting, setWaiting] = useState("none")
|
const { colors, toggleColors } = useContext(ColorContext)
|
||||||
const [separator, setSeparator] = useState("none")
|
|
||||||
const changeStatus = () => {
|
|
||||||
if (props.disableSelection){
|
|
||||||
setWaiting("none")
|
|
||||||
}
|
|
||||||
else if (waiting == "flex"){
|
|
||||||
setWaiting("none")
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
setWaiting("flex")
|
|
||||||
}
|
|
||||||
if (props.disableSelection){
|
|
||||||
setSeparator("none")
|
|
||||||
}
|
|
||||||
else if (props.isActive == "flex" && waiting == "none"){
|
|
||||||
setSeparator("flex")
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
setSeparator("none")
|
|
||||||
}
|
|
||||||
console.log(waiting, separator, props.name)
|
|
||||||
}
|
|
||||||
|
|
||||||
let imageSource
|
const [waiting, setWaiting] = useState("none")
|
||||||
if (props.avatar == "plus.png"){
|
const [separator, setSeparator] = useState("none")
|
||||||
imageSource = require('../assets/images/plus.png')
|
const changeStatus = () => {
|
||||||
}
|
if (props.disableSelection){
|
||||||
else if (props.avatar == "plus_small.png"){
|
setWaiting("none")
|
||||||
imageSource = require('../assets/images/plus_small.png')
|
}
|
||||||
}
|
else if (waiting == "flex"){
|
||||||
else{
|
setWaiting("none")
|
||||||
imageSource = require('../assets/images/logo.png')
|
}
|
||||||
}
|
else{
|
||||||
|
setWaiting("flex")
|
||||||
|
}
|
||||||
|
if (props.disableSelection){
|
||||||
|
setSeparator("none")
|
||||||
|
}
|
||||||
|
else if (props.isActive == "flex" && waiting == "none"){
|
||||||
|
setSeparator("flex")
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
setSeparator("none")
|
||||||
|
}
|
||||||
|
console.log(waiting, separator, props.name)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
let imageSource
|
||||||
<Pressable onPress={changeStatus} style={styles.button}>
|
if (props.avatar == "plus.png"){
|
||||||
<View>
|
imageSource = require('../assets/images/plus.png')
|
||||||
<View style={styles.pseudoBar}>
|
}
|
||||||
<Image source={imageSource} style={styles.avatar}></Image>
|
else if (props.avatar == "plus_small.png"){
|
||||||
<Text style={styles.text}>{props.name}</Text>
|
imageSource = require('../assets/images/plus_small.png')
|
||||||
</View>
|
}
|
||||||
<View style={styles.pseudoBar}>
|
else{
|
||||||
<View style={[styles.active, {display: props.isActive}]}>
|
imageSource = require('../assets/images/logo.png')
|
||||||
<Text style={styles.textActive}>Activated</Text>
|
}
|
||||||
</View>
|
|
||||||
<View style={{flex: 0.3, display: separator}}/>
|
|
||||||
<View style={[styles.waiting, {display: waiting}]}>
|
|
||||||
<Text style={styles.textWaiting}>Waiting...</Text>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</Pressable>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
button: {
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'flex-start',
|
|
||||||
height: "80%",
|
|
||||||
width: "78%",
|
|
||||||
marginVertical: "3%",
|
|
||||||
},
|
|
||||||
pseudoBar: {
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
width: "100%",
|
|
||||||
marginHorizontal: "3%",
|
|
||||||
marginBottom: "3%",
|
|
||||||
},
|
|
||||||
avatar: {
|
|
||||||
padding: "5%",
|
|
||||||
resizeMode: 'contain',
|
|
||||||
borderWidth: 2,
|
|
||||||
borderColor: "#ACA279",
|
|
||||||
borderRadius: 45,
|
|
||||||
height: "100%",
|
|
||||||
flex: 0.01,
|
|
||||||
},
|
|
||||||
text: {
|
|
||||||
fontSize: 15,
|
|
||||||
color: '#ACA279',
|
|
||||||
alignItems: 'center',
|
|
||||||
textAlign: 'left',
|
|
||||||
flex: 0.9,
|
|
||||||
marginLeft: "10%",
|
|
||||||
padding: "2%",
|
|
||||||
},
|
|
||||||
|
|
||||||
active: {
|
const styles = StyleSheet.create({
|
||||||
borderWidth: 1,
|
button: {
|
||||||
borderRadius: 20,
|
alignItems: 'center',
|
||||||
borderColor: "#59BDCD",
|
justifyContent: 'flex-start',
|
||||||
padding: "1%",
|
height: "80%",
|
||||||
},
|
width: "78%",
|
||||||
textActive: {
|
marginVertical: "3%",
|
||||||
fontSize: 10,
|
},
|
||||||
color: "#59BDCD",
|
pseudoBar: {
|
||||||
},
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
width: "100%",
|
||||||
|
marginHorizontal: "3%",
|
||||||
|
marginBottom: "3%",
|
||||||
|
},
|
||||||
|
avatar: {
|
||||||
|
padding: "5%",
|
||||||
|
resizeMode: 'contain',
|
||||||
|
borderWidth: 2,
|
||||||
|
borderColor: colors.carrouselText,
|
||||||
|
borderRadius: 45,
|
||||||
|
height: "100%",
|
||||||
|
flex: 0.01,
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
fontSize: 15,
|
||||||
|
color: colors.carrouselText,
|
||||||
|
alignItems: 'center',
|
||||||
|
textAlign: 'left',
|
||||||
|
flex: 0.9,
|
||||||
|
marginLeft: "10%",
|
||||||
|
padding: "2%",
|
||||||
|
},
|
||||||
|
|
||||||
|
active: {
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 20,
|
||||||
|
borderColor: colors.carrouselDetail,
|
||||||
|
padding: "1%",
|
||||||
|
},
|
||||||
|
textActive: {
|
||||||
|
fontSize: 10,
|
||||||
|
color: colors.carrouselDetail,
|
||||||
|
},
|
||||||
|
|
||||||
|
waiting: {
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 20,
|
||||||
|
borderColor: "#ACA279",
|
||||||
|
padding: "1%",
|
||||||
|
},
|
||||||
|
textWaiting: {
|
||||||
|
fontSize: 10,
|
||||||
|
color: "#ACA279",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
waiting: {
|
return (
|
||||||
borderWidth: 1,
|
<Pressable onPress={changeStatus} style={styles.button}>
|
||||||
borderRadius: 20,
|
<View>
|
||||||
borderColor: "#ACA279",
|
<View style={styles.pseudoBar}>
|
||||||
padding: "1%",
|
<Image source={imageSource} style={styles.avatar}></Image>
|
||||||
},
|
<Text style={styles.text}>{props.name}</Text>
|
||||||
textWaiting: {
|
</View>
|
||||||
fontSize: 10,
|
<View style={styles.pseudoBar}>
|
||||||
color: "#ACA279",
|
<View style={[styles.active, {display: props.isActive}]}>
|
||||||
},
|
<Text style={styles.textActive}>Activated</Text>
|
||||||
});
|
</View>
|
||||||
|
<View style={{flex: 0.3, display: separator}}/>
|
||||||
|
<View style={[styles.waiting, {display: waiting}]}>
|
||||||
|
<Text style={styles.textWaiting}>Waiting...</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</Pressable>
|
||||||
|
);
|
||||||
|
}
|
@ -1,115 +1,119 @@
|
|||||||
import {React, useState} from 'react';
|
import React, { useContext, useState } from 'react';
|
||||||
import {StyleSheet, Text, TextInput, View, Image} from 'react-native';
|
import {StyleSheet, Text, TextInput, View, Image} from 'react-native';
|
||||||
|
|
||||||
import ValidateButton from './ValidateButton';
|
import ValidateButton from './ValidateButton';
|
||||||
import ListSelect from './ListSelect';
|
import ListSelect from './ListSelect';
|
||||||
import ListWithoutSelect from './ListWithoutSelect';
|
import ListWithoutSelect from './ListWithoutSelect';
|
||||||
|
import ColorContext from '../theme/ColorContext';
|
||||||
|
|
||||||
type ProfileProps = {
|
type ProfileProps = {
|
||||||
name: string
|
name: string
|
||||||
avatar: string
|
avatar: string
|
||||||
diets: list<string>
|
diets: string[]
|
||||||
allergies: list<string>
|
allergies: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ProfileModification(props: ProfileProps) {
|
export default function ProfileModification(props: ProfileProps) {
|
||||||
const [name, onChangeName] = useState(props.name);
|
const [name, onChangeName] = useState(props.name);
|
||||||
|
const { colors, toggleColors } = useContext(ColorContext);
|
||||||
|
|
||||||
let imageSource
|
let imageSource
|
||||||
if (props.avatar == "plus.png"){
|
if (props.avatar == "plus.png"){
|
||||||
imageSource = require('../assets/images/plus.png')
|
imageSource = require('../assets/images/plus.png')
|
||||||
}
|
}
|
||||||
else if (props.avatar == "plus_small.png"){
|
else if (props.avatar == "plus_small.png"){
|
||||||
imageSource = require('../assets/images/plus_small.png')
|
imageSource = require('../assets/images/plus_small.png')
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
imageSource = require('../assets/images/logo.png')
|
imageSource = require('../assets/images/logo.png')
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
const styles = StyleSheet.create({
|
||||||
<View style={styles.background}>
|
background: {
|
||||||
<View style={styles.pseudoBar}>
|
flexDirection: 'column',
|
||||||
<Image source={imageSource} style={styles.avatar}></Image>
|
alignItems: 'center',
|
||||||
<TextInput style={styles.textInput} value={name} onChangeText={onChangeName} placeholder="Name"></TextInput>
|
justifyContent: 'center',
|
||||||
<Image source={require("../assets/images/modify.png")} style={styles.modify}></Image>
|
borderRadius: 15,
|
||||||
</View>
|
backgroundColor: colors.cardBackground,
|
||||||
<View style={styles.filterBar}>
|
padding: "3%",
|
||||||
<Text style={styles.filters}>Filters</Text>
|
marginHorizontal: "3%",
|
||||||
<Text style={styles.nbSelected}>3 selected</Text>
|
},
|
||||||
|
|
||||||
|
pseudoBar: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
width: "100%",
|
||||||
|
marginHorizontal: "3%",
|
||||||
|
marginBottom: "3%",
|
||||||
|
},
|
||||||
|
avatar: {
|
||||||
|
padding: "5%",
|
||||||
|
resizeMode: 'contain',
|
||||||
|
borderWidth: 2,
|
||||||
|
borderColor: colors.cardTitle,
|
||||||
|
borderRadius: 45,
|
||||||
|
height: "100%",
|
||||||
|
flex: 0.04,
|
||||||
|
},
|
||||||
|
textInput: {
|
||||||
|
fontSize: 15,
|
||||||
|
color: colors.cardTitle,
|
||||||
|
borderRadius: 10,
|
||||||
|
borderWidth: 2,
|
||||||
|
borderStyle: 'dashed',
|
||||||
|
borderColor: colors.cardTitle,
|
||||||
|
alignItems: 'center',
|
||||||
|
textAlign: 'left',
|
||||||
|
flex: 0.8,
|
||||||
|
marginLeft: "7%",
|
||||||
|
padding: "2%",
|
||||||
|
},
|
||||||
|
modify: {
|
||||||
|
height: "100%",
|
||||||
|
tintColor: colors.cardTitle,
|
||||||
|
resizeMode: 'contain',
|
||||||
|
flex: 0.1,
|
||||||
|
marginLeft: "3%",
|
||||||
|
},
|
||||||
|
|
||||||
|
filterBar: {
|
||||||
|
flexDirection: "row",
|
||||||
|
width: "85%",
|
||||||
|
paddingTop: "3%",
|
||||||
|
paddingBottom: "2%",
|
||||||
|
alignItems: "flex-end",
|
||||||
|
justifyContent: "center",
|
||||||
|
},
|
||||||
|
filters: {
|
||||||
|
fontSize: 20,
|
||||||
|
color: colors.cardTitle,
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
nbSelected: {
|
||||||
|
fontSize: 11,
|
||||||
|
color: colors.cardDetail,
|
||||||
|
textAlign: "right",
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.background}>
|
||||||
|
<View style={styles.pseudoBar}>
|
||||||
|
<Image source={imageSource} style={styles.avatar}></Image>
|
||||||
|
<TextInput style={styles.textInput} value={name} onChangeText={onChangeName} placeholder="Name"></TextInput>
|
||||||
|
<Image source={require("../assets/images/modify.png")} style={styles.modify}></Image>
|
||||||
|
</View>
|
||||||
|
<View style={styles.filterBar}>
|
||||||
|
<Text style={styles.filters}>Filters</Text>
|
||||||
|
<Text style={styles.nbSelected}>3 selected</Text>
|
||||||
|
</View>
|
||||||
|
<ListSelect title="Diets" content={props.diets}></ListSelect>
|
||||||
|
<View style={{marginTop: "6%"}}/>
|
||||||
|
<ListWithoutSelect title="Allergies" content={props.allergies}></ListWithoutSelect>
|
||||||
|
<View style={{marginTop: "3%"}}/>
|
||||||
|
<ValidateButton title="Add Allergy" image="plus.png" colour={colors.buttonDetail} backColour={colors.buttonBackground} todo={() => console.log("Create Profile...")}/>
|
||||||
</View>
|
</View>
|
||||||
<ListSelect title="Diets" content={props.diets}></ListSelect>
|
);
|
||||||
<View style={{marginTop: "6%"}}/>
|
|
||||||
<ListWithoutSelect title="Allergies" content={props.allergies}></ListWithoutSelect>
|
|
||||||
<View style={{marginTop: "3%"}}/>
|
|
||||||
<ValidateButton title="Add Allergy" image="plus.png" colour="#59BDCD" backColour="#E3DEC9"></ValidateButton>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
background: {
|
|
||||||
flexDirection: 'column',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
borderRadius: 15,
|
|
||||||
backgroundColor: '#F2F0E4',
|
|
||||||
padding: "3%",
|
|
||||||
marginHorizontal: "3%",
|
|
||||||
},
|
|
||||||
|
|
||||||
pseudoBar: {
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
width: "100%",
|
|
||||||
marginHorizontal: "3%",
|
|
||||||
marginBottom: "3%",
|
|
||||||
},
|
|
||||||
avatar: {
|
|
||||||
padding: "5%",
|
|
||||||
resizeMode: 'contain',
|
|
||||||
borderWidth: 2,
|
|
||||||
borderColor: "#ACA279",
|
|
||||||
borderRadius: 45,
|
|
||||||
height: "100%",
|
|
||||||
flex: 0.04,
|
|
||||||
},
|
|
||||||
textInput: {
|
|
||||||
fontSize: 15,
|
|
||||||
color: '#ACA279',
|
|
||||||
borderRadius: 10,
|
|
||||||
borderWidth: 2,
|
|
||||||
borderStyle: 'dashed',
|
|
||||||
borderColor: '#ACA279',
|
|
||||||
alignItems: 'center',
|
|
||||||
textAlign: 'left',
|
|
||||||
flex: 0.8,
|
|
||||||
marginLeft: "7%",
|
|
||||||
padding: "2%",
|
|
||||||
},
|
|
||||||
modify: {
|
|
||||||
height: "100%",
|
|
||||||
tintColor: "#ACA279",
|
|
||||||
resizeMode: 'contain',
|
|
||||||
flex: 0.1,
|
|
||||||
marginLeft: "3%",
|
|
||||||
},
|
|
||||||
|
|
||||||
filterBar: {
|
|
||||||
flexDirection: "row",
|
|
||||||
width: "85%",
|
|
||||||
paddingTop: "3%",
|
|
||||||
paddingBottom: "2%",
|
|
||||||
alignItems: "flex-end",
|
|
||||||
justifyContent: "center",
|
|
||||||
},
|
|
||||||
filters: {
|
|
||||||
fontSize: 20,
|
|
||||||
color: '#ACA279',
|
|
||||||
flex: 1,
|
|
||||||
},
|
|
||||||
nbSelected: {
|
|
||||||
fontSize: 11,
|
|
||||||
color: "#3F3C42",
|
|
||||||
textAlign: "right",
|
|
||||||
}
|
|
||||||
});
|
|
@ -0,0 +1,135 @@
|
|||||||
|
import React, { useContext, useState } from 'react';
|
||||||
|
import { View, Text, TouchableOpacity, Image, Pressable } from 'react-native';
|
||||||
|
import { GestureResponderEvent, StyleSheet } from 'react-native';
|
||||||
|
import { BlurView } from 'expo-blur';
|
||||||
|
import ThemeContext from '../theme/ThemeContext';
|
||||||
|
import ColorContext from '../theme/ColorContext';
|
||||||
|
import { LightTheme, DarkTheme } from '../theme/colors';
|
||||||
|
|
||||||
|
import HomeIcon from '../assets/images/home.png';
|
||||||
|
import ProfileIcon from '../assets/images/person_icon.png';
|
||||||
|
import CookingIcon from '../assets/images/cook.png';
|
||||||
|
import LightIcon from '../assets/images/sun.png';
|
||||||
|
import DarkIcon from '../assets/images/moon.png';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export default function BottomBar({ state, descriptors, navigation }) {
|
||||||
|
const {theme, toggleTheme} = useContext(ThemeContext);
|
||||||
|
const {colors, toggleColors} = useContext(ColorContext)
|
||||||
|
const [iconThemeButton, setThemeIconButton] = useState(( theme === 'dark' ) ? LightIcon : DarkIcon)
|
||||||
|
const [textThemeButton, setTextThemeButton] = useState(( theme === 'dark' ) ? 'Light' : 'Dark');
|
||||||
|
|
||||||
|
const onThemeButtonPress = (event: GestureResponderEvent) => {
|
||||||
|
if (textThemeButton === "Light") {
|
||||||
|
setThemeIconButton(DarkIcon);
|
||||||
|
setTextThemeButton("Dark");
|
||||||
|
toggleTheme('light');
|
||||||
|
toggleColors(LightTheme)
|
||||||
|
} else {
|
||||||
|
setThemeIconButton(LightIcon);
|
||||||
|
setTextThemeButton("Light");
|
||||||
|
toggleTheme('dark')
|
||||||
|
toggleColors(DarkTheme)
|
||||||
|
}
|
||||||
|
console.log('TextThemeButton is now: ' + textThemeButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
BottomBarMainContainer: {
|
||||||
|
position: 'absolute',
|
||||||
|
bottom: 0,
|
||||||
|
right: 0,
|
||||||
|
left: 0,
|
||||||
|
height: 70,
|
||||||
|
backgroundColor: theme === 'dark' ? "#3F3C42" : "transparent"
|
||||||
|
},
|
||||||
|
BottomBarBlurContainer: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
alignContent: 'space-around',
|
||||||
|
padding: 2,
|
||||||
|
borderBlockColor: theme === 'light' ? '#F2F0E4' : '#222222',
|
||||||
|
borderWidth: 3,
|
||||||
|
borderLeftColor: theme === 'light'? '#F2F0E4' : '#222222',
|
||||||
|
borderLeftWidth: 3,
|
||||||
|
borderRightColor: theme === 'light'? '#F2F0E4' : '#222222',
|
||||||
|
borderRightWidth: 3
|
||||||
|
},
|
||||||
|
BottomBarIcon: {
|
||||||
|
width: 35,
|
||||||
|
height: 35
|
||||||
|
},
|
||||||
|
BottomBarElementContainer: {
|
||||||
|
flexDirection: 'column',
|
||||||
|
alignItems: 'center',
|
||||||
|
margin: 3
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.BottomBarMainContainer}>
|
||||||
|
<BlurView
|
||||||
|
style={[StyleSheet.absoluteFill, styles.BottomBarBlurContainer]}
|
||||||
|
tint='dark'
|
||||||
|
intensity={theme === 'light' ? 50 : 0}
|
||||||
|
>
|
||||||
|
{state.routes.map((route, index) => {
|
||||||
|
const { options } = descriptors[route.key];
|
||||||
|
const label =
|
||||||
|
options.tabBarLabel !== undefined
|
||||||
|
? options.tabBarLabel
|
||||||
|
: options.title !== undefined
|
||||||
|
? options.title
|
||||||
|
: route.name;
|
||||||
|
|
||||||
|
let icon;
|
||||||
|
if (route.name === 'HOME') {
|
||||||
|
icon = HomeIcon;
|
||||||
|
} else if (route.name === 'PROFILE') {
|
||||||
|
icon = ProfileIcon;
|
||||||
|
} else if (route.name === 'COOKING') {
|
||||||
|
icon = CookingIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isFocused = state.index === index;
|
||||||
|
|
||||||
|
const onPress = () => {
|
||||||
|
const event = navigation.emit({
|
||||||
|
type: 'tabPress',
|
||||||
|
target: route.key,
|
||||||
|
canPreventDefault: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!isFocused && !event.defaultPrevented) {
|
||||||
|
navigation.navigate(route.name, route.params);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TouchableOpacity
|
||||||
|
accessibilityRole="button"
|
||||||
|
accessibilityState={isFocused ? { selected: true } : {}}
|
||||||
|
accessibilityLabel={options.tabBarAccessibilityLabel}
|
||||||
|
testID={options.tabBarTestID}
|
||||||
|
onPress={onPress}
|
||||||
|
style={[styles.BottomBarElementContainer, { flex: 1 }]}
|
||||||
|
key={route.name}
|
||||||
|
>
|
||||||
|
<Image source={icon} style={[styles.BottomBarIcon, {tintColor: isFocused ? (theme === 'light' ? '#59BDCD': '#8DB4D9'): '#F2F0E4'}]} />
|
||||||
|
<Text style={{ color: isFocused ? '#59BDCD' : '#F2F0E4' }}>
|
||||||
|
{label}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
<Pressable onPress={ onThemeButtonPress }>
|
||||||
|
<Image source={iconThemeButton} style={[styles.BottomBarIcon, {tintColor: '#F2F0E4'}]} />
|
||||||
|
<Text style={{color: '#F2F0E4'}}>
|
||||||
|
{textThemeButton}
|
||||||
|
</Text>
|
||||||
|
</Pressable>
|
||||||
|
</BlurView>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
import React, { useContext } from 'react'
|
||||||
|
import { StyleSheet } from 'react-native'
|
||||||
|
import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
||||||
|
|
||||||
|
import IngredientSelection from '../screens/IngredientSelection';
|
||||||
|
import { HeaderTitle } from './Utils';
|
||||||
|
import ThemeContext from '../theme/ThemeContext';
|
||||||
|
|
||||||
|
const CookingStack = createNativeStackNavigator()
|
||||||
|
|
||||||
|
export default function CookingStackScreen() {
|
||||||
|
const {theme, toggleTheme} = useContext(ThemeContext);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CookingStack.Navigator>
|
||||||
|
<CookingStack.Screen
|
||||||
|
name='IngredientSelection'
|
||||||
|
component={IngredientSelection}
|
||||||
|
options={{
|
||||||
|
headerStyle: {backgroundColor: theme === 'light' ? '#F2F0E4' : '#3F3C42'},
|
||||||
|
headerTitle: () => (
|
||||||
|
<HeaderTitle title='Profile Modification'/>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</CookingStack.Navigator>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
headerBarContainer: {
|
||||||
|
backgroundColor: '#F2F0E4',
|
||||||
|
},
|
||||||
|
})
|
@ -0,0 +1,81 @@
|
|||||||
|
import React, { useContext } from 'react';
|
||||||
|
import { Image, Text, StyleSheet } from 'react-native';
|
||||||
|
import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
||||||
|
|
||||||
|
import HomePage from '../screens/HomePage';
|
||||||
|
import Profiles from '../screens/Profiles';
|
||||||
|
import CreateProfile from '../screens/CreateProfile';
|
||||||
|
import ModifyProfile from '../screens/ModifyProfile';
|
||||||
|
import ThemeContext from '../theme/ThemeContext';
|
||||||
|
import ColorContext from '../theme/ColorContext';
|
||||||
|
import { HeaderTitle } from './Utils';
|
||||||
|
|
||||||
|
import appLogo from '../assets/images/logo.png';
|
||||||
|
|
||||||
|
const HomeStack = createNativeStackNavigator()
|
||||||
|
|
||||||
|
function AppIcon() {
|
||||||
|
return (
|
||||||
|
<Image
|
||||||
|
source={appLogo}
|
||||||
|
style={styles.headerAppIcon}/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function HomeStackScreen() {
|
||||||
|
const {theme, toggleTheme} = useContext(ThemeContext)
|
||||||
|
const {colors, toggleColors} = useContext(ColorContext)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<HomeStack.Navigator>
|
||||||
|
<HomeStack.Screen
|
||||||
|
name='Home'
|
||||||
|
component={HomePage}
|
||||||
|
options={{
|
||||||
|
headerStyle: {backgroundColor: colors.cardBackground},
|
||||||
|
|
||||||
|
headerLeft: () => (
|
||||||
|
<AppIcon/>
|
||||||
|
),
|
||||||
|
|
||||||
|
headerTitle: () => (
|
||||||
|
<HeaderTitle title='LeftOvers'/>
|
||||||
|
),
|
||||||
|
headerTitleAlign: 'center',
|
||||||
|
|
||||||
|
headerRight: () => (
|
||||||
|
<AppIcon/>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<HomeStack.Screen
|
||||||
|
name='Profiles'
|
||||||
|
component={Profiles}
|
||||||
|
options={{
|
||||||
|
headerStyle: {backgroundColor: colors.cardBackground},
|
||||||
|
headerTitle: () => (
|
||||||
|
<HeaderTitle title='Profiles'/>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<HomeStack.Screen
|
||||||
|
name='ProfileModification'
|
||||||
|
component={ModifyProfile}
|
||||||
|
options={{
|
||||||
|
headerStyle: {backgroundColor: colors.cardBackground},
|
||||||
|
headerTitle: () => (
|
||||||
|
<HeaderTitle title='Profile Modification'/>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</HomeStack.Navigator>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
headerAppIcon: {
|
||||||
|
width: 45,
|
||||||
|
height: 45,
|
||||||
|
marginHorizontal: 10,
|
||||||
|
}
|
||||||
|
})
|
@ -0,0 +1,91 @@
|
|||||||
|
import React, { useContext } from 'react'
|
||||||
|
import { StyleSheet, View, Image, Pressable } from 'react-native'
|
||||||
|
import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
||||||
|
|
||||||
|
import Profiles from '../screens/Profiles';
|
||||||
|
import CreateProfile from '../screens/CreateProfile';
|
||||||
|
import ModifyProfile from '../screens/ModifyProfile';
|
||||||
|
import ThemeContext from '../theme/ThemeContext';
|
||||||
|
|
||||||
|
import { HeaderTitle } from './Utils';
|
||||||
|
|
||||||
|
import SearchIcon from '../assets/images/search.png';
|
||||||
|
import AddIcon from '../assets/images/plus.png'
|
||||||
|
|
||||||
|
const ProfilesStack = createNativeStackNavigator()
|
||||||
|
|
||||||
|
export default function ProfilesStackScreen({ navigation }) {
|
||||||
|
const {theme, toggleTheme} = useContext(ThemeContext);
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
headerBarContainer: {
|
||||||
|
backgroundColor: theme === 'light' ? '#F2F0E4' : '#3F3C42',
|
||||||
|
},
|
||||||
|
headerBarRightContainer: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignContent: 'space-between',
|
||||||
|
marginHorizontal: 10,
|
||||||
|
},
|
||||||
|
headerBarIcon: {
|
||||||
|
width: 30,
|
||||||
|
height: 30,
|
||||||
|
marginHorizontal: 10
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const _handleSearch = () => console.log('Searching');
|
||||||
|
const _handleHeaderAdd = () => navigation.navigate('ProfileCreation');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ProfilesStack.Navigator>
|
||||||
|
<ProfilesStack.Screen
|
||||||
|
name='Profiles'
|
||||||
|
component={Profiles}
|
||||||
|
options={{
|
||||||
|
headerStyle: styles.headerBarContainer,
|
||||||
|
headerTitle: () => (
|
||||||
|
<HeaderTitle title='Profiles'/>
|
||||||
|
),
|
||||||
|
headerRight: () => (
|
||||||
|
<View style={styles.headerBarRightContainer}>
|
||||||
|
<Pressable onPress={_handleSearch}>
|
||||||
|
<Image
|
||||||
|
source={SearchIcon}
|
||||||
|
style={styles.headerBarIcon}
|
||||||
|
tintColor={theme === 'light' ? '#3F3C42' : '#F2F0E4'}/>
|
||||||
|
</Pressable>
|
||||||
|
<Pressable onPress={_handleHeaderAdd}>
|
||||||
|
<Image
|
||||||
|
source={AddIcon}
|
||||||
|
style={styles.headerBarIcon}
|
||||||
|
tintColor={theme === 'light' ? '#3F3C42' : '#F2F0E4'}/>
|
||||||
|
</Pressable>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ProfilesStack.Screen
|
||||||
|
name='ProfileCreation'
|
||||||
|
component={CreateProfile}
|
||||||
|
options={{
|
||||||
|
headerStyle: styles.headerBarContainer,
|
||||||
|
headerTitle: () => (
|
||||||
|
<HeaderTitle title='Profile Creation'/>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ProfilesStack.Screen
|
||||||
|
name='ProfileModification'
|
||||||
|
component={ModifyProfile}
|
||||||
|
options={{
|
||||||
|
headerStyle: styles.headerBarContainer,
|
||||||
|
headerTitle: () => (
|
||||||
|
<HeaderTitle title='Profile Modification'/>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ProfilesStack.Navigator>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
|||||||
|
import React, { useContext } from 'react';
|
||||||
|
import { Text, StyleSheet } from 'react-native';
|
||||||
|
|
||||||
|
import ColorContext from '../theme/ColorContext';
|
||||||
|
|
||||||
|
export function HeaderTitle(props) {
|
||||||
|
const {colors, toggleColors} = useContext(ColorContext)
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
headerTitle: {
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: colors.cardDetail,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Text
|
||||||
|
style={styles.headerTitle}>
|
||||||
|
{props.title}
|
||||||
|
</Text>
|
||||||
|
)
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -1,44 +1,39 @@
|
|||||||
import React from 'react';
|
import React, { useContext } from 'react';
|
||||||
import {StyleSheet, View, ScrollView, useWindowDimensions} from 'react-native';
|
import {StyleSheet, View, ScrollView, useWindowDimensions} from 'react-native';
|
||||||
import ProfileModification from '../components/ProfileModification';
|
|
||||||
import ValidateButton from '../components/ValidateButton';
|
|
||||||
import TopBar from '../components/TopBar';
|
|
||||||
import { LinearGradient } from 'expo-linear-gradient';
|
import { LinearGradient } from 'expo-linear-gradient';
|
||||||
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
||||||
|
|
||||||
|
import ProfileModification from '../components/ProfileModification';
|
||||||
|
import ValidateButton from '../components/ValidateButton';
|
||||||
|
import ColorContext from '../theme/ColorContext';
|
||||||
|
|
||||||
export default function CreateProfile(props) {
|
export default function CreateProfile(props) {
|
||||||
const all = []
|
const { colors, toggleColors } = useContext(ColorContext)
|
||||||
const die = [{value: "Dairy free"}, {value: "Gluten free"}, {value: "Porkless"}, {value: "Vegan"}, {value: "Vegetarian"}, {value: "Pescatarian"}]
|
const all = []
|
||||||
return (
|
const die = [{value: "Dairy free"}, {value: "Gluten free"}, {value: "Porkless"}, {value: "Vegan"}, {value: "Vegetarian"}, {value: "Pescatarian"}]
|
||||||
<SafeAreaProvider style={{flex: 1}}>
|
|
||||||
<TopBar title="Create Profile" isVisible="true"/>
|
const styles = StyleSheet.create({
|
||||||
<ScrollView>
|
linearGradient: {
|
||||||
<LinearGradient colors={['#2680AA', '#59BDCD']} style={[styles.linearGradient, {minHeight: useWindowDimensions().height}]}>
|
height: "100%",
|
||||||
<View style={{marginTop: "6%"}}/>
|
width: "100%",
|
||||||
<ProfileModification name="" avatar="plus_small.png" diets={die} allergies={all}></ProfileModification>
|
flex: 1,
|
||||||
<View style={{marginTop: "3%"}}/>
|
padding: "2%",
|
||||||
<ValidateButton title="Create Profile" image="plus.png" colour="#ACA279" backColour="#F2F0E4"></ValidateButton>
|
paddingTop: 0,
|
||||||
<View style={{marginTop: "20%"}}/>
|
},
|
||||||
</LinearGradient>
|
});
|
||||||
</ScrollView>
|
|
||||||
</SafeAreaProvider>
|
return (
|
||||||
);
|
<SafeAreaProvider style={{flex: 1}}>
|
||||||
|
<ScrollView>
|
||||||
|
<LinearGradient colors={[colors.primary, colors.primaryComplement]} style={[styles.linearGradient, {minHeight: useWindowDimensions().height}]}>
|
||||||
|
<View style={{marginTop: "6%"}}/>
|
||||||
|
<ProfileModification name="" avatar="plus_small.png" diets={die} allergies={all}></ProfileModification>
|
||||||
|
<View style={{marginTop: "3%"}}/>
|
||||||
|
<ValidateButton title="Create Profile" image="plus.png" colour={colors.cardTitle} backColour={colors.cardBackground} todo={() => (console.log("Profile Created"))}></ValidateButton>
|
||||||
|
<View style={{marginTop: "20%"}}/>
|
||||||
|
</LinearGradient>
|
||||||
|
</ScrollView>
|
||||||
|
</SafeAreaProvider>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
container: {
|
|
||||||
height: "100%",
|
|
||||||
width: "100%",
|
|
||||||
flex: 1,
|
|
||||||
backgroundColor: '#3F3C42',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
},
|
|
||||||
linearGradient: {
|
|
||||||
height: "100%",
|
|
||||||
width: "100%",
|
|
||||||
flex: 1,
|
|
||||||
padding: "2%",
|
|
||||||
paddingTop: 0,
|
|
||||||
},
|
|
||||||
});
|
|
@ -0,0 +1,42 @@
|
|||||||
|
import React, {createContext, useState, useEffect} from 'react';
|
||||||
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
|
|
||||||
|
import { LightTheme, Theme } from './colors';
|
||||||
|
|
||||||
|
interface ColorContextType {
|
||||||
|
colors: Theme,
|
||||||
|
toggleColors: (Theme) => void
|
||||||
|
};
|
||||||
|
|
||||||
|
const ColorContext = createContext<ColorContextType | null>(null);
|
||||||
|
|
||||||
|
export const ColorProvider = ({ children }) => {
|
||||||
|
const [colors, setColors] = useState(LightTheme);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const getColors = async () => {
|
||||||
|
try {
|
||||||
|
const savedColors = await AsyncStorage.getItem('colors');
|
||||||
|
if (savedColors) {
|
||||||
|
setColors(JSON.parse(savedColors));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Error loading colors:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
getColors();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const toggleColors = (newColors: Theme) => {
|
||||||
|
setColors(newColors);
|
||||||
|
AsyncStorage.setItem('colors', JSON.stringify(newColors))
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ColorContext.Provider value={{colors, toggleColors}}>
|
||||||
|
{children}
|
||||||
|
</ColorContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ColorContext;
|
@ -0,0 +1,42 @@
|
|||||||
|
import React, {createContext, useState, useEffect} from 'react';
|
||||||
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
|
|
||||||
|
|
||||||
|
interface ThemeContextType {
|
||||||
|
theme: string,
|
||||||
|
toggleTheme: (any)=> void
|
||||||
|
};
|
||||||
|
|
||||||
|
const ThemeContext = createContext<ThemeContextType | null>(null);
|
||||||
|
|
||||||
|
export const ThemeProvider = ({ children }) => {
|
||||||
|
const [theme, setTheme] = useState('light');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Load saved theme from storage
|
||||||
|
const getTheme = async () => {
|
||||||
|
try {
|
||||||
|
const savedTheme = await AsyncStorage.getItem('theme');
|
||||||
|
if (savedTheme) {
|
||||||
|
setTheme(savedTheme);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Error loading theme:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
getTheme();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const toggleTheme = newTheme => {
|
||||||
|
setTheme(newTheme);
|
||||||
|
AsyncStorage.setItem('theme', newTheme)
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemeContext.Provider value={{theme, toggleTheme}}>
|
||||||
|
{children}
|
||||||
|
</ThemeContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ThemeContext;
|
@ -0,0 +1,81 @@
|
|||||||
|
const Ecru = '#ACA279'
|
||||||
|
const Alabaster = '#F2F0E4'
|
||||||
|
const Jet = '#3F3C42'
|
||||||
|
const Moonstone = '#59BDCD'
|
||||||
|
const Cerulean = '#2680AA'
|
||||||
|
const Celeste = '#ADF3EA'
|
||||||
|
const Tan = '#E0C293'
|
||||||
|
const Pearl = '#E3DEC9'
|
||||||
|
const EerieBlack = '#222222'
|
||||||
|
const CarolinaBlue = '#8DB4D9'
|
||||||
|
const SteelBlue = '#5882A8'
|
||||||
|
|
||||||
|
export interface Theme {
|
||||||
|
primary: string,
|
||||||
|
primaryComplement: string,
|
||||||
|
cardBackground: string,
|
||||||
|
cardTitle: string,
|
||||||
|
cardDetail: string,
|
||||||
|
cardElementBackground: string,
|
||||||
|
cardElementText: string,
|
||||||
|
cardElementBorder: string,
|
||||||
|
cardElementTitle: string,
|
||||||
|
cardElementTitleBackground: string,
|
||||||
|
ingredientBackground: string,
|
||||||
|
ingredientContent: string,
|
||||||
|
ingredientBorder: string,
|
||||||
|
buttonBackground: string,
|
||||||
|
buttonDetail: string,
|
||||||
|
welcomeText: string,
|
||||||
|
welcomeName: string,
|
||||||
|
carrouselBackground: string,
|
||||||
|
carrouselText: string,
|
||||||
|
carrouselDetail: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LightTheme : Theme = {
|
||||||
|
primary: Cerulean,
|
||||||
|
primaryComplement: Moonstone,
|
||||||
|
cardBackground: Alabaster,
|
||||||
|
cardTitle: Ecru,
|
||||||
|
cardDetail: Jet,
|
||||||
|
cardElementBackground: Pearl,
|
||||||
|
cardElementText: Jet,
|
||||||
|
cardElementBorder: Ecru,
|
||||||
|
cardElementTitle: Jet,
|
||||||
|
cardElementTitleBackground: Alabaster,
|
||||||
|
ingredientBackground: Pearl,
|
||||||
|
ingredientBorder: EerieBlack,
|
||||||
|
ingredientContent: Jet,
|
||||||
|
buttonBackground: Pearl,
|
||||||
|
buttonDetail: Moonstone,
|
||||||
|
welcomeText: Ecru,
|
||||||
|
welcomeName: Moonstone,
|
||||||
|
carrouselBackground: Pearl,
|
||||||
|
carrouselText: Ecru,
|
||||||
|
carrouselDetail: Moonstone
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DarkTheme : Theme = {
|
||||||
|
primary: EerieBlack,
|
||||||
|
primaryComplement: Jet,
|
||||||
|
cardBackground: Jet,
|
||||||
|
cardTitle: Alabaster,
|
||||||
|
cardDetail: Alabaster,
|
||||||
|
cardElementBackground: SteelBlue,
|
||||||
|
cardElementText: Jet,
|
||||||
|
cardElementTitle: Alabaster,
|
||||||
|
cardElementBorder: SteelBlue,
|
||||||
|
cardElementTitleBackground: CarolinaBlue,
|
||||||
|
ingredientBackground: EerieBlack,
|
||||||
|
ingredientBorder: SteelBlue,
|
||||||
|
ingredientContent: Alabaster,
|
||||||
|
buttonBackground: Jet,
|
||||||
|
buttonDetail: CarolinaBlue,
|
||||||
|
welcomeText: SteelBlue,
|
||||||
|
welcomeName:Alabaster,
|
||||||
|
carrouselBackground: CarolinaBlue,
|
||||||
|
carrouselText: SteelBlue,
|
||||||
|
carrouselDetail: Alabaster
|
||||||
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"dependencies": {
|
|
||||||
"@eva-design/eva": "^2.2.0",
|
|
||||||
"@ui-kitten/components": "^5.3.1",
|
|
||||||
"expo": "^49.0.17",
|
|
||||||
"react-native-svg": "^13.14.0",
|
|
||||||
"typescript": "^5.1.3",
|
|
||||||
"@types/react": "~18.2.14",
|
|
||||||
"react-native-web": "~0.19.6",
|
|
||||||
"react-dom": "18.2.0",
|
|
||||||
"@expo/webpack-config": "^19.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in new issue