remake app ohome setup /notworking

This commit is contained in:
2021-10-24 22:18:31 +02:00
parent 4568076445
commit 55c6704d1b
76 changed files with 22173 additions and 749 deletions

32
src/pages/HomePage.js Normal file
View File

@@ -0,0 +1,32 @@
import React from 'react'
import { View } from 'react-native'
import HeaderPadding from '../components/Header'
//components
import Header from '../components/Header'
import GroceryCard from '../components/Home/GroceryCard'
import RecipeCard from '../components/Home/RecipeCard'
//styling
import { Wrapper, WrapperBoard, WrapperRight, WrapperLeft } from './styles/HomePage'
const HomePage = () => {
return (
<View style={{flex: 1}}>
<HeaderPadding/>
<Wrapper>
<WrapperBoard>
<WrapperLeft>
<GroceryCard />
</WrapperLeft>
<WrapperRight>
<RecipeCard />
</WrapperRight>
</WrapperBoard>
</Wrapper>
</View>
)
}
export default HomePage

View File

@@ -0,0 +1,20 @@
import React, { useState } from 'react'
//components
import TabMenu from '../../components/GroceryList/TabMenu'
import Groceries from './storageManagement/Groceries'
import Products from './storageManagement/Products'
//styling
import { WrapperGroceryPage } from './styles/GroceryListPage'
const GroceryListPage = () => {
const [currentTab, setCurrentTab] = useState("Groceries")
return (
<WrapperGroceryPage>
{
currentTab === "Groceries" ? <Groceries /> : <Products />
}
<TabMenu currentTab={currentTab} setCurrentTab={setCurrentTab} />
</WrapperGroceryPage>
)
}
export default GroceryListPage

View File

@@ -0,0 +1,26 @@
import { Text, View } from 'react-native'
import React from 'react'
//components
import Header from '../../../components/Header'
import GroceryList from '../../../components/GroceryList/groceries/GroceryList'
import { LoadAnimation } from '../../../styles/componentBlueprints'
import { ContainerButtons, AddItemButton } from '../../../components/GroceryList/groceries/GroceryButtons'
//styling
import { ArrowBack } from '../../styles/page'
//redux
import { useSelector } from 'react-redux'
const Groceries = () => {
const statusItems = useSelector(state => state.items.status)
return (
<View>
{statusItems === 'loading' ? <LoadAnimation/>
: <GroceryList />}
<ContainerButtons />
<AddItemButton />
</View>
)
}
export default Groceries

View File

@@ -0,0 +1,28 @@
import { Text, View } from 'react-native'
import React from 'react'
//components
import Header from '../../../components/Header'
import ProductsList from '../../../components/GroceryList/products/ProductsList'
import { AddProductButton, ContainerButtons } from '../../../components/GroceryList/products/ProductButtons'
import { LoadAnimation } from '../../../styles/componentBlueprints'
//styling
import { ArrowBack } from '../../styles/page'
//redux
import { useSelector } from 'react-redux'
const Products = () => {
const statusProducts = useSelector(state => state.products.status)
return (
<View>
{statusProducts === 'loading' ? <LoadAnimation />
: <ProductsList />}
<AddProductButton />
<ContainerButtons />
</View>
)
}
export default Products

View File

@@ -0,0 +1,6 @@
import { View } from "react-native"
import styled from 'styled-components'
export const WrapperGroceryPage = styled(View)`
width:100%;
`

View File

