MoonMiners/src/app/Components/StakingSource.tsx
Emil Andreas Nielsen 801532759d
Feature/resource yields (#3)
* Add  handleSetUpgrade function and other related stuff

* Fix select drill to upgrade

* Small refactor - apply drill on upgrade

* Refactor types - WIP

* Add handleBuy function, sort storeItems by owned

* Add tiers to storeItems

* Show equipment on moon, add radiobutton to select

* Modify types

* Cleanup some code and comments  etc.

* Add claim function to increment user balance and decrement well

* Add API to get data

* Set inventoryItem and activeTier in state

* Update stakingSource whenever inventoryItems are updated

* Disable upgrade button when mining is active

* Add initial implementation of lightbox

---------

Co-authored-by: Nico Li <nilindenau@gmail.com>
2023-02-24 13:37:07 +07:00

188 lines
5.9 KiB
TypeScript

import React, { useState, useEffect } from "react";
import { IInventoryItem, IStakingSource, IClaimableResource } from "typings";
import CardLayout from "../Layouts/CardLayout";
const StakingSource = (props: {
stakingSource: IStakingSource;
inventoryItems: IInventoryItem[] | null | undefined;
handleAddItem: (
inventoryItem: IInventoryItem,
stakingSource: IStakingSource
) => void;
claimResource: (
stakingSource: IStakingSource,
claimedResource: IClaimableResource
) => boolean;
}) => {
const [isMining, setIsMining] = useState(false);
const [miningTime, setMiningTime] = useState(0);
const [claimableResource, setClaimableResource] =
useState<IClaimableResource | null>(null);
const [activeInventoryItem, setActiveInventoryItem] =
useState<IInventoryItem | null>(null);
const [activeTier, setActiveTier] = useState(0);
useEffect(() => {
if (isMining && activeInventoryItem) {
const intervalId = setInterval(() => {
setMiningTime((prev) => prev - 1);
}, 1000);
if (miningTime === 0) {
setIsMining(false);
// Get a random resource from available wells
let randResource =
props.stakingSource.resourceWells[
Math.floor(Math.random() * props.stakingSource.resourceWells.length)
];
// Get yield based on the tier
const totalYield = activeInventoryItem.storeItem.tiers[activeTier].tier;
// Construct the claimableResource
const claimableResource: IClaimableResource = {
resourceType: randResource.resourceType,
balance: totalYield,
};
setClaimableResource(claimableResource);
clearInterval(intervalId);
setMiningTime(activeInventoryItem.storeItem.timeToClaim);
}
return () => {
clearInterval(intervalId);
};
}
}, [isMining, miningTime]);
const isChecked = (item: IInventoryItem) => {
if (!props.stakingSource.inventoryItem) return false;
return item.id === props.stakingSource.inventoryItem.id;
};
const handleStartMining = () => {
if (props.stakingSource.inventoryItem) {
setActiveInventoryItem(props.stakingSource.inventoryItem);
setMiningTime(props.stakingSource.inventoryItem.storeItem.timeToClaim);
setActiveTier(props.stakingSource.inventoryItem.currentTierIndex);
setIsMining(true);
}
};
const handleClaim = () => {
if (!claimableResource) return;
if (props.claimResource(props.stakingSource, claimableResource)) {
setClaimableResource(null);
}
};
const renderButton = () => {
if (props.stakingSource.inventoryItem) {
if (!claimableResource && !isMining) {
return (
<button
onClick={() => handleStartMining()}
className="bg-slate-100 text-slate-900 px-4 py-2 rounded-lg font-bold text-center"
>
Start Mining
</button>
);
}
}
if (isMining)
return (
<button className="bg-slate-400 text-slate-600 px-4 py-2 rounded-lg font-bold w-28 text-center cursor-not-allowed">
{miningTime}
</button>
);
if (claimableResource) {
return (
<button
onClick={() => handleClaim()}
className="bg-slate-100 text-slate-900 px-4 py-2 rounded-lg font-bold text-center"
>
Claim
</button>
);
}
};
return (
<CardLayout>
<h3 className="text-xl font-bold mb-2">{props.stakingSource.name}</h3>
<p className="text-sm">{props.stakingSource.description}</p>
<div className="flex gap-4">
<div className="flex-1">
<p className="font-bold mt-4">Resources</p>
<ul className="list-none">
{props.stakingSource.resourceWells.map((resourceWell, id) => (
<li key={id}>
<span>{resourceWell.resourceType.name}</span>{" "}
<span className="text-teal-500 font-bold">
{resourceWell.supply}
</span>
</li>
))}
</ul>
</div>
<div className="flex-1">
<p className="font-bold mt-4">Status</p>
<ul className="list-none">
<li className="flex">
<span className="text-green-600 mr-1">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth="1.5"
stroke="currentColor"
className="w-6 h-6"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</span>
Operational
</li>
</ul>
<p className="font-bold mt-4">Equipment</p>
{!isMining
? props.inventoryItems &&
props.inventoryItems.map((item, id) => (
<div key={id}>
<input
type="radio"
name="inventoryItem"
value={item.id}
checked={isChecked(item)}
onChange={() =>
props.handleAddItem(item, props.stakingSource)
}
/>
<label htmlFor={item.id.toString()}>
{item.storeItem.name}{" "}
<span className="bg-white text-black rounded-full px-2">
{item.currentTierIndex + 1}
</span>
</label>
</div>
))
: props.stakingSource.inventoryItem && (
<p>{props.stakingSource.inventoryItem.storeItem.name}</p>
)}
</div>
</div>
{renderButton()}
</CardLayout>
);
};
export default StakingSource;