refactor: add useFormatters hook to reduce boilerplate across 14 components
Created useFormatters() combining useWeightUnit + useCurrency + formatWeight/formatPrice into a single hook returning weight(grams) and price(cents) bound functions plus raw unit and currency values. Updated all 14 consumer files to use the new hook, removing the repeated 4-import + 2-hook-call pattern from each. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,4 @@
|
||||
import { useCurrency } from "../hooks/useCurrency";
|
||||
import { useWeightUnit } from "../hooks/useWeightUnit";
|
||||
import { formatPrice, formatWeight } from "../lib/formatters";
|
||||
import { useFormatters } from "../hooks/useFormatters";
|
||||
import { LucideIcon } from "../lib/iconData";
|
||||
import { useUIStore } from "../stores/uiStore";
|
||||
import { RankBadge } from "./CandidateListItem";
|
||||
@@ -41,8 +39,7 @@ export function CandidateCard({
|
||||
cons,
|
||||
rank,
|
||||
}: CandidateCardProps) {
|
||||
const unit = useWeightUnit();
|
||||
const currency = useCurrency();
|
||||
const { weight, price } = useFormatters();
|
||||
const openCandidateEditPanel = useUIStore((s) => s.openCandidateEditPanel);
|
||||
const openConfirmDeleteCandidate = useUIStore(
|
||||
(s) => s.openConfirmDeleteCandidate,
|
||||
@@ -165,12 +162,12 @@ export function CandidateCard({
|
||||
{rank != null && <RankBadge rank={rank} />}
|
||||
{weightGrams != null && (
|
||||
<span className="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-blue-50 text-blue-400">
|
||||
{formatWeight(weightGrams, unit)}
|
||||
{weight(weightGrams)}
|
||||
</span>
|
||||
)}
|
||||
{priceCents != null && (
|
||||
<span className="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-green-50 text-green-500">
|
||||
{formatPrice(priceCents, currency)}
|
||||
{price(priceCents)}
|
||||
</span>
|
||||
)}
|
||||
<span className="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-gray-50 text-gray-600">
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { Reorder, useDragControls } from "framer-motion";
|
||||
import { useCurrency } from "../hooks/useCurrency";
|
||||
import { useWeightUnit } from "../hooks/useWeightUnit";
|
||||
import { formatPrice, formatWeight } from "../lib/formatters";
|
||||
import { useFormatters } from "../hooks/useFormatters";
|
||||
import { LucideIcon } from "../lib/iconData";
|
||||
import { useUIStore } from "../stores/uiStore";
|
||||
import { StatusBadge } from "./StatusBadge";
|
||||
@@ -53,8 +51,7 @@ export function CandidateListItem({
|
||||
onStatusChange,
|
||||
}: CandidateListItemProps) {
|
||||
const controls = useDragControls();
|
||||
const unit = useWeightUnit();
|
||||
const currency = useCurrency();
|
||||
const { weight, price } = useFormatters();
|
||||
const openCandidateEditPanel = useUIStore((s) => s.openCandidateEditPanel);
|
||||
const openConfirmDeleteCandidate = useUIStore(
|
||||
(s) => s.openConfirmDeleteCandidate,
|
||||
@@ -113,12 +110,12 @@ export function CandidateListItem({
|
||||
<div className="flex flex-wrap gap-1.5 mt-1">
|
||||
{candidate.weightGrams != null && (
|
||||
<span className="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-blue-50 text-blue-400">
|
||||
{formatWeight(candidate.weightGrams, unit)}
|
||||
{weight(candidate.weightGrams)}
|
||||
</span>
|
||||
)}
|
||||
{candidate.priceCents != null && (
|
||||
<span className="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-green-50 text-green-500">
|
||||
{formatPrice(candidate.priceCents, currency)}
|
||||
{price(candidate.priceCents)}
|
||||
</span>
|
||||
)}
|
||||
<span className="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-gray-50 text-gray-600">
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { useState } from "react";
|
||||
import { useDeleteCategory, useUpdateCategory } from "../hooks/useCategories";
|
||||
import { useCurrency } from "../hooks/useCurrency";
|
||||
import { useWeightUnit } from "../hooks/useWeightUnit";
|
||||
import { formatPrice, formatWeight } from "../lib/formatters";
|
||||
import { useFormatters } from "../hooks/useFormatters";
|
||||
import { LucideIcon } from "../lib/iconData";
|
||||
import { IconPicker } from "./IconPicker";
|
||||
|
||||
@@ -23,8 +21,7 @@ export function CategoryHeader({
|
||||
totalCost,
|
||||
itemCount,
|
||||
}: CategoryHeaderProps) {
|
||||
const unit = useWeightUnit();
|
||||
const currency = useCurrency();
|
||||
const { weight, price } = useFormatters();
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const [editName, setEditName] = useState(name);
|
||||
const [editIcon, setEditIcon] = useState(icon);
|
||||
@@ -88,8 +85,8 @@ export function CategoryHeader({
|
||||
<LucideIcon name={icon} size={22} className="text-gray-500" />
|
||||
<h2 className="text-lg font-semibold text-gray-900">{name}</h2>
|
||||
<span className="text-sm text-gray-400">
|
||||
{itemCount} {itemCount === 1 ? "item" : "items"} ·{" "}
|
||||
{formatWeight(totalWeight, unit)} · {formatPrice(totalCost, currency)}
|
||||
{itemCount} {itemCount === 1 ? "item" : "items"} · {weight(totalWeight)}{" "}
|
||||
· {price(totalCost)}
|
||||
</span>
|
||||
{!isUncategorized && (
|
||||
<div className="ml-auto flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { useMemo, useState } from "react";
|
||||
import { useCategories } from "../hooks/useCategories";
|
||||
import { useCurrency } from "../hooks/useCurrency";
|
||||
import { useFormatters } from "../hooks/useFormatters";
|
||||
import { useItems } from "../hooks/useItems";
|
||||
import { useTotals } from "../hooks/useTotals";
|
||||
import { useWeightUnit } from "../hooks/useWeightUnit";
|
||||
import { formatPrice, formatWeight } from "../lib/formatters";
|
||||
import { LucideIcon } from "../lib/iconData";
|
||||
import { useUIStore } from "../stores/uiStore";
|
||||
import { CategoryFilterDropdown } from "./CategoryFilterDropdown";
|
||||
@@ -15,8 +13,7 @@ export function CollectionView() {
|
||||
const { data: items, isLoading: itemsLoading } = useItems();
|
||||
const { data: totals } = useTotals();
|
||||
const { data: categories } = useCategories();
|
||||
const unit = useWeightUnit();
|
||||
const currency = useCurrency();
|
||||
const { weight, price } = useFormatters();
|
||||
const openAddPanel = useUIStore((s) => s.openAddPanel);
|
||||
|
||||
const [searchText, setSearchText] = useState("");
|
||||
@@ -148,7 +145,7 @@ export function CollectionView() {
|
||||
<LucideIcon name="weight" size={14} className="text-gray-400" />
|
||||
<span className="text-xs text-gray-500">Total Weight</span>
|
||||
<span className="text-sm font-semibold text-gray-900">
|
||||
{formatWeight(totals.global.totalWeight, unit)}
|
||||
{weight(totals.global.totalWeight)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-1">
|
||||
@@ -159,7 +156,7 @@ export function CollectionView() {
|
||||
/>
|
||||
<span className="text-xs text-gray-500">Total Spent</span>
|
||||
<span className="text-sm font-semibold text-gray-900">
|
||||
{formatPrice(totals.global.totalCost, currency)}
|
||||
{price(totals.global.totalCost)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { useMemo } from "react";
|
||||
import { useCurrency } from "../hooks/useCurrency";
|
||||
import { useWeightUnit } from "../hooks/useWeightUnit";
|
||||
import { formatPrice, formatWeight } from "../lib/formatters";
|
||||
import { useFormatters } from "../hooks/useFormatters";
|
||||
import { LucideIcon } from "../lib/iconData";
|
||||
import { useUIStore } from "../stores/uiStore";
|
||||
import { RankBadge } from "./CandidateListItem";
|
||||
@@ -40,8 +38,7 @@ export function ComparisonTable({
|
||||
candidates,
|
||||
resolvedCandidateId,
|
||||
}: ComparisonTableProps) {
|
||||
const unit = useWeightUnit();
|
||||
const currency = useCurrency();
|
||||
const { weight, price } = useFormatters();
|
||||
const openExternalLink = useUIStore((s) => s.openExternalLink);
|
||||
|
||||
const { bestWeightId, bestPriceId, weightDeltas, priceDeltas } =
|
||||
@@ -62,8 +59,7 @@ export function ComparisonTable({
|
||||
weightDeltas[c.id] = null;
|
||||
} else {
|
||||
const delta = c.weightGrams - minWeight;
|
||||
weightDeltas[c.id] =
|
||||
delta === 0 ? null : `+${formatWeight(delta, unit)}`;
|
||||
weightDeltas[c.id] = delta === 0 ? null : `+${weight(delta)}`;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -88,8 +84,7 @@ export function ComparisonTable({
|
||||
priceDeltas[c.id] = null;
|
||||
} else {
|
||||
const delta = c.priceCents - minPrice;
|
||||
priceDeltas[c.id] =
|
||||
delta === 0 ? null : `+${formatPrice(delta, currency)}`;
|
||||
priceDeltas[c.id] = delta === 0 ? null : `+${price(delta)}`;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -99,7 +94,7 @@ export function ComparisonTable({
|
||||
}
|
||||
|
||||
return { bestWeightId, bestPriceId, weightDeltas, priceDeltas };
|
||||
}, [candidates, unit, currency]);
|
||||
}, [candidates, weight, price]);
|
||||
|
||||
const ATTRIBUTE_ROWS: Array<{
|
||||
key: string;
|
||||
@@ -155,7 +150,7 @@ export function ComparisonTable({
|
||||
return (
|
||||
<div>
|
||||
<span className="font-medium text-gray-900">
|
||||
{formatWeight(c.weightGrams, unit)}
|
||||
{weight(c.weightGrams)}
|
||||
</span>
|
||||
{!isBest && delta && (
|
||||
<div className="text-xs text-gray-400">{delta}</div>
|
||||
@@ -181,7 +176,7 @@ export function ComparisonTable({
|
||||
return (
|
||||
<div>
|
||||
<span className="font-medium text-gray-900">
|
||||
{formatPrice(c.priceCents, currency)}
|
||||
{price(c.priceCents)}
|
||||
</span>
|
||||
{!isBest && delta && (
|
||||
<div className="text-xs text-gray-400">{delta}</div>
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { useCurrency } from "../hooks/useCurrency";
|
||||
import { useWeightUnit } from "../hooks/useWeightUnit";
|
||||
import { formatPrice, formatWeight } from "../lib/formatters";
|
||||
import { useFormatters } from "../hooks/useFormatters";
|
||||
import { LucideIcon } from "../lib/iconData";
|
||||
import { useUIStore } from "../stores/uiStore";
|
||||
import { ClassificationBadge } from "./ClassificationBadge";
|
||||
@@ -32,8 +30,7 @@ export function ItemCard({
|
||||
classification,
|
||||
onClassificationCycle,
|
||||
}: ItemCardProps) {
|
||||
const unit = useWeightUnit();
|
||||
const currency = useCurrency();
|
||||
const { weight, price } = useFormatters();
|
||||
const openEditPanel = useUIStore((s) => s.openEditPanel);
|
||||
const openExternalLink = useUIStore((s) => s.openExternalLink);
|
||||
|
||||
@@ -131,12 +128,12 @@ export function ItemCard({
|
||||
<div className="flex flex-wrap gap-1.5">
|
||||
{weightGrams != null && (
|
||||
<span className="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-blue-50 text-blue-400">
|
||||
{formatWeight(weightGrams, unit)}
|
||||
{weight(weightGrams)}
|
||||
</span>
|
||||
)}
|
||||
{priceCents != null && (
|
||||
<span className="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-green-50 text-green-500">
|
||||
{formatPrice(priceCents, currency)}
|
||||
{price(priceCents)}
|
||||
</span>
|
||||
)}
|
||||
<span className="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-gray-50 text-gray-600">
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useCurrency } from "../hooks/useCurrency";
|
||||
import { useFormatters } from "../hooks/useFormatters";
|
||||
import { useItems } from "../hooks/useItems";
|
||||
import { useSyncSetupItems } from "../hooks/useSetups";
|
||||
import { useWeightUnit } from "../hooks/useWeightUnit";
|
||||
import { formatPrice, formatWeight } from "../lib/formatters";
|
||||
import { LucideIcon } from "../lib/iconData";
|
||||
import { SlideOutPanel } from "./SlideOutPanel";
|
||||
|
||||
@@ -22,8 +20,7 @@ export function ItemPicker({
|
||||
}: ItemPickerProps) {
|
||||
const { data: items } = useItems();
|
||||
const syncItems = useSyncSetupItems(setupId);
|
||||
const unit = useWeightUnit();
|
||||
const currency = useCurrency();
|
||||
const { weight, price } = useFormatters();
|
||||
const [selectedIds, setSelectedIds] = useState<Set<number>>(new Set());
|
||||
|
||||
// Reset selected IDs when panel opens
|
||||
@@ -117,13 +114,11 @@ export function ItemPicker({
|
||||
{item.name}
|
||||
</span>
|
||||
<span className="text-xs text-gray-400 shrink-0">
|
||||
{item.weightGrams != null &&
|
||||
formatWeight(item.weightGrams, unit)}
|
||||
{item.weightGrams != null && weight(item.weightGrams)}
|
||||
{item.weightGrams != null &&
|
||||
item.priceCents != null &&
|
||||
" · "}
|
||||
{item.priceCents != null &&
|
||||
formatPrice(item.priceCents, currency)}
|
||||
{item.priceCents != null && price(item.priceCents)}
|
||||
</span>
|
||||
</label>
|
||||
))}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { Link } from "@tanstack/react-router";
|
||||
import { useCurrency } from "../hooks/useCurrency";
|
||||
import { useWeightUnit } from "../hooks/useWeightUnit";
|
||||
import { formatPrice, formatWeight } from "../lib/formatters";
|
||||
import { useFormatters } from "../hooks/useFormatters";
|
||||
|
||||
interface SetupCardProps {
|
||||
id: number;
|
||||
@@ -18,8 +16,7 @@ export function SetupCard({
|
||||
totalWeight,
|
||||
totalCost,
|
||||
}: SetupCardProps) {
|
||||
const unit = useWeightUnit();
|
||||
const currency = useCurrency();
|
||||
const { weight, price } = useFormatters();
|
||||
return (
|
||||
<Link
|
||||
to="/setups/$setupId"
|
||||
@@ -34,10 +31,10 @@ export function SetupCard({
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-1.5">
|
||||
<span className="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-blue-50 text-blue-400">
|
||||
{formatWeight(totalWeight, unit)}
|
||||
{weight(totalWeight)}
|
||||
</span>
|
||||
<span className="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-green-50 text-green-500">
|
||||
{formatPrice(totalCost, currency)}
|
||||
{price(totalCost)}
|
||||
</span>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useNavigate } from "@tanstack/react-router";
|
||||
import { useCurrency } from "../hooks/useCurrency";
|
||||
import { formatPrice } from "../lib/formatters";
|
||||
import { useFormatters } from "../hooks/useFormatters";
|
||||
import { LucideIcon } from "../lib/iconData";
|
||||
|
||||
interface ThreadCardProps {
|
||||
@@ -20,16 +19,6 @@ function formatDate(iso: string): string {
|
||||
return d.toLocaleDateString("en-US", { month: "short", day: "numeric" });
|
||||
}
|
||||
|
||||
function formatPriceRange(
|
||||
min: number | null,
|
||||
max: number | null,
|
||||
currency: Parameters<typeof formatPrice>[1],
|
||||
): string | null {
|
||||
if (min == null && max == null) return null;
|
||||
if (min === max) return formatPrice(min, currency);
|
||||
return `${formatPrice(min, currency)} - ${formatPrice(max, currency)}`;
|
||||
}
|
||||
|
||||
export function ThreadCard({
|
||||
id,
|
||||
name,
|
||||
@@ -42,10 +31,19 @@ export function ThreadCard({
|
||||
categoryIcon,
|
||||
}: ThreadCardProps) {
|
||||
const navigate = useNavigate();
|
||||
const currency = useCurrency();
|
||||
const { price } = useFormatters();
|
||||
|
||||
function formatPriceRange(
|
||||
min: number | null,
|
||||
max: number | null,
|
||||
): string | null {
|
||||
if (min == null && max == null) return null;
|
||||
if (min === max) return price(min);
|
||||
return `${price(min)} - ${price(max)}`;
|
||||
}
|
||||
|
||||
const isResolved = status === "resolved";
|
||||
const priceRange = formatPriceRange(minPriceCents, maxPriceCents, currency);
|
||||
const priceRange = formatPriceRange(minPriceCents, maxPriceCents);
|
||||
|
||||
return (
|
||||
<button
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Link } from "@tanstack/react-router";
|
||||
import { useAuth, useLogout } from "../hooks/useAuth";
|
||||
import { useFormatters } from "../hooks/useFormatters";
|
||||
import { useUpdateSetting } from "../hooks/useSettings";
|
||||
import { useTotals } from "../hooks/useTotals";
|
||||
import { useWeightUnit } from "../hooks/useWeightUnit";
|
||||
import { formatPrice, formatWeight, type WeightUnit } from "../lib/formatters";
|
||||
import type { WeightUnit } from "../lib/formatters";
|
||||
import { LucideIcon } from "../lib/iconData";
|
||||
|
||||
const UNITS: WeightUnit[] = ["g", "oz", "lb", "kg"];
|
||||
@@ -23,7 +23,7 @@ export function TotalsBar({
|
||||
const { data: auth } = useAuth();
|
||||
const logout = useLogout();
|
||||
const isAuthenticated = !!auth?.user;
|
||||
const unit = useWeightUnit();
|
||||
const { weight, price, unit } = useFormatters();
|
||||
const updateSetting = useUpdateSetting();
|
||||
|
||||
// When no stats provided, use global totals (backward compatible)
|
||||
@@ -34,14 +34,14 @@ export function TotalsBar({
|
||||
{ label: "items", value: String(data.global.itemCount) },
|
||||
{
|
||||
label: "total",
|
||||
value: formatWeight(data.global.totalWeight, unit),
|
||||
value: weight(data.global.totalWeight),
|
||||
},
|
||||
{ label: "spent", value: formatPrice(data.global.totalCost) },
|
||||
{ label: "spent", value: price(data.global.totalCost) },
|
||||
]
|
||||
: [
|
||||
{ label: "items", value: "0" },
|
||||
{ label: "total", value: formatWeight(null, unit) },
|
||||
{ label: "spent", value: formatPrice(null) },
|
||||
{ label: "total", value: weight(null) },
|
||||
{ label: "spent", value: price(null) },
|
||||
]);
|
||||
|
||||
const titleContent = (
|
||||
|
||||
@@ -7,8 +7,8 @@ import {
|
||||
ResponsiveContainer,
|
||||
Tooltip,
|
||||
} from "recharts";
|
||||
import { useFormatters } from "../hooks/useFormatters";
|
||||
import type { SetupItemWithCategory } from "../hooks/useSetups";
|
||||
import { useWeightUnit } from "../hooks/useWeightUnit";
|
||||
import { formatWeight, type WeightUnit } from "../lib/formatters";
|
||||
import { LucideIcon } from "../lib/iconData";
|
||||
|
||||
@@ -143,7 +143,7 @@ function LegendRow({
|
||||
}
|
||||
|
||||
export function WeightSummaryCard({ items }: WeightSummaryCardProps) {
|
||||
const unit = useWeightUnit();
|
||||
const { unit } = useFormatters();
|
||||
const [viewMode, setViewMode] = useState<ViewMode>("category");
|
||||
|
||||
const baseWeight = items.reduce(
|
||||
|
||||
14
src/client/hooks/useFormatters.ts
Normal file
14
src/client/hooks/useFormatters.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { formatPrice, formatWeight } from "../lib/formatters";
|
||||
import { useCurrency } from "./useCurrency";
|
||||
import { useWeightUnit } from "./useWeightUnit";
|
||||
|
||||
export function useFormatters() {
|
||||
const unit = useWeightUnit();
|
||||
const currency = useCurrency();
|
||||
return {
|
||||
weight: (grams: number | null) => formatWeight(grams, unit),
|
||||
price: (cents: number | null) => formatPrice(cents, currency),
|
||||
unit,
|
||||
currency,
|
||||
};
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
import { DashboardCard } from "../components/DashboardCard";
|
||||
import { useCurrency } from "../hooks/useCurrency";
|
||||
import { useFormatters } from "../hooks/useFormatters";
|
||||
import { useSetups } from "../hooks/useSetups";
|
||||
import { useThreads } from "../hooks/useThreads";
|
||||
import { useTotals } from "../hooks/useTotals";
|
||||
import { useWeightUnit } from "../hooks/useWeightUnit";
|
||||
import { formatPrice, formatWeight } from "../lib/formatters";
|
||||
|
||||
export const Route = createFileRoute("/")({
|
||||
component: DashboardPage,
|
||||
@@ -15,8 +13,7 @@ function DashboardPage() {
|
||||
const { data: totals } = useTotals();
|
||||
const { data: threads } = useThreads(false);
|
||||
const { data: setups } = useSetups();
|
||||
const unit = useWeightUnit();
|
||||
const currency = useCurrency();
|
||||
const { weight, price } = useFormatters();
|
||||
|
||||
const global = totals?.global;
|
||||
const activeThreadCount = threads?.length ?? 0;
|
||||
@@ -33,11 +30,11 @@ function DashboardPage() {
|
||||
{ label: "Items", value: String(global?.itemCount ?? 0) },
|
||||
{
|
||||
label: "Weight",
|
||||
value: formatWeight(global?.totalWeight ?? null, unit),
|
||||
value: weight(global?.totalWeight ?? null),
|
||||
},
|
||||
{
|
||||
label: "Cost",
|
||||
value: formatPrice(global?.totalCost ?? null, currency),
|
||||
value: price(global?.totalCost ?? null),
|
||||
},
|
||||
]}
|
||||
emptyText="Get started"
|
||||
|
||||
@@ -4,15 +4,13 @@ import { CategoryHeader } from "../../components/CategoryHeader";
|
||||
import { ItemCard } from "../../components/ItemCard";
|
||||
import { ItemPicker } from "../../components/ItemPicker";
|
||||
import { WeightSummaryCard } from "../../components/WeightSummaryCard";
|
||||
import { useCurrency } from "../../hooks/useCurrency";
|
||||
import { useFormatters } from "../../hooks/useFormatters";
|
||||
import {
|
||||
useDeleteSetup,
|
||||
useRemoveSetupItem,
|
||||
useSetup,
|
||||
useUpdateItemClassification,
|
||||
} from "../../hooks/useSetups";
|
||||
import { useWeightUnit } from "../../hooks/useWeightUnit";
|
||||
import { formatPrice, formatWeight } from "../../lib/formatters";
|
||||
import { LucideIcon } from "../../lib/iconData";
|
||||
|
||||
export const Route = createFileRoute("/setups/$setupId")({
|
||||
@@ -21,8 +19,7 @@ export const Route = createFileRoute("/setups/$setupId")({
|
||||
|
||||
function SetupDetailPage() {
|
||||
const { setupId } = Route.useParams();
|
||||
const unit = useWeightUnit();
|
||||
const currency = useCurrency();
|
||||
const { weight, price } = useFormatters();
|
||||
const navigate = useNavigate();
|
||||
const numericId = Number(setupId);
|
||||
const { data: setup, isLoading } = useSetup(numericId);
|
||||
@@ -127,13 +124,13 @@ function SetupDetailPage() {
|
||||
</span>
|
||||
<span>
|
||||
<span className="font-medium text-gray-700">
|
||||
{formatWeight(totalWeight, unit)}
|
||||
{weight(totalWeight)}
|
||||
</span>{" "}
|
||||
total
|
||||
</span>
|
||||
<span>
|
||||
<span className="font-medium text-gray-700">
|
||||
{formatPrice(totalCost, currency)}
|
||||
{price(totalCost)}
|
||||
</span>{" "}
|
||||
cost
|
||||
</span>
|
||||
|
||||
Reference in New Issue
Block a user