fix: price labels use user's selected currency instead of hardcoded $
Replaced hardcoded "Price ($)" labels across 6 components and 2 locale files to display the user's selected currency (EUR, GBP, USD, etc.). AddToCollectionModal also updated to show correct currency. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { useCategories } from "../hooks/useCategories";
|
import { useCategories } from "../hooks/useCategories";
|
||||||
|
import { useCurrency } from "../hooks/useCurrency";
|
||||||
import { useCreateItem } from "../hooks/useItems";
|
import { useCreateItem } from "../hooks/useItems";
|
||||||
import { useUIStore } from "../stores/uiStore";
|
import { useUIStore } from "../stores/uiStore";
|
||||||
import { CategoryPicker } from "./CategoryPicker";
|
import { CategoryPicker } from "./CategoryPicker";
|
||||||
@@ -12,6 +13,7 @@ export function AddToCollectionModal() {
|
|||||||
const closeAddToCollection = useUIStore((s) => s.closeAddToCollection);
|
const closeAddToCollection = useUIStore((s) => s.closeAddToCollection);
|
||||||
|
|
||||||
const { data: categories } = useCategories();
|
const { data: categories } = useCategories();
|
||||||
|
const { currency } = useCurrency();
|
||||||
const createItem = useCreateItem();
|
const createItem = useCreateItem();
|
||||||
|
|
||||||
const [categoryId, setCategoryId] = useState<number | null>(null);
|
const [categoryId, setCategoryId] = useState<number | null>(null);
|
||||||
@@ -127,7 +129,7 @@ export function AddToCollectionModal() {
|
|||||||
htmlFor="collection-price"
|
htmlFor="collection-price"
|
||||||
className="block text-sm font-medium text-gray-700 mb-1"
|
className="block text-sm font-medium text-gray-700 mb-1"
|
||||||
>
|
>
|
||||||
Purchase Price ($)
|
Purchase Price ({currency})
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="collection-price"
|
id="collection-price"
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useCreateCandidate, useUpdateCandidate } from "../hooks/useCandidates";
|
import { useCreateCandidate, useUpdateCandidate } from "../hooks/useCandidates";
|
||||||
|
import { useCurrency } from "../hooks/useCurrency";
|
||||||
import { useThread } from "../hooks/useThreads";
|
import { useThread } from "../hooks/useThreads";
|
||||||
import { CategoryPicker } from "./CategoryPicker";
|
import { CategoryPicker } from "./CategoryPicker";
|
||||||
import { ImageUpload } from "./ImageUpload";
|
import { ImageUpload } from "./ImageUpload";
|
||||||
@@ -42,6 +43,7 @@ export function CandidateForm({
|
|||||||
onClose,
|
onClose,
|
||||||
}: CandidateFormProps) {
|
}: CandidateFormProps) {
|
||||||
const { data: thread } = useThread(threadId);
|
const { data: thread } = useThread(threadId);
|
||||||
|
const { currency } = useCurrency();
|
||||||
const createCandidate = useCreateCandidate(threadId);
|
const createCandidate = useCreateCandidate(threadId);
|
||||||
const updateCandidate = useUpdateCandidate(threadId);
|
const updateCandidate = useUpdateCandidate(threadId);
|
||||||
|
|
||||||
@@ -204,7 +206,7 @@ export function CandidateForm({
|
|||||||
htmlFor="candidate-price"
|
htmlFor="candidate-price"
|
||||||
className="block text-sm font-medium text-gray-700 mb-1"
|
className="block text-sm font-medium text-gray-700 mb-1"
|
||||||
>
|
>
|
||||||
Price ($)
|
{`Price (${currency})`}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="candidate-price"
|
id="candidate-price"
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
import { useCurrency } from "../hooks/useCurrency";
|
||||||
import { useCreateItem, useItems, useUpdateItem } from "../hooks/useItems";
|
import { useCreateItem, useItems, useUpdateItem } from "../hooks/useItems";
|
||||||
import { useUIStore } from "../stores/uiStore";
|
import { useUIStore } from "../stores/uiStore";
|
||||||
import { CategoryPicker } from "./CategoryPicker";
|
import { CategoryPicker } from "./CategoryPicker";
|
||||||
@@ -34,6 +35,7 @@ const INITIAL_FORM: FormData = {
|
|||||||
|
|
||||||
export function ItemForm({ mode, itemId, onClose }: ItemFormProps) {
|
export function ItemForm({ mode, itemId, onClose }: ItemFormProps) {
|
||||||
const { data: items } = useItems();
|
const { data: items } = useItems();
|
||||||
|
const { currency } = useCurrency();
|
||||||
const createItem = useCreateItem();
|
const createItem = useCreateItem();
|
||||||
const updateItem = useUpdateItem();
|
const updateItem = useUpdateItem();
|
||||||
const openConfirmDelete = useUIStore((s) => s.openConfirmDelete);
|
const openConfirmDelete = useUIStore((s) => s.openConfirmDelete);
|
||||||
@@ -192,7 +194,7 @@ export function ItemForm({ mode, itemId, onClose }: ItemFormProps) {
|
|||||||
htmlFor="item-price"
|
htmlFor="item-price"
|
||||||
className="block text-sm font-medium text-gray-700 mb-1"
|
className="block text-sm font-medium text-gray-700 mb-1"
|
||||||
>
|
>
|
||||||
Price ($)
|
{`Price (${currency})`}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="item-price"
|
id="item-price"
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useCategories } from "../hooks/useCategories";
|
import { useCategories } from "../hooks/useCategories";
|
||||||
|
import { useCurrency } from "../hooks/useCurrency";
|
||||||
import { useCreateItem } from "../hooks/useItems";
|
import { useCreateItem } from "../hooks/useItems";
|
||||||
import { CategoryPicker } from "./CategoryPicker";
|
import { CategoryPicker } from "./CategoryPicker";
|
||||||
import { ImageUpload } from "./ImageUpload";
|
import { ImageUpload } from "./ImageUpload";
|
||||||
@@ -14,6 +15,7 @@ export function ManualEntryForm({
|
|||||||
onSuccess,
|
onSuccess,
|
||||||
}: ManualEntryFormProps) {
|
}: ManualEntryFormProps) {
|
||||||
const { data: categories } = useCategories();
|
const { data: categories } = useCategories();
|
||||||
|
const { currency } = useCurrency();
|
||||||
const createItem = useCreateItem();
|
const createItem = useCreateItem();
|
||||||
|
|
||||||
const [name, setName] = useState(initialName ?? "");
|
const [name, setName] = useState(initialName ?? "");
|
||||||
@@ -160,7 +162,7 @@ export function ManualEntryForm({
|
|||||||
htmlFor="manual-purchase-price"
|
htmlFor="manual-purchase-price"
|
||||||
className="block text-sm font-medium text-gray-700 mb-1"
|
className="block text-sm font-medium text-gray-700 mb-1"
|
||||||
>
|
>
|
||||||
Purchase Price ($)
|
{`Purchase Price (${currency})`}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="manual-purchase-price"
|
id="manual-purchase-price"
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
"namePlaceholder": "z.B. Osprey Talon 22",
|
"namePlaceholder": "z.B. Osprey Talon 22",
|
||||||
"weight": "Gewicht (g)",
|
"weight": "Gewicht (g)",
|
||||||
"weightPlaceholder": "z.B. 680",
|
"weightPlaceholder": "z.B. 680",
|
||||||
"price": "Preis ($)",
|
"price": "Preis",
|
||||||
"pricePlaceholder": "z.B. 129,99",
|
"pricePlaceholder": "z.B. 129,99",
|
||||||
"quantity": "Menge",
|
"quantity": "Menge",
|
||||||
"category": "Kategorie",
|
"category": "Kategorie",
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
"namePlaceholder": "e.g. Osprey Talon 22",
|
"namePlaceholder": "e.g. Osprey Talon 22",
|
||||||
"weight": "Weight (g)",
|
"weight": "Weight (g)",
|
||||||
"weightPlaceholder": "e.g. 680",
|
"weightPlaceholder": "e.g. 680",
|
||||||
"price": "Price ($)",
|
"price": "Price",
|
||||||
"pricePlaceholder": "e.g. 129.99",
|
"pricePlaceholder": "e.g. 129.99",
|
||||||
"quantity": "Quantity",
|
"quantity": "Quantity",
|
||||||
"category": "Category",
|
"category": "Category",
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { GearImage, imageContainerBg } from "../../components/GearImage";
|
|||||||
import { ImageCropEditor } from "../../components/ImageCropEditor";
|
import { ImageCropEditor } from "../../components/ImageCropEditor";
|
||||||
import { ImageUpload } from "../../components/ImageUpload";
|
import { ImageUpload } from "../../components/ImageUpload";
|
||||||
import { useAuth } from "../../hooks/useAuth";
|
import { useAuth } from "../../hooks/useAuth";
|
||||||
|
import { useCurrency } from "../../hooks/useCurrency";
|
||||||
import { useFormatters } from "../../hooks/useFormatters";
|
import { useFormatters } from "../../hooks/useFormatters";
|
||||||
import { useDuplicateItem, useItem, useUpdateItem } from "../../hooks/useItems";
|
import { useDuplicateItem, useItem, useUpdateItem } from "../../hooks/useItems";
|
||||||
import { usePublicSetupItem, useSharedSetupItem } from "../../hooks/useSetups";
|
import { usePublicSetupItem, useSharedSetupItem } from "../../hooks/useSetups";
|
||||||
@@ -39,6 +40,7 @@ function ItemDetail() {
|
|||||||
const { setup: setupId, share: shareToken } = Route.useSearch();
|
const { setup: setupId, share: shareToken } = Route.useSearch();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { data: auth } = useAuth();
|
const { data: auth } = useAuth();
|
||||||
|
const { currency } = useCurrency();
|
||||||
const isAuthenticated = !!auth?.user;
|
const isAuthenticated = !!auth?.user;
|
||||||
|
|
||||||
// Determine access mode: shared (token), public (setup context, no auth), or owner
|
// Determine access mode: shared (token), public (setup context, no auth), or owner
|
||||||
@@ -500,7 +502,7 @@ function ItemDetail() {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-xs font-medium text-gray-500 mb-1">
|
<label className="block text-xs font-medium text-gray-500 mb-1">
|
||||||
Price ($)
|
{`Price (${currency})`}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { ImageCropEditor } from "../../../../components/ImageCropEditor";
|
|||||||
import { ImageUpload } from "../../../../components/ImageUpload";
|
import { ImageUpload } from "../../../../components/ImageUpload";
|
||||||
import { StatusBadge } from "../../../../components/StatusBadge";
|
import { StatusBadge } from "../../../../components/StatusBadge";
|
||||||
import { useUpdateCandidate } from "../../../../hooks/useCandidates";
|
import { useUpdateCandidate } from "../../../../hooks/useCandidates";
|
||||||
|
import { useCurrency } from "../../../../hooks/useCurrency";
|
||||||
import { useFormatters } from "../../../../hooks/useFormatters";
|
import { useFormatters } from "../../../../hooks/useFormatters";
|
||||||
import { useThread } from "../../../../hooks/useThreads";
|
import { useThread } from "../../../../hooks/useThreads";
|
||||||
import { LucideIcon } from "../../../../lib/iconData";
|
import { LucideIcon } from "../../../../lib/iconData";
|
||||||
@@ -37,6 +38,7 @@ function CandidateDetailPage() {
|
|||||||
const { data: thread, isLoading, isError } = useThread(threadId);
|
const { data: thread, isLoading, isError } = useThread(threadId);
|
||||||
const updateCandidate = useUpdateCandidate(threadId);
|
const updateCandidate = useUpdateCandidate(threadId);
|
||||||
const { weight, price } = useFormatters();
|
const { weight, price } = useFormatters();
|
||||||
|
const { currency } = useCurrency();
|
||||||
const openResolveDialog = useUIStore((s) => s.openResolveDialog);
|
const openResolveDialog = useUIStore((s) => s.openResolveDialog);
|
||||||
const openConfirmDeleteCandidate = useUIStore(
|
const openConfirmDeleteCandidate = useUIStore(
|
||||||
(s) => s.openConfirmDeleteCandidate,
|
(s) => s.openConfirmDeleteCandidate,
|
||||||
@@ -330,7 +332,7 @@ function CandidateDetailPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<label className="text-xs font-medium text-gray-500">
|
<label className="text-xs font-medium text-gray-500">
|
||||||
Price ($)
|
{`Price (${currency})`}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
useReorderCandidates,
|
useReorderCandidates,
|
||||||
useUpdateCandidate,
|
useUpdateCandidate,
|
||||||
} from "../../../hooks/useCandidates";
|
} from "../../../hooks/useCandidates";
|
||||||
|
import { useCurrency } from "../../../hooks/useCurrency";
|
||||||
import { useImpactDeltas } from "../../../hooks/useImpactDeltas";
|
import { useImpactDeltas } from "../../../hooks/useImpactDeltas";
|
||||||
import { useSetup } from "../../../hooks/useSetups";
|
import { useSetup } from "../../../hooks/useSetups";
|
||||||
import { useThread } from "../../../hooks/useThreads";
|
import { useThread } from "../../../hooks/useThreads";
|
||||||
@@ -340,6 +341,7 @@ const INITIAL_MODAL_FORM: ModalFormData = {
|
|||||||
|
|
||||||
function AddCandidateModal({ threadId, onClose }: AddCandidateModalProps) {
|
function AddCandidateModal({ threadId, onClose }: AddCandidateModalProps) {
|
||||||
const createCandidate = useCreateCandidate(threadId);
|
const createCandidate = useCreateCandidate(threadId);
|
||||||
|
const { currency } = useCurrency();
|
||||||
const [form, setForm] = useState<ModalFormData>(INITIAL_MODAL_FORM);
|
const [form, setForm] = useState<ModalFormData>(INITIAL_MODAL_FORM);
|
||||||
const [errors, setErrors] = useState<Record<string, string>>({});
|
const [errors, setErrors] = useState<Record<string, string>>({});
|
||||||
|
|
||||||
@@ -490,7 +492,7 @@ function AddCandidateModal({ threadId, onClose }: AddCandidateModalProps) {
|
|||||||
htmlFor="modal-candidate-price"
|
htmlFor="modal-candidate-price"
|
||||||
className="block text-sm font-medium text-gray-700 mb-1"
|
className="block text-sm font-medium text-gray-700 mb-1"
|
||||||
>
|
>
|
||||||
Price ($)
|
{`Price (${currency})`}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="modal-candidate-price"
|
id="modal-candidate-price"
|
||||||
|
|||||||
Reference in New Issue
Block a user