refactor resourceStore
This commit is contained in:
parent
b84b8eadb5
commit
e20775068f
123
src/app/Components/Accounts/Account.tsx
Normal file
123
src/app/Components/Accounts/Account.tsx
Normal file
@ -0,0 +1,123 @@
|
||||
"use client";
|
||||
import React, { useState } from "react";
|
||||
import { IResourceAccount, IConversionPair } from "typings";
|
||||
import { resourceToFc } from "../../../utils/helpers";
|
||||
import ResourceModal from "./ResourceModal";
|
||||
|
||||
const ResourceAccount = (props: {
|
||||
account: IResourceAccount;
|
||||
sellResource: (pairs: IConversionPair[]) => void;
|
||||
}) => {
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const [conversionPair, setConversionPair] = useState<
|
||||
IConversionPair | undefined
|
||||
>(undefined);
|
||||
const [conversionRate, setConversionRate] = useState<Number>(0.1);
|
||||
|
||||
const handleConversionPair = (amount: number, resourceType: string) => {
|
||||
const updatedPair = {
|
||||
resourceType: resourceType,
|
||||
resourceAmount: amount,
|
||||
moneyAmount: amount * conversionRate.valueOf(),
|
||||
};
|
||||
setConversionPair(updatedPair);
|
||||
};
|
||||
console.log(conversionPair);
|
||||
return (
|
||||
<>
|
||||
{showModal && (
|
||||
<div className="z-10 fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center">
|
||||
<div className="p-8 relative w-96">
|
||||
<button
|
||||
onClick={() => {
|
||||
setShowModal(!showModal);
|
||||
}}
|
||||
className="text-white absolute top-0"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
strokeWidth={2}
|
||||
stroke="currentColor"
|
||||
className="w-6 h-6"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<div className="md:h-auto max-w-md max-h-full overflow-y-auto">
|
||||
<ResourceModal
|
||||
resourceAccount={props.account}
|
||||
conversionPair={conversionPair}
|
||||
handleConversionPair={handleConversionPair}
|
||||
/>
|
||||
{
|
||||
<div className="mt-2 bg-white rounded-lg p-3">
|
||||
<p className="mb-0 text-2xl font-bold text-black">
|
||||
Grand total
|
||||
</p>
|
||||
<p className="mb-2 text-2xl font-bold underline text-green-700">
|
||||
${" "}
|
||||
{conversionPair
|
||||
? conversionPair.moneyAmount.toLocaleString("en-US", {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})
|
||||
: 0}
|
||||
</p>
|
||||
{conversionPair && (
|
||||
<button
|
||||
onClick={() => props.sellResource([conversionPair])}
|
||||
className="bg-green-700 py-2 text-slate-900 rounded-lg font-bold w-28 text-center text-white"
|
||||
>
|
||||
Sell Now
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex-1 md:mb-0 mb-2 bg-gradient-to-tr from-purple-600 via-blue-600 to-indigo-700 h-auto p-1 rounded-xl">
|
||||
<div className="relative bg-slate-900 text-white px-8 py-4 rounded-xl">
|
||||
<span
|
||||
className={resourceToFc(props.account.resourceType) + " font-bold"}
|
||||
>
|
||||
{props.account.resourceType}
|
||||
</span>
|
||||
<h3 className="text-2xl font-bold">
|
||||
{props.account.balance.toLocaleString("en-US", {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}{" "}
|
||||
kg
|
||||
</h3>
|
||||
<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 absolute right-0 top-0 mt-4 mr-4"
|
||||
onClick={() => {
|
||||
setShowModal(!showModal);
|
||||
}}
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M2.25 18.75a60.07 60.07 0 0115.797 2.101c.727.198 1.453-.342 1.453-1.096V18.75M3.75 4.5v.75A.75.75 0 013 6h-.75m0 0v-.375c0-.621.504-1.125 1.125-1.125H20.25M2.25 6v9m18-10.5v.75c0 .414.336.75.75.75h.75m-1.5-1.5h.375c.621 0 1.125.504 1.125 1.125v9.75c0 .621-.504 1.125-1.125 1.125h-.375m1.5-1.5H21a.75.75 0 00-.75.75v.75m0 0H3.75m0 0h-.375a1.125 1.125 0 01-1.125-1.125V15m1.5 1.5v-.75A.75.75 0 003 15h-.75M15 10.5a3 3 0 11-6 0 3 3 0 016 0zm3 0h.008v.008H18V10.5zm-12 0h.008v.008H6V10.5z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ResourceAccount;
|
@ -1,12 +1,12 @@
|
||||
"use client";
|
||||
import React from "react";
|
||||
import { IBankAccount } from "typings";
|
||||
import ResourceAccount from "./ResourceAccount";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { IBankAccount, IConversionPair } from "typings";
|
||||
import Account from "./Account";
|
||||
import { BiLoaderAlt } from "react-icons/bi";
|
||||
|
||||
const BankAccountsView = (props: {
|
||||
bankAccount: IBankAccount | undefined;
|
||||
setLightBoxIsActive: () => void;
|
||||
sellResource: (pairs: IConversionPair[]) => void;
|
||||
}) => {
|
||||
if (props.bankAccount === undefined) {
|
||||
return (
|
||||
@ -15,10 +15,11 @@ const BankAccountsView = (props: {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="p-4">
|
||||
<div className="flex items-center gap-8">
|
||||
<div className="flex-1 bg-gradient-to-tr from-purple-600 via-blue-600 to-indigo-700 h-auto p-1 rounded-xl">
|
||||
<div className="md:flex items-center gap-8">
|
||||
<div className="flex-1 md:mb-0 mb-2 bg-gradient-to-tr from-purple-600 via-blue-600 to-indigo-700 h-auto p-1 rounded-xl">
|
||||
<div className="text-white bg-slate-900 px-8 py-4 rounded-xl">
|
||||
<span className="text-green-600 font-bold">Moonbucks</span>
|
||||
<h3 className="text-2xl font-bold">
|
||||
@ -33,7 +34,13 @@ const BankAccountsView = (props: {
|
||||
{props.bankAccount &&
|
||||
props.bankAccount?.resourceAccounts.length > 0 &&
|
||||
props.bankAccount.resourceAccounts.map((account, id) => {
|
||||
return <ResourceAccount key={id} account={account} />;
|
||||
return (
|
||||
<Account
|
||||
key={id}
|
||||
account={account}
|
||||
sellResource={props.sellResource}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
110
src/app/Components/Accounts/Old/ResourceStore.tsx
Normal file
110
src/app/Components/Accounts/Old/ResourceStore.tsx
Normal file
@ -0,0 +1,110 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import ResourceStoreItem from "../ResourceModal";
|
||||
import { sumValues } from "../../../../utils/helpers";
|
||||
import { IBankAccount, IConversionPair } from "typings";
|
||||
|
||||
const ResourceStore = (props: {
|
||||
bankAccount: IBankAccount | undefined;
|
||||
sellResource: (pairs: IConversionPair[]) => void;
|
||||
}) => {
|
||||
const [conversionRate, setConversionRate] = useState<Number>(0.1);
|
||||
const [conversionPairs, setConversionPairs] = useState<
|
||||
IConversionPair[] | null
|
||||
>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (props.bankAccount) {
|
||||
const pairs = props.bankAccount.resourceAccounts.map((resource) => ({
|
||||
resourceType: resource.resourceType,
|
||||
resourceAmount: 0,
|
||||
moneyAmount: 0,
|
||||
}));
|
||||
setConversionPairs(pairs);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleConversionPairs = (amount: number, resourceType: string) => {
|
||||
if (!conversionPairs) return;
|
||||
|
||||
const existingObj = conversionPairs.find(
|
||||
(obj) => obj.resourceType === resourceType
|
||||
);
|
||||
|
||||
const updatedPairs = conversionPairs.map((pair) => {
|
||||
if (pair.resourceType === existingObj?.resourceType) {
|
||||
return {
|
||||
...pair,
|
||||
resourceAmount: amount,
|
||||
moneyAmount: amount * conversionRate.valueOf(),
|
||||
};
|
||||
} else {
|
||||
return pair;
|
||||
}
|
||||
});
|
||||
setConversionPairs(updatedPairs);
|
||||
};
|
||||
|
||||
const getConversionPair = (resourceType: string) => {
|
||||
return conversionPairs?.find((obj) => obj.resourceType === resourceType);
|
||||
};
|
||||
|
||||
const handleSellResources = async () => {
|
||||
if (conversionPairs) {
|
||||
const response = props.sellResource(conversionPairs);
|
||||
// if ok clear pairs
|
||||
// setConversionPairs(null);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="bg-gradient-to-tr from-purple-600 via-blue-600 to-indigo-700 h-auto p-1 rounded-xl rounded-xl col-span-2">
|
||||
<div className="bg-slate-900 text-white p-4 md:p-8 rounded-xl">
|
||||
<h1 className="text-white text-3xl font-bold">Sell Resources</h1>
|
||||
<div className="flex gap-4 mt-4">
|
||||
<div className="flex-1">
|
||||
{props.bankAccount &&
|
||||
props.bankAccount.resourceAccounts.map((resourceAccount, id) => (
|
||||
<div key={id} className="flex mb-4 gap-4">
|
||||
<div className="flex-1">
|
||||
<ResourceStoreItem
|
||||
resourceAccount={resourceAccount}
|
||||
conversionPair={getConversionPair(
|
||||
resourceAccount.resourceType
|
||||
)}
|
||||
handleConversionPairs={handleConversionPairs}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
{conversionPairs && (
|
||||
<div className="bg-slate-200 rounded-lg p-3">
|
||||
<p className="mb-0 text-2xl font-bold text-black">
|
||||
Grand total
|
||||
</p>
|
||||
<p className="mb-3 text-2xl font-bold underline text-green-700">
|
||||
${" "}
|
||||
{sumValues(conversionPairs, "moneyAmount").toLocaleString(
|
||||
"en-US",
|
||||
{
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
<button
|
||||
onClick={handleSellResources}
|
||||
className="bg-green-700 py-2 text-slate-900 rounded-lg font-bold w-28 text-center text-white"
|
||||
>
|
||||
Sell Now
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ResourceStore;
|
121
src/app/Components/Accounts/ResourceModal.tsx
Normal file
121
src/app/Components/Accounts/ResourceModal.tsx
Normal file
@ -0,0 +1,121 @@
|
||||
"use client";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { IResourceAccount, IConversionPair } from "typings";
|
||||
import { resourceToBg, resourceToFc } from "../../../utils/helpers";
|
||||
|
||||
const ResourceModal = (props: {
|
||||
resourceAccount: IResourceAccount;
|
||||
conversionPair: IConversionPair | undefined;
|
||||
handleConversionPair: (amount: number, resourceType: string) => void;
|
||||
}) => {
|
||||
const [error, setError] = useState("");
|
||||
|
||||
const handleAmountChange = (
|
||||
e: React.ChangeEvent<HTMLInputElement>,
|
||||
resourceType: string
|
||||
) => {
|
||||
console.log("Changing amount");
|
||||
const amount = Number(e.target.value);
|
||||
if (amount <= props.resourceAccount.balance) {
|
||||
props.handleConversionPair(amount, resourceType);
|
||||
if (error) setError("");
|
||||
} else {
|
||||
setError("You don't have enough");
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
resourceToBg(props.resourceAccount.resourceType) +
|
||||
" bg-gradient-to-br hover:bg-gradient-to-tr rounded-lg p-3"
|
||||
}
|
||||
>
|
||||
<div className="text-white mr-4">
|
||||
<span
|
||||
className={
|
||||
resourceToFc(props.resourceAccount.resourceType) + " font-bold"
|
||||
}
|
||||
>
|
||||
{props.resourceAccount.resourceType}
|
||||
</span>
|
||||
<h3 className="md:text-2xl font-bold">
|
||||
{props.resourceAccount.balance.toLocaleString("en-US", {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}{" "}
|
||||
kg
|
||||
</h3>
|
||||
</div>
|
||||
<div className="text-white mt-4">
|
||||
<div className="flex">
|
||||
<span>
|
||||
<span
|
||||
className={
|
||||
resourceToFc(props.resourceAccount.resourceType) + " font-bold"
|
||||
}
|
||||
>
|
||||
Amount
|
||||
</span>
|
||||
<h3 className="md:text-2xl font-bold">
|
||||
{props.conversionPair
|
||||
? props.conversionPair.resourceAmount.toLocaleString("en-US", {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})
|
||||
: 0}{" "}
|
||||
kg.
|
||||
</h3>
|
||||
</span>
|
||||
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
strokeWidth="2.5"
|
||||
stroke="currentColor"
|
||||
className="w-6 h-6 mt-4 mx-4"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M17.25 8.25L21 12m0 0l-3.75 3.75M21 12H3"
|
||||
/>
|
||||
</svg>
|
||||
<span>
|
||||
<span
|
||||
className={
|
||||
resourceToFc(props.resourceAccount.resourceType) + " font-bold"
|
||||
}
|
||||
>
|
||||
Moonbucks
|
||||
</span>
|
||||
<h3 className="md:text-2xl font-bold">
|
||||
$
|
||||
{props.conversionPair
|
||||
? props.conversionPair.moneyAmount.toLocaleString("en-US", {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})
|
||||
: 0}
|
||||
</h3>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
{error && (
|
||||
<span className="text-red-500 font-bold mb-1 text-sm">{error}</span>
|
||||
)}
|
||||
<input
|
||||
type="text"
|
||||
className="bg-white px-4 py-2 mr-2 mt-4 rounded-lg h-full"
|
||||
placeholder="0"
|
||||
onChange={(e) =>
|
||||
handleAmountChange(e, props.resourceAccount.resourceType)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ResourceModal;
|
@ -1,6 +1,6 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { IInventoryItem, IStake } from "typings";
|
||||
import CardLayout from "../Layouts/CardLayout";
|
||||
import CardLayout from "../../Layouts/CardLayout";
|
||||
import Image from "next/image";
|
||||
const InventoryItem = (props: {
|
||||
inventoryItem: IInventoryItem;
|
||||
@ -35,7 +35,7 @@ const InventoryItem = (props: {
|
||||
};
|
||||
return (
|
||||
<CardLayout>
|
||||
<div className="flex gap-4">
|
||||
<div className="md:flex gap-4">
|
||||
<div className="flex-1">
|
||||
<h3 className="text-2xl font-bold mb-2">
|
||||
{props.inventoryItem.storeItem.name}
|
||||
@ -95,7 +95,7 @@ const InventoryItem = (props: {
|
||||
<span className="ml-1">({getNextUpgradePrice()})</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative object-contain w-48 h-48">
|
||||
<div className="relative object-contain w-48 h-48 mt-4 md:mt-0">
|
||||
<Image
|
||||
src={props.inventoryItem.storeItem.image}
|
||||
alt={props.inventoryItem.storeItem.name}
|
@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { IInventoryItem, IStakingSource, IStake } from "typings";
|
||||
import { IInventoryItem, IStake } from "typings";
|
||||
import InventoryItem from "./InventoryItem";
|
||||
|
||||
const InventoryItemView = (props: {
|
||||
@ -11,7 +11,7 @@ const InventoryItemView = (props: {
|
||||
<div className="bg-gradient-to-tr from-purple-600 via-blue-600 to-indigo-700 h-auto p-1 rounded-xl rounded-xl col-span-5">
|
||||
<div className="bg-slate-900 text-white p-8 rounded-xl">
|
||||
<h2 className="text-3xl font-bold mb-4">Your Inventory</h2>
|
||||
<div className="grid grid-cols-3 gap-8">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||
{props.inventoryItems &&
|
||||
props.inventoryItems.length > 0 &&
|
||||
props.inventoryItems.map((inventoryItem, id) => (
|
@ -88,7 +88,7 @@ export default function Navbar({
|
||||
<nav className="text-white flex justify-between mt-4">
|
||||
<button
|
||||
onClick={() => router.push("/")}
|
||||
className="p-2 m-4 text-3xl font-bold"
|
||||
className="p-2 m-4 text-xl md:text-3xl font-bold"
|
||||
>
|
||||
Moon Miners
|
||||
</button>
|
||||
@ -109,8 +109,8 @@ export default function Navbar({
|
||||
)}
|
||||
</button>
|
||||
) : (
|
||||
<div className="flex items-stretch">
|
||||
<button className="p-2 m-4 bg-slate-800 rounded-lg">
|
||||
<div className="flex">
|
||||
<button className="w-24 md:w-32 p-2 m-4 bg-slate-800 rounded-lg truncate">
|
||||
{walletAddress}
|
||||
</button>
|
||||
<button onClick={logout} className="p-2 m-4 bg-slate-800 rounded-lg">
|
@ -9,7 +9,6 @@ const menuItems: MenuItem[] = [
|
||||
{ name: "Moons", componentKey: "stakingsourcesview" },
|
||||
{ name: "Inventory", componentKey: "inventoryitemview" },
|
||||
{ name: "Buy Items", componentKey: "storeitemview" },
|
||||
{ name: "Sell Resources", componentKey: "resourcestore" },
|
||||
];
|
||||
|
||||
interface NavbarProps {
|
||||
@ -22,7 +21,7 @@ const NavbarVertical: React.FC<NavbarProps> = ({
|
||||
activeItem,
|
||||
}) => {
|
||||
return (
|
||||
<div className="">
|
||||
<div className="w-full col-span-5 md:col-span-1">
|
||||
<nav className="bg-gradient-to-tr from-purple-600 via-blue-600 to-indigo-700 h-auto p-1 rounded-xl">
|
||||
<ul className="bg-slate-900 p-8 rounded-xl">
|
||||
{menuItems.map((item) => (
|
@ -1,27 +0,0 @@
|
||||
"use client";
|
||||
import React from "react";
|
||||
import { IResourceAccount } from "typings";
|
||||
import { resourceToBg, resourceToFc } from "../../utils/helpers";
|
||||
|
||||
const ResourceAccount = (props: { account: IResourceAccount }) => {
|
||||
return (
|
||||
<div className="flex-1 bg-gradient-to-tr from-purple-600 via-blue-600 to-indigo-700 h-auto p-1 rounded-xl">
|
||||
<div className="bg-slate-900 text-white px-8 py-4 rounded-xl">
|
||||
<span
|
||||
className={resourceToFc(props.account.resourceType) + " font-bold"}
|
||||
>
|
||||
{props.account.resourceType}
|
||||
</span>
|
||||
<h3 className="text-2xl font-bold">
|
||||
{props.account.balance.toLocaleString("en-US", {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}{" "}
|
||||
kg
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ResourceAccount;
|
@ -1,100 +0,0 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import ResourceStoreItem from "./ResourceStoreItem";
|
||||
import { sumValues } from "../../utils/helpers";
|
||||
import { IBankAccount, IConversionPair } from "typings";
|
||||
|
||||
const ResourceStore = (props: { bankAccount: IBankAccount | undefined }) => {
|
||||
const [conversionRate, setConversionRate] = useState<Number>(0.1);
|
||||
const [conversionPairs, setConversionPairs] = useState<
|
||||
IConversionPair[] | null
|
||||
>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (props.bankAccount) {
|
||||
const pairs = props.bankAccount.resourceAccounts.map((resource) => ({
|
||||
resourceType: resource.resourceType,
|
||||
resourceAmount: 0,
|
||||
moneyAmount: 0,
|
||||
}));
|
||||
setConversionPairs(pairs);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleConversionPairs = (amount: number, resourceType: string) => {
|
||||
if (!conversionPairs) return;
|
||||
|
||||
const existingObj = conversionPairs.find(
|
||||
(obj) => obj.resourceType === resourceType
|
||||
);
|
||||
|
||||
const updatedPairs = conversionPairs.map((pair) => {
|
||||
if (pair.resourceType === existingObj?.resourceType) {
|
||||
return {
|
||||
...pair,
|
||||
resourceAmount: amount,
|
||||
moneyAmount: amount * conversionRate.valueOf(),
|
||||
};
|
||||
} else {
|
||||
return pair;
|
||||
}
|
||||
});
|
||||
setConversionPairs(updatedPairs);
|
||||
};
|
||||
|
||||
const getConversionPair = (resourceType: string) => {
|
||||
return conversionPairs?.find((obj) => obj.resourceType === resourceType);
|
||||
};
|
||||
|
||||
const handleSellResources = () => {
|
||||
// Do something..
|
||||
console.log(conversionPairs);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="bg-slate-800 rounded-lg p-4 col-span-2">
|
||||
<h1 className="text-white text-3xl font-bold">Sell Resources</h1>
|
||||
<div className="flex gap-4 mt-4">
|
||||
<div className="flex-1">
|
||||
{props.bankAccount &&
|
||||
props.bankAccount.resourceAccounts.map((resourceAccount) => (
|
||||
<div className="flex mb-4 gap-4">
|
||||
<div className="flex-1">
|
||||
<ResourceStoreItem
|
||||
resourceAccount={resourceAccount}
|
||||
conversionPair={getConversionPair(
|
||||
resourceAccount.resourceType
|
||||
)}
|
||||
handleConversionPairs={handleConversionPairs}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
{conversionPairs && (
|
||||
<div className="bg-slate-200 rounded-lg p-3">
|
||||
<p className="mb-0 text-2xl font-bold text-black">Grand total</p>
|
||||
<p className="mb-3 text-2xl font-bold underline text-green-700">
|
||||
${" "}
|
||||
{sumValues(conversionPairs, "moneyAmount").toLocaleString(
|
||||
"en-US",
|
||||
{
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
<button
|
||||
onClick={handleSellResources}
|
||||
className="bg-green-700 py-2 text-slate-900 rounded-lg font-bold w-28 text-center text-white"
|
||||
>
|
||||
Sell Now
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ResourceStore;
|
@ -1,122 +0,0 @@
|
||||
"use client";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { IResourceAccount, IConversionPair } from "typings";
|
||||
import { resourceToBg, resourceToFc } from "../../utils/helpers";
|
||||
|
||||
const ResourceStoreItem = (props: {
|
||||
resourceAccount: IResourceAccount;
|
||||
conversionPair: IConversionPair | undefined;
|
||||
handleConversionPairs: (amount: number, resourceType: string) => void;
|
||||
}) => {
|
||||
const [error, setError] = useState("");
|
||||
|
||||
const handleAmountChange = (
|
||||
e: React.ChangeEvent<HTMLInputElement>,
|
||||
resourceType: string
|
||||
) => {
|
||||
const amount = Number(e.target.value);
|
||||
if (amount <= props.resourceAccount.balance) {
|
||||
props.handleConversionPairs(amount, resourceType);
|
||||
if (error) setError("");
|
||||
} else {
|
||||
setError("You don't have enough");
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
resourceToBg(props.resourceAccount.resourceType) +
|
||||
" bg-gradient-to-br hover:bg-gradient-to-tr rounded-lg p-3 flex flex-row"
|
||||
}
|
||||
>
|
||||
<div className="text-white mr-4 flex-none">
|
||||
<span
|
||||
className={
|
||||
resourceToFc(props.resourceAccount.resourceType) + " font-bold"
|
||||
}
|
||||
>
|
||||
{props.resourceAccount.resourceType}
|
||||
</span>
|
||||
<h3 className="text-2xl font-bold">
|
||||
{props.resourceAccount.balance.toLocaleString("en-US", {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}{" "}
|
||||
kg
|
||||
</h3>
|
||||
</div>
|
||||
{props.conversionPair ? (
|
||||
<div className={"text-white flex-1 border-l border-white/25 pl-4"}>
|
||||
<div className="flex">
|
||||
<span>
|
||||
<span
|
||||
className={
|
||||
resourceToFc(props.resourceAccount.resourceType) +
|
||||
" font-bold"
|
||||
}
|
||||
>
|
||||
{props.conversionPair.resourceType}
|
||||
</span>
|
||||
<h3 className="text-2xl font-bold">
|
||||
{props.conversionPair.resourceAmount.toLocaleString("en-US", {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}{" "}
|
||||
kg.
|
||||
</h3>
|
||||
</span>
|
||||
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
strokeWidth="2.5"
|
||||
stroke="currentColor"
|
||||
className="w-6 h-6 mt-4 mx-4"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M17.25 8.25L21 12m0 0l-3.75 3.75M21 12H3"
|
||||
/>
|
||||
</svg>
|
||||
<span>
|
||||
<span
|
||||
className={
|
||||
resourceToFc(props.resourceAccount.resourceType) +
|
||||
" font-bold"
|
||||
}
|
||||
>
|
||||
Moonbucks
|
||||
</span>
|
||||
<h3 className="text-2xl font-bold">
|
||||
$
|
||||
{props.conversionPair.moneyAmount.toLocaleString("en-US", {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})}
|
||||
</h3>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex-1"></div>
|
||||
)}
|
||||
<div className="flex flex-col">
|
||||
{error && (
|
||||
<span className="text-red-500 font-bold mb-1 text-sm">{error}</span>
|
||||
)}
|
||||
<input
|
||||
type="text"
|
||||
className="bg-white px-4 py-2 mr-2 rounded-lg h-full"
|
||||
placeholder="0"
|
||||
onChange={(e) =>
|
||||
handleAmountChange(e, props.resourceAccount.resourceType)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ResourceStoreItem;
|
237
src/app/Components/Staking/StakingSource.tsx
Normal file
237
src/app/Components/Staking/StakingSource.tsx
Normal file
@ -0,0 +1,237 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { IInventoryItem, IStakingSource, IStake, IOption } from "typings";
|
||||
import {
|
||||
calculateRemainingTime,
|
||||
getObjectFromArray,
|
||||
} from "../../../utils/helpers";
|
||||
import SelectDropdown from "../SelectDropdown";
|
||||
import Image from "next/image";
|
||||
|
||||
const StakingSource = (props: {
|
||||
stakingSource: IStakingSource;
|
||||
inventoryItems: IInventoryItem[] | null | undefined;
|
||||
claimStake: (stakingEventId: number) => void;
|
||||
startStake: (
|
||||
inventoryItemId: number,
|
||||
storeItemId: string,
|
||||
wellId: number
|
||||
) => void;
|
||||
}) => {
|
||||
const [activeStakes, setActiveStakes] = useState<IStake[]>([]);
|
||||
const [selectedItemId, setSelectedItemId] = useState<number | null>(null);
|
||||
const [selectedStoreItemId, setSelectedStoreItemId] = useState<string | null>(
|
||||
null
|
||||
);
|
||||
const [selectedWellId, setSelectedWellId] = useState<number | null>(null);
|
||||
const [showInfo, setShowInfo] = useState(false);
|
||||
|
||||
// Check if claimable every second
|
||||
useEffect(() => {
|
||||
const updatedActiveStakes = props.stakingSource.activeStakes.map(
|
||||
(stake) => {
|
||||
const remainingTime = calculateRemainingTime(
|
||||
stake.startTime,
|
||||
stake.durationInMins
|
||||
);
|
||||
|
||||
const obj = {
|
||||
...stake,
|
||||
remainingTime: remainingTime,
|
||||
};
|
||||
|
||||
return obj;
|
||||
}
|
||||
);
|
||||
|
||||
const intervalId = setInterval(() => {
|
||||
setActiveStakes(updatedActiveStakes);
|
||||
}, 1000);
|
||||
|
||||
return () => {
|
||||
clearInterval(intervalId);
|
||||
};
|
||||
});
|
||||
|
||||
const handleStartMining = () => {
|
||||
if (selectedItemId && selectedWellId && selectedStoreItemId) {
|
||||
props.startStake(selectedItemId, selectedStoreItemId, selectedWellId);
|
||||
}
|
||||
};
|
||||
|
||||
const handleClaim = (stakingEventId: number) => {
|
||||
props.claimStake(stakingEventId);
|
||||
};
|
||||
|
||||
const handleSelectChange = (
|
||||
wellId: string,
|
||||
itemId: number,
|
||||
storeitemId: string
|
||||
) => {
|
||||
setSelectedWellId(Number(wellId));
|
||||
setSelectedStoreItemId(storeitemId);
|
||||
setSelectedItemId(itemId);
|
||||
};
|
||||
|
||||
const Countdown = (props: { remainingTime: number }) => {
|
||||
const hours = Math.floor((props.remainingTime / (1000 * 60 * 60)) % 24)
|
||||
.toString()
|
||||
.padStart(2, "0");
|
||||
const minutes = Math.floor((props.remainingTime / (1000 * 60)) % 60)
|
||||
.toString()
|
||||
.padStart(2, "0");
|
||||
const seconds = Math.floor((props.remainingTime / 1000) % 60)
|
||||
.toString()
|
||||
.padStart(2, "0");
|
||||
return (
|
||||
<span className="font-bold">
|
||||
{hours} : {minutes} : {seconds}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
const RenderButtonOrCountdown = (props: { stake: IStake }) => {
|
||||
if (!props.stake.remainingTime) return <p>Error</p>;
|
||||
|
||||
if (props.stake.remainingTime <= 0) {
|
||||
return (
|
||||
<button
|
||||
onClick={() => handleClaim(props.stake.id)}
|
||||
className="bg-slate-100 text-slate-900 px-4 py-2 rounded-lg font-bold text-center"
|
||||
>
|
||||
Claim
|
||||
</button>
|
||||
);
|
||||
} else {
|
||||
return <Countdown remainingTime={props.stake.remainingTime} />;
|
||||
}
|
||||
};
|
||||
|
||||
const isActive = (item: IInventoryItem): boolean => {
|
||||
return props.stakingSource.activeStakes.some(
|
||||
(obj) => obj.inventoryItemId === item.id
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex justify-center items-center">
|
||||
<div className="relative group">
|
||||
<Image
|
||||
src="/assets/moon_1.png"
|
||||
alt="Moon"
|
||||
width={props.stakingSource.size}
|
||||
height={props.stakingSource.size}
|
||||
onClick={() => setShowInfo(!showInfo)}
|
||||
className="hover:cursor-pointer"
|
||||
/>
|
||||
{showInfo && (
|
||||
<div className="z-10 fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center">
|
||||
<div className="w-full h-full md:h-auto max-w-md max-h-full overflow-y-auto">
|
||||
<div className="relative h-full md:h-auto text-white bg-gradient-to-tr from-purple-600 via-blue-600 to-indigo-700 h-auto md:rounded-xl h-auto p-1">
|
||||
<div className="h-full md:h-auto bg-slate-900 md:rounded-xl p-4">
|
||||
<button
|
||||
onClick={() => {
|
||||
setShowInfo(!showInfo);
|
||||
}}
|
||||
className="text-white absolute -right-0 mr-4"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
strokeWidth={2}
|
||||
stroke="currentColor"
|
||||
className="w-6 h-6"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<h3 className="text-3xl font-bold mb-2">
|
||||
{props.stakingSource.name}
|
||||
</h3>
|
||||
<p className="text-sm">{props.stakingSource.description}</p>
|
||||
<div className="flex-1">
|
||||
<p className="font-bold mt-4 mb-2">Active Drills</p>
|
||||
{activeStakes &&
|
||||
activeStakes.map((stake, id) => (
|
||||
<div
|
||||
key={id}
|
||||
className="border border-white rounded-xl p-3 mb-2 bg-black/20"
|
||||
>
|
||||
<p>
|
||||
<span className="font-bold">Drill: </span>
|
||||
{props.inventoryItems &&
|
||||
getObjectFromArray(
|
||||
props.inventoryItems,
|
||||
"id",
|
||||
stake.inventoryItemId
|
||||
)?.storeItem.name}
|
||||
</p>
|
||||
<p>
|
||||
<span className="font-bold">Resource: </span>
|
||||
{stake.resourceType}
|
||||
</p>
|
||||
<p className="mb-2">
|
||||
<span className="font-bold">Yield: </span>
|
||||
{stake.stakeAmount}
|
||||
</p>
|
||||
<RenderButtonOrCountdown stake={stake} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<p className="font-bold mt-4 mb-2">Inactive Drills</p>
|
||||
{props.inventoryItems &&
|
||||
props.inventoryItems.map(
|
||||
(item, id) =>
|
||||
!isActive(item) && (
|
||||
<div
|
||||
key={id}
|
||||
className="border border-white rounded-xl p-3 mb-2 bg-black/20"
|
||||
>
|
||||
<p className="font-bold">{item.storeItem.name}</p>
|
||||
<p className="mt-2">Select Resource</p>
|
||||
<div className="flex">
|
||||
<SelectDropdown
|
||||
options={props.stakingSource.resourceWells.map(
|
||||
(well): IOption => ({
|
||||
value: well.id,
|
||||
label: well.resourceType,
|
||||
})
|
||||
)}
|
||||
onChange={(value) =>
|
||||
handleSelectChange(
|
||||
value,
|
||||
item.id,
|
||||
item.storeItem.id
|
||||
)
|
||||
}
|
||||
isActive={selectedItemId === item.id}
|
||||
/>
|
||||
{selectedItemId === item.id ? (
|
||||
<button
|
||||
onClick={handleStartMining}
|
||||
className="bg-slate-100 text-slate-900 px-4 py-2 rounded-lg font-bold w-28 text-center ml-2"
|
||||
>
|
||||
Activate
|
||||
</button>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default StakingSource;
|
@ -43,7 +43,7 @@ const moons = [
|
||||
|
||||
interface RowProps {
|
||||
stakingSources: IStakingSource[];
|
||||
inventoryItems: IInventoryItem[];
|
||||
inventoryItems: IInventoryItem[] | undefined | null;
|
||||
claimStake: (stakingEventId: number) => void;
|
||||
startStake: (
|
||||
inventoryItemId: number,
|
||||
@ -59,7 +59,7 @@ const Row: React.FC<RowProps> = ({
|
||||
startStake,
|
||||
}) => {
|
||||
return (
|
||||
<div className="flex justify-between items-center w-full mb-8 mt-8">
|
||||
<div className="md:flex md:justify-between md:items-center w-full mb-8 mt-8">
|
||||
{stakingSources.map((stakingSource, index) => (
|
||||
<div key={index} className="w-full">
|
||||
<StakingSource
|
@ -1,237 +0,0 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { IInventoryItem, IStakingSource, IStake, IOption } from "typings";
|
||||
import CardLayout from "../Layouts/CardLayout";
|
||||
import {
|
||||
calculateRemainingTime,
|
||||
getObjectFromArray,
|
||||
} from "../../utils/helpers";
|
||||
import SelectDropdown from "./SelectDropdown";
|
||||
import Image from "next/image";
|
||||
|
||||
const StakingSource = (props: {
|
||||
stakingSource: IStakingSource;
|
||||
inventoryItems: IInventoryItem[] | null | undefined;
|
||||
claimStake: (stakingEventId: number) => void;
|
||||
startStake: (
|
||||
inventoryItemId: number,
|
||||
storeItemId: string,
|
||||
wellId: number
|
||||
) => void;
|
||||
}) => {
|
||||
const [activeStakes, setActiveStakes] = useState<IStake[]>([]);
|
||||
const [selectedItemId, setSelectedItemId] = useState<number | null>(null);
|
||||
const [selectedStoreItemId, setSelectedStoreItemId] = useState<string | null>(
|
||||
null
|
||||
);
|
||||
const [selectedWellId, setSelectedWellId] = useState<number | null>(null);
|
||||
const [showInfo, setShowInfo] = useState(false);
|
||||
|
||||
// Check if claimable every second
|
||||
useEffect(() => {
|
||||
const updatedActiveStakes = props.stakingSource.activeStakes.map(
|
||||
(stake) => {
|
||||
const remainingTime = calculateRemainingTime(
|
||||
stake.startTime,
|
||||
stake.durationInMins
|
||||
);
|
||||
|
||||
const obj = {
|
||||
...stake,
|
||||
remainingTime: remainingTime,
|
||||
};
|
||||
|
||||
return obj;
|
||||
}
|
||||
);
|
||||
|
||||
const intervalId = setInterval(() => {
|
||||
setActiveStakes(updatedActiveStakes);
|
||||
}, 1000);
|
||||
|
||||
return () => {
|
||||
clearInterval(intervalId);
|
||||
};
|
||||
});
|
||||
|
||||
const handleStartMining = () => {
|
||||
if (selectedItemId && selectedWellId && selectedStoreItemId) {
|
||||
props.startStake(selectedItemId, selectedStoreItemId, selectedWellId);
|
||||
}
|
||||
};
|
||||
|
||||
const handleClaim = (stakingEventId: number) => {
|
||||
props.claimStake(stakingEventId);
|
||||
};
|
||||
|
||||
const handleSelectChange = (
|
||||
wellId: string,
|
||||
itemId: number,
|
||||
storeitemId: string
|
||||
) => {
|
||||
setSelectedWellId(Number(wellId));
|
||||
setSelectedStoreItemId(storeitemId);
|
||||
setSelectedItemId(itemId);
|
||||
};
|
||||
|
||||
const Countdown = (props: { remainingTime: number }) => {
|
||||
const hours = Math.floor((props.remainingTime / (1000 * 60 * 60)) % 24)
|
||||
.toString()
|
||||
.padStart(2, "0");
|
||||
const minutes = Math.floor((props.remainingTime / (1000 * 60)) % 60)
|
||||
.toString()
|
||||
.padStart(2, "0");
|
||||
const seconds = Math.floor((props.remainingTime / 1000) % 60)
|
||||
.toString()
|
||||
.padStart(2, "0");
|
||||
return (
|
||||
<span className="font-bold">
|
||||
{hours} : {minutes} : {seconds}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
const RenderButtonOrCountdown = (props: { stake: IStake }) => {
|
||||
if (!props.stake.remainingTime) return <p>Error</p>;
|
||||
|
||||
if (props.stake.remainingTime <= 0) {
|
||||
return (
|
||||
<button
|
||||
onClick={() => handleClaim(props.stake.id)}
|
||||
className="bg-slate-100 text-slate-900 px-4 py-2 rounded-lg font-bold text-center"
|
||||
>
|
||||
Claim
|
||||
</button>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
// I'll fix it
|
||||
<Countdown remainingTime={props.stake.remainingTime} />
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const isActive = (item: IInventoryItem): boolean => {
|
||||
return props.stakingSource.activeStakes.some(
|
||||
(obj) => obj.inventoryItemId === item.id
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex justify-center items-center">
|
||||
<div className="relative group">
|
||||
<Image
|
||||
src="/assets/moon_1.png"
|
||||
alt="Moon"
|
||||
width={props.stakingSource.size}
|
||||
height={props.stakingSource.size}
|
||||
onClick={() => setShowInfo(!showInfo)}
|
||||
className="hover:cursor-pointer"
|
||||
/>
|
||||
{showInfo && (
|
||||
<div className="absolute -right-0 top-1/2 transform -translate-y-1/2 w-96">
|
||||
<div className="bg-slate-500 border-2 border-white rounded-xl p-4 text-white">
|
||||
<button
|
||||
onClick={() => {
|
||||
setShowInfo(!showInfo);
|
||||
}}
|
||||
className="text-white absolute -right-0 mr-4"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
strokeWidth={2}
|
||||
stroke="currentColor"
|
||||
className="w-6 h-6"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<h3 className="text-xl font-bold mb-2">
|
||||
{props.stakingSource.name}
|
||||
</h3>
|
||||
<p className="text-sm">{props.stakingSource.description}</p>
|
||||
<div className="flex-1">
|
||||
<p className="font-bold mt-4 mb-2">Active Drills</p>
|
||||
{activeStakes &&
|
||||
activeStakes.map((stake, id) => (
|
||||
<div
|
||||
key={id}
|
||||
className="border border-white rounded-xl p-3 mb-2 bg-black/20"
|
||||
>
|
||||
<p>
|
||||
<span className="font-bold">Drill: </span>
|
||||
{props.inventoryItems &&
|
||||
getObjectFromArray(
|
||||
props.inventoryItems,
|
||||
"id",
|
||||
stake.inventoryItemId
|
||||
)?.storeItem.name}
|
||||
</p>
|
||||
<p>
|
||||
<span className="font-bold">Resource: </span>
|
||||
{stake.resourceType}
|
||||
</p>
|
||||
<p className="mb-2">
|
||||
<span className="font-bold">Yield: </span>
|
||||
{stake.stakeAmount}
|
||||
</p>
|
||||
<RenderButtonOrCountdown stake={stake} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<p className="font-bold mt-4 mb-2">Inactive Drills</p>
|
||||
{props.inventoryItems &&
|
||||
props.inventoryItems.map(
|
||||
(item, id) =>
|
||||
!isActive(item) && (
|
||||
<div
|
||||
key={id}
|
||||
className="border border-white rounded-xl p-3 mb-2 bg-black/20"
|
||||
>
|
||||
<p className="font-bold">{item.storeItem.name}</p>
|
||||
<p className="mt-2">Select Resource</p>
|
||||
<div className="flex">
|
||||
<SelectDropdown
|
||||
options={props.stakingSource.resourceWells.map(
|
||||
(well): IOption => ({
|
||||
value: well.id,
|
||||
label: well.resourceType,
|
||||
})
|
||||
)}
|
||||
onChange={(value) =>
|
||||
handleSelectChange(
|
||||
value,
|
||||
item.id,
|
||||
item.storeItem.id
|
||||
)
|
||||
}
|
||||
isActive={selectedItemId === item.id}
|
||||
/>
|
||||
{selectedItemId === item.id ? (
|
||||
<button
|
||||
onClick={handleStartMining}
|
||||
className="bg-slate-100 text-slate-900 px-4 py-2 rounded-lg font-bold w-28 text-center ml-2"
|
||||
>
|
||||
Activate
|
||||
</button>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default StakingSource;
|
@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
import React, { useState } from "react";
|
||||
import React from "react";
|
||||
import { IStoreItem } from "typings";
|
||||
import CardLayout from "../Layouts/CardLayout";
|
||||
import CardLayout from "../../Layouts/CardLayout";
|
||||
import Image from "next/image";
|
||||
|
||||
const StoreItem = (props: {
|
||||
@ -10,7 +10,7 @@ const StoreItem = (props: {
|
||||
}) => {
|
||||
return (
|
||||
<CardLayout>
|
||||
<div className="flex ">
|
||||
<div className="md:flex">
|
||||
<div className="flex-1 pr-4 mr-4">
|
||||
<h3 className="text-2xl font-bold mb-2">{props.storeItem.name}</h3>
|
||||
<p className="text-sm mb-3">{props.storeItem.description}</p>
|
||||
@ -42,7 +42,7 @@ const StoreItem = (props: {
|
||||
src={props.storeItem.image}
|
||||
alt={props.storeItem.name}
|
||||
fill
|
||||
className="rounded-lg border border-white/20 shadow-lg object-contain"
|
||||
className="rounded-lg border border-white/20 shadow-lg object-contain mt-4 md:mt-0"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
32
src/app/Components/Store/StoreItemView.tsx
Normal file
32
src/app/Components/Store/StoreItemView.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
import React from "react";
|
||||
import { IInventoryItem, IStoreItem } from "typings";
|
||||
import StoreItem from "./StoreItem";
|
||||
|
||||
const StoreItemView = (props: {
|
||||
inventoryItems: IInventoryItem[] | null | undefined;
|
||||
storeItems: IStoreItem[];
|
||||
buyStoreItem: (itemId: string) => void;
|
||||
}) => {
|
||||
return (
|
||||
<div className="bg-gradient-to-tr from-purple-600 via-blue-600 to-indigo-700 h-auto p-1 rounded-xl rounded-xl col-span-5">
|
||||
<div className="bg-slate-900 text-white p-8 rounded-xl">
|
||||
<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.length > 0 &&
|
||||
props.storeItems
|
||||
.filter((item) => !item.isOwned)
|
||||
.map((storeItem, id) => (
|
||||
<StoreItem
|
||||
key={id}
|
||||
storeItem={storeItem}
|
||||
buyStoreItem={props.buyStoreItem}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default StoreItemView;
|
@ -1,30 +0,0 @@
|
||||
import React, { useState } from "react";
|
||||
import { IInventoryItem, IStakingSource, IStoreItem } from "typings";
|
||||
import StoreItem from "./StoreItem";
|
||||
|
||||
const StoreItemView = (props: {
|
||||
inventoryItems: IInventoryItem[] | null | undefined;
|
||||
storeItems: IStoreItem[];
|
||||
buyStoreItem: (itemId: string) => void;
|
||||
}) => {
|
||||
return (
|
||||
<div className="border-2 border-white p-8 rounded-lg col-span-5">
|
||||
<h2 className="text-3xl font-bold mb-4 text-white">Store</h2>
|
||||
<div className="grid grid-cols-3 gap-8">
|
||||
{props.storeItems &&
|
||||
props.storeItems.length > 0 &&
|
||||
props.storeItems
|
||||
.filter((item) => !item.isOwned)
|
||||
.map((storeItem, id) => (
|
||||
<StoreItem
|
||||
key={id}
|
||||
storeItem={storeItem}
|
||||
buyStoreItem={props.buyStoreItem}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default StoreItemView;
|
@ -1,10 +1,10 @@
|
||||
"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 InventoryItemView from "./Components/Inventory/InventoryItemView";
|
||||
import StakingSourcesView from "./Components/Staking/StakingSourcesView";
|
||||
import BankAccountsView from "./Components/Accounts/AccountsView";
|
||||
import StoreItemView from "./Components/Store/StoreItemView";
|
||||
import ResourceStore from "./Components/Accounts/Old/ResourceStore";
|
||||
import NotificationPopover from "./Components/NotificationPopover";
|
||||
import { gameConfig } from "@/utils/gameLogic";
|
||||
import {
|
||||
@ -12,10 +12,11 @@ import {
|
||||
IStakingSource,
|
||||
IBankAccount,
|
||||
IStake,
|
||||
IConversionPair,
|
||||
Notification,
|
||||
} from "typings";
|
||||
import Navbar from "./Components/Navbar";
|
||||
import NavbarVertical from "./Components/NavbarVertical";
|
||||
import Navbar from "./Components/Navigation/Navbar";
|
||||
import NavbarVertical from "./Components/Navigation/NavbarVertical";
|
||||
|
||||
export default function Home() {
|
||||
const [inventoryItems, setInventoryItems] = useState<
|
||||
@ -170,13 +171,14 @@ export default function Home() {
|
||||
}
|
||||
};
|
||||
|
||||
// Which object is it?
|
||||
const sellResource = async (obj: any) => {
|
||||
// TODO Joe create sql
|
||||
const sellResource = async (pairs: IConversionPair[]) => {
|
||||
console.log("Selling resource");
|
||||
const response = await fetch(`/api/user/${userId}/bank-account`, {
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
obj: obj,
|
||||
pairs: pairs,
|
||||
}),
|
||||
});
|
||||
return await response.json();
|
||||
@ -261,7 +263,6 @@ export default function Home() {
|
||||
};
|
||||
|
||||
const createStakingSource = async () => {
|
||||
console.log("Minting...");
|
||||
try {
|
||||
const response = await fetch(`/api/user/${userId}/staking-sources`, {
|
||||
method: "POST",
|
||||
@ -315,7 +316,6 @@ export default function Home() {
|
||||
return <p>Loading...</p>;
|
||||
}
|
||||
|
||||
//console.log(stakingSources);
|
||||
return (
|
||||
<>
|
||||
<Navbar setUserId={setUserId} />
|
||||
@ -325,11 +325,8 @@ export default function Home() {
|
||||
onClose={handleCloseNotification}
|
||||
/>
|
||||
)}
|
||||
<BankAccountsView
|
||||
bankAccount={bankAccount}
|
||||
setLightBoxIsActive={handleSetLightBox}
|
||||
/>
|
||||
<div className="grid grid-cols-6 p-4 gap-8">
|
||||
<BankAccountsView bankAccount={bankAccount} sellResource={sellResource} />
|
||||
<div className="grid grid-cols-1 md:grid-cols-6 p-4 gap-8">
|
||||
<NavbarVertical
|
||||
onMenuItemClick={handleMenuItemClick}
|
||||
activeItem={activeComponent}
|
||||
@ -357,9 +354,6 @@ export default function Home() {
|
||||
buyStoreItem={buyStoreItem}
|
||||
/>
|
||||
)}
|
||||
{activeComponent === "resourcestore" && (
|
||||
<ResourceStore bankAccount={bankAccount} />
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
@ -19,14 +19,6 @@ export default async function handler(
|
||||
const result = await db.query("SELECT * FROM get_accounts($1)", [userId]);
|
||||
|
||||
if (result.rowCount > 0) {
|
||||
|
||||
// Make the result to the type
|
||||
/* const updatedResult: IBankAccount = {
|
||||
id: result.rows[0].id,
|
||||
primaryBalance: result.rows[0].primarybalance,
|
||||
resourceAccounts: result.rows[0].resourceaccounts
|
||||
} */
|
||||
|
||||
return res.status(200).json(result.rows[0]);
|
||||
} else {
|
||||
return res.status(400).json({error: "Could not find accounts for user"});
|
||||
@ -37,9 +29,9 @@ export default async function handler(
|
||||
// sell resource
|
||||
// payload userId, key:resourceName/value:amount
|
||||
const { userId } = req.query;
|
||||
const { obj } = req.body;
|
||||
// make sure they have each resource they say they have
|
||||
// calculate conversion rates
|
||||
// an array of IConversionPairs
|
||||
const { pairs } = req.body;
|
||||
// check they have appropriate amount of each resource
|
||||
// increment balance
|
||||
// decrement resources
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user