@@ -0,0 +1,113 @@
import { Text, View } from 'react-native'
//components
import Header from "../../components/Header"
import { ArrowBack } from "../styles/page";
import { Ingredients } from "../../components/recipes/addRecipe/Inputs";
//styling
import { Wrapper, WrapperRecipe, Input, InputInstructions, IconRecipe, IconPot, IconMeal, IconImage, IconCheck } from "./styles/addRecipe"
import { useState } from "react";
import { addRecipe, findRecipeById, updateRecipe } from "../../redux/slices/recipesSlice";
import { useDispatch, useSelector } from "react-redux";
import { StyledImage } from "./styles/recipe";
import HeaderPadding from '../../components/Header';
const AddRecipe = () => {
let { id } = useParams()
const foundRecipe = useSelector(state => findRecipeById(state, id))
let recipe = foundRecipe ? foundRecipe : { name: '', prepTime: '', servings: '', image: '', ingredients: [], instructions: '' }
const dispatch = useDispatch()
const [name, setName] = useState(recipe.name)
const [prepTime, setPrepTime] = useState(recipe.prepTime)
const [servings, setServings] = useState(recipe.servings)
const [image, setImage] = useState(recipe.image)
const [ingredients, setIngredients] = useState(recipe.ingredients)
const [instructions, setInstructions] = useState(recipe.instructions)
const handleImageInput = (input) => {
if (input.target.files && input.target.files[0] && input.target.files[0].size < 1000000) {
let reader = new FileReader()
reader.onload = function (e) {
setImage(e.target.result)
};
reader.readAsDataURL(input.target.files[0])
}
else {
alert("That file is too big! Choose an image with a size lower than 1MB")
}
}
const submitRecipe = () => {
if (name && ingredients && instructions) {
foundRecipe ? dispatch(updateRecipe({ _id: foundRecipe._id, name, prepTime: Number(prepTime), servings: Number(servings), image, ingredients, instructions }))
: dispatch(addRecipe({ name, prepTime: Number(prepTime), servings: Number(servings), image, ingredients, instructions }))
console.log(typeof (image))
}
else {
alert("You should add a name, at least one ingredient and the instructions")
}
}
const handleInput = (event) => {
let lastChar = event.target.value.substr(-1).charCodeAt(0);
let penultimateChar = event.target.value.substr(-2).charCodeAt(0);
if (instructions === '') {
setInstructions("- " + event.target.value)
return
}
else if (penultimateChar === 10 && lastChar === 45) {
setInstructions(instructions.slice(0, instructions.length - 3))
return
}
else if (lastChar === 10) {
setInstructions(event.target.value + "- ")
return
}
setInstructions(event.target.value)
}
return (
<>
<HeaderPadding/>
<Wrapper >
{image && <StyledImage src={image} alt="Recipe" />}
<WrapperRecipe>
<View id="row">
<IconRecipe />
<Input
type="text"
value={name}
onChange={(text) => setName(text.target.value)}
placeholder="Recipe name" />
</View>
<View id="row">
<IconPot />
<Input
type="number"
value={prepTime}
onChange={(text) => setPrepTime(text.target.value)}
placeholder="Prep time (min)" />
<IconMeal />
<Input
type="number"
value={servings}
onChange={(text) => setServings(text.target.value)}
placeholder="Servings" />
</View>
<View id="row">
<IconImage />
<Input
style={{ borderBottom: 'none' }}
type="file" accept="image/*"
onChange={input => handleImageInput(input)} />
</View>
<Ingredients ingredients={ingredients} setIngredients={setIngredients} />
<InputInstructions
type="text"
value={instructions}
onChange={(text) => handleInput(text)}
placeholder='Instructions' />
</WrapperRecipe>
</Wrapper>
</>
)
}
export default AddRecipe

View File

@@ -0,0 +1,72 @@
import { useSelector } from "react-redux"
import { useParams } from "react-router"
//redux
import { findRecipeById } from "../../redux/slices/recipesSlice"
import Header from "../../components/Header"
import { ArrowBack } from "../styles/page"
import { Wrapper, WrapperRecipe } from "./styles/addRecipe"
import { Ingredient } from "../../components/recipes/addRecipe/Ingredient"
import { Title, InstructionWrapper, InstructionNumber, StyledImage, TextPrep, TextTime, TextMinutes, WrapperServings, TextServings, IconPotLarge, IconMeal, Hr } from "./styles/recipe"
import { OptionsButtonRecipe, AddIngredientsButton } from "../../components/recipes/addRecipe/Buttons"
import { Text, View } from "react-native"
import HeaderPadding from "../../components/Header"
const Recipe = () => {
let { id } = useParams()
const recipe = useSelector(state => findRecipeById(state, id))
const IngredientList = recipe.ingredients.map((ingredient, index) => {
return (<Ingredient ingredient={ingredient} index={index} key={index} />)
}
)
let strArr = recipe.instructions.split("- ")
const InstructionList = strArr.map((instruction, index) => {
return index !== 0 && (<InstructionWrapper key={index} >
<View><InstructionNumber>{index}</InstructionNumber></View>
<Text id="instruction">{instruction}</Text>
</InstructionWrapper>)
})
return (
<>
<HeaderPadding/>
<Wrapper >
{recipe.image && <StyledImage src={recipe.image} />}
<WrapperRecipe>
<Text>{recipe.name}</Text>
<Hr />
{recipe.prepTime !== 0 && recipe.prepTime && <>
<View id="row" style={{ position: 'relative', marginTop: 0 }} >
<IconPotLarge />
<TextPrep>READY IN:</TextPrep>
<View id="column" >
<TextTime>{recipe.prepTime}</TextTime>
<TextMinutes>minutes</TextMinutes>
</View>
{recipe.servings !== 0 && recipe.servings && <>
<WrapperServings>
<IconMeal />
<View>
<TextTime>{recipe.servings}</TextTime>
<TextServings>servings</TextServings>
</View>
</WrapperServings>
</>}
</View>
<Hr />
</>}
<View style={{ width: '100%' }}>
<Title>Ingredients</Title>
{IngredientList}
<Hr />
<Title>Instructions</Title>
{InstructionList}
</View>
</WrapperRecipe>
</Wrapper>
<AddIngredientsButton id={id} />
</>
)
}
export default Recipe

