diff --git a/src/client/components/CandidateCard.tsx b/src/client/components/CandidateCard.tsx
index 86df439..f994e1b 100644
--- a/src/client/components/CandidateCard.tsx
+++ b/src/client/components/CandidateCard.tsx
@@ -1,3 +1,4 @@
+import { useWeightUnit } from "../hooks/useWeightUnit";
import { formatPrice, formatWeight } from "../lib/formatters";
import { LucideIcon } from "../lib/iconData";
import { useUIStore } from "../stores/uiStore";
@@ -27,6 +28,7 @@ export function CandidateCard({
threadId,
isActive,
}: CandidateCardProps) {
+ const unit = useWeightUnit();
const openCandidateEditPanel = useUIStore((s) => s.openCandidateEditPanel);
const openConfirmDeleteCandidate = useUIStore(
(s) => s.openConfirmDeleteCandidate,
@@ -88,7 +90,7 @@ export function CandidateCard({
{weightGrams != null && (
- {formatWeight(weightGrams)}
+ {formatWeight(weightGrams, unit)}
)}
{priceCents != null && (
diff --git a/src/client/components/CategoryHeader.tsx b/src/client/components/CategoryHeader.tsx
index c24731a..33ee346 100644
--- a/src/client/components/CategoryHeader.tsx
+++ b/src/client/components/CategoryHeader.tsx
@@ -1,5 +1,6 @@
import { useState } from "react";
import { useDeleteCategory, useUpdateCategory } from "../hooks/useCategories";
+import { useWeightUnit } from "../hooks/useWeightUnit";
import { formatPrice, formatWeight } from "../lib/formatters";
import { LucideIcon } from "../lib/iconData";
import { IconPicker } from "./IconPicker";
@@ -21,6 +22,7 @@ export function CategoryHeader({
totalCost,
itemCount,
}: CategoryHeaderProps) {
+ const unit = useWeightUnit();
const [isEditing, setIsEditing] = useState(false);
const [editName, setEditName] = useState(name);
const [editIcon, setEditIcon] = useState(icon);
@@ -85,7 +87,7 @@ export function CategoryHeader({
{name}
{itemCount} {itemCount === 1 ? "item" : "items"} ·{" "}
- {formatWeight(totalWeight)} · {formatPrice(totalCost)}
+ {formatWeight(totalWeight, unit)} · {formatPrice(totalCost)}
{!isUncategorized && (
diff --git a/src/client/components/ItemCard.tsx b/src/client/components/ItemCard.tsx
index e5fc5c4..d11bd02 100644
--- a/src/client/components/ItemCard.tsx
+++ b/src/client/components/ItemCard.tsx
@@ -1,3 +1,4 @@
+import { useWeightUnit } from "../hooks/useWeightUnit";
import { formatPrice, formatWeight } from "../lib/formatters";
import { LucideIcon } from "../lib/iconData";
import { useUIStore } from "../stores/uiStore";
@@ -25,6 +26,7 @@ export function ItemCard({
productUrl,
onRemove,
}: ItemCardProps) {
+ const unit = useWeightUnit();
const openEditPanel = useUIStore((s) => s.openEditPanel);
const openExternalLink = useUIStore((s) => s.openExternalLink);
@@ -122,7 +124,7 @@ export function ItemCard({
{weightGrams != null && (
- {formatWeight(weightGrams)}
+ {formatWeight(weightGrams, unit)}
)}
{priceCents != null && (
diff --git a/src/client/components/ItemPicker.tsx b/src/client/components/ItemPicker.tsx
index af2b16a..d1b4267 100644
--- a/src/client/components/ItemPicker.tsx
+++ b/src/client/components/ItemPicker.tsx
@@ -1,6 +1,7 @@
import { useEffect, useState } from "react";
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";
@@ -20,6 +21,7 @@ export function ItemPicker({
}: ItemPickerProps) {
const { data: items } = useItems();
const syncItems = useSyncSetupItems(setupId);
+ const unit = useWeightUnit();
const [selectedIds, setSelectedIds] = useState
>(new Set());
// Reset selected IDs when panel opens
@@ -114,7 +116,7 @@ export function ItemPicker({
{item.weightGrams != null &&
- formatWeight(item.weightGrams)}
+ formatWeight(item.weightGrams, unit)}
{item.weightGrams != null &&
item.priceCents != null &&
" · "}
diff --git a/src/client/components/SetupCard.tsx b/src/client/components/SetupCard.tsx
index 68cd6a6..8dd87da 100644
--- a/src/client/components/SetupCard.tsx
+++ b/src/client/components/SetupCard.tsx
@@ -1,4 +1,5 @@
import { Link } from "@tanstack/react-router";
+import { useWeightUnit } from "../hooks/useWeightUnit";
import { formatPrice, formatWeight } from "../lib/formatters";
interface SetupCardProps {
@@ -16,6 +17,7 @@ export function SetupCard({
totalWeight,
totalCost,
}: SetupCardProps) {
+ const unit = useWeightUnit();
return (
- {formatWeight(totalWeight)}
+ {formatWeight(totalWeight, unit)}
{formatPrice(totalCost)}
diff --git a/src/client/components/TotalsBar.tsx b/src/client/components/TotalsBar.tsx
index f7a126c..b6fa5a9 100644
--- a/src/client/components/TotalsBar.tsx
+++ b/src/client/components/TotalsBar.tsx
@@ -1,8 +1,12 @@
import { Link } from "@tanstack/react-router";
+import { useUpdateSetting } from "../hooks/useSettings";
import { useTotals } from "../hooks/useTotals";
-import { formatPrice, formatWeight } from "../lib/formatters";
+import { useWeightUnit } from "../hooks/useWeightUnit";
+import { formatPrice, formatWeight, type WeightUnit } from "../lib/formatters";
import { LucideIcon } from "../lib/iconData";
+const UNITS: WeightUnit[] = ["g", "oz", "lb", "kg"];
+
interface TotalsBarProps {
title?: string;
stats?: Array<{ label: string; value: string }>;
@@ -15,6 +19,8 @@ export function TotalsBar({
linkTo,
}: TotalsBarProps) {
const { data } = useTotals();
+ const unit = useWeightUnit();
+ const updateSetting = useUpdateSetting();
// When no stats provided, use global totals (backward compatible)
const displayStats =
@@ -22,12 +28,15 @@ export function TotalsBar({
(data?.global
? [
{ label: "items", value: String(data.global.itemCount) },
- { label: "total", value: formatWeight(data.global.totalWeight) },
+ {
+ label: "total",
+ value: formatWeight(data.global.totalWeight, unit),
+ },
{ label: "spent", value: formatPrice(data.global.totalCost) },
]
: [
{ label: "items", value: "0" },
- { label: "total", value: formatWeight(null) },
+ { label: "total", value: formatWeight(null, unit) },
{ label: "spent", value: formatPrice(null) },
]);
@@ -57,18 +66,41 @@ export function TotalsBar({
{titleElement}
- {showStats && (
-
- {displayStats.map((stat) => (
-
-
- {stat.value}
- {" "}
- {stat.label}
-
+
+
+ {UNITS.map((u) => (
+
))}
- )}
+ {showStats && (
+
+ {displayStats.map((stat) => (
+
+
+ {stat.value}
+ {" "}
+ {stat.label}
+
+ ))}
+
+ )}
+
diff --git a/src/client/routes/index.tsx b/src/client/routes/index.tsx
index f3ee600..ef70f9d 100644
--- a/src/client/routes/index.tsx
+++ b/src/client/routes/index.tsx
@@ -3,6 +3,7 @@ import { DashboardCard } from "../components/DashboardCard";
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("/")({
@@ -13,6 +14,7 @@ function DashboardPage() {
const { data: totals } = useTotals();
const { data: threads } = useThreads(false);
const { data: setups } = useSetups();
+ const unit = useWeightUnit();
const global = totals?.global;
const activeThreadCount = threads?.length ?? 0;
@@ -29,7 +31,7 @@ function DashboardPage() {
{ label: "Items", value: String(global?.itemCount ?? 0) },
{
label: "Weight",
- value: formatWeight(global?.totalWeight ?? null),
+ value: formatWeight(global?.totalWeight ?? null, unit),
},
{ label: "Cost", value: formatPrice(global?.totalCost ?? null) },
]}
diff --git a/src/client/routes/setups/$setupId.tsx b/src/client/routes/setups/$setupId.tsx
index 6dd3b71..7a48e05 100644
--- a/src/client/routes/setups/$setupId.tsx
+++ b/src/client/routes/setups/$setupId.tsx
@@ -8,6 +8,7 @@ import {
useRemoveSetupItem,
useSetup,
} from "../../hooks/useSetups";
+import { useWeightUnit } from "../../hooks/useWeightUnit";
import { formatPrice, formatWeight } from "../../lib/formatters";
import { LucideIcon } from "../../lib/iconData";
@@ -17,6 +18,7 @@ export const Route = createFileRoute("/setups/$setupId")({
function SetupDetailPage() {
const { setupId } = Route.useParams();
+ const unit = useWeightUnit();
const navigate = useNavigate();
const numericId = Number(setupId);
const { data: setup, isLoading } = useSetup(numericId);
@@ -105,7 +107,7 @@ function SetupDetailPage() {
- {formatWeight(totalWeight)}
+ {formatWeight(totalWeight, unit)}
{" "}
total