Commit Graph

24 Commits

Author SHA1 Message Date
254fed4a99 feat(cart): mockup-style item rows + separate-shipping note
- CartItem: compact row — image + title + رنگ/سایز attribute chips
  (circular color dot) + a bottom row with the stepper and the effective
  price plus struck original. Drops the verbose label:value rows and the
  product-code line. Shared with the desktop detail column (verified).
- cart list: add a green «ارسال جداگانه» badge per seller-cart, matching
  the mockup's per-seller grouping.

Keeps the existing list -> detail checkout flow.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 23:16:42 +03:30
e6574b1e9e feat(seller): mobile brand header redesign (cover + overlapping logo)
Bring the seller page mobile header in line with the design / desktop:
replace the plain top bar + centered logo with a cover banner, a floating
circular back button (safe-area aware), an overlapping rounded logo, the
store name + verified badge + @handle, a clean borderless stats row
(محصول / دنبال‌کننده / امتیاز), the description, and follow + message-icon
actions. Search bar and product masonry unchanged. Desktop untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 21:44:20 +03:30
252d3f8f50 feat(search/explore): home-style product tiles with seller brand chip
Bring the home product tile to search and explore: seller brand chip
(SellerChip) plus price/discount overlay, instead of a bare image.

- search: map discountPercent/discountPrice/basePrice + sellerName from
  ProductSearchResult (sellerName is already returned, so the chip shows
  now with the initial-letter fallback).
- explore: map sellerName/sellerLogo/sellerUsername (and add them to the
  Product type); these populate once the backend ProductSerializer change
  ships.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 17:09:58 +03:30
11656c2996 feat(home): seller brand chip (logo + name) on product tiles
Show the seller's brand on the home product cards, like the design:
a small logo circle + name overlaid above the title.

- new SellerChip component: renders nothing without a name; falls back to
  the seller's initial when no logo is present (e.g. before the backend
  ships seller_logo). seller_name is already returned today, so the name
  shows immediately.
- thread sellerName/sellerLogo/sellerUsername through ProductHomepage type,
  the home discounts + for-you mappings, and the MondrianProductList /
  HorizontalProductList card interfaces + overlays.

Only renders where seller data is mapped (home), so seller-page and
store-dashboard tiles are unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 16:38:44 +03:30
bac93568f5 feat(upload): convert HEIC/HEIF to JPEG on the client before preview/upload
Most browsers (everything but Safari/WebKit) can't decode HEIC in <img> or
canvas, so picking an iPhone HEIC photo broke the preview and the crop editor,
and could reach the backend in a format it couldn't process. Convert HEIC/HEIF
to JPEG right after selection via heic2any (dynamically imported, browser-only).

- new util app/utils/convert-heic.ts: isHeic() detection (MIME or extension
  when iOS reports no type) + convertHeicToJpeg()/convertHeicFiles(); never
  throws — falls back to the original file on failure.
- wired into the product image picker (store.add.manual) and the store
  logo picker (StoreForm).
- adds heic2any dependency.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 16:43:30 +03:30
b4d5f8d8db fix(ios): respect safe-area insets so chrome clears the notch/home bar
Content was drawing under the iOS status bar and home indicator because
the app uses viewport-fit=cover + black-translucent but the fixed/sticky
chrome didn't reserve the safe areas.

- bottom nav (MyLayout): move the 50px row into an inner box and let the
  bar extend by env(safe-area-inset-bottom) so icons sit above the home
  indicator (previously the fixed height clipped the inset padding).
- top headers gain env(safe-area-inset-top): HomePageTopBar, ExploreTopBar,
  SearchTopBar, CartHeader, ChatHeader, and wrapper-padded HeaderWithSupport
  / ProfilePagesHeader (so their absolutely-positioned buttons shift too).
- chat input pads bottom by the inset; chat scroll area height accounts for
  the taller header/input.
