fix: Use active WooCommerce currency instead of hardcoded USD

Fixed Issues:
1.  Currency hardcoded to USD in product forms
2.  Edit page redirect to non-existent detail page

Changes:

🌍 Currency Integration (GeneralTab.tsx):
- Import getStoreCurrency() from @/lib/currency
- Get store currency data: symbol, decimals, position
- Replace hardcoded $ icon with dynamic store.symbol
- Use store.decimals for input step:
  * step="1" for zero-decimal currencies (IDR, JPY, etc.)
  * step="0.01" for decimal currencies (USD, EUR, etc.)
- Update placeholder based on decimals:
  * "0" for zero-decimal
  * "0.00" for decimal

Before:
- <DollarSign /> icon (always $)
- step="0.01" (always 2 decimals)
- placeholder="0.00" (always 2 decimals)

After:
- <span>{store.symbol}</span> (Rp, $, RM, etc.)
- step={store.decimals === 0 ? '1' : '0.01'}
- placeholder={store.decimals === 0 ? '0' : '0.00'}

🌍 Currency Display (index.tsx):
- Import formatMoney() from @/lib/currency
- Replace hardcoded $:
  * Before: ${parseFloat(product.regular_price).toFixed(2)}
  * After: formatMoney(product.regular_price)
- Now respects:
  * Currency symbol (Rp, $, RM, etc.)
  * Decimal places (0 for IDR, 2 for USD)
  * Thousand separator (. for IDR, , for USD)
  * Decimal separator (, for IDR, . for USD)
  * Position (left/right/left_space/right_space)

Examples:
- IDR: Rp 100.000 (no decimals, dot separator)
- USD: $100.00 (2 decimals, comma separator)
- MYR: RM 100.00 (2 decimals)

🔧 Edit Page Fix:
- Changed redirect after update:
  * Before: navigate(`/products/${id}`) → 404 (no detail page)
  * After: navigate('/products') → products list 

Result:
 Product forms use active WooCommerce currency
 Prices display with correct symbol and format
 Input fields respect currency decimals
 Edit page redirects to index after save
 Consistent with Orders module pattern
This commit is contained in:
dwindown
2025-11-19 23:32:59 +07:00
parent 4d185f0c24
commit 07b5b072c2
3 changed files with 18 additions and 9 deletions

View File

@@ -39,8 +39,8 @@ export default function ProductEdit() {
queryClient.invalidateQueries({ queryKey: ['products'] }); queryClient.invalidateQueries({ queryKey: ['products'] });
queryClient.invalidateQueries({ queryKey: ['products', id] }); queryClient.invalidateQueries({ queryKey: ['products', id] });
// Navigate back to product detail or list // Navigate back to products list
navigate(`/products/${id}`); navigate('/products');
}, },
onError: (error: any) => { onError: (error: any) => {
toast.error(error.message || __('Failed to update product')); toast.error(error.message || __('Failed to update product'));

View File

@@ -28,6 +28,7 @@ import {
SelectValue, SelectValue,
} from "@/components/ui/select"; } from "@/components/ui/select";
import { Link, useNavigate } from 'react-router-dom'; import { Link, useNavigate } from 'react-router-dom';
import { formatMoney, getStoreCurrency } from '@/lib/currency';
import { Skeleton } from '@/components/ui/skeleton'; import { Skeleton } from '@/components/ui/skeleton';
import { setQuery, getQuery } from '@/lib/query-params'; import { setQuery, getQuery } from '@/lib/query-params';
import { ProductCard } from './components/ProductCard'; import { ProductCard } from './components/ProductCard';
@@ -386,7 +387,7 @@ export default function Products() {
{product.price_html ? ( {product.price_html ? (
<span dangerouslySetInnerHTML={{ __html: product.price_html }} /> <span dangerouslySetInnerHTML={{ __html: product.price_html }} />
) : product.regular_price ? ( ) : product.regular_price ? (
<span>${parseFloat(product.regular_price).toFixed(2)}</span> <span>{formatMoney(product.regular_price)}</span>
) : ( ) : (
<span className="text-muted-foreground"></span> <span className="text-muted-foreground"></span>
)} )}

View File

@@ -8,6 +8,7 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/com
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Separator } from '@/components/ui/separator'; import { Separator } from '@/components/ui/separator';
import { DollarSign } from 'lucide-react'; import { DollarSign } from 'lucide-react';
import { getStoreCurrency } from '@/lib/currency';
type GeneralTabProps = { type GeneralTabProps = {
name: string; name: string;
@@ -63,6 +64,9 @@ export function GeneralTab({
salePrice && regularPrice && parseFloat(salePrice) < parseFloat(regularPrice) salePrice && regularPrice && parseFloat(salePrice) < parseFloat(regularPrice)
? Math.round((1 - parseFloat(salePrice) / parseFloat(regularPrice)) * 100) ? Math.round((1 - parseFloat(salePrice) / parseFloat(regularPrice)) * 100)
: 0; : 0;
const store = getStoreCurrency();
return ( return (
<Card> <Card>
<CardHeader> <CardHeader>
@@ -187,14 +191,16 @@ export function GeneralTab({
{__('Regular Price')} {type === 'simple' && '*'} {__('Regular Price')} {type === 'simple' && '*'}
</Label> </Label>
<div className="relative mt-1.5"> <div className="relative mt-1.5">
<DollarSign className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" /> <span className="absolute left-3 top-1/2 -translate-y-1/2 text-sm text-muted-foreground font-medium">
{store.symbol}
</span>
<Input <Input
id="regular_price" id="regular_price"
type="number" type="number"
step="0.01" step={store.decimals === 0 ? '1' : '0.01'}
value={regularPrice} value={regularPrice}
onChange={(e) => setRegularPrice(e.target.value)} onChange={(e) => setRegularPrice(e.target.value)}
placeholder="0.00" placeholder={store.decimals === 0 ? '0' : '0.00'}
required={type === 'simple'} required={type === 'simple'}
className="pl-10" className="pl-10"
/> />
@@ -209,14 +215,16 @@ export function GeneralTab({
<div> <div>
<Label htmlFor="sale_price">{__('Sale Price')}</Label> <Label htmlFor="sale_price">{__('Sale Price')}</Label>
<div className="relative mt-1.5"> <div className="relative mt-1.5">
<DollarSign className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" /> <span className="absolute left-3 top-1/2 -translate-y-1/2 text-sm text-muted-foreground font-medium">
{store.symbol}
</span>
<Input <Input
id="sale_price" id="sale_price"
type="number" type="number"
step="0.01" step={store.decimals === 0 ? '1' : '0.01'}
value={salePrice} value={salePrice}
onChange={(e) => setSalePrice(e.target.value)} onChange={(e) => setSalePrice(e.target.value)}
placeholder="0.00" placeholder={store.decimals === 0 ? '0' : '0.00'}
className="pl-10" className="pl-10"
/> />
</div> </div>