- app/components/product/ProductDescription.tsx: new below-fold section
with a "توضیحات محصول" heading, whitespace-pre-line so multi-line seller
copy (Instagram scrapes, victorwear WooCommerce imports) renders with
its bullet-list line breaks preserved. Renders on both mobile and
desktop; nothing shown when the product has no description.
- app/components/product/ProductInfo.tsx: removed the collapsed
single-<p> mobile description; the new section replaces it.
- app/components/product/ProductDetailView.tsx: pricingOf now hides the
discount when discount_price >= price (was only hiding when equal),
so a stale row where the discount price accidentally matches or
exceeds the base can never render as a fake promo. Mounts
ProductDescription just above the mobile Contact button and reviews.
- app/components/product/index.ts: export ProductDescription.
- src/api/types/models/index.ts: ProductCategory now carries readonly
parentId / parentName so the two-step category picker can build the
parent→sub tree from a flat category list without an extra fetch.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Product-page chat buttons pass the product id when starting a thread, so it's
shared into the conversation as a card the seller can see (and tap through).
- MessageBubble renders the product card (image, title, price → product page);
card-only messages no longer render an empty bubble.
- Inbox preview shows 🛍 <product> instead of "بدون پیام" for product-card
threads. ChatProductCard type + product on message/last-message types.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sellers fill a size grid (rows = sizes, columns = measurements) in the
product create/edit wizard; buyers see it via a راهنمای سایز dialog.
- SizeChartSection editor: rows seeded from the product's sizes, columns
seeded from category-aware defaults, category-specific quick-add chips
(tops→دور سینه/سرشانه/آستین, pants→دور کمر/دور باسن/فاق, shoes→سایز اروپایی,
bags→طول/عرض/ارتفاع, …), custom columns, cm/inch toggle, scrollable grid
- required-if-the-product-has-sizes gate on publish (with per-size hint);
optional otherwise so accessories/one-size and imports aren't blocked
- buyer SizeGuideDialog + راهنمای سایز link in the size selector header
- SizeChart types on ProductDetail / FullProductCreate / FullProductUpdate
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fire a fire-and-forget view event when an authenticated, non-owner user
opens a product page (deduped per product), POSTing to the new
/api/engagement/v1/views/ endpoint. Silent on failure so tracking never
disrupts browsing.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per design feedback, restructure the mobile product page (desktop layout
unchanged except color swatches):
- remove the top seller bar; the seller/brand (logo + name + ارسال پیام)
now sits in a row below the gallery.
- add a floating circular back button over the image (safe-area aware).
- move the rating out of the action row into a prominent body row, shown
only when the average rating is > 0.
- color swatches are now circles with a selection ring (shared with
desktop for consistency) instead of squares.
- make the افزودن به سبد خرید button full-width/taller with a compact
price beside it.
- the action row keeps save / share / add-to-collection / try-on.
- the red discount icon is kept as-is.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Single-product page showed basePrice with no discount while list tiles
showed the cheapest variant's discounted price. Cause: the detail view
defaulted selectedColor/selectedSize to the first in-stock color and the
first in-stock size independently — a combo that often isn't a real
variant, so no variant matched and it fell back to basePrice / no sale.
- ProductDetailView: derive a `defaultVariant` (cheapest in-stock variant
by final price, == the tile's min/discount price) and use it for the
initial selection, the initial displayed price, and the fallback when no
exact color/size combo is matched. A shared `pricingOf` helper applies
the same discount rule everywhere. Detail price now matches the tile.
- use-home-hooks: drop staleTime 5m -> 60s on the For You / discounts /
top-sellers feeds so price/discount edits show up promptly in lists.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- new store.$storeId.tsx layout: sticky admin sidebar (store/products/orders/
financial/shipping/threads/settings) beside content at lg; mobile unchanged
- MyLayout: store/* gets a full-width desktop canvas (own sidebar), no shopper
header/footer, mobile store-nav hidden at lg
- store home: hide the redundant mobile store header at lg
- ProductImageCarousel: prev/next arrows now opt-in (showArrows) so they only
appear on the product gallery, not every masonry card
Gallery (desktop):
- portrait 3/4 box, object-contain so the photo isn't cropped
- prev/next arrows on the carousel
- save (heart) overlay top-left; AI try-on button "آنلاین پرو کن" at image bottom
Info column (desktop): hide the mobile action icon row (incl. share); clean
layout — title, star rating + review count, prominent price with old/strike,
color + size, buy row (chat + add-to-cart + qty stepper), assurance cards.
Mobile keeps its existing components (ProductActions / ProductInfo / BottomBar /
ContactButton are lg:hidden).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- product: show seller (logo + name) in the desktop info column (was missing
after hiding the mobile header); action icons (save/share/collection/AI) are
now circular bordered buttons on desktop instead of a bare icon row
- collection detail: cover constrained to a 360px portrait column with
object-cover (fixes over-long image + side margins); tighter spacing
- masonry: only render the loading skeleton while actively fetching (removes
the persistent grey block before the footer); sentinel moved above it
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- ProductDetailView: gallery | info two-column grid on desktop with breadcrumb;
gallery sticky; reviews + similar products full-width below. Mobile stack
unchanged (only lg: utilities + a moved BottomBar, which is position:fixed so
its DOM location doesn't affect mobile)
- BottomBar: static inline buy card on desktop (fixed bottom bar on mobile)
- ProductInfo: larger title + tightened top spacing at lg
- MyLayout: desktop gate now includes /product/*
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>