From 7bf304cfb62cd931b28de16f107d7ca9455c5ace Mon Sep 17 00:00:00 2001 From: chaojun Date: Thu, 2 Jul 2026 17:22:14 +0800 Subject: [PATCH 01/23] Support hollar as fellowship salary asset, #7389 --- .../collectives/core/member/salary.js | 6 ++-- .../components/collectives/members/table.js | 2 +- .../fellowship/params/descriptions.jsx | 4 +-- .../components/fellowship/params/list.jsx | 4 +-- .../hooks/useMyAccountSalaryWithSymbol.js | 4 +-- .../fellowship/salary/claimants/list.jsx | 8 ++--- .../fellowship/salary/claimants/status.jsx | 4 +-- .../salary/cycles/history/expenditure.jsx | 5 ++- .../salary/cycles/history/registerPaid.jsx | 6 ++-- .../salary/cycles/info/progress.jsx | 4 +-- .../salary/cycles/summary/budgetItem.js | 4 +-- .../salary/cycles/summary/potItem.js | 4 +-- .../salary/cycles/summary/registrationItem.js | 4 +-- .../salary/cycles/summary/unregisteredItem.js | 4 +-- .../salary/cycles/tabsList/columns/paid.jsx | 6 ++-- .../cycles/tabsList/columns/payment.jsx | 5 ++- .../cycles/tabsList/columns/yearlySalary.jsx | 6 ++-- .../fellowship/salary/feeds/events/paid.js | 5 ++- .../salary/feeds/events/registered.js | 2 +- .../fellowship/statistics/common.js | 6 ++-- .../expenditure/claimants/columns/paid.jsx | 11 ++----- .../expenditure/cycles/cyclesChart.jsx | 15 +++++++-- .../expenditure/rank/doughnutChart/labels.jsx | 15 +++------ .../statistics/expenditure/summary/index.jsx | 20 +++++++----- .../membership/summary/summaryItems.jsx | 13 ++------ .../member/fellowshipMember/salary.js | 8 ++--- .../components/pages/secretary/members.js | 2 +- .../profile/fellowship/memberInfo.jsx | 4 +-- .../salary/payments/columns/paid.jsx | 6 ++-- .../profile/fellowship/statisticsInfo.jsx | 2 +- .../secretary/salary/claimants/list.jsx | 4 +-- .../secretary/statistics/claimants/index.jsx | 2 +- .../secretary/statistics/summary/index.jsx | 9 ++++-- .../core/useSubFellowshipCoreMember.js | 20 ++++++++---- .../hooks/fellowship/salary/useSalaryAsset.js | 24 ++++++++++++++ .../utils/consts/getSalaryAsset.js | 32 ++++++++++++++++--- 36 files changed, 175 insertions(+), 105 deletions(-) create mode 100644 packages/next-common/hooks/fellowship/salary/useSalaryAsset.js diff --git a/packages/next-common/components/collectives/core/member/salary.js b/packages/next-common/components/collectives/core/member/salary.js index a773cf82cb..45a5e6b118 100644 --- a/packages/next-common/components/collectives/core/member/salary.js +++ b/packages/next-common/components/collectives/core/member/salary.js @@ -9,11 +9,12 @@ export function CoreFellowshipMemberSalaryContent({ rank, isActive, params = {}, + section = "fellowship", }) { const { activeSalary, passiveSalary } = params; const salaryArray = isActive ? activeSalary : passiveSalary; const salary = getRankSalary(salaryArray, rank); - const { symbol, decimals } = getSalaryAsset(); + const { symbol, decimals } = getSalaryAsset(section); return ( { return [ diff --git a/packages/next-common/components/fellowship/salary/actions/hooks/useMyAccountSalaryWithSymbol.js b/packages/next-common/components/fellowship/salary/actions/hooks/useMyAccountSalaryWithSymbol.js index 174f8796b3..9c8c8bdf53 100644 --- a/packages/next-common/components/fellowship/salary/actions/hooks/useMyAccountSalaryWithSymbol.js +++ b/packages/next-common/components/fellowship/salary/actions/hooks/useMyAccountSalaryWithSymbol.js @@ -1,4 +1,4 @@ -import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; +import { useSalaryAsset } from "next-common/hooks/fellowship/salary/useSalaryAsset"; import rankToIndex from "next-common/utils/fellowship/rankToIndex"; import { useCoreFellowshipParams } from "next-common/context/collectives/collectives"; import { isSameAddress } from "next-common/utils"; @@ -26,7 +26,7 @@ export function useMySalary() { export function useMyAccountSalaryWithSymbol() { const salaryValue = useMySalary() ?? 0; - const { decimals, symbol } = getSalaryAsset(); + const { decimals, symbol } = useSalaryAsset(); return { value: salaryValue, diff --git a/packages/next-common/components/fellowship/salary/claimants/list.jsx b/packages/next-common/components/fellowship/salary/claimants/list.jsx index 241dfb756d..8847d57f49 100644 --- a/packages/next-common/components/fellowship/salary/claimants/list.jsx +++ b/packages/next-common/components/fellowship/salary/claimants/list.jsx @@ -5,7 +5,6 @@ import { has, isNil } from "lodash-es"; import AddressUser from "next-common/components/user/addressUser"; import FellowshipSalaryMemberIsRegistered from "./isRegistered"; import Link from "next-common/components/link"; -import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; import ValueDisplay from "next-common/components/valueDisplay"; import { toPrecision } from "next-common/utils"; import { getRankSalary } from "next-common/utils/fellowship/getRankSalary"; @@ -18,9 +17,10 @@ import Tooltip from "next-common/components/tooltip"; import { isSameAddress } from "next-common/utils"; import FieldLoading from "next-common/components/icons/fieldLoading"; import { SystemVoteAbstain } from "@osn/icons/subsquare"; +import { useSalaryAsset } from "next-common/hooks/fellowship/salary/useSalaryAsset"; function SalaryCellTooltip({ isActive, rank, params, children }) { - const { symbol, decimals } = getSalaryAsset(); + const { symbol, decimals } = useSalaryAsset(); const { activeSalary = [], passiveSalary = [] } = params ?? {}; const activeRankSalary = getRankSalary(activeSalary, rank); @@ -54,7 +54,7 @@ function SalaryCellTooltip({ isActive, rank, params, children }) { } function ClaimantAmountCell({ claimant }) { - const { symbol, decimals } = getSalaryAsset(); + const { symbol, decimals } = useSalaryAsset(); const status = claimant?.status?.status || {}; const registered = has(status, "registered") ? status?.registered @@ -72,7 +72,7 @@ function ClaimantSalaryCell({ claimant, member, params }) { const isActive = member?.status?.isActive; const rank = claimant?.rank; - const { symbol, decimals } = getSalaryAsset(); + const { symbol, decimals } = useSalaryAsset(); const { activeSalary = [], passiveSalary = [] } = params ?? {}; const activeRankSalary = getRankSalary(activeSalary, rank); diff --git a/packages/next-common/components/fellowship/salary/claimants/status.jsx b/packages/next-common/components/fellowship/salary/claimants/status.jsx index ea2054739b..72fa22c174 100644 --- a/packages/next-common/components/fellowship/salary/claimants/status.jsx +++ b/packages/next-common/components/fellowship/salary/claimants/status.jsx @@ -1,10 +1,10 @@ import { has } from "lodash-es"; import Tooltip from "next-common/components/tooltip"; -import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; +import { useSalaryAsset } from "next-common/hooks/fellowship/salary/useSalaryAsset"; import { toPrecision } from "next-common/utils"; export default function FellowshipSalaryMemberStatus({ status }) { - const { decimals, symbol } = getSalaryAsset(); + const { decimals, symbol } = useSalaryAsset(); let content = -; let tooltipContent; diff --git a/packages/next-common/components/fellowship/salary/cycles/history/expenditure.jsx b/packages/next-common/components/fellowship/salary/cycles/history/expenditure.jsx index 2a6a4f94b0..fd9c7ba9e8 100644 --- a/packages/next-common/components/fellowship/salary/cycles/history/expenditure.jsx +++ b/packages/next-common/components/fellowship/salary/cycles/history/expenditure.jsx @@ -6,7 +6,10 @@ import Tooltip from "next-common/components/tooltip"; import bigAdd from "next-common/utils/math/bigAdd"; export default function FellowshipSalaryExpenditure({ cycle = {} }) { - const { symbol, decimals } = getSalaryAsset(); + const { symbol, decimals } = getSalaryAsset( + "fellowship", + cycle?.indexer?.blockHeight, + ); const { status = {}, registeredPaid, unRegisteredPaid } = cycle || {}; const { budget } = status; diff --git a/packages/next-common/components/fellowship/salary/cycles/history/registerPaid.jsx b/packages/next-common/components/fellowship/salary/cycles/history/registerPaid.jsx index 1e91b48e07..7d9206fdd8 100644 --- a/packages/next-common/components/fellowship/salary/cycles/history/registerPaid.jsx +++ b/packages/next-common/components/fellowship/salary/cycles/history/registerPaid.jsx @@ -3,8 +3,8 @@ import ValueDisplay from "next-common/components/valueDisplay"; import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; import { toPrecision } from "next-common/utils"; -function RegisterPaid({ count, paid, type = "" }) { - const { symbol, decimals } = getSalaryAsset(); +function RegisterPaid({ count, paid, type = "", blockHeight }) { + const { symbol, decimals } = getSalaryAsset("fellowship", blockHeight); return (
@@ -27,6 +27,7 @@ export function FellowshipSalaryRegisteredPaid({ cycle = {} }) { paid={cycle.registeredPaid} count={cycle.registeredPaidCount} type="Registers" + blockHeight={cycle?.indexer?.blockHeight} /> ); } @@ -37,6 +38,7 @@ export function FellowshipSalaryUnregisteredPaid({ cycle = {} }) { paid={cycle.unRegisteredPaid} count={cycle.unRegisteredPaidCount} type="Unregisters" + blockHeight={cycle?.indexer?.blockHeight} /> ); } diff --git a/packages/next-common/components/fellowship/salary/cycles/info/progress.jsx b/packages/next-common/components/fellowship/salary/cycles/info/progress.jsx index f9563b4f18..0e1a10f39f 100644 --- a/packages/next-common/components/fellowship/salary/cycles/info/progress.jsx +++ b/packages/next-common/components/fellowship/salary/cycles/info/progress.jsx @@ -1,6 +1,6 @@ import MultiProgress from "next-common/components/progress/multiProgress"; import ValueDisplay from "next-common/components/valueDisplay"; -import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; +import { useSalaryAsset } from "next-common/hooks/fellowship/salary/useSalaryAsset"; import { cn, toPercentage, toPrecision } from "next-common/utils"; const registreredPaidColor = "var(--theme500)"; @@ -62,7 +62,7 @@ export default function FellowshipCycleProgress({ cycle }) { } function PaidLabel({ value, label = "", color = "" }) { - const { decimals, symbol } = getSalaryAsset(); + const { decimals, symbol } = useSalaryAsset(); return (
diff --git a/packages/next-common/components/fellowship/salary/cycles/summary/budgetItem.js b/packages/next-common/components/fellowship/salary/cycles/summary/budgetItem.js index bf82dbee0e..b066a86a9a 100644 --- a/packages/next-common/components/fellowship/salary/cycles/summary/budgetItem.js +++ b/packages/next-common/components/fellowship/salary/cycles/summary/budgetItem.js @@ -3,10 +3,10 @@ import LoadableContent from "next-common/components/common/loadableContent"; import { isNil } from "lodash-es"; import ValueDisplay from "next-common/components/valueDisplay"; import { toPrecision } from "next-common/utils"; -import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; +import { useSalaryAsset } from "next-common/hooks/fellowship/salary/useSalaryAsset"; export default function SalaryStatsBudgetItem({ budget }) { - const { decimals, symbol } = getSalaryAsset(); + const { decimals, symbol } = useSalaryAsset(); return ( diff --git a/packages/next-common/components/fellowship/salary/cycles/summary/potItem.js b/packages/next-common/components/fellowship/salary/cycles/summary/potItem.js index 3f9901dba7..fb265167d1 100644 --- a/packages/next-common/components/fellowship/salary/cycles/summary/potItem.js +++ b/packages/next-common/components/fellowship/salary/cycles/summary/potItem.js @@ -1,4 +1,4 @@ -import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; +import { useSalaryAsset } from "next-common/hooks/fellowship/salary/useSalaryAsset"; import SummaryItem from "next-common/components/summary/layout/item"; import LoadableContent from "next-common/components/common/loadableContent"; import { isNil } from "lodash-es"; @@ -6,7 +6,7 @@ import ValueDisplay from "next-common/components/valueDisplay"; import { toPrecision } from "next-common/utils"; export default function SalaryStatsPotItem({ pot }) { - const { decimals, symbol } = getSalaryAsset(); + const { decimals, symbol } = useSalaryAsset(); return ( diff --git a/packages/next-common/components/fellowship/salary/cycles/summary/registrationItem.js b/packages/next-common/components/fellowship/salary/cycles/summary/registrationItem.js index 47016352ff..6a9bb5ffef 100644 --- a/packages/next-common/components/fellowship/salary/cycles/summary/registrationItem.js +++ b/packages/next-common/components/fellowship/salary/cycles/summary/registrationItem.js @@ -1,5 +1,5 @@ import SummaryItem from "next-common/components/summary/layout/item"; -import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; +import { useSalaryAsset } from "next-common/hooks/fellowship/salary/useSalaryAsset"; import { isNil } from "lodash-es"; import LoadableContent from "next-common/components/common/loadableContent"; import ValueDisplay from "next-common/components/valueDisplay"; @@ -10,7 +10,7 @@ export default function SalaryStatsRegistrationItem({ cycleData }) { const stats = useFellowshipSalaryStats(); const { totalRegistrations } = stats || {}; - const { decimals, symbol } = getSalaryAsset(); + const { decimals, symbol } = useSalaryAsset(); const { registeredCount } = cycleData || {}; return ( diff --git a/packages/next-common/components/fellowship/salary/cycles/summary/unregisteredItem.js b/packages/next-common/components/fellowship/salary/cycles/summary/unregisteredItem.js index 1cc58add5c..eee78e51da 100644 --- a/packages/next-common/components/fellowship/salary/cycles/summary/unregisteredItem.js +++ b/packages/next-common/components/fellowship/salary/cycles/summary/unregisteredItem.js @@ -3,14 +3,14 @@ import { isNil } from "lodash-es"; import LoadableContent from "next-common/components/common/loadableContent"; import ValueDisplay from "next-common/components/valueDisplay"; import { toPrecision } from "next-common/utils"; -import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; +import { useSalaryAsset } from "next-common/hooks/fellowship/salary/useSalaryAsset"; import { useFellowshipSalaryStats } from "next-common/hooks/fellowship/salary/useFellowshipSalaryStats"; export default function SalaryStatsUnregisteredItem({ cycleData }) { const stats = useFellowshipSalaryStats(); const { totalUnregisteredPaid } = stats || {}; - const { decimals, symbol } = getSalaryAsset(); + const { decimals, symbol } = useSalaryAsset(); const { unRegisteredPaidCount } = cycleData || {}; return ( diff --git a/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/paid.jsx b/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/paid.jsx index 3af04e60ad..fd9e6a5e5d 100644 --- a/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/paid.jsx +++ b/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/paid.jsx @@ -3,13 +3,15 @@ import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; import { toPrecision } from "next-common/utils"; export function useFellowshipSalaryCyclePaidColumn() { - const { decimals, symbol } = getSalaryAsset(); - return { name: "Paid", width: 160, className: "text-right", cellRender(data) { + const { decimals, symbol } = getSalaryAsset( + "fellowship", + data?.paidIndexer?.blockHeight, + ); return ( diff --git a/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/yearlySalary.jsx b/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/yearlySalary.jsx index fca4234d1a..e8fc5b9531 100644 --- a/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/yearlySalary.jsx +++ b/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/yearlySalary.jsx @@ -3,12 +3,14 @@ import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; import { toPrecision } from "next-common/utils"; export function useFellowshipSalaryCycleYearlySalaryColumn() { - const { decimals, symbol } = getSalaryAsset(); - return { name: "Salary", width: 160, cellRender(data) { + const { decimals, symbol } = getSalaryAsset( + "fellowship", + data?.paidIndexer?.blockHeight, + ); return ( diff --git a/packages/next-common/components/fellowship/salary/feeds/events/registered.js b/packages/next-common/components/fellowship/salary/feeds/events/registered.js index 6f60e23998..3b92babc13 100644 --- a/packages/next-common/components/fellowship/salary/feeds/events/registered.js +++ b/packages/next-common/components/fellowship/salary/feeds/events/registered.js @@ -7,8 +7,8 @@ import Link from "next-common/components/link"; import { useCollectivesContext } from "next-common/context/collectives/collectives"; export function FellowshipRegisteredFeedContent({ amount, index }) { - const { symbol, decimals } = getSalaryAsset(); const { section } = useCollectivesContext(); + const { symbol, decimals } = getSalaryAsset(section); return ( <> diff --git a/packages/next-common/components/fellowship/statistics/common.js b/packages/next-common/components/fellowship/statistics/common.js index e7fbb9d085..85a04578a5 100644 --- a/packages/next-common/components/fellowship/statistics/common.js +++ b/packages/next-common/components/fellowship/statistics/common.js @@ -12,7 +12,7 @@ export const expenditureDoughnutChartOptions = { const name = item.dataset.name[item.dataIndex]; const percentage = item.dataset.percentage[item.dataIndex]; const count = item.dataset.data[item.dataIndex]; - return `${name}: ${getAbbreviateBigNumber(count)} (${percentage})`; + return `${name}: ${formatNum(count)} (${percentage})`; }, }, }, @@ -72,8 +72,8 @@ export const doughnutChartColors = [ "#E684B8", ]; -export function getAbbreviateBigNumber(count, showSymbol = true) { - const { symbol, decimals } = getSalaryAsset(); +export function getAbbreviateBigNumber(count, showSymbol = true, blockHeight) { + const { symbol, decimals } = getSalaryAsset("fellowship", blockHeight); const precisionCount = toPrecision(count, decimals); return showSymbol ? `${formatNum(precisionCount)} ${symbol}` diff --git a/packages/next-common/components/fellowship/statistics/expenditure/claimants/columns/paid.jsx b/packages/next-common/components/fellowship/statistics/expenditure/claimants/columns/paid.jsx index c1326e1e4e..5589d7bf9b 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/claimants/columns/paid.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/claimants/columns/paid.jsx @@ -1,22 +1,15 @@ import ValueDisplay from "next-common/components/valueDisplay"; import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; -import { toPrecision } from "next-common/utils"; export function useStatisticsClaimantsPaidColumn() { - const { decimals, symbol } = getSalaryAsset(); + const { symbol } = getSalaryAsset("fellowship"); return { name: "Total Paid", width: 160, className: "text-right", cellRender(data, idx) { - return ( - - ); + return ; }, }; } diff --git a/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx b/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx index 5dea067162..8a239a24a3 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx @@ -18,18 +18,29 @@ function getTooltipLabel(item, currentDataset) { registeredPaid, unRegisteredPaid, } = currentDataset; + const blockHeight = currentDataset.indexer?.blockHeight; const totalPaid = getAbbreviateBigNumber( new BigNumber(registeredPaid).plus(unRegisteredPaid), + true, + blockHeight, ); if (datasetIndex === 0) { return [ `Total: ${totalPaid}`, - `${dataset.label}: ${getAbbreviateBigNumber(registeredPaid)}`, + `${dataset.label}: ${getAbbreviateBigNumber( + registeredPaid, + true, + blockHeight, + )}`, ]; } if (datasetIndex === 1) { return [ - `${dataset.label}: ${getAbbreviateBigNumber(unRegisteredPaid)}`, + `${dataset.label}: ${getAbbreviateBigNumber( + unRegisteredPaid, + true, + blockHeight, + )}`, `Registered Paid Count: ${registeredPaidCount}`, `Unregistered Paid Count: ${unRegisteredPaidCount}`, ]; diff --git a/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx b/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx index 2d1c34259c..f10bee1b9e 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx @@ -1,15 +1,10 @@ import { cn } from "next-common/utils"; import ValueDisplay from "next-common/components/valueDisplay"; import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; -import { toPrecision } from "next-common/utils"; import { getPercentageValue } from "next-common/components/fellowship/statistics/common"; -function getSalaryValue(count, decimals, symbol) { - return count ? ( - - ) : ( - `0 ${symbol}` - ); +function getSalaryValue(count, symbol) { + return count ? : `0 ${symbol}`; } function RowItem({ bgColor, label, percentage, count }) { @@ -29,7 +24,7 @@ function RowItem({ bgColor, label, percentage, count }) { } export default function DoughnutChartLabels({ labelDataArr }) { - const { symbol, decimals } = getSalaryAsset(); + const { symbol } = getSalaryAsset("fellowship"); return (
{labelDataArr.map((i) => ( @@ -38,9 +33,7 @@ export default function DoughnutChartLabels({ labelDataArr }) { label={i.label} bgColor={i.bgColor} percentage={getPercentageValue(i.percent)} - count={getSalaryValue(i.count, decimals, symbol)} - symbol={symbol} - decimals={decimals} + count={getSalaryValue(i.count, symbol)} /> ))}
diff --git a/packages/next-common/components/fellowship/statistics/expenditure/summary/index.jsx b/packages/next-common/components/fellowship/statistics/expenditure/summary/index.jsx index df5efa097f..c6cb36114a 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/summary/index.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/summary/index.jsx @@ -4,13 +4,20 @@ import SummaryLayout from "next-common/components/summary/layout/layout"; import BigNumber from "bignumber.js"; import ValueDisplay from "next-common/components/valueDisplay"; import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; -import { toPrecision } from "next-common/utils"; function getTotalSpent(data) { if (data && data.length > 0) { const totalSpent = data.reduce((total, item) => { - const registeredPaid = new BigNumber(item.registeredPaid); - const unRegisteredPaid = new BigNumber(item.unRegisteredPaid); + const { decimals } = getSalaryAsset( + "fellowship", + item.indexer?.blockHeight, + ); + const registeredPaid = new BigNumber(item.registeredPaid || 0).div( + 10 ** decimals, + ); + const unRegisteredPaid = new BigNumber(item.unRegisteredPaid || 0).div( + 10 ** decimals, + ); return total.plus(registeredPaid).plus(unRegisteredPaid); }, new BigNumber(0)); return totalSpent; @@ -24,13 +31,10 @@ function SpentCycles({ count }) { function TotalSpent({ cycles }) { const totalSpent = getTotalSpent(cycles); - const { symbol, decimals } = getSalaryAsset(); + const { symbol } = getSalaryAsset("fellowship"); return ( - + ); } diff --git a/packages/next-common/components/fellowship/statistics/membership/summary/summaryItems.jsx b/packages/next-common/components/fellowship/statistics/membership/summary/summaryItems.jsx index 100e653000..95e1667551 100644 --- a/packages/next-common/components/fellowship/statistics/membership/summary/summaryItems.jsx +++ b/packages/next-common/components/fellowship/statistics/membership/summary/summaryItems.jsx @@ -2,10 +2,9 @@ import SummaryItem from "next-common/components/summary/layout/item"; import SummaryLayout from "next-common/components/summary/layout/layout"; import ValueDisplay from "next-common/components/valueDisplay"; import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; -import { toPrecision } from "next-common/utils"; export default function StatisticsMembershipSummaryItems({ summaryData }) { - const { decimals, symbol } = getSalaryAsset(); + const { symbol } = getSalaryAsset("fellowship"); if (!summaryData) { return null; } @@ -22,17 +21,11 @@ export default function StatisticsMembershipSummaryItems({ summaryData }) { {promotionTimes} - + {demotionTimes} - + {retentionTimes} diff --git a/packages/next-common/components/pages/fellowship/member/fellowshipMember/salary.js b/packages/next-common/components/pages/fellowship/member/fellowshipMember/salary.js index 6029ad4a1e..ac4c991230 100644 --- a/packages/next-common/components/pages/fellowship/member/fellowshipMember/salary.js +++ b/packages/next-common/components/pages/fellowship/member/fellowshipMember/salary.js @@ -4,7 +4,7 @@ import ValueDisplay from "next-common/components/valueDisplay"; import { usePageProps } from "next-common/context/page"; import useSubCollectiveRank from "next-common/hooks/collectives/useSubCollectiveRank"; import { isSameAddress, toPrecision } from "next-common/utils"; -import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; +import { useSalaryAsset } from "next-common/hooks/fellowship/salary/useSalaryAsset"; import { getRankSalary } from "next-common/utils/fellowship/getRankSalary"; import { BorderedRow, @@ -72,7 +72,7 @@ export function LastPayment() { } function SalaryValue({ salary }) { - const { symbol, decimals } = getSalaryAsset(); + const { symbol, decimals } = useSalaryAsset(); return ( @@ -81,7 +81,7 @@ function SalaryValue({ salary }) { } function TotalPaid({ totalPaid }) { - const { decimals } = getSalaryAsset(); + const { symbol } = useSalaryAsset(); return (
@@ -89,7 +89,7 @@ function TotalPaid({ totalPaid }) { Total Paid
- +
); diff --git a/packages/next-common/components/pages/secretary/members.js b/packages/next-common/components/pages/secretary/members.js index b3f58b9c85..0415d347a6 100644 --- a/packages/next-common/components/pages/secretary/members.js +++ b/packages/next-common/components/pages/secretary/members.js @@ -32,7 +32,7 @@ const columns = [ ]; function SalaryCell({ rank }) { - const { symbol, decimals } = getSalaryAsset(); + const { symbol, decimals } = getSalaryAsset("secretary"); const salary = getSecretaryMemberSalary(rank); return ; } diff --git a/packages/next-common/components/profile/fellowship/memberInfo.jsx b/packages/next-common/components/profile/fellowship/memberInfo.jsx index 6257045efe..084807af32 100644 --- a/packages/next-common/components/profile/fellowship/memberInfo.jsx +++ b/packages/next-common/components/profile/fellowship/memberInfo.jsx @@ -8,7 +8,7 @@ import SummaryLayout from "next-common/components/summary/layout/layout"; import ValueDisplay from "next-common/components/valueDisplay"; import { usePageProps } from "next-common/context/page"; import useFellowshipCoreMembersWithRank from "next-common/hooks/fellowship/core/useFellowshipCoreMembersWithRank"; -import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; +import { useSalaryAsset } from "next-common/hooks/fellowship/salary/useSalaryAsset"; import { backendApi } from "next-common/services/nextApi"; import { ambassadorParamsApi, @@ -132,7 +132,7 @@ function ProfileFellowshipMemberInfoPanel({ member, paramsApi }) { function MemberSalaryItem({ params, isActive, rank, loading }) { const { activeSalary, passiveSalary } = params; - const { decimals, symbol } = getSalaryAsset(); + const { decimals, symbol } = useSalaryAsset(); const salaryTable = isActive ? activeSalary : passiveSalary; const salary = getRankSalary(salaryTable, rank); diff --git a/packages/next-common/components/profile/fellowship/salary/payments/columns/paid.jsx b/packages/next-common/components/profile/fellowship/salary/payments/columns/paid.jsx index 70026969ca..7a8de98aba 100644 --- a/packages/next-common/components/profile/fellowship/salary/payments/columns/paid.jsx +++ b/packages/next-common/components/profile/fellowship/salary/payments/columns/paid.jsx @@ -3,13 +3,15 @@ import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; import { toPrecision } from "next-common/utils"; export function useProfileFellowshipSalaryPaymentPaidColumn(props = {}) { - const { decimals, symbol } = getSalaryAsset(); - return { name: "Paid", width: 160, className: "text-right", cellRender(data, idx) { + const { decimals, symbol } = getSalaryAsset( + "fellowship", + data?.paidIndexer?.blockHeight, + ); return ( diff --git a/packages/next-common/components/secretary/salary/claimants/list.jsx b/packages/next-common/components/secretary/salary/claimants/list.jsx index b067e5d1b6..1fbec0149f 100644 --- a/packages/next-common/components/secretary/salary/claimants/list.jsx +++ b/packages/next-common/components/secretary/salary/claimants/list.jsx @@ -28,7 +28,7 @@ function getClaimantAmount(claimant) { } function ClaimantAmountCell({ claimant }) { - const { symbol, decimals } = getSalaryAsset(); + const { symbol, decimals } = getSalaryAsset("secretary"); const amount = getClaimantAmount(claimant); if (isNil(amount)) { @@ -39,7 +39,7 @@ function ClaimantAmountCell({ claimant }) { } function ClaimantSalaryCell({ rank }) { - const { symbol, decimals } = getSalaryAsset(); + const { symbol, decimals } = getSalaryAsset("secretary"); const salary = getSecretaryMemberSalary(rank); if (!salary) { return -; diff --git a/packages/next-common/components/secretary/statistics/claimants/index.jsx b/packages/next-common/components/secretary/statistics/claimants/index.jsx index 8dc0a530b4..9dd72809e7 100644 --- a/packages/next-common/components/secretary/statistics/claimants/index.jsx +++ b/packages/next-common/components/secretary/statistics/claimants/index.jsx @@ -78,7 +78,7 @@ function useSecretaryClaimantsReferendaColumn(paymentReferenda) { } function useSecretaryClaimantsPaidColumn(paymentReferenda) { - const { decimals, symbol } = getSalaryAsset(); + const { decimals, symbol } = getSalaryAsset("secretary"); return { name: "Total Paid", diff --git a/packages/next-common/components/secretary/statistics/summary/index.jsx b/packages/next-common/components/secretary/statistics/summary/index.jsx index 9fa49dd077..ce8ac51f5d 100644 --- a/packages/next-common/components/secretary/statistics/summary/index.jsx +++ b/packages/next-common/components/secretary/statistics/summary/index.jsx @@ -13,7 +13,8 @@ import { } from "next-common/components/secretary/statistics/breakdown"; function TotalSpent({ cycles, paymentReferenda }) { - const { decimals: salaryDecimals } = getSalaryAsset(); + const { decimals: salaryDecimals, symbol: salarySymbol } = + getSalaryAsset("secretary"); const cyclesTotal = getCyclesTotal(cycles); const referendaTotal = getReferendaTotal(paymentReferenda); const referendaUsd = getReferendaUsd(paymentReferenda); @@ -22,7 +23,11 @@ function TotalSpent({ cycles, paymentReferenda }) { const usdTotal = formatNum(cyclesUsd.plus(referendaUsd).toFixed(2)); const rows = [ - { value: cyclesTotal.toString(), decimals: salaryDecimals, symbol: "USDT" }, + { + value: cyclesTotal.toString(), + decimals: salaryDecimals, + symbol: salarySymbol, + }, ]; if (referendaTotal.gt(0)) { diff --git a/packages/next-common/hooks/fellowship/core/useSubFellowshipCoreMember.js b/packages/next-common/hooks/fellowship/core/useSubFellowshipCoreMember.js index 57caec40f7..fb33229107 100644 --- a/packages/next-common/hooks/fellowship/core/useSubFellowshipCoreMember.js +++ b/packages/next-common/hooks/fellowship/core/useSubFellowshipCoreMember.js @@ -6,13 +6,19 @@ export default function useSubFellowshipCoreMember( pallet = "fellowshipCore", ) { const [member, setMember] = useState(null); - const { loading } = useSubStorage(pallet, "member", [address], { - callback: useCallback((rawOptional) => { - if (rawOptional.isSome) { - setMember(rawOptional.unwrap().toJSON()); - } - }, []), - }); + const { loading } = useSubStorage( + pallet, + "member", + address ? [address] : [], + { + callback: useCallback((rawOptional) => { + if (rawOptional.isSome) { + setMember(rawOptional.unwrap().toJSON()); + } + }, []), + skip: !address, + }, + ); return { isLoading: loading, member }; } diff --git a/packages/next-common/hooks/fellowship/salary/useSalaryAsset.js b/packages/next-common/hooks/fellowship/salary/useSalaryAsset.js new file mode 100644 index 0000000000..cf6d40380f --- /dev/null +++ b/packages/next-common/hooks/fellowship/salary/useSalaryAsset.js @@ -0,0 +1,24 @@ +import { useCollectivesSection } from "next-common/context/collectives/collectives"; +import useChainOrScanHeight from "next-common/hooks/height"; +import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; + +/** + * React hook that returns the salary asset info. + * Automatically reads the current section from CollectivesContext. + * If blockHeight is not provided, uses the current chain/scan height. + * + * @param {number} [blockHeight] - Optional block height to determine asset switching + * @returns {{ symbol: string, decimals: number }} + * + * Usage: + * // With explicit blockHeight (from API data) + * const { symbol, decimals } = useSalaryAsset(data.paidIndexer?.blockHeight); + * + * // Without blockHeight (uses current chain height for live data) + * const { symbol, decimals } = useSalaryAsset(); + */ +export function useSalaryAsset(blockHeight) { + const section = useCollectivesSection(); + const height = useChainOrScanHeight(); + return getSalaryAsset(section, blockHeight ?? height); +} diff --git a/packages/next-common/utils/consts/getSalaryAsset.js b/packages/next-common/utils/consts/getSalaryAsset.js index 2d5c23c2a1..ea4ab53e8c 100644 --- a/packages/next-common/utils/consts/getSalaryAsset.js +++ b/packages/next-common/utils/consts/getSalaryAsset.js @@ -1,6 +1,28 @@ -export function getSalaryAsset() { - return { - decimals: 6, - symbol: "USDT", - }; +// Asset switch points per section. +// Each section has its own independent switch timeline. +// Proposal #568: Fellowship switches from USDT(6) to HOLLAR(18) at block 9,247,655. +const SWITCH_POINTS = { + fellowship: [{ blockHeight: 8599655, symbol: "HOLLAR", decimals: 18 }], + ambassador: [], + secretary: [], +}; + +/** + * Get the salary asset info based on section and optional block height. + * @param {string} section - "fellowship" | "ambassador" | "secretary" + * @param {number} [blockHeight] - Optional block height to determine asset switching + * @returns {{ symbol: string, decimals: number }} + */ +export function getSalaryAsset(section = "fellowship", blockHeight) { + const switches = SWITCH_POINTS[section] || []; + const active = [...switches] + .reverse() + .find( + (s) => + blockHeight !== undefined && + blockHeight !== null && + blockHeight >= s.blockHeight, + ); + if (active) return { symbol: active.symbol, decimals: active.decimals }; + return { symbol: "USDT", decimals: 6 }; } From 70f0cc9874088abdb75a734cd7d7ba3e88ddf515 Mon Sep 17 00:00:00 2001 From: chaojun Date: Fri, 3 Jul 2026 14:11:03 +0800 Subject: [PATCH 02/23] Update UI to show correct asset, #7389 --- .../collectives/core/member/salary.js | 8 +- .../components/collectives/members/table.js | 12 +- .../collectives/salaryAssetValues.jsx | 51 +++++ .../components/feeds/fellowshipCommonEvent.js | 1 + .../fellowship/salary/cycles/info/closed.jsx | 5 +- .../fellowship/salary/cycles/info/ongoing.jsx | 10 +- .../salary/cycles/info/progress.jsx | 8 +- .../salary/cycles/summary/budgetItem.js | 4 +- .../salary/cycles/summary/potItem.js | 4 +- .../salary/cycles/summary/registrationItem.js | 3 +- .../salary/cycles/summary/unregisteredItem.js | 3 +- .../fellowship/salary/feeds/events/index.jsx | 1 + .../salary/feeds/events/registered.js | 15 +- .../fellowship/statistics/common.js | 3 +- .../expenditure/claimants/columns/paid.jsx | 9 +- .../expenditure/rank/doughnutChart/index.jsx | 178 ++++++++++++------ .../expenditure/rank/doughnutChart/labels.jsx | 27 ++- .../statistics/expenditure/summary/index.jsx | 3 +- .../membership/summary/summaryItems.jsx | 4 +- .../overview/fellowship/salary/stats/index.js | 20 +- .../member/fellowshipMember/salary.js | 16 +- .../profile/fellowship/statisticsInfo.jsx | 10 +- .../secretary/statistics/claimants/index.jsx | 57 ++++-- 23 files changed, 308 insertions(+), 144 deletions(-) create mode 100644 packages/next-common/components/collectives/salaryAssetValues.jsx diff --git a/packages/next-common/components/collectives/core/member/salary.js b/packages/next-common/components/collectives/core/member/salary.js index 45a5e6b118..61def90dc7 100644 --- a/packages/next-common/components/collectives/core/member/salary.js +++ b/packages/next-common/components/collectives/core/member/salary.js @@ -1,4 +1,4 @@ -import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; +import { useSalaryAsset } from "next-common/hooks/fellowship/salary/useSalaryAsset"; import ValueDisplay from "next-common/components/valueDisplay"; import { toPrecision } from "next-common/utils"; import { getRankSalary } from "next-common/utils/fellowship/getRankSalary"; @@ -9,12 +9,11 @@ export function CoreFellowshipMemberSalaryContent({ rank, isActive, params = {}, - section = "fellowship", }) { const { activeSalary, passiveSalary } = params; const salaryArray = isActive ? activeSalary : passiveSalary; const salary = getRankSalary(salaryArray, rank); - const { symbol, decimals } = getSalaryAsset(section); + const { symbol, decimals } = useSalaryAsset(); return ( -
; + } + + return ( +
+ {hasUsdt && ( + + )} + {hasHollar && ( + + )} +
+ ); +} diff --git a/packages/next-common/components/feeds/fellowshipCommonEvent.js b/packages/next-common/components/feeds/fellowshipCommonEvent.js index d31e253b2e..f4c8141c19 100644 --- a/packages/next-common/components/feeds/fellowshipCommonEvent.js +++ b/packages/next-common/components/feeds/fellowshipCommonEvent.js @@ -61,6 +61,7 @@ function EventContent({ feed, showUserInfo = true }) { ); } diff --git a/packages/next-common/components/fellowship/salary/cycles/info/closed.jsx b/packages/next-common/components/fellowship/salary/cycles/info/closed.jsx index 970304a5a4..cd2c12954d 100644 --- a/packages/next-common/components/fellowship/salary/cycles/info/closed.jsx +++ b/packages/next-common/components/fellowship/salary/cycles/info/closed.jsx @@ -29,7 +29,10 @@ export default function FellowshipSalaryCycleDetailInfoClosed({ cycle = {} }) {
- + diff --git a/packages/next-common/components/fellowship/salary/cycles/info/ongoing.jsx b/packages/next-common/components/fellowship/salary/cycles/info/ongoing.jsx index 444fd68489..c83e7deb6a 100644 --- a/packages/next-common/components/fellowship/salary/cycles/info/ongoing.jsx +++ b/packages/next-common/components/fellowship/salary/cycles/info/ongoing.jsx @@ -40,7 +40,10 @@ export default function FellowshipSalaryCycleDetailInfoOngoing({ - + @@ -55,7 +58,10 @@ export default function FellowshipSalaryCycleDetailInfoOngoing({ - +
); } -function PaidLabel({ value, label = "", color = "" }) { - const { decimals, symbol } = useSalaryAsset(); +function PaidLabel({ value, label = "", color = "", blockHeight }) { + const { decimals, symbol } = useSalaryAsset(blockHeight); return (
diff --git a/packages/next-common/components/fellowship/salary/cycles/summary/budgetItem.js b/packages/next-common/components/fellowship/salary/cycles/summary/budgetItem.js index b066a86a9a..e0b7ba96e0 100644 --- a/packages/next-common/components/fellowship/salary/cycles/summary/budgetItem.js +++ b/packages/next-common/components/fellowship/salary/cycles/summary/budgetItem.js @@ -5,8 +5,8 @@ import ValueDisplay from "next-common/components/valueDisplay"; import { toPrecision } from "next-common/utils"; import { useSalaryAsset } from "next-common/hooks/fellowship/salary/useSalaryAsset"; -export default function SalaryStatsBudgetItem({ budget }) { - const { decimals, symbol } = useSalaryAsset(); +export default function SalaryStatsBudgetItem({ budget, blockHeight }) { + const { decimals, symbol } = useSalaryAsset(blockHeight); return ( diff --git a/packages/next-common/components/fellowship/salary/cycles/summary/potItem.js b/packages/next-common/components/fellowship/salary/cycles/summary/potItem.js index fb265167d1..2b50b719e7 100644 --- a/packages/next-common/components/fellowship/salary/cycles/summary/potItem.js +++ b/packages/next-common/components/fellowship/salary/cycles/summary/potItem.js @@ -5,8 +5,8 @@ import { isNil } from "lodash-es"; import ValueDisplay from "next-common/components/valueDisplay"; import { toPrecision } from "next-common/utils"; -export default function SalaryStatsPotItem({ pot }) { - const { decimals, symbol } = useSalaryAsset(); +export default function SalaryStatsPotItem({ pot, blockHeight }) { + const { decimals, symbol } = useSalaryAsset(blockHeight); return ( diff --git a/packages/next-common/components/fellowship/salary/cycles/summary/registrationItem.js b/packages/next-common/components/fellowship/salary/cycles/summary/registrationItem.js index 6a9bb5ffef..e32644930d 100644 --- a/packages/next-common/components/fellowship/salary/cycles/summary/registrationItem.js +++ b/packages/next-common/components/fellowship/salary/cycles/summary/registrationItem.js @@ -10,7 +10,8 @@ export default function SalaryStatsRegistrationItem({ cycleData }) { const stats = useFellowshipSalaryStats(); const { totalRegistrations } = stats || {}; - const { decimals, symbol } = useSalaryAsset(); + const { indexer } = cycleData || {}; + const { decimals, symbol } = useSalaryAsset(indexer?.blockHeight); const { registeredCount } = cycleData || {}; return ( diff --git a/packages/next-common/components/fellowship/salary/cycles/summary/unregisteredItem.js b/packages/next-common/components/fellowship/salary/cycles/summary/unregisteredItem.js index eee78e51da..c8231ab663 100644 --- a/packages/next-common/components/fellowship/salary/cycles/summary/unregisteredItem.js +++ b/packages/next-common/components/fellowship/salary/cycles/summary/unregisteredItem.js @@ -10,7 +10,8 @@ export default function SalaryStatsUnregisteredItem({ cycleData }) { const stats = useFellowshipSalaryStats(); const { totalUnregisteredPaid } = stats || {}; - const { decimals, symbol } = useSalaryAsset(); + const { indexer } = cycleData || {}; + const { decimals, symbol } = useSalaryAsset(indexer?.blockHeight); const { unRegisteredPaidCount } = cycleData || {}; return ( diff --git a/packages/next-common/components/fellowship/salary/feeds/events/index.jsx b/packages/next-common/components/fellowship/salary/feeds/events/index.jsx index 1df5581c57..6132be412f 100644 --- a/packages/next-common/components/fellowship/salary/feeds/events/index.jsx +++ b/packages/next-common/components/fellowship/salary/feeds/events/index.jsx @@ -23,6 +23,7 @@ export function getFellowshipSalaryFeedsEventContent( amount={feed?.args?.amount} index={feed?.index} showUserInfo={showUserInfo} + blockHeight={feed?.indexer?.blockHeight} /> ), CycleStarted: , diff --git a/packages/next-common/components/fellowship/salary/feeds/events/registered.js b/packages/next-common/components/fellowship/salary/feeds/events/registered.js index 3b92babc13..921cf2d13b 100644 --- a/packages/next-common/components/fellowship/salary/feeds/events/registered.js +++ b/packages/next-common/components/fellowship/salary/feeds/events/registered.js @@ -6,9 +6,13 @@ import { toPrecision } from "next-common/utils"; import Link from "next-common/components/link"; import { useCollectivesContext } from "next-common/context/collectives/collectives"; -export function FellowshipRegisteredFeedContent({ amount, index }) { +export function FellowshipRegisteredFeedContent({ + amount, + index, + blockHeight, +}) { const { section } = useCollectivesContext(); - const { symbol, decimals } = getSalaryAsset(section); + const { symbol, decimals } = getSalaryAsset(section, blockHeight); return ( <> @@ -32,12 +36,17 @@ export default function FellowshipRegisteredFeed({ amount, index, showUserInfo = true, + blockHeight, }) { return ( <> {showUserInfo && } - + ); diff --git a/packages/next-common/components/fellowship/statistics/common.js b/packages/next-common/components/fellowship/statistics/common.js index 85a04578a5..d6cfdfcdf7 100644 --- a/packages/next-common/components/fellowship/statistics/common.js +++ b/packages/next-common/components/fellowship/statistics/common.js @@ -12,7 +12,8 @@ export const expenditureDoughnutChartOptions = { const name = item.dataset.name[item.dataIndex]; const percentage = item.dataset.percentage[item.dataIndex]; const count = item.dataset.data[item.dataIndex]; - return `${name}: ${formatNum(count)} (${percentage})`; + const symbol = item.dataset.symbol?.[item.dataIndex]; + return `${name}: ${formatNum(count)} ${symbol} (${percentage})`; }, }, }, diff --git a/packages/next-common/components/fellowship/statistics/expenditure/claimants/columns/paid.jsx b/packages/next-common/components/fellowship/statistics/expenditure/claimants/columns/paid.jsx index 5589d7bf9b..5072672510 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/claimants/columns/paid.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/claimants/columns/paid.jsx @@ -1,15 +1,12 @@ -import ValueDisplay from "next-common/components/valueDisplay"; -import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; +import SalaryAssetValues from "next-common/components/collectives/salaryAssetValues"; export function useStatisticsClaimantsPaidColumn() { - const { symbol } = getSalaryAsset("fellowship"); - return { name: "Total Paid", - width: 160, + width: 240, className: "text-right", cellRender(data, idx) { - return ; + return ; }, }; } diff --git a/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/index.jsx b/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/index.jsx index 0ce28c67ea..026b359b95 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/index.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/index.jsx @@ -15,65 +15,147 @@ import { import DoughnutChartLabels from "./labels"; import { useNavCollapsed } from "next-common/context/nav"; -function getTotalSalary(ranksData) { +function getAssetAmount(item, asset) { + return new BigNumber(item.salary?.[asset] || 0); +} + +function getAssetTotalSalary(ranksData, asset) { return ranksData.reduce((acc, item) => { - return acc.plus(new BigNumber(item.salary)); + return acc.plus(getAssetAmount(item, asset)); }, new BigNumber(0)); } -function transformRanksDataToObject(ranksData) { +function transformRanksDataToObject(ranksData, asset) { return ranksData.reduce((acc, item) => { - acc[item.rank] = new BigNumber(item.salary); + acc[item.rank] = getAssetAmount(item, asset); return acc; }, {}); } -function handleLabelDataArr(members, ranksData) { - const rankArr = getUniqueRanks(members); - const totalSalary = getTotalSalary(ranksData); - const ranksDataObj = transformRanksDataToObject(ranksData); - const dataArr = rankArr.map((rank, index) => { - const count = ranksDataObj[rank] || 0; - const percent = ranksDataObj[rank] - ? new BigNumber(ranksDataObj[rank]).div(totalSalary) - : ""; - return { - label: `Rank ${rank}`, - bgColor: colors[index], - count, - percent, - }; - }); - return dataArr.reverse(); +function getRankArr(members, ranksData) { + const memberRanks = getUniqueRanks(members || []); + if (memberRanks.length > 0) { + return memberRanks; + } + + return ranksData + .map((item) => item.rank) + .filter((rank) => rank !== undefined && rank !== null) + .sort((a, b) => a - b); +} + +function handleAssetLabelDataArr(members, ranksData, asset, symbol) { + const rankArr = getRankArr(members, ranksData); + const totalSalary = getAssetTotalSalary(ranksData, asset); + const ranksDataObj = transformRanksDataToObject(ranksData, asset); + return rankArr + .map((rank, index) => { + const count = ranksDataObj[rank] || new BigNumber(0); + const percent = + totalSalary.gt(0) && count.gt(0) ? count.div(totalSalary) : ""; + return { + label: `Rank ${rank}`, + bgColor: colors[index], + count: count.toNumber(), + salary: { + [asset]: count.toString(), + }, + symbol, + percent, + }; + }) + .filter((item) => item.count > 0) + .reverse(); +} + +function handleLabelDataGroups(members, ranksData) { + return [ + { + key: "usdt", + title: "USDT", + labelDataArr: handleAssetLabelDataArr(members, ranksData, "usdt", "USDT"), + }, + { + key: "hollar", + title: "HOLLAR", + labelDataArr: handleAssetLabelDataArr( + members, + ranksData, + "hollar", + "HOLLAR", + ), + }, + ].filter((item) => item.labelDataArr.length > 0); +} + +function getChartData(labelDataArr) { + return { + labels: labelDataArr.map((i) => i.label), + datasets: [ + { + data: labelDataArr.map((item) => item.count), + backgroundColor: labelDataArr.map((item) => item.bgColor), + borderColor: labelDataArr.map((item) => item.bgColor), + borderWidth: 0, + name: labelDataArr.map((i) => i.label), + symbol: labelDataArr.map((i) => i.symbol), + percentage: labelDataArr.map((item) => + item.percent ? `${item.percent.times(100).toFixed(2)}%` : "0%", + ), + }, + ], + }; } -function RankChart({ labelDataArr, data }) { +function AssetRankChart({ title, labelDataArr }) { + const data = getChartData(labelDataArr); const [navCollapsed] = useNavCollapsed(); const options = useDoughnutChartOptions(expenditureDoughnutChartOptions); return ( -
- -
- +
+
{title}
+
+ +
+ +
); } +function RankChart({ labelDataGroups }) { + if (labelDataGroups.length === 0) { + return No data; + } + + return ( +
+ {labelDataGroups.map((item) => ( + + ))} +
+ ); +} + export default function RankDoughnutChart({ members = [] }) { const ranksApi = fellowshipStatisticsRanksApi; - const [labelDataArr, setLabelDataArr] = useState([]); + const [labelDataGroups, setLabelDataGroups] = useState([]); const [contentLoading, setContentLoading] = useState(false); const { value: ranksData } = useAsync(async () => { @@ -92,34 +174,18 @@ export default function RankDoughnutChart({ members = [] }) { useEffect(() => { if (members && ranksData) { - const dataArr = handleLabelDataArr(members, ranksData); - setLabelDataArr(dataArr); + const groups = handleLabelDataGroups(members, ranksData); + setLabelDataGroups(groups); setContentLoading(false); } }, [members, ranksData]); - const data = { - labels: labelDataArr.map((i) => i.label), - datasets: [ - { - data: labelDataArr.map((item) => item.count), - backgroundColor: labelDataArr.map((item) => item.bgColor), - borderColor: labelDataArr.map((item) => item.bgColor), - borderWidth: 0, - name: labelDataArr.map((i) => i.label), - percentage: labelDataArr.map( - (item) => `${(item.percent * 100).toFixed(2)}%`, - ), - }, - ], - }; - return ( <> {contentLoading ? ( ) : ( - + )} ); diff --git a/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx b/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx index f10bee1b9e..5c374dc7b1 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx @@ -1,22 +1,22 @@ import { cn } from "next-common/utils"; -import ValueDisplay from "next-common/components/valueDisplay"; -import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; import { getPercentageValue } from "next-common/components/fellowship/statistics/common"; +import SalaryAssetValues from "next-common/components/collectives/salaryAssetValues"; -function getSalaryValue(count, symbol) { - return count ? : `0 ${symbol}`; -} - -function RowItem({ bgColor, label, percentage, count }) { +function RowItem({ bgColor, label, percentage, salary }) { return (
- {label} - {count} - + {label} +
+ +
+ {percentage}
@@ -24,16 +24,15 @@ function RowItem({ bgColor, label, percentage, count }) { } export default function DoughnutChartLabels({ labelDataArr }) { - const { symbol } = getSalaryAsset("fellowship"); return ( -
+
{labelDataArr.map((i) => ( ))}
diff --git a/packages/next-common/components/fellowship/statistics/expenditure/summary/index.jsx b/packages/next-common/components/fellowship/statistics/expenditure/summary/index.jsx index c6cb36114a..f02e6dd128 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/summary/index.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/summary/index.jsx @@ -4,6 +4,7 @@ import SummaryLayout from "next-common/components/summary/layout/layout"; import BigNumber from "bignumber.js"; import ValueDisplay from "next-common/components/valueDisplay"; import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; +import { useSalaryAsset } from "next-common/hooks/fellowship/salary/useSalaryAsset"; function getTotalSpent(data) { if (data && data.length > 0) { @@ -31,7 +32,7 @@ function SpentCycles({ count }) { function TotalSpent({ cycles }) { const totalSpent = getTotalSpent(cycles); - const { symbol } = getSalaryAsset("fellowship"); + const { symbol } = useSalaryAsset(); return ( diff --git a/packages/next-common/components/fellowship/statistics/membership/summary/summaryItems.jsx b/packages/next-common/components/fellowship/statistics/membership/summary/summaryItems.jsx index 95e1667551..d3742cf314 100644 --- a/packages/next-common/components/fellowship/statistics/membership/summary/summaryItems.jsx +++ b/packages/next-common/components/fellowship/statistics/membership/summary/summaryItems.jsx @@ -1,10 +1,10 @@ import SummaryItem from "next-common/components/summary/layout/item"; import SummaryLayout from "next-common/components/summary/layout/layout"; import ValueDisplay from "next-common/components/valueDisplay"; -import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; +import { useSalaryAsset } from "next-common/hooks/fellowship/salary/useSalaryAsset"; export default function StatisticsMembershipSummaryItems({ summaryData }) { - const { symbol } = getSalaryAsset("fellowship"); + const { symbol } = useSalaryAsset(); if (!summaryData) { return null; } diff --git a/packages/next-common/components/overview/fellowship/salary/stats/index.js b/packages/next-common/components/overview/fellowship/salary/stats/index.js index 825762d5b7..4000858990 100644 --- a/packages/next-common/components/overview/fellowship/salary/stats/index.js +++ b/packages/next-common/components/overview/fellowship/salary/stats/index.js @@ -51,8 +51,14 @@ export default function FellowshipSalaryStats() { className={cn(navCollapsed ? "max-sm:hidden" : "max-md:hidden")} > - - + + @@ -62,8 +68,14 @@ export default function FellowshipSalaryStats() { - - + + diff --git a/packages/next-common/components/pages/fellowship/member/fellowshipMember/salary.js b/packages/next-common/components/pages/fellowship/member/fellowshipMember/salary.js index ac4c991230..e1a1da8ab7 100644 --- a/packages/next-common/components/pages/fellowship/member/fellowshipMember/salary.js +++ b/packages/next-common/components/pages/fellowship/member/fellowshipMember/salary.js @@ -5,6 +5,7 @@ import { usePageProps } from "next-common/context/page"; import useSubCollectiveRank from "next-common/hooks/collectives/useSubCollectiveRank"; import { isSameAddress, toPrecision } from "next-common/utils"; import { useSalaryAsset } from "next-common/hooks/fellowship/salary/useSalaryAsset"; +import SalaryAssetValues from "next-common/components/collectives/salaryAssetValues"; import { getRankSalary } from "next-common/utils/fellowship/getRankSalary"; import { BorderedRow, @@ -22,7 +23,7 @@ import useSubCoreCollectivesMember from "next-common/hooks/collectives/useSubCor function Wrapper({ children }) { return ( -
+
{children}
); @@ -48,7 +49,7 @@ function ActionsWrapper({ children, className = "" }) { function NotImportedSalary() { return ( -
+
Salary -
@@ -81,15 +82,14 @@ function SalaryValue({ salary }) { } function TotalPaid({ totalPaid }) { - const { symbol } = useSalaryAsset(); return (
- + Total Paid
- +
); @@ -99,7 +99,7 @@ function JoinedCycles({ joinedCycles }) { return (
- + Joined Cycles
{joinedCycles} @@ -133,13 +133,13 @@ function MemberSalary({ address }) { return ( -
+
Salary
diff --git a/packages/next-common/components/profile/fellowship/statisticsInfo.jsx b/packages/next-common/components/profile/fellowship/statisticsInfo.jsx index d3d6e16f35..92f47456db 100644 --- a/packages/next-common/components/profile/fellowship/statisticsInfo.jsx +++ b/packages/next-common/components/profile/fellowship/statisticsInfo.jsx @@ -3,15 +3,13 @@ import LoadableContent from "next-common/components/common/loadableContent"; import { NeutralPanel } from "next-common/components/styled/containers/neutralPanel"; import SummaryItem from "next-common/components/summary/layout/item"; import SummaryLayout from "next-common/components/summary/layout/layout"; -import ValueDisplay from "next-common/components/valueDisplay"; +import SalaryAssetValues from "next-common/components/collectives/salaryAssetValues"; import { usePageProps } from "next-common/context/page"; -import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; import { backendApi } from "next-common/services/nextApi"; import { ambassadorStatisticsUsersApi, fellowshipStatisticsUsersApi, } from "next-common/services/url"; -import { toPrecision } from "next-common/utils"; import { useAsync } from "react-use"; import MemberRankChanges from "./memberRankChanges"; @@ -37,17 +35,13 @@ function useUserStatisticsData(address, section) { function ProfileFellowshipStatisticsInfoImpl({ section = "fellowship" }) { const { id: address } = usePageProps(); const { value, loading } = useUserStatisticsData(address, section); - const { decimals, symbol } = getSalaryAsset(section || "fellowship"); return ( - + diff --git a/packages/next-common/components/secretary/statistics/claimants/index.jsx b/packages/next-common/components/secretary/statistics/claimants/index.jsx index 9dd72809e7..0a221ae890 100644 --- a/packages/next-common/components/secretary/statistics/claimants/index.jsx +++ b/packages/next-common/components/secretary/statistics/claimants/index.jsx @@ -19,9 +19,11 @@ import { getReferendaTotalByAddress, getReferendaUsdByAddress, } from "next-common/components/secretary/statistics/breakdown"; -import ValueDisplay from "next-common/components/valueDisplay"; +import SalaryAssetValues, { + isPositiveAmount, +} from "next-common/components/collectives/salaryAssetValues"; import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; -import { formatNum, toPrecision } from "next-common/utils"; +import { formatNum } from "next-common/utils"; function handleClaimantsData(originalMembers, members) { const membersRank = members.reduce((acc, member) => { @@ -78,43 +80,58 @@ function useSecretaryClaimantsReferendaColumn(paymentReferenda) { } function useSecretaryClaimantsPaidColumn(paymentReferenda) { - const { decimals, symbol } = getSalaryAsset("secretary"); + const { decimals } = getSalaryAsset("secretary"); return { name: "Total Paid", className: "text-right", + width: 240, cellRender(data, idx) { - const salary = BigInt(data.salary || 0); + const salary = data.salary || {}; + const usdt = salary.usdt || "0"; + const hollar = salary.hollar || "0"; const address = data.who; const referendaTotal = getReferendaTotalByAddress( paymentReferenda, address, ); + const hasHollar = isPositiveAmount(hollar); + const hasUsdt = isPositiveAmount(usdt); + if (referendaTotal.isZero()) { - return ( - - ); + return ; } const referendaUsd = getReferendaUsdByAddress(paymentReferenda, address); - const cyclesUsd = new BigNumber(salary.toString()).div( - Math.pow(10, decimals), - ); - const usdTotal = cyclesUsd.plus(referendaUsd).toFixed(2); + const salaryUsd = new BigNumber(usdt).plus(hollar); + const usdTotal = salaryUsd.plus(referendaUsd).toFixed(2); + + const rows = []; + + if (hasUsdt) { + rows.push({ + value: new BigNumber(usdt).shiftedBy(decimals).toFixed(0), + decimals, + symbol: "USDT", + }); + } + + if (hasHollar) { + rows.push({ + value: new BigNumber(hollar).shiftedBy(18).toFixed(0), + decimals: 18, + symbol: "HOLLAR", + }); + } - const rows = [ - { value: salary.toString(), decimals, symbol }, - { + if (referendaTotal.gt(0)) { + rows.push({ value: referendaTotal.toString(), decimals: 10, symbol: "DOT", - }, - ]; + }); + } return ( Date: Fri, 3 Jul 2026 14:42:00 +0800 Subject: [PATCH 03/23] fix, #7389 --- .../fellowship/statistics/common.js | 14 +- .../expenditure/rank/doughnutChart/index.jsx | 147 +++++++----------- .../expenditure/rank/doughnutChart/labels.jsx | 62 ++++++-- 3 files changed, 119 insertions(+), 104 deletions(-) diff --git a/packages/next-common/components/fellowship/statistics/common.js b/packages/next-common/components/fellowship/statistics/common.js index d6cfdfcdf7..e839d26efb 100644 --- a/packages/next-common/components/fellowship/statistics/common.js +++ b/packages/next-common/components/fellowship/statistics/common.js @@ -3,6 +3,17 @@ import deepmerge from "deepmerge"; import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; import { toPrecision, formatNum } from "next-common/utils"; import Loading from "next-common/components/loading"; +import BigNumber from "bignumber.js"; + +const amountFormat = { + decimalSeparator: ".", + groupSeparator: ",", + groupSize: 3, +}; + +function formatUsdAmount(value) { + return new BigNumber(value || 0).toFormat(2, amountFormat); +} export const expenditureDoughnutChartOptions = { plugins: { @@ -12,8 +23,7 @@ export const expenditureDoughnutChartOptions = { const name = item.dataset.name[item.dataIndex]; const percentage = item.dataset.percentage[item.dataIndex]; const count = item.dataset.data[item.dataIndex]; - const symbol = item.dataset.symbol?.[item.dataIndex]; - return `${name}: ${formatNum(count)} ${symbol} (${percentage})`; + return `${name}: ${formatUsdAmount(count)} USD (${percentage})`; }, }, }, diff --git a/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/index.jsx b/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/index.jsx index 026b359b95..4750e6a3a7 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/index.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/index.jsx @@ -15,19 +15,23 @@ import { import DoughnutChartLabels from "./labels"; import { useNavCollapsed } from "next-common/context/nav"; -function getAssetAmount(item, asset) { - return new BigNumber(item.salary?.[asset] || 0); -} - -function getAssetTotalSalary(ranksData, asset) { +function getTotalSalary(ranksData) { return ranksData.reduce((acc, item) => { - return acc.plus(getAssetAmount(item, asset)); + const s = item.salary || {}; + const usdt = new BigNumber(s.usdt || 0); + const hollar = new BigNumber(s.hollar || 0); + return acc.plus(usdt).plus(hollar); }, new BigNumber(0)); } -function transformRanksDataToObject(ranksData, asset) { +function transformRanksDataToObject(ranksData) { return ranksData.reduce((acc, item) => { - acc[item.rank] = getAssetAmount(item, asset); + const s = item.salary || {}; + const usdt = new BigNumber(s.usdt || 0); + const hollar = new BigNumber(s.hollar || 0); + acc[item.rank] = usdt.plus(hollar); + acc[`${item.rank}_usdt`] = usdt; + acc[`${item.rank}_hollar`] = hollar; return acc; }, {}); } @@ -44,13 +48,15 @@ function getRankArr(members, ranksData) { .sort((a, b) => a - b); } -function handleAssetLabelDataArr(members, ranksData, asset, symbol) { +function handleLabelDataArr(members, ranksData) { const rankArr = getRankArr(members, ranksData); - const totalSalary = getAssetTotalSalary(ranksData, asset); - const ranksDataObj = transformRanksDataToObject(ranksData, asset); + const totalSalary = getTotalSalary(ranksData); + const ranksDataObj = transformRanksDataToObject(ranksData); return rankArr .map((rank, index) => { const count = ranksDataObj[rank] || new BigNumber(0); + const usdtAmount = ranksDataObj[`${rank}_usdt`] || new BigNumber(0); + const hollarAmount = ranksDataObj[`${rank}_hollar`] || new BigNumber(0); const percent = totalSalary.gt(0) && count.gt(0) ? count.div(totalSalary) : ""; return { @@ -58,9 +64,9 @@ function handleAssetLabelDataArr(members, ranksData, asset, symbol) { bgColor: colors[index], count: count.toNumber(), salary: { - [asset]: count.toString(), + usdt: usdtAmount.toString(), + hollar: hollarAmount.toString(), }, - symbol, percent, }; }) @@ -68,86 +74,25 @@ function handleAssetLabelDataArr(members, ranksData, asset, symbol) { .reverse(); } -function handleLabelDataGroups(members, ranksData) { - return [ - { - key: "usdt", - title: "USDT", - labelDataArr: handleAssetLabelDataArr(members, ranksData, "usdt", "USDT"), - }, - { - key: "hollar", - title: "HOLLAR", - labelDataArr: handleAssetLabelDataArr( - members, - ranksData, - "hollar", - "HOLLAR", - ), - }, - ].filter((item) => item.labelDataArr.length > 0); -} - -function getChartData(labelDataArr) { - return { - labels: labelDataArr.map((i) => i.label), - datasets: [ - { - data: labelDataArr.map((item) => item.count), - backgroundColor: labelDataArr.map((item) => item.bgColor), - borderColor: labelDataArr.map((item) => item.bgColor), - borderWidth: 0, - name: labelDataArr.map((i) => i.label), - symbol: labelDataArr.map((i) => i.symbol), - percentage: labelDataArr.map((item) => - item.percent ? `${item.percent.times(100).toFixed(2)}%` : "0%", - ), - }, - ], - }; -} - -function AssetRankChart({ title, labelDataArr }) { - const data = getChartData(labelDataArr); +function RankChart({ labelDataArr, data }) { const [navCollapsed] = useNavCollapsed(); const options = useDoughnutChartOptions(expenditureDoughnutChartOptions); return ( -
-
{title}
-
- -
- -
-
-
- ); -} - -function RankChart({ labelDataGroups }) { - if (labelDataGroups.length === 0) { - return No data; - } - - return ( -
- {labelDataGroups.map((item) => ( - + +
+ - ))} +
); } @@ -155,7 +100,7 @@ function RankChart({ labelDataGroups }) { export default function RankDoughnutChart({ members = [] }) { const ranksApi = fellowshipStatisticsRanksApi; - const [labelDataGroups, setLabelDataGroups] = useState([]); + const [labelDataArr, setLabelDataArr] = useState([]); const [contentLoading, setContentLoading] = useState(false); const { value: ranksData } = useAsync(async () => { @@ -174,18 +119,34 @@ export default function RankDoughnutChart({ members = [] }) { useEffect(() => { if (members && ranksData) { - const groups = handleLabelDataGroups(members, ranksData); - setLabelDataGroups(groups); + const dataArr = handleLabelDataArr(members, ranksData); + setLabelDataArr(dataArr); setContentLoading(false); } }, [members, ranksData]); + const data = { + labels: labelDataArr.map((i) => i.label), + datasets: [ + { + data: labelDataArr.map((item) => item.count), + backgroundColor: labelDataArr.map((item) => item.bgColor), + borderColor: labelDataArr.map((item) => item.bgColor), + borderWidth: 0, + name: labelDataArr.map((i) => i.label), + percentage: labelDataArr.map((item) => + item.percent ? `${item.percent.times(100).toFixed(2)}%` : "0%", + ), + }, + ], + }; + return ( <> {contentLoading ? ( ) : ( - + )} ); diff --git a/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx b/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx index 5c374dc7b1..477701c5c7 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx @@ -1,8 +1,53 @@ import { cn } from "next-common/utils"; import { getPercentageValue } from "next-common/components/fellowship/statistics/common"; -import SalaryAssetValues from "next-common/components/collectives/salaryAssetValues"; +import Tooltip from "next-common/components/tooltip"; +import BigNumber from "bignumber.js"; -function RowItem({ bgColor, label, percentage, salary }) { +const amountFormat = { + decimalSeparator: ".", + groupSeparator: ",", + groupSize: 3, +}; + +function formatUsdAmount(value) { + return new BigNumber(value || 0).toFormat(2, amountFormat); +} + +function formatUsdLabelAmount(value) { + const amount = new BigNumber(value || 0); + const abbreviations = [ + { value: new BigNumber("1000000000000000"), suffix: "Q" }, + { value: new BigNumber("1000000000000"), suffix: "T" }, + { value: new BigNumber("1000000000"), suffix: "B" }, + { value: new BigNumber("1000000"), suffix: "M" }, + { value: new BigNumber("1000"), suffix: "K" }, + ]; + + const abbreviation = abbreviations.find((item) => + amount.isGreaterThanOrEqualTo(item.value), + ); + + if (!abbreviation) { + return amount.toFormat(2, amountFormat); + } + + return `${amount.dividedBy(abbreviation.value).toFormat(2, amountFormat)}${ + abbreviation.suffix + }`; +} + +function tooltipContent(salary) { + const parts = []; + if (new BigNumber(salary?.usdt || 0).gt(0)) { + parts.push(
{formatUsdAmount(salary.usdt)} USDT
); + } + if (new BigNumber(salary?.hollar || 0).gt(0)) { + parts.push(
{formatUsdAmount(salary.hollar)} HOLLAR
); + } + return parts.length > 0 ? parts : null; +} + +function RowItem({ bgColor, label, percentage, count }) { return (
{label} -
- -
+ + + {formatUsdLabelAmount(count.count)} USD + + {percentage} @@ -32,7 +76,7 @@ export default function DoughnutChartLabels({ labelDataArr }) { label={i.label} bgColor={i.bgColor} percentage={getPercentageValue(i.percent)} - salary={i.salary} + count={{ count: i.count, salary: i.salary }} /> ))}
From ec87dc66272848a24a072d45a3a9058a3802e705 Mon Sep 17 00:00:00 2001 From: chaojun Date: Fri, 3 Jul 2026 15:04:22 +0800 Subject: [PATCH 04/23] fix, #7389 --- .../detail/treasury/common/bountyCountDown.js | 2 +- .../expenditure/cycles/cyclesChart.jsx | 49 ++++++++++++++++++- .../salary/payments/columns/paid.jsx | 5 +- .../core/useSubFellowshipCoreMember.js | 8 ++- .../utils/consts/getSalaryAsset.js | 2 +- 5 files changed, 60 insertions(+), 6 deletions(-) diff --git a/packages/next-common/components/detail/treasury/common/bountyCountDown.js b/packages/next-common/components/detail/treasury/common/bountyCountDown.js index 5dd589cdba..9807513a15 100644 --- a/packages/next-common/components/detail/treasury/common/bountyCountDown.js +++ b/packages/next-common/components/detail/treasury/common/bountyCountDown.js @@ -10,7 +10,7 @@ import { useOnchainData } from "next-common/context/post"; */ export default function BountyCountDown() { const data = useOnchainData(); - if (data.state?.state !== "PendingPayout") { + if (!data || data.state?.state !== "PendingPayout") { return null; } diff --git a/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx b/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx index 8a239a24a3..747e929791 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx @@ -3,6 +3,40 @@ import BarChart from "./barChart"; import { startCase } from "lodash-es"; import BigNumber from "bignumber.js"; import { getAbbreviateBigNumber } from "next-common/components/fellowship/statistics/common.js"; +import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; + +const amountFormat = { + decimalSeparator: ".", + groupSeparator: ",", + groupSize: 3, +}; + +function normalizeCycleAmount(value, cycle) { + const { decimals } = getSalaryAsset("fellowship", cycle.indexer?.blockHeight); + return new BigNumber(value || 0).shiftedBy(-decimals).toNumber(); +} + +function formatAxisAmount(value) { + const amount = new BigNumber(value || 0); + const abbreviations = [ + { value: new BigNumber("1000000000000000"), suffix: "Q" }, + { value: new BigNumber("1000000000000"), suffix: "T" }, + { value: new BigNumber("1000000000"), suffix: "B" }, + { value: new BigNumber("1000000"), suffix: "M" }, + { value: new BigNumber("1000"), suffix: "K" }, + ]; + const abbreviation = abbreviations.find((item) => + amount.isGreaterThanOrEqualTo(item.value), + ); + + if (!abbreviation) { + return amount.toFormat(2, amountFormat); + } + + return `${amount.dividedBy(abbreviation.value).toFormat(2, amountFormat)}${ + abbreviation.suffix + }`; +} function getTooltipTitle(item) { const tooltipItem = item[0]; @@ -58,7 +92,9 @@ export default function CyclesChart({ values }) { categoryPercentage, barPercentage, label: "Registered Paid", - data: values.map((value) => value.registeredPaid), + data: values.map((value) => + normalizeCycleAmount(value.registeredPaid, value), + ), backgroundColor: "rgba(230, 0, 122, 1)", tooltip: true, }, @@ -66,7 +102,9 @@ export default function CyclesChart({ values }) { categoryPercentage, barPercentage, label: "Unregistered Paid", - data: values.map((value) => value.unRegisteredPaid), + data: values.map((value) => + normalizeCycleAmount(value.unRegisteredPaid, value), + ), backgroundColor: "rgba(230, 0, 122, 0.4)", tooltip: true, }, @@ -93,6 +131,13 @@ export default function CyclesChart({ values }) { }, }, }, + scales: { + y: { + ticks: { + callback: formatAxisAmount, + }, + }, + }, }} /> ); diff --git a/packages/next-common/components/profile/fellowship/salary/payments/columns/paid.jsx b/packages/next-common/components/profile/fellowship/salary/payments/columns/paid.jsx index 7a8de98aba..71894fab55 100644 --- a/packages/next-common/components/profile/fellowship/salary/payments/columns/paid.jsx +++ b/packages/next-common/components/profile/fellowship/salary/payments/columns/paid.jsx @@ -1,15 +1,18 @@ import ValueDisplay from "next-common/components/valueDisplay"; import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; import { toPrecision } from "next-common/utils"; +import { useCollectivesSection } from "next-common/context/collectives/collectives"; export function useProfileFellowshipSalaryPaymentPaidColumn(props = {}) { + const section = useCollectivesSection(); + return { name: "Paid", width: 160, className: "text-right", cellRender(data, idx) { const { decimals, symbol } = getSalaryAsset( - "fellowship", + section, data?.paidIndexer?.blockHeight, ); return ( diff --git a/packages/next-common/hooks/fellowship/core/useSubFellowshipCoreMember.js b/packages/next-common/hooks/fellowship/core/useSubFellowshipCoreMember.js index fb33229107..148e125318 100644 --- a/packages/next-common/hooks/fellowship/core/useSubFellowshipCoreMember.js +++ b/packages/next-common/hooks/fellowship/core/useSubFellowshipCoreMember.js @@ -1,4 +1,4 @@ -import { useCallback, useState } from "react"; +import { useCallback, useEffect, useState } from "react"; import useSubStorage from "next-common/hooks/common/useSubStorage"; export default function useSubFellowshipCoreMember( @@ -6,6 +6,12 @@ export default function useSubFellowshipCoreMember( pallet = "fellowshipCore", ) { const [member, setMember] = useState(null); + useEffect(() => { + if (!address) { + setMember(null); + } + }, [address]); + const { loading } = useSubStorage( pallet, "member", diff --git a/packages/next-common/utils/consts/getSalaryAsset.js b/packages/next-common/utils/consts/getSalaryAsset.js index ea4ab53e8c..bcc1755cd1 100644 --- a/packages/next-common/utils/consts/getSalaryAsset.js +++ b/packages/next-common/utils/consts/getSalaryAsset.js @@ -2,7 +2,7 @@ // Each section has its own independent switch timeline. // Proposal #568: Fellowship switches from USDT(6) to HOLLAR(18) at block 9,247,655. const SWITCH_POINTS = { - fellowship: [{ blockHeight: 8599655, symbol: "HOLLAR", decimals: 18 }], + fellowship: [{ blockHeight: 9247655, symbol: "HOLLAR", decimals: 18 }], ambassador: [], secretary: [], }; From 9c41ddbb6fc316b0e4e2979de06e1c4911f17988 Mon Sep 17 00:00:00 2001 From: chaojun Date: Fri, 3 Jul 2026 16:00:58 +0800 Subject: [PATCH 05/23] fix, salary asset type format, #7389 --- .../statistics/membership/summary/summaryItems.jsx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/next-common/components/fellowship/statistics/membership/summary/summaryItems.jsx b/packages/next-common/components/fellowship/statistics/membership/summary/summaryItems.jsx index d3742cf314..737b4529c2 100644 --- a/packages/next-common/components/fellowship/statistics/membership/summary/summaryItems.jsx +++ b/packages/next-common/components/fellowship/statistics/membership/summary/summaryItems.jsx @@ -2,9 +2,10 @@ import SummaryItem from "next-common/components/summary/layout/item"; import SummaryLayout from "next-common/components/summary/layout/layout"; import ValueDisplay from "next-common/components/valueDisplay"; import { useSalaryAsset } from "next-common/hooks/fellowship/salary/useSalaryAsset"; +import { toPrecision } from "next-common/utils"; export default function StatisticsMembershipSummaryItems({ summaryData }) { - const { symbol } = useSalaryAsset(); + const { symbol, decimals } = useSalaryAsset(); if (!summaryData) { return null; } @@ -21,11 +22,17 @@ export default function StatisticsMembershipSummaryItems({ summaryData }) { {promotionTimes} - + {demotionTimes} - + {retentionTimes} From 8b1b83cd3dc5be86b0c0fd1450181fe9ed54797d Mon Sep 17 00:00:00 2001 From: chaojun Date: Fri, 3 Jul 2026 16:51:30 +0800 Subject: [PATCH 06/23] fix ValueDisplay tooltip, #7389 --- packages/next-common/components/valueDisplay.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/next-common/components/valueDisplay.js b/packages/next-common/components/valueDisplay.js index f8f4c64aa2..8291de33e8 100644 --- a/packages/next-common/components/valueDisplay.js +++ b/packages/next-common/components/valueDisplay.js @@ -55,9 +55,9 @@ export default function ValueDisplay({ {symbolContent} ); - tooltipContent = `${bigValue.toFixed()}${ - symbol ? " " + symbol : "" - } ${tooltipOtherContent}`; + tooltipContent = `${bigValue.toFixed()}${symbol ? " " + symbol : ""} ${ + tooltipOtherContent || "" + }`; } else if ( Number(value) >= 100000 || getEffectiveNumbers(value)?.length >= 11 From 2309bba4ef35767987e10e0e83284aa9f369c711 Mon Sep 17 00:00:00 2001 From: chaojun Date: Fri, 3 Jul 2026 17:22:41 +0800 Subject: [PATCH 07/23] SImplify, #7389 --- .../next-common/components/collectives/salaryAssetValues.jsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/next-common/components/collectives/salaryAssetValues.jsx b/packages/next-common/components/collectives/salaryAssetValues.jsx index e2fc341a21..f427b93bf6 100644 --- a/packages/next-common/components/collectives/salaryAssetValues.jsx +++ b/packages/next-common/components/collectives/salaryAssetValues.jsx @@ -7,9 +7,8 @@ export function normalizeSalaryAssetValue(value = {}) { } return { - usdt: value.usdt || value.usdtSalary || value.usdtTotalSalary || "0", - hollar: - value.hollar || value.hollarSalary || value.hollarTotalSalary || "0", + usdt: value.usdt || "0", + hollar: value.hollar || "0", }; } From 8d63817d161a84a64749677070a881e27109dc6b Mon Sep 17 00:00:00 2001 From: chaojun Date: Fri, 3 Jul 2026 17:34:27 +0800 Subject: [PATCH 08/23] Update, #7389 --- .../expenditure/rank/doughnutChart/index.jsx | 5 +++-- .../expenditure/rank/doughnutChart/labels.jsx | 10 ++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/index.jsx b/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/index.jsx index 4750e6a3a7..3b030cb253 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/index.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/index.jsx @@ -12,12 +12,13 @@ import { getUniqueRanks, useDoughnutChartOptions, } from "next-common/components/fellowship/statistics/common.js"; +import { normalizeSalaryAssetValue } from "next-common/components/collectives/salaryAssetValues"; import DoughnutChartLabels from "./labels"; import { useNavCollapsed } from "next-common/context/nav"; function getTotalSalary(ranksData) { return ranksData.reduce((acc, item) => { - const s = item.salary || {}; + const s = normalizeSalaryAssetValue(item.salary); const usdt = new BigNumber(s.usdt || 0); const hollar = new BigNumber(s.hollar || 0); return acc.plus(usdt).plus(hollar); @@ -26,7 +27,7 @@ function getTotalSalary(ranksData) { function transformRanksDataToObject(ranksData) { return ranksData.reduce((acc, item) => { - const s = item.salary || {}; + const s = normalizeSalaryAssetValue(item.salary); const usdt = new BigNumber(s.usdt || 0); const hollar = new BigNumber(s.hollar || 0); acc[item.rank] = usdt.plus(hollar); diff --git a/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx b/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx index 477701c5c7..0113ec8080 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx @@ -1,5 +1,6 @@ import { cn } from "next-common/utils"; import { getPercentageValue } from "next-common/components/fellowship/statistics/common"; +import { normalizeSalaryAssetValue } from "next-common/components/collectives/salaryAssetValues"; import Tooltip from "next-common/components/tooltip"; import BigNumber from "bignumber.js"; @@ -37,12 +38,13 @@ function formatUsdLabelAmount(value) { } function tooltipContent(salary) { + const value = normalizeSalaryAssetValue(salary); const parts = []; - if (new BigNumber(salary?.usdt || 0).gt(0)) { - parts.push(
{formatUsdAmount(salary.usdt)} USDT
); + if (new BigNumber(value.usdt || 0).gt(0)) { + parts.push(
{formatUsdAmount(value.usdt)} USDT
); } - if (new BigNumber(salary?.hollar || 0).gt(0)) { - parts.push(
{formatUsdAmount(salary.hollar)} HOLLAR
); + if (new BigNumber(value.hollar || 0).gt(0)) { + parts.push(
{formatUsdAmount(value.hollar)} HOLLAR
); } return parts.length > 0 ? parts : null; } From ae794556d3529cbe04b392314b733392c3793c1d Mon Sep 17 00:00:00 2001 From: chaojun Date: Tue, 7 Jul 2026 11:56:46 +0800 Subject: [PATCH 09/23] refactor, #7389 --- .../expenditure/rank/doughnutChart/index.jsx | 12 ++-- .../expenditure/rank/doughnutChart/labels.jsx | 65 +++++++------------ 2 files changed, 31 insertions(+), 46 deletions(-) diff --git a/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/index.jsx b/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/index.jsx index 3b030cb253..67dfbe10d2 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/index.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/index.jsx @@ -55,23 +55,25 @@ function handleLabelDataArr(members, ranksData) { const ranksDataObj = transformRanksDataToObject(ranksData); return rankArr .map((rank, index) => { - const count = ranksDataObj[rank] || new BigNumber(0); + const totalAmount = ranksDataObj[rank] || new BigNumber(0); const usdtAmount = ranksDataObj[`${rank}_usdt`] || new BigNumber(0); const hollarAmount = ranksDataObj[`${rank}_hollar`] || new BigNumber(0); const percent = - totalSalary.gt(0) && count.gt(0) ? count.div(totalSalary) : ""; + totalSalary.gt(0) && totalAmount.gt(0) + ? totalAmount.div(totalSalary) + : ""; return { label: `Rank ${rank}`, bgColor: colors[index], - count: count.toNumber(), salary: { usdt: usdtAmount.toString(), hollar: hollarAmount.toString(), + total: totalAmount.toNumber(), }, percent, }; }) - .filter((item) => item.count > 0) + .filter((item) => item.salary.total > 0) .reverse(); } @@ -130,7 +132,7 @@ export default function RankDoughnutChart({ members = [] }) { labels: labelDataArr.map((i) => i.label), datasets: [ { - data: labelDataArr.map((item) => item.count), + data: labelDataArr.map((item) => item.salary.total), backgroundColor: labelDataArr.map((item) => item.bgColor), borderColor: labelDataArr.map((item) => item.bgColor), borderWidth: 0, diff --git a/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx b/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx index 0113ec8080..fce80a8590 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx @@ -1,55 +1,37 @@ import { cn } from "next-common/utils"; import { getPercentageValue } from "next-common/components/fellowship/statistics/common"; import { normalizeSalaryAssetValue } from "next-common/components/collectives/salaryAssetValues"; +import ValueDisplay from "next-common/components/valueDisplay"; import Tooltip from "next-common/components/tooltip"; import BigNumber from "bignumber.js"; -const amountFormat = { - decimalSeparator: ".", - groupSeparator: ",", - groupSize: 3, -}; - -function formatUsdAmount(value) { - return new BigNumber(value || 0).toFormat(2, amountFormat); -} - -function formatUsdLabelAmount(value) { - const amount = new BigNumber(value || 0); - const abbreviations = [ - { value: new BigNumber("1000000000000000"), suffix: "Q" }, - { value: new BigNumber("1000000000000"), suffix: "T" }, - { value: new BigNumber("1000000000"), suffix: "B" }, - { value: new BigNumber("1000000"), suffix: "M" }, - { value: new BigNumber("1000"), suffix: "K" }, - ]; - - const abbreviation = abbreviations.find((item) => - amount.isGreaterThanOrEqualTo(item.value), - ); - - if (!abbreviation) { - return amount.toFormat(2, amountFormat); - } - - return `${amount.dividedBy(abbreviation.value).toFormat(2, amountFormat)}${ - abbreviation.suffix - }`; -} - function tooltipContent(salary) { const value = normalizeSalaryAssetValue(salary); const parts = []; if (new BigNumber(value.usdt || 0).gt(0)) { - parts.push(
{formatUsdAmount(value.usdt)} USDT
); + parts.push( + , + ); } if (new BigNumber(value.hollar || 0).gt(0)) { - parts.push(
{formatUsdAmount(value.hollar)} HOLLAR
); + parts.push( + , + ); } return parts.length > 0 ? parts : null; } -function RowItem({ bgColor, label, percentage, count }) { +function RowItem({ bgColor, label, percentage, salary }) { return (
{label} - - - {formatUsdLabelAmount(count.count)} USD - + + {percentage} @@ -78,7 +61,7 @@ export default function DoughnutChartLabels({ labelDataArr }) { label={i.label} bgColor={i.bgColor} percentage={getPercentageValue(i.percent)} - count={{ count: i.count, salary: i.salary }} + salary={i.salary} /> ))}
From 3dabb9a68f7854dc20909c57120fcda4e500c6eb Mon Sep 17 00:00:00 2001 From: chaojun Date: Tue, 7 Jul 2026 12:03:18 +0800 Subject: [PATCH 10/23] refactor, #7389 --- .../expenditure/rank/doughnutChart/labels.jsx | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx b/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx index fce80a8590..09cd559e0e 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx @@ -10,22 +10,20 @@ function tooltipContent(salary) { const parts = []; if (new BigNumber(value.usdt || 0).gt(0)) { parts.push( - , +
+ +
, ); } if (new BigNumber(value.hollar || 0).gt(0)) { parts.push( - , +
+ +
, ); } return parts.length > 0 ? parts : null; From de556295e28e3b7abf477b9505fd850ad5860a26 Mon Sep 17 00:00:00 2001 From: chaojun Date: Tue, 7 Jul 2026 12:12:36 +0800 Subject: [PATCH 11/23] fix: should pass context section, #7389 --- .../fellowship/salary/cycles/history/expenditure.jsx | 4 +++- .../fellowship/salary/cycles/history/registerPaid.jsx | 4 +++- .../fellowship/salary/cycles/tabsList/columns/paid.jsx | 4 +++- .../fellowship/salary/cycles/tabsList/columns/payment.jsx | 4 +++- .../salary/cycles/tabsList/columns/yearlySalary.jsx | 4 +++- .../components/fellowship/salary/feeds/events/paid.js | 4 +++- packages/next-common/utils/consts/getSalaryAsset.js | 2 +- 7 files changed, 19 insertions(+), 7 deletions(-) diff --git a/packages/next-common/components/fellowship/salary/cycles/history/expenditure.jsx b/packages/next-common/components/fellowship/salary/cycles/history/expenditure.jsx index fd9c7ba9e8..ef691424f5 100644 --- a/packages/next-common/components/fellowship/salary/cycles/history/expenditure.jsx +++ b/packages/next-common/components/fellowship/salary/cycles/history/expenditure.jsx @@ -4,10 +4,12 @@ import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; import { toPercentage, toPrecision } from "next-common/utils"; import Tooltip from "next-common/components/tooltip"; import bigAdd from "next-common/utils/math/bigAdd"; +import { useCollectivesSection } from "next-common/context/collectives/collectives"; export default function FellowshipSalaryExpenditure({ cycle = {} }) { + const section = useCollectivesSection(); const { symbol, decimals } = getSalaryAsset( - "fellowship", + section, cycle?.indexer?.blockHeight, ); diff --git a/packages/next-common/components/fellowship/salary/cycles/history/registerPaid.jsx b/packages/next-common/components/fellowship/salary/cycles/history/registerPaid.jsx index 7d9206fdd8..ac99f32393 100644 --- a/packages/next-common/components/fellowship/salary/cycles/history/registerPaid.jsx +++ b/packages/next-common/components/fellowship/salary/cycles/history/registerPaid.jsx @@ -2,9 +2,11 @@ import Tooltip from "next-common/components/tooltip"; import ValueDisplay from "next-common/components/valueDisplay"; import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; import { toPrecision } from "next-common/utils"; +import { useCollectivesSection } from "next-common/context/collectives/collectives"; function RegisterPaid({ count, paid, type = "", blockHeight }) { - const { symbol, decimals } = getSalaryAsset("fellowship", blockHeight); + const section = useCollectivesSection(); + const { symbol, decimals } = getSalaryAsset(section, blockHeight); return (
diff --git a/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/paid.jsx b/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/paid.jsx index fd9e6a5e5d..a8999f8456 100644 --- a/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/paid.jsx +++ b/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/paid.jsx @@ -1,15 +1,17 @@ import ValueDisplay from "next-common/components/valueDisplay"; import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; import { toPrecision } from "next-common/utils"; +import { useCollectivesSection } from "next-common/context/collectives/collectives"; export function useFellowshipSalaryCyclePaidColumn() { + const section = useCollectivesSection(); return { name: "Paid", width: 160, className: "text-right", cellRender(data) { const { decimals, symbol } = getSalaryAsset( - "fellowship", + section, data?.paidIndexer?.blockHeight, ); return ( diff --git a/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/payment.jsx b/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/payment.jsx index 717053785e..7a66deaa38 100644 --- a/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/payment.jsx +++ b/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/payment.jsx @@ -4,6 +4,7 @@ import AddressUser from "next-common/components/user/addressUser"; import ValueDisplay from "next-common/components/valueDisplay"; import { cn, toPrecision } from "next-common/utils"; import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; +import { useCollectivesSection } from "next-common/context/collectives/collectives"; const subColumns = [ { @@ -101,8 +102,9 @@ function BeneficiaryValue({ data }) { } function AmountValue({ data }) { + const section = useCollectivesSection(); const { decimals, symbol } = getSalaryAsset( - "fellowship", + section, data?.paidIndexer?.blockHeight, ); diff --git a/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/yearlySalary.jsx b/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/yearlySalary.jsx index e8fc5b9531..ed3d6b8558 100644 --- a/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/yearlySalary.jsx +++ b/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/yearlySalary.jsx @@ -1,14 +1,16 @@ import ValueDisplay from "next-common/components/valueDisplay"; import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; import { toPrecision } from "next-common/utils"; +import { useCollectivesSection } from "next-common/context/collectives/collectives"; export function useFellowshipSalaryCycleYearlySalaryColumn() { + const section = useCollectivesSection(); return { name: "Salary", width: 160, cellRender(data) { const { decimals, symbol } = getSalaryAsset( - "fellowship", + section, data?.paidIndexer?.blockHeight, ); return ( diff --git a/packages/next-common/components/fellowship/salary/feeds/events/paid.js b/packages/next-common/components/fellowship/salary/feeds/events/paid.js index fb76c9ba07..f6501c11e0 100644 --- a/packages/next-common/components/fellowship/salary/feeds/events/paid.js +++ b/packages/next-common/components/fellowship/salary/feeds/events/paid.js @@ -3,14 +3,16 @@ import { FellowshipFeedEventLabel } from "next-common/components/fellowship/feed import ValueDisplay from "next-common/components/valueDisplay"; import { toPrecision } from "next-common/utils"; import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; +import { useCollectivesSection } from "next-common/context/collectives/collectives"; export default function FellowshipSalaryPaidFeed({ feed = {}, showUserInfo = true, }) { + const section = useCollectivesSection(); const { args: { who, amount } = {} } = feed || {}; const { symbol, decimals } = getSalaryAsset( - "fellowship", + section, feed?.indexer?.blockHeight, ); diff --git a/packages/next-common/utils/consts/getSalaryAsset.js b/packages/next-common/utils/consts/getSalaryAsset.js index bcc1755cd1..7fd8bfd09f 100644 --- a/packages/next-common/utils/consts/getSalaryAsset.js +++ b/packages/next-common/utils/consts/getSalaryAsset.js @@ -2,7 +2,7 @@ // Each section has its own independent switch timeline. // Proposal #568: Fellowship switches from USDT(6) to HOLLAR(18) at block 9,247,655. const SWITCH_POINTS = { - fellowship: [{ blockHeight: 9247655, symbol: "HOLLAR", decimals: 18 }], + fellowship: [{ blockHeight: 8815655, symbol: "HOLLAR", decimals: 18 }], ambassador: [], secretary: [], }; From fe18c2ce0c0ac416dffda4d77592767379f563f2 Mon Sep 17 00:00:00 2001 From: chaojun Date: Tue, 7 Jul 2026 12:16:59 +0800 Subject: [PATCH 12/23] fix: should pass context section to getSalaryAsset --- .../components/fellowship/statistics/common.js | 13 ++++++++++--- .../expenditure/cycles/cyclesChart.jsx | 17 +++++++++++------ .../statistics/expenditure/summary/index.jsx | 11 +++++------ 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/packages/next-common/components/fellowship/statistics/common.js b/packages/next-common/components/fellowship/statistics/common.js index e839d26efb..47842ff9c6 100644 --- a/packages/next-common/components/fellowship/statistics/common.js +++ b/packages/next-common/components/fellowship/statistics/common.js @@ -4,6 +4,7 @@ import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; import { toPrecision, formatNum } from "next-common/utils"; import Loading from "next-common/components/loading"; import BigNumber from "bignumber.js"; +import { useCollectivesSection } from "next-common/context/collectives/collectives"; const amountFormat = { decimalSeparator: ".", @@ -83,8 +84,13 @@ export const doughnutChartColors = [ "#E684B8", ]; -export function getAbbreviateBigNumber(count, showSymbol = true, blockHeight) { - const { symbol, decimals } = getSalaryAsset("fellowship", blockHeight); +export function getAbbreviateBigNumber( + count, + showSymbol = true, + blockHeight, + section = "fellowship", +) { + const { symbol, decimals } = getSalaryAsset(section, blockHeight); const precisionCount = toPrecision(count, decimals); return showSymbol ? `${formatNum(precisionCount)} ${symbol}` @@ -93,6 +99,7 @@ export function getAbbreviateBigNumber(count, showSymbol = true, blockHeight) { export function useBarChartOptions(userOptions) { const theme = useTheme(); + const section = useCollectivesSection(); /** * @type {import("react-chartjs-2").ChartProps} */ @@ -147,7 +154,7 @@ export function useBarChartOptions(userOptions) { }, ticks: { callback: function (value) { - return getAbbreviateBigNumber(value, false); + return getAbbreviateBigNumber(value, false, undefined, section); }, font: { size: 12, diff --git a/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx b/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx index 747e929791..295c047b10 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx @@ -4,6 +4,7 @@ import { startCase } from "lodash-es"; import BigNumber from "bignumber.js"; import { getAbbreviateBigNumber } from "next-common/components/fellowship/statistics/common.js"; import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; +import { useCollectivesSection } from "next-common/context/collectives/collectives"; const amountFormat = { decimalSeparator: ".", @@ -11,8 +12,8 @@ const amountFormat = { groupSize: 3, }; -function normalizeCycleAmount(value, cycle) { - const { decimals } = getSalaryAsset("fellowship", cycle.indexer?.blockHeight); +function normalizeCycleAmount(value, cycle, section = "fellowship") { + const { decimals } = getSalaryAsset(section, cycle.indexer?.blockHeight); return new BigNumber(value || 0).shiftedBy(-decimals).toNumber(); } @@ -44,7 +45,7 @@ function getTooltipTitle(item) { return `Cycle ${label}`; } -function getTooltipLabel(item, currentDataset) { +function getTooltipLabel(item, currentDataset, section) { const { dataset, datasetIndex } = item; const { registeredPaidCount, @@ -57,6 +58,7 @@ function getTooltipLabel(item, currentDataset) { new BigNumber(registeredPaid).plus(unRegisteredPaid), true, blockHeight, + section, ); if (datasetIndex === 0) { return [ @@ -65,6 +67,7 @@ function getTooltipLabel(item, currentDataset) { registeredPaid, true, blockHeight, + section, )}`, ]; } @@ -74,6 +77,7 @@ function getTooltipLabel(item, currentDataset) { unRegisteredPaid, true, blockHeight, + section, )}`, `Registered Paid Count: ${registeredPaidCount}`, `Unregistered Paid Count: ${unRegisteredPaidCount}`, @@ -82,6 +86,7 @@ function getTooltipLabel(item, currentDataset) { } export default function CyclesChart({ values }) { + const section = useCollectivesSection(); const height = 180; const categoryPercentage = 0.6; const barPercentage = 1; @@ -93,7 +98,7 @@ export default function CyclesChart({ values }) { barPercentage, label: "Registered Paid", data: values.map((value) => - normalizeCycleAmount(value.registeredPaid, value), + normalizeCycleAmount(value.registeredPaid, value, section), ), backgroundColor: "rgba(230, 0, 122, 1)", tooltip: true, @@ -103,7 +108,7 @@ export default function CyclesChart({ values }) { barPercentage, label: "Unregistered Paid", data: values.map((value) => - normalizeCycleAmount(value.unRegisteredPaid, value), + normalizeCycleAmount(value.unRegisteredPaid, value, section), ), backgroundColor: "rgba(230, 0, 122, 0.4)", tooltip: true, @@ -126,7 +131,7 @@ export default function CyclesChart({ values }) { title: getTooltipTitle, label: (item) => { const currentDataset = values[item.dataIndex]; - return getTooltipLabel(item, currentDataset); + return getTooltipLabel(item, currentDataset, section); }, }, }, diff --git a/packages/next-common/components/fellowship/statistics/expenditure/summary/index.jsx b/packages/next-common/components/fellowship/statistics/expenditure/summary/index.jsx index f02e6dd128..eb316f76e2 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/summary/index.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/summary/index.jsx @@ -5,14 +5,12 @@ import BigNumber from "bignumber.js"; import ValueDisplay from "next-common/components/valueDisplay"; import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; import { useSalaryAsset } from "next-common/hooks/fellowship/salary/useSalaryAsset"; +import { useCollectivesSection } from "next-common/context/collectives/collectives"; -function getTotalSpent(data) { +function getTotalSpent(data, section = "fellowship") { if (data && data.length > 0) { const totalSpent = data.reduce((total, item) => { - const { decimals } = getSalaryAsset( - "fellowship", - item.indexer?.blockHeight, - ); + const { decimals } = getSalaryAsset(section, item.indexer?.blockHeight); const registeredPaid = new BigNumber(item.registeredPaid || 0).div( 10 ** decimals, ); @@ -31,7 +29,8 @@ function SpentCycles({ count }) { } function TotalSpent({ cycles }) { - const totalSpent = getTotalSpent(cycles); + const section = useCollectivesSection(); + const totalSpent = getTotalSpent(cycles, section); const { symbol } = useSalaryAsset(); return ( From f9b269e36c569ceb07ca393a342f5409ac9ab65a Mon Sep 17 00:00:00 2001 From: chaojun Date: Tue, 7 Jul 2026 12:29:19 +0800 Subject: [PATCH 13/23] refactor, #7389 --- .../fellowship/salary/cycles/history/expenditure.jsx | 9 ++------- .../fellowship/salary/cycles/history/registerPaid.jsx | 6 ++---- .../salary/cycles/tabsList/columns/payment.jsx | 9 ++------- .../components/fellowship/salary/feeds/events/paid.js | 9 ++------- .../fellowship/salary/feeds/events/registered.js | 8 ++++---- packages/next-common/utils/consts/getSalaryAsset.js | 10 ++++------ 6 files changed, 16 insertions(+), 35 deletions(-) diff --git a/packages/next-common/components/fellowship/salary/cycles/history/expenditure.jsx b/packages/next-common/components/fellowship/salary/cycles/history/expenditure.jsx index ef691424f5..7f2d303e76 100644 --- a/packages/next-common/components/fellowship/salary/cycles/history/expenditure.jsx +++ b/packages/next-common/components/fellowship/salary/cycles/history/expenditure.jsx @@ -1,17 +1,12 @@ import ValueDisplay from "next-common/components/valueDisplay"; import Progress from "next-common/components/progress"; -import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; import { toPercentage, toPrecision } from "next-common/utils"; import Tooltip from "next-common/components/tooltip"; import bigAdd from "next-common/utils/math/bigAdd"; -import { useCollectivesSection } from "next-common/context/collectives/collectives"; +import { useSalaryAsset } from "next-common/hooks/fellowship/salary/useSalaryAsset"; export default function FellowshipSalaryExpenditure({ cycle = {} }) { - const section = useCollectivesSection(); - const { symbol, decimals } = getSalaryAsset( - section, - cycle?.indexer?.blockHeight, - ); + const { symbol, decimals } = useSalaryAsset(cycle?.indexer?.blockHeight); const { status = {}, registeredPaid, unRegisteredPaid } = cycle || {}; const { budget } = status; diff --git a/packages/next-common/components/fellowship/salary/cycles/history/registerPaid.jsx b/packages/next-common/components/fellowship/salary/cycles/history/registerPaid.jsx index ac99f32393..703d5555ca 100644 --- a/packages/next-common/components/fellowship/salary/cycles/history/registerPaid.jsx +++ b/packages/next-common/components/fellowship/salary/cycles/history/registerPaid.jsx @@ -1,12 +1,10 @@ import Tooltip from "next-common/components/tooltip"; import ValueDisplay from "next-common/components/valueDisplay"; -import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; import { toPrecision } from "next-common/utils"; -import { useCollectivesSection } from "next-common/context/collectives/collectives"; +import { useSalaryAsset } from "next-common/hooks/fellowship/salary/useSalaryAsset"; function RegisterPaid({ count, paid, type = "", blockHeight }) { - const section = useCollectivesSection(); - const { symbol, decimals } = getSalaryAsset(section, blockHeight); + const { symbol, decimals } = useSalaryAsset(blockHeight); return (
diff --git a/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/payment.jsx b/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/payment.jsx index 7a66deaa38..54c2ab99fd 100644 --- a/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/payment.jsx +++ b/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/payment.jsx @@ -3,8 +3,7 @@ import Descriptions from "next-common/components/Descriptions"; import AddressUser from "next-common/components/user/addressUser"; import ValueDisplay from "next-common/components/valueDisplay"; import { cn, toPrecision } from "next-common/utils"; -import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; -import { useCollectivesSection } from "next-common/context/collectives/collectives"; +import { useSalaryAsset } from "next-common/hooks/fellowship/salary/useSalaryAsset"; const subColumns = [ { @@ -102,11 +101,7 @@ function BeneficiaryValue({ data }) { } function AmountValue({ data }) { - const section = useCollectivesSection(); - const { decimals, symbol } = getSalaryAsset( - section, - data?.paidIndexer?.blockHeight, - ); + const { decimals, symbol } = useSalaryAsset(data?.paidIndexer?.blockHeight); return ( diff --git a/packages/next-common/components/fellowship/salary/feeds/events/paid.js b/packages/next-common/components/fellowship/salary/feeds/events/paid.js index f6501c11e0..797d69642c 100644 --- a/packages/next-common/components/fellowship/salary/feeds/events/paid.js +++ b/packages/next-common/components/fellowship/salary/feeds/events/paid.js @@ -2,19 +2,14 @@ import AddressUser from "next-common/components/user/addressUser"; import { FellowshipFeedEventLabel } from "next-common/components/fellowship/feeds/label"; import ValueDisplay from "next-common/components/valueDisplay"; import { toPrecision } from "next-common/utils"; -import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; -import { useCollectivesSection } from "next-common/context/collectives/collectives"; +import { useSalaryAsset } from "next-common/hooks/fellowship/salary/useSalaryAsset"; export default function FellowshipSalaryPaidFeed({ feed = {}, showUserInfo = true, }) { - const section = useCollectivesSection(); const { args: { who, amount } = {} } = feed || {}; - const { symbol, decimals } = getSalaryAsset( - section, - feed?.indexer?.blockHeight, - ); + const { symbol, decimals } = useSalaryAsset(feed?.indexer?.blockHeight); return ( <> diff --git a/packages/next-common/components/fellowship/salary/feeds/events/registered.js b/packages/next-common/components/fellowship/salary/feeds/events/registered.js index 921cf2d13b..8033860c0b 100644 --- a/packages/next-common/components/fellowship/salary/feeds/events/registered.js +++ b/packages/next-common/components/fellowship/salary/feeds/events/registered.js @@ -1,18 +1,18 @@ import AddressUser from "next-common/components/user/addressUser"; import { FellowshipFeedEventLabel } from "next-common/components/fellowship/feeds/label"; -import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; import ValueDisplay from "next-common/components/valueDisplay"; import { toPrecision } from "next-common/utils"; import Link from "next-common/components/link"; -import { useCollectivesContext } from "next-common/context/collectives/collectives"; +import { useCollectivesSection } from "next-common/context/collectives/collectives"; +import { useSalaryAsset } from "next-common/hooks/fellowship/salary/useSalaryAsset"; export function FellowshipRegisteredFeedContent({ amount, index, blockHeight, }) { - const { section } = useCollectivesContext(); - const { symbol, decimals } = getSalaryAsset(section, blockHeight); + const section = useCollectivesSection(); + const { symbol, decimals } = useSalaryAsset(blockHeight); return ( <> diff --git a/packages/next-common/utils/consts/getSalaryAsset.js b/packages/next-common/utils/consts/getSalaryAsset.js index 7fd8bfd09f..453bf27982 100644 --- a/packages/next-common/utils/consts/getSalaryAsset.js +++ b/packages/next-common/utils/consts/getSalaryAsset.js @@ -1,5 +1,8 @@ // Asset switch points per section. // Each section has its own independent switch timeline. + +import { isNil } from "lodash-es"; + // Proposal #568: Fellowship switches from USDT(6) to HOLLAR(18) at block 9,247,655. const SWITCH_POINTS = { fellowship: [{ blockHeight: 8815655, symbol: "HOLLAR", decimals: 18 }], @@ -17,12 +20,7 @@ export function getSalaryAsset(section = "fellowship", blockHeight) { const switches = SWITCH_POINTS[section] || []; const active = [...switches] .reverse() - .find( - (s) => - blockHeight !== undefined && - blockHeight !== null && - blockHeight >= s.blockHeight, - ); + .find((s) => !isNil(blockHeight) && blockHeight >= s.blockHeight); if (active) return { symbol: active.symbol, decimals: active.decimals }; return { symbol: "USDT", decimals: 6 }; } From 48223849d36af8ae41d1186cba1f82832b24588a Mon Sep 17 00:00:00 2001 From: chaojun Date: Tue, 7 Jul 2026 14:23:53 +0800 Subject: [PATCH 14/23] fix: fellowship statistics salary cycles, #7389 --- .../expenditure/cycles/cyclesChart.jsx | 67 +++++++++-------- .../statistics/expenditure/summary/index.jsx | 75 ++++++++++++++----- 2 files changed, 89 insertions(+), 53 deletions(-) diff --git a/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx b/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx index 295c047b10..44c4ba35bf 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx @@ -3,8 +3,7 @@ import BarChart from "./barChart"; import { startCase } from "lodash-es"; import BigNumber from "bignumber.js"; import { getAbbreviateBigNumber } from "next-common/components/fellowship/statistics/common.js"; -import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; -import { useCollectivesSection } from "next-common/context/collectives/collectives"; +import { normalizeSalaryAssetValue } from "next-common/components/collectives/salaryAssetValues"; const amountFormat = { decimalSeparator: ".", @@ -12,9 +11,9 @@ const amountFormat = { groupSize: 3, }; -function normalizeCycleAmount(value, cycle, section = "fellowship") { - const { decimals } = getSalaryAsset(section, cycle.indexer?.blockHeight); - return new BigNumber(value || 0).shiftedBy(-decimals).toNumber(); +function getCycleTotal(value) { + const v = normalizeSalaryAssetValue(value); + return new BigNumber(v.usdt || 0).plus(v.hollar || 0).toNumber(); } function formatAxisAmount(value) { @@ -45,7 +44,7 @@ function getTooltipTitle(item) { return `Cycle ${label}`; } -function getTooltipLabel(item, currentDataset, section) { +function getTooltipLabel(item, currentDataset) { const { dataset, datasetIndex } = item; const { registeredPaidCount, @@ -53,32 +52,39 @@ function getTooltipLabel(item, currentDataset, section) { registeredPaid, unRegisteredPaid, } = currentDataset; - const blockHeight = currentDataset.indexer?.blockHeight; - const totalPaid = getAbbreviateBigNumber( - new BigNumber(registeredPaid).plus(unRegisteredPaid), - true, - blockHeight, - section, + + const registeredTotal = normalizeSalaryAssetValue(registeredPaid); + const unRegisteredTotal = normalizeSalaryAssetValue(unRegisteredPaid); + const totalUsdt = new BigNumber(registeredTotal.usdt || 0).plus( + unRegisteredTotal.usdt || 0, + ); + const totalHollar = new BigNumber(registeredTotal.hollar || 0).plus( + unRegisteredTotal.hollar || 0, ); + const totalPaid = totalUsdt.plus(totalHollar).toNumber(); + + const abbreviatedPaid = (value) => { + if (value >= 1000) { + return getAbbreviateBigNumber(new BigNumber(value), false); + } + return value.toFixed(2); + }; + if (datasetIndex === 0) { + const registeredTotalNum = new BigNumber(registeredTotal.usdt || 0) + .plus(registeredTotal.hollar || 0) + .toNumber(); return [ - `Total: ${totalPaid}`, - `${dataset.label}: ${getAbbreviateBigNumber( - registeredPaid, - true, - blockHeight, - section, - )}`, + `Total: ${abbreviatedPaid(totalPaid)} USD`, + `${dataset.label}: ${abbreviatedPaid(registeredTotalNum)} USD`, ]; } if (datasetIndex === 1) { + const unRegisteredTotalNum = new BigNumber(unRegisteredTotal.usdt || 0) + .plus(unRegisteredTotal.hollar || 0) + .toNumber(); return [ - `${dataset.label}: ${getAbbreviateBigNumber( - unRegisteredPaid, - true, - blockHeight, - section, - )}`, + `${dataset.label}: ${abbreviatedPaid(unRegisteredTotalNum)} USD`, `Registered Paid Count: ${registeredPaidCount}`, `Unregistered Paid Count: ${unRegisteredPaidCount}`, ]; @@ -86,7 +92,6 @@ function getTooltipLabel(item, currentDataset, section) { } export default function CyclesChart({ values }) { - const section = useCollectivesSection(); const height = 180; const categoryPercentage = 0.6; const barPercentage = 1; @@ -97,9 +102,7 @@ export default function CyclesChart({ values }) { categoryPercentage, barPercentage, label: "Registered Paid", - data: values.map((value) => - normalizeCycleAmount(value.registeredPaid, value, section), - ), + data: values.map((value) => getCycleTotal(value.registeredPaid)), backgroundColor: "rgba(230, 0, 122, 1)", tooltip: true, }, @@ -107,9 +110,7 @@ export default function CyclesChart({ values }) { categoryPercentage, barPercentage, label: "Unregistered Paid", - data: values.map((value) => - normalizeCycleAmount(value.unRegisteredPaid, value, section), - ), + data: values.map((value) => getCycleTotal(value.unRegisteredPaid)), backgroundColor: "rgba(230, 0, 122, 0.4)", tooltip: true, }, @@ -131,7 +132,7 @@ export default function CyclesChart({ values }) { title: getTooltipTitle, label: (item) => { const currentDataset = values[item.dataIndex]; - return getTooltipLabel(item, currentDataset, section); + return getTooltipLabel(item, currentDataset); }, }, }, diff --git a/packages/next-common/components/fellowship/statistics/expenditure/summary/index.jsx b/packages/next-common/components/fellowship/statistics/expenditure/summary/index.jsx index eb316f76e2..6190c437f6 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/summary/index.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/summary/index.jsx @@ -3,38 +3,73 @@ import SummaryItem from "next-common/components/summary/layout/item"; import SummaryLayout from "next-common/components/summary/layout/layout"; import BigNumber from "bignumber.js"; import ValueDisplay from "next-common/components/valueDisplay"; -import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; -import { useSalaryAsset } from "next-common/hooks/fellowship/salary/useSalaryAsset"; -import { useCollectivesSection } from "next-common/context/collectives/collectives"; +import Tooltip from "next-common/components/tooltip"; +import { normalizeSalaryAssetValue } from "next-common/components/collectives/salaryAssetValues"; -function getTotalSpent(data, section = "fellowship") { +function getTotalSpent(data) { if (data && data.length > 0) { - const totalSpent = data.reduce((total, item) => { - const { decimals } = getSalaryAsset(section, item.indexer?.blockHeight); - const registeredPaid = new BigNumber(item.registeredPaid || 0).div( - 10 ** decimals, - ); - const unRegisteredPaid = new BigNumber(item.unRegisteredPaid || 0).div( - 10 ** decimals, - ); - return total.plus(registeredPaid).plus(unRegisteredPaid); - }, new BigNumber(0)); - return totalSpent; + let totalUsdt = new BigNumber(0); + let totalHollar = new BigNumber(0); + + data.forEach((item) => { + const registered = normalizeSalaryAssetValue(item.registeredPaid); + const unRegistered = normalizeSalaryAssetValue(item.unRegisteredPaid); + totalUsdt = totalUsdt + .plus(registered.usdt || 0) + .plus(unRegistered.usdt || 0); + totalHollar = totalHollar + .plus(registered.hollar || 0) + .plus(unRegistered.hollar || 0); + }); + + return { + usdt: totalUsdt.toString(), + hollar: totalHollar.toString(), + total: totalUsdt.plus(totalHollar), + }; } - return new BigNumber(0); + return { usdt: "0", hollar: "0", total: new BigNumber(0) }; } function SpentCycles({ count }) { return {count}; } +function tooltipContent(salary) { + const value = normalizeSalaryAssetValue(salary); + const parts = []; + if (new BigNumber(value.usdt || 0).gt(0)) { + parts.push( +
+ +
, + ); + } + if (new BigNumber(value.hollar || 0).gt(0)) { + parts.push( +
+ +
, + ); + } + return parts.length > 0 ? parts : null; +} + function TotalSpent({ cycles }) { - const section = useCollectivesSection(); - const totalSpent = getTotalSpent(cycles, section); - const { symbol } = useSalaryAsset(); + const { total, usdt, hollar } = getTotalSpent(cycles); return ( - + + + ); } From 0d5786e92a3a4e8ea154c383bdb088bb7261472b Mon Sep 17 00:00:00 2001 From: chaojun Date: Tue, 7 Jul 2026 14:27:50 +0800 Subject: [PATCH 15/23] fix, #7389 --- packages/next-common/utils/consts/getSalaryAsset.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/next-common/utils/consts/getSalaryAsset.js b/packages/next-common/utils/consts/getSalaryAsset.js index 453bf27982..a10240680e 100644 --- a/packages/next-common/utils/consts/getSalaryAsset.js +++ b/packages/next-common/utils/consts/getSalaryAsset.js @@ -5,7 +5,7 @@ import { isNil } from "lodash-es"; // Proposal #568: Fellowship switches from USDT(6) to HOLLAR(18) at block 9,247,655. const SWITCH_POINTS = { - fellowship: [{ blockHeight: 8815655, symbol: "HOLLAR", decimals: 18 }], + fellowship: [{ blockHeight: 9247655, symbol: "HOLLAR", decimals: 18 }], ambassador: [], secretary: [], }; From 19498d95821f9c94231a9d158d79b1202108fba7 Mon Sep 17 00:00:00 2001 From: chaojun Date: Tue, 7 Jul 2026 14:55:23 +0800 Subject: [PATCH 16/23] fix, #7389 --- .../fellowship/statistics/expenditure/cycles/cyclesChart.jsx | 4 ++-- .../statistics/expenditure/rank/doughnutChart/labels.jsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx b/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx index 44c4ba35bf..adacbc55e5 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx @@ -2,7 +2,7 @@ import React from "react"; import BarChart from "./barChart"; import { startCase } from "lodash-es"; import BigNumber from "bignumber.js"; -import { getAbbreviateBigNumber } from "next-common/components/fellowship/statistics/common.js"; +import { abbreviateBigNumber } from "next-common/utils"; import { normalizeSalaryAssetValue } from "next-common/components/collectives/salaryAssetValues"; const amountFormat = { @@ -65,7 +65,7 @@ function getTooltipLabel(item, currentDataset) { const abbreviatedPaid = (value) => { if (value >= 1000) { - return getAbbreviateBigNumber(new BigNumber(value), false); + return abbreviateBigNumber(value, 2); } return value.toFixed(2); }; diff --git a/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx b/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx index 09cd559e0e..0a1b77d445 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx @@ -39,11 +39,11 @@ function RowItem({ bgColor, label, percentage, salary }) { {label} - + {percentage}
From c891e1f3b3b378a45cd2aa8b853dfacef9caedf6 Mon Sep 17 00:00:00 2001 From: chaojun Date: Tue, 7 Jul 2026 14:57:32 +0800 Subject: [PATCH 17/23] refactor, #7389 --- .../next-common/components/collectives/members/table.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/next-common/components/collectives/members/table.js b/packages/next-common/components/collectives/members/table.js index b97abe5e7a..d7fae6a256 100644 --- a/packages/next-common/components/collectives/members/table.js +++ b/packages/next-common/components/collectives/members/table.js @@ -13,10 +13,7 @@ import { FellowshipPromotionPeriodWithProgress, } from "next-common/components/collectives/members/periodWithProgress.jsx"; import { useSalaryAsset } from "next-common/hooks/fellowship/salary/useSalaryAsset"; -import { - useCollectivesContext, - useCollectivesSection, -} from "next-common/context/collectives/collectives"; +import { useCollectivesContext } from "next-common/context/collectives/collectives"; import Period from "next-common/components/fellowship/params/period"; export function AddressCol({ address }) { @@ -28,7 +25,7 @@ export default function CollectivesMemberTable({ members = [], isAllLoaded = true, }) { - const { params = {} } = useCollectivesContext(); + const { params = {}, section } = useCollectivesContext(); const { activeSalary = [], passiveSalary = [], @@ -37,7 +34,6 @@ export default function CollectivesMemberTable({ offboardTimeout, } = params ?? {}; const { symbol, decimals } = useSalaryAsset(); - const section = useCollectivesSection(); const isLoading = isNil(members) || !isAllLoaded; From cd802541bc0077b88814a297d92a3f83a8b7ea04 Mon Sep 17 00:00:00 2001 From: chaojun Date: Tue, 7 Jul 2026 15:03:32 +0800 Subject: [PATCH 18/23] simplify, #7389 --- .../expenditure/cycles/cyclesChart.jsx | 30 +------------------ 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx b/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx index adacbc55e5..ff3b5cdf8d 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx @@ -5,39 +5,11 @@ import BigNumber from "bignumber.js"; import { abbreviateBigNumber } from "next-common/utils"; import { normalizeSalaryAssetValue } from "next-common/components/collectives/salaryAssetValues"; -const amountFormat = { - decimalSeparator: ".", - groupSeparator: ",", - groupSize: 3, -}; - function getCycleTotal(value) { const v = normalizeSalaryAssetValue(value); return new BigNumber(v.usdt || 0).plus(v.hollar || 0).toNumber(); } -function formatAxisAmount(value) { - const amount = new BigNumber(value || 0); - const abbreviations = [ - { value: new BigNumber("1000000000000000"), suffix: "Q" }, - { value: new BigNumber("1000000000000"), suffix: "T" }, - { value: new BigNumber("1000000000"), suffix: "B" }, - { value: new BigNumber("1000000"), suffix: "M" }, - { value: new BigNumber("1000"), suffix: "K" }, - ]; - const abbreviation = abbreviations.find((item) => - amount.isGreaterThanOrEqualTo(item.value), - ); - - if (!abbreviation) { - return amount.toFormat(2, amountFormat); - } - - return `${amount.dividedBy(abbreviation.value).toFormat(2, amountFormat)}${ - abbreviation.suffix - }`; -} - function getTooltipTitle(item) { const tooltipItem = item[0]; const { label = "" } = tooltipItem; @@ -140,7 +112,7 @@ export default function CyclesChart({ values }) { scales: { y: { ticks: { - callback: formatAxisAmount, + callback: (value) => abbreviateBigNumber(value, 2), }, }, }, From 3680b3545203a07acb73e2f6f29262b2a79f81f0 Mon Sep 17 00:00:00 2001 From: chaojun Date: Tue, 7 Jul 2026 15:10:11 +0800 Subject: [PATCH 19/23] simplify, #7389 --- .../components/fellowship/statistics/common.js | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/packages/next-common/components/fellowship/statistics/common.js b/packages/next-common/components/fellowship/statistics/common.js index 47842ff9c6..6c20b0ab5a 100644 --- a/packages/next-common/components/fellowship/statistics/common.js +++ b/packages/next-common/components/fellowship/statistics/common.js @@ -1,21 +1,10 @@ import { useTheme } from "styled-components"; import deepmerge from "deepmerge"; import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; -import { toPrecision, formatNum } from "next-common/utils"; +import { toPrecision, formatNum, abbreviateBigNumber } from "next-common/utils"; import Loading from "next-common/components/loading"; -import BigNumber from "bignumber.js"; import { useCollectivesSection } from "next-common/context/collectives/collectives"; -const amountFormat = { - decimalSeparator: ".", - groupSeparator: ",", - groupSize: 3, -}; - -function formatUsdAmount(value) { - return new BigNumber(value || 0).toFormat(2, amountFormat); -} - export const expenditureDoughnutChartOptions = { plugins: { tooltip: { @@ -24,7 +13,10 @@ export const expenditureDoughnutChartOptions = { const name = item.dataset.name[item.dataIndex]; const percentage = item.dataset.percentage[item.dataIndex]; const count = item.dataset.data[item.dataIndex]; - return `${name}: ${formatUsdAmount(count)} USD (${percentage})`; + return `${name}: ${abbreviateBigNumber( + count, + 2, + )} USD (${percentage})`; }, }, }, From 197d371867183443905510294e228fd63ef26317 Mon Sep 17 00:00:00 2001 From: chaojun Date: Tue, 7 Jul 2026 15:15:15 +0800 Subject: [PATCH 20/23] Simplify, #7389 --- .../next-common/components/fellowship/statistics/common.js | 4 +--- .../statistics/expenditure/cycles/cyclesChart.jsx | 7 ------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/packages/next-common/components/fellowship/statistics/common.js b/packages/next-common/components/fellowship/statistics/common.js index 6c20b0ab5a..463a6b6f58 100644 --- a/packages/next-common/components/fellowship/statistics/common.js +++ b/packages/next-common/components/fellowship/statistics/common.js @@ -3,7 +3,6 @@ import deepmerge from "deepmerge"; import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; import { toPrecision, formatNum, abbreviateBigNumber } from "next-common/utils"; import Loading from "next-common/components/loading"; -import { useCollectivesSection } from "next-common/context/collectives/collectives"; export const expenditureDoughnutChartOptions = { plugins: { @@ -91,7 +90,6 @@ export function getAbbreviateBigNumber( export function useBarChartOptions(userOptions) { const theme = useTheme(); - const section = useCollectivesSection(); /** * @type {import("react-chartjs-2").ChartProps} */ @@ -146,7 +144,7 @@ export function useBarChartOptions(userOptions) { }, ticks: { callback: function (value) { - return getAbbreviateBigNumber(value, false, undefined, section); + return abbreviateBigNumber(value, 2); }, font: { size: 12, diff --git a/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx b/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx index ff3b5cdf8d..a6fd198de4 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx @@ -109,13 +109,6 @@ export default function CyclesChart({ values }) { }, }, }, - scales: { - y: { - ticks: { - callback: (value) => abbreviateBigNumber(value, 2), - }, - }, - }, }} /> ); From 5010109ed523797fdb6c7726ff22ea38794f8da0 Mon Sep 17 00:00:00 2001 From: chaojun Date: Tue, 7 Jul 2026 15:18:05 +0800 Subject: [PATCH 21/23] Remove unused function, #7389 --- .../components/fellowship/statistics/common.js | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/packages/next-common/components/fellowship/statistics/common.js b/packages/next-common/components/fellowship/statistics/common.js index 463a6b6f58..146aff1183 100644 --- a/packages/next-common/components/fellowship/statistics/common.js +++ b/packages/next-common/components/fellowship/statistics/common.js @@ -1,7 +1,6 @@ import { useTheme } from "styled-components"; import deepmerge from "deepmerge"; -import { getSalaryAsset } from "next-common/utils/consts/getSalaryAsset"; -import { toPrecision, formatNum, abbreviateBigNumber } from "next-common/utils"; +import { abbreviateBigNumber } from "next-common/utils"; import Loading from "next-common/components/loading"; export const expenditureDoughnutChartOptions = { @@ -75,19 +74,6 @@ export const doughnutChartColors = [ "#E684B8", ]; -export function getAbbreviateBigNumber( - count, - showSymbol = true, - blockHeight, - section = "fellowship", -) { - const { symbol, decimals } = getSalaryAsset(section, blockHeight); - const precisionCount = toPrecision(count, decimals); - return showSymbol - ? `${formatNum(precisionCount)} ${symbol}` - : formatNum(precisionCount); -} - export function useBarChartOptions(userOptions) { const theme = useTheme(); /** From c7002f36323e12886996c4083fcfc4e4990ead3a Mon Sep 17 00:00:00 2001 From: chaojun Date: Wed, 8 Jul 2026 10:18:25 +0800 Subject: [PATCH 22/23] fix, #7389 --- .../fellowship/salary/cycles/tabsList/columns/yearlySalary.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/yearlySalary.jsx b/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/yearlySalary.jsx index ed3d6b8558..9162f20671 100644 --- a/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/yearlySalary.jsx +++ b/packages/next-common/components/fellowship/salary/cycles/tabsList/columns/yearlySalary.jsx @@ -11,7 +11,7 @@ export function useFellowshipSalaryCycleYearlySalaryColumn() { cellRender(data) { const { decimals, symbol } = getSalaryAsset( section, - data?.paidIndexer?.blockHeight, + data?.paidIndexer?.blockHeight ?? data?.indexer?.blockHeight, ); return ( Date: Wed, 8 Jul 2026 10:55:04 +0800 Subject: [PATCH 23/23] Update USD -> $, #7389 --- .../next-common/components/fellowship/statistics/common.js | 5 +---- .../statistics/expenditure/cycles/cyclesChart.jsx | 6 +++--- .../statistics/expenditure/rank/doughnutChart/labels.jsx | 2 +- .../fellowship/statistics/expenditure/summary/index.jsx | 6 +----- 4 files changed, 6 insertions(+), 13 deletions(-) diff --git a/packages/next-common/components/fellowship/statistics/common.js b/packages/next-common/components/fellowship/statistics/common.js index 146aff1183..edae0b2071 100644 --- a/packages/next-common/components/fellowship/statistics/common.js +++ b/packages/next-common/components/fellowship/statistics/common.js @@ -11,10 +11,7 @@ export const expenditureDoughnutChartOptions = { const name = item.dataset.name[item.dataIndex]; const percentage = item.dataset.percentage[item.dataIndex]; const count = item.dataset.data[item.dataIndex]; - return `${name}: ${abbreviateBigNumber( - count, - 2, - )} USD (${percentage})`; + return `${name}: $${abbreviateBigNumber(count, 2)} (${percentage})`; }, }, }, diff --git a/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx b/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx index a6fd198de4..f748416dd3 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/cycles/cyclesChart.jsx @@ -47,8 +47,8 @@ function getTooltipLabel(item, currentDataset) { .plus(registeredTotal.hollar || 0) .toNumber(); return [ - `Total: ${abbreviatedPaid(totalPaid)} USD`, - `${dataset.label}: ${abbreviatedPaid(registeredTotalNum)} USD`, + `Total: $${abbreviatedPaid(totalPaid)}`, + `${dataset.label}: $${abbreviatedPaid(registeredTotalNum)}`, ]; } if (datasetIndex === 1) { @@ -56,7 +56,7 @@ function getTooltipLabel(item, currentDataset) { .plus(unRegisteredTotal.hollar || 0) .toNumber(); return [ - `${dataset.label}: ${abbreviatedPaid(unRegisteredTotalNum)} USD`, + `${dataset.label}: $${abbreviatedPaid(unRegisteredTotalNum)}`, `Registered Paid Count: ${registeredPaidCount}`, `Unregistered Paid Count: ${unRegisteredPaidCount}`, ]; diff --git a/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx b/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx index 0a1b77d445..74cbc28755 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/rank/doughnutChart/labels.jsx @@ -41,7 +41,7 @@ function RowItem({ bgColor, label, percentage, salary }) { content={tooltipContent(salary)} className="text12Medium text-textTertiary" > - + {percentage} diff --git a/packages/next-common/components/fellowship/statistics/expenditure/summary/index.jsx b/packages/next-common/components/fellowship/statistics/expenditure/summary/index.jsx index 6190c437f6..98f820fdb1 100644 --- a/packages/next-common/components/fellowship/statistics/expenditure/summary/index.jsx +++ b/packages/next-common/components/fellowship/statistics/expenditure/summary/index.jsx @@ -64,11 +64,7 @@ function TotalSpent({ cycles }) { return ( - + );