Skip to content

Commit a2b0c2c

Browse files
clucraftclaude
andcommitted
Fix price formatting for PostgreSQL DECIMAL type
PostgreSQL returns DECIMAL as strings, not numbers. Updated all price formatting functions to handle both. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 5263ac9 commit a2b0c2c

File tree

3 files changed

+29
-15
lines changed

3 files changed

+29
-15
lines changed

frontend/src/components/PriceChart.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,20 +41,23 @@ export default function PriceChart({
4141

4242
const chartData = prices.map((p) => ({
4343
date: new Date(p.recorded_at).getTime(),
44-
price: parseFloat(p.price.toString()),
44+
price: typeof p.price === 'string' ? parseFloat(p.price) : p.price,
4545
}));
4646

47-
const minPrice = Math.min(...chartData.map((d) => d.price));
48-
const maxPrice = Math.max(...chartData.map((d) => d.price));
49-
const avgPrice =
50-
chartData.reduce((sum, d) => sum + d.price, 0) / chartData.length;
47+
const priceValues = chartData.map((d) => d.price).filter((p) => !isNaN(p));
48+
const minPrice = priceValues.length > 0 ? Math.min(...priceValues) : 0;
49+
const maxPrice = priceValues.length > 0 ? Math.max(...priceValues) : 0;
50+
const avgPrice = priceValues.length > 0
51+
? priceValues.reduce((sum, p) => sum + p, 0) / priceValues.length
52+
: 0;
5153

5254
const formatDate = (timestamp: number) => {
5355
const date = new Date(timestamp);
5456
return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
5557
};
5658

5759
const formatPrice = (value: number) => {
60+
if (value === null || value === undefined || isNaN(value)) return 'N/A';
5861
return `${currencySymbol}${value.toFixed(2)}`;
5962
};
6063

frontend/src/components/ProductCard.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ interface ProductCardProps {
77
}
88

99
export default function ProductCard({ product, onDelete }: ProductCardProps) {
10-
const formatPrice = (price: number | null, currency: string | null) => {
11-
if (price === null) return 'N/A';
10+
const formatPrice = (price: number | string | null, currency: string | null) => {
11+
if (price === null || price === undefined) return 'N/A';
12+
const numPrice = typeof price === 'string' ? parseFloat(price) : price;
13+
if (isNaN(numPrice)) return 'N/A';
1214
const currencySymbol =
1315
currency === 'EUR' ? '€' : currency === 'GBP' ? '£' : '$';
14-
return `${currencySymbol}${price.toFixed(2)}`;
16+
return `${currencySymbol}${numPrice.toFixed(2)}`;
1517
};
1618

1719
const formatDate = (dateStr: string | null) => {

frontend/src/pages/ProductDetail.tsx

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,13 @@ export default function ProductDetail() {
7171
fetchData(days);
7272
};
7373

74-
const formatPrice = (price: number | null, currency: string | null) => {
75-
if (price === null) return 'N/A';
74+
const formatPrice = (price: number | string | null, currency: string | null) => {
75+
if (price === null || price === undefined) return 'N/A';
76+
const numPrice = typeof price === 'string' ? parseFloat(price) : price;
77+
if (isNaN(numPrice)) return 'N/A';
7678
const currencySymbol =
7779
currency === 'EUR' ? '€' : currency === 'GBP' ? '£' : '$';
78-
return `${currencySymbol}${price.toFixed(2)}`;
80+
return `${currencySymbol}${numPrice.toFixed(2)}`;
7981
};
8082

8183
if (isLoading) {
@@ -105,10 +107,17 @@ export default function ProductDetail() {
105107
);
106108
}
107109

108-
const priceChange =
109-
product.stats && prices.length > 1
110-
? ((product.current_price || 0) - prices[0].price) / prices[0].price
111-
: null;
110+
const priceChange = (() => {
111+
if (!product.stats || prices.length < 1) return null;
112+
const currentPrice = typeof product.current_price === 'string'
113+
? parseFloat(product.current_price)
114+
: (product.current_price || 0);
115+
const firstPrice = typeof prices[0].price === 'string'
116+
? parseFloat(prices[0].price)
117+
: prices[0].price;
118+
if (firstPrice === 0) return null;
119+
return (currentPrice - firstPrice) / firstPrice;
120+
})();
112121

113122
return (
114123
<Layout>

0 commit comments

Comments
 (0)