Wizard:
- failed saves now route to the exact step+field: a new data-field attribute on every required section (supplier_id, line_items, termsheets, project, quote_date, expiry_date, notes, proforma) plus resolveErrorTarget() that maps ApiError.field / message keywords (supplier, line item/material/unit/quantity, termsheet/schedule/milestone, project, dates, notes, file) to the offending step — the «رفع خطا» toast action scrolls/focuses the right control instead of guessing
- material records are no longer created on the fly while typing (rememberMaterial no longer fires addMaterial per blur); materials/specs/units are written once during the final save, avoiding half-created catalog rows
Accept flow:
- quote_service no longer rewrites LineItemProjects on accept — those candidate-project rows stay 100% untouched and only item_decisions.project_id is written, matching the per-item target-project model and the UI payload (item_projects: [])
Dates/time:
- JalaliDatePicker: hour/minute are now editable text fields (Persian digits, clamping, 3-digit retype handling) with a controlled useEffect that only rewrites the inputs when the numeric value actually changes — no more wiping in-progress typing; date-only detection tightened to a full YYYY-MM-DD match so datetime strings are not misread
Also: /api validation logging (RequestValidationError) now includes the path and error list for faster diagnosis.
Verified: api + frontend image builds (python, tsc, vite) clean on top of origin/production (incl. the team's mobile layout merges).
Merges main_v2 a110741 (mobile UI optimizations) into production and
reinstates the mobile bottom navigation that f0e4243 had removed.
Conflicts in DashboardPage, QuoteCard and InventoryPage resolved in
favour of main_v2's mobile-first markup, keeping production's newer
design system (Button variant="primary" on InventoryPage).
f0e4243's removal was reverted in effect: MobileTabBar is restored and
remounted in App.tsx, and PageLayout regains max-md:pb-24 clearance so
content is not hidden behind the fixed bar.
For accepted quotes with PM-confirmed (partial) receipts the dashboard row
only showed «رسیده X از Y — در راه Z» with no timestamp (quote header
arrived_date is set only when everything arrives). The cell now also shows
«آخرین رسید: <date time>» computed from the newest item receipt; arrived
quotes keep the arrival date with a last-receipt fallback.
New shared materialLabel() renders the global materials.name with brand/specs
appended only when not already part of the name (deduped; «؟» fallback kept).
Replaces the category-first composer in five places: supplier card badges
(CategoryPage), dashboard item lines (QuoteCard), ledger items summary,
project rows and purchase history. Also fixes the stale Units subtitle
«ضریب تبدیل همان دسته» → «ضریب تبدیل متریال» (category model kept).
- bug1: quote header fulfillment counter («رسید: X از Y قلم» amber / «تکمیل
شد» green / «در راه»); expanded line items visually split into the
received part (رسید شده ✓ + date + target warehouse from the receipt
allocations) and the in-transit remainder — quantities always sum to the
original line (invariant D holds, display-only split)
- bug2: 8-topic grids (suppliers/wizard/units) now come from
/material-categories via the store (new lib/topics.ts; fixed the mismatched
«ابزار و تجهیزات ساخت» label); suppliers topic->category resolution no
longer falls back to an arbitrary category; duplicate month/status lists
reuse the shared dictionaries; TopicGrid gained a loading EmptyState
- bug3: hub-and-spoke — the tab strip renders only on the warehouse
dashboard; sub-views hide it and navigate back via «بازگشت به داشبورد»;
«افزایش موجود» became the «تغییر موجودی» entry button
- bug4: stock count goes through a confirmation modal (current vs counted
vs variance with کسری/مازاد badges) before posting STOCK_COUNT; numbers
parsed defensively
- bug5: found qty is capped client-side (red input + inline warning, submit
disabled) and backend returns 422 when exceeding the missing balance;
fully-recovered losses drop off the pending list
- bug6+7: quantities render as absolute values with semantic color coding
(emerald inflow / rose outflow / blue neutral) across dashboard timeline,
daily control and the change-inventory form