I leverage the npm package react-modal (https://www.npmjs.com/package/react-modal).
I want to submit a form that resides within the modal.
For some reason when clicking on 'Abschicken', nothing happens. The handleSubmitfunction is never triggered as I do not see any console logs.
What do I miss here?
import { useState, useRef } from "react";
import Modal from "react-modal";
import LogoHori from "../../../public/images/logo_hori.png";
import Image from "next/image";
const customStyles = {
content: {
top: "50%",
left: "50%",
right: "auto",
bottom: "auto",
marginRight: "-50%",
transform: "translate(-50%, -50%)",
position: "absolute",
},
overlay: { zIndex: 1000 },
};
Modal.setAppElement("#__next");
// Make sure to bind modal to your appElement (https://reactcommunity.org/react-modal/accessibility/)
const ContactModal = ({ buttonStyles }) => {
const [modalIsOpen, setIsOpen] = useState(false);
const [isValidEmail, setIsValidEmail] = useState(true);
const [successfulSubmission, setSuccessfulSubmission] = useState("");
const lastNameInputElement = useRef();
const firstNameInputElement = useRef();
const emailInputElement = useRef();
const messageInputElement = useRef();
const validate = (email) => {
const expression =
/(?!.*\.{2})^([a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+(\.[a-z\d!#$%&'*+\-\/=?^_`{|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)*|"((([\t]*\r\n)?[\t]+)?([\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*(([\t]*\r\n)?[\t]+)?")#(([a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\d\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.)+([a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF][a-z\d\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]*[a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])\.?$/i;
return expression.test(String(email).toLowerCase());
};
function openModal() {
setIsOpen(true);
}
function afterOpenModal() {
// references are now sync'd and can be accessed.
}
function closeModal() {
setIsOpen(false);
}
const handleSubmit = async (event) => {
console.log("clicked");
event.preventDefault();
const data = {
lastName: lastNameInputElement.current?.value,
firstName: firstNameInputElement.current?.value,
email: emailInputElement.current?.value,
message: messageInputElement.current?.value,
};
if (!validate(data.email)) {
setIsValidEmail(false);
return;
}
setIsValidEmail(true);
console.log(data);
const requestOptions = {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify(data),
};
try {
const result = await fetch(
"https://someEndpoint",
requestOptions
);
if (result.status == 200) {
setSuccessfulSubmission(true);
setTimeout(closeModal, 5000);
} else {
throw new Error();
}
} catch {
console.log(error);
setSuccessfulSubmission(false);
}
};
return (
<div>
<button className={buttonStyles} onClick={openModal}>
Anfrage
</button>
<Modal
isOpen={modalIsOpen}
onAfterOpen={afterOpenModal}
onRequestClose={closeModal}
style={customStyles}
contentLabel="Nido Surf"
>
<div className="w-[300px] md:w-[600px]">
<Image src={LogoHori} alt="nido-surf-logo" width={300} />
<form action="Post" onSubmit={handleSubmit} className="mt-5 flex flex-col justify-between">
<label htmlFor="name" className="font-bold mb-2">
Nachname
</label>
<input
ref={lastNameInputElement}
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 focus:outline-none focus:shadow-outline"
id="name"
type="text"
placeholder="Nachname"
/>
<label htmlFor="firstname" className="font-bold my-2">
Vorname
</label>
<input
ref={firstNameInputElement}
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 focus:outline-none focus:shadow-outline"
id="firstname"
type="text"
placeholder="Vorname"
/>
<label htmlFor="email" className="font-bold my-2">
Email-Adresse
</label>
<input
ref={emailInputElement}
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 focus:outline-none focus:shadow-outline"
id="email"
type="text"
placeholder="Email-Adresse"
/>
{!isValidEmail && (
<p className="text-secondary-red-200">
Deine Email-Adresse ist ungültig!
</p>
)}
<label htmlFor="message" className="font-bold my-2">
Nachricht
</label>
<textarea
ref={messageInputElement}
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 focus:outline-none focus:shadow-outline"
name="message"
id="message"
cols="30"
rows="10"
></textarea>
</form>
<div className="mt-5 flex gap-x-4 justify-center items-center">
<button
type="submit"
className="w-full text-white rounded-md py-4 hover:bg-secondary-green-300 bg-secondary-green-400"
>
Senden
</button>
<button
className="w-full text-white rounded-md py-4 hover:bg-secondary-red-100 bg-secondary-red-300"
onClick={closeModal}
>
Abbrechen
</button>
</div>
</div>
</Modal>
</div>
);
};
export default ContactModal;
It's not triggering the submit event because your button is not inside the form. Move the below div above the closing tag of form. Also, notice this type="button" on the second button:
<div className="mt-5 flex gap-x-4 justify-center items-center">
<button
type="submit"
className="w-full text-white rounded-md py-4 hover:bg-secondary-green-300 bg-secondary-green-400"
>
Senden
</button>
<button
className="w-full text-white rounded-md py-4 hover:bg-secondary-red-100 bg-secondary-red-300"
onClick={closeModal}
type="button"
>
Abbrechen
</button>
</div>
Related
I want to set the fetched data from firestore as initial value of useState but it gives me undefined value because I want to update user profile and I don't know the user edits or updates which property because I want to keep the other properties of the user the same, only change the edited one.
I've tried this code, but it gives me this error:
Uncaught (in promise) FirebaseError: Function updateDoc() called with invalid data. Unsupported field value: undefined (found in field surname in document users/DQjpLaKYVgVuH9TeqNomIEyuMJB2)
import React, { useState, useEffect } from 'react';
import { useAuthState } from 'react-firebase-hooks/auth';
import { doc, onSnapshot, updateDoc } from "firebase/firestore";
import { auth, db } from '../../firebase';
export default function Form({ setEditForm }) {
const [user, setUser] = useState([]);
const [currentUser] = useAuthState(auth);
// fetching user information from firestore
useEffect(() => {
const getUser = async () => {
const docRef = await doc(db, 'users', currentUser.uid)
try {
await onSnapshot(docRef, (doc) => {
setUser({
...doc.data(), id: doc.id
})
})
} catch (e) {
console.log(e)
}
}
getUser()
}, [])
const [name, setName] = useState(user.firstName);
const [surname, setSurname] = useState(user.surname);
const [biography, setBiography] = useState(user.biography);
const [location, setLocation] = useState(user.location);
// updating user's profile
const updateProfile = async (e) => {
e.preventDefault();
const docRef = doc(db, 'users', currentUser.uid);
await updateDoc(docRef, {
firstName: name,
surname: surname,
biography: biography,
location: location
})
}
console.log(user)
return (
<form
onSubmit={updateProfile}
className="flex flex-col w-4/6 lg:w-3/6"
>
<div className="lg:flex lg:flex-row lg:justify-between lg:gap-6">
<div className="lg:flex lg:flex-col lg:w-1/2">
<h2 className="text-left text-[#4699C2] font-bold py-2">Name: </h2>
<div className="border border-gray-300 rounded-md">
<input
type="text"
placeholder={name}
value={name}
onChange={(e) => setName(e.target.value)}
className="w-full py-2 px-4 opacity-50 focus:opacity-100"
/>
</div>
</div>
<div className="lg:flex lg:flex-col lg:w-1/2">
<h2 className="text-left text-[#4699C2] font-bold py-2">Surname: </h2>
<div className="border border-gray-300 rounded-md">
<input
type="text"
placeholder={surname}
value={surname}
onChange={(e) => setSurname(e.target.value)}
className="opacity-50 px-4 focus:opacity-100 w-full py-2"
/>
</div>
</div>
</div>
<h2 className="text-left text-[#4699C2] font-bold py-2">Biograhpy: </h2>
<div className="border border-gray-300 rounded-md">
<textarea
onChange={(e) => setBiography(e.target.value)}
className="opacity-50 px-4 focus:opacity-100 w-full py-4"
>
{biography}
</textarea>
</div>
<h2 className="text-left text-[#4699C2] font-bold py-2">Location: </h2>
<div className="border border-gray-300 rounded-md">
<input
placeholder={location}
value={location}
onChange={(e) => setLocation(e.target.value)}
className="opacity-50 px-4 focus:opacity-100 w-full py-2"
/>
</div>
<div className="flex flex-row justify-center py-4">
<input
type="submit"
value="SAVE"
className="bg-[#4699C2] text-white fong-bold w-24 py-3 rounded-full mx-4 font-bold hover:bg-[#026FC2] hover:shadow-lg focus:bg-[#026FC2] focus:shadow-lg focus:outline-none focus:ring-0 active:bg-[#026FC2] active:shadow-lg transition duration-150 ease-in-out"
/>
<input
onClick={() => {
setEditForm(false);
}}
type="reset"
value="CANCEL"
className="bg-[#4699C2] cursor-pointer lg:bg-white hover:bg-[#026FC2] hover:text-white hover:shadow-lg focus:bg-[#026FC2] focus:shadow-lg focus:outline-none focus:ring-0 focus:text-white active:bg-[#026FC2] active:shadow-lg transition duration-150 ease-in-out text-white lg:text-[#4699C2] lg:border lg:border-[#4699C2] fong-bold w-24 py-3 rounded-full font-bold"
/>
</div>
</form>
);
}
Answering this as community wiki, As suggested by #yograjtandel, instead of storing the response in one single state, first declare all the states like name, biography, surname, etc... to null. then in useState set all the states ex. setName(doc.data().Name).
I am trying to open a hosted page from a payment gateway provider. 2 parameters are required by the page.
I have successfully created the parameters and saved them in my database but when I try to pass the data to my script it does not pass the value of the variable in blade.php view file.
blade.php view:
<?php
namespace App\Http\Livewire\Open;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
use Livewire\Component;
use App\Models\OpenTransactions;
class NewDeposit extends Component
{
public $op_id;
public $op_amount;
public $op_udf;
public $op_attempts;
public $op_sub_accounts_id;
public $op_entity;
public $op_status;
public $op_contact_number;
public $op_email_id;
public $op_mtx;
public $op_currency;
public $op_customer_id;
public $apiKey;
public $mydata;
public function mount(Request $request){
$this->op_mtx = Str::uuid()->toString();
$this->op_currency = "INR";
$this->op_amount =$request->get('op_amount');
$this->op_email_id =$request->get('op_email_id');
}
public function render()
{
return view('livewire.open.new-deposit');
}
public function createNewDepositOpen(Request $request)
{
$apiKey = config('app.open_key');
$response = Http::withHeaders([
'Authorization' => 'Bearer ' . $apiKey,
'accept' => 'application/json',
'content-type' => 'application/json',
])->post('https://sandbox-icp-api.bankopen.co/api/payment_token',[
'amount' => $this->op_amount,
'mtx' => $this->op_mtx,
'currency' => $this->op_currency,
'udf' => $this->op_udf,
'contact_number' => $this->op_contact_number,
'email_id' => $this->op_email_id
]);
$mydata = json_decode($response->getBody()->getContents(), true);
//dd($mydata);
$newpayload = OpenTransactions::create([
'op_mtx' => $mydata['mtx'],
'op_amount' => $mydata['amount'],
'op_udf' => $mydata['udf'] ?? null,
'op_contact_number' => Arr::get($mydata, 'customer.contact_number'),
'op_email_id' => Arr::get($mydata, 'customer.email_id'),
'op_currency' => $mydata['currency'],
'op_id' => $mydata['id'],
'op_attempts' => $mydata['attempts'],
'op_sub_accounts_id' => $mydata['sub_accounts_id'],
'op_entity' => $mydata['entity'],
'op_status' => $mydata['status'],
'op_customer_id' => Arr::get($mydata, 'customer.id')
]);
//dd($newpayload);
$this->emit('token_create');
}
}
Livewire Component:
<div>
{{-- Care about people's approval and you will be their prisoner. --}}
<div class="flex min-h-full items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
<div class="w-full max-w-md space-y-8">
<div>
<img
class="mx-auto h-12 w-auto"
src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=600"
alt="Your Company"
/>
<h2
class="mt-6 text-center text-3xl font-bold tracking-tight text-gray-900"
>
Deposit
</h2>
<p class="mt-2 text-center text-sm text-gray-600">
<a
href="#"
class="font-medium text-indigo-600 hover:text-indigo-500"
></a>
</p>
</div>
<form
wire:submit.prevent="createNewDepositOpen"
class="mt-8 space-y-6"
method="POST"
>
<input type="hidden" name="remember" value="true" />
<div class="-space-y-px rounded-md shadow-sm">
<div>
<label for="op_email_id" class="sr-only">Email address</label>
<input
wire:model="op_email_id"
id="op_email_id"
name="op_email_id"
type="email"
autocomplete="email"
required
class="relative block w-full appearance-none rounded-none rounded-t-md border border-gray-300 px-3 py-2 text-gray-900 placeholder-gray-500 focus:z-10 focus:border-indigo-500 focus:outline-none focus:ring-indigo-500 sm:text-sm"
placeholder="Email address"
/>
</div>
<div class="mt-2">
<label for="op_contact_number" class="sr-only">Mobile Number</label>
<input
wire:model="op_contact_number"
id="op_contact_number"
name="op_contact_number"
type="tel"
pattern="^[6-9]\d{9}$"
required
class="relative block w-full appearance-none rounded-none rounded-b-md border border-gray-300 px-3 py-2 text-gray-900 placeholder-gray-500 focus:z-10 focus:border-indigo-500 focus:outline-none focus:ring-indigo-500 sm:text-sm"
placeholder="Enter 10 digit Mobile No."
/>
</div>
<div class="mt-2">
<label for="op_amount" class="sr-only">amount</label>
<input
wire:model="op_amount"
id="op_amount"
name="op_amount"
type="number"
required
class="relative block w-full appearance-none rounded-none rounded-b-md border border-gray-300 px-3 py-2 text-gray-900 placeholder-gray-500 focus:z-10 focus:border-indigo-500 focus:outline-none focus:ring-indigo-500 sm:text-sm"
placeholder="Amount"
/>
</div>
</div>
<div>
<button
type="submit"
class="group relative flex w-full justify-center rounded-md border border-transparent bg-indigo-600 py-2 px-4 text-sm font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
>
<span class="absolute inset-y-0 left-0 flex items-center pl-3">
<!-- Heroicon name: mini/lock-closed -->
</span>
Next
</button>
</div>
</form>
</div>
</div>
<script type="text/javascript">
window.onload = function () {
Livewire.on("token_create", () => {
//You can bind the Layer.checkout initialization script to a button click event.
//Binding inside a click event open Layer payment page on click of a button
Layer.checkout(
{
token: "#js($op_id)",
accesskey: "#js($apiKey)",
theme: {
logo: "https://open-logo.png",
color: "#3d9080",
error_color: "#ff2b2b",
},
},
function (response) {
if (response.status == "captured") {
// response.payment_token_id
// response.payment_id
window.location.href = "success_redirect_url"
} else if (response.status == "created") {
} else if (response.status == "pending") {
} else if (response.status == "failed") {
window.location.href = "failure_redirect_url"
} else if (response.status == "cancelled") {
window.location.href = "cancel_redirect_url"
}
},
function (err) {
//integration errors
}
)
})
}
</script>
</div>
I am pretty sure you can just pass it like any blade variable:
token: "{{$op_id}}",
accesskey: "{{$apiKey}}" ,
theme: {
logo : "https://open-logo.png",
color: "#3d9080",
error_color : "#ff2b2b"
I'm trying to return a few functions in react but I'm unable to perform as I wanted.
return (
loadingMessage(),
errorMessage(),
loginForm(),
performRedirect()
)
}
I want to return my functions as above but when try this my app directly calls the last function performRedirect(). I don't know whether am I running this correctly or not.
please find the whole code below.
import React, { useState } from "react";
import { Link, Navigate } from "react-router-dom";
import {signin, authenticate, isAutheticated} from "../auth/helper/index"
const Login = () => {
const [values, setValues] = useState({
username: "",
password: "",
error: "",
loading: false,
didRedirect: false,
});
const {username, password, error, loading, didRedirect} = values;
const {user} = isAutheticated();
const handleChange = name => event => {
setValues({ ...values, error: false, [name]: event.target.value });
};
const onSubmit = event => {
event.preventDefault();
setValues({ ...values, error: false, loading: true });
signin({ username, password })
.then(data => {
if (data.error) {
setValues({ ...values, error: data.error, loading: false });
} else {
authenticate(data, () => {
setValues({
...values,
didRedirect: true
});
});
}
})
.catch(console.log("signin request failed", error, user));
};
const performRedirect = () => {
//TODO: do a redirect here
if (didRedirect) {
if (user && user.role === 1) {
return <p>redirect to admin</p>;
} else {
return <p>redirect to user dashboard</p>;
}
}
if (isAutheticated()) {
return <Navigate to="/" />;
}
};
const loadingMessage = () => {
return (
loading && (
<div className="alert alert-info">
<h2>Loading...</h2>
</div>
)
);
};
const errorMessage = () => {
return (
<div className="row">
<div className="col-md-6 offset-sm-3 text-left">
<div
className="alert alert-danger"
style={{ display: error ? "" : "none" }}
>
{error}
</div>
</div>
</div>
);
};
const loginForm = () => {
return (
<div className='bg-gray-200'>
<div className="flex items-center h-screen w-full">
<div className="w-80 bg-white rounded-2xl p-6 m-0 md:max-w-sm md:mx-auto border border-slate-300 shadow-sm">
<div align='center' className='mt-3 mb-3 items-center content-center'> <img src={require('./../data/logo.jpg')} width="120px"/></div>
<span className="block w-full text-xl uppercase font-bold mb-4 text-center">Sign in to EMS
</span>
<form className="mb-0" action="/" method="post">
<div className="mb-4 md:w-full">
<label for="email" className="block text-xs mb-1 text-left text-gray-500">Username</label>
<input onChange={handleChange("username")} className="bg-gray-100 w-full border rounded-2xl px-4 py-2 outline-none focus:shadow-outline text-left text-xs" type="text" name="username" id="username" placeholder="Username" value={username}/>
</div>
<div className="mb-6 md:w-full relative">
<div className='flex w-full'>
<label for="password" className="block text-xs mb-1 text-center text-gray-500">Password</label>
<a className="text-xs text-right text-[#58a6ff] absolute right-0" href="/login">Forgot password?</a></div>
<input onChange={handleChange("password")} className="bg-gray-100 w-full border rounded-2xl px-4 py-2 outline-none focus:shadow-outline text-left text-xs" type="password" name="password" id="password" placeholder="Password" value={password}/>
</div>
<div className="mb-6 md:w-full relative">
<div className='flex w-full'>
<p className="block text-xs mb-1 text-center text-gray-500">{JSON.stringify(values)}</p>
</div>
<button className="bg-green-500 hover:bg-green-700 shadow-lg text-white uppercase text-sm font-semibold px-4 py-2 rounded-2xl text-center items-center w-full" onClick={onSubmit}>Login</button>
</form>
</div>
</div>
</div>
);
};
return (
loadingMessage(),
errorMessage(),
loginForm(),
performRedirect()
)
}
export default Login
Please someone help me on this?
You can modify your return statement with an array value [] like below
return [
loadingMessage(),
errorMessage(),
loginForm(),
performRedirect()
]
Another way, you can render those JSX functions by {} and wrap them into <React.Fragment></React.Fragment> (Or simpler version <></>)
return (
<React.Fragment>
{loadingMessage()}
{errorMessage()}
{loginForm()}
{performRedirect()}
</React.Fragment>)
like this:
return (
<>
{loadingMessage()}
{errorMessage()}
{loginForm()}
{performRedirect()}
</>
)
I have built a checkout page where on clicking the pay button a payment page should render. But due to some issue I can't find why?
The checkout page:
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
import Link from 'next/link'
import React, { useState, useEffect } from 'react'
import Head from 'next/head'
import Script from 'next/script'
import { AiFillMinusCircle, AiFillPlusCircle } from 'react-icons/ai'
import { BsFillBagCheckFill } from 'react-icons/bs'
import { ToastContainer, toast } from 'react-toastify'
import 'react-toastify/dist/ReactToastify.css';
const Checkout = ({ cart, clearCart, subTotal, addToCart, removeFromCart }) => {
const [name, setName] = useState('')
const [email, setEmail] = useState('')
const [address, setAddress] = useState('')
const [phone, setPhone] = useState('')
const [pincode, setPincode] = useState('')
const [city, setCity] = useState('')
const [state, setState] = useState('')
const [disabled, setDisabled] = useState(true)
const [user, setUser] = useState({ value: null })
useEffect(() => {
const myuser = JSON.parse(localStorage.getItem('myuser'));
if (myuser && myuser.token) {
setUser(myuser)
setEmail(myuser.email)
fetchData(myuser.token)
}
}, [])
useEffect(() => {
if (name.length > 3 && email.length > 3 && address.length > 3 && phone.length > 3 && pincode.length > 3) {
setDisabled(false)
}
else {
setDisabled(true)
}
}, [name, email, address, phone, pincode])
const fetchData = async (token) => {
let data = { token: token }
let a = await fetch(`${process.env.NEXT_PUBLIC_HOST}/api/getuser`, {
method: 'POST', // or 'PUT'
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
let res = await a.json()
setName(res.name)
setAddress(res.address)
setPincode(res.pincode)
setPhone(res.phone)
getPinCode(res.pincode)
}
const getPinCode = async (pincode) => {
let url = 'https://api.postalpincode.in/pincode/' + pincode
let pins = await fetch(url, {
Method: 'GET'
})
let pinJson = await pins.json()
if (pinJson[0].Status == 'Success') {
setState(pinJson[0].PostOffice[0].State)
setCity(pinJson[0].PostOffice[0].District)
}
else {
setState('')
setCity('')
}
}
const handleChange = async (e) => {
if (e.target.name == 'name') {
setName(e.target.value)
}
else if (e.target.name == 'email') {
setEmail(e.target.value)
}
else if (e.target.name == 'address') {
setAddress(e.target.value)
}
else if (e.target.name == 'phone') {
setPhone(e.target.value)
}
else if (e.target.name == 'pincode') {
setPincode(e.target.value)
if (e.target.value.length == 6) {
getPinCode(e.target.value)
}
}
}
const initializeRazorpay = () => {
return new Promise((resolve) => {
const script = document.createElement("script");
script.src = "https://checkout.razorpay.com/v1/checkout.js";
console.log("intialzeRazorpay")
script.onload = () => {
resolve(true);
};
script.onerror = () => {
resolve(false);
};
document.body.appendChild(script);
});
};
const makePayment = async () => {
const res = await initializeRazorpay();
let oid = Math.floor(Math.random() * Date.now());
if (!res) {
alert("Your are offline.... Razorpay SDK Failed to load");
return;
}
const pdata = { cart, subTotal: subTotal, oid, email: email, name, address, pincode, phone, state, city };
let data = await fetch(`${process.env.NEXT_PUBLIC_HOST}/api/pretransaction`, {
method: 'POST', // or 'PUT'
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(pdata),
})
if (!data.success) {
toast.error(data.err, {
position: "top-center",
autoClose: 3000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
});
}
else {
var options = {
key: process.env.RAZORPAY_KEY, // Enter the Key ID generated from the Dashboard
name: "Pixelwear",
currency: "INR",
amount: data.amount,
order_id: data.id,
description: "Thank You for your test donation",
image: "/logo.png",
handler: function (response) {
// Validate payment at server - using webhooks is a better idea
alert(response.razorpay_payment_id)
alert(response.razorpay_order_id);
alert(response.razorpay_signature);
},
prefill: {
name: name,
email: email,
contact: phone,
},
};
const paymentObject = new window.Razorpay(options);
paymentObject.open();
}
};
return (
<>
<div className='container px-2 sm:m-auto'>
<ToastContainer
position="top-center"
autoClose={5000}
hideProgressBar={false}
newestOnTop={false}
closeOnClick
rtl={false}
pauseOnFocusLoss
draggable
pauseOnHover
/>
<Head><meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0" /></Head>
<h1 className='font-bold text-3xl my-8 text-center'>Checkout</h1>
<h2 className='font-semibold text-xl'>1. Delivery Details</h2>
<div className="mx-auto flex my-2">
<div className="px-2 w-1/2">
<div className="mb-4">
<label htmlFor="name" className="leading-7 text-sm text-gray-600">Name</label>
<input value={name} onChange={handleChange} type="text" id="name" name="name" className="w-full bg-white rounded border border-gray-300 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-200 text-base outline-none text-gray-700 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out" />
</div>
</div>
<div className="px-2 w-1/2">
<div className="mb-4">
<label htmlFor="email" className="leading-7 text-sm text-gray-600">Email</label>
{user && user.token ? <input value={user.email} type="email" id="email" name="email" className="w-full bg-white rounded border border-gray-300 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-200 text-base outline-none text-gray-700 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out" readOnly /> : <input value={email} onChange={handleChange} type="email" id="email" name="email" className="w-full bg-white rounded border border-gray-300 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-200 text-base outline-none text-gray-700 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out" />}
</div>
</div>
</div>
<div className="px-2 w-full">
<div className="mb-4">
<label htmlFor="address" className="leading-7 text-sm text-gray-600">Address</label>
<textarea onChange={handleChange} value={address} name="address" id="address" cols="30" rows="2" className="w-full bg-white rounded border border-gray-300 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-200 text-base outline-none text-gray-700 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out"></textarea>
</div>
</div>
<div className="mx-auto flex my-2">
<div className="px-2 w-1/2">
<div className="mb-4">
<label htmlFor="phone" className="leading-7 text-sm text-gray-600">Phone</label>
<input value={phone} onChange={handleChange} placeholder="Your 10 digit phone number" type="phone" id="phone" name="phone" className="w-full bg-white rounded border border-gray-300 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-200 text-base outline-none text-gray-700 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out" />
</div>
</div>
<div className="px-2 w-1/2">
<div className="mb-4">
<label htmlFor="pincode" className="leading-7 text-sm text-gray-600">Pincode</label>
<input value={pincode} onChange={handleChange} type="text" id="pincode" name="pincode" className="w-full bg-white rounded border border-gray-300 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-200 text-base outline-none text-gray-700 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out" />
</div>
</div>
</div>
<div className="mx-auto flex my-2">
<div className="px-2 w-1/2">
<div className="mb-4">
<label htmlFor="state" className="leading-7 text-sm text-gray-600">State</label>
<input onChange={handleChange} value={state} type="text" id="state" name="state" className="w-full bg-white rounded border border-gray-300 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-200 text-base outline-none text-gray-700 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out" />
</div>
</div>
<div className="px-2 w-1/2">
<div className="mb-4">
<label htmlFor="city" className="leading-7 text-sm text-gray-600">District</label>
<input onChange={handleChange} value={city} type="text" id="city" name="city" className="w-full bg-white rounded border border-gray-300 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-200 text-base outline-none text-gray-700 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out" />
</div>
</div>
</div>
<h2 className='font-semibold text-xl'>2. Review Cart Items & Pay</h2>
<div className="sideCart bg-blue-100 p-6 m-2">
<ol className='list-decimal font-semibold'>
{Object.keys(cart).length == 0 && <div className='my-4 font-semibold'>Your cart is Empty!</div>}
{Object.keys(cart).map((k) => {
return <li key={k}>
<div className="item flex my-5">
<div className='font-semibold'>{cart[k].name} ({cart[k].size}/{cart[k].variant})</div>
<div className='flex items-center justify-center w-1/3 font-semibold text-lg'>
<AiFillMinusCircle onClick={() => { removeFromCart(k, 1, cart[k].price, cart[k].name, cart[k].size, cart[k].variant, cart[k].category, cart[k].img) }} className='cursor-pointer text-blue-500' /><span className='mx-2 text-sm' >{cart[k].qty}</span>
<AiFillPlusCircle onClick={() => { addToCart(k, 1, cart[k].price, cart[k].name, cart[k].size, cart[k].variant, cart[k].category, cart[k].img) }} className='cursor-pointer text-blue-500' /></div>
</div>
</li>
})}
</ol>
<span className="font-bold">Subtotal: ₹{subTotal}</span>
</div>
<div className="mx-4">
<Link href={'/checkout'} ><button disabled={disabled} onClick={makePayment} className="disabled:bg-indigo-300 flex mr-2 text-white bg-indigo-500 border-0 py-2 px-2 focus:outline-none hover:bg-indigo-600 rounded text-sm"><BsFillBagCheckFill className='m-1' />Pay ₹{subTotal}</button></Link>
</div>
</div>
</>
)
}
export default Checkout
pretransaction page:
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
import Order from "../../models/Order"
import Product from "../../models/Product"
import connectDb from "../../middleware/mongoose"
require('dotenv').config()
const Razorpay = require("razorpay");
const shortid = require("shortid");
const handler = async (req, res) => {
if (req.method == 'POST') {
//Check if the pincode is serviceable
let url = 'https://api.postalpincode.in/pincode/' + req.body.pincode
let pins = await fetch(url, {
Method: 'GET'
})
let pinJson = await pins.json()
if (pinJson[0].Status != 'Success') {
res.status(200).json({ success: false, "error": "The pincode you have entered is not serviceable.", cartClear: false })
return
}
//Check if the cart is tampered
let product, sumTotal = 0;
let cart = req.body.cart;
if (req.body.subTotal <= 0) {
res.status(200).json({ success: false, "error": "Your Cart is empty. Please build your cart and try again!", cartClear: false })
return
}
for (let item in cart) {
product = await Product.findOne({ slug: item })
sumTotal += cart[item].price * cart[item].qty
//Check if the cart items are out of stock
if (product.availableQty < cart[item].qty) {
res.status(200).json({ success: false, "error": "Some items in your cart are out of stock.", cartClear: true })
return
}
if (product.price != cart[item].price) {
res.status(200).json({ success: false, "error": "price of some items in cart have changed", cartClear: true })
return
}
}
if (sumTotal != req.body.subTotal) {
res.status(200).json({ success: false, "error": "price of some items in cart have changed", cartClear: true })
return
}
//Check if the details are valid
if (req.body.phone.length !== 10 || !Number.isInteger(Number(req.body.phone))) {
res.status(200).json({ success: false, "error": "Please enter your 10 digit phone number", cartClear: false })
return
}
if (req.body.pincode.length !== 6 || !Number.isInteger(Number(req.body.pincode))) {
res.status(200).json({ success: false, "error": "Please enter your 6 digit pincode", cartClear: false })
return
}
const razorpay = new Razorpay({
key_id: process.env.RAZORPAY_KEY,
key_secret: process.env.RAZORPAY_SECRET,
});
const payment_capture = 1;
const amount = req.body.subTotal;
const currency = "INR";
const options = {
amount: (amount * 100).toString(),
currency,
receipt: shortid.generate(),
payment_capture,
};
try {
const response = await razorpay.orders.create(options);
// Initiate an order corresponding to the order id
let order = new Order({
email: req.body.email,
name: req.body.name,
phone: req.body.phone,
orderId: response.id,
address: req.body.address,
district: req.body.city,
state: req.body.state,
pincode: req.body.pincode,
amount: req.body.subTotal,
products: req.body.cart,
})
await order.save()
res.status(200).json({
success: true,
id: response.id,
currency: response.currency,
amount: response.amount,
});
return
} catch (err) {
console.log(err);
res.status(400).json({ success: false , err: err});
return
}
}
}
export default connectDb(handler);
Everything is working fine, but when I click on the pay button the razorpay page is not rendering.
And in the console it is showing one error, Invalid HMR message: {"event":"serverOnlyChanges","pages":["/api/pretransaction"]}.
Console Image
How to fix this error?
Sorry if I ask again, I try to make dropdown from array in my database then use the dropdown to take the value I want looping the array to the dropdown in here but still not showed
//tipe akademik
//define state
const [postsTipe, setPostsTipe] = useState([]);
//useEffect hook
useEffect(() => {
//panggil method "fetchData"
fectDataTipe();
}, []);
//function "fetchData"
const fectDataTipe = async () => {
//fetching
const responseTipe = await axios.get('http://localhost:3000/api/tipe_akademik');
//get response data
const dataTipe = await responseTipe.data.data;
//assign response data to state "posts"
setPostsTipe(dataTipe);
}
const Dropdown = () => {
// dropdown props
const [dropdownPopoverShow, setDropdownPopoverShow] = React.useState(false);
const btnDropdownRef = React.createRef();
const popoverDropdownRef = React.createRef();
const openDropdownPopover = () => {
createPopper(btnDropdownRef.current, popoverDropdownRef.current, {
placement: "bottom-start",
});
setDropdownPopoverShow(true);
};
const closeDropdownPopover = () => {
setDropdownPopoverShow(false);
};
return (
<>
<a
className="text-blueGray-500 block"
href="#pablo"
ref={btnDropdownRef}
onClick={(e) => {
e.preventDefault();
dropdownPopoverShow ? closeDropdownPopover() : openDropdownPopover();
}} >
<div class="relative inline-block text-left">
<div>
<button type="button" class="inline-flex justify-center w-full rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-indigo-500" id="menu-button" aria-expanded="true" aria-haspopup="true">
Tipe Akademik
</button>
</div>
</div>
</a>
<div
ref={popoverDropdownRef}
className={
(dropdownPopoverShow ? "block " : "hidden ") +
"bg-white text-base z-50 float-left py-2 list-none text-left rounded shadow-lg min-w-48"
}
>
{postsTipe.map((kategori)=> {
return(<>
<a
href="#pablo"
className={
"text-sm py-2 px-4 font-normal block w-full whitespace-nowrap bg-transparent text-blueGray-700"
}
onClick={(e) => e.preventDefault()}
>
{kategori.tipe_akademik}
</a> /</> )})}
</div>
</>
);
};
export default Dropdown;
Then I call it to my input form with import from dropdown and I want take the value in form and its still wrong. I dont know how to take the the value from import the dropdown named TipeDropdown
import TipeDropdown from "components/Dropdowns/Dropdown";
method "storePost"
const storePost = async (e) => {
e.preventDefault();
//send data to server
await axios.post('http://localhost:3000/api/akademik_a/store', {
tipeA: TipeA,
})
.then(() => {
//redirect
history.push('/admin/dafgur');
})
.catch((error) => {
//assign validation on state
setValidation(error.response.data);
})
};
export default function InputAkademik({ color }) {
return (
<>
<form onSubmit={ storePost }
<input className="border-0 px-3 py-3 placeholder-blueGray-300 text-blueGray-600 bg-white rounded text-sm shadow focus:outline-none focus:ring w-full ease-linear transition-all duration-150"
placeholder="" />
<div className="field mt-5">
<label className="label">Tipe Akademik</label>
<div className="controls">
<TipeDropdown value={TipeA} onChange={(e) => setTipe(e.target.value)}/>
<input type="text" className="border-0 px-3 py-3 placeholder-blueGray-300 text-blueGray-600 bg-white rounded text-sm shadow focus:outline-none focus:ring w-full ease-linear transition-all duration-150" placeholder="" value={TipeInput} onChange={(e) => TipeInput(e.target.value)} />
</div>
</div> </div>
</>
);
};