function App() {
return (
<PayPalScriptProvider
options={{
"client-id": process.env.REACT_APP_PAYPAL_CLIENT_ID,
currency: "PHP",
}}
>
<Router>
<div className="app">
<Routes>
<Route path="/" element={<LandingPage />}></Route>
<Route path="/admin" element={<Admin />}></Route>
</Routes>
</div>
</Router>
</PayPalScriptProvider>
);
}
I specified the currency in the properties of paypal script provider but it's still in usd
Purchase Image showing USD
What should I do to change the currency of it to Philippine Peso
Here is the link of the npm package that i used:
https://www.npmjs.com/package/#paypal/react-paypal-js
Whole Code
import "./App.css";
import { useState, useRef, useEffect } from "react";
import Dropzone from "react-dropzone";
import { PayPalButtons, PayPalScriptProvider } from "#paypal/react-paypal-js";
import {
arrayUnion,
collection,
deleteDoc,
doc,
onSnapshot,
orderBy,
query,
serverTimestamp,
setDoc,
updateDoc,
} from "firebase/firestore";
import { db, storage } from "./firebase.js";
import { v4 as uuidv4 } from "uuid";
import { getDownloadURL, ref, uploadString } from "firebase/storage";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import thanks from "./Images/thanks.png";
function PaypalCheckoutButton(props) {
const [error, setError] = useState(null);
const handleApprove = (orderID) => {
props.completeOrder();
};
if (error) {
alert(error);
}
return (
<div style={{ marginTop: "1rem" }}>
<PayPalButtons
createOrder={(data, actions) => {
return actions.order.create({
purchase_units: [
{
description: props.product.description,
amount: {
currency_code: "PHP",
value: props.product.price,
},
},
],
});
}}
onApprove={async (data, action) => {
const order = await action.order.capture();
console.log("order", order);
handleApprove(data.orderID);
}}
onCancel={() => {}}
onError={(err) => {
setError(err);
console.log("Paypal Checkout Error", err);
}}
/>
</div>
);
}
function Step1(props) {
const [isGift, setIsGift] = useState(null);
const [message, setMessage] = useState("");
function newKeychain() {
setIsGift(null);
props.setOrders((currentOrders) => [
{ image: props.image, message: message },
...currentOrders,
]);
props.setImage(null);
}
function handleShowButton() {
if (isGift === false) {
return props.image;
} else if (isGift === true) {
return props.image && message !== "";
}
}
return (
<div
className="step1 step"
style={isGift === true ? { marginTop: "5rem" } : {}}
>
{isGift === null && (
<>
<h1 className="title">Choose what type of keychain</h1>
<div className="purchaseTypeSection">
<div
className="formyself purchaseType"
onClick={() => setIsGift(false)}
>
<h2>Standard</h2>
<p className="keychainTypeDescription">
Perfect for personal use
</p>
<h2 className="price">₱69</h2>
</div>
<div className="gift purchaseType" onClick={() => setIsGift(true)}>
<h2>With Message</h2>
<p className="keychainTypeDescription">
Perfect for gifts to your love ones
</p>
<h2 className="price">₱99</h2>
</div>
</div>
</>
)}
{isGift !== null && (
<>
<h1 className="title">Choose your image</h1>
<Dropzone
onDrop={(acceptedFiles) =>
props.setImage(() => {
if (!acceptedFiles[0]) {
return null;
}
var fr = new FileReader();
fr.onload = function () {
props.setImage(fr.result);
};
fr.readAsDataURL(acceptedFiles[0]);
})
}
multiple={false}
accept={{ "image/jpeg": [".png", ".jpg"] }}
>
{({ getRootProps, getInputProps }) => (
<section>
<div
{...getRootProps()}
style={props.image ? { padding: "0 !important" } : {}}
>
<input {...getInputProps()} />
{props.image ? (
<img
className="drop__image"
src={props.image}
alt="Your Keychain"
/>
) : (
<h3 className="drop__text">
Drag your image here, or click to select a file
</h3>
)}
</div>
</section>
)}
</Dropzone>
{isGift === true && (
<textarea
className="messageInput largeInput"
maxLength={100}
placeholder="Enter your message to your special someone here"
value={message}
onChange={(e) => setMessage(e.target.value)}
></textarea>
)}
<div className="step1Buttons">
<button
className="step1Button"
onClick={() => {
setIsGift(null);
props.setImage(null);
}}
>
Go back
</button>
{handleShowButton() && (
<>
<button className="step1Button" onClick={newKeychain}>
Create Another Keychain
</button>
<button
className="step1Button"
onClick={() => {
newKeychain();
props.setStep((step) => step + 1);
}}
>
Next
</button>
</>
)}
</div>
</>
)}
</div>
);
}
function Step2(props) {
function completed() {
return (
props.customerName !== "" &&
props.customerNumber > 0 &&
props.customerAddress !== ""
);
}
return (
<div className="step2 step center">
<div className="question center">
<h3>Let us know who will we deliver it to</h3>
<input
placeholder="Enter your name"
value={props.customerName}
onChange={(e) => props.setCustomerName(e.target.value)}
></input>
</div>
<div className="question center">
<h3>For us to give you infomations about the delivery and package</h3>
<input
type="number"
placeholder="Enter your phone number"
value={props.customerNumber}
onChange={(e) => props.setCustomerNumber(e.target.value)}
></input>
</div>
<div className="question center">
<h3>Let us know where to deliver</h3>
<textarea
className="largeInput locationInput"
placeholder="Enter your location"
value={props.customerAddress}
onChange={(e) => props.setCustomerAddress(e.target.value)}
></textarea>
</div>
<div className="step1Buttons">
<button
className="step1Button createAnother"
onClick={() => props.setStep((step) => step - 1)}
>
Go Back
</button>
<button
className="step1Button"
style={
completed()
? { backgroundColor: "#5c90a0", cursor: "pointer" }
: { backgroundColor: "#b5b5b5", cursor: "default" }
}
onClick={() => {
if (!completed()) {
return;
}
props.setStep((step) => step + 1);
}}
>
Next
</button>
</div>
</div>
);
}
function Step3(props) {
function getPrice() {
var p = 0;
props.orders.forEach((o) => {
if (o.message === "") {
p += 69;
} else {
p += 99;
}
});
return p;
}
function getDescription() {
var giftCount = 0;
var standardCount = 0;
props.orders.forEach((o) => {
if (o.message === "") {
standardCount += 1;
} else {
giftCount += 1;
}
});
return `${giftCount > 0 ? `${giftCount} Gift Keychain/s` : ""}${
giftCount * standardCount !== 0 ? " and " : ""
}${standardCount > 0 ? `${standardCount} Standard Keychain/s` : ""}`;
}
async function completeOrder(method) {
// get the order informations
// add it to the orders collection in firebase
const orderId = uuidv4();
await setDoc(doc(db, "orders", orderId), {
customerName: props.customerName,
customerNumber: props.customerNumber,
customerAddress: props.customerAddress,
timestamp: serverTimestamp(),
paymentMethod: method,
description: getDescription(),
price: getPrice(),
status: "toApprove",
});
for (let i = 0; i < props.orders.length; i++) {
let order = props.orders[i];
const fileRef = ref(storage, `orders/${orderId}`);
await uploadString(fileRef, order.image, "data_url").then(
async (snapshot) => {
const downloadUrl = await getDownloadURL(fileRef);
updateDoc(doc(db, "orders", orderId), {
orders: arrayUnion({
keychainImage: downloadUrl,
keychainMessage: order.message,
}),
});
}
);
}
props.setHasOrdered(true);
props.setOrders([]);
props.setCustomerName("");
props.setCustomerAddress("");
props.setCustomerNumber("");
props.setStep(1);
}
return (
<div className="step3 step">
<button
className="paymentMethod cod"
onClick={() => completeOrder("Cash On Delivery")}
>
Cash on Delivery
</button>
<h2 style={{ marginTop: "1rem" }}>Or</h2>
<PaypalCheckoutButton
completeOrder={() => completeOrder("Online")}
product={{ description: getDescription(), price: getPrice() }}
/>
</div>
);
}
function LandingPage(props) {
const [orders, setOrders] = useState([]);
const [customerName, setCustomerName] = useState("");
const [customerNumber, setCustomerNumber] = useState();
const [customerAddress, setCustomerAddress] = useState("");
const [step, setStep] = useState(1);
const [navbar, setNavbar] = useState(false);
const bottomRef = useRef();
const topRef = useRef();
const [image, setImage] = useState(null);
const changeBackground = () => {
setNavbar(window.scrollY > 0);
};
useEffect(() => {
window.addEventListener("scroll", changeBackground);
}, []);
function handleStepIndicator() {
if (step === 1) {
return "Step 1. Create your keychains";
} else if (step === 2) {
return "Step 2. Delivery Informations";
} else if (step === 3) {
return "Step 3. Payment Method";
}
}
const [hasOrdered, setHasOrdered] = useState(false);
return (
<>
{hasOrdered && (
<>
<div className="overlay" onClick={() => setHasOrdered(false)} />
<div className="purchaseModal">
<img src={thanks} alt="thanks" className="thanksImage"></img>
<h2>Thank you for your purchase</h2>
<p className="purchaseInfo">
We will inform you about the package via phone number that you
gave us
</p>
</div>
</>
)}
<div className="top" ref={topRef} style={{ marginTop: "-2rem" }} />
<section className="hero">
<div
className={`hero__navbar ${navbar && "active"}`}
onClick={() => {
topRef.current?.scrollIntoView({ behavior: "smooth" });
}}
>
<h2
className="hero__nav"
onClick={() => {
topRef.current?.scrollIntoView({ behavior: "smooth" });
}}
>
KEYCH
</h2>
</div>
<div className="hero__about">
<h1 className="hero__headline">BRING YOUR KEYCHAIN IDEAS TO LIFE</h1>
<p className="hero__support">
We make handmade and customized keychains using images that you like
</p>
</div>
<button
className="hero__cta"
onClick={() => {
bottomRef.current?.scrollIntoView({ behavior: "smooth" });
}}
>
<h3>Create Now</h3>
</button>
</section>
<section className="creation">
<h1 className="creation__stepIndicator">{handleStepIndicator()}</h1>
{step === 1 && (
<Step1
image={image}
setImage={setImage}
orders={orders}
setOrders={setOrders}
setStep={setStep}
/>
)}
{step === 2 && (
<Step2
customerName={customerName}
setCustomerName={setCustomerName}
customerNumber={customerNumber}
setCustomerNumber={setCustomerNumber}
customerAddress={customerAddress}
setCustomerAddress={setCustomerAddress}
setStep={setStep}
/>
)}
{step === 3 && (
<Step3
orders={orders}
setOrders={setOrders}
customerName={customerName}
customerAddress={customerAddress}
customerNumber={customerNumber}
setCustomerName={setCustomerName}
setCustomerAddress={setCustomerAddress}
setCustomerNumber={setCustomerNumber}
setHasOrdered={setHasOrdered}
setStep={setStep}
/>
)}
</section>
<div className="bottom" ref={bottomRef} />
</>
);
}
function OrderInfo(props) {
return (
<div className="orderInfo">
<div className="info__segment" style={{ marginBottom: "3rem" }}>
<h1>{props.id}</h1>
<h5>Order ID</h5>
</div>
{props.orders.map((o, i) => (
<div className="keychainInfo">
<h1>Keychain No. {i + 1}</h1>
<div className="info__segment">
<img
className="keychainImage"
src={o.keychainImage}
alt="keychainImage"
/>
<h5>Keychain Image</h5>
</div>
{o.keychainMessage && (
<div className="info__segment">
<h3 className="keychainMessage">{o.keychainMessage}</h3>
<h5>Keychain Message</h5>
</div>
)}
</div>
))}
<div className="customerInfo">
<div className="info__segment">
<h3 className="customerName">{props.customerName}</h3>
<h5>Customer Name</h5>
</div>
<div className="info__segment">
<h3 className="customerNumber">{props.customerNumber}</h3>
<h5>Customer Number</h5>
</div>
<div className="info__segment">
<h3 className="customerAddress">{props.customerAddress}</h3>
<h5>Customer Address</h5>
</div>
<div className="info__segment">
<h3 className="customerAddress">{props.paymentMethod}</h3>
<h5>Payment Method</h5>
</div>
<div className="info__segment">
<h3 className="totalPrice">₱ {props.price}</h3>
<h5>Total Price</h5>
</div>
</div>
</div>
);
}
function OrderManagement() {
const [orders, setOrders] = useState([]);
useEffect(
() =>
onSnapshot(
query(collection(db, "orders"), orderBy("timestamp", "desc")),
(snapshot) => {
setOrders(snapshot.docs);
}
),
[]
);
return (
<section className="orders">
<section className="toApprove orders__section">
<h1 className="segmentTitle">To Approve</h1>
{orders
.filter((o) => o.data().status === "toApprove")
.map((o) => (
<div className="toApproveOrder Order">
<OrderInfo
key={o.id}
orders={o.data().orders}
customerName={o.data().customerName}
customerAddress={o.data().customerAddress}
customerNumber={o.data().customerNumber}
price={o.data().price}
id={o.id}
paymentMethod={o.data().paymentMethod}
/>
<div className="toApproveControls controls">
<button
className="declineButton controlButton decline"
onClick={() => {
deleteDoc(doc(db, "orders", o.id));
}}
>
Decline
</button>
<button
className="approveButton controlButton"
onClick={() => {
updateDoc(doc(db, "orders", o.id), {
status: "toCreate",
});
}}
>
Approve
</button>
</div>
</div>
))}
</section>
<section className="toCreate orders__section">
<h1 className="segmentTitle">To Create</h1>
{orders
.filter((o) => o.data().status === "toCreate")
.map((o) => (
<div className="Order">
<OrderInfo
key={o.id}
orders={o.data().orders}
customerName={o.data().customerName}
customerAddress={o.data().customerAddress}
customerNumber={o.data().customerNumber}
price={o.data().price}
id={o.id}
paymentMethod={o.data().paymentMethod}
/>
<div className="controls">
<button
className="controlButton"
onClick={() => {
updateDoc(doc(db, "orders", o.id), {
status: "toShip",
});
}}
>
Ship Order
</button>
</div>
</div>
))}
</section>
<section className="toShip orders__section">
<h1 className="segmentTitle">To Ship</h1>
{orders
.filter((o) => o.data().status === "toShip")
.map((o) => (
<div className="Order">
<OrderInfo
key={o.id}
orders={o.data().orders}
customerName={o.data().customerName}
customerAddress={o.data().customerAddress}
customerNumber={o.data().customerNumber}
price={o.data().price}
id={o.id}
paymentMethod={o.data().paymentMethod}
/>
<div className="controls">
<button
className="controlButton"
onClick={() => {
deleteDoc(doc(db, "orders", o.id));
}}
>
Complete Order
</button>
</div>
</div>
))}
</section>
</section>
);
}
function Admin() {
const securityPassword = "Pogi Ni Vlad";
const [password, setPassword] = useState("");
return password === securityPassword ? (
<OrderManagement />
) : (
<section className="login">
<h1 className="title">Keych Admin Login</h1>
<div className="login__form">
<input
type="text"
className="form__pasword"
placeholder="Input password to enter: "
value={password}
onChange={(e) => setPassword(e.target.value)}
></input>
</div>
</section>
);
}
function App() {
return (
<PayPalScriptProvider
options={{
"client-id": process.env.REACT_APP_PAYPAL_CLIENT_ID,
currency: "PHP",
}}
>
<Router>
<div className="app">
<Routes>
<Route path="/" element={<LandingPage />}></Route>
<Route path="/admin" element={<Admin />}></Route>
</Routes>
</div>
</Router>
</PayPalScriptProvider>
);
}
export default App;
Where is the PayPalButtons component in the first code sample?
Consider using the full sample the package provides as a base. There's a currency variable set in two locations (line 10 and later within the PayPalScriptProvider) for whatever reason.
Related
Hello guys i have a project made with react, node, express, and mysql. I have a problem, in this project user can register and login. In the login page i want to display snackbar with material ui after user succeed login. But the problem is user will redirecting to ("/home) without displaying the snackbar first. I want to make the snackbar appear for like 3second and after that the user will go to the next page.
This is the code, problem occur in login function :
const Login = () => {
let navigate = useNavigate();
Axios.defaults.withCredentials = true;
const { emailLog, setEmailLog } = useContext(EmailUser);
const [ passwordLog, setPasswordLog ] = useState("");
const { loginStatus, setLoginStatus } = useContext(LoginStatus);
const [ showSuccess, setShowSuccess ] = React.useState(false);
const [ showWarning, setShowWarning ] = React.useState(false);
const handleNotShowSuccess = (event, reason) => {
if (reason === 'clickaway') {
return;
}
setShowSuccess(false);
};
const handleNotShowWarning= (event, reason) => {
if (reason === 'clickaway') {
return;
}
setShowWarning(false);
};
const [ passwordType, setPasswordType] = useState(false);
const TogglePassword = () => {
setPasswordType(!passwordType);
}
Axios.defaults.withCredentials = true;
const login = (e) => {
e.preventDefault()
Axios.post("http://localhost:3001/login" , {
email: emailLog,
password: passwordLog
}).then((response)=> {
if(response.data.message) {
setShowWarning(true)
} else{
setLoginStatus(response.data[0].email);
setShowSuccess(true);
navigate("/home");
}
})
}
useEffect(() => {
Axios.get('http://localhost:3001/login').then((response)=> {
if(response.data.loggedIn === true) {
setLoginStatus(response.data.email[0].email)
}
})
}, [])
return (
<div>
<Stack spacing={2} sx={{ width: '100%' }}>
<Snackbar open={showSuccess} autoHideDuration={6000} onClose={handleNotShowSuccess}>
<Alert onClose={handleNotShowSuccess} severity="success" sx={{ width: '100%' }}>
Logging in
</Alert>
</Snackbar>
<Snackbar open={showWarning} autoHideDuration={6000} onClose={handleNotShowWarning}>
<Alert onClose={handleNotShowWarning} severity="warning" sx={{ width: '100%' }}>
User does not exist
</Alert>
</Snackbar>
</Stack>
<div className="wrapper">
<div className="img">
<img src={userNoBg} alt="background profile"/>
</div>
<div className="login-content">
<div className='loginForm'>
<img src={user} alt="default avatar profile" />
<h2 className="title">Welcome</h2>
<div className="input-div one">
<div className="icon">
<i className="fas fa-user"><GrMail /></i>
</div>
<div className="div">
<input type="email" name="emailLogin" className="input" placeholder='Email' required
onChange={(e)=> {
setEmailLog(e.target.value)
}}/>
</div>
</div>
<div className="input-div pass">
<div onClick={TogglePassword} className="icon">
{passwordType ? <i className="fas fa-lock"><MdVisibility /></i> : <i className="fas fa-lock"><MdVisibilityOff /></i>}
</div>
<div className="div">
<input type={passwordType ? "text" : "password"} className="input" placeholder='Password' required
onChange={(e)=> {
setPasswordLog(e.target.value)
}}/>
</div>
</div>
Don't have an account ?
<button type='submit' className='btnLogin' onClick={login}>Login</button>
</div>
</div>
</div>
</div>
)
}
export default Login
Maybe I'm misunderstanding, but could you not wrap the navigate call in a setTimeout?
setLoginStatus(response.data[0].email);
setShowSuccess(true);
setTimeout(() => navigate("/home"), 3000);
Please help! I don't know why I'm getting this error. I can't find what I need to change :( The needed output in browser is perfectly fine. But I am getting this error. I'm not used to list and keys on react. I have the latest versions of React and Nodejs and the packages needed
Homescreen.js:
import React, { useState, useEffect } from 'react'
import axios from 'axios';
import Room from '../components/Room';
import Loader from '../components/Loader';
import Error from '../components/Error';
function Homescreen() {
let [rooms, setrooms] = useState([]);
const [loading, setloading] = useState();
const [error, seterror] = useState();
useEffect(() => {
async function getResults() {
try {
seterror(false);
setloading(true);
const data = (await axios('/api/rooms/getallrooms')).data;
setrooms(data);
setloading(false);
} catch (e) {
seterror(true);
setloading(false);
}
}
getResults();
}, []);
return (
<div className='container'>
<div className='row justify-content-center mt-5'>
{loading ? (
<Loader />
) : rooms.length > 1 ? (
rooms.map(room => {
return <div className="col-md-9 mt-3">
<Room room={room} />
</div>;
})
) : (
<Error />
)}
</div>
</div>
)
}
export default Homescreen;
//<h1>{room.name}</h1>
and my Room.js:
import React, { useState } from "react";
import { Modal, Button, Carousel } from 'react-bootstrap'
import { First } from "react-bootstrap/esm/PageItem";
import { Link } from 'react-router-dom'
function Room({ room }) {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
< div className="row bs" >
<div className="col-md-4">
<img src={room.imageurls[0]} className="smallimg" />
</div>
<div className="col-md-7">
<h1>{room.name}</h1>
<b>
{" "}
<p>Max Count : {room.maxcount}</p>
<p>Phone Number : {room.phonenumber}</p>
<p>Type : {room.type}</p>
</b>
<div style={{ float: "right" }}>
<Link to={`/book/${room._id}`}>
<button className="btn btn-primary m-5">Book Now!</button>
</Link>
<button className="btn btn-primary" onClick={handleShow}>View Details</button>
</div>
</div>
<Modal show={show} onHide={handleClose} size='lg'>
<Modal.Header>
<Modal.Title>{room.name}</Modal.Title>
</Modal.Header>
<Modal.Body>
<Carousel prevLabel='' nextLabel=''>
{room.imageurls.map(url => {
return <Carousel.Item>
<img
className="d-block w-100 bigimg"
src={url}
/>
</Carousel.Item>
})}
</Carousel>
<p>{room.description}</p>
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
</Modal.Footer>
</Modal>
</div>
);
}
export default Room;
Browser Console Error:
You have to give the first element in a map function a key:
rooms.map((room, index) => {
return (
<div key={index} className="col-md-9 mt-3">
<Room room={room} />
</div>
);
});
I already have the condition, but i need to set the state, if i setColor on the if method, give me error- Too many re-renders. React limits the number of renders to prevent an infinite loop.
State:
const [color, setColor] = useState();
Map:
{data.map((doc) => {
let verificacao = "";
if (doc.status === "Não Necessário") {
verificacao = "Proxima Verificação:";
setColor(true)
} else if (doc.status === "Verificado e Conforme") {
verificacao = "Data:";
setColor(false)
} else {
console.log("ERRO");
}
return (
The span i want to change the color:
<div className="row">
<div className="pontos">
<span className={color ? "red" : "green"}>
{doc.status}
</span>
<span className="data-status">{verificacao}</span>
{JSON.stringify(
doc.dateVerificado
.toDate()
.toISOString()
.replace(/T.*/, "")
.split("-")
.reverse()
.join("-")
)}
</div>
</div>
Full Code:
import React, { useEffect, useState } from "react";
import { Button } from "react-bootstrap";
import ManutencaoDataService from
"../../Services/ManutecaoDataService";
import "./ManutencaoInfo.css";
const ManutencaoInfo = ({ getDataId }) => {
const [data, setData] = useState([]);
const [color, setColor] = useState();
useEffect(() => {
getData();
return () => {
setData([]);
};
}, []);
const getData = async () => {
const data = await ManutencaoDataService.getAllData();
console.log(data.docs);
setData(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })));
};
const deleteHandler = async (id) => {
await ManutencaoDataService.deleteData(id);
getData();
};
return (
<>
<div className=" container mb-2">
<Button variant="dark edit" onClick={getData}>
Atualizar Lista
</Button>
</div>
{/* <pre>{JSON.stringify(books, undefined, 2)}</pre>} */}
{data.map((doc) => {
let verificacao = "";
if (doc.status === "Não Necessário") {
verificacao = "Proxima Verificação:";
setColor(true)
} else if (doc.status === "Verificado e Conforme") {
verificacao = "Data:";
setColor(false)
} else {
console.log("ERRO");
}
return (
<div key={doc.id} className="container-principal">
<div className="container">
<div className="row relatorio">
<div className="col">
<div className="departamento">
<h3>{doc.departamentos}</h3>
</div>
</div>
</div>
<div className="row detalhes">
<div className="col">
<div className="row">
<div className="pontos">
<span className="identificacao">Equipamento:
</span>
{doc.equipamentos}
</div>
</div>
<div className="row">
<div className="pontos">
<span className="identificacao">Responsável:
</span>
{doc.responsaveis}
</div>
</div>
<div className="row">
<div className="pontos">
<span className="codigo">{doc.codigos.codigo}
</span>
<span className="tipo">{doc.tipo}</span>
</div>
</div>
</div>
<div className="col ">
<div className="row">
<div className="pontos">
<span className="identificacao">Data Manutenção:
</span>
{JSON.stringify(
doc.dateManutencao
.toDate()
.toISOString()
.replace(/T.*/, "")
.split("-")
.reverse()
.join("-")
)}
</div>
</div>
<div className="row">
<div className="pontos">
<span className={color ? "red" : "green"}>
{doc.status}
</span>
<span className="data-status">{verificacao}</span>
{JSON.stringify(
doc.dateVerificado
.toDate()
.toISOString()
.replace(/T.*/, "")
.split("-")
.reverse()
.join("-")
)}
</div>
</div>
<div className="row">
<div className="pontos">{doc.codigos.observacoes}
</div>
</div>
</div>
</div>
<div className="row botoes">
<div className="col">
<span className="botao-editar">
<Button
variant="secondary"
className="edit"
onClick={(e) => getDataId(doc.id)}
>
Editar
</Button>
</span>
<span className="botao-apagar">
<Button
variant="danger"
className="delete"
onClick={(e) => deleteHandler(doc.id)}
>
Apagar
</Button>
</span>
</div>
</div>
</div>
</div>
);
})}
</>
);
};
export default ManutencaoInfo;
Instead of using state, I would recommend using doc's status property for using the correct CSS class like this:
<span className={doc.status === "Não Necessário" ? "red" : "green"}>
{doc.status}
</span>
import React, { useEffect, useState } from "react";
import { Button } from "react-bootstrap";
import ManutencaoDataService from
"../../Services/ManutecaoDataService";
import "./ManutencaoInfo.css";
import classNames from 'classnames';
const ManutencaoInfo = ({ getDataId }) => {
const [data, setData] = useState([]);
useEffect(() => {
getData();
}, []);
const getData = async () => {
const data = await ManutencaoDataService.getAllData();
console.log(data.docs);
setData(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })));
}
return (
<>
...
{data.map((doc) => {
return (
<div key={doc.id} className="container-principal">
<div className="container">
...
<div className="row detalhes">
...
<div className="col ">
...
<div className="row">
<div className="pontos">
<span className={classNames({red: doc.status === "Não Necessário", green:doc.status === "Verificado e Conforme" })}>
{doc.status}
</span>
<span className="data-status">{
doc.status === "Não Necessário" ? "Proxima Verificação:" : doc.status === "Verificado e Conforme" ? "Data:" :""
}</span>
....
</div>
</div>
....
</div>
</div>
...
</div>
</div>
);
})}
</>
);
};
export default ManutencaoInfo;
create a new component which renders inside the map function, it will be better to maintain
I think you are overcomplicating it with introducing state variable.
You can just use local variable in your function like this:
// Remove this state
// const [color, setColor] = useState();
{data.map((doc) => {
let verificacao = "";
let color; // add this var
if (doc.status === "Não Necessário") {
verificacao = "Proxima Verificação:";
color = 'red' // changed
} else if (doc.status === "Verificado e Conforme") {
verificacao = "Data:";
color = 'green' // changed
} else {
console.log("ERRO");
}
return (
// ...
<span className={color}> {/* changed */}
{doc.status}
</span>
// ...
)
Currently I have a component that is loaded when I call my API. This content has a CitizenshipType field that separates the items from each other. I have 2 buttons on top which I want to use to filter my data. 1 button is called Europe which should bring out all the content where CitizenshipType=Europe, etc. Currently I have all my data showing without any filtering. Here is my code:
Citizenship Page:
export default function Citizenship({ items, citi }) {
return (
<>
<div>
<div onClick=//SomeFunction>
CARRIBEAN
</div>
<div onClick=//SomeFunction>
EUROPE
</div>
</div>
<div>
<div onClick=//SomeFunction>
OTHER PROGRAMS
</div>
</div>
<div>
{items &&
items.map((item) => (
<div style={{ padding: "40px" }}>
<div class="citizen-item" key={item.id}>
<div className="container6">
<img
src={`http://localhost:1337${item.Thumbnail.url}`}
/>
<div>
{item.Title}
</div>
<div>
Access to {item.CountriesAccessible} countries
</div>
<div>
<button class="findButton">FIND OUT MORE</button>
</div>
</div>
</div>
</div>
))}
{citi &&
citi.map((test) => (
<div style={{ padding: "40px" }}>
<div class="citizen-item" key={test.id}>
<div className="container6">
<img
src={`http://localhost:1337${test.Thumbnail.url}`}
/>
<div>
{test.Title}
</div>
<div>
Access to {test.CountriesAccessible} countries
</div>
<div>
<button class="findButton">FIND OUT MORE</button>
</div>
</div>
</div>
</div>
))}
</>
);
}
Home Page where I am calling the APIs:
export default function Home({ items, citi }) {
return (
<div>
<Benefits />
<Citizenship items={items} citi={citi} />
<Video />
</div>
);
}
export async function getStaticProps() {
const CitizenshipEUres = await fetch(
"http://localhost:1337/citizenships?_limit=5&CitizenshipType=Europe"
);
const CitizenshipCAres = await fetch(
"http://localhost:1337/citizenships?_limit=5&CitizenshipType=Caribbien"
);
const items = await CitizenshipEUres.json();
const citi = await CitizenshipCAres.json();
return {
props: { items, citi },
};
}
you toggle them with states:
import React, { useState } from 'react'
export const TestComponent = () => {
const [carribeanIsShowing, setShowCarribean] = useState(false)
const [europeIsShowing, setShowEurope] = useState(false)
const toggleCarribean = () => {
if (!carribeanIsShowing) {
if(europeIsShowing) {
setShowEurope(false)
}
setShowCarribean(!carribeanIsShowing)
} else {
return
}
}
const toggleEurope = () => {
if (!europeIsShowing) {
if(carribeanIsShowing) {
setShowCarribean(false)
}
setShowEurope(!europeIsShowing)
} else {
return
}
}
return (
<div>
<button onClick={() => toggleCarribean()}>
CARRIBEAN
</button>
<button onClick={() => toggleEurope()}>
EUROPE
</button>
{europeIsShowing && <div>Europe</div>}
{carribeanIsShowing && <div>carribean</div>}
</div>
)
}
Create a new variable where you store the current CitizenshipType, with a default value of 'Europe'.
const [currentCitizenshipType, setCurrentCitizenshipType] = useState(
"Europe"
);
You change your onClick event
<div onClick={() => setCurrentCitizenshipType('Europe')}>
EUROPE
</div>
And finally add a filter statment to your items.map call:
{
items
.filter((item) => item.citizenshipType === currentCitizenshipType)
.map((item)
...}
I have developed a simple todo app using react-beautiful-dnd. I am able to retrieve data from the database and display it in the list. However, when I try to drag and rearrange the order, the reordered array is getting printed in the console (I tried testing using console.log), however the new reorderd array is not getting displayed in the interface. I am very new to this MERN stack, therefore I am unable to find the reason for this error.
I have attached screenshots of the output before and after dragging an element, and also the console log output.
before drag-and-drop
after drag and drop
console-log array order before drag and drop
console-log reordered array
The code :
function ProjectsDashboard() {
useEffect(() => {
preload();
}, []);
const [state, setState] = useState([]);
const[stage,setStage] = useState([]);
const [todo, setTodo] = useState("");
const [loading, setLoading] = useState(false);
const preload = async () => {
setLoading(true);
try {
const res = await axios.get("/stages");
setState(res.data);
console.log(state, "STATE")
console.log(res.data,"DATA")
setLoading(false);
} catch (error) {
alert("Couldn't find any Todos! ");
setLoading(false);
}
};
var formattedArray =state.stage && state.stage.map(item => Object.keys(item).map(i => item[i]));
console.log(formattedArray, "FORMATTED ARRAY")
// setState( formattedArray);
// console.log(state, "STATE")
const lists = () => (
<div className="row">
<div className="col-sm-12 col-md-4 offset-md-2 col-lg-4 offset-lg-2 border border-danger p-4">
<h3 className="text-center mb-4">Draggable List</h3>
<DragDropContext onDragEnd={handleDragEnd}>
<Droppable droppableId="todos">
{(provided) => (
<ul
className="list-group"
{...provided.droppableProps}
ref={provided.innerRef}
>
{console.log("HELLO-out")}
{state.stage && state.stage.map((item, index) => (
<Draggable
key={item._id}
draggableId={item._id + ""}
index={index}
>
{(provided) => (
<li
className="list-group-item d-flex justify-content-between align-items-start align-items-center"
{...provided.draggableProps}
{...provided.dragHandleProps}
ref={provided.innerRef}
>
{console.log("HELLO")}
<div className="ms-2 me-auto">
<span className="font-weight-bold">{item.stageName}</span>
</div>
<span>
{/* <i className="bi bi-trash text-danger" /> */}
<button
className="btn btn-sm"
onClick={(e) => {
e.preventDefault();
handleDelete(item._id, index);
}}
>
<i className="bi bi-trash text-danger" />
</button>
</span>
</li>
)}
</Draggable>
))}
{provided.placeholder}
</ul>
)}
</Droppable>
</DragDropContext>
</div>
<div
className="col-sm-12 col-md-4 col-lg-4 border border-info p-4"
style={{ marginLeft: "10px" }}
>
<h3 className="text-center mb-4">NON-Draggable List</h3>
<ul className="list-group">
{state.stage && state.stage.map(
(item, index) =>
item.selected && (
<li className="list-group-item" key={index}>
{item.title}
</li>
)
)}
</ul>
</div>
</div>
);
const handleDragEnd = (result) => {
console.log(result.destination,"DESTI");
if (!result.destination) return;
const items = Array.from(state.stage);
console.log(items,"ITEMS-DRAG")
console.log(result.source.index,"SOURCE INDEX")
console.log(result.destination.index,"DESTINATION INDEX")
const [recordedItem] = items.splice(result.source.index, 1);
console.log(recordedItem,"RECORDED")
items.splice(result.destination.index, 0, recordedItem);
console.log(items, "NEW ITEM")
setState(items);
console.log(state, "STATE");
};
const handleDelete = async (id, index) => {
try {
await axios.delete(`/api/todo/${id}`);
// preload();
const temp = Array.from(state);
temp.splice(index, 1);
setState(temp);
} catch (error) {
if (`Error! ${error.response.data.err}`) {
alert(error.response.data.err);
} else {
alert(`Error ${error.response.status}: ${error.response.statusText}`);
}
}
};
const addNewTodoForm = () => (
<div className="row">
<div className="col-md-8 offset-md-2 mb-4 form-group">
<label htmlFor="newtodo">Add a New Todo Item</label>
<input
type="text"
className="form-control"
name="newtodo"
id="newtodo"
value={todo}
placeholder="Add New Todo"
required
onChange={handleChange}
/>
<button
className="btn btn-block btn-outline-primary mt-2"
onClick={handleSubmit}
>
Submit
</button>
</div>
</div>
);
const handleChange = (e) => {
e.preventDefault();
setTodo(e.target.value);
};
const handleSubmit = async (e) => {
e.preventDefault();
if (todo === "" || todo === null) {
alert(
"To add a New Todo item, please fill out the 'Add New Todo' field."
);
return;
}
const temp = {
title: todo,
};
try {
const res = await axios.post("/api/todo", temp);
setTodo("");
const tmp = Array.from(state);
tmp.push(res.data);
setState(tmp);
// preload();
} catch (error) {
if (error.response.data && error.response.data.err) {
alert(`Error! ${error.response.data.err}`);
} else {
console.log(error);
alert(`Error ${error.response.status}: ${error.response.statusText}`);
}
}
};
return (
<>
<div className="container">
<h1 className="text-center m-4 font-weight-bold text-uppercase">
DRAG TO DO{" "}
<span className="text-lowercase font-weight-normal">V1.0.1</span>
</h1>
{/* {addNewTodoForm()}*/}
{ lists() }
</div>
</>
);
};
export default ProjectsDashboard;