MoonMiners/src/app/page.tsx

367 lines
10 KiB
TypeScript

"use client";
import { useState, useEffect } from "react";
import InventoryItemView from "./Components/InventoryItemView";
import StakingSourcesView from "./Components/StakingSourcesView";
import BankAccountsView from "./Components/BankAccountsView";
import StoreItemView from "./Components/StoreItemView";
import ResourceStore from "./Components/ResourceStore";
import NotificationPopover from "./Components/NotificationPopover";
import { gameConfig } from "@/utils/gameLogic";
import {
IInventoryItem,
IStakingSource,
IBankAccount,
IStake,
Notification,
} from "typings";
import Navbar from "./Components/Navbar";
import NavbarVertical from "./Components/NavbarVertical";
export default function Home() {
const [inventoryItems, setInventoryItems] = useState<
IInventoryItem[] | null | undefined
>([]);
const [stakingSources, setStakingSources] = useState<IStakingSource[] | null>(
[]
);
const [bankAccount, setBankAccount] = useState<IBankAccount>();
const [userStakes, setUserStakes] = useState<IStake[]>([]);
const [lightBoxIsActive, setLightBoxIsActive] = useState(false);
const [userId, setUserId] = useState<string>("");
const [notification, setNotification] = useState<Notification | null>(null);
const [notificationTime, setNotificationTime] = useState(30);
const [storeItems, setStoreItems] = useState(gameConfig.store);
const [isLoading, setIsLoading] = useState(true);
const [activeComponent, setActiveComponent] = useState("stakingsourcesview");
const isOwned = (storeItemId: string) => {
if (inventoryItems && inventoryItems?.length > 0) {
return inventoryItems?.some((item) => item.storeItem.id == storeItemId);
} else {
return false;
}
};
const fetchInventoryItems = async () => {
const response = await fetch(`/api/user/${userId}/inventory-items`);
const DBInventoryItems = await response.json();
for (const invItem of DBInventoryItems.inventoryItems) {
invItem.storeItem = gameConfig.store.find(
(item) => item.id === invItem.storeItemId
);
}
// TODO Can you just return the array?
setInventoryItems(DBInventoryItems.inventoryItems);
};
const fetchStakingSources = async () => {
const response = await fetch(`/api/user/${userId}/staking-sources`);
const sources = await response.json();
// TODO Can you just return the array?
setStakingSources(sources.stakingSources);
};
const fetchStakes = async () => {
const response = await fetch(`/api/user/${userId}/stakes`);
const stakes = await response.json();
setUserStakes(
stakes.stakes.map((stake: IStake) => ({
...stake,
unclaimed: stake.unclaimed,
}))
);
};
const fetchBankAccount = async () => {
const response = await fetch(`/api/user/${userId}/bank-account`);
const bankAccount = await response.json();
setBankAccount(bankAccount);
};
useEffect(() => {
if (userId === "") return;
fetchBankAccount();
fetchStakingSources();
fetchInventoryItems();
fetchStakes();
setIsLoading(false);
}, [userId]);
// Update data
useEffect(() => {
const updatedStoreItems = storeItems.map((storeItem) => {
return {
...storeItem,
isOwned: isOwned(storeItem.id),
};
});
updatedStoreItems && setStoreItems(updatedStoreItems);
}, [inventoryItems]);
// Hide error automatically
useEffect(() => {
if (notification) {
const intervalId = setInterval(() => {
setNotificationTime((prev) => prev - 1);
}, 1000);
if (notificationTime === 0) {
setNotification(null);
clearInterval(intervalId);
setNotificationTime(30);
}
return () => {
clearInterval(intervalId);
};
}
}, [notification, notificationTime]);
const claimStake = async (stakingEventId: number) => {
const response = await fetch(`/api/user/${userId}/stakes/claim`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ stakingEventId: stakingEventId }),
});
if (!response.ok) {
const error = await response.text();
setNotification({ message: error, type: "Error" });
}
if (response.status == 200) {
const data = await response.json();
setNotification({
message: `You've successfully claimed`,
type: "Success",
});
fetchStakes();
fetchStakingSources();
fetchInventoryItems();
fetchBankAccount();
}
};
const startStake = async (
inventoryItemId: number,
storeItemId: string,
wellId: number
) => {
const response = await fetch(`/api/user/${userId}/stakes/start`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
inventoryItemId: inventoryItemId,
storeItemId,
wellId: wellId,
}),
});
if (!response.ok) {
const error = await response.text();
setNotification({ message: error, type: "Error" });
}
if (response.status == 200) {
const data = await response.json();
setNotification({
message: `You've successfully staked`,
type: "Success",
});
fetchStakes();
fetchStakingSources();
}
};
// Which object is it?
const sellResource = async (obj: any) => {
const response = await fetch(`/api/user/${userId}/bank-account`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
obj: obj,
}),
});
return await response.json();
};
const buyStoreItem = async (itemId: string) => {
console.log(`Buying item with id ${itemId}`);
try {
const response = await fetch(`/api/user/${userId}/inventory-items`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
storeItemId: itemId,
}),
});
if (!response.ok) {
const error = await response.text();
setNotification({ message: error, type: "Error" });
return;
}
const data = await response.json();
if (response.status == 200) {
// Return success message
setNotification({
message: "Item has been purchased",
type: "Success",
});
fetchInventoryItems();
}
} catch (error) {
if (error instanceof Error) {
setNotification({ message: error.message, type: "Error" });
} else {
setNotification({ message: "An unknown error occured", type: "Error" });
}
}
};
const upgradeInventoryItem = async (
inventoryItemId: number,
storeItemId: string
) => {
try {
const response = await fetch(`/api/user/${userId}/inventory-items`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
inventoryItemId: inventoryItemId,
storeItemId: storeItemId,
}),
});
if (!response.ok) {
const error = await response.text();
setNotification({ message: error, type: "Error" });
return;
}
const data = await response.json();
if (response.status == 200) {
// Return success message
setNotification({ message: "Item has been upgraded", type: "Success" });
fetchInventoryItems();
fetchBankAccount();
}
if (response.status == 400) {
// return error message
setNotification({ message: data.error, type: "Error" });
}
} catch (error) {
if (error instanceof Error) {
setNotification({ message: error.message, type: "Error" });
} else {
setNotification({ message: "An unknown error occured", type: "Error" });
}
}
};
const createStakingSource = async () => {
console.log("Minting...");
try {
const response = await fetch(`/api/user/${userId}/staking-sources`, {
method: "POST",
headers: { "Content-Type": "application/json" },
});
const data = await response.json();
if (response.status == 200) {
// Return success message
setNotification({ message: "Moon has been minted", type: "Success" });
fetchInventoryItems();
fetchStakingSources();
fetchBankAccount();
}
if (response.status == 400) {
// return error message
setNotification({ message: data.error, type: "Error" });
}
} catch (error) {
if (error instanceof Error) {
setNotification({ message: error.message, type: "Error" });
} else {
setNotification({ message: "An unknown error occured", type: "Error" });
}
}
};
const handleSetLightBox = () => {
setLightBoxIsActive(!lightBoxIsActive);
};
const handleCloseNotification = () => {
setNotification(null);
};
const handleMenuItemClick = (componentKey: string) => {
setActiveComponent(componentKey);
};
if (!userId)
return (
<>
<Navbar setUserId={setUserId} />
<p>Please login</p>
</>
);
if (isLoading) {
return <p>Loading...</p>;
}
//console.log(stakingSources);
return (
<>
<Navbar setUserId={setUserId} />
{notification && (
<NotificationPopover
notification={notification}
onClose={handleCloseNotification}
/>
)}
<BankAccountsView
bankAccount={bankAccount}
setLightBoxIsActive={handleSetLightBox}
/>
<div className="grid grid-cols-6 p-4 gap-8">
<NavbarVertical
onMenuItemClick={handleMenuItemClick}
activeItem={activeComponent}
/>
{activeComponent === "stakingsourcesview" && (
<StakingSourcesView
stakingSources={stakingSources}
inventoryItems={inventoryItems}
claimStake={claimStake}
startStake={startStake}
createStakingSource={createStakingSource}
/>
)}
{activeComponent === "inventoryitemview" && (
<InventoryItemView
stakes={userStakes}
inventoryItems={inventoryItems}
upgradeInventoryItem={upgradeInventoryItem}
/>
)}
{activeComponent === "storeitemview" && (
<StoreItemView
inventoryItems={inventoryItems}
storeItems={storeItems}
buyStoreItem={buyStoreItem}
/>
)}
{activeComponent === "resourcestore" && (
<ResourceStore bankAccount={bankAccount} />
)}
</div>
</>
);
}