- _index.tsx no longer overrides the viewport meta (it was dropping
  viewport-fit=cover on the home page); the global one in root.tsx wins.

env(safe-area-inset-*) is 0 on non-notch devices, so desktop/Android render
identically — only iOS gains the padding.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 13:42:51 +03:30
fef53fd003 feat(notifications): web push opt-in + unread nav badges
Surfaces three events without a full notification center:
- service worker (public/sw.js) gains push + notificationclick handlers
  (RTL, focuses an existing tab or opens the target URL).
- usePushNotifications hook: permission + VAPID subscribe/unsubscribe
  against the backend push endpoints.
- opt-in UI both ways: a one-time dismissible post-login banner
  (PushPermissionBanner, rendered in MyLayout) and a permanent toggle
  (PushSettingToggle) on buyer profile settings and seller store settings.
- useBadgeCounts polls /api/notif/v1/badges/; small red badges on the
  bottom-nav profile icon (chat + order updates), the profile sidebar
  (پیام‌ها / سفارش‌ها) and the seller dashboard sidebar. Visiting orders
  clears its badge.

Degrades gracefully: if the backend endpoints are absent the counts fall
back to zero and nothing throws.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 14:02:56 +03:30
257871d5f1 feat(seller-dashboard): desktop-friendly layouts for list and hub pages
Redesign mobile-style seller dashboard pages for desktop (lg:) while
leaving the mobile view unchanged:

- products: table-style header row (product/price/variant/actions) with a
  bordered card wrapper and an "add product" button; accordion rows align
  to the columns, inline price hidden on desktop.
- orders: pill-style status tabs + search on one row, orders shown as a
  two-column card grid instead of stretched full-width rows.
- financial-dashboard: three-column card grid with icon chips.
- setting: status/theme as side-by-side cards, menu items as a
  three-column card grid (logout styled in red).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 13:00:18 +03:30
