Add loading wheels

This commit is contained in:
Emil Nielsen 2023-05-02 07:51:38 +07:00
parent b965371fe5
commit a7c03a2703
7 changed files with 173 additions and 128 deletions

View File

@ -3,6 +3,7 @@ import React, { useEffect, useState } from "react";
import { IResourceAccount, IConversionPair, IGameConfig } from "typings"; import { IResourceAccount, IConversionPair, IGameConfig } from "typings";
import { resourceToFc, resourceToBg } from "../../../utils/helpers"; import { resourceToFc, resourceToBg } from "../../../utils/helpers";
import ResourceModal from "./ResourceModal"; import ResourceModal from "./ResourceModal";
import { BiLoaderAlt } from "react-icons/bi";
const ResourceAccount = (props: { const ResourceAccount = (props: {
account: IResourceAccount; account: IResourceAccount;
@ -14,6 +15,7 @@ const ResourceAccount = (props: {
IConversionPair | undefined IConversionPair | undefined
>(undefined); >(undefined);
const [conversionRate, setConversionRate] = useState<number>(0); const [conversionRate, setConversionRate] = useState<number>(0);
const [isLoading, setIsLoading] = useState(false);
const handleConversionPair = (amount: number, resourceType: string) => { const handleConversionPair = (amount: number, resourceType: string) => {
const updatedPair = { const updatedPair = {
@ -31,9 +33,20 @@ const ResourceAccount = (props: {
return rate; return rate;
}; };
const handleSellResource = () => { const handleSellResource = async () => {
conversionPair && props.sellResource([conversionPair]); if (conversionPair) {
setIsLoading(true);
try {
await props.sellResource([conversionPair]);
} catch (error) {
// Show error here
} finally {
setShowModal(false); setShowModal(false);
}
conversionPair && props.sellResource([conversionPair]);
setIsLoading(false);
setShowModal(false);
}
}; };
useEffect(() => { useEffect(() => {
@ -67,7 +80,12 @@ const ResourceAccount = (props: {
/> />
</svg> </svg>
</button> </button>
<div className="md:h-auto max-w-md max-h-full overflow-y-auto"> <div className="relative md:h-auto max-w-md max-h-full overflow-y-auto">
{isLoading && (
<div className="absolute bg-white/75 text-white w-full h-full grid justify-center items-center rounded-xl">
<BiLoaderAlt className="animate-spin w-6 h-6" />
</div>
)}
<ResourceModal <ResourceModal
resourceAccount={props.account} resourceAccount={props.account}
conversionPair={conversionPair} conversionPair={conversionPair}

View File

@ -2,6 +2,8 @@ import React, { useState, useEffect } from "react";
import { IInventoryItem, IStake, IUpgrade } from "typings"; import { IInventoryItem, IStake, IUpgrade } from "typings";
import CardLayout from "../../Layouts/CardLayout"; import CardLayout from "../../Layouts/CardLayout";
import Image from "next/image"; import Image from "next/image";
import { BiLoaderAlt } from "react-icons/bi";
const InventoryItem = (props: { const InventoryItem = (props: {
inventoryItem: IInventoryItem; inventoryItem: IInventoryItem;
stakes: IStake[] | null; stakes: IStake[] | null;
@ -19,6 +21,23 @@ const InventoryItem = (props: {
setCurrentUpgrade(currentUpdade); setCurrentUpgrade(currentUpdade);
}, [props.inventoryItem]); }, [props.inventoryItem]);
const [isLoading, setIsLoading] = useState(false);
const handleUpgradeInventoryItem = async () => {
setIsLoading(true);
try {
// Create the source
await props.upgradeInventoryItem(
props.inventoryItem.id,
props.inventoryItem.storeItem.id
);
} catch (error) {
// Handle error if needed (e.g., show a notification or log the error)
} finally {
setIsLoading(false);
}
};
const renderUpgradeButton = () => { const renderUpgradeButton = () => {
// If no staking source // If no staking source
if (!props.stakes) return "No staking source"; if (!props.stakes) return "No staking source";
@ -37,14 +56,14 @@ const InventoryItem = (props: {
// Show price // Show price
return ( return (
<> <>
{isLoading ? (
<button className="bg-green-600 rounded-full p-1">
<BiLoaderAlt className="animate-spin w-6 h-6" />
</button>
) : (
<button <button
onClick={() => onClick={() => handleUpgradeInventoryItem()}
props.upgradeInventoryItem( className="bg-green-600 rounded-full p-1"
props.inventoryItem.id,
props.inventoryItem.storeItem.id
)
}
className="bg-orange-600 rounded-full p-1"
> >
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@ -61,6 +80,7 @@ const InventoryItem = (props: {
/> />
</svg> </svg>
</button> </button>
)}
<span className="ml-1"> <span className="ml-1">
{`$${ {`$${
props.inventoryItem.storeItem.upgrades[currentTierIndex + 1].price props.inventoryItem.storeItem.upgrades[currentTierIndex + 1].price

View File

@ -6,6 +6,7 @@ import {
} from "../../../utils/helpers"; } from "../../../utils/helpers";
import SelectDropdown from "../SelectDropdown"; import SelectDropdown from "../SelectDropdown";
import Image from "next/image"; import Image from "next/image";
import { BiLoaderAlt } from "react-icons/bi";
const StakingSource = (props: { const StakingSource = (props: {
stakingSource: IStakingSource; stakingSource: IStakingSource;
@ -25,7 +26,7 @@ const StakingSource = (props: {
null null
); );
const [selectedWellId, setSelectedWellId] = useState<string | null>(null); const [selectedWellId, setSelectedWellId] = useState<string | null>(null);
const [showInfo, setShowInfo] = useState(false); const [isLoading, setIsLoading] = useState(false);
// Check if claimable every second // Check if claimable every second
useEffect(() => { useEffect(() => {
@ -54,18 +55,33 @@ const StakingSource = (props: {
}; };
}); });
const handleStartMining = () => { const handleStartMining = async () => {
if (selectedInventoryItemId && selectedWellId && selectedStoreItemId) { if (selectedInventoryItemId && selectedWellId && selectedStoreItemId) {
props.startStake( setIsLoading(true);
try {
await props.startStake(
selectedInventoryItemId, selectedInventoryItemId,
selectedStoreItemId, selectedStoreItemId,
selectedWellId selectedWellId
); );
} catch (error) {
// Handle error if needed (e.g., show a notification or log the error)
} finally {
setIsLoading(false);
}
} }
}; };
const handleClaim = (stakingEventId: number) => { const handleClaim = async (stakingEventId: number) => {
props.claimStake(stakingEventId); setIsLoading(true);
try {
await props.claimStake(stakingEventId);
} catch (error) {
// Handle error if needed (e.g., show a notification or log the error)
} finally {
setIsLoading(false);
}
}; };
const handleSelectChange = ( const handleSelectChange = (
@ -129,8 +145,13 @@ const StakingSource = (props: {
className="mr-4" className="mr-4"
/> />
<div className="max-w-md text-white bg-gradient-to-tr from-purple-600 via-blue-600 to-indigo-700 md:rounded-xl p-1"> <div className="max-w-md text-white bg-gradient-to-tr from-purple-600 via-blue-600 to-indigo-700 md:rounded-xl p-1">
<div className="bg-slate-900 md:rounded-xl p-4"> <div className="relative bg-slate-900 md:rounded-xl h-full">
<div className=""> {isLoading && (
<div className="absolute bg-slate-900 w-full h-full grid justify-center items-center rounded-xl">
<BiLoaderAlt className="animate-spin w-6 h-6" />
</div>
)}
<div className="p-4">
<h3 className="text-3xl font-bold mb-2"> <h3 className="text-3xl font-bold mb-2">
{props.stakingSource.name}{" "} {props.stakingSource.name}{" "}
<span> <span>
@ -144,10 +165,9 @@ const StakingSource = (props: {
</h3> </h3>
<p className="text-sm">{props.stakingSource.description}</p> <p className="text-sm">{props.stakingSource.description}</p>
</div> </div>
<h3 className="mt-4 mb-2 text-2xl font-bold">Inventory</h3> <div className="p-4">
<div className="">
{activeStakes.length > 0 && ( {activeStakes.length > 0 && (
<div className=""> <>
{activeStakes.map((stake, id) => ( {activeStakes.map((stake, id) => (
<div <div
key={id} key={id}
@ -172,7 +192,7 @@ const StakingSource = (props: {
<RenderButtonOrCountdown stake={stake} /> <RenderButtonOrCountdown stake={stake} />
</div> </div>
))} ))}
</div> </>
)} )}
{props.inventoryItems && ( {props.inventoryItems && (
<div className=""> <div className="">

View File

@ -1,7 +1,8 @@
"use client"; "use client";
import React from "react"; import React, { useState } from "react";
import { IInventoryItem, IStakingSource } from "typings"; import { IInventoryItem, IStakingSource } from "typings";
import StakingSource from "./StakingSource"; import StakingSource from "./StakingSource";
import { BiLoaderAlt } from "react-icons/bi";
const StakingSourcesView = (props: { const StakingSourcesView = (props: {
stakingSources: IStakingSource[] | null; stakingSources: IStakingSource[] | null;
@ -14,14 +15,33 @@ const StakingSourcesView = (props: {
) => void; ) => void;
createStakingSource: () => void; createStakingSource: () => void;
}) => { }) => {
const [isLoading, setIsLoading] = useState(false);
const handleCreateStakingSource = async () => {
setIsLoading(true);
try {
// Create the source
await props.createStakingSource();
} catch (error) {
// Handle error if needed (e.g., show a notification or log the error)
} finally {
setIsLoading(false);
}
};
return ( return (
<div className="bg-gradient-to-tr from-purple-600 via-blue-600 to-indigo-700 h-auto p-1 rounded-xl h-auto p-1 rounded-xl col-span-5"> <div className="bg-gradient-to-tr from-purple-600 via-blue-600 to-indigo-700 h-auto p-1 rounded-xl h-auto p-1 rounded-xl col-span-5">
<div className="bg-slate-900 p-8 rounded-xl h-full"> <div className="bg-slate-900 p-8 rounded-xl h-full">
<div className="flex items-center mb-4"> <div className="flex items-center mb-4">
<h2 className="text-3xl text-white font-bold">Your Moons</h2> <h2 className="text-3xl text-white font-bold">Your Moons</h2>
{isLoading ? (
<button className="bg-green-600 text-white rounded-full ml-2 p-1 inline">
<BiLoaderAlt className="animate-spin w-6 h-6" />
</button>
) : (
<button <button
className="bg-green-600 text-white rounded-full ml-2 p-1 inline" className="bg-green-600 text-white rounded-full ml-2 p-1 inline"
onClick={() => props.createStakingSource()} onClick={() => handleCreateStakingSource()}
> >
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@ -38,6 +58,7 @@ const StakingSourcesView = (props: {
/> />
</svg> </svg>
</button> </button>
)}
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8"> <div className="grid grid-cols-1 md:grid-cols-2 gap-8">
{props.stakingSources ? ( {props.stakingSources ? (

View File

@ -1,58 +0,0 @@
"use client";
import React from "react";
import { IInventoryItem, IStakingSource } from "typings";
import StakingSource from "./StakingSource";
const StakingSourcesView = (props: {
stakingSources: IStakingSource[] | null;
inventoryItems: IInventoryItem[] | null | undefined;
claimStake: (stakingEventId: number) => void;
startStake: (
inventoryItemId: number,
storeItemId: string,
wellId: number
) => void;
createStakingSource: () => void;
}) => {
return (
<div className="bg-slate-800 p-4 rounded-lg text-white col-span-5">
<div className="flex items-center mb-4">
<h2 className="text-3xl font-bold">Your Moons</h2>
<button
className="bg-green-600 rounded-full ml-2 p-1 inline"
onClick={() => props.createStakingSource()}
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={2}
stroke="currentColor"
className="w-6 h-6"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M12 4.5v15m7.5-7.5h-15"
/>
</svg>
</button>
</div>
<div className="grid grid-cols-3 gap-4">
{props.stakingSources &&
props.stakingSources.length > 0 &&
props.stakingSources.map((stakingSource, id) => (
<StakingSource
key={id}
stakingSource={stakingSource}
inventoryItems={props.inventoryItems}
claimStake={props.claimStake}
startStake={props.startStake}
/>
))}
</div>
</div>
);
};
export default StakingSourcesView;

View File

@ -1,13 +1,28 @@
"use client"; "use client";
import React from "react"; import React, { useState } from "react";
import { IStoreItem } from "typings"; import { IStoreItem } from "typings";
import CardLayout from "../../Layouts/CardLayout"; import CardLayout from "../../Layouts/CardLayout";
import Image from "next/image"; import Image from "next/image";
import { BiLoaderAlt } from "react-icons/bi";
const StoreItem = (props: { const StoreItem = (props: {
storeItem: IStoreItem; storeItem: IStoreItem;
buyStoreItem: (storeItemId: number) => void; buyStoreItem: (storeItemId: number) => void;
}) => { }) => {
const [isLoading, setIsLoading] = useState(false);
const handleBuyStoreItem = async () => {
setIsLoading(true);
try {
// Create the source
await props.buyStoreItem(props.storeItem.id);
} catch (error) {
// Handle error if needed (e.g., show a notification or log the error)
} finally {
setIsLoading(false);
}
};
return ( return (
<CardLayout> <CardLayout>
<div className="md:flex"> <div className="md:flex">
@ -15,12 +30,18 @@ const StoreItem = (props: {
<h3 className="text-2xl font-bold mb-2">{props.storeItem.name}</h3> <h3 className="text-2xl font-bold mb-2">{props.storeItem.name}</h3>
<p className="text-sm mb-3">{props.storeItem.description}</p> <p className="text-sm mb-3">{props.storeItem.description}</p>
<div className="py-4 my-2"> <div className="py-4 my-2">
{isLoading ? (
<button className="bg-green-600 text-white px-4 py-2 rounded-lg font-bold w-auto text-center">
<BiLoaderAlt className="animate-spin w-6 h-6" />
</button>
) : (
<button <button
onClick={() => props.buyStoreItem(props.storeItem.id)} onClick={() => handleBuyStoreItem()}
className="bg-green-600 text-white px-4 py-2 rounded-lg font-bold w-auto text-center" className="bg-green-600 text-white px-4 py-2 rounded-lg font-bold w-auto text-center"
> >
Buy | ${props.storeItem.price} Buy | ${props.storeItem.price}
</button> </button>
)}
</div> </div>
</div> </div>
<div className="relative object-contain w-48 h-48"> <div className="relative object-contain w-48 h-48">

View File

@ -338,7 +338,11 @@ export default function Home() {
return ( return (
<> <>
<Navbar setUserId={setUserId} /> <Navbar setUserId={setUserId} />
<p>Please login</p> <div className="grid justify-center items-center h-96">
<h1 className="text-3xl text-white">
Connect Your Wallet to Continue
</h1>
</div>
</> </>
); );
@ -346,7 +350,6 @@ export default function Home() {
return <p>Loading...</p>; return <p>Loading...</p>;
} }
console.log(storeItems);
return ( return (
<> <>
<Navbar setUserId={setUserId} /> <Navbar setUserId={setUserId} />