fix(marketplace): add centralized formatCurrency/formatCents utilities to prevent toFixed errors
This commit is contained in:
parent
b7ed676153
commit
965cedca05
7 changed files with 36 additions and 9 deletions
|
|
@ -1,4 +1,5 @@
|
|||
import { ProductWithDistance } from '../types/product'
|
||||
import { formatCents } from '../utils/format'
|
||||
|
||||
interface ProductCardProps {
|
||||
product: ProductWithDistance
|
||||
|
|
@ -38,7 +39,7 @@ export const ProductCard = ({ product, onAddToCart }: ProductCardProps) => {
|
|||
|
||||
<div className="flex justify-between items-end mt-4">
|
||||
<div className="text-2xl font-bold text-green-600">
|
||||
R$ {(product.price_cents / 100).toFixed(2).replace('.', ',')}
|
||||
{formatCents(product.price_cents)}
|
||||
</div>
|
||||
<button
|
||||
onClick={() => onAddToCart(product)}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { Shell } from '../layouts/Shell'
|
||||
import { selectGroupedCart, selectCartSummary, useCartStore } from '../stores/cartStore'
|
||||
import { formatCurrency } from '../utils/format'
|
||||
|
||||
export function CartPage() {
|
||||
const items = useCartStore((state) => state.items)
|
||||
|
|
@ -22,7 +23,7 @@ export function CartPage() {
|
|||
</div>
|
||||
<div className="text-right">
|
||||
<p className="text-sm text-gray-600">Itens: {summary.totalItems}</p>
|
||||
<p className="text-lg font-semibold text-medicalBlue">R$ {summary.totalValue.toFixed(2)}</p>
|
||||
<p className="text-lg font-semibold text-medicalBlue">R$ {formatCurrency(summary.totalValue)}</p>
|
||||
</div>
|
||||
</div>
|
||||
{items.length === 0 ? (
|
||||
|
|
@ -58,7 +59,7 @@ export function CartPage() {
|
|||
</div>
|
||||
<div className="text-right">
|
||||
<p className="text-xs text-gray-500">Preço</p>
|
||||
<p className="font-semibold text-medicalBlue">R$ {item.unitPrice.toFixed(2)}</p>
|
||||
<p className="font-semibold text-medicalBlue">R$ {formatCurrency(item.unitPrice)}</p>
|
||||
</div>
|
||||
<div className="flex items-center justify-end gap-2">
|
||||
<input
|
||||
|
|
@ -73,7 +74,7 @@ export function CartPage() {
|
|||
<div className="text-right">
|
||||
<p className="text-xs text-gray-500">Subtotal</p>
|
||||
<p className="font-semibold text-gray-800">
|
||||
R$ {(item.quantity * item.unitPrice).toFixed(2)}
|
||||
R$ {formatCurrency(item.quantity * item.unitPrice)}
|
||||
</p>
|
||||
<button
|
||||
className="text-xs text-red-500 hover:underline"
|
||||
|
|
@ -86,7 +87,7 @@ export function CartPage() {
|
|||
))}
|
||||
<div className="flex items-center justify-between rounded bg-gray-100 px-3 py-2 text-sm">
|
||||
<span className="font-semibold text-gray-700">Total do fornecedor</span>
|
||||
<span className="font-bold text-medicalBlue">R$ {group.total.toFixed(2)}</span>
|
||||
<span className="font-bold text-medicalBlue">R$ {formatCurrency(group.total)}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -109,3 +110,4 @@ export function CartPage() {
|
|||
</Shell>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { FixedSizeList as List, ListChildComponentProps } from 'react-window'
|
|||
import { Product } from '../types/product'
|
||||
import { useCartStore } from '../stores/cartStore'
|
||||
import { Shell } from '../layouts/Shell'
|
||||
import { formatCents } from '../utils/format'
|
||||
|
||||
// Mock data updated to match new Product interface
|
||||
const mockProducts: Product[] = Array.from({ length: 500 }).map((_, idx) => {
|
||||
|
|
@ -33,7 +34,7 @@ function DenseRow({ index, style, data }: ListChildComponentProps<Product[]>) {
|
|||
<div className="truncate text-gray-700">{product.description}</div>
|
||||
<div className="truncate text-gray-700">{product.batch}</div>
|
||||
<div className="truncate text-gray-700">{product.expires_at}</div>
|
||||
<div className="text-right font-semibold text-medicalBlue">R$ {(product.price_cents / 100).toFixed(2)}</div>
|
||||
<div className="text-right font-semibold text-medicalBlue">{formatCents(product.price_cents)}</div>
|
||||
<div className="col-span-2 flex items-center justify-end gap-2">
|
||||
<button
|
||||
className="rounded bg-healthGreen px-3 py-1 text-xs font-semibold text-white shadow-sm hover:opacity-90"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { useEffect, useState } from 'react'
|
||||
import { Shell } from '../layouts/Shell'
|
||||
import { apiClient } from '../services/apiClient'
|
||||
import { formatCents } from '../utils/format'
|
||||
|
||||
interface InventoryItem {
|
||||
product_id: string
|
||||
|
|
@ -124,7 +125,7 @@ export function InventoryPage() {
|
|||
</td>
|
||||
<td className="px-4 py-3 text-right text-sm font-semibold text-gray-800">{item.quantity}</td>
|
||||
<td className="px-4 py-3 text-right text-sm text-medicalBlue">
|
||||
R$ {(item.price_cents / 100).toFixed(2)}
|
||||
{formatCents(item.price_cents)}
|
||||
</td>
|
||||
<td className="px-4 py-3 text-center">
|
||||
<div className="flex justify-center gap-2">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { useEffect, useState } from 'react'
|
||||
import { Shell } from '../layouts/Shell'
|
||||
import { apiClient } from '../services/apiClient'
|
||||
import { formatCents } from '../utils/format'
|
||||
|
||||
interface Order {
|
||||
id: string
|
||||
|
|
@ -50,7 +51,7 @@ export function OrdersPage() {
|
|||
}
|
||||
}
|
||||
|
||||
const formatCurrency = (cents: number) => `R$ ${(cents / 100).toFixed(2)}`
|
||||
const formatCurrency = (cents: number | undefined | null) => formatCents(cents)
|
||||
|
||||
return (
|
||||
<Shell>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { useEffect, useState } from 'react'
|
||||
import { Shell } from '../layouts/Shell'
|
||||
import { apiClient } from '../services/apiClient'
|
||||
import { formatCents } from '../utils/format'
|
||||
|
||||
interface SellerDashboardData {
|
||||
seller_id: string
|
||||
|
|
@ -48,7 +49,7 @@ export function SellerDashboardPage() {
|
|||
}
|
||||
}
|
||||
|
||||
const formatCurrency = (cents: number) => `R$ ${(cents / 100).toFixed(2)}`
|
||||
const formatCurrency = (cents: number | undefined | null) => formatCents(cents)
|
||||
|
||||
return (
|
||||
<Shell>
|
||||
|
|
|
|||
20
marketplace/src/utils/format.ts
Normal file
20
marketplace/src/utils/format.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* Safely format a numeric value as Brazilian currency (R$)
|
||||
* Handles undefined, null, and NaN values gracefully
|
||||
*/
|
||||
export const formatCurrency = (value: number | undefined | null): string => {
|
||||
if (value === undefined || value === null || isNaN(value)) {
|
||||
return '0,00'
|
||||
}
|
||||
return value.toFixed(2).replace('.', ',')
|
||||
}
|
||||
|
||||
/**
|
||||
* Format cents to currency string
|
||||
*/
|
||||
export const formatCents = (cents: number | undefined | null): string => {
|
||||
if (cents === undefined || cents === null || isNaN(cents)) {
|
||||
return 'R$ 0,00'
|
||||
}
|
||||
return `R$ ${(cents / 100).toFixed(2).replace('.', ',')}`
|
||||
}
|
||||
Loading…
Reference in a new issue