Redesign product detail page and fix icon/cart reactivity bugs

- SingleProduct.vue: rebuild gallery/header/action bar as a self-scrolling
  layout with a sticky photo, solid-on-scroll header matching PageBar, and
  a full-screen image preview (blurred overlay, centered thumbnail strip)
- Add GallerySlider.vue: pointer-based swipe carousel isolated in an
  LTR subtree, fixing RTL/transform sign mismatch that caused slide jumps
- Fix Icon.vue: icon was read into a plain ref once at setup and never
  updated on prop change; switch to computed so icon swaps (e.g. cart
  qty stepper trash/minus toggle) actually re-render
- Fix quantity stepper DOM order in SingleProduct.vue/CartItem.vue so
  plus/minus render correctly under RTL flex
- prisma/assign-downloaded-images.js: seed real product photos (FEATURED/
  FEATURED_MOBILE/GALLERY/GALLERY_MOBILE) onto the 5 placeholder products
This commit is contained in:
s.esmaeili
2026-09-18 16:22:31 +03:30
parent 53a304b5d5
commit b80fa9bcfb
73 changed files with 1035 additions and 180 deletions
+10
View File
@@ -42,6 +42,16 @@ ax.interceptors.request.use(
} else {
delete config.headers['Authorization'];
}
// The instance-level default Content-Type is 'application/json', and axios
// only auto-sets multipart/form-data + boundary when no Content-Type is
// already present — an existing default is NOT replaced. Posting a
// FormData body (file uploads) with the JSON default left in place sends
// the raw FormData object as a JSON-labelled body, so multer/NestJS's
// FileInterceptor sees no file at all and 400s. Let axios/the browser set
// the correct multipart boundary for FormData bodies instead.
if (config.data instanceof FormData) {
delete config.headers['Content-Type'];
}
return config;
},
(error) => Promise.reject(error),