4af143bccf Desktop: seller dashboard shell + gate carousel arrows to product gallery
- 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
2026-06-17 12:28:59 +03:30
207d46eefd Profile hard-guard: redirect /profile to /login when logged out
The account sub-pages were already protected via validateTokens; add a loader
on the profile index so the hub itself bounces to /login when unauthenticated.
2026-06-16 15:00:53 +03:30
030a883327 Desktop header: login/profile state + theme toggle; hide about/faq header
- header shows "ورود / ثبت نام" when logged out (no profile/cart/bookmark icons,
  so the profile tab isn't reachable) and the avatar + cart + bookmarks when
  logged in
- add the light/dark SunMoonToggle to the desktop header
- about/faq: hide their mobile HeaderWithSupport at lg (content already
  width-constrained)
2026-06-16 13:59:34 +03:30
4a7bf51572 Desktop: inline the fixed-bottom buttons on account pages
profile/location + profile/wallet "add" buttons were fixed to the viewport
bottom; make them static/inline at lg so they sit at the end of the content.
2026-06-16 12:58:51 +03:30
3156fb4204 Desktop: account area (shared sidebar) + brands list
- new profile.tsx layout: sticky desktop sidebar (user card + menu) wrapping all
  /profile/* pages; mobile renders page content only (unchanged)
- ProfilePagesHeader hidden at lg (one change covers all account sub-pages +
  cart); profile index shows a welcome on desktop (menu lives in the sidebar)
- sellers: 5-col brand grid with name overlay, contained, mobile header hidden
- MyLayout: desktop gate now covers /profile/* and /sellers
2026-06-16 12:46:22 +03:30
96034fe61a Desktop: cart checkout two-column + profile account grid
- cart checkout (/cart/$cartId): steps on the left, sticky order summary on the
  right at lg (1320px container); CartSummary becomes an inline card on desktop
  (fixed bottom bar on mobile)
- profile (/profile): contained account layout; menu becomes a 2-col card grid
  on desktop with a heading
- MyLayout: desktop gate now includes /cart/* and /profile
2026-06-16 11:19:55 +03:30
7845ab5e75 Desktop: explore page (category grid + contained layout)
- explore: hide mobile search bar at lg (global header has search); contain
  content to 1320px; category grid 2-col mobile -> 4-col desktop with taller tiles
- MyLayout: desktop gate now includes /explore
2026-06-16 11:11:46 +03:30
fa65db8804 Desktop fixes: product seller + actions, collection cover, masonry skeleton
- 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>
2026-06-14 22:59:24 +03:30
f57fe4e9d6 Desktop polish: seller header contrast, collection image crop, infinite scroll
- seller: only the logo overlaps the cover now; name/handle/stats sit below the
  cover on white (fixes low-contrast name on the gradient)
- collections (home rail, /collections grid, /collection cover): portrait 3/4
  images so full-body figures aren't cropped; detail cover uses object-contain
- MondrianProductList: add IntersectionObserver sentinel for reliable
  infinite scroll on desktop (window-scroll math missed under the footer)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 22:19:40 +03:30
cf55e16a9a Desktop: seller brand header redesign + collections list/detail
- seller: desktop brand header matching the design — cover, overlapping rounded
  logo, name + verified badge + @handle, horizontal stats, Follow/Message
  actions, description; mobile blocks hidden at lg; feed = responsive masonry
- /collections: 4-column card grid on desktop (was a stretched single column)
- /collection/<id>: two-column hero (cover + info) on desktop, contained width,
  mobile header hidden at lg; products use the responsive masonry
- MyLayout: desktop gate now includes /collections and /collection/*

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 22:00:49 +03:30
d0571f8253 Login: 6-digit OTP + desktop layout
- OTP input now 6 digits (matches backend 6-digit codes): maxLength 6, six
  slots with responsive widths, verify enabled at length === 6
- login page: centered desktop card on a neutral canvas with brand mark
- MyLayout: auth pages (/login, /logout) get full-width desktop canvas and no
  mobile bottom nav at lg (no shopping header/footer)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 21:36:42 +03:30
232f7d1b3c Desktop responsive: collections grid + seller page
- HorizontalCollectionsList: 4-column grid at lg (overrides mobile fixed-width
  cards), hide scroll arrows on desktop
- seller page: contained desktop layout, hide mobile back-header at lg, show
  store name; feed uses the responsive masonry
- MyLayout: desktop chrome gate now includes /seller/*

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 21:28:25 +03:30
9650073b04 Desktop responsive: search page, cart list, masonry grid
- MondrianProductList: add desktop 4-column masonry (mobile 2-col unchanged);
  improves home "for you", search results and seller feed at lg+
- search: hide mobile SearchTopBar at lg, add results heading + centered
  1320px container
- cart list: responsive 2-column grid of cart cards + desktop heading
- MyLayout: desktop chrome gate now covers / , /search/* and /cart

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 21:06:34 +03:30
e1c5899002 Add responsive desktop layout for home page
Single responsive tree (Tailwind lg:) — mobile experience unchanged; desktop
chrome is gated to the home route for now.

- DesktopHeader / DesktopFooter components (visible only at lg+), wired to
  real routes with live cart badge and working search
- MyLayout: render desktop header/footer on home, expand container and hide
  mobile bottom nav at lg
- Home: hide mobile top bar at lg, 1320px centered container, desktop hero
  grid (carousel + 2 promos), larger section headers
- SellerTilesGrid: 2-col mobile -> 5-col desktop with name overlay

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 20:07:47 +03:30
485f8d460a Security fixes: session hardening, open redirect, SSR path injection
- sessions: require REMIX_SECRET in prod (no "secret" fallback); base Secure
  cookie on NODE_ENV; add maxAge
- login: safeRedirect() blocks open-redirect via redirectTo (loader + action)
- SSR loaders: encodeURIComponent on user path params before internal API
  fetch (product, store product, seller)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 19:02:11 +03:30
0293655fc1 first 2026-04-29 01:44:16 +03:30