Skip to content

Commit

Permalink
Added show message component
Browse files Browse the repository at this point in the history
  • Loading branch information
riadelimemmedov committed Mar 15, 2024
1 parent c2409cb commit 508be5a
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 19 deletions.
1 change: 0 additions & 1 deletion backend/apps/order/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ def post(self, request, format=None):
}
],
)
print("checkout_session ", checkout_session)
return Response({"sessionId": checkout_session["id"]})
except Exception as e:
print("e ", e)
Expand Down
2 changes: 1 addition & 1 deletion frontend/contract-ui/contracts/PetLocal.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"abi":"[{\"type\":\"constructor\",\"payable\":false,\"inputs\":[{\"type\":\"uint256\",\"name\":\"initialPetIndex\"}]},{\"type\":\"function\",\"name\":\"addPet\",\"constant\":false,\"payable\":false,\"inputs\":[],\"outputs\":[]},{\"type\":\"function\",\"name\":\"addToCart\",\"constant\":false,\"payable\":false,\"inputs\":[{\"type\":\"uint256\",\"name\":\"_petId\"},{\"type\":\"string\",\"name\":\"_petName\"},{\"type\":\"string\",\"name\":\"_petColor\"},{\"type\":\"uint256\",\"name\":\"_petPrice\"},{\"type\":\"string\",\"name\":\"_petPhoto\"}],\"outputs\":[]},{\"type\":\"function\",\"name\":\"adoptPet\",\"constant\":false,\"payable\":false,\"inputs\":[{\"type\":\"uint256\",\"name\":\"adoptIdx\"}],\"outputs\":[]},{\"type\":\"function\",\"name\":\"allAdoptedPets\",\"constant\":true,\"stateMutability\":\"view\",\"payable\":false,\"inputs\":[{\"type\":\"uint256\"}],\"outputs\":[{\"type\":\"uint256\"}]},{\"type\":\"function\",\"name\":\"getAllAdoptedPets\",\"constant\":true,\"stateMutability\":\"view\",\"payable\":false,\"inputs\":[],\"outputs\":[{\"type\":\"uint256[]\"}]},{\"type\":\"function\",\"name\":\"getAllAdoptedPetsByOwner\",\"constant\":true,\"stateMutability\":\"view\",\"payable\":false,\"inputs\":[],\"outputs\":[{\"type\":\"uint256[]\"}]},{\"type\":\"function\",\"name\":\"getCartItems\",\"constant\":true,\"stateMutability\":\"view\",\"payable\":false,\"inputs\":[],\"outputs\":[{\"type\":\"tuple[]\",\"components\":[{\"type\":\"uint256\",\"name\":\"id\"},{\"type\":\"string\",\"name\":\"name\"},{\"type\":\"string\",\"name\":\"color\"},{\"type\":\"uint256\",\"name\":\"price\"},{\"type\":\"string\",\"name\":\"photo\"}]}]},{\"type\":\"function\",\"name\":\"getCartLength\",\"constant\":true,\"stateMutability\":\"view\",\"payable\":false,\"inputs\":[],\"outputs\":[{\"type\":\"uint256\"}]},{\"type\":\"function\",\"name\":\"getOwner\",\"constant\":true,\"stateMutability\":\"view\",\"payable\":false,\"inputs\":[],\"outputs\":[{\"type\":\"address\"}]},{\"type\":\"function\",\"name\":\"owner\",\"constant\":true,\"stateMutability\":\"view\",\"payable\":false,\"inputs\":[],\"outputs\":[{\"type\":\"address\"}]},{\"type\":\"function\",\"name\":\"ownerAddressToPetList\",\"constant\":true,\"stateMutability\":\"view\",\"payable\":false,\"inputs\":[{\"type\":\"address\"},{\"type\":\"uint256\"}],\"outputs\":[{\"type\":\"uint256\"}]},{\"type\":\"function\",\"name\":\"petIdxToOwnerAddress\",\"constant\":true,\"stateMutability\":\"view\",\"payable\":false,\"inputs\":[{\"type\":\"uint256\"}],\"outputs\":[{\"type\":\"address\"}]},{\"type\":\"function\",\"name\":\"petIndex\",\"constant\":true,\"stateMutability\":\"view\",\"payable\":false,\"inputs\":[],\"outputs\":[{\"type\":\"uint256\"}]},{\"type\":\"function\",\"name\":\"removeCart\",\"constant\":false,\"payable\":false,\"inputs\":[{\"type\":\"uint256\",\"name\":\"index\"}],\"outputs\":[]}]","address":"0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9","network":"localhost","deployer":"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"}
{"abi":"[{\"type\":\"constructor\",\"payable\":false,\"inputs\":[{\"type\":\"uint256\",\"name\":\"initialPetIndex\"}]},{\"type\":\"function\",\"name\":\"addPet\",\"constant\":false,\"payable\":false,\"inputs\":[],\"outputs\":[]},{\"type\":\"function\",\"name\":\"addToCart\",\"constant\":false,\"payable\":false,\"inputs\":[{\"type\":\"uint256\",\"name\":\"_petId\"},{\"type\":\"string\",\"name\":\"_petName\"},{\"type\":\"string\",\"name\":\"_petColor\"},{\"type\":\"uint256\",\"name\":\"_petPrice\"},{\"type\":\"string\",\"name\":\"_petPhoto\"}],\"outputs\":[]},{\"type\":\"function\",\"name\":\"adoptPet\",\"constant\":false,\"payable\":false,\"inputs\":[{\"type\":\"uint256\",\"name\":\"adoptIdx\"}],\"outputs\":[]},{\"type\":\"function\",\"name\":\"allAdoptedPets\",\"constant\":true,\"stateMutability\":\"view\",\"payable\":false,\"inputs\":[{\"type\":\"uint256\"}],\"outputs\":[{\"type\":\"uint256\"}]},{\"type\":\"function\",\"name\":\"getAllAdoptedPets\",\"constant\":true,\"stateMutability\":\"view\",\"payable\":false,\"inputs\":[],\"outputs\":[{\"type\":\"uint256[]\"}]},{\"type\":\"function\",\"name\":\"getAllAdoptedPetsByOwner\",\"constant\":true,\"stateMutability\":\"view\",\"payable\":false,\"inputs\":[],\"outputs\":[{\"type\":\"uint256[]\"}]},{\"type\":\"function\",\"name\":\"getCartItems\",\"constant\":true,\"stateMutability\":\"view\",\"payable\":false,\"inputs\":[],\"outputs\":[{\"type\":\"tuple[]\",\"components\":[{\"type\":\"uint256\",\"name\":\"id\"},{\"type\":\"string\",\"name\":\"name\"},{\"type\":\"string\",\"name\":\"color\"},{\"type\":\"uint256\",\"name\":\"price\"},{\"type\":\"string\",\"name\":\"photo\"}]}]},{\"type\":\"function\",\"name\":\"getCartLength\",\"constant\":true,\"stateMutability\":\"view\",\"payable\":false,\"inputs\":[],\"outputs\":[{\"type\":\"uint256\"}]},{\"type\":\"function\",\"name\":\"getOwner\",\"constant\":true,\"stateMutability\":\"view\",\"payable\":false,\"inputs\":[],\"outputs\":[{\"type\":\"address\"}]},{\"type\":\"function\",\"name\":\"owner\",\"constant\":true,\"stateMutability\":\"view\",\"payable\":false,\"inputs\":[],\"outputs\":[{\"type\":\"address\"}]},{\"type\":\"function\",\"name\":\"ownerAddressToPetList\",\"constant\":true,\"stateMutability\":\"view\",\"payable\":false,\"inputs\":[{\"type\":\"address\"},{\"type\":\"uint256\"}],\"outputs\":[{\"type\":\"uint256\"}]},{\"type\":\"function\",\"name\":\"petIdxToOwnerAddress\",\"constant\":true,\"stateMutability\":\"view\",\"payable\":false,\"inputs\":[{\"type\":\"uint256\"}],\"outputs\":[{\"type\":\"address\"}]},{\"type\":\"function\",\"name\":\"petIndex\",\"constant\":true,\"stateMutability\":\"view\",\"payable\":false,\"inputs\":[],\"outputs\":[{\"type\":\"uint256\"}]},{\"type\":\"function\",\"name\":\"removeCart\",\"constant\":false,\"payable\":false,\"inputs\":[{\"type\":\"uint256\",\"name\":\"index\"}],\"outputs\":[]}]","address":"0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512","network":"localhost","deployer":"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"}
9 changes: 9 additions & 0 deletions frontend/contract-ui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/contract-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
},
"dependencies": {
"dotenv": "^16.4.5",
"email-validator": "^2.0.4",
"ethers": "^5.7.2",
"gsap": "^3.12.5",
"moralis-v1": "^1.13.0",
Expand Down
23 changes: 23 additions & 0 deletions frontend/contract-ui/src/components/PaymentCancelled.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from "react"
import {Link} from 'react-router-dom'


// *PaymentCancelledCard
const PaymentCancelledCard = () => {
//return jsx to client
return (
<>
<div className="container mx-auto mt-20">
<div className="flex justify-center">
<div className="w-10/12">
<h1 className="text-4xl font-bold mb-4">Your payment was cancelled.</h1>
<hr className="my-4" />
<br />
<Link to={"/"} className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-full text-sm">Back Home</Link>
</div>
</div>
</div>
</>
)
}
export default PaymentCancelledCard;
39 changes: 37 additions & 2 deletions frontend/contract-ui/src/components/PaymentSuccsess.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,47 @@
import React from 'react';
import {Link} from 'react-router-dom'
import React, { useEffect, useState } from 'react';
import {Link,useLocation} from 'react-router-dom'
import connect_contract from '../../helpers/connect_contract';
import { getSigner } from '../../helpers/get_signer';
import { useMoralis } from "react-moralis";
import { Navbar } from './Navbar';


// *PaymentSuccessCard
const PaymentSuccessCard = () => {
// Moralis
const { web3,account } = useMoralis();

// getPaymentSessionId
const getPaymentSessionId = () => {
const queryString = window.location.search;
const params = new URLSearchParams(queryString);
return params.get('session_id');
}

// removePetsFromCard
const removePetsFromCard = async () => {
if(getPaymentSessionId() != null){
const connected_contract = await connect_contract()
const signer = getSigner(account)
const pets = await connected_contract.connect(signer).getCartItems()
pets.length>0&&pets.forEach(async (pet,index) => {
await connected_contract.connect(signer).removeCart(index)
})
}
else{
return null
}
}

useEffect(()=>{
removePetsFromCard()
},[])


//return jsx to client
return (
<>
<Navbar/>
<div class="bg-white p-6 md:mx-auto justify-center mt-20">
<svg viewBox="0 0 24 24" class="text-green-600 w-16 h-16 mx-auto my-6">
<path fill="currentColor"
Expand Down
2 changes: 2 additions & 0 deletions frontend/contract-ui/src/main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { BrowserRouter, Routes, Route } from 'react-router-dom';

import Cart from './routes/Cart'
import PaymentSuccessCard from './components/PaymentSuccsess'
import PaymentCancelledCard from './components/PaymentCancelled'


ReactDOM.createRoot(document.getElementById('root')).render(
Expand All @@ -19,6 +20,7 @@ ReactDOM.createRoot(document.getElementById('root')).render(
<Route exact path="/" element={<App/>}/>
<Route exact path="cart" element={<Cart/>}/>
<Route exact path="success" element={<PaymentSuccessCard/>}/>
<Route exact path="canceled" element={<PaymentCancelledCard/>}/>
</Routes>
</BrowserRouter>
<ToastContainer />
Expand Down
88 changes: 73 additions & 15 deletions frontend/contract-ui/src/routes/Cart.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,28 @@ import { Navbar } from "../components/Navbar";
// !Helpers methods
import connect_contract from '../../helpers/connect_contract';
import {getSigner} from '../../helpers/get_signer';
import getStripePublishableKey from '../../helpers/init_stripe';



// !Third part packages
import { useMoralis } from "react-moralis";
import { gsap } from "gsap";
import { toast } from 'react-toastify'
import { useNavigate } from "react-router-dom";
import getStripePublishableKey from '../../helpers/init_stripe';


import validator from 'email-validator';


// *Cart
export default function Cart(){
export default function Cart(){
const [contract,setContract] = useState(null)
const [provider,setProvider] = useState(window.ethereum)
const [pets,setPets] = useState(null)
const [paymentOption,setPaymentOption] = useState('ethereum')
const [signer,setSigner] = useState()
const [reload,setReload] = useState(false)
const [paymentIsStart,setPaymentIsStart] = useState(false)
const [email,setEmail] = useState(null)

//mavigate
const navigate = useNavigate();
Expand All @@ -38,6 +39,20 @@ export default function Cart(){
//moralis
const { web3,account,Moralis,isAuthenticated,user,authenticate } = useMoralis();


//? showMessage
const showMessage = (message_text,message_type) => {
if(message_type == "success"){
toast.success(message_text)
}
else if(message_type == "error"){
toast.error(message_text)
}
else if(message_type == "info"){
toast.warning(message_text)
}
}

// ?gsap
const elementRef = useRef(null);

Expand All @@ -60,19 +75,25 @@ export default function Cart(){
await contract.connect(signer).removeCart(index)
await removePet()
if(await getCartItems()){
setTimeout(()=>navigate("/"),0)
setPaymentIsStart(true)
toast.success('Adopted Pet Successesfully')
setTimeout(()=>navigate("/"),3000)
}
}

// ?adoptPet
const adoptPet = async () => {
setPaymentIsStart(true)
pets.map(async(pet,index) => {
await contract.connect(signer).adoptPet(index)
await removeCart(index >= 1 ? index-1 : 0)
})
const {isValidEmail,isValidPaymentMethod:ethereum} = checkPaymentCredentials(paymentOption,web3)
const isCheckedPaymentCredentials = isValidEmail && ethereum ? true : false
if(isCheckedPaymentCredentials){
setPaymentIsStart(true)
pets.map(async(pet,index) => {
await contract.connect(signer).adoptPet(index)
await removeCart(index >= 1 ? index-1 : 0)
})
}
else{
setPaymentIsStart(false)
}
}

// ?removePet
Expand All @@ -91,11 +112,43 @@ export default function Cart(){
}
}

// ?validateEmail
const validateEmail = () => {
const isValidEmail = validator.validate(email);
if(!isValidEmail) {
showMessage('Invalid email address', 'error')
return false
}
return true
}

// ?validatePaymentMethod
const validatePaymentMethod = (payment_method,wallet_public_key=null) => {
if(payment_method=='ethereum' && wallet_public_key == null){
return null
}
else if(payment_method=='stripe' && wallet_public_key){
const stripe = getStripePublishableKey()
return stripe
}
}

//? checkPaymentCredentials
const checkPaymentCredentials = (payment_method,wallet_public_key=null) => {//ethereum or stripe
const isValidEmail = validateEmail()
const isValidPaymentMethod = validatePaymentMethod(payment_method, wallet_public_key)
if(isValidEmail && isValidPaymentMethod){
return {isValidEmail,isValidPaymentMethod}
}
}

//?handlePurchase
const handlePurchase = () =>{
const stripe = getStripePublishableKey()
setPaymentIsStart(true)
fetch('http://localhost:8000/orders/create-checkout-session', {
const {isValidEmail,isValidPaymentMethod:stripe} = checkPaymentCredentials(paymentOption,true)
const isCheckedPaymentCredentials = isValidEmail && stripe ? true : false
if(isCheckedPaymentCredentials){
setPaymentIsStart(true)
fetch('http://localhost:8000/orders/create-checkout-session', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Expand All @@ -112,6 +165,11 @@ export default function Cart(){
.then((res) => {
console.log(res);
});
}
else{
return null
}

}

//useEffect
Expand Down Expand Up @@ -201,7 +259,7 @@ export default function Cart(){
<div className="">
<label for="email" className="mt-4 mb-2 block text-sm font-medium">Email</label>
<div className="relative">
<input type="text" id="email" name="email" className="w-full rounded-md border border-gray-200 px-4 py-3 pl-11 text-sm shadow-sm outline-none focus:z-10 focus:border-blue-500 focus:ring-blue-500" placeholder="your.email@gmail.com" required/>
<input onChange={(e)=>setEmail(e.target.value)} type="text" id="email" name="email" className="w-full rounded-md border border-gray-200 px-4 py-3 pl-11 text-sm shadow-sm outline-none focus:z-10 focus:border-blue-500 focus:ring-blue-500" placeholder="your.email@gmail.com" required/>
<div className="pointer-events-none absolute inset-y-0 left-0 inline-flex items-center px-3">
<svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M16 12a4 4 0 10-8 0 4 4 0 008 0zm0 0v1.5a2.5 2.5 0 005 0V12a9 9 0 10-9 9m4.5-1.206a8.959 8.959 0 01-4.5 1.207" />
Expand Down

0 comments on commit 508be5a

Please sign in to comment.