View File

@@ -0,0 +1,22 @@
//components
import RecipeList from "../../components/recipes/RecipeList"
import Header from '../../components/Header'
import { ArrowBack } from '../styles/page'
import { AddRecipeButton } from "../../components/recipes/addRecipe/Buttons";
import { LoadAnimation } from "../../styles/componentBlueprints";
//redux
import { useSelector } from "react-redux";
import { Text } from "react-native";
import HeaderPadding from "../../components/Header";
const RecipesPage = () => {
const statusRecipes = useSelector(state => state.recipes.status)
return (<>
<HeaderPadding/>
{statusRecipes === 'loading' ? <LoadAnimation/>
: <RecipeList />}
<AddRecipeButton />
</>
)
}
export default RecipesPage

View File

@@ -0,0 +1,95 @@
import { Image, Text, TextInput, View } from "react-native"
import styled from 'styled-components'
import { GiHotMeal, GiMeal, GiCookingPot } from 'react-icons/gi'
import { HiCheck } from 'react-icons/hi'
import { BiImageAdd } from 'react-icons/bi'
export const Wrapper = styled(View)`
display: flex;
flex-direction: column;
align-items: center;
@media ${({ theme }) => theme.mediaQueries.below768}{
align-items: flex-start;
}
`
export const WrapperRecipe = styled(View)`
display: flex;
flex-direction: column;
align-items: flex-start;
width: 500px;
padding: 10px;
#row{
margin-top: 5px;
display: flex;
flex-direction: row;
width: 100%;
align-items: flex-end;
}
#column{
margin-left: 5px;
margin-bottom: -3px;
display: flex;
flex-direction: column;
width: 100%;
justify-content: flex-end;
}
@media ${({ theme }) => theme.mediaQueries.below768}{
width: 100%;
}
`
export const Input = styled(TextInput)`
flex:1;
margin-left: 5px;
color: ${props => props.theme.colors.textW1};
border-bottom-color: ${props => props.theme.colors.primary + 'aa'};
border-bottom-width: 1px;
font-size: ${({theme}) => theme.fontSize.fontS};
width: 100%;
`
export const InputInstructions = styled(Text)`
margin-top: 30px;
padding: 5px;
color: ${props => props.theme.colors.textW1};
border-top: solid ${props => props.theme.colors.primary + 'aa'} 1px;
border-bottom-color: ${props => props.theme.colors.primary + 'aa'};
border-bottom-width: 1px;
font-size: ${({theme}) => theme.fontSize.fontS};
min-height: 600px;
width: 100%;
`
export const StyledImage = styled(Image)`
object-fit: cover;
width: 100px;
height: 100px;
`
export const IconRecipe = styled(GiHotMeal)`
color: ${({ theme }) => theme.colors.primaryVar};
font-size: ${({theme}) => theme.fontSize.fontM};
`
export const IconPot = styled(GiCookingPot)`
color: ${({ theme }) => theme.colors.primaryVar};
font-size: ${({theme}) => theme.fontSize.fontM};
`
export const IconMeal = styled(GiMeal)`
margin-left: 5px;
color: ${({ theme }) => theme.colors.primaryVar};
font-size: ${({theme}) => theme.fontSize.fontM};
`
export const IconImage = styled(BiImageAdd)`
color: ${({ theme }) => theme.colors.primaryVar};
font-size: ${({theme}) => theme.fontSize.fontM};
`
export const IconCheck = styled(HiCheck)`
margin-right: 10px;
color: ${({ theme }) => theme.colors.textB3};
background-color: ${({ theme }) => theme.colors.primary + 'cc'};
border-radius: 30px;
min-width: 40px;
height: 40px;
font-size: ${({theme}) => theme.fontSize.fontL};
`

