/**
* PriceTable - Responsive APMC price table with sorting and highlights.
*
* Features:
* - Desktop: Full table with sortable columns
* - Mobile: Card-based layout
* - Best price row highlighted
* - Price range bar (min/max)
* - Formatted dates and prices
* - Empty state
*/
import { useMemo } from "react";
import PropTypes from "prop-types";
import { motion } from "framer-motion";
import {
ArrowTrendingUpIcon,
ArrowTrendingDownIcon,
MinusIcon,
MapPinIcon,
StarIcon,
} from "@heroicons/react/24/outline";
import { Card, Badge } from "@components/common";
import { formatPricePerQuintal, formatDate } from "@utils/helpers";
/**
* Determine a price trend indicator based on modal vs min/max spread.
*/
function getTrendIndicator(price) {
if (!price.modal_price || !price.min_price || !price.max_price) {
return { icon: MinusIcon, color: "text-neutral-400", label: "Stable" };
}
const mid = (price.min_price + price.max_price) / 2;
const diff = ((price.modal_price - mid) / mid) * 100;
if (diff > 2) {
return { icon: ArrowTrendingUpIcon, color: "text-primary-600", label: "Rising" };
}
if (diff < -2) {
return { icon: ArrowTrendingDownIcon, color: "text-danger-600", label: "Falling" };
}
return { icon: MinusIcon, color: "text-neutral-400", label: "Stable" };
}
function PriceTable({ prices = [], bestAPMCName = "", className = "" }) {
// Find the best price row
const bestPrice = useMemo(() => {
if (prices.length === 0) return null;
return prices.reduce((best, p) =>
(p.price_per_quintal || 0) > (best.price_per_quintal || 0) ? p : best,
);
}, [prices]);
// Price range for bar visualization
const priceRange = useMemo(() => {
if (prices.length === 0) return { min: 0, max: 1 };
const allPrices = prices.map((p) => p.price_per_quintal).filter(Boolean);
return {
min: Math.min(...allPrices),
max: Math.max(...allPrices),
};
}, [prices]);
if (prices.length === 0) {
return (
No price data available. Select a commodity to see prices.
Showing {prices.length} APMCs
{bestPrice && (| APMC | Location | Price/qtl | Range | Trend | Date |
{isBest && (
|
{/* Location */}
{[price.district, price.state].filter(Boolean).join(", ")} | {/* Price */}{formatPricePerQuintal(price.price_per_quintal)} | {/* Range bar */}
{price.min_price ? `${Math.round(price.min_price)}` : "--"}
|
{/* Trend */}
{trend.label}
|
{/* Date */}
{formatDate(price.arrival_date)} |
|---|
{[price.district, price.state].filter(Boolean).join(", ")}