Skip to content

Commit

Permalink
Add resource filter for contributions (#2596)
Browse files Browse the repository at this point in the history
* Add resource filter for contributions

* Change % for specific resource contribution
  • Loading branch information
bob0005 authored Dec 26, 2024
1 parent d668b3e commit 76ccb88
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 35 deletions.
97 changes: 65 additions & 32 deletions client/src/ui/components/hyperstructures/ContributionSummary.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { useContributions } from "@/hooks/helpers/useContributions";
import { useRealm } from "@/hooks/helpers/useRealm";
import { ResourceIcon } from "@/ui/elements/ResourceIcon";
import { currencyIntlFormat, divideByPrecision, formatNumber } from "@/ui/utils/utils";
import { SelectResource } from "@/ui/elements/SelectResource";
import { copyPlayerAddressToClipboard, currencyIntlFormat, divideByPrecision, formatNumber } from "@/ui/utils/utils";
import { ContractAddress, ID, ResourcesIds } from "@bibliothecadao/eternum";
import { useState } from "react";
import { useMemo, useState } from "react";

export const ContributionSummary = ({
hyperstructureEntityId,
Expand All @@ -15,6 +16,9 @@ export const ContributionSummary = ({
const { getContributions, getContributionsTotalPercentage } = useContributions();
const { getAddressName } = useRealm();

const [showContributions, setShowContributions] = useState(false);
const [selectedResource, setSelectedResource] = useState<number | null>(null);

type Resource = {
amount: number;
resourceId: number;
Expand All @@ -36,25 +40,40 @@ export const ContributionSummary = ({

const resourceContributions: Record<string, Resource[]> = Object.entries(groupedContributions).reduce(
(acc, [playerAddress, resources]) => {
acc[playerAddress] = Object.entries(resources).map(([resourceType, amount]) => ({
amount: Number(amount),
resourceId: Number(resourceType),
}));
acc[playerAddress] = Object.entries(resources)
.filter(([resourceType]) => (selectedResource ? Number(resourceType) === selectedResource : true))
.map(([resourceType, amount]) => ({
amount: Number(amount),
resourceId: Number(resourceType),
}));
return acc;
},
{} as Record<string, Resource[]>,
);

const [showContributions, setShowContributions] = useState(false);

// Calculate percentages and sort contributors
const sortedContributors = Object.entries(groupedContributions)
.map(([playerAddress, resources]) => ({
playerAddress,
resources,
percentage: getContributionsTotalPercentage(hyperstructureEntityId, resourceContributions[playerAddress]) * 100,
}))
.sort((a, b) => b.percentage - a.percentage);
const sortedContributors = useMemo(
() =>
Object.entries(groupedContributions)
.map(([playerAddress, resources]) => ({
playerAddress,
resources,
percentage:
getContributionsTotalPercentage(hyperstructureEntityId, resourceContributions[playerAddress]) * 100,
}))
.filter(({ resources }) =>
selectedResource ? resources[selectedResource] > 0n : Object.values(resources).some((amount) => amount > 0n),
)
.sort((a, b) => {
if (selectedResource) {
const amountA = a.resources[selectedResource] || 0n;
const amountB = b.resources[selectedResource] || 0n;
return amountA > amountB ? -1 : amountA < amountB ? 1 : 0;
}
return b.percentage - a.percentage;
}),
[groupedContributions, selectedResource],
);

return (
<div className={`space-y-2 ${className || ""}`}>
Expand All @@ -66,24 +85,38 @@ export const ContributionSummary = ({
<span className={`transform transition-transform ${showContributions ? "rotate-90" : ""}`}></span>
</div>
{showContributions && (
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-2">
{sortedContributors.map(({ playerAddress, resources, percentage }) => (
<div key={playerAddress} className="bg-gold/10 p-1 rounded">
<div className="flex flex-row mb-1 justify-between mr-1 items-end">
<div className="text-sm font-bold">{getAddressName(ContractAddress(playerAddress))}</div>
<div className="text-xs">{formatNumber(percentage, 2)}%</div>
</div>
<div className="flex flex-wrap gap-2">
{Object.entries(resources).map(([resourceType, amount]) => (
<div key={resourceType} className="flex items-center">
<ResourceIcon size="xs" resource={ResourcesIds[Number(resourceType)]} />
<span className="ml-1 text-xs">{currencyIntlFormat(divideByPrecision(Number(amount)))}</span>
<>
<SelectResource onSelect={(resourceId) => setSelectedResource(resourceId)} />
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-2">
{sortedContributors.map(({ playerAddress, resources, percentage }) => {
const addressName = getAddressName(ContractAddress(playerAddress)) || "Unknown";

return (
<div key={playerAddress} className="bg-gold/10 p-1 rounded">
<div className="flex flex-row mb-1 justify-between mr-1 items-end">
<div
onClick={() => copyPlayerAddressToClipboard(ContractAddress(playerAddress), addressName, true)}
className="text-sm font-bold cursor-pointer hover:text-gold/50"
>
{addressName}
</div>
<div className="text-xs">{formatNumber(percentage, 2)}%</div>
</div>
<div className="flex flex-wrap gap-2">
{Object.entries(resources)
.filter(([resourceType]) => (selectedResource ? Number(resourceType) === selectedResource : true))
.map(([resourceType, amount]) => (
<div key={resourceType} className="flex items-center">
<ResourceIcon size="xs" resource={ResourcesIds[Number(resourceType)]} />
<span className="ml-1 text-xs">{currencyIntlFormat(divideByPrecision(Number(amount)))}</span>
</div>
))}
</div>
))}
</div>
</div>
))}
</div>
</div>
);
})}
</div>
</>
)}
</div>
);
Expand Down
5 changes: 4 additions & 1 deletion client/src/ui/elements/SelectResource.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,10 @@ export const SelectResource: React.FC<SelectResourceProps> = ({ onSelect, classN
"my-auto w-8 mx-auto hover:fill-gold/50 fill-gold hover:scale-125 hover:animate-pulse duration-300 transition-all",
{ "pointer-events-none fill-gold/50": !selectedResource },
)}
onClick={() => setSelectedResource("")}
onClick={() => {
setSelectedResource("");
onSelect(null);
}}
/>
<Select
open={open}
Expand Down
4 changes: 2 additions & 2 deletions client/src/ui/utils/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -258,9 +258,9 @@ export const formatTime = (
return parts.join(" ");
};

export const copyPlayerAddressToClipboard = (address: ContractAddress, name: string) => {
export const copyPlayerAddressToClipboard = (address: ContractAddress, name: string, hex: boolean = false) => {
navigator.clipboard
.writeText(address.toString())
.writeText(hex ? toHexString(address) : address.toString())
.then(() => {
alert(`Address of ${name} copied to clipboard`);
})
Expand Down

0 comments on commit 76ccb88

Please sign in to comment.