remake app ohome setup /notworking
This commit is contained in:
32
src/pages/HomePage.js
Normal file
32
src/pages/HomePage.js
Normal 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
|
||||
20
src/pages/groceryList/GroceryListPage.js
Normal file
20
src/pages/groceryList/GroceryListPage.js
Normal 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
|
||||
26
src/pages/groceryList/storageManagement/Groceries.js
Normal file
26
src/pages/groceryList/storageManagement/Groceries.js
Normal 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
|
||||
28
src/pages/groceryList/storageManagement/Products.js
Normal file
28
src/pages/groceryList/storageManagement/Products.js
Normal 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
|
||||
6
src/pages/groceryList/styles/GroceryListPage.js
Normal file
6
src/pages/groceryList/styles/GroceryListPage.js
Normal file
@@ -0,0 +1,6 @@
|
||||
import { View } from "react-native"
|
||||
import styled from 'styled-components'
|
||||
|
||||
export const WrapperGroceryPage = styled(View)`
|
||||
width:100%;
|
||||
`
|
||||
113
src/pages/recipes/AddRecipe.js
Normal file
113
src/pages/recipes/AddRecipe.js
Normal 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
|
||||
72
src/pages/recipes/Recipe.js
Normal file
72
src/pages/recipes/Recipe.js
Normal 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
|
||||
22
src/pages/recipes/RecipesPage.js
Normal file
22
src/pages/recipes/RecipesPage.js
Normal 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
|
||||
95
src/pages/recipes/styles/addRecipe.js
Normal file
95
src/pages/recipes/styles/addRecipe.js
Normal 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};
|
||||
`
|
||||
93
src/pages/recipes/styles/recipe.js
Normal file
93
src/pages/recipes/styles/recipe.js
Normal 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};
|
||||
`
|
||||
30
src/pages/styles/HomePage.js
Normal file
30
src/pages/styles/HomePage.js
Normal 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
9
src/pages/styles/page.js
Normal 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;
|
||||
`
|
||||
Reference in New Issue
Block a user