diff --git a/src/app/Components/BankAccount.tsx b/src/app/Components/BankAccount.tsx
new file mode 100644
index 0000000..19248f4
--- /dev/null
+++ b/src/app/Components/BankAccount.tsx
@@ -0,0 +1,33 @@
+"use client";
+import React, { useEffect, useState } from "react";
+import { IBankAccount } from "typings";
+
+const BankAccount = (props: { bankAccount: IBankAccount }) => {
+ return (
+
+
+
+ {props.bankAccount.resourceType.name}
+
+
+ {props.bankAccount.balance.toLocaleString("en-US", {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}{" "}
+ kg
+
+
+
+ );
+};
+
+export default BankAccount;
diff --git a/src/app/Components/BankAccountsView.tsx b/src/app/Components/BankAccountsView.tsx
new file mode 100644
index 0000000..642832d
--- /dev/null
+++ b/src/app/Components/BankAccountsView.tsx
@@ -0,0 +1,33 @@
+"use client";
+import React from "react";
+import { IBankAccount } from "typings";
+import BankAccount from "./BankAccount";
+
+const BankAccountsView = (props: {
+ bankAccounts: IBankAccount[];
+ setLightBoxIsActive: () => void;
+}) => {
+ return (
+
+
+
+
+ Moonbucks
+
$5,342.23
+
+
+
+ {props.bankAccounts.map((bankAccount, id) => {
+ return
;
+ })}
+
+
+ );
+};
+
+export default BankAccountsView;
diff --git a/src/app/Components/InventoryItem.tsx b/src/app/Components/InventoryItem.tsx
new file mode 100644
index 0000000..5652334
--- /dev/null
+++ b/src/app/Components/InventoryItem.tsx
@@ -0,0 +1,51 @@
+import React from "react";
+import { IInventoryItem, IStoreItem } from "typings";
+import CardLayout from "../Layouts/CardLayout";
+
+const InventoryItem = (props: {
+ inventoryItem: IInventoryItem;
+ inUse: boolean | undefined;
+ handleIncrementTier: (inventoryItem: IInventoryItem) => void;
+}) => {
+ const getCurrentTier = (index: number) => {
+ return props.inventoryItem.storeItem.tiers[index];
+ };
+
+ return (
+
+
+ {props.inventoryItem.storeItem.name}{" "}
+
+ {props.inventoryItem.currentTierIndex + 1}
+
+
+ {props.inventoryItem.storeItem.description}
+
+
+
Yield
+
+ {getCurrentTier(props.inventoryItem.currentTierIndex).tier}
+
+
+
+
+ {props.inUse ? (
+
+ ) : (
+
+ )}
+
+
+
+
+ );
+};
+
+export default InventoryItem;
diff --git a/src/app/Components/InventoryItemView.tsx b/src/app/Components/InventoryItemView.tsx
new file mode 100644
index 0000000..3425852
--- /dev/null
+++ b/src/app/Components/InventoryItemView.tsx
@@ -0,0 +1,33 @@
+import React from "react";
+import { IInventoryItem, IStakingSource } from "typings";
+import InventoryItem from "./InventoryItem";
+
+const InventoryItemView = (props: {
+ stakingSources: IStakingSource[] | null;
+ inventoryItems: IInventoryItem[] | null | undefined;
+ handleIncrementTier: (inventoryItem: IInventoryItem) => void;
+}) => {
+ const inUse = (inventoryItemId: number) => {
+ return props.stakingSources?.some((source) => {
+ if (!source.inventoryItem) return false;
+ return source.inventoryItem.id == inventoryItemId;
+ });
+ };
+
+ return (
+
+
Your Inventory
+ {props.inventoryItems &&
+ props.inventoryItems.map((inventoryItem, id) => (
+
+ ))}
+
+ );
+};
+
+export default InventoryItemView;
diff --git a/src/app/Components/LightBox.tsx b/src/app/Components/LightBox.tsx
new file mode 100644
index 0000000..14b87ca
--- /dev/null
+++ b/src/app/Components/LightBox.tsx
@@ -0,0 +1,12 @@
+import React from "react";
+import { IBankAccount } from "typings";
+
+const LightBox = (props: { bankAccounts: IBankAccount[] }) => {
+ return (
+
+
Sell Your Resources
+
+ );
+};
+
+export default LightBox;
diff --git a/src/app/Components/MiningItem.tsx b/src/app/Components/MiningItem.tsx
deleted file mode 100644
index 7064085..0000000
--- a/src/app/Components/MiningItem.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-import React from "react";
-import { Drill } from "typings";
-import CardLayout from "../Layouts/CardLayout";
-
-const MiningItem = (props: { drill: Drill }) => {
- return (
-
- {props.drill.name}
- {props.drill.description}
-
-
-
Base Yield
-
- {props.drill.yield.map(
- (x, id) =>
- x.resource && (
- -
- {x.baseYield}{" "}
-
- {x.resource.name}
-
-
- )
- )}
-
-
Upgrades
-
-
-
-
Status
-
- -
- Active Mining on Moon 1
-
-
-
Moon
-
-
-
-
- );
-};
-
-export default MiningItem;
diff --git a/src/app/Components/MiningView.tsx b/src/app/Components/MiningView.tsx
deleted file mode 100644
index e533ad8..0000000
--- a/src/app/Components/MiningView.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import React from "react";
-import { Drill } from "typings";
-import MiningItem from "./MiningItem";
-
-const MiningView = (props: { drills: Drill[] }) => {
- return (
-
-
Drills
- {props.drills.map((drill, id) => (
-
- ))}
-
- );
-};
-
-export default MiningView;
diff --git a/src/app/Components/MoonItem.tsx b/src/app/Components/MoonItem.tsx
deleted file mode 100644
index 539bcfd..0000000
--- a/src/app/Components/MoonItem.tsx
+++ /dev/null
@@ -1,57 +0,0 @@
-import React from "react";
-import { Moon } from "typings";
-import CardLayout from "../Layouts/CardLayout";
-
-const MoonItem = (props: { moon: Moon }) => {
- return (
-
- {props.moon.name}
- {props.moon.description}
-
-
-
Mineral Composition
-
- {props.moon.resources.map((resource, id) => (
- -
- {resource.name}{" "}
- 80%
-
- ))}
-
-
-
-
Status
-
- -
-
-
-
- Operational
-
-
-
Drill
-
-
-
-
- );
-};
-
-export default MoonItem;
diff --git a/src/app/Components/MoonsView.tsx b/src/app/Components/MoonsView.tsx
deleted file mode 100644
index b9f9037..0000000
--- a/src/app/Components/MoonsView.tsx
+++ /dev/null
@@ -1,76 +0,0 @@
-"use client";
-import React, { useEffect, useState } from "react";
-import { Moon } from "typings";
-import MoonItem from "./MoonItem";
-
-const MoonsView = (props: { moons: Moon[] }) => {
- const [isMining, setIsMining] = useState(false);
- const [miningTime, setMiningTime] = useState(3);
- const [farmedResources, setFarmedResources] = useState([]);
-
- const resources = ["Moonstone", "Lunarite", "Selenite", "Heliogem"];
-
- useEffect(() => {
- if (isMining) {
- const intervalId = setInterval(() => {
- setMiningTime((prev) => prev - 1);
- }, 1000);
-
- if (miningTime === 0) {
- setIsMining(false);
- setFarmedResources((prev) => [
- ...prev,
- resources[Math.floor(Math.random() * (resources.length - 1 - 1))],
- ]);
- clearInterval(intervalId);
- setMiningTime(3);
- }
-
- return () => {
- clearInterval(intervalId);
- };
- }
- }, [isMining, miningTime]);
-
- return (
-
-
Moons
- {props.moons.map((moon, id) => (
-
- ))}
-
-
- {isMining &&
Mining time: {miningTime}
}
-
-
Here you will see your mined resources
- {farmedResources.length <= 0 ? (
-
Start mining to get resources
- ) : (
- <>
- {farmedResources.map((farmedResource, index) => (
-
- {farmedResource}
-
-
- ))}
- >
- )}
-
- );
-};
-
-export default MoonsView;
diff --git a/src/app/Components/ResourceItem.tsx b/src/app/Components/ResourceItem.tsx
deleted file mode 100644
index acb39af..0000000
--- a/src/app/Components/ResourceItem.tsx
+++ /dev/null
@@ -1,51 +0,0 @@
-"use client";
-import React, { useEffect, useState } from "react";
-import { IResourceCardProps } from "typings";
-
-const ResourceItem = (props: { resourceCardProps: IResourceCardProps }) => {
- const [totalYield, settotalYield] = useState(100);
- const [isMining, setIsMining] = useState(props.resourceCardProps.isMining);
-
- useEffect(() => {
- if (isMining) {
- const intervalId = setInterval(() => {
- settotalYield((prev) => prev + props.resourceCardProps.yieldPerSecond);
- }, 1000);
-
- return () => {
- clearInterval(intervalId);
- };
- }
- }, [totalYield]);
-
- return (
-
-
-
- {props.resourceCardProps.resource.name}
-
-
- {totalYield.toLocaleString("en-US", {
- minimumFractionDigits: 2,
- maximumFractionDigits: 2,
- })}{" "}
- kg
-
-
- {props.resourceCardProps.yieldPerSecond * 3600} / hour
-
-
-
- );
-};
-
-export default ResourceItem;
diff --git a/src/app/Components/ResourceView.tsx b/src/app/Components/ResourceView.tsx
deleted file mode 100644
index b9fcbd9..0000000
--- a/src/app/Components/ResourceView.tsx
+++ /dev/null
@@ -1,34 +0,0 @@
-"use client";
-import React from "react";
-import { Resource } from "typings";
-import ResourceItem from "./ResourceItem";
-
-const ResourceView = (props: { resources: Resource[] }) => {
- return (
-
-
-
-
- Moonbucks
-
$5,342.23
-
-
-
- {props.resources.map((resource, id) => {
- const resourceCardProps = {
- resource: resource,
- isMining: true,
- yieldPerSecond: 0.15,
- };
- return (
-
- );
- })}
-
-
- );
-};
-
-export default ResourceView;
diff --git a/src/app/Components/StakingSource.tsx b/src/app/Components/StakingSource.tsx
new file mode 100644
index 0000000..b75d891
--- /dev/null
+++ b/src/app/Components/StakingSource.tsx
@@ -0,0 +1,187 @@
+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(null);
+ const [activeInventoryItem, setActiveInventoryItem] =
+ useState(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 (
+
+ );
+ }
+ }
+
+ if (isMining)
+ return (
+
+ );
+
+ if (claimableResource) {
+ return (
+
+ );
+ }
+ };
+
+ return (
+
+ {props.stakingSource.name}
+ {props.stakingSource.description}
+
+
+
Resources
+
+ {props.stakingSource.resourceWells.map((resourceWell, id) => (
+ -
+ {resourceWell.resourceType.name}{" "}
+
+ {resourceWell.supply}
+
+
+ ))}
+
+
+
+
Status
+
+ -
+
+
+
+ Operational
+
+
+
Equipment
+ {!isMining
+ ? props.inventoryItems &&
+ props.inventoryItems.map((item, id) => (
+
+
+ props.handleAddItem(item, props.stakingSource)
+ }
+ />
+
+
+ ))
+ : props.stakingSource.inventoryItem && (
+
{props.stakingSource.inventoryItem.storeItem.name}
+ )}
+
+
+ {renderButton()}
+
+ );
+};
+
+export default StakingSource;
diff --git a/src/app/Components/StakingSourcesView.tsx b/src/app/Components/StakingSourcesView.tsx
new file mode 100644
index 0000000..1aa191e
--- /dev/null
+++ b/src/app/Components/StakingSourcesView.tsx
@@ -0,0 +1,35 @@
+"use client";
+import React, { useEffect, useState } from "react";
+import { IInventoryItem, IStakingSource, IClaimableResource } from "typings";
+import StakingSource from "./StakingSource";
+
+const StakingSourcesView = (props: {
+ stakingSources: IStakingSource[] | null;
+ inventoryItems: IInventoryItem[] | null | undefined;
+ handleAddItem: (
+ inventoryItem: IInventoryItem,
+ stakingSource: IStakingSource
+ ) => void;
+ claimResource: (
+ stakingSource: IStakingSource,
+ claimedResource: IClaimableResource
+ ) => boolean;
+}) => {
+ return (
+
+
Your Moons
+ {props.stakingSources &&
+ props.stakingSources.map((stakingSource, id) => (
+
+ ))}
+
+ );
+};
+
+export default StakingSourcesView;
diff --git a/src/app/Components/StoreItem.tsx b/src/app/Components/StoreItem.tsx
new file mode 100644
index 0000000..dc81392
--- /dev/null
+++ b/src/app/Components/StoreItem.tsx
@@ -0,0 +1,60 @@
+"use client";
+import React, { useState } from "react";
+import { IStoreItem, IInventoryItem } from "typings";
+import CommonCardLayout from "../Layouts/CommonCardLayout";
+
+const StoreItem = (props: {
+ storeItem: IStoreItem;
+ handleBuy: (storeItem: IStoreItem) => void;
+ owned: boolean | undefined;
+}) => {
+ return (
+
+
+
+ {props.owned ? (
+
Owned
+ ) : (
+ ""
+ )}
+
{props.storeItem.name}
+
{props.storeItem.description}
+
$ {props.storeItem.price}
+
Tier Upgrades
+
+
+ Tier |
+ Price |
+
+ {props.storeItem.tiers.map((tier) => (
+
+
+ {tier.tier}
+ |
+
+ ${tier.price}
+ |
+
+ ))}
+
+
+
+ {props.owned ? (
+
+ ) : (
+
+ )}
+
+
+
+ );
+};
+
+export default StoreItem;
diff --git a/src/app/Components/StoreItemView.tsx b/src/app/Components/StoreItemView.tsx
new file mode 100644
index 0000000..26a1ee0
--- /dev/null
+++ b/src/app/Components/StoreItemView.tsx
@@ -0,0 +1,41 @@
+import React from "react";
+import { IInventoryItem, IStoreItem } from "typings";
+import StoreItem from "./StoreItem";
+
+const StoreItemView = (props: {
+ storeItems: IStoreItem[] | null;
+ inventoryItems: IInventoryItem[] | null | undefined;
+ handleBuy: (storeItem: IStoreItem) => void;
+}) => {
+ const isOwned = (storeItemId: number) => {
+ return props.inventoryItems?.some(
+ (item) => item.storeItem.id == storeItemId
+ );
+ };
+
+ const storeItemsToRender = props.storeItems?.map((storeItem) => {
+ return {
+ ...storeItem,
+ owned: isOwned(storeItem.id),
+ };
+ });
+
+ return (
+
+
Store
+ {storeItemsToRender &&
+ storeItemsToRender
+ .sort((a, b) => (a.owned === b.owned ? 0 : a.owned ? 1 : -1))
+ .map((storeItem, id) => (
+
+ ))}
+
+ );
+};
+
+export default StoreItemView;
diff --git a/src/app/Components/UpgradeItem.tsx b/src/app/Components/UpgradeItem.tsx
deleted file mode 100644
index a262c88..0000000
--- a/src/app/Components/UpgradeItem.tsx
+++ /dev/null
@@ -1,57 +0,0 @@
-import React from "react";
-import { Upgrade } from "typings";
-import CardLayout from "../Layouts/CardLayout";
-import RareCardLayout from "../Layouts/RareCardLayout";
-import EpicCardLayout from "../Layouts/EpicCardLayout";
-import PrestineCardLayout from "../Layouts/PrestineCardLayout";
-import CommonCardLayout from "../Layouts/CommonCardLayout";
-
-const UpgradeItem = (props: { upgrade: Upgrade }) => {
- return (
-
-
-
- {props.upgrade.owned && (
-
Owned
- )}
-
{props.upgrade.name}
-
{props.upgrade.description}
- {!props.upgrade.owned && (
-
${props.upgrade.price}
- )}
-
Modifies
-
- {props.upgrade.modifiers.map((modifier, id) => (
- -
- {modifier.yield}{" "}
-
- {modifier.resource && modifier.resource.name}
-
-
- ))}
-
-
- {!props.upgrade.owned ? (
-
-
-
- ) : (
-
-
Drill
-
-
- )}
-
-
- );
-};
-
-export default UpgradeItem;
diff --git a/src/app/Components/UpgradeView.tsx b/src/app/Components/UpgradeView.tsx
deleted file mode 100644
index 815aac8..0000000
--- a/src/app/Components/UpgradeView.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import React from "react";
-import { Upgrade } from "typings";
-import UpgradeItem from "./UpgradeItem";
-
-const UpgradeView = (props: { upgrades: Upgrade[] }) => {
- return (
-
-
Upgrades
- {props.upgrades.map((upgrade, id) => (
-
- ))}
-
- );
-};
-
-export default UpgradeView;
diff --git a/src/app/page.tsx b/src/app/page.tsx
index ed02308..83ec836 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,97 +1,382 @@
-import MiningView from "./Components/MiningView";
-import MoonsView from "./Components/MoonsView";
-import ResourceView from "./Components/ResourceView";
-import UpgradeView from "./Components/UpgradeView";
-import { Resource, Upgrade, Drill, Moon } from "typings";
+"use client";
+import { useState, useEffect } from "react";
-import getObjectFromArray from "@/utils/helpers";
+import InventoryItemView from "./Components/InventoryItemView";
+import StakingSourcesView from "./Components/StakingSourcesView";
+import BankAccountsView from "./Components/BankAccountsView";
+import StoreItemView from "./Components/StoreItemView";
+import LightBox from "./Components/LightBox";
+import {
+ IResourceWell,
+ IResourceType,
+ IStoreItem,
+ IInventoryItem,
+ IStakingSource,
+ IBankAccount,
+ IClaimableResource,
+} from "typings";
-const resources: Resource[] = [
+import { getObjectFromArray } from "../utils/helpers";
+
+const DBresourceTypes: IResourceType[] = [
{
+ id: 1,
name: "Moonstone",
fontColorClass: "text-teal-400",
bgColorClass: "from-teal-800 to-teal-900",
},
{
+ id: 2,
name: "Lunarite",
fontColorClass: "text-cyan-400",
bgColorClass: "from-cyan-800 to-cyan-900",
},
{
+ id: 3,
name: "Selenite",
fontColorClass: "text-purple-300",
bgColorClass: "from-purple-800 to-purple-900",
},
{
+ id: 4,
name: "Heliogem",
fontColorClass: "text-rose-300",
bgColorClass: "from-rose-800 to-rose-900",
},
];
-const upgrades: Upgrade[] = [
+const DBresourceWells: IResourceWell[] = [
{
- name: "SkyMiner MK-III",
- description:
- "A cutting-edge mining robot equipped with advanced sensors, capable of identifying and extracting even the rarest minerals on the moon's surface.",
- price: 500,
- modifiers: [
- {
- resource: getObjectFromArray(resources, "name", "Moonstone"),
- yield: 1,
- },
- ],
- owned: false,
- },
- {
- name: "Astro-Excavator 5000",
- description:
- "A state-of-the-art excavation machine, capable of digging deeper and faster than any other equipment on the market.",
- price: 250,
- modifiers: [
- {
- resource: getObjectFromArray(resources, "name", "Selenite"),
- yield: 1,
- },
- ],
- owned: true,
+ id: 1,
+ resourceType: DBresourceTypes[0],
+ supply: 10000,
},
];
-const drills: Drill[] = [
+const DBstoreItems: IStoreItem[] = [
{
+ id: 1,
name: "Eclipse Drill",
description:
"A compact and lightweight drill designed for use in tight and narrow mining tunnels.",
- price: 1500,
- yield: [
+ price: 225,
+ timeToClaim: 3,
+ tiers: [
{
- resource: getObjectFromArray(resources, "name", "Lunarite"),
- baseYield: 250,
+ tier: 500,
+ price: 50,
+ },
+ {
+ tier: 600,
+ price: 75,
+ },
+ {
+ tier: 700,
+ price: 100,
+ },
+ {
+ tier: 800,
+ price: 150,
+ },
+ {
+ tier: 900,
+ price: 200,
+ },
+ ],
+ },
+ {
+ id: 2,
+ name: "Moon Saw 2000",
+ description:
+ "A compact and lightweight drill designed for use in tight and narrow mining tunnels.",
+ price: 100,
+ timeToClaim: 3,
+ tiers: [
+ {
+ tier: 500,
+ price: 50,
+ },
+ {
+ tier: 550,
+ price: 75,
+ },
+ {
+ tier: 600,
+ price: 100,
+ },
+ {
+ tier: 650,
+ price: 150,
+ },
+ {
+ tier: 700,
+ price: 200,
},
],
- upgrades: null,
},
];
-const moons: Moon[] = [
+const DBinventoryItems: IInventoryItem[] = [];
+
+const DBstakingSources: IStakingSource[] = [
{
+ id: 1,
name: "Selene's Eye",
description:
"Selene's Eye is a large and mysterious moon, named for its distinctive appearance - a bright, glowing eye that seems to stare out from the void of space",
- resources: resources,
- drill: null,
+ resourceWells: DBresourceWells,
+ inventoryItem: null,
+ },
+];
+
+const DBbankAccounts: IBankAccount[] = [
+ {
+ id: 1,
+ resourceType: DBresourceTypes[0],
+ balance: 0,
+ },
+ {
+ id: 2,
+ resourceType: DBresourceTypes[1],
+ balance: 0,
+ },
+ {
+ id: 3,
+ resourceType: DBresourceTypes[2],
+ balance: 0,
+ },
+ {
+ id: 4,
+ resourceType: DBresourceTypes[3],
+ balance: 0,
},
];
export default function Home() {
+ const [inventoryItems, setInventoryItems] = useState<
+ IInventoryItem[] | null | undefined
+ >([]);
+ const [stakingSources, setStakingSources] = useState(
+ []
+ );
+ const [bankAccounts, setBankAccounts] = useState([]);
+ const [storeItems, setStoreItems] = useState([]);
+ const [lightBoxIsActive, setLightBoxIsActive] = useState(false);
+
+ // Connect to DB here
+ useEffect(() => {
+ // get the user who is currently logged in
+ const loggedInUser = 1;
+
+ const fetchInventoryItems = async () => {
+ // old
+ setInventoryItems(DBinventoryItems);
+ // new
+ // const response = await fetch(`/api/user/${loggedInUser}/inventory-items`);
+ // const DBInventoryItems = await response.json();
+ // setInventoryItems(DBInventoryItems.message);
+ };
+
+ const fetchStakingSources = async () => {
+ // old
+ setStakingSources(DBstakingSources);
+ // new
+ // const response = await fetch(`/api/user/${loggedInUser}/staking-sources`);
+ // const DBStakingSources = await response.json();
+ // setStakingSources(DBStakingSources);
+ };
+
+ const fetchBankAccounts = async () => {
+ // old
+ setBankAccounts(DBbankAccounts);
+ // new
+ // const response = await fetch(`/api/user/${loggedInUser}/bank-accounts`);
+ // const DBBankAccounts = await response.json();
+ // setStakingSources(DBBankAccounts.message);
+ };
+
+ const fetchStoreItems = async () => {
+ // old
+ setStoreItems(DBstoreItems);
+ // new
+ // const response = await fetch(`/api/store/items`);
+ // const DBStoreItems = await response.json();
+ // setStoreItems(DBStoreItems.message);
+ };
+
+ fetchBankAccounts();
+ fetchStakingSources();
+ fetchInventoryItems();
+ fetchStoreItems();
+ }, []);
+
+ // Use effect to update the items on staking sources when inventoryItems are updated
+ useEffect(() => {
+ const updateItemsOnStakingSources = () => {
+ const updatedStakingSources = stakingSources?.map((source) => {
+ const item = inventoryItems?.find(
+ (item) => source.inventoryItem?.id === item.id
+ );
+ if (item) {
+ return { ...source, inventoryItem: item };
+ } else {
+ return source;
+ }
+ });
+ updatedStakingSources && setStakingSources(updatedStakingSources);
+ };
+ if (stakingSources && stakingSources?.length > 0) {
+ updateItemsOnStakingSources();
+ }
+ }, [inventoryItems]);
+
+ const handleAddItem = (
+ inventoryItem: IInventoryItem,
+ stakingSource: IStakingSource
+ ) => {
+ const newStakingSources = stakingSources?.map((source) => {
+ if (source.id === stakingSource.id) {
+ return { ...source, inventoryItem: inventoryItem };
+ } else {
+ return source;
+ }
+ });
+
+ if (newStakingSources) {
+ setStakingSources(newStakingSources);
+ }
+ };
+
+ const handleBuy = (storeItem: IStoreItem) => {
+ const hasItem = inventoryItems?.some((item) => {
+ item.storeItem.id === storeItem.id;
+ });
+
+ if (hasItem) return;
+
+ const getNewIndex = () => {
+ if (!inventoryItems) return 0;
+ return inventoryItems.length;
+ };
+
+ const newInventoryItem = {
+ id: getNewIndex(),
+ stakingSource: null,
+ storeItem: storeItem,
+ currentTierIndex: 0,
+ };
+
+ if (inventoryItems && inventoryItems !== undefined) {
+ setInventoryItems([...inventoryItems, newInventoryItem]);
+ }
+ };
+
+ const claimResource = (
+ stakingSource: IStakingSource,
+ claimedResource: IClaimableResource
+ ): boolean => {
+ // Known bug: If a Inventory is already selected, and then upgraded, claiming will be from old tier
+ const bankAccount = getBankAccount(claimedResource.resourceType);
+ if (!bankAccount) return false;
+
+ decrementResourceWell(stakingSource, claimedResource);
+ incrementBalance(bankAccount, claimedResource.balance);
+
+ return true;
+ };
+
+ const decrementResourceWell = (
+ stakingSource: IStakingSource,
+ claimedResource: IClaimableResource
+ ) => {
+ const updatedResourceWells = stakingSource.resourceWells.map((well) => {
+ if (well.resourceType.name === claimedResource.resourceType.name) {
+ return { ...well, supply: well.supply - claimedResource.balance };
+ } else {
+ return well;
+ }
+ });
+
+ const updatedStakingSources = stakingSources?.map((source) => {
+ if (source.id === stakingSource.id) {
+ return { ...source, resourceWells: updatedResourceWells };
+ } else {
+ return source;
+ }
+ });
+
+ updatedStakingSources && setStakingSources(updatedStakingSources);
+ };
+
+ const decrementBalance = () => {};
+
+ const incrementBalance = (bankAccount: IBankAccount, amount: number) => {
+ const updatedBankAccounts = bankAccounts.map((account) => {
+ if (account.id === bankAccount.id) {
+ return { ...account, balance: account.balance + amount };
+ } else {
+ return account;
+ }
+ });
+ setBankAccounts(updatedBankAccounts);
+ };
+
+ const getStoreItemConfiguration = () => {};
+
+ const getBankAccount = (resourceType: IResourceType) => {
+ return getObjectFromArray(bankAccounts, "resourceType", resourceType);
+ };
+
+ const handleIncrementTier = (inventoryItem: IInventoryItem) => {
+ console.log("Incrementing Tier");
+ // Check user has balance
+ // Decrement user balance
+
+ if (inventoryItem.currentTierIndex === 4) return;
+
+ const updatedInventoryItems = inventoryItems?.map((item) => {
+ if (item.id === inventoryItem.id) {
+ return { ...item, currentTierIndex: item.currentTierIndex + 1 };
+ } else {
+ return item;
+ }
+ });
+
+ if (updatedInventoryItems !== undefined)
+ setInventoryItems(updatedInventoryItems);
+ };
+
+ const handleSetLightBox = () => {
+ setLightBoxIsActive(!lightBoxIsActive);
+ };
+
+ const renderLightBox = () => {
+ if (lightBoxIsActive) return ;
+ };
+
return (
<>
-
+
-
-
-
+
+
+
>
);
diff --git a/src/pages/api/hello.ts b/src/pages/api/hello.ts
deleted file mode 100644
index 78a0eba..0000000
--- a/src/pages/api/hello.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import type { NextApiRequest, NextApiResponse } from "next";
-
-type Data = {
- name: string;
-};
-
-export default function handler(
- req: NextApiRequest,
- res: NextApiResponse
-) {
- res.status(200).json({ name: "Moon Miners!" });
-}
diff --git a/src/pages/api/store/items.ts b/src/pages/api/store/items.ts
new file mode 100644
index 0000000..ac4f044
--- /dev/null
+++ b/src/pages/api/store/items.ts
@@ -0,0 +1,80 @@
+import type { NextApiRequest, NextApiResponse } from "next";
+import { IStoreItem } from "typings";
+
+export default function handler(req: NextApiRequest, res: NextApiResponse) {
+ try {
+ if (req.method === "GET") {
+ // query all store items
+ const storeItems: IStoreItem[] = [
+ {
+ id: 1,
+ name: "Eclipse Drill",
+ description:
+ "A compact and lightweight drill designed for use in tight and narrow mining tunnels.",
+ price: 225,
+ timeToClaim: 3,
+ tiers: [
+ {
+ tier: 500,
+ price: 50,
+ },
+ {
+ tier: 600,
+ price: 75,
+ },
+ {
+ tier: 700,
+ price: 100,
+ },
+ {
+ tier: 800,
+ price: 150,
+ },
+ {
+ tier: 900,
+ price: 200,
+ },
+ ],
+ },
+ {
+ id: 2,
+ name: "Moon Saw 2000",
+ description:
+ "A compact and lightweight drill designed for use in tight and narrow mining tunnels.",
+ price: 100,
+ timeToClaim: 3,
+ tiers: [
+ {
+ tier: 500,
+ price: 50,
+ },
+ {
+ tier: 550,
+ price: 75,
+ },
+ {
+ tier: 600,
+ price: 100,
+ },
+ {
+ tier: 650,
+ price: 150,
+ },
+ {
+ tier: 700,
+ price: 200,
+ },
+ ],
+ },
+ ];
+
+ // if no store items send empty array
+ if (!storeItems) return res.status(200).json({ message: [] });
+
+ // if store items found send store items
+ return res.status(200).json({ message: storeItems });
+ }
+ } catch (error) {
+ res.status(500).json({ message: "Unexpexted server error" });
+ }
+}
diff --git a/src/pages/api/user/[userId]/bank-accounts.ts b/src/pages/api/user/[userId]/bank-accounts.ts
new file mode 100644
index 0000000..131a35e
--- /dev/null
+++ b/src/pages/api/user/[userId]/bank-accounts.ts
@@ -0,0 +1,73 @@
+import type { NextApiRequest, NextApiResponse } from "next";
+import { IBankAccount, IResourceType } from "typings";
+
+export default function handler(req: NextApiRequest, res: NextApiResponse) {
+ try {
+ if (req.method === "GET") {
+ const { userId } = req.query;
+
+ // query db for user ID
+ const user = true;
+ // if user not found send error
+ if (!user) return res.status(404).json({ message: "User not found" });
+
+ // if user found query all bank accounts attached to this user
+ const DBresourceTypes: IResourceType[] = [
+ {
+ id: 1,
+ name: "Moonstone",
+ fontColorClass: "text-teal-400",
+ bgColorClass: "from-teal-800 to-teal-900",
+ },
+ {
+ id: 2,
+ name: "Lunarite",
+ fontColorClass: "text-cyan-400",
+ bgColorClass: "from-cyan-800 to-cyan-900",
+ },
+ {
+ id: 3,
+ name: "Selenite",
+ fontColorClass: "text-purple-300",
+ bgColorClass: "from-purple-800 to-purple-900",
+ },
+ {
+ id: 4,
+ name: "Heliogem",
+ fontColorClass: "text-rose-300",
+ bgColorClass: "from-rose-800 to-rose-900",
+ },
+ ];
+ const bankAccounts: IBankAccount[] = [
+ {
+ id: 1,
+ resourceType: DBresourceTypes[0],
+ balance: 0,
+ },
+ {
+ id: 2,
+ resourceType: DBresourceTypes[1],
+ balance: 0,
+ },
+ {
+ id: 3,
+ resourceType: DBresourceTypes[2],
+ balance: 0,
+ },
+ {
+ id: 4,
+ resourceType: DBresourceTypes[3],
+ balance: 0,
+ },
+ ];
+
+ // if bank accounts not found send empty array
+ if (!bankAccounts) return res.status(200).json({ message: [] });
+
+ // if bank accounts found send bank accounts
+ return res.status(200).json({ message: bankAccounts });
+ }
+ } catch (error) {
+ res.status(500).json({ message: "Unexpexted server error" });
+ }
+}
diff --git a/src/pages/api/user/[userId]/inventory-items.ts b/src/pages/api/user/[userId]/inventory-items.ts
new file mode 100644
index 0000000..16d54ea
--- /dev/null
+++ b/src/pages/api/user/[userId]/inventory-items.ts
@@ -0,0 +1,32 @@
+import type { NextApiRequest, NextApiResponse } from "next";
+import { IInventoryItem } from "typings";
+
+export default function handler(req: NextApiRequest, res: NextApiResponse) {
+ try {
+ if (req.method === "GET") {
+ const { userId } = req.query;
+
+ // query db for user ID
+ const user = true;
+ // if user not found send error
+ if (!user) return res.status(404).json({ message: "User not found" });
+
+ // if user found query all inventory items attached to this user
+ const inventoryItems: IInventoryItem[] = [
+ {
+ id: 123,
+ storeItem: "Example StoreItem",
+ currentTierIndex: 0,
+ },
+ ];
+
+ // if inventory items not found send empty array
+ if (!inventoryItems) return res.status(200).json({ message: [] });
+
+ // if inventory items found send inventory items
+ return res.status(200).json({ message: inventoryItems });
+ }
+ } catch (error) {
+ res.status(500).json({ message: "Unexpexted server error" });
+ }
+}
diff --git a/src/pages/api/user/[userId]/staking-sources.ts b/src/pages/api/user/[userId]/staking-sources.ts
new file mode 100644
index 0000000..82caad3
--- /dev/null
+++ b/src/pages/api/user/[userId]/staking-sources.ts
@@ -0,0 +1,35 @@
+import type { NextApiRequest, NextApiResponse } from "next";
+import { IStakingSource } from "typings";
+
+export default function handler(req: NextApiRequest, res: NextApiResponse) {
+ try {
+ if (req.method === "GET") {
+ const { userId } = req.query;
+
+ // query db for user ID
+ const user = true;
+ // if user not found send error
+ if (!user) return res.status(404).json({ message: "User not found" });
+
+ // if user found query all staking sources attached to this user
+ const stakingSources: IStakingSource[] = [
+ {
+ id: 1,
+ name: "Selene's Eye",
+ description:
+ "Selene's Eye is a large and mysterious moon, named for its distinctive appearance - a bright, glowing eye that seems to stare out from the void of space",
+ resourceWells: "Example DBresourceWells",
+ inventoryItem: null,
+ },
+ ];
+
+ // if staking sources not found send empty array
+ if (!stakingSources) return res.status(200).json({ message: [] });
+
+ // if staking sources found send staking sources
+ return res.status(200).json({ message: stakingSources });
+ }
+ } catch (error) {
+ res.status(500).json({ message: "Unexpexted server error" });
+ }
+}
diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts
index 7de1cd2..f58d17b 100644
--- a/src/utils/helpers.ts
+++ b/src/utils/helpers.ts
@@ -1,3 +1,9 @@
-export default function getObjectFromArray(array: T[], key: keyof T, value: any): T | undefined {
+export function getObjectFromArray(array: T[], key: keyof T, value: any): T | undefined {
return array.find(obj => obj[key] === value);
+ }
+
+export function pushElementToArray(array: T[], element: T): T[] {
+ const newArray = [...array]; // create a new array
+ newArray.push(element); // add the new element to the array
+ return newArray; // return the new array
}
\ No newline at end of file
diff --git a/tsconfig.json b/tsconfig.json
index 6a9c1a2..dc36fb0 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,9 +1,12 @@
{
"compilerOptions": {
"target": "es5",
- "lib": ["dom", "dom.iterable", "esnext"],
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
"allowJs": true,
- "skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
@@ -21,9 +24,19 @@
],
"baseUrl": ".",
"paths": {
- "@/*": ["./src/*"]
- }
+ "@/*": [
+ "./src/*"
+ ]
+ },
+ "skipLibCheck": true
},
- "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
- "exclude": ["node_modules"]
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ ".next/types/**/*.ts"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
}
diff --git a/typings.d.ts b/typings.d.ts
index c1ee1ba..e607270 100644
--- a/typings.d.ts
+++ b/typings.d.ts
@@ -1,45 +1,54 @@
+export type User = {
+ id: number;
+ inventoryItems: IInventoryItem[];
+};
-export type Resource = {
- name: string,
- fontColorClass: string,
- bgColorClass: string
+export interface IResourceType {
+ id: number;
+ name: string;
+ fontColorClass: string;
+ bgColorClass: string;
}
-export interface IResourceCardProps {
- resource: Resource,
- isMining: boolean,
- yieldPerSecond: number
+export interface IResourceWell {
+ id: number;
+ resourceType: IResourceType;
+ supply: number;
}
-export type Modifier = {
- resource: Resource | undefined,
- yield: number
+export interface IStakingSource {
+ id: number;
+ name: string;
+ description: string;
+ resourceWells: IResourceWell[];
+ inventoryItem: IInventoryItem | null;
}
-export type Yield = {
- resource: Resource | undefined,
- baseYield: number
+export interface IInventoryItem {
+ id: number;
+ storeItem: IStoreItem;
+ currentTierIndex: number;
}
-export type Moon = {
- name: string,
- description: string,
- resources: Resource[]
- drill: Drill | null
+export interface IStoreItem {
+ id: number;
+ name: string;
+ description: string;
+ price: number;
+ timeToClaim: number;
+ tiers: {
+ tier: number;
+ price: number;
+ }[];
}
-export type Drill = {
- name: string,
- description: string,
- price: number,
- yield: Yield[]
- upgrades: Upgrade[] | null
+export interface IBankAccount {
+ id: number;
+ resourceType: IResourceType;
+ balance: number;
}
-export type Upgrade = {
- name: string,
- description: string,
- price: number,
- modifiers: Modifier[]
- owned: boolean
-}
\ No newline at end of file
+export interface IClaimableResource {
+ resourceType: IResourceType;
+ balance: number;
+}