fix(ime/lme): eliminate duplicate titles and double prices, convert all calendars and dates to Persian Jalali
This commit is contained in:
parent
9a36873dbe
commit
aec46eb0e6
|
|
@ -33,20 +33,20 @@ HEADERS = {
|
|||
def clean_persian_title(title: str) -> tuple[str, str]:
|
||||
"""
|
||||
Removes English symbol codes (e.g. FTKC-BSG017OO-00, KHSS-DRIBRI-00)
|
||||
and returns (clean_title, manufacturer).
|
||||
and returns (product_name, manufacturer).
|
||||
Avoids duplicate manufacturer names.
|
||||
"""
|
||||
if not title:
|
||||
return "", ""
|
||||
parts = [p.strip() for p in title.split(" - ") if p.strip()]
|
||||
if len(parts) >= 3:
|
||||
if re.search(r'^[A-Za-z0-9_-]+$', parts[1]):
|
||||
product = parts[0]
|
||||
manufacturer = parts[2]
|
||||
return f"{product} ({manufacturer})", manufacturer
|
||||
product = parts[0]
|
||||
manufacturer = parts[2]
|
||||
return product, manufacturer
|
||||
elif len(parts) == 2:
|
||||
if re.search(r'^[A-Za-z0-9_-]+$', parts[1]):
|
||||
return parts[0], ""
|
||||
return f"{parts[0]} ({parts[1]})", parts[1]
|
||||
return parts[0], parts[1]
|
||||
|
||||
cleaned = re.sub(r'\b[A-Za-z0-9]{3,}-[A-Za-z0-9_-]+\b', '', title)
|
||||
cleaned = re.sub(r'\s*-\s*-+\s*', ' - ', cleaned).strip(" -")
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import {
|
|||
CartesianGrid
|
||||
} from "recharts";
|
||||
import { API_BASE } from "@/lib/api";
|
||||
import { toJalali } from "@/lib/metals-data";
|
||||
|
||||
const API = API_BASE;
|
||||
|
||||
|
|
@ -355,7 +356,7 @@ export function ImeView() {
|
|||
onClick={() => setSelectedSymbol(sym)}
|
||||
className="group cursor-pointer relative overflow-hidden rounded-2xl border border-border/70 bg-gradient-to-b from-card to-card/40 p-5 backdrop-blur-md transition-all duration-200 hover:shadow-xl hover:-translate-y-1 hover:border-primary flex flex-col justify-between"
|
||||
>
|
||||
<div className="space-y-2">
|
||||
<div className="space-y-1.5">
|
||||
<div className="text-sm font-bold text-foreground group-hover:text-primary transition-colors line-clamp-2">
|
||||
{sym.product_name || sym.title}
|
||||
</div>
|
||||
|
|
@ -368,22 +369,18 @@ export function ImeView() {
|
|||
)}
|
||||
</div>
|
||||
|
||||
{/* LATEST PRICE PROMINENTLY DISPLAYED ON CARD FACE */}
|
||||
{/* LATEST PRICE: Clean, prominent single price in Tomans */}
|
||||
<div className="mt-4 pt-3 border-t border-border/40 space-y-2">
|
||||
<div className="flex items-baseline justify-between">
|
||||
<span className="text-xs text-muted-foreground">آخرین قیمت:</span>
|
||||
<span className="text-xs text-muted-foreground">آخرین نرخ کشفشده:</span>
|
||||
<div className="text-left font-mono">
|
||||
{sym.latest_price?.mid ? (
|
||||
<div>
|
||||
<div className="text-lg font-bold text-primary">
|
||||
{sym.latest_price.mid.toLocaleString()} <span className="text-xs font-normal text-muted-foreground">ریال</span>
|
||||
</div>
|
||||
<div className="text-[11px] text-muted-foreground">
|
||||
{(Math.round(sym.latest_price.mid / 10)).toLocaleString()} تومان
|
||||
</div>
|
||||
</div>
|
||||
<span className="text-base sm:text-lg font-bold text-primary">
|
||||
{(Math.round(sym.latest_price.mid / 10)).toLocaleString()}{" "}
|
||||
<span className="text-xs font-normal text-muted-foreground">تومان/کیلو</span>
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-xs text-muted-foreground">ثبت معامله ندارد</span>
|
||||
<span className="text-xs text-muted-foreground">بدون معامله اخیر</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -395,7 +392,7 @@ export function ImeView() {
|
|||
|
||||
{sym.latest_price?.date && (
|
||||
<span className="text-[10px] text-muted-foreground font-mono">
|
||||
{sym.latest_price.date}
|
||||
{toJalali(sym.latest_price.date)}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -446,24 +443,24 @@ export function ImeView() {
|
|||
<div className="rounded-2xl border border-border/60 bg-card/60 p-3.5">
|
||||
<div className="text-[11px] text-muted-foreground">آخرین قیمت کشفشده</div>
|
||||
<div className="text-base sm:text-lg font-bold font-mono text-foreground mt-0.5">
|
||||
{stats.last.toLocaleString()} ریال
|
||||
{(Math.round(stats.last / 10)).toLocaleString()} تومان
|
||||
</div>
|
||||
<div className="text-[10px] text-muted-foreground mt-0.5">
|
||||
{(Math.round(stats.last / 10)).toLocaleString()} تومان
|
||||
{stats.last.toLocaleString()} ریال
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="rounded-2xl border border-border/60 bg-card/60 p-3.5">
|
||||
<div className="text-[11px] text-muted-foreground">بالاترین قیمت دوره</div>
|
||||
<div className="text-base sm:text-lg font-bold font-mono text-foreground mt-0.5">
|
||||
{stats.max.toLocaleString()} ریال
|
||||
{(Math.round(stats.max / 10)).toLocaleString()} تومان
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="rounded-2xl border border-border/60 bg-card/60 p-3.5">
|
||||
<div className="text-[11px] text-muted-foreground">پایینترین قیمت دوره</div>
|
||||
<div className="text-base sm:text-lg font-bold font-mono text-foreground mt-0.5">
|
||||
{stats.min.toLocaleString()} ریال
|
||||
{(Math.round(stats.min / 10)).toLocaleString()} تومان
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -475,7 +472,7 @@ export function ImeView() {
|
|||
}`}
|
||||
>
|
||||
{stats.diff >= 0 ? "+" : ""}
|
||||
{stats.diff.toLocaleString()} ({stats.pct.toFixed(1)}%)
|
||||
{(Math.round(stats.diff / 10)).toLocaleString()} تومان ({stats.pct.toFixed(1)}%)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -506,12 +503,17 @@ export function ImeView() {
|
|||
<XAxis
|
||||
dataKey="date"
|
||||
tick={{ fontSize: 10, fill: "var(--muted-foreground)" }}
|
||||
tickFormatter={(val) => {
|
||||
const jal = toJalali(val);
|
||||
const parts = jal.split("/");
|
||||
return parts.length === 3 ? `${parts[1]}/${parts[2]}` : jal;
|
||||
}}
|
||||
minTickGap={35}
|
||||
/>
|
||||
<YAxis
|
||||
domain={["auto", "auto"]}
|
||||
tick={{ fontSize: 10, fill: "var(--muted-foreground)" }}
|
||||
tickFormatter={(v) => `${(v / 1000).toLocaleString()}k`}
|
||||
tickFormatter={(v) => `${(v / 10000).toLocaleString()}k ت`}
|
||||
orientation="right"
|
||||
/>
|
||||
<Tooltip
|
||||
|
|
@ -521,16 +523,16 @@ export function ImeView() {
|
|||
return (
|
||||
<div className="rounded-xl border border-border/80 bg-card/95 p-3 text-foreground shadow-2xl backdrop-blur-md space-y-1 min-w-[160px]" dir="rtl">
|
||||
<div className="text-[11px] text-muted-foreground font-mono pb-1 border-b border-border/40">
|
||||
تاریخ معامله: {pt.date}
|
||||
تاریخ معامله: {toJalali(pt.date)}
|
||||
</div>
|
||||
<div className="flex items-center justify-between text-xs pt-1">
|
||||
<span className="text-muted-foreground">قیمت پایانی:</span>
|
||||
<span className="font-mono font-bold text-primary">
|
||||
{pt.mid.toLocaleString()} ریال
|
||||
{(Math.round(pt.mid / 10)).toLocaleString()} تومان
|
||||
</span>
|
||||
</div>
|
||||
<div className="text-[10px] text-muted-foreground">
|
||||
معادل {(Math.round(pt.mid / 10)).toLocaleString()} تومان
|
||||
<div className="text-[10px] text-muted-foreground font-mono">
|
||||
({pt.mid.toLocaleString()} ریال)
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { toJalali } from "@/lib/metals-data";
|
||||
import { useState, useEffect, useMemo } from "react";
|
||||
import {
|
||||
Search,
|
||||
|
|
@ -678,8 +679,9 @@ export function LmeView() {
|
|||
tick={{ fontSize: 10, fill: "var(--muted-foreground)" }}
|
||||
tickFormatter={(val) => {
|
||||
if (!val) return "";
|
||||
const p = val.split("-");
|
||||
return p.length === 3 ? `${p[0]}/${p[1]}` : val;
|
||||
const jal = toJalali(val);
|
||||
const p = jal.split("/");
|
||||
return p.length === 3 ? `${p[0]}/${p[1]}` : jal;
|
||||
}}
|
||||
minTickGap={40}
|
||||
/>
|
||||
|
|
@ -716,7 +718,7 @@ export function LmeView() {
|
|||
return (
|
||||
<div className="rounded-xl border border-border/80 bg-card/95 p-3 text-foreground shadow-2xl backdrop-blur-md space-y-1.5 min-w-[170px]" dir="rtl">
|
||||
<div className="text-[11px] font-medium text-muted-foreground border-b border-border/40 pb-1 font-mono">
|
||||
تاریخ: {ptData.date_display || label}
|
||||
تاریخ: {toJalali(ptData.date || label)}
|
||||
</div>
|
||||
|
||||
{showPrice && ptData.priceVal !== undefined && (
|
||||
|
|
|
|||
Loading…
Reference in New Issue