From 2907ee2a50e3ba31b92e8efca5451cb9c23a7bad Mon Sep 17 00:00:00 2001
From: 18521124 <18521124@gm.uit.edu.vn>
Date: Sun, 26 Jun 2022 20:09:08 +0700
Subject: [PATCH 1/4] feat/add popup
---
components/Popup.tsx | 45 ++++++++
components/popup.module.css | 100 ++++++++++++++++++
components/professions/Inventory/index.tsx | 8 +-
components/professions/ProfessionsModal.tsx | 8 +-
.../blacksmith/forgehammer/ForgeHammer.tsx | 9 +-
.../openian/fishingModal/FishingModal.tsx | 39 +++----
.../openian/miningModal/MiningModal.tsx | 52 ++++-----
.../openian/sellModal/SellBoard.tsx | 8 +-
components/worldmap/CreateProfile.tsx | 10 +-
components/worldmap/RefillStaminaModal.tsx | 51 ++++-----
hooks/useTransactionState.tsx | 81 +++++++-------
pages/castle/shop/index.tsx | 8 +-
pages/foodcourt/index.tsx | 16 +--
pages/professions/supplier/index.tsx | 14 +--
pages/workshop/index.tsx | 16 +--
public/images/popup/background-2.png | Bin 0 -> 1461 bytes
public/images/popup/background-3.png | Bin 0 -> 19209 bytes
public/images/popup/background.png | Bin 0 -> 186001 bytes
public/images/popup/cancel.png | Bin 0 -> 6369 bytes
public/images/popup/close.png | Bin 0 -> 282 bytes
public/images/popup/failed.png | Bin 0 -> 5981 bytes
public/images/popup/fish.png | Bin 0 -> 7586 bytes
public/images/popup/ore.png | Bin 0 -> 6495 bytes
public/images/popup/other.png | Bin 0 -> 8550 bytes
public/images/popup/stamina.png | Bin 0 -> 4042 bytes
public/images/popup/success.png | Bin 0 -> 6037 bytes
public/images/popup/sushi.png | Bin 0 -> 6586 bytes
public/images/popup/waiting.png | Bin 0 -> 23257 bytes
28 files changed, 316 insertions(+), 149 deletions(-)
create mode 100644 components/Popup.tsx
create mode 100644 components/popup.module.css
create mode 100644 public/images/popup/background-2.png
create mode 100644 public/images/popup/background-3.png
create mode 100644 public/images/popup/background.png
create mode 100644 public/images/popup/cancel.png
create mode 100644 public/images/popup/close.png
create mode 100644 public/images/popup/failed.png
create mode 100644 public/images/popup/fish.png
create mode 100644 public/images/popup/ore.png
create mode 100644 public/images/popup/other.png
create mode 100644 public/images/popup/stamina.png
create mode 100644 public/images/popup/success.png
create mode 100644 public/images/popup/sushi.png
create mode 100644 public/images/popup/waiting.png
diff --git a/components/Popup.tsx b/components/Popup.tsx
new file mode 100644
index 00000000..56710d94
--- /dev/null
+++ b/components/Popup.tsx
@@ -0,0 +1,45 @@
+import styles from "./popup.module.css"
+
+const infoType = {
+ sushi: '/images/popup/sushi.png',
+ stamina: '/images/popup/stamina.png',
+ fish: '/images/popup/fish.png',
+ ore: '/images/popup/ore.png',
+ other: '/images/popup/other.png',
+ success: '/images/popup/success.png',
+ failed: '/images/popup/failed.png',
+ cancel: '/images/popup/cancel.png',
+ waiting: '/images/popup/waiting.png',
+}
+
+const Popup = ({
+ type = null,
+ content,
+ subcontent = null,
+ actionContent,
+ setIsOpen,
+ action
+}) => {
+ return (
+
+
+
+
+
+
NOTI
+
+
+ {type &&

}
+
{content}
+ {subcontent &&
({subcontent})
}
+
+
+
+
+
+ )
+}
+
+export default Popup
\ No newline at end of file
diff --git a/components/popup.module.css b/components/popup.module.css
new file mode 100644
index 00000000..1c4f35ec
--- /dev/null
+++ b/components/popup.module.css
@@ -0,0 +1,100 @@
+
+.modal {
+ position: fixed; /* Stay in place */
+ z-index: 1000000; /* Sit on top */
+ left: 0;
+ top: 0;
+ width: 100vw; /* Full width */
+ height: 100vh; /* Full height */
+ background-color: rgb(0,0,0); /* Fallback color */
+ background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
+}
+
+/* Modal Content/Box */
+.background3 {
+ margin: 15% auto; /* 15% from the top and centered */
+ padding: 2px;
+ width: 600px; /* Could be more or less, depending on screen size */
+ background-image: url('/images/popup/background-3.png');
+ background-size: 100% 100%;
+ background-repeat: no-repeat;
+ background-color: transparent;
+}
+
+.background2{
+ background-image: url('/images/popup/background-2.png');
+ background-size: 100% 100%;
+ background-repeat: no-repeat;
+ height: 100%;
+ width: 100%;
+ padding: 10px;
+}
+
+.background1{
+ background-image: url('/images/popup/background.png');
+ background-size: 100% 100%;
+ background-repeat: no-repeat;
+ height: 100%;
+ width: 100%;
+ text-align: center;
+ padding: 15px 20px;
+}
+
+.background1 > div:first-child{
+ display: flex;
+ justify-content: space-between;
+}
+
+.background1 > div:first-child > img{
+ width: 22px;
+ height: 22px;
+}
+
+.background1 > div:first-child > div{
+ color: #472805;
+ font-size: 24px;
+ font-weight: 800;
+}
+
+.background1 > img{
+ display: block;
+ margin: auto;
+ margin-top: 20px;
+}
+
+.background1 > div:nth-child(3){
+ font-family: cursive;
+ color: #592203;
+ font-size: 22px;
+ padding: 16px;
+}
+
+.background1 > div:nth-child(4){
+ font-family: "Gill Sans", sans-serif;
+ color: #c74f0c;
+ font-size: 16px;
+}
+
+.background1 > div:nth-child(4) a svg{
+ margin-top: -5px;
+}
+
+.background1 > button.invalid{
+ font-family: system-ui;
+ background-color: #bcbcbc;
+ color: #838383;
+ padding: 6px 25px;
+ border-radius: 10px;
+ font-weight: 500;
+ margin: 20px 0;
+}
+
+.background1 > button{
+ font-family: system-ui;
+ background-color: #472805;
+ color: #f0e0d0;
+ padding: 5px 20px;
+ border-radius: 10px;
+ font-weight: 500;
+ margin: 20px 0;
+}
\ No newline at end of file
diff --git a/components/professions/Inventory/index.tsx b/components/professions/Inventory/index.tsx
index 02c02098..c6577350 100644
--- a/components/professions/Inventory/index.tsx
+++ b/components/professions/Inventory/index.tsx
@@ -40,6 +40,7 @@ function Inventory(_, ref) {
const [isOpenNotify, setIsOpenNotify] = useState(null)
const [data, setData] = useState(null)
const handleTxStateChange = useTransactionState()
+ const [popup, setPopup] = useState(null)
useImperativeHandle(
ref,
@@ -66,14 +67,14 @@ function Inventory(_, ref) {
selectedItem?.ids?.slice(0, Number(amountItems)),
price,
(txHash) => {
- handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING)
+ handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING, setPopup)
}
)
if (result) {
- handleTxStateChange(title, result.transactionHash, result.status)
+ handleTxStateChange(title, result.transactionHash, result.status, setPopup)
} else {
- handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED)
+ handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED, setPopup)
}
getItemsIndex()
@@ -242,6 +243,7 @@ function Inventory(_, ref) {
+ {popup}
)
}
diff --git a/components/professions/ProfessionsModal.tsx b/components/professions/ProfessionsModal.tsx
index f3e7f1ea..4f6af42f 100644
--- a/components/professions/ProfessionsModal.tsx
+++ b/components/professions/ProfessionsModal.tsx
@@ -56,6 +56,7 @@ function ProfessionsModal(props: Props) {
const [requireBalance, setRequireBalance] = useState(0)
const [isLoading, setIsLoading] = useState(false)
const handleTxStateChange = useTransactionState()
+ const [popup, setPopup] = useState(null)
const getRequireBalanceProfession = async () => {
const balance = await fetchRequireBalanceProfession()
@@ -83,15 +84,15 @@ function ProfessionsModal(props: Props) {
professionNft,
hero.heroId,
(txHash) => {
- handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING)
+ handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING, setPopup)
}
)
if (data) {
getResult(data.status)
- handleTxStateChange(title, data.transactionHash, data.status)
+ handleTxStateChange(title, data.transactionHash, data.status, setPopup)
} else {
- handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED)
+ handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED, setPopup)
}
}
setIsLoading(false)
@@ -222,6 +223,7 @@ function ProfessionsModal(props: Props) {
onClick={closeModal}
>
+ {popup}
>
)
}
diff --git a/components/professions/blacksmith/forgehammer/ForgeHammer.tsx b/components/professions/blacksmith/forgehammer/ForgeHammer.tsx
index 93279bee..7e73e686 100644
--- a/components/professions/blacksmith/forgehammer/ForgeHammer.tsx
+++ b/components/professions/blacksmith/forgehammer/ForgeHammer.tsx
@@ -23,6 +23,7 @@ export default function ForgeHammer(props: Props) {
const [isStartQuestFail, setIsStartQuestFail] = useState(false)
const [checkIsSuccess, setCheckIsSuccess] = useState(false)
const handleTxStateChange = useTransactionState()
+ const [popup, setPopup] = useState(null)
const numberOreNeed = useMemo(() => numberHammer / 2, [numberHammer])
@@ -51,7 +52,7 @@ export default function ForgeHammer(props: Props) {
if (numberOreNeed <= numberYourOre.length && numberHammer !== 0) {
const listSellHammer = numberYourOre.slice(0, numberOreNeed)
const forgeHammer = await makeHammer(listSellHammer, (txHash) => {
- handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING)
+ handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING, setPopup)
})
if (forgeHammer) {
@@ -60,10 +61,11 @@ export default function ForgeHammer(props: Props) {
handleTxStateChange(
title,
forgeHammer.transactionHash,
- forgeHammer.status
+ forgeHammer.status,
+ setPopup
)
} else {
- handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED)
+ handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED, setPopup)
}
toggleLoadingModal(false)
@@ -172,6 +174,7 @@ export default function ForgeHammer(props: Props) {
{isStartQuestFail && (
)}
+ {popup}
)
}
diff --git a/components/professions/openian/fishingModal/FishingModal.tsx b/components/professions/openian/fishingModal/FishingModal.tsx
index f4aef292..85e60435 100644
--- a/components/professions/openian/fishingModal/FishingModal.tsx
+++ b/components/professions/openian/fishingModal/FishingModal.tsx
@@ -1,4 +1,4 @@
-import { Button, useToast } from '@chakra-ui/react'
+import { Button } from '@chakra-ui/react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { useCallback, useEffect, useState } from 'react'
import {
@@ -17,6 +17,8 @@ import { addHours, fromUnixTime, intervalToDuration, isBefore } from 'date-fns'
import useTransactionState, {
TRANSACTION_STATE,
} from 'hooks/useTransactionState'
+import Popup from '@components/Popup'
+import { useRouter } from 'next/router'
type Props = {
isOpen: boolean
@@ -36,11 +38,12 @@ function FishingModal(props: Props) {
const [typeofModal, setTypeOfModal] = useState(TYPE_OF_MODAL.START)
const [requireStamina, setRequireStamina] = useState(0)
const [duration, setDuration] = useState(10)
+ const [popup, setPopup] = useState(null)
+ const router = useRouter()
const [canFinish, setCanFinish] = useState(false)
const [timeLeft, setTimeLeft] = useState(null)
const [loading, setLoading] = useState(true)
- const toast = useToast()
const handleTxStateChange = useTransactionState()
const initialize = useCallback(async () => {
@@ -81,18 +84,17 @@ function FishingModal(props: Props) {
const stamina = await getStamina()
if (Number(stamina) < 49) {
- toast({
- title: 'Fishing Quest',
- description:
- "Fishing quest requires at least 49 stamina to start. You don't have enough stamina to start fishing quest.",
- status: 'error',
- duration: 15000,
- isClosable: true,
- })
+ setPopup( { router.push('foodcourt') }}
+ />)
}
-
return Number(stamina) >= 49
- }, [toast])
+ }, [popup])
const handleStartQuest = useCallback(async () => {
const title = 'Start fishing quest'
@@ -109,7 +111,7 @@ function FishingModal(props: Props) {
toggleLoadingModal(true)
const fishing = await startFishing((txHash) => {
- handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING)
+ handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING, setPopup)
})
setTimeout(() => {
toggleLoadingModal(false)
@@ -117,10 +119,10 @@ function FishingModal(props: Props) {
if (fishing !== null) {
setTypeOfModal(TYPE_OF_MODAL.WAITING)
setCanFinish(false)
- handleTxStateChange(title, fishing.transactionHash, fishing.status)
+ handleTxStateChange(title, fishing.transactionHash, fishing.status, setPopup)
} else {
toggleLoadingModal(false)
- handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED)
+ handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED, setPopup)
}
}, [checkRequirementBeforeStartQuest, toggleLoadingModal])
@@ -129,14 +131,14 @@ function FishingModal(props: Props) {
if (canFinish) {
toggleLoadingModal(true)
const finish = await finishFishing((txHash) => {
- handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING)
+ handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING, setPopup)
})
if (finish) {
- handleTxStateChange(title, finish.transactionHash, finish.status)
+ handleTxStateChange(title, finish.transactionHash, finish.status, setPopup)
updateInventory()
setTypeOfModal(TYPE_OF_MODAL.FINISH)
} else {
- handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED)
+ handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED, setPopup)
}
toggleLoadingModal(false)
}
@@ -226,6 +228,7 @@ function FishingModal(props: Props) {
+ {popup}
)
}
diff --git a/components/professions/openian/miningModal/MiningModal.tsx b/components/professions/openian/miningModal/MiningModal.tsx
index 1f913fa1..9cd2e5ec 100644
--- a/components/professions/openian/miningModal/MiningModal.tsx
+++ b/components/professions/openian/miningModal/MiningModal.tsx
@@ -1,6 +1,6 @@
import { useCallback, useEffect, useRef, useState } from 'react'
import style from './Mining.module.css'
-import { Button, useToast } from '@chakra-ui/react'
+import { Button } from '@chakra-ui/react'
import ResultMining from './ResultMining'
import MiningWait from './MiningWait'
@@ -18,6 +18,8 @@ import { getStamina } from 'utils/profileContract'
import useTransactionState, {
TRANSACTION_STATE,
} from 'hooks/useTransactionState'
+import { useRouter } from 'next/router'
+import Popup from '@components/Popup'
type Props = {
isOpen: boolean
@@ -38,7 +40,8 @@ export default function MiningModal(props: Props) {
intervalToDuration({ start: 0, end: 0 })
)
const handleTxStateChange = useTransactionState()
- const toast = useToast()
+ const [popup, setPopup] = useState(null)
+ const router = useRouter()
const initialize = useCallback(async () => {
toggleLoadingModal(true)
@@ -74,31 +77,29 @@ export default function MiningModal(props: Props) {
const checkRequirementBeforeStartQuest = useCallback(async () => {
const hammerList = await fetchAmountItemByTrait(3)
if (hammerList?.length < 1) {
- toast({
- title: 'Mining Quest',
- description: "You don't have enough hammer to start mining quest",
- status: 'error',
- duration: 15000,
- isClosable: true,
- })
+ setPopup( { router.push('professions') }}
+ />)
return false
}
const stamina = await getStamina()
if (Number(stamina) < 49) {
- toast({
- title: 'Mining Quest',
- description:
- "Mining quest requires at least 49 stamina to start. You don't have enough stamina to start mining quest.",
- status: 'error',
- duration: 15000,
- isClosable: true,
- })
+ setPopup( { router.push('foodcourt') }}
+ />)
return false
}
-
return true
- }, [toast])
+ }, [popup])
const startQuest = useCallback(async () => {
try {
@@ -111,17 +112,17 @@ export default function MiningModal(props: Props) {
toggleLoadingModal(true)
const mining = await startMining((txHash) => {
- handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING)
+ handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING, setPopup)
})
if (mining) {
- handleTxStateChange(title, mining.transactionHash, mining.status)
+ handleTxStateChange(title, mining.transactionHash, mining.status, setPopup)
const data = await getMiningQuest()
setIsFinished(data.finish)
setIsStartQuest(false)
setCanFinish(false)
} else {
- handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED)
+ handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED, setPopup)
}
} catch (e) {
} finally {
@@ -133,17 +134,17 @@ export default function MiningModal(props: Props) {
const title = 'Finish mining quest'
toggleLoadingModal(true)
const finish = await finishMining((txHash) => {
- handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING)
+ handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING, setPopup)
})
if (finish) {
- handleTxStateChange(title, finish.transactionHash, finish.status)
+ handleTxStateChange(title, finish.transactionHash, finish.status, setPopup)
updateInventory()
setIsStartQuest(false)
setIsFinished(true)
// setTimeLeft(duration)
} else {
- handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED)
+ handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED, setPopup)
}
toggleLoadingModal(false)
}, [])
@@ -185,6 +186,7 @@ export default function MiningModal(props: Props) {
) : (
)}
+ {popup}
)
}
diff --git a/components/professions/openian/sellModal/SellBoard.tsx b/components/professions/openian/sellModal/SellBoard.tsx
index 434bbe31..b8ea856d 100644
--- a/components/professions/openian/sellModal/SellBoard.tsx
+++ b/components/professions/openian/sellModal/SellBoard.tsx
@@ -31,6 +31,7 @@ function SellBoard(props: Props) {
const [isLoading, setIsLoading] = useState(false)
const [listingResult, setListingResult] = useState(undefined)
const handleTxStateChange = useTransactionState()
+ const [popup, setPopup] = useState(null)
const fetchSelectedItemAmount = async () => {
const itemAmount = await fetchUserInventoryItemAmount()
@@ -129,15 +130,15 @@ function SellBoard(props: Props) {
const itemSellIds = selectedItemIds.slice(0, sellingAmount)
const result = await listMultiItems(itemSellIds, price, (txHash) => {
- handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING)
+ handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING, setPopup)
})
if (result !== null) {
handleFinishListing()
setListingResult(true)
- handleTxStateChange(title, result.transactionHash, result.status)
+ handleTxStateChange(title, result.transactionHash, result.status, setPopup)
} else {
setListingResult(false)
- handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED)
+ handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED, setPopup)
}
priceRef.current.value = '0'
setPrice(0)
@@ -255,6 +256,7 @@ function SellBoard(props: Props) {
+ {popup}
>
)
}
diff --git a/components/worldmap/CreateProfile.tsx b/components/worldmap/CreateProfile.tsx
index ced993b9..3876940d 100644
--- a/components/worldmap/CreateProfile.tsx
+++ b/components/worldmap/CreateProfile.tsx
@@ -26,6 +26,7 @@ export default function CreateProfile({
const [isLoading, setIsLoading] = useState(false)
const router = useRouter()
const handleTxStateChange = useTransactionState()
+ const [popup, setPopup] = useState(null)
const handleCloseModalCreateProfile = useCallback(
(e: any) => {
@@ -43,7 +44,7 @@ export default function CreateProfile({
title = 'Create profile'
}
const status = data.status ? 1 : 0
- handleTxStateChange(title, data.transactionHash, status)
+ handleTxStateChange(title, data.transactionHash, status, setPopup)
}
const onTransactionExecute = (txHash) => {
@@ -53,7 +54,7 @@ export default function CreateProfile({
} else {
title = 'Create profile'
}
- handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING)
+ handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING, setPopup)
}
const handleCreateProfile = useCallback(async () => {
@@ -74,7 +75,7 @@ export default function CreateProfile({
setIsOpenCreateProfile(false)
setIsLoading(false)
} else {
- handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED)
+ handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED, setPopup)
setIsOpenCreateProfile(false)
setIsLoading(false)
}
@@ -102,7 +103,7 @@ export default function CreateProfile({
setIsLoading(false)
handleOpenTutorial(true)
} else {
- handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED)
+ handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED, setPopup)
setIsOpenCreateProfile(false)
setIsLoading(false)
}
@@ -201,6 +202,7 @@ export default function CreateProfile({
)}
+ {popup}
)
}
diff --git a/components/worldmap/RefillStaminaModal.tsx b/components/worldmap/RefillStaminaModal.tsx
index bc3ab830..ac0ea04e 100644
--- a/components/worldmap/RefillStaminaModal.tsx
+++ b/components/worldmap/RefillStaminaModal.tsx
@@ -17,7 +17,6 @@ import {
Wrap,
WrapItem,
Text,
- useToast,
Link,
useDisclosure,
} from '@chakra-ui/react'
@@ -25,6 +24,8 @@ import { fetchAmountItemByTrait } from 'utils/blackSmithContract'
import { refillStamina } from 'utils/professionContract'
import { ExternalLinkIcon } from '@chakra-ui/icons'
import LoadingModal from '@components/LoadingModal'
+import { useRouter } from 'next/router'
+import Popup from '@components/Popup'
type Props = {
isOpen: boolean
@@ -41,7 +42,8 @@ function RefillStaminaModal(props: Props) {
} = useDisclosure()
const [amountSushi, setAmountSushi] = useState(0)
const [success, setSuccess] = useState(false)
- const toast = useToast()
+ const [popup, setPopup] = useState(null)
+ const router = useRouter()
const handleUseSushi = useCallback(async () => {
if (success) {
@@ -53,13 +55,14 @@ function RefillStaminaModal(props: Props) {
onToggleLoading()
const availableSushi = await fetchAmountItemByTrait(4)
if (availableSushi?.length < amountSushi) {
- toast({
- title: 'Recover stamina',
- description: 'Not enough sushi to recover stamina',
- duration: 10000,
- isClosable: true,
- status: 'warning',
- })
+ setPopup( { router.push('foodcourt') }}
+ />)
onClose()
return
}
@@ -67,20 +70,19 @@ function RefillStaminaModal(props: Props) {
await refillStamina(
availableSushi?.slice(0, amountSushi).map((v) => `${v}`),
(txHash) => {
- toast({
- title: 'Recover stamina transaction is executing',
- description: (
-
- Transaction detail
-
- ),
- duration: 10000,
- isClosable: true,
- status: 'info',
- })
+ setPopup(
+ Transaction detail
+ }
+ actionContent="Close"
+ setIsOpen={setPopup}
+ action={() => { setPopup(null) }}
+ />)
}
)
onSuccess()
@@ -89,7 +91,7 @@ function RefillStaminaModal(props: Props) {
} finally {
onClose()
}
- }, [amountSushi, onClose, onSuccess, onToggleLoading, success, toast])
+ }, [amountSushi, onClose, onSuccess, onToggleLoading, success, popup])
const handleChangeAmountSushi = useCallback((_: string, value: number) => {
setAmountSushi(value)
@@ -210,6 +212,7 @@ function RefillStaminaModal(props: Props) {
+ {popup}
>
)
}
diff --git a/hooks/useTransactionState.tsx b/hooks/useTransactionState.tsx
index eb166706..ead0065d 100644
--- a/hooks/useTransactionState.tsx
+++ b/hooks/useTransactionState.tsx
@@ -1,6 +1,6 @@
import { useCallback, useMemo } from 'react'
-import { useToast } from '@chakra-ui/react'
import { ExternalLinkIcon } from '@chakra-ui/icons'
+import Popup from '@components/Popup'
export enum TRANSACTION_STATE {
FAILED = 0,
@@ -10,8 +10,6 @@ export enum TRANSACTION_STATE {
}
function useTransactionState() {
- const toast = useToast()
-
const blockExplorer = useMemo(() => {
const chainId = window?.ethereum?.chainId
switch (chainId) {
@@ -36,29 +34,28 @@ function useTransactionState() {
}, [])
const handleTxStateChange = useCallback(
- (title, txHash, txResult: TRANSACTION_STATE) => {
- toast.closeAll()
+ (title, txHash, txResult: TRANSACTION_STATE, setPopup) => {
switch (txResult) {
case TRANSACTION_STATE.FAILED:
- return toast({
- title: title + ' transaction is failed',
- description: (
+ return setPopup(
- Transaction detail
-
- ),
- duration: 10000,
- isClosable: true,
- status: 'error',
- })
+ />
+ )}
+ actionContent="Close"
+ setIsOpen={setPopup}
+ action={() => { setPopup(null) }}
+ />)
case TRANSACTION_STATE.SUCCESSFUL:
- return toast({
- title: title + ' transaction is successful',
- description: (
+ return setPopup(
Transaction detail
- ),
- duration: 10000,
- isClosable: true,
- status: 'success',
- })
-
+ )}
+ actionContent="Close"
+ setIsOpen={setPopup}
+ action={() => { setPopup(null) }}
+ />)
case TRANSACTION_STATE.WAITING:
- return toast({
- title: title + ' transaction is excuting',
- duration: 100000,
- description: (
+ return setPopup(
Transaction detail
- ),
- status: 'info',
- containerStyle: {
- zIndex: 999999,
- },
- })
-
+ )}
+ actionContent="Close"
+ setIsOpen={setPopup}
+ action={() => { setPopup(null) }}
+ />)
case TRANSACTION_STATE.NOT_EXECUTED:
- return toast({
- title: title + ' transaction is failed to execute',
- duration: 10000,
- isClosable: true,
- status: 'error',
- })
+ return setPopup( { setPopup(null) }}
+ />)
}
},
- [blockExplorer, toast]
+ [blockExplorer]
)
return handleTxStateChange
diff --git a/pages/castle/shop/index.tsx b/pages/castle/shop/index.tsx
index 78161aae..077848fb 100644
--- a/pages/castle/shop/index.tsx
+++ b/pages/castle/shop/index.tsx
@@ -28,18 +28,19 @@ function Shop() {
const [fetchPricesInterval, setFetchPricesInterval] = useState(null)
const [isLoading, setIsLoading] = useState(false)
const handleTxStateChange = useTransactionState()
+ const [popup, setPopup] = useState(null)
const mintProfessionsNFT = async (trait) => {
const title = 'Purchase NFT card'
setIsLoading(true)
const data = await mintProfessionNFT(trait, (txHash) => {
- handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING)
+ handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING, setPopup)
})
if (data) {
- handleTxStateChange(title, data.transactionHash, data.status)
+ handleTxStateChange(title, data.transactionHash, data.status, setPopup)
await fetchNFTAmount()
} else {
- handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED)
+ handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED, setPopup)
}
setIsLoading(false)
}
@@ -171,6 +172,7 @@ function Shop() {
+ {popup}
)
}
diff --git a/pages/foodcourt/index.tsx b/pages/foodcourt/index.tsx
index 6e9e27f9..03ad3d2d 100644
--- a/pages/foodcourt/index.tsx
+++ b/pages/foodcourt/index.tsx
@@ -37,6 +37,7 @@ export default function FoodCourt() {
const [buyDetail, setBuyDetail] = useState({})
const [isLoading, setIsLoading] = useState(false)
const handleTxStateChange = useTransactionState()
+ const [popup, setPopup] = useState(null)
const handleGetSushiList = async () => {
const data = await getListingIDs(false)
@@ -113,14 +114,14 @@ export default function FoodCourt() {
const title = `Cancel listing item in Food Court`
setIsLoading(true)
const data = await cancelListingItem(item?.id, (txHash) => {
- handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING)
+ handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING, setPopup)
})
setIsLoading(false)
if (data) {
- handleTxStateChange(title, data.transactionHash, data.status)
+ handleTxStateChange(title, data.transactionHash, data.status, setPopup)
handleGetMyList()
} else {
- handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED)
+ handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED, setPopup)
}
},
[handleTxStateChange]
@@ -135,17 +136,17 @@ export default function FoodCourt() {
id,
listIds,
(txHash) => {
- handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING)
+ handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING, setPopup)
},
(error) => {
- handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED)
+ handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED, setPopup)
setIsLoading(false)
}
)
if (data) {
setIsLoading(false)
- handleTxStateChange(title, data.transactionHash, data.status)
+ handleTxStateChange(title, data.transactionHash, data.status, setPopup)
if (isItemBoard === 'sushi') {
handleGetSushiList()
} else {
@@ -154,7 +155,7 @@ export default function FoodCourt() {
return data
} else {
setIsLoading(false)
- handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED)
+ handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED, setPopup)
}
},
[handleTxStateChange, isItemBoard]
@@ -296,6 +297,7 @@ export default function FoodCourt() {
+ {popup}
>
)
}
diff --git a/pages/professions/supplier/index.tsx b/pages/professions/supplier/index.tsx
index fd239939..15f4e4eb 100644
--- a/pages/professions/supplier/index.tsx
+++ b/pages/professions/supplier/index.tsx
@@ -29,6 +29,7 @@ function Supplier() {
const [typeModal, setTypeModal] = useState(TYPE_OF_MODAL.START)
const [isLoading, setIsLoading] = useState(false)
const handleTxStateChange = useTransactionState()
+ const [popup, setPopup] = useState(null)
const getListItemByTrait = useCallback(async () => {
const data = await getNFTsByTrait(1)
@@ -64,13 +65,13 @@ function Supplier() {
setIsLoading(true)
const data = await makeMultiSushi(listFishBurn, (txHash) => {
- handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING)
+ handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING, setPopup)
})
if (data) {
- handleTxStateChange(title, data.transactionHash, data.status)
+ handleTxStateChange(title, data.transactionHash, data.status, setPopup)
} else {
- handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED)
+ handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED, setPopup)
}
setIsLoading(false)
@@ -92,16 +93,16 @@ function Supplier() {
const listSushiSell = []
listSushiSell.push(parseInt(listSushi[0]))
const data = await listMultiItems(listSushiSell, valueSushi, (txHash) => {
- handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING)
+ handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING, setPopup)
})
if (data) {
- handleTxStateChange(title, data.transactionHash, data.status)
+ handleTxStateChange(title, data.transactionHash, data.status, setPopup)
setTypeModal(TYPE_OF_MODAL.FINISH)
getListSushi()
setIsLoading(false)
} else {
setIsLoading(false)
- handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED)
+ handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED, setPopup)
}
},
[getApprovedStatus, getListSushi, listSushi]
@@ -149,6 +150,7 @@ function Supplier() {
/>
{isLoading ? : null}
+ {popup}
)
}
diff --git a/pages/workshop/index.tsx b/pages/workshop/index.tsx
index 6b8731eb..aab15c1b 100644
--- a/pages/workshop/index.tsx
+++ b/pages/workshop/index.tsx
@@ -41,6 +41,7 @@ export default function WorkShop() {
const [isLoading, setIsLoading] = useState(false)
const inventoryRef = useRef()
const handleTxStateChange = useTransactionState()
+ const [popup, setPopup] = useState(null)
const handleGetHammerList = async () => {
const data = await getListingIDs(false)
@@ -81,13 +82,13 @@ export default function WorkShop() {
(item) => async () => {
const title = `Cancel listing item in Workshop`
const data = await cancelListingItem(item?.id, (txHash) => {
- handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING)
+ handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING, setPopup)
})
if (data) {
- handleTxStateChange(title, data.transactionHash, data.status)
+ handleTxStateChange(title, data.transactionHash, data.status, setPopup)
handleGetMyList()
} else {
- handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED)
+ handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED, setPopup)
}
},
[]
@@ -125,15 +126,15 @@ export default function WorkShop() {
id,
listIds,
(txHash) => {
- handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING)
+ handleTxStateChange(title, txHash, TRANSACTION_STATE.WAITING, setPopup)
},
(error) => {
- handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED)
+ handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED, setPopup)
setIsLoading(false)
}
)
if (data) {
- handleTxStateChange(title, data.transactionHash, data.status)
+ handleTxStateChange(title, data.transactionHash, data.status, setPopup)
setIsLoading(false)
if (isItemBoard === 'ore') {
handleGetOreList()
@@ -143,7 +144,7 @@ export default function WorkShop() {
return data
} else {
setIsLoading(false)
- handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED)
+ handleTxStateChange(title, '', TRANSACTION_STATE.NOT_EXECUTED, setPopup)
}
},
[isItemBoard]
@@ -296,6 +297,7 @@ export default function WorkShop() {
+ {popup}
>
)
}
diff --git a/public/images/popup/background-2.png b/public/images/popup/background-2.png
new file mode 100644
index 0000000000000000000000000000000000000000..4ed8e16a4a587bf831ab5338c3e7c60ed8edacf9
GIT binary patch
literal 1461
zcmeAS@N?(olHy`uVBq!ia0y~yV7vpwA{=Z$kw%Gj9R>#08c!F;kcv5PZ##C$l*+U{
zj90VT>149*h_rsVWU6BFN3-F;`hOT%NUet!8F^PnOvFK2y!`m?)ljTs(X>#Yz@EaF@
z`sFCj`u*9NJF{o<^Kdczzdd>8&!RNBIsYGB-1&Wa`m@(>88)&um~WQ)_4nG9)9L9I
zukWmUckYbrW2OU+b4*KP-~KCZt@h4geDL61POt4>{_?v#Utgculb+6CvE#Y%=YP8n
z?bY4Juwiz#@#m8lzrEmR*f3vOdxyNF1VdSAE$jDHy^IOr@7Fwt+i1w}=GBiA`xrLZ
zA7pK4c);Y~P{635u!BKBAcld1Lyv)lMVx`DiJO6ORC+X6Mw7!3%m!fv^~NT^T%N-E
zy%m)0^??H5Y=2zzj=LFKL#%Do!M}NF^KMEqlzpt(TE_Z4C2ijZV7c(<^UR-*-)vk^
zI<@-#IfjCO@7s^<`y}%&-1u|vT*e0q`|jSVdR0^Kf7Z&ZOz4#ecPM!&z)&EF3wH6x6PX2&++-Udjsvyo;mzh{Yh#4mHlbY^2>^C
V$_4&k?f@3Y44$rjF6*2UngE-5tP21D
literal 0
HcmV?d00001
diff --git a/public/images/popup/background-3.png b/public/images/popup/background-3.png
new file mode 100644
index 0000000000000000000000000000000000000000..19859c773ce82f62fa5d4ebeed46bd30a2d86cf6
GIT binary patch
literal 19209
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