-
Notifications
You must be signed in to change notification settings - Fork 52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat/client labor #2666
base: next
Are you sure you want to change the base?
Feat/client labor #2666
Changes from all commits
0eb4592
edff80e
89408ee
a036374
1571053
41dc492
360a57b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { ID, LaborIds, ResourcesIds } from "@bibliothecadao/eternum"; | ||
import { useDojo } from "@bibliothecadao/react"; | ||
import { LaborChip } from "./labor-chip"; | ||
|
||
export const EntityLaborTable = ({ entityId }: { entityId: ID | undefined }) => { | ||
const dojo = useDojo(); | ||
|
||
if (!entityId || entityId === 0) { | ||
return <div>No Entity Selected</div>; | ||
} | ||
|
||
const startProduction = async (resourceType: ResourcesIds, producedAmount: number) => { | ||
try { | ||
await dojo.setup.systemCalls.start_production({ | ||
signer: dojo.account.account, | ||
entity_id: entityId, | ||
resource_type: resourceType, | ||
amount: producedAmount, | ||
}); | ||
} catch (error) { | ||
console.error("Failed to start production", error); | ||
} | ||
}; | ||
|
||
return Object.entries(LaborIds).map(([_, laborId]) => { | ||
if (isNaN(Number(laborId))) return null; | ||
return <LaborChip key={laborId} laborId={laborId as LaborIds} startProduction={startProduction} />; | ||
}); | ||
}; |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,62 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
import Button from "@/ui/elements/button"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { NumberInput } from "@/ui/elements/number-input"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { ResourceIcon } from "@/ui/elements/resource-icon"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
configManager, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
findResourceById, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
getResourceIdFromLaborId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
LaborIds, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
ResourcesIds, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
} from "@bibliothecadao/eternum"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { useState } from "react"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
type LaborChipProps = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
laborId: LaborIds; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
startProduction: (resourceType: ResourcesIds, amount: number) => void; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
export const LaborChip = ({ laborId, startProduction }: LaborChipProps) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
const resourceId = getResourceIdFromLaborId(laborId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
const [productionAmount, setProductionAmount] = useState(0); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
const laborInputs = configManager.laborInputs[resourceId as ResourcesIds]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
<> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
<div className={`flex gap-2 relative group items-center text-xs px-2 p-1 hover:bg-gold/20 `}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
<div className="flex flex-col"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
{laborInputs?.map(({ resource, amount }) => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
<div key={resource} className="flex flex-row items-center"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
<ResourceIcon | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
withTooltip={false} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
resource={findResourceById(resource)?.trait as string} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
size="sm" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
className="mr-3 self-center" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
<div className="text-red">-{amount * productionAmount}</div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
))} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+29
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add null check for laborInputs before mapping. The current implementation might throw if laborInputs is undefined. - {laborInputs?.map(({ resource, amount }) => (
+ {laborInputs ? (
+ laborInputs.map(({ resource, amount }) => (
<div key={resource} className="flex flex-row items-center">
<ResourceIcon
withTooltip={false}
resource={findResourceById(resource)?.trait as string}
size="sm"
className="mr-3 self-center"
/>
<div className="text-red">-{amount * productionAmount}</div>
</div>
- ))}
+ ))
+ ) : (
+ <div>No labor inputs configured</div>
+ )} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
<div className="grid grid-cols-10 w-full items-center"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
<div className="flex flex-col col-span-7"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
<NumberInput | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
value={productionAmount} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
onChange={(productionAmount) => setProductionAmount(productionAmount)} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
className="col-span-7" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+43
to
+47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add validation for production amount input. The NumberInput component should have minimum/maximum value constraints and proper validation. <NumberInput
value={productionAmount}
onChange={(productionAmount) => setProductionAmount(productionAmount)}
+ min={0}
+ max={999999}
className="col-span-7"
/> 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Button variant="primary" onClick={() => startProduction(resourceId, productionAmount)}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Start Producing | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
</Button> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
<ResourceIcon | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
withTooltip={false} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
resource={findResourceById(resourceId)?.trait as string} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
size="md" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
className="" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
</> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
import { useUIStore } from "@/hooks/store/use-ui-store"; | ||
import { RightView } from "@/types"; | ||
import { EntityLaborTable } from "@/ui/components/resources/entity-labor-table"; | ||
import { BuildingThumbs, MenuEnum } from "@/ui/config"; | ||
import Button from "@/ui/elements/button"; | ||
import CircleButton from "@/ui/elements/circle-button"; | ||
|
@@ -25,6 +26,7 @@ export const RightNavigationModule = () => { | |
<CircleButton | ||
className="resource-table-selector" | ||
image={BuildingThumbs.resources} | ||
disabled={!structureEntityId} | ||
size="xl" | ||
tooltipLocation="top" | ||
label="Balance" | ||
|
@@ -33,6 +35,21 @@ export const RightNavigationModule = () => { | |
/> | ||
), | ||
}, | ||
{ | ||
name: MenuEnum.laborTable, | ||
button: ( | ||
<CircleButton | ||
className="labor-table-selector" | ||
image={BuildingThumbs.construction} | ||
disabled={!structureEntityId} | ||
size="xl" | ||
tooltipLocation="top" | ||
label="Labor" | ||
active={view === RightView.LaborTable} | ||
onClick={() => setView(view === RightView.LaborTable ? RightView.None : RightView.LaborTable)} | ||
/> | ||
), | ||
}, | ||
], | ||
[view, structureEntityId], | ||
); | ||
|
@@ -65,24 +82,23 @@ export const RightNavigationModule = () => { | |
className={`w-full pointer-events-auto overflow-y-scroll h-[60vh] rounded-l-2xl border-l-2 border-y-2 border-gold/20`} | ||
> | ||
<Suspense fallback={<div className="p-8">Loading...</div>}> | ||
{!!structureEntityId && ( | ||
<div className="entity-resource-table-selector p-2 flex flex-col space-y-1 overflow-y-auto"> | ||
<a | ||
className="text-brown cursor-pointer text-lg w-full" | ||
href={`https://empire.realms.world/trade`} | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
> | ||
<Button variant="secondary" className="w-full"> | ||
<div className="flex items-center gap-2"> | ||
<ResourceIcon resource="Lords" size="xs" /> | ||
Bridge Lords & Resources | ||
</div> | ||
</Button> | ||
</a> | ||
<EntityResourceTable entityId={structureEntityId} /> | ||
</div> | ||
)} | ||
<div className="entity-resource-table-selector p-2 flex flex-col space-y-1 overflow-y-auto"> | ||
<a | ||
className="text-brown cursor-pointer text-lg w-full" | ||
href={`https://empire.realms.world/trade`} | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
> | ||
<Button variant="secondary" className="w-full"> | ||
<div className="flex items-center gap-2"> | ||
<ResourceIcon resource="Lords" size="xs" /> | ||
Bridge Lords & Resources | ||
</div> | ||
</Button> | ||
</a> | ||
Comment on lines
+86
to
+98
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Environment-specific URL handling needs attention While the link is secure with proper
Consider updating the URL to respect the environment setting: const bridgeUrl = env.VITE_PUBLIC_CHAIN === "mainnet"
? "https://empire.realms.world/trade"
: "https://empire-next.realms.world/trade"; 🔗 Analysis chainVerify security implications of external link. The external link to
🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Search for other instances of this URL to verify consistency
rg -l 'empire\.realms\.world'
# Search for environment-specific URL configurations
rg -l 'VITE_PUBLIC.*URL|VITE_PUBLIC.*ENDPOINT'
Length of output: 1059 Script: #!/bin/bash
# Check how the URL is used in other files
rg -A 2 -B 2 'empire\.realms\.world'
# Check environment configuration files for URL settings
cat client/apps/game/env.ts
cat client/apps/game/dojoConfig.ts
# Look for any feature flags related to trading or bridging
rg -i "feature.*flag.*bridge|feature.*flag.*trade"
Length of output: 8038 |
||
{view === RightView.ResourceTable && <EntityResourceTable entityId={structureEntityId} />} | ||
{view === RightView.LaborTable && <EntityLaborTable entityId={structureEntityId} />} | ||
</div> | ||
</Suspense> | ||
</BaseContainer> | ||
</div> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Replace
isNaN
withNumber.isNaN
for safer type checking.The
isNaN
function performs type coercion which can lead to unexpected results. UseNumber.isNaN
instead for more reliable number validation.📝 Committable suggestion
🧰 Tools
🪛 Biome (1.9.4)
[error] 26-26: isNaN is unsafe. It attempts a type coercion. Use Number.isNaN instead.
See the MDN documentation for more details.
Unsafe fix: Use Number.isNaN instead.
(lint/suspicious/noGlobalIsNan)