View File

@@ -0,0 +1,93 @@
import { Image, Text, View } from "react-native"
import styled from 'styled-components'
import { GiCookingPot, GiMeal } from 'react-icons/gi'
export const Title = styled(Text)`
margin-top: 10px;
`
export const InstructionWrapper = styled(View)`
display: flex;
flex-direction: row;
width: 100%;
padding: 5px 0px;
align-items: center;
border-bottom-color: ${({ theme }) => theme.colors.dp02};
border-bottom-width: 3px;
#instruction{
margin-left: 7px;
color: ${({theme}) => theme.colors.textW4};
}
`
export const InstructionNumber = styled(Text)`
display: flex;
align-items: center;
justify-content: center;
background-color: ${({theme}) => theme.colors.primary + 'dd'};
color: ${({theme}) => theme.colors.textB1};
font-size: 25px;
font-weight: bold;
height: 34px;
width: 34px;
border-radius: 17px;
`
export const StyledImage = styled(Image)`
margin-top: -70px;
object-fit: cover;
height: 200px;
width: 100%;
@media ${({theme}) => theme.mediaQueries.above768}{
width: 500px;
}
`
export const TextPrep = styled(Text)`
text-align: right;
width: 70px;
font-weight: bold;
font-size: ${({theme}) => theme.fontSize.fontS};
line-height: 1.2;
`
export const TextTime = styled(Text)`
margin-bottom: -3px;
width: 70px;
font-size: ${({theme}) => theme.fontSize.fontS};
font-weight: bold;
line-height: 1.2;
color: ${({ theme }) => theme.colors.primary};
`
export const TextMinutes = styled(Text)`
width: 70px;
font-size: ${({theme}) => theme.fontSize.fontS};
font-weight: normal;
color: ${({ theme }) => theme.colors.primary};
`
export const WrapperServings = styled(View)`
display: flex;
position: absolute;
right: 2%;
top: 2px;
`
export const TextServings = styled(Text)`
margin-top: -5px;
font-weight: bold;
`
export const IconPotLarge = styled(GiCookingPot)`
margin: -20px 0px -16px 0px;
color: ${({ theme }) => theme.colors.primary};
font-size: ${({theme}) => theme.fontSize.fontL};
`
export const IconMeal = styled(GiMeal)`
margin: -20px 0px -16px 0px;
color: ${({ theme }) => theme.colors.primary};
font-size: ${({theme}) => theme.fontSize.fontL};
`
export const Hr = styled(View)`
width: 100%;
margin: 4px 0px;
height: 2px;
border-radius: 1px;
background-color: ${({ theme }) => theme.colors.dp08};
`

View File

@@ -0,0 +1,30 @@
import { View } from "react-native"
import styled from 'styled-components'
import { FiMenu } from 'react-icons/fi'
export const Wrapper = styled(View)`
display: flex;
flex-direction: column;
width: 100%;
align-items: center;
`
export const WrapperBoard = styled(View)`
display: flex;
justify-content: center;
flex-direction: row;
width: 100%;
flex: 1;
align-items: center;
`
export const WrapperLeft = styled(View)`
width: 50%;
padding: 0px 4px 8px 8px;
`
export const WrapperRight = styled(View)`
width: 50%;
padding: 0px 8px 8px 4px;
`
// export const Menu = styled(FiMenu)`
// color: ${props=>props.theme.colors.textW2};
// font-size: 45px;
// `

9
src/pages/styles/page.js Normal file
View File

@@ -0,0 +1,9 @@
import styled from 'styled-components'
import { BiArrowBack } from 'react-icons/bi'
export const ArrowBack = styled(BiArrowBack).attrs(props=>({
// onClick:() => history.goBack()
}))`
color: ${({theme}) => theme.colors.textW2};
font-size: 45px;
`