fix(marketplace): add centralized formatCurrency/formatCents utilities to prevent toFixed errors

This commit is contained in:
Tiago Yamamoto 2025-12-22 16:31:39 -03:00
parent b7ed676153
commit 965cedca05
7 changed files with 36 additions and 9 deletions

View file

@ -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)}

View file

@ -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>
)
}

View file

@ -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"

View file

@ -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">

View file

@ -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>

View file

@ -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>

View 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('.', ',')}`
}