I have an App from which orders are made to a restaurant.
The customer selects the products they want from the catalog, then places the order from the app and a summary of the selected products and the price of all the products is displayed. This price of each product is calculated in the PlateForm and the total price of all the products is calculated in the State and the OrderSummary.js
So the restaurant responds from the Admin Panel. When the order is finished by the restaurant, in the administration panel they have a button to mark the order as finished. When they mark the finished order, it automatically sends a notification to the customer's App informing them: Your Order is ready. Please can you come and pick it up. Remember that the cost of your meal was: ...."
When the restaurant completes the order, it shows the message in the App, but the place of the order is shown in "0", the price is in the variable { total }, which I import from the order summary file and from the State. The problem I have, I don't know how to import to the OrderProgress screen, which is the one that shows the message. But I'm not calling { total } correctly, since it is not shown in the message,
This element is imported from ordersContext, that's why I don't import OrderSummary, but I don't know if I'm doing it correctly
How should I call the variable { total } to get it? I should say that I have a State and a Context to communicate the application, but there is something I have forgotten and the App gives me an error. What should I do to add the total price to the message? end that the client receives? What am I forgetting?
I show my files, I also show the Context and State
File OrderProgress.js
import React, { useContext, useEffect, useState } from 'react'
import { StyleSheet, View } from 'react-native'
import { Container, Button, Text, H1, H3 } from 'native-base'
import globalStyles from '../styles/global'
import { useNavigation } from '@react-navigation/native'
import PedidoContext from '../context/pedidos/pedidosContext'
import firebase from '../firebase'
import Countdown from 'react-countdown'
const ProgresoPedido = () => {
const navigation = useNavigation()
const { idpedido, total } = useContext(PedidoContext)
const [tiempo, guardarTiempo] = useState(0)
const [completado, guardarCompletado] = useState(false)
useEffect(() => {
const obtenerProducto = () => {
firebase.db.collection('ordenes')
.doc(idpedido)
.onSnapshot(function(doc) {
guardarTiempo(doc.data().tiempoentrega)
guardarCompletado(doc.data().completado)
})
}
obtenerProducto()
}, [])
// Muestra el tiempo en pantalla con Countdown
const renderer = ({ minutes, seconds }) => {
return (
<Text style={styles.tiempo}>{minutes}:{seconds}</Text>
)
}
return (
<Container style={globalStyles.contenedor}>
<View style={[globalStyles.contenido, { marginTop: 50 }]}>
{tiempo === 0 && (
<>
<Text style={{ textAlign: 'center', fontSize: 24 }}> Hemos recibido su pedido ...</Text>
<Text style={{ textAlign: 'center', fontSize: 24 }}>Estamos calculando el tiempo de entrega</Text>
</>
)}
{!completado && tiempo > 0 && (
<>
<Text style={{ textAlign: 'center' }}> </Text>
<Text>Tu pedido estará listo en
<Countdown
date={Date.now() + tiempo * 60000}
renderer={renderer} //muestra el tiempo que queda del pedido en la pantalla
/>
</Text>
</>
)}
{completado && (
<>
<H1 style={styles.textoCompletado}>Tu pedido esta listo</H1>
<H3 style={styles.textoCompletado}>Puedes pasar a recogerlo</H3>
<Text style={[styles.textoComplPrecio, {marginVertical: 40}]}> Recuerde que el costo de la comida fue: { total } </Text>
<Button tyle={ [globalStyles.boton, {marginTop:200}]}
rounded
block
onPress={ () => navigation.navigate("NuevaOrden")}
>
<Text style={ globalStyles.botonTexto}>Salir al Menu</Text>
</Button>
</>
)}
</View>
</Container>
)
}
const styles = StyleSheet.create({
tiempo: {
marginBottom: 20,
fontSize: 60,
textAlign: 'center',
marginTop: 80,
},
textoCompletado: {
textAlign: 'center',
textTransform: 'uppercase',
marginBottom: 20
},
textoComplPrecio: {
textAlign: 'center',
fontSize: 24,
color: '#8E44AD'
}
})
export default ProgresoPedido
File OrderSummary
import React, { useContext, useEffect } from 'react'
import { Alert, ScrollView } from 'react-native'
import {
Container,
List,
ListItem,
Thumbnail,
Text,
Left,
Body,
Button,
H1
} from 'native-base'
import { useNavigation } from '@react-navigation/native'
import globalStyles from '../styles/global'
import firebase from '../firebase'
import PedidoContext from '../context/pedidos/pedidosContext'
const ResumenPedido = () => {
const navigation = useNavigation()
// Context del pedido realizado
const { pedido, total, mostrarResumen, eliminarProducto, pedidoRealizado } = useContext(PedidoContext)
//console.log(pedido)
useEffect(() => {
calcularTotal()
}, [pedido])
// se crea un buucle infinito
/*useEffect(() => {
calcularTotal();
}), [pedido]*/
// Funcin para iterar sobre el pedido y los productos que añadimos y sus cantidades
const calcularTotal = () => {
let nuevoTotal = 0
nuevoTotal = pedido.reduce((nuevoTotal, articulo) => nuevoTotal + articulo.total, 0)
mostrarResumen(nuevoTotal)
}
// funcion para redirecionar al progreso del pedido
const progresoPedido = () => {
Alert.alert(
'Revisar el pedido',
'Una vez realizado el pedido, no podrás cambiarlo.',
[
{
text: 'Confirm',
onPress: async () => {
// crear un objeto
const pedidoObjeto = {
tiempoentrega: 0,
completado: false,
total: Number(total),
orden: pedido, //array
creado: Date.now()
}
// console.log(pedidoObjeto)
try {
const pedido = await firebase.db.collection('ordenes').add(pedidoObjeto)
pedidoRealizado(pedido.id)
navigation.navigate("ProgresoPedido")
} catch (error) {
console.log(error)
}
}
},
{ text: 'Revisar', style: 'cancel' }
]
)
}
// Elimina un producto del arreglo de pedido final
const confirmaEliminar = (id) => {
Alert.alert(
'¿Quieres eliminar este artículo ...?',
'Una vez eliminada no podrás recuperarlo.',
[
{
text: 'Confirm',
onPress: () => {
// eliminar producto del state
eliminarProducto(id)
}
},
{ text: 'Cancelar', style: 'cancel' }
]
)
}
return (
<Container style={globalStyles.contenedor}>
<ScrollView>
<List>
<H1 style={globalStyles.titulo}>Resumen de Producto</H1>
{pedido.map((plato, i) => {
const { cantidad, nombre, imagen, id, precio } = plato
return (
<List key={id + i}>
<ListItem thumbnail>
<Left>
<Thumbnail large square source={{ uri: imagen }} />
</Left>
<Body>
<Text> {nombre} </Text>
<Text>{cantidad} Unidades </Text>
<Text> {precio}€ Precio Unidad</Text>
<Button
onPress={() => confirmaEliminar(id)}
full
danger
style={{ marginTop: 20 }}
>
<Text style={[globalStyles.botonTexto, { color: '#FFF' }]}>Eliminar</Text>
</Button>
</Body>
</ListItem>
</List>
)
})}
<Text style={globalStyles.cantidad}>Total a Pagar:{total} €</Text>
<Button
onPress={() => navigation.navigate('Menu')}
style={{ marginTop: 20 }}
full
rounded
dark
>
<Text style={[globalStyles.botonTexto, { color: '#FFF' }]}>Seguir Comprando</Text>
</Button>
<Button
onPress={() => progresoPedido()}
style={globalStyles.botonForm}
full
>
<Text style={globalStyles.botonTexto}>Confirmar</Text>
</Button>
</List>
</ScrollView>
</Container>
)
}
export default ResumenPedido
OrdersState.js file
import React, { useReducer } from 'react'
import PedidoReducer from './pedidosReducer'
import PedidoContext from './pedidosContext'
import {
SELECCIONAR_PRODUCTO,
CONFIRMAR_ORDENAR_PLATO,
MOSTRAR_RESUMEN,
ELIMINAR_PRODUCTO,
PEDIDO_ORDENADO
} from '../../types'
const PedidosState = props => {
// Crear state inicial
const initialState = {
pedido: [],
plato: null,
total: 0,
idpedido: ''
}
// useReducer con dispatch para ejecutar las funciones
const [state, dispatch] = useReducer(PedidoReducer, initialState)
// Selecciona el Producto que el usuario desea ordenar
const selecionarPlato = plato => {
dispatch({
type: SELECCIONAR_PRODUCTO,
payload: plato
})
}
// cuando el usuario confirma un pedido
const guardarPedido = pedido => {
dispatch({
type: CONFIRMAR_ORDENAR_PLATO,
payload: pedido
})
}
// Muestra el total a pagar en el resumen de cada articulo
const mostrarResumen = total => {
dispatch({
type: MOSTRAR_RESUMEN,
payload: total
})
}
// Elimina el articulo seleccionado del carro de compra
const eliminarProducto = id => {
dispatch({
type: ELIMINAR_PRODUCTO,
payload: id
})
}
const pedidoRealizado = id => {
dispatch({
type: PEDIDO_ORDENADO,
payload: id
})
}
return (
<PedidoContext.Provider
value={{
pedido: state.pedido,
plato: state.plato,
total: state.total,
idpedido: state.idpedido,
selecionarPlato,
guardarPedido,
mostrarResumen,
eliminarProducto,
pedidoRealizado
}}
>
{props.children}
</PedidoContext.Provider>
)
}
export default PedidosState
FileFormPlato.js
import React, { useState, useContext, useEffect } from 'react'
import { StyleSheet, Alert } from 'react-native'
import {
Container,
Form,
Icon,
Input,
startIcon,
View,
Text
} from 'native-base'
import { useNavigation } from '@react-navigation/native'
import globalStyles from '../styles/global'
import PedidoContext from '../context/pedidos/pedidosContext'
const FormularioPlato = () => {
// State para la cantidad que marca el usuario de cada producto
const [cantidad, guardarCantidad] = useState(1)
const [total, guardarTotal] = useState(0)
// Context
const { plato, guardarPedido } = useContext(PedidoContext)
const { precio } = plato
// Redireccionar hasta el resumen de pedido
const navigation = useNavigation()
// En cuanto el componente carga, calcular la cantidad a pagar
useEffect(() => {
calcularTotal()
}, [cantidad])
// Calcula el total del platillo por su cantidad
const calcularTotal = () => {
const totalPagar = precio * cantidad;
guardarTotal(totalPagar);
}
// decrementar cantidad del producto elegido en Uno
const decrementarCantidad = () => {
if (cantidad > 1) {
const nuevaCantidad = parseInt(cantidad) - 1
guardarCantidad(nuevaCantidad)
}
}
//incrementar cantidad del producto elegido en Uno
const incrementarCantidad = () => {
const nuevaCantidad = parseInt(cantidad) + 1
guardarCantidad(nuevaCantidad)
}
// confirma si la cantidad de produto es correcta
const confirmarOrden = () => {
Alert.alert(
'Do you want to confirm your order?',
'A confirmed order can no longer be modified',
[
{
text: 'Confirm',
onPress: () => {
//Añade y Almacena el producto en el pedido principal
const pedido = {
...plato,
cantidad,
total
}
// console.log(pedido)
guardarPedido(pedido)
// Navegar hacia el resumen
navigation.navigate("ResumenPedido")
}
},
{
text: 'Cancelar',
style: 'cancel'
}
]
)
}
return (
<View>
<Form>
<Text style={globalStyles.titulo}>Cantidad</Text>
<Grid>
<Col>
<Button
props
dark
style={{ height: 70, justifyContent: 'center' }}
onPress={() => decrementarCantidad()}
>
<Icon style={{ fontSize: 40 }} name="remove" />
</Button>
</Col>
<Input
style={{ textAlign: 'center', fontSize: 22, marginTop: 10 }}
value={cantidad.toString()}
keyboardType="numeric"
onChangeText={cantidad => guardarCantidad(cantidad)}
/>
<Col>
<Button
props
style={{ height: 70, justifyContent: 'center' }}
onPress={() => incrementarCantidad()}
>
<Icon style={{ fontSize: 40 }} name="add" />
</Button>
</Col>
</Grid>
<Text style={globalStyles.cantidadSubtotal}>Subtotal: {total}€ </Text>
</Form>
<Footer style={styles.footer}>
<FooterTab>
<Button
style={globalStyles.boton}
onPress={() => confirmarOrden()}
>
<Text style={globalStyles.botonTexto}>Añadir a La Cesta</Text>
</Button>
</FooterTab>
</Footer>
</View>
)
}
const styles = StyleSheet.create({
footer: {
marginTop: '10%'
}
})
export default FormularioPlato
RequestReducer.js file
import {
SELECCIONAR_PRODUCTO,
CONFIRMAR_ORDENAR_PLATO,
MOSTRAR_RESUMEN,
ELIMINAR_PRODUCTO,
PEDIDO_ORDENADO
} from '../../types'
export default (state, action) => {
switch (action.type) {
case SELECCIONAR_PRODUCTO:
return {
...state,
plato: action.payload
}
case CONFIRMAR_ORDENAR_PLATO:
return {
...state,
pedido: [...state.pedido, action.payload]
}
case MOSTRAR_RESUMEN:
return {
...state,
total: action.payload
}
case ELIMINAR_PRODUCTO:
return {
...state,
pedido: state.pedido.filter(articulo => articulo.id !== action.payload)
}
case PEDIDO_ORDENADO:
return {
...state,
pedido: [],
total: 0,
idpedido: action.payload
}
default:
return state
}
}
I think it may be a problem related to the form submission, but in the form I don't see the event
onSubmit
, so I can't exactly emulate the problem on my side. But I have a proposal.Use the `total` from the command directly from Firebase
When the order is confirmed, it
app
redirects it to:Then, in
ResumenPedido
, the is computedtotal
and the methodprogresoPedido
executes an asynchronous operationfirebase
to persist the order inBD
, and immediately redirect to the component in questionProgresoPedido
:Then, in
ProgresoPedido
a query is made to the order:Here, I suggest reviewing what's in
doc.data()
, the order may come theretotal
. If so, then the total is saved in a new UI state in that same statescope
:A new UI state is declared for the exclusive use of the component
ProgresoPedido
:Then, it would only be necessary to use the new state
totalBD
where it is required to use the expression{total}
, for example:Hope this answer is helpful.