* 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>
188 lines
5.9 KiB
TypeScript
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;
|