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";
|
"use client";
|
||||||
import React, { useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { IResourceAccount, IConversionPair } from "typings";
|
import { IResourceAccount, IConversionPair, IGameConfig } from "typings";
|
||||||
import { resourceToFc } from "../../../utils/helpers";
|
import { resourceToFc } from "../../../utils/helpers";
|
||||||
import ResourceModal from "./ResourceModal";
|
import ResourceModal from "./ResourceModal";
|
||||||
|
|
||||||
const ResourceAccount = (props: {
|
const ResourceAccount = (props: {
|
||||||
account: IResourceAccount;
|
account: IResourceAccount;
|
||||||
sellResource: (pairs: IConversionPair[]) => void;
|
sellResource: (pairs: IConversionPair[]) => void;
|
||||||
|
gameConfig: IGameConfig | undefined;
|
||||||
}) => {
|
}) => {
|
||||||
const [showModal, setShowModal] = useState(false);
|
const [showModal, setShowModal] = useState(false);
|
||||||
const [conversionPair, setConversionPair] = useState<
|
const [conversionPair, setConversionPair] = useState<
|
||||||
IConversionPair | undefined
|
IConversionPair | undefined
|
||||||
>(undefined);
|
>(undefined);
|
||||||
const [conversionRate, setConversionRate] = useState<Number>(0.1);
|
const [conversionRate, setConversionRate] = useState<number>(0.1);
|
||||||
|
|
||||||
const handleConversionPair = (amount: number, resourceType: string) => {
|
const handleConversionPair = (amount: number, resourceType: string) => {
|
||||||
const updatedPair = {
|
const updatedPair = {
|
||||||
resourceType: resourceType,
|
resourceType: resourceType,
|
||||||
resourceAmount: amount,
|
resourceAmount: amount,
|
||||||
moneyAmount: amount * conversionRate.valueOf(),
|
moneyAmount: amount * conversionRate,
|
||||||
};
|
};
|
||||||
setConversionPair(updatedPair);
|
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 (
|
return (
|
||||||
<>
|
<>
|
||||||
{showModal && (
|
{showModal && (
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { IBankAccount, IConversionPair } from "typings";
|
import {
|
||||||
|
IBankAccount,
|
||||||
|
IConversionPair,
|
||||||
|
IGameConfig,
|
||||||
|
IResourceAccount,
|
||||||
|
} from "typings";
|
||||||
import Account from "./Account";
|
import Account from "./Account";
|
||||||
import { BiLoaderAlt } from "react-icons/bi";
|
import { BiLoaderAlt } from "react-icons/bi";
|
||||||
|
|
||||||
const BankAccountsView = (props: {
|
const BankAccountsView = (props: {
|
||||||
bankAccount: IBankAccount | undefined;
|
bankAccount: IBankAccount | undefined;
|
||||||
sellResource: (pairs: IConversionPair[]) => void;
|
sellResource: (pairs: IConversionPair[]) => void;
|
||||||
|
gameConfig: IGameConfig | undefined;
|
||||||
}) => {
|
}) => {
|
||||||
if (props.bankAccount === undefined) {
|
if (props.bankAccount === undefined) {
|
||||||
return (
|
return (
|
||||||
@ -39,6 +45,7 @@ const BankAccountsView = (props: {
|
|||||||
key={id}
|
key={id}
|
||||||
account={account}
|
account={account}
|
||||||
sellResource={props.sellResource}
|
sellResource={props.sellResource}
|
||||||
|
gameConfig={props.gameConfig}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { IInventoryItem, IStake } from "typings";
|
import { IInventoryItem, IStake, IUpgrade } from "typings";
|
||||||
import CardLayout from "../../Layouts/CardLayout";
|
import CardLayout from "../../Layouts/CardLayout";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
const InventoryItem = (props: {
|
const InventoryItem = (props: {
|
||||||
@ -10,14 +10,13 @@ const InventoryItem = (props: {
|
|||||||
const [currentTierIndex, setCurrentTierIndex] = useState(
|
const [currentTierIndex, setCurrentTierIndex] = useState(
|
||||||
props.inventoryItem.currentTierIndex
|
props.inventoryItem.currentTierIndex
|
||||||
);
|
);
|
||||||
const [currentUpgrade, setCurrentUpgrade] = useState(
|
const [currentUpgrade, setCurrentUpgrade] = useState<IUpgrade | null>(null);
|
||||||
props.inventoryItem.storeItem.upgrades[currentTierIndex]
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const index = props.inventoryItem.currentTierIndex;
|
const index = props.inventoryItem.currentTierIndex;
|
||||||
setCurrentTierIndex(index);
|
setCurrentTierIndex(index);
|
||||||
setCurrentUpgrade(props.inventoryItem.storeItem.upgrades[index]);
|
const currentUpdade = props.inventoryItem.storeItem.upgrades[index];
|
||||||
|
setCurrentUpgrade(currentUpdade);
|
||||||
}, [props.inventoryItem]);
|
}, [props.inventoryItem]);
|
||||||
|
|
||||||
const isInUse = () => {
|
const isInUse = () => {
|
||||||
@ -47,7 +46,8 @@ const InventoryItem = (props: {
|
|||||||
<p>{props.inventoryItem.storeItem.claimAmount}</p>
|
<p>{props.inventoryItem.storeItem.claimAmount}</p>
|
||||||
<p className="font-bold mb-1 mt-4">Tier</p>
|
<p className="font-bold mb-1 mt-4">Tier</p>
|
||||||
<div className="flex items-center">
|
<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) {
|
if (upgrade.tier <= currentUpgrade.tier) {
|
||||||
return (
|
return (
|
||||||
<span key={id} className="bg-green-600 px-4 py-2"></span>
|
<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>
|
</div>
|
||||||
<p className="font-bold mb-1 mt-4">Upgrade</p>
|
<p className="font-bold mb-1 mt-4">Upgrade</p>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
@ -97,7 +99,7 @@ const InventoryItem = (props: {
|
|||||||
</div>
|
</div>
|
||||||
<div className="relative object-contain w-48 h-48 mt-4 md:mt-0">
|
<div className="relative object-contain w-48 h-48 mt-4 md:mt-0">
|
||||||
<Image
|
<Image
|
||||||
src={props.inventoryItem.storeItem.image}
|
src={"/assets/items/" + props.inventoryItem.storeItem.image}
|
||||||
alt={props.inventoryItem.storeItem.name}
|
alt={props.inventoryItem.storeItem.name}
|
||||||
fill
|
fill
|
||||||
className="rounded-lg border border-white/20 shadow-lg object-contain"
|
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 { IInventoryItem, IStakingSource } from "typings";
|
||||||
import StakingSource from "./StakingSource";
|
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 {
|
interface RowProps {
|
||||||
stakingSources: IStakingSource[];
|
stakingSources: IStakingSource[];
|
||||||
inventoryItems: IInventoryItem[] | undefined | null;
|
inventoryItems: IInventoryItem[] | undefined | null;
|
||||||
|
@ -39,7 +39,7 @@ const StoreItem = (props: {
|
|||||||
</div>
|
</div>
|
||||||
<div className="relative object-contain w-48 h-48">
|
<div className="relative object-contain w-48 h-48">
|
||||||
<Image
|
<Image
|
||||||
src={props.storeItem.image}
|
src={"/assets/items/" + props.storeItem.image}
|
||||||
alt={props.storeItem.name}
|
alt={props.storeItem.name}
|
||||||
fill
|
fill
|
||||||
className="rounded-lg border border-white/20 shadow-lg object-contain mt-4 md:mt-0"
|
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: {
|
const StoreItemView = (props: {
|
||||||
inventoryItems: IInventoryItem[] | null | undefined;
|
inventoryItems: IInventoryItem[] | null | undefined;
|
||||||
storeItems: IStoreItem[];
|
storeItems: IStoreItem[] | null;
|
||||||
buyStoreItem: (storeItemId: number) => void;
|
buyStoreItem: (storeItemId: number) => void;
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
@ -12,7 +12,8 @@ const StoreItemView = (props: {
|
|||||||
<div className="bg-slate-900 text-white p-8 rounded-xl h-full">
|
<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>
|
<h2 className="text-3xl font-bold mb-4 text-white">Store</h2>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||||
{props.storeItems
|
{props.storeItems &&
|
||||||
|
props.storeItems
|
||||||
.filter((item) => !item.isOwned)
|
.filter((item) => !item.isOwned)
|
||||||
.map((storeItem, id) => (
|
.map((storeItem, id) => (
|
||||||
<StoreItem
|
<StoreItem
|
||||||
|
@ -5,7 +5,6 @@ import StakingSourcesView from "./Components/Staking/StakingSourcesView";
|
|||||||
import BankAccountsView from "./Components/Accounts/AccountsView";
|
import BankAccountsView from "./Components/Accounts/AccountsView";
|
||||||
import StoreItemView from "./Components/Store/StoreItemView";
|
import StoreItemView from "./Components/Store/StoreItemView";
|
||||||
import NotificationPopover from "./Components/NotificationPopover";
|
import NotificationPopover from "./Components/NotificationPopover";
|
||||||
import { gameConfig } from "@/utils/gameLogic";
|
|
||||||
import {
|
import {
|
||||||
IInventoryItem,
|
IInventoryItem,
|
||||||
IStakingSource,
|
IStakingSource,
|
||||||
@ -13,6 +12,8 @@ import {
|
|||||||
IStake,
|
IStake,
|
||||||
IConversionPair,
|
IConversionPair,
|
||||||
Notification,
|
Notification,
|
||||||
|
IGameConfig,
|
||||||
|
IStoreItem,
|
||||||
} from "typings";
|
} from "typings";
|
||||||
import Navbar from "./Components/Navigation/Navbar";
|
import Navbar from "./Components/Navigation/Navbar";
|
||||||
import NavbarVertical from "./Components/Navigation/NavbarVertical";
|
import NavbarVertical from "./Components/Navigation/NavbarVertical";
|
||||||
@ -26,13 +27,13 @@ export default function Home() {
|
|||||||
);
|
);
|
||||||
const [bankAccount, setBankAccount] = useState<IBankAccount>();
|
const [bankAccount, setBankAccount] = useState<IBankAccount>();
|
||||||
const [userStakes, setUserStakes] = useState<IStake[]>([]);
|
const [userStakes, setUserStakes] = useState<IStake[]>([]);
|
||||||
const [lightBoxIsActive, setLightBoxIsActive] = useState(false);
|
|
||||||
const [userId, setUserId] = useState<string>("");
|
const [userId, setUserId] = useState<string>("");
|
||||||
const [notification, setNotification] = useState<Notification | null>(null);
|
const [notification, setNotification] = useState<Notification | null>(null);
|
||||||
const [notificationTime, setNotificationTime] = useState(30);
|
const [notificationTime, setNotificationTime] = useState(30);
|
||||||
const [storeItems, setStoreItems] = useState(gameConfig.store);
|
const [storeItems, setStoreItems] = useState<IStoreItem[] | null>(null);
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const [activeComponent, setActiveComponent] = useState("stakingsourcesview");
|
const [activeComponent, setActiveComponent] = useState("inventoryitemview");
|
||||||
|
const [gameConfig, setGameConfig] = useState<IGameConfig>();
|
||||||
|
|
||||||
const isOwned = (storeItemId: number) => {
|
const isOwned = (storeItemId: number) => {
|
||||||
if (inventoryItems && inventoryItems?.length > 0) {
|
if (inventoryItems && inventoryItems?.length > 0) {
|
||||||
@ -46,20 +47,34 @@ export default function Home() {
|
|||||||
const response = await fetch(`/api/user/${userId}/inventory-items`);
|
const response = await fetch(`/api/user/${userId}/inventory-items`);
|
||||||
const DBInventoryItems = await response.json();
|
const DBInventoryItems = await response.json();
|
||||||
|
|
||||||
for (const invItem of DBInventoryItems.inventoryItems) {
|
// Calling the endpoint here because state might not be ready
|
||||||
invItem.storeItem = gameConfig.store.find(
|
const gameConfig = await fetch(`/api/get-game-config`);
|
||||||
(item) => item.id === invItem.storeItemId
|
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 fetchStakingSources = async () => {
|
||||||
const response = await fetch(`/api/user/${userId}/staking-sources`);
|
const response = await fetch(`/api/user/${userId}/staking-sources`);
|
||||||
const sources = await response.json();
|
const sources = await response.json();
|
||||||
// TODO Can you just return the array?
|
|
||||||
setStakingSources(sources.stakingSources);
|
setStakingSources(sources.stakingSources);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -86,11 +101,13 @@ export default function Home() {
|
|||||||
fetchStakingSources();
|
fetchStakingSources();
|
||||||
fetchInventoryItems();
|
fetchInventoryItems();
|
||||||
fetchStakes();
|
fetchStakes();
|
||||||
|
fetchStoreItems();
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}, [userId]);
|
}, [userId]);
|
||||||
|
|
||||||
// Update data
|
// Update data
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (storeItems) {
|
||||||
const updatedStoreItems = storeItems.map((storeItem) => {
|
const updatedStoreItems = storeItems.map((storeItem) => {
|
||||||
return {
|
return {
|
||||||
...storeItem,
|
...storeItem,
|
||||||
@ -98,9 +115,9 @@ export default function Home() {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
updatedStoreItems && setStoreItems(updatedStoreItems);
|
updatedStoreItems && setStoreItems(updatedStoreItems);
|
||||||
|
}
|
||||||
}, [inventoryItems]);
|
}, [inventoryItems]);
|
||||||
|
|
||||||
// Hide error automatically
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (notification) {
|
if (notification) {
|
||||||
const intervalId = setInterval(() => {
|
const intervalId = setInterval(() => {
|
||||||
@ -332,7 +349,11 @@ export default function Home() {
|
|||||||
onClose={handleCloseNotification}
|
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">
|
<div className="grid grid-cols-1 md:grid-cols-6 p-4 gap-8">
|
||||||
<NavbarVertical
|
<NavbarVertical
|
||||||
onMenuItemClick={handleMenuItemClick}
|
onMenuItemClick={handleMenuItemClick}
|
||||||
|
1
typings.d.ts
vendored
@ -83,6 +83,7 @@ export interface IGameConfig {
|
|||||||
resources: string[];
|
resources: string[];
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
store: IStoreItem[];
|
store: IStoreItem[];
|
||||||
|
gameConstants: {[key: string]: any;}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IConversionPair {
|
export interface IConversionPair {
|
||||||
|