refactor to use gameConfig from endpoint
Before Width: | Height: | Size: 417 KiB |
Before Width: | Height: | Size: 405 KiB |
BIN
public/assets/items/dustexcavator.png
Normal file
After Width: | Height: | Size: 410 KiB |
BIN
public/assets/items/lunarcoreextractor.png
Normal file
After Width: | Height: | Size: 667 KiB |
Before Width: | Height: | Size: 482 KiB After Width: | Height: | Size: 482 KiB |
BIN
public/assets/items/lunarlite300.png
Normal file
After Width: | Height: | Size: 460 KiB |
BIN
public/assets/items/pickaxe.png
Normal file
After Width: | Height: | Size: 408 KiB |
Before Width: | Height: | Size: 374 KiB After Width: | Height: | Size: 374 KiB |
BIN
public/assets/items/shovel.png
Normal file
After Width: | Height: | Size: 421 KiB |
@ -1,28 +1,41 @@
|
||||
"use client";
|
||||
import React, { useState } from "react";
|
||||
import { IResourceAccount, IConversionPair } from "typings";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { IResourceAccount, IConversionPair, IGameConfig } from "typings";
|
||||
import { resourceToFc } from "../../../utils/helpers";
|
||||
import ResourceModal from "./ResourceModal";
|
||||
|
||||
const ResourceAccount = (props: {
|
||||
account: IResourceAccount;
|
||||
sellResource: (pairs: IConversionPair[]) => void;
|
||||
gameConfig: IGameConfig | undefined;
|
||||
}) => {
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const [conversionPair, setConversionPair] = useState<
|
||||
IConversionPair | undefined
|
||||
>(undefined);
|
||||
const [conversionRate, setConversionRate] = useState<Number>(0.1);
|
||||
const [conversionRate, setConversionRate] = useState<number>(0.1);
|
||||
|
||||
const handleConversionPair = (amount: number, resourceType: string) => {
|
||||
const updatedPair = {
|
||||
resourceType: resourceType,
|
||||
resourceAmount: amount,
|
||||
moneyAmount: amount * conversionRate.valueOf(),
|
||||
moneyAmount: amount * conversionRate,
|
||||
};
|
||||
setConversionPair(updatedPair);
|
||||
};
|
||||
|
||||
const getConversionRate = (account: IResourceAccount) => {
|
||||
if (props.gameConfig === undefined) return 0;
|
||||
const query = account.resourceType + "ToMoonbucks";
|
||||
const rate = props.gameConfig.gameConstants[query];
|
||||
return rate;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const rate = getConversionRate(props.account);
|
||||
setConversionRate(rate);
|
||||
}, [props.gameConfig]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{showModal && (
|
||||
|
@ -1,12 +1,18 @@
|
||||
"use client";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { IBankAccount, IConversionPair } from "typings";
|
||||
import {
|
||||
IBankAccount,
|
||||
IConversionPair,
|
||||
IGameConfig,
|
||||
IResourceAccount,
|
||||
} from "typings";
|
||||
import Account from "./Account";
|
||||
import { BiLoaderAlt } from "react-icons/bi";
|
||||
|
||||
const BankAccountsView = (props: {
|
||||
bankAccount: IBankAccount | undefined;
|
||||
sellResource: (pairs: IConversionPair[]) => void;
|
||||
gameConfig: IGameConfig | undefined;
|
||||
}) => {
|
||||
if (props.bankAccount === undefined) {
|
||||
return (
|
||||
@ -39,6 +45,7 @@ const BankAccountsView = (props: {
|
||||
key={id}
|
||||
account={account}
|
||||
sellResource={props.sellResource}
|
||||
gameConfig={props.gameConfig}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { IInventoryItem, IStake } from "typings";
|
||||
import { IInventoryItem, IStake, IUpgrade } from "typings";
|
||||
import CardLayout from "../../Layouts/CardLayout";
|
||||
import Image from "next/image";
|
||||
const InventoryItem = (props: {
|
||||
@ -10,14 +10,13 @@ const InventoryItem = (props: {
|
||||
const [currentTierIndex, setCurrentTierIndex] = useState(
|
||||
props.inventoryItem.currentTierIndex
|
||||
);
|
||||
const [currentUpgrade, setCurrentUpgrade] = useState(
|
||||
props.inventoryItem.storeItem.upgrades[currentTierIndex]
|
||||
);
|
||||
const [currentUpgrade, setCurrentUpgrade] = useState<IUpgrade | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const index = props.inventoryItem.currentTierIndex;
|
||||
setCurrentTierIndex(index);
|
||||
setCurrentUpgrade(props.inventoryItem.storeItem.upgrades[index]);
|
||||
const currentUpdade = props.inventoryItem.storeItem.upgrades[index];
|
||||
setCurrentUpgrade(currentUpdade);
|
||||
}, [props.inventoryItem]);
|
||||
|
||||
const isInUse = () => {
|
||||
@ -47,7 +46,8 @@ const InventoryItem = (props: {
|
||||
<p>{props.inventoryItem.storeItem.claimAmount}</p>
|
||||
<p className="font-bold mb-1 mt-4">Tier</p>
|
||||
<div className="flex items-center">
|
||||
{props.inventoryItem.storeItem.upgrades.map((upgrade, id) => {
|
||||
{currentUpgrade &&
|
||||
props.inventoryItem.storeItem.upgrades.map((upgrade, id) => {
|
||||
if (upgrade.tier <= currentUpgrade.tier) {
|
||||
return (
|
||||
<span key={id} className="bg-green-600 px-4 py-2"></span>
|
||||
@ -58,7 +58,9 @@ const InventoryItem = (props: {
|
||||
);
|
||||
}
|
||||
})}
|
||||
<p className="font-bold ml-1">(+{currentUpgrade.claimBoost})</p>
|
||||
<p className="font-bold ml-1">
|
||||
(+{currentUpgrade && currentUpgrade.claimBoost})
|
||||
</p>
|
||||
</div>
|
||||
<p className="font-bold mb-1 mt-4">Upgrade</p>
|
||||
<div className="flex items-center">
|
||||
@ -97,7 +99,7 @@ const InventoryItem = (props: {
|
||||
</div>
|
||||
<div className="relative object-contain w-48 h-48 mt-4 md:mt-0">
|
||||
<Image
|
||||
src={props.inventoryItem.storeItem.image}
|
||||
src={"/assets/items/" + props.inventoryItem.storeItem.image}
|
||||
alt={props.inventoryItem.storeItem.name}
|
||||
fill
|
||||
className="rounded-lg border border-white/20 shadow-lg object-contain"
|
||||
|
@ -3,44 +3,6 @@ import React from "react";
|
||||
import { IInventoryItem, IStakingSource } from "typings";
|
||||
import StakingSource from "./StakingSource";
|
||||
|
||||
const moons = [
|
||||
{
|
||||
name: "Caelusium",
|
||||
description:
|
||||
"Caelusium is a medium-sized moon with a diverse landscape. Its craters contain a wealth of common resources, making it an ideal starting location for beginners. The moon's relatively mild weather conditions and stable surface offer a friendly environment for establishing mining operations.",
|
||||
image: "/assets/moon_1.png",
|
||||
price: 100,
|
||||
},
|
||||
{
|
||||
name: "Caelusium",
|
||||
description:
|
||||
"Caelusium is a medium-sized moon with a diverse landscape. Its craters contain a wealth of common resources, making it an ideal starting location for beginners. The moon's relatively mild weather conditions and stable surface offer a friendly environment for establishing mining operations.",
|
||||
image: "/assets/moon_2.png",
|
||||
price: 100,
|
||||
},
|
||||
{
|
||||
name: "Caelusium",
|
||||
description:
|
||||
"Caelusium is a medium-sized moon with a diverse landscape. Its craters contain a wealth of common resources, making it an ideal starting location for beginners. The moon's relatively mild weather conditions and stable surface offer a friendly environment for establishing mining operations.",
|
||||
image: "/assets/moon_3.png",
|
||||
price: 100,
|
||||
},
|
||||
{
|
||||
name: "Caelusium",
|
||||
description:
|
||||
"Caelusium is a medium-sized moon with a diverse landscape. Its craters contain a wealth of common resources, making it an ideal starting location for beginners. The moon's relatively mild weather conditions and stable surface offer a friendly environment for establishing mining operations.",
|
||||
image: "/assets/moon_4.png",
|
||||
price: 100,
|
||||
},
|
||||
{
|
||||
name: "Caelusium",
|
||||
description:
|
||||
"Caelusium is a medium-sized moon with a diverse landscape. Its craters contain a wealth of common resources, making it an ideal starting location for beginners. The moon's relatively mild weather conditions and stable surface offer a friendly environment for establishing mining operations.",
|
||||
image: "/assets/moon_5.png",
|
||||
price: 100,
|
||||
},
|
||||
];
|
||||
|
||||
interface RowProps {
|
||||
stakingSources: IStakingSource[];
|
||||
inventoryItems: IInventoryItem[] | undefined | null;
|
||||
|
@ -39,7 +39,7 @@ const StoreItem = (props: {
|
||||
</div>
|
||||
<div className="relative object-contain w-48 h-48">
|
||||
<Image
|
||||
src={props.storeItem.image}
|
||||
src={"/assets/items/" + props.storeItem.image}
|
||||
alt={props.storeItem.name}
|
||||
fill
|
||||
className="rounded-lg border border-white/20 shadow-lg object-contain mt-4 md:mt-0"
|
||||
|
@ -4,7 +4,7 @@ import StoreItem from "./StoreItem";
|
||||
|
||||
const StoreItemView = (props: {
|
||||
inventoryItems: IInventoryItem[] | null | undefined;
|
||||
storeItems: IStoreItem[];
|
||||
storeItems: IStoreItem[] | null;
|
||||
buyStoreItem: (storeItemId: number) => void;
|
||||
}) => {
|
||||
return (
|
||||
@ -12,7 +12,8 @@ const StoreItemView = (props: {
|
||||
<div className="bg-slate-900 text-white p-8 rounded-xl h-full">
|
||||
<h2 className="text-3xl font-bold mb-4 text-white">Store</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||
{props.storeItems
|
||||
{props.storeItems &&
|
||||
props.storeItems
|
||||
.filter((item) => !item.isOwned)
|
||||
.map((storeItem, id) => (
|
||||
<StoreItem
|
||||
|
@ -5,7 +5,6 @@ import StakingSourcesView from "./Components/Staking/StakingSourcesView";
|
||||
import BankAccountsView from "./Components/Accounts/AccountsView";
|
||||
import StoreItemView from "./Components/Store/StoreItemView";
|
||||
import NotificationPopover from "./Components/NotificationPopover";
|
||||
import { gameConfig } from "@/utils/gameLogic";
|
||||
import {
|
||||
IInventoryItem,
|
||||
IStakingSource,
|
||||
@ -13,6 +12,8 @@ import {
|
||||
IStake,
|
||||
IConversionPair,
|
||||
Notification,
|
||||
IGameConfig,
|
||||
IStoreItem,
|
||||
} from "typings";
|
||||
import Navbar from "./Components/Navigation/Navbar";
|
||||
import NavbarVertical from "./Components/Navigation/NavbarVertical";
|
||||
@ -26,13 +27,13 @@ export default function Home() {
|
||||
);
|
||||
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 [storeItems, setStoreItems] = useState<IStoreItem[] | null>(null);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [activeComponent, setActiveComponent] = useState("stakingsourcesview");
|
||||
const [activeComponent, setActiveComponent] = useState("inventoryitemview");
|
||||
const [gameConfig, setGameConfig] = useState<IGameConfig>();
|
||||
|
||||
const isOwned = (storeItemId: number) => {
|
||||
if (inventoryItems && inventoryItems?.length > 0) {
|
||||
@ -46,20 +47,34 @@ export default function Home() {
|
||||
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
|
||||
);
|
||||
// Calling the endpoint here because state might not be ready
|
||||
const gameConfig = await fetch(`/api/get-game-config`);
|
||||
const gameConfigData = await gameConfig.json();
|
||||
|
||||
const updatedInventoryItems = DBInventoryItems.inventoryItems.map(
|
||||
(invItem: IInventoryItem) => {
|
||||
return {
|
||||
...invItem,
|
||||
storeItem: gameConfigData.storeItems?.find(
|
||||
(item: IStoreItem) => item.id === invItem.storeItemId
|
||||
),
|
||||
};
|
||||
}
|
||||
// TODO Can you just return the array?
|
||||
console.log(DBInventoryItems.inventoryItems);
|
||||
setInventoryItems(DBInventoryItems.inventoryItems);
|
||||
);
|
||||
|
||||
setInventoryItems(updatedInventoryItems);
|
||||
};
|
||||
|
||||
const fetchStoreItems = async () => {
|
||||
const response = await fetch(`/api/get-game-config`);
|
||||
const data = await response.json();
|
||||
setGameConfig(data);
|
||||
setStoreItems(data.storeItems);
|
||||
};
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
@ -86,11 +101,13 @@ export default function Home() {
|
||||
fetchStakingSources();
|
||||
fetchInventoryItems();
|
||||
fetchStakes();
|
||||
fetchStoreItems();
|
||||
setIsLoading(false);
|
||||
}, [userId]);
|
||||
|
||||
// Update data
|
||||
useEffect(() => {
|
||||
if (storeItems) {
|
||||
const updatedStoreItems = storeItems.map((storeItem) => {
|
||||
return {
|
||||
...storeItem,
|
||||
@ -98,9 +115,9 @@ export default function Home() {
|
||||
};
|
||||
});
|
||||
updatedStoreItems && setStoreItems(updatedStoreItems);
|
||||
}
|
||||
}, [inventoryItems]);
|
||||
|
||||
// Hide error automatically
|
||||
useEffect(() => {
|
||||
if (notification) {
|
||||
const intervalId = setInterval(() => {
|
||||
@ -332,7 +349,11 @@ export default function Home() {
|
||||
onClose={handleCloseNotification}
|
||||
/>
|
||||
)}
|
||||
<BankAccountsView bankAccount={bankAccount} sellResource={sellResource} />
|
||||
<BankAccountsView
|
||||
bankAccount={bankAccount}
|
||||
sellResource={sellResource}
|
||||
gameConfig={gameConfig}
|
||||
/>
|
||||
<div className="grid grid-cols-1 md:grid-cols-6 p-4 gap-8">
|
||||
<NavbarVertical
|
||||
onMenuItemClick={handleMenuItemClick}
|
||||
|
1
typings.d.ts
vendored
@ -83,6 +83,7 @@ export interface IGameConfig {
|
||||
resources: string[];
|
||||
[key: string]: any;
|
||||
store: IStoreItem[];
|
||||
gameConstants: {[key: string]: any;}
|
||||
}
|
||||
|
||||
export interface IConversionPair {
|
||||
|