244 lines
8.5 KiB
TypeScript
244 lines
8.5 KiB
TypeScript
import React, { useState, useEffect } from "react";
|
|
import { IInventoryItem, IStakingSource, IStake, IOption } from "typings";
|
|
import {
|
|
calculateRemainingTime,
|
|
getObjectFromArray,
|
|
} from "../../../utils/helpers";
|
|
import SelectDropdown from "../SelectDropdown";
|
|
import Image from "next/image";
|
|
|
|
const StakingSource = (props: {
|
|
stakingSource: IStakingSource;
|
|
inventoryItems: IInventoryItem[] | null | undefined;
|
|
claimStake: (stakingEventId: number) => void;
|
|
startStake: (
|
|
inventoryItemId: string,
|
|
storeItemId: number,
|
|
wellId: string
|
|
) => void;
|
|
}) => {
|
|
const [activeStakes, setActiveStakes] = useState<IStake[]>([]);
|
|
const [selectedInventoryItemId, setSelectedInventoryItemId] = useState<
|
|
string | null
|
|
>(null);
|
|
const [selectedStoreItemId, setSelectedStoreItemId] = useState<number | null>(
|
|
null
|
|
);
|
|
const [selectedWellId, setSelectedWellId] = useState<string | null>(null);
|
|
const [showInfo, setShowInfo] = useState(false);
|
|
|
|
// Check if claimable every second
|
|
useEffect(() => {
|
|
const updatedActiveStakes = props.stakingSource.activeStakes.map(
|
|
(stake) => {
|
|
const remainingTime = calculateRemainingTime(
|
|
stake.startTime,
|
|
stake.durationInMins
|
|
);
|
|
|
|
const obj = {
|
|
...stake,
|
|
remainingTime: remainingTime,
|
|
};
|
|
|
|
return obj;
|
|
}
|
|
);
|
|
|
|
const intervalId = setInterval(() => {
|
|
setActiveStakes(updatedActiveStakes);
|
|
}, 1000);
|
|
|
|
return () => {
|
|
clearInterval(intervalId);
|
|
};
|
|
});
|
|
|
|
const handleStartMining = () => {
|
|
if (selectedInventoryItemId && selectedWellId && selectedStoreItemId) {
|
|
props.startStake(
|
|
selectedInventoryItemId,
|
|
selectedStoreItemId,
|
|
selectedWellId
|
|
);
|
|
}
|
|
};
|
|
|
|
const handleClaim = (stakingEventId: number) => {
|
|
props.claimStake(stakingEventId);
|
|
};
|
|
|
|
const handleSelectChange = (
|
|
wellId: string,
|
|
inventoryItemId: string,
|
|
storeitemId: number
|
|
) => {
|
|
setSelectedWellId(wellId);
|
|
setSelectedStoreItemId(storeitemId);
|
|
setSelectedInventoryItemId(inventoryItemId);
|
|
};
|
|
|
|
const Countdown = (props: { remainingTime: number }) => {
|
|
const hours = Math.floor((props.remainingTime / (1000 * 60 * 60)) % 24)
|
|
.toString()
|
|
.padStart(2, "0");
|
|
const minutes = Math.floor((props.remainingTime / (1000 * 60)) % 60)
|
|
.toString()
|
|
.padStart(2, "0");
|
|
const seconds = Math.floor((props.remainingTime / 1000) % 60)
|
|
.toString()
|
|
.padStart(2, "0");
|
|
return (
|
|
<span className="font-bold">
|
|
{hours} : {minutes} : {seconds}
|
|
</span>
|
|
);
|
|
};
|
|
|
|
const RenderButtonOrCountdown = (props: { stake: IStake }) => {
|
|
if (!props.stake.remainingTime) return <p>Error</p>;
|
|
|
|
if (props.stake.remainingTime <= 0) {
|
|
return (
|
|
<button
|
|
onClick={() => handleClaim(props.stake.id)}
|
|
className="bg-slate-100 text-slate-900 px-4 py-2 rounded-lg font-bold text-center"
|
|
>
|
|
Claim
|
|
</button>
|
|
);
|
|
} else {
|
|
return <Countdown remainingTime={props.stake.remainingTime} />;
|
|
}
|
|
};
|
|
|
|
const isActive = (item: IInventoryItem): boolean => {
|
|
return props.stakingSource.activeStakes.some(
|
|
(obj) => obj.inventoryItemId === item.id
|
|
);
|
|
};
|
|
|
|
return (
|
|
<div className="flex justify-center items-center">
|
|
<div className="relative group">
|
|
<Image
|
|
src="/assets/moon_1.png"
|
|
alt="Moon"
|
|
width={props.stakingSource.size}
|
|
height={props.stakingSource.size}
|
|
onClick={() => setShowInfo(!showInfo)}
|
|
className="hover:cursor-pointer"
|
|
/>
|
|
{showInfo && (
|
|
<div className="z-10 fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center">
|
|
<div className="w-full h-full md:h-auto max-w-md max-h-full overflow-y-auto">
|
|
<div className="relative h-full md:h-auto text-white bg-gradient-to-tr from-purple-600 via-blue-600 to-indigo-700 h-auto md:rounded-xl h-auto p-1">
|
|
<div className="h-full md:h-auto bg-slate-900 md:rounded-xl p-4">
|
|
<button
|
|
onClick={() => {
|
|
setShowInfo(!showInfo);
|
|
}}
|
|
className="text-white absolute -right-0 mr-4"
|
|
>
|
|
<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="M6 18L18 6M6 6l12 12"
|
|
/>
|
|
</svg>
|
|
</button>
|
|
<h3 className="text-3xl font-bold mb-2">
|
|
{props.stakingSource.name}
|
|
</h3>
|
|
<p className="text-sm">{props.stakingSource.description}</p>
|
|
<div className="flex-1">
|
|
<p className="font-bold mt-4 mb-2">Active Drills</p>
|
|
{activeStakes &&
|
|
activeStakes.map((stake, id) => (
|
|
<div
|
|
key={id}
|
|
className="border border-white rounded-xl p-3 mb-2 bg-black/20"
|
|
>
|
|
<p>
|
|
<span className="font-bold">Drill: </span>
|
|
{props.inventoryItems &&
|
|
getObjectFromArray(
|
|
props.inventoryItems,
|
|
"id",
|
|
stake.inventoryItemId
|
|
)?.storeItem.name}
|
|
</p>
|
|
<p>
|
|
<span className="font-bold">Resource: </span>
|
|
{stake.resourceType}
|
|
</p>
|
|
<p className="mb-2">
|
|
<span className="font-bold">Yield: </span>
|
|
{stake.stakeAmount}
|
|
</p>
|
|
<RenderButtonOrCountdown stake={stake} />
|
|
</div>
|
|
))}
|
|
</div>
|
|
<p className="font-bold mt-4 mb-2">Inactive Drills</p>
|
|
{props.inventoryItems &&
|
|
props.inventoryItems.map(
|
|
(item, id) =>
|
|
!isActive(item) && (
|
|
<div
|
|
key={id}
|
|
className="border border-white rounded-xl p-3 mb-2 bg-black/20"
|
|
>
|
|
<p className="font-bold">{item.storeItem.name}</p>
|
|
<p className="mt-2">Select Resource</p>
|
|
<div className="flex">
|
|
<SelectDropdown
|
|
options={props.stakingSource.resourceWells.map(
|
|
(well): IOption => ({
|
|
value: well.id,
|
|
label: well.resourceType,
|
|
})
|
|
)}
|
|
onChange={(value) =>
|
|
handleSelectChange(
|
|
value,
|
|
item.id,
|
|
item.storeItem.id
|
|
)
|
|
}
|
|
isActive={selectedInventoryItemId === item.id}
|
|
/>
|
|
{selectedInventoryItemId === item.id ? (
|
|
<button
|
|
onClick={handleStartMining}
|
|
className="bg-slate-100 text-slate-900 px-4 py-2 rounded-lg font-bold w-28 text-center ml-2"
|
|
>
|
|
Activate
|
|
</button>
|
|
) : (
|
|
<></>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default StakingSource;
|