feat(ui): ürün sayfası, fiyat geçmişi grafiği ve birim fiyat karşılaştırması
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,8 @@ import { PageHeader } from "@/components/page-header";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { tr } from "@/i18n/tr";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { formatDate, formatMoney } from "@/shared/format";
|
||||
import { formatUnitPrice } from "@/shared/prices";
|
||||
import { formatStock } from "@/shared/stock";
|
||||
import type { StockAnalysis, StockAnalysisRow } from "../service";
|
||||
|
||||
@@ -72,6 +74,7 @@ function Num({ value, unit, tone }: { value: number | null; unit: string; tone?:
|
||||
export function StockAnalysisView({ data }: { data: StockAnalysis }) {
|
||||
const groups = new Map<string, StockAnalysisRow[]>();
|
||||
for (const r of data.rows) groups.set(r.categoryPath, [...(groups.get(r.categoryPath) ?? []), r]);
|
||||
const totalCost = data.rows.reduce((sum, r) => sum + (r.avgMonthlyCostMinor ?? 0), 0);
|
||||
const first = data.months[0]!;
|
||||
const last = data.months.at(-1)!;
|
||||
|
||||
@@ -91,6 +94,7 @@ export function StockAnalysisView({ data }: { data: StockAnalysis }) {
|
||||
</p>
|
||||
) : (
|
||||
<>
|
||||
{totalCost > 0 ? <p className="text-sm">{t.totalCost(formatMoney(totalCost))}</p> : null}
|
||||
<div className="flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-muted-foreground">
|
||||
<span>
|
||||
{t.trend(data.months.length)}: {monthShort(first)} – {monthShort(last)}
|
||||
@@ -106,10 +110,11 @@ export function StockAnalysisView({ data }: { data: StockAnalysis }) {
|
||||
</div>
|
||||
|
||||
<div className="overflow-hidden rounded-xl border bg-card">
|
||||
<div className="hidden grid-cols-[minmax(0,1.4fr)_minmax(0,1fr)_repeat(4,minmax(0,0.7fr))] gap-3 border-b px-3 py-2 text-xs text-muted-foreground md:grid">
|
||||
<div className="hidden grid-cols-[minmax(0,1.4fr)_minmax(0,1fr)_repeat(5,minmax(0,0.7fr))] gap-3 border-b px-3 py-2 text-xs text-muted-foreground md:grid">
|
||||
<span>{t.product}</span>
|
||||
<span>{t.trend(data.months.length)}</span>
|
||||
<span className="text-right">{t.avgUsed}</span>
|
||||
<span className="text-right">{t.avgCost}</span>
|
||||
<span className="text-right">{t.avgWasted}</span>
|
||||
<span className="text-right">{t.wastePct}</span>
|
||||
<span className="text-right">{t.thisMonth}</span>
|
||||
@@ -125,7 +130,7 @@ export function StockAnalysisView({ data }: { data: StockAnalysis }) {
|
||||
return (
|
||||
<li
|
||||
key={r.id}
|
||||
className="grid grid-cols-2 items-center gap-x-3 gap-y-2 px-3 py-2.5 text-sm md:grid-cols-[minmax(0,1.4fr)_minmax(0,1fr)_repeat(4,minmax(0,0.7fr))]"
|
||||
className="grid grid-cols-2 items-center gap-x-3 gap-y-2 px-3 py-2.5 text-sm md:grid-cols-[minmax(0,1.4fr)_minmax(0,1fr)_repeat(5,minmax(0,0.7fr))]"
|
||||
>
|
||||
<Link
|
||||
href={`/stok/${r.id}`}
|
||||
@@ -140,6 +145,29 @@ export function StockAnalysisView({ data }: { data: StockAnalysis }) {
|
||||
</span>
|
||||
<Num value={r.avgMonthlyUsed} unit={r.unit} />
|
||||
</p>
|
||||
<p className="flex justify-between gap-2 md:block md:text-right">
|
||||
<span className="text-xs text-muted-foreground md:hidden">
|
||||
{t.avgCost}
|
||||
</span>
|
||||
<span
|
||||
className={cn(
|
||||
"tabular-nums",
|
||||
r.avgMonthlyCostMinor === null && "text-muted-foreground",
|
||||
)}
|
||||
title={
|
||||
r.unitPrice
|
||||
? t.costHint(
|
||||
formatUnitPrice(r.unitPrice.minor, r.unit),
|
||||
formatDate(`${r.unitPrice.date}T12:00:00+03:00`),
|
||||
)
|
||||
: t.noPrice
|
||||
}
|
||||
>
|
||||
{r.avgMonthlyCostMinor === null
|
||||
? t.noData
|
||||
: formatMoney(r.avgMonthlyCostMinor)}
|
||||
</span>
|
||||
</p>
|
||||
<p className="flex justify-between gap-2 md:block md:text-right">
|
||||
<span className="text-xs text-muted-foreground md:hidden">
|
||||
{t.avgWasted}
|
||||
|
||||
Reference in New Issue
Block a user