From 4eaacb5741084d811a9c023368104cc0a9e5a7d5 Mon Sep 17 00:00:00 2001 From: darthmaim Date: Mon, 6 Jan 2025 13:04:49 +0100 Subject: [PATCH] Highlight cheapest homestead material --- .../[language]/homestead/materials/page.tsx | 63 ++++++++++++------- apps/web/components/ItemTable/columns.tsx | 2 +- 2 files changed, 43 insertions(+), 22 deletions(-) diff --git a/apps/web/app/[language]/homestead/materials/page.tsx b/apps/web/app/[language]/homestead/materials/page.tsx index 2de5a1ee0..f7ab7cf86 100644 --- a/apps/web/app/[language]/homestead/materials/page.tsx +++ b/apps/web/app/[language]/homestead/materials/page.tsx @@ -1,6 +1,6 @@ import { Trans } from '@/components/I18n/Trans'; import { ItemLink } from '@/components/Item/ItemLink'; -import { globalColumnRenderer as itemTableColumn } from '@/components/ItemTable/columns'; +import { globalColumnRenderer as itemTableColumn, renderPriceWithOptionalWarning } from '@/components/ItemTable/columns'; import { Description } from '@/components/Layout/Description'; import { PageView } from '@/components/PageView/PageView'; import { ColumnSelect } from '@/components/Table/ColumnSelect'; @@ -26,6 +26,7 @@ import { Tip } from '@gw2treasures/ui/components/Tip/Tip'; import { Coins } from '@/components/Format/Coins'; import { Fraction } from '@/components/Format/Fraction'; import { ResetTimer } from '@/components/Reset/ResetTimer'; +import { Badge } from '@/components/Badge/Badge'; const getItems = cache( async (ids: number[]) => { @@ -117,6 +118,21 @@ interface RefinedMaterialProps { const RefinedMaterial: FC = ({ id, material, efficiencies, sources }) => { const Sources = createDataTable(sources, ({ id }) => id); + let cheapestBuy: number | undefined = undefined; + let cheapestSell: number | undefined = undefined; + + for(const source of sources) { + const buy = getCostPerUnit(source.item?.buyPrice, source.rate); + const sell = getCostPerUnit(source.item?.sellPrice, source.rate); + + if(buy && (cheapestBuy === undefined || cheapestBuy > buy)) { + cheapestBuy = buy; + } + if(sell && (cheapestSell === undefined || cheapestSell > sell)) { + cheapestSell = sell; + } + } + return ( <> , ]}> @@ -154,16 +170,7 @@ const RefinedMaterial: FC = ({ id, material, efficiencies, sortBy={({ item, rate }) => getCostPerUnit(item?.buyPrice, rate)} align="right" > - {({ item, rate }) => item && item.buyPrice && ( - × Price = × ()} preferredPlacement="top-end"> - - {itemTableColumn.buyPrice({ - ...item, - buyPrice: getCostPerUnit(item.buyPrice, rate) - }, {})} - - - )} + {({ item, rate }) => renderCostPerUnit(item, rate, item?.buyPrice, cheapestBuy)} } sortBy={({ item }) => item?.sellPrice} align="right" hidden> {({ item }) => item && itemTableColumn.sellPrice(item, {})} @@ -180,16 +187,7 @@ const RefinedMaterial: FC = ({ id, material, efficiencies, sortBy={({ item, rate }) => getCostPerUnit(item?.sellPrice, rate)} align="right" > - {({ item, rate }) => item && item.sellPrice && ( - × Price = × ()} preferredPlacement="top-end"> - - {itemTableColumn.sellPrice({ - ...item, - sellPrice: getCostPerUnit(item.sellPrice, rate) - }, {})} - - - )} + {({ item, rate }) => renderCostPerUnit(item, rate, item?.sellPrice, cheapestSell)} @@ -200,6 +198,29 @@ const getCostPerUnit = (price: number | null | undefined, rate: ConversionRate) ? Math.round(price * rate.required / rate.produced) : null; +function renderCostPerUnit(item: DbItem | undefined, rate: ConversionRate, itemPrice: number | undefined | null, cheapestPrice: number | undefined) { + if(!item || !itemPrice) { + return ( + + - + + ); + } + + const costPerUnit = getCostPerUnit(itemPrice, rate); + const isCheapest = costPerUnit === cheapestPrice; + + return ( + × Price = × ()} preferredPlacement="top-end"> + + {isCheapest && Cheapest} + + {renderPriceWithOptionalWarning(item.tpCheckedAt, costPerUnit)} + + + + ); +} interface EfficiencySwitchProps { id: Material, diff --git a/apps/web/components/ItemTable/columns.tsx b/apps/web/components/ItemTable/columns.tsx index c6f05d642..1f90a4547 100644 --- a/apps/web/components/ItemTable/columns.tsx +++ b/apps/web/components/ItemTable/columns.tsx @@ -167,7 +167,7 @@ export const globalColumnRenderer: Renderer = { sellQuantity: (item) => !item.tpTradeable ? empty() : , }; -function renderPriceWithOptionalWarning(date: Date | string | null, price: number | null): ReactNode { +export function renderPriceWithOptionalWarning(date: Date | string | null, price: number | null): ReactNode { if(!price) { return empty(); }