fix(user-app): rebuild product gallery with fullscreen preview, fix icon reactivity bug

- Extract product image gallery into a dedicated GallerySlider component
  with swipe/tap support
- Add a teleported fullscreen image preview (tap to open, thumbnail strip,
  body scroll lock) to SingleProduct
- Restore the Trust section that was accidentally commented out
- Swap back/favorite button positions and recenter the image counter
- Fix Icon.vue: tempIcon was a static ref set once at setup, so it never
  updated on prop change when Vue reused the component instance (e.g. cart
  qty steppers toggling trash/minus icons); switched to computed + watch
- Rename brand text from "منتزر" to "هنزاگلد"
- Fix a CSS typo in user-app-v2 SingleProduct (rgba alpha value)
- Rebuild dist assets
This commit is contained in:
s.esmaeili
2026-09-18 19:54:26 +03:30
parent 062fe80a68
commit e8c67bead0
52 changed files with 573 additions and 86 deletions
@@ -802,7 +802,7 @@ onBeforeUnmount(() => {
border-radius: 12px;
cursor: pointer;
color: #fff;
background: rgba(0, 0, 0, 0.4);
background: rgba(0, 0, 0, 0.35);
backdrop-filter: blur(10px);
transform: rotate(45deg);
transition: transform 0.18s ease, background 0.18s ease;
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{d as f,o as v,c as s,e,w as u,j as m,l as p,g as o,F as g,r as y,I as P,b as k,f as C,q as b,J as x,s as h,_ as w}from"./index-CtDx9pmc.js";import{P as B}from"./PageBar-5aeeoH1Q.js";import{a as V}from"./Spinner.vue_vue_type_style_index_0_lang-DJDyZ-LG.js";import{S as I}from"./SectionHead-B3LfQC4D.js";import{P as N}from"./ProductCard-BhW6Xyov.js";import{a as q}from"./client-WIBW0tF5.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./SingleProduct-BoiPvnnl.js";import"./NotifyVant.vue_vue_type_script_setup_true_lang-BsRikX3M.js";import"./DialogVant.vue_vue_type_style_index_0_lang-Cn78wyzA.js";import"./cartStore-BvHQLfZ8.js";import"./dialogEmpty1-E3h_JfwQ.js";import"./index-B698smgh.js";import"./classCallCheck-DCKKMDGE.js";const F={class:"coll"},S={key:0,class:"coll__grid"},j={key:1,class:"coll__empty"},z=f({__name:"CollectionView",setup(E){const l=x(),t=m(!1),n=m([]),d=p(()=>l.query.page||"مجموعه"),r=p(()=>n.value.filter(i=>i.collections.some(a=>a.collectionId===l.params.id)));return v(async()=>{t.value=!0;try{n.value=await q.listProducts()}finally{t.value=!1}}),(i,a)=>{const _=b("container");return o(),s("div",F,[e(B,{title:d.value,"back-to":"search"},null,8,["title"]),e(V,{spinning:t.value,tip:"درحال دریافت اطلاعات"},{default:u(()=>[e(_,{class:"coll__body"},{default:u(()=>[e(I,{title:"محصولات این مجموعه",subtitle:"برای دیدن جزئیات، روی محصول ضربه بزنید"}),r.value.length?(o(),s("div",S,[(o(!0),s(g,null,y(r.value,c=>(o(),h(N,{key:c.id,value:c},null,8,["value"]))),128))])):t.value?C("",!0):(o(),s("section",j,[e(P,{icon:"vuesax-linear:box",size:"26"}),a[0]||(a[0]=k("p",null,"در این مجموعه محصولی ثبت نشده است.",-1))]))]),_:1})]),_:1},8,["spinning"])])}}}),W=w(z,[["__scopeId","data-v-4e05d52b"]]);export{W as default};
import{d as f,o as v,c as s,e,w as u,j as m,l as p,g as o,F as g,r as y,I as P,b as k,f as C,q as b,J as x,s as h,_ as w}from"./index-CGo5tz1H.js";import{P as B}from"./PageBar-B7OwbOZ2.js";import{a as V}from"./Spinner.vue_vue_type_style_index_0_lang-OVIFoXDj.js";import{S as I}from"./SectionHead-CxJqY2Fp.js";import{P as N}from"./ProductCard-BRjA425s.js";import{a as q}from"./client-WIBW0tF5.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./SingleProduct-Bwwg0fYN.js";import"./NotifyVant.vue_vue_type_script_setup_true_lang-Dp9GLLVy.js";import"./DialogVant.vue_vue_type_style_index_0_lang-dNck8nuH.js";import"./cartStore-C7cRUw47.js";import"./dialogEmpty1-Caw7F5KL.js";import"./index-BmmdHz27.js";import"./classCallCheck-Bw9dWuSE.js";const F={class:"coll"},S={key:0,class:"coll__grid"},j={key:1,class:"coll__empty"},z=f({__name:"CollectionView",setup(E){const l=x(),t=m(!1),n=m([]),d=p(()=>l.query.page||"مجموعه"),r=p(()=>n.value.filter(i=>i.collections.some(a=>a.collectionId===l.params.id)));return v(async()=>{t.value=!0;try{n.value=await q.listProducts()}finally{t.value=!1}}),(i,a)=>{const _=b("container");return o(),s("div",F,[e(B,{title:d.value,"back-to":"search"},null,8,["title"]),e(V,{spinning:t.value,tip:"درحال دریافت اطلاعات"},{default:u(()=>[e(_,{class:"coll__body"},{default:u(()=>[e(I,{title:"محصولات این مجموعه",subtitle:"برای دیدن جزئیات، روی محصول ضربه بزنید"}),r.value.length?(o(),s("div",S,[(o(!0),s(g,null,y(r.value,c=>(o(),h(N,{key:c.id,value:c},null,8,["value"]))),128))])):t.value?C("",!0):(o(),s("section",j,[e(P,{icon:"vuesax-linear:box",size:"26"}),a[0]||(a[0]=k("p",null,"در این مجموعه محصولی ثبت نشده است.",-1))]))]),_:1})]),_:1},8,["spinning"])])}}}),W=w(z,[["__scopeId","data-v-4e05d52b"]]);export{W as default};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{d as l,s as n,w as r,u as d,aj as c,g as x,b as t,B as o,i as a,t as i}from"./index-CtDx9pmc.js";const f={class:"my-4"},u={class:"w-full flex justify-center"},m={class:"w-full flex justify-center text-[18px] font-semibold"},_={class:"grid grid-cols-2 border-t border-solid border-[#E5E7EB] pt-4 mx-2 mt-6 font-semibold text-[15px]"},p=l({__name:"DialogVant",props:{timeOut:{},text1:{},text2:{},text3:{}},setup(e){return(s,b)=>(x(),n(d(c),null,{default:r(()=>[t("div",f,[t("div",u,[o(s.$slots,"img",{},()=>[a(i(e.text2),1)])]),t("div",m,[o(s.$slots,"title",{},()=>[a(i(e.text1),1)])]),t("div",_,[o(s.$slots,"button",{},()=>[a(i(e.text3),1)])])])]),_:3}))}});export{p as _};
import{d as l,s as n,w as r,u as d,am as c,g as x,b as t,B as o,i as a,t as i}from"./index-CGo5tz1H.js";const f={class:"my-4"},m={class:"w-full flex justify-center"},u={class:"w-full flex justify-center text-[18px] font-semibold"},_={class:"grid grid-cols-2 border-t border-solid border-[#E5E7EB] pt-4 mx-2 mt-6 font-semibold text-[15px]"},p=l({__name:"DialogVant",props:{timeOut:{},text1:{},text2:{},text3:{}},setup(e){return(s,b)=>(x(),n(d(c),null,{default:r(()=>[t("div",f,[t("div",m,[o(s.$slots,"img",{},()=>[a(i(e.text2),1)])]),t("div",u,[o(s.$slots,"title",{},()=>[a(i(e.text1),1)])]),t("div",_,[o(s.$slots,"button",{},()=>[a(i(e.text3),1)])])])]),_:3}))}});export{p as _};
@@ -1 +1 @@
import{d as v,o as b,c as o,e,w as c,j as m,g as t,F as p,b as i,r as g,I as y,u as k,f as P,x as h,l as C,q as x,s as F,_ as w}from"./index-CtDx9pmc.js";import{P as B}from"./PageBar-5aeeoH1Q.js";import{a as V}from"./Spinner.vue_vue_type_style_index_0_lang-DJDyZ-LG.js";import{S}from"./SectionHead-B3LfQC4D.js";import{P as I}from"./ProductCard-BhW6Xyov.js";import{u as N}from"./SingleProduct-BoiPvnnl.js";import{a as $}from"./client-WIBW0tF5.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./cartStore-BvHQLfZ8.js";import"./index-B698smgh.js";import"./classCallCheck-DCKKMDGE.js";import"./NotifyVant.vue_vue_type_script_setup_true_lang-BsRikX3M.js";import"./DialogVant.vue_vue_type_style_index_0_lang-Cn78wyzA.js";import"./dialogEmpty1-E3h_JfwQ.js";const R={class:"favs"},j={class:"favs__grid"},q={key:1,class:"favs__empty"},z=v({__name:"FavoritesView",setup(E){const d=h(),_=N(),a=m(!1),l=m([]),r=C(()=>l.value.filter(u=>_.isFavorite(u.id)));return b(async()=>{a.value=!0;try{l.value=await $.listProducts()}finally{a.value=!1}}),(u,s)=>{const f=x("container");return t(),o("div",R,[e(B,{title:"علاقه‌مندی","back-to":"userPage::hasSubRoute"}),e(V,{spinning:a.value,tip:"در حال دریافت اطلاعات"},{default:c(()=>[e(f,{class:"favs__body"},{default:c(()=>[r.value.length?(t(),o(p,{key:0},[e(S,{title:"ذخیره‌شده‌ها",subtitle:`${r.value.length} محصول`},null,8,["subtitle"]),i("div",j,[(t(!0),o(p,null,g(r.value,n=>(t(),F(I,{key:n.id,value:n},null,8,["value"]))),128))])],64)):a.value?P("",!0):(t(),o("section",q,[e(y,{icon:"vuesax-linear:heart",size:"26"}),s[1]||(s[1]=i("p",null,"هنوز محصولی را به علاقه‌مندی‌ها اضافه نکرده‌اید.",-1)),i("button",{type:"button",class:"favs__emptyCta",onClick:s[0]||(s[0]=n=>k(d).push({name:"home"}))}," دیدن محصولات ")]))]),_:1})]),_:1},8,["spinning"])])}}}),Y=w(z,[["__scopeId","data-v-93bb7c6a"]]);export{Y as default};
import{d as v,o as b,c as o,e,w as c,j as m,g as t,F as p,b as i,r as g,I as y,u as k,f as P,x as h,l as C,q as x,s as F,_ as w}from"./index-CGo5tz1H.js";import{P as B}from"./PageBar-B7OwbOZ2.js";import{a as V}from"./Spinner.vue_vue_type_style_index_0_lang-OVIFoXDj.js";import{S}from"./SectionHead-CxJqY2Fp.js";import{P as I}from"./ProductCard-BRjA425s.js";import{u as N}from"./SingleProduct-Bwwg0fYN.js";import{a as $}from"./client-WIBW0tF5.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./cartStore-C7cRUw47.js";import"./index-BmmdHz27.js";import"./classCallCheck-Bw9dWuSE.js";import"./NotifyVant.vue_vue_type_script_setup_true_lang-Dp9GLLVy.js";import"./DialogVant.vue_vue_type_style_index_0_lang-dNck8nuH.js";import"./dialogEmpty1-Caw7F5KL.js";const R={class:"favs"},j={class:"favs__grid"},q={key:1,class:"favs__empty"},z=v({__name:"FavoritesView",setup(E){const d=h(),_=N(),a=m(!1),l=m([]),r=C(()=>l.value.filter(u=>_.isFavorite(u.id)));return b(async()=>{a.value=!0;try{l.value=await $.listProducts()}finally{a.value=!1}}),(u,s)=>{const f=x("container");return t(),o("div",R,[e(B,{title:"علاقه‌مندی","back-to":"userPage::hasSubRoute"}),e(V,{spinning:a.value,tip:"در حال دریافت اطلاعات"},{default:c(()=>[e(f,{class:"favs__body"},{default:c(()=>[r.value.length?(t(),o(p,{key:0},[e(S,{title:"ذخیره‌شده‌ها",subtitle:`${r.value.length} محصول`},null,8,["subtitle"]),i("div",j,[(t(!0),o(p,null,g(r.value,n=>(t(),F(I,{key:n.id,value:n},null,8,["value"]))),128))])],64)):a.value?P("",!0):(t(),o("section",q,[e(y,{icon:"vuesax-linear:heart",size:"26"}),s[1]||(s[1]=i("p",null,"هنوز محصولی را به علاقه‌مندی‌ها اضافه نکرده‌اید.",-1)),i("button",{type:"button",class:"favs__emptyCta",onClick:s[0]||(s[0]=n=>k(d).push({name:"home"}))}," دیدن محصولات ")]))]),_:1})]),_:1},8,["spinning"])])}}}),Y=w(z,[["__scopeId","data-v-93bb7c6a"]]);export{Y as default};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-1
View File
@@ -1 +0,0 @@
import{P as x}from"./PageBar-5aeeoH1Q.js";import{E as P,a as _}from"./Spinner.vue_vue_type_style_index_0_lang-DJDyZ-LG.js";import{S}from"./SectionHead-B3LfQC4D.js";import{P as k}from"./ProductCard-BhW6Xyov.js";import{d,g as n,c as l,e as o,u as c,y as b,z as B,A as E,B as C,s as v,f as y,j as u,C as L,D as A,w as p,F as $,r as F,l as N,q as V,_ as D}from"./index-CtDx9pmc.js";import{a as I}from"./client-WIBW0tF5.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./SingleProduct-BoiPvnnl.js";import"./NotifyVant.vue_vue_type_script_setup_true_lang-BsRikX3M.js";import"./DialogVant.vue_vue_type_style_index_0_lang-Cn78wyzA.js";import"./cartStore-BvHQLfZ8.js";import"./dialogEmpty1-E3h_JfwQ.js";import"./index-B698smgh.js";import"./classCallCheck-DCKKMDGE.js";const j={class:"flex justify-center items-center empty"},z=d({__name:"EmptyState",props:{description:{},image:{}},setup(t){return(e,a)=>(n(),l("div",j,[o(c(P),{description:"موردی یافت نشد",image:t.image,class:"h-[200px] w-[200px] opacity-70"},null,8,["image"])]))}}),H="/assets/favoritEmpty-kbtPAdi5.svg",T=d({__name:"ScrollFetchSearch",props:{loading:{type:Boolean},flag:{type:Boolean},padding:{}},emits:["fetch"],setup(t,{emit:e}){const a=e,r=b(),s=u(null);return B(s,()=>{a("fetch")},{distance:50}),(i,m)=>(n(),l("main",{class:"flex flex-col flex-1 overflow-auto no-scrollbar w-[100vw] max-w-screen-md m-auto",style:E({paddingTop:t.padding||c(r).headerHeight+"px"}),ref_key:"scrollArea",ref:s},[C(i.$slots,"default"),o(_,{cls:"my-[10px]",spinning:t.loading,indicator:!0,tip:"درحال دریافت اطلاعات"},null,8,["spinning"]),t.flag?(n(),v(z,{key:0,image:c(H)},null,8,["image"])):y("",!0)],4))}});function q(){const t=L({totalPages:0,productList:[],flag:!1});return{productsData:t,getProducts:async(a,r=!1)=>{if(!r){a.value=!0;try{t.productList=await I.listProducts(),t.flag=t.productList.length<1}catch(s){console.log(s)}finally{a.value=!1}}}}}const G={class:"newest"},M={key:0,class:"newest__grid"},g=20,Z=d({__name:"NewestView",setup(t){const{productsData:e,getProducts:a}=q(),r=u(!1),s=u(!1),i=u(g),m=N(()=>e.productList.slice(0,i.value));A(async()=>{await a(r,!1)});const h=async()=>{if(i.value<e.productList.length){i.value+=g;return}await a(s,!0)};return(J,K)=>{const w=V("container");return n(),l("div",G,[o(x,{title:"جدیدترین محصولات","back-to":"home"}),o(_,{spinning:r.value,tip:"درحال دریافت اطلاعات"},{default:p(()=>[o(T,{class:"newest__scroll",loading:s.value,flag:c(e).flag,padding:"0px",onFetch:h},{default:p(()=>[o(w,{class:"newest__body"},{default:p(()=>[o(S,{title:"تازه‌ها",subtitle:"آخرین افزوده‌های مجموعه"}),c(e).productList.length?(n(),l("div",M,[(n(!0),l($,null,F(m.value,f=>(n(),v(k,{key:f.id,value:f},null,8,["value"]))),128))])):y("",!0)]),_:1})]),_:1},8,["loading","flag"])]),_:1},8,["spinning"])])}}}),it=D(Z,[["__scopeId","data-v-62cb523e"]]);export{it as default};
+1
View File
@@ -0,0 +1 @@
import{P as x}from"./PageBar-B7OwbOZ2.js";import{E as P,a as _}from"./Spinner.vue_vue_type_style_index_0_lang-OVIFoXDj.js";import{S}from"./SectionHead-CxJqY2Fp.js";import{P as k}from"./ProductCard-BRjA425s.js";import{d,g as n,c as l,e as o,u as c,y as B,z as C,A as E,B as b,s as v,f as y,j as u,C as L,D as $,w as p,F as A,r as F,l as I,q as N,_ as V}from"./index-CGo5tz1H.js";import{a as D}from"./client-WIBW0tF5.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./SingleProduct-Bwwg0fYN.js";import"./NotifyVant.vue_vue_type_script_setup_true_lang-Dp9GLLVy.js";import"./DialogVant.vue_vue_type_style_index_0_lang-dNck8nuH.js";import"./cartStore-C7cRUw47.js";import"./dialogEmpty1-Caw7F5KL.js";import"./index-BmmdHz27.js";import"./classCallCheck-Bw9dWuSE.js";const j={class:"flex justify-center items-center empty"},q=d({__name:"EmptyState",props:{description:{},image:{}},setup(t){return(e,a)=>(n(),l("div",j,[o(c(P),{description:"موردی یافت نشد",image:t.image,class:"h-[200px] w-[200px] opacity-70"},null,8,["image"])]))}}),z="/assets/favoritEmpty-CIK7qR49.svg",H=d({__name:"ScrollFetchSearch",props:{loading:{type:Boolean},flag:{type:Boolean},padding:{}},emits:["fetch"],setup(t,{emit:e}){const a=e,r=B(),s=u(null);return C(s,()=>{a("fetch")},{distance:50}),(i,m)=>(n(),l("main",{class:"flex flex-col flex-1 overflow-auto no-scrollbar w-[100vw] max-w-screen-md m-auto",style:E({paddingTop:t.padding||c(r).headerHeight+"px"}),ref_key:"scrollArea",ref:s},[b(i.$slots,"default"),o(_,{cls:"my-[10px]",spinning:t.loading,indicator:!0,tip:"درحال دریافت اطلاعات"},null,8,["spinning"]),t.flag?(n(),v(q,{key:0,image:c(z)},null,8,["image"])):y("",!0)],4))}});function T(){const t=L({totalPages:0,productList:[],flag:!1});return{productsData:t,getProducts:async(a,r=!1)=>{if(!r){a.value=!0;try{t.productList=await D.listProducts(),t.flag=t.productList.length<1}catch(s){console.log(s)}finally{a.value=!1}}}}}const G={class:"newest"},K={key:0,class:"newest__grid"},g=20,M=d({__name:"NewestView",setup(t){const{productsData:e,getProducts:a}=T(),r=u(!1),s=u(!1),i=u(g),m=I(()=>e.productList.slice(0,i.value));$(async()=>{await a(r,!1)});const h=async()=>{if(i.value<e.productList.length){i.value+=g;return}await a(s,!0)};return(R,Z)=>{const w=N("container");return n(),l("div",G,[o(x,{title:"جدیدترین محصولات","back-to":"home"}),o(_,{spinning:r.value,tip:"درحال دریافت اطلاعات"},{default:p(()=>[o(H,{class:"newest__scroll",loading:s.value,flag:c(e).flag,padding:"0px",onFetch:h},{default:p(()=>[o(w,{class:"newest__body"},{default:p(()=>[o(S,{title:"تازه‌ها",subtitle:"آخرین افزوده‌های مجموعه"}),c(e).productList.length?(n(),l("div",K,[(n(!0),l(A,null,F(m.value,f=>(n(),v(k,{key:f.id,value:f},null,8,["value"]))),128))])):y("",!0)]),_:1})]),_:1},8,["loading","flag"])]),_:1},8,["spinning"])])}}}),it=V(M,[["__scopeId","data-v-62cb523e"]]);export{it as default};
@@ -1 +1 @@
import{d as a,c as n,e as o,w as i,q as c,g as _,b as e,I as r,_ as p}from"./index-CtDx9pmc.js";import{P as d}from"./PageBar-5aeeoH1Q.js";const f={class:"notif"},l={class:"notif__empty"},m=a({__name:"NotificationsView",setup(u){return(x,t)=>{const s=c("container");return _(),n("div",f,[o(d,{title:"اعلان‌ها","back-to":"home"}),o(s,{class:"notif__body"},{default:i(()=>[e("section",l,[o(r,{icon:"vuesax-linear:notification",size:"26"}),t[0]||(t[0]=e("p",null,"اعلانی برای نمایش وجود ندارد.",-1))])]),_:1})])}}}),B=p(m,[["__scopeId","data-v-44d0c9a5"]]);export{B as default};
import{d as a,c as n,e as o,w as i,q as c,g as _,b as e,I as r,_ as p}from"./index-CGo5tz1H.js";import{P as d}from"./PageBar-B7OwbOZ2.js";const f={class:"notif"},l={class:"notif__empty"},m=a({__name:"NotificationsView",setup(u){return(x,t)=>{const s=c("container");return _(),n("div",f,[o(d,{title:"اعلان‌ها","back-to":"home"}),o(s,{class:"notif__body"},{default:i(()=>[e("section",l,[o(r,{icon:"vuesax-linear:notification",size:"26"}),t[0]||(t[0]=e("p",null,"اعلانی برای نمایش وجود ندارد.",-1))])]),_:1})])}}}),B=p(m,[["__scopeId","data-v-44d0c9a5"]]);export{B as default};
@@ -1 +0,0 @@
import{d as r,e as n,ac as p,ad as f,ae as h,af as w,ag as y,ah as g,a4 as x,ai as i,a3 as k,ab as N,G as S,g as V,c as v,u as P,A as b,w as B,b as l,I as _,B as I,i as z,t as C,f as O,j as T}from"./index-CtDx9pmc.js";const[U,j]=k("notify"),A=["lockScroll","position","show","teleport","zIndex"],D=w({},y,{type:i("danger"),color:String,message:x,position:i("top"),className:g,background:String,lockScroll:Boolean});var E=r({name:U,props:D,emits:["update:show"],setup(e,{emit:o,slots:t}){const a=s=>o("update:show",s);return()=>n(h,p({class:[j([e.type]),e.className],style:{color:e.color,background:e.background},overlay:!1,duration:.2,"onUpdate:show":a},f(e,A)),{default:()=>[t.default?t.default():e.message]})}});const G=N(E),$={key:0,class:"flex"},q={class:"w-full text-white my-2"},F={class:"w-full flex content-end"},J=r({__name:"NotifyVant",props:{modelValue:{type:Boolean},timeOut:{},text:{},color:{}},emits:["update:modelValue"],setup(e,{emit:o}){const t=T(!0),a=e,s=o;S(()=>a.modelValue,()=>{a.timeOut!==-1&&u()});const u=()=>{setTimeout(()=>{s("update:modelValue",!1)},a.timeOut)};return(d,c)=>e.modelValue?(V(),v("div",$,[n(P(G),{show:t.value,"onUpdate:show":c[0]||(c[0]=m=>t.value=m),style:b(e.color)},{default:B(()=>[l("div",q,[l("div",F,[n(_,{icon:"vuesax-linear:info-circle",class:"ml-[20px] text-white",size:"25"}),l("div",null,[I(d.$slots,"default",{},()=>[z(C(e.text),1)])])])])]),_:3},8,["show","style"])])):O("",!0)}});export{J as _};
@@ -0,0 +1 @@
import{d as r,e as n,af as p,ag as f,ah as h,ai as w,aj as y,ak as g,a4 as x,al as c,a3 as k,ab as N,G as S,g as V,c as v,u as P,A as b,w as B,b as l,I as _,B as I,i as z,t as C,f as O,j}from"./index-CGo5tz1H.js";const[T,U]=k("notify"),A=["lockScroll","position","show","teleport","zIndex"],D=w({},y,{type:c("danger"),color:String,message:x,position:c("top"),className:g,background:String,lockScroll:Boolean});var E=r({name:T,props:D,emits:["update:show"],setup(e,{emit:o,slots:t}){const a=s=>o("update:show",s);return()=>n(h,p({class:[U([e.type]),e.className],style:{color:e.color,background:e.background},overlay:!1,duration:.2,"onUpdate:show":a},f(e,A)),{default:()=>[t.default?t.default():e.message]})}});const G=N(E),$={key:0,class:"flex"},q={class:"w-full text-white my-2"},F={class:"w-full flex content-end"},J=r({__name:"NotifyVant",props:{modelValue:{type:Boolean},timeOut:{},text:{},color:{}},emits:["update:modelValue"],setup(e,{emit:o}){const t=j(!0),a=e,s=o;S(()=>a.modelValue,()=>{a.timeOut!==-1&&u()});const u=()=>{setTimeout(()=>{s("update:modelValue",!1)},a.timeOut)};return(d,i)=>e.modelValue?(V(),v("div",$,[n(P(G),{show:t.value,"onUpdate:show":i[0]||(i[0]=m=>t.value=m),style:b(e.color)},{default:B(()=>[l("div",q,[l("div",F,[n(_,{icon:"vuesax-linear:info-circle",class:"ml-[20px] text-white",size:"25"}),l("div",null,[I(d.$slots,"default",{},()=>[z(C(e.text),1)])])])])]),_:3},8,["show","style"])])):O("",!0)}});export{J as _};
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{d as _,c as s,b as a,e as d,I as b,t as u,B as i,g as t,x as p,_ as k}from"./index-CtDx9pmc.js";const h={class:"bar"},f={class:"bar__inner"},B={key:1,class:"bar__spacer","aria-hidden":"true"},g={class:"bar__title"},m={class:"bar__trailing"},v=_({__name:"PageBar",props:{title:{},back:{type:Boolean,default:!0},backTo:{}},setup(e){const o=e,r=p();function l(){o.backTo?r.push({name:o.backTo}):r.back()}return(n,c)=>(t(),s("header",h,[a("div",f,[e.back?(t(),s("button",{key:0,type:"button",class:"bar__btn","aria-label":"بازگشت",onClick:l},[d(b,{icon:"vuesax-linear:arrow-right-1",size:"20"})])):(t(),s("span",B)),a("h1",g,u(e.title),1),a("div",m,[i(n.$slots,"trailing",{},()=>[c[0]||(c[0]=a("span",{class:"bar__spacer","aria-hidden":"true"},null,-1))],!0)])]),i(n.$slots,"below",{},void 0,!0)]))}}),x=k(v,[["__scopeId","data-v-d2d3dfeb"]]);export{x as P};
import{d as _,c as s,b as a,e as d,I as b,t as u,B as i,g as t,x as p,_ as k}from"./index-CGo5tz1H.js";const h={class:"bar"},f={class:"bar__inner"},B={key:1,class:"bar__spacer","aria-hidden":"true"},g={class:"bar__title"},m={class:"bar__trailing"},v=_({__name:"PageBar",props:{title:{},back:{type:Boolean,default:!0},backTo:{}},setup(e){const o=e,r=p();function l(){o.backTo?r.push({name:o.backTo}):r.back()}return(n,c)=>(t(),s("header",h,[a("div",f,[e.back?(t(),s("button",{key:0,type:"button",class:"bar__btn","aria-label":"بازگشت",onClick:l},[d(b,{icon:"vuesax-linear:arrow-right-1",size:"20"})])):(t(),s("span",B)),a("h1",g,u(e.title),1),a("div",m,[i(n.$slots,"trailing",{},()=>[c[0]||(c[0]=a("span",{class:"bar__spacer","aria-hidden":"true"},null,-1))],!0)])]),i(n.$slots,"below",{},void 0,!0)]))}}),x=k(v,[["__scopeId","data-v-d2d3dfeb"]]);export{x as P};
@@ -1 +1 @@
import{d as D,m as P,g as s,c as i,F as S,b as t,u as e,h as z,e as _,I as f,k as B,n as I,f as d,t as u,w as N,s as V,j as E,l as $,_ as j}from"./index-CtDx9pmc.js";import{u as q,S as L}from"./SingleProduct-BoiPvnnl.js";import{u as M}from"./cartStore-BvHQLfZ8.js";import{D as O}from"./index-B698smgh.js";const U={class:"pc__art"},A=["alt"],G={key:1,class:"pc__artEmpty","aria-hidden":"true"},H=["aria-label"],J={key:2,class:"pc__flag"},K={key:3,class:"pc__flag pc__flag--soft"},Q={class:"pc__body"},R={class:"pc__title"},T={class:"pc__meta"},W={class:"pc__weight"},X={key:0,class:"pc__wage"},Y=D({__name:"ProductCard",props:{value:{}},setup(g){const h=g,n=q(),{image:p,id:a,title:v,min_gram:y,wage:m,is_exist:b,qty:k,isPreOrder:w}=M(h.value),l=E(!1);function x(){l.value=!0}const C=$(()=>{const r=m.value;return r==null?"":r%1===0?String(r):r.toFixed(2)});return(r,o)=>{const F=P("lazy");return s(),i(S,null,[t("article",{class:"pc",onClick:x},[t("div",U,[e(p)?z((s(),i("img",{key:0,alt:e(v)},null,8,A)),[[F,e(p)]]):(s(),i("div",G,[_(f,{icon:"vuesax-linear:diamonds",size:"26"})])),t("button",{type:"button",class:I(["pc__fav",{"is-on":e(n).isFavorite(e(a))}]),"aria-label":e(n).isFavorite(e(a))?"حذف از علاقه‌مندی":"افزودن به علاقه‌مندی",onClick:o[0]||(o[0]=B(c=>e(n).toggle(e(a)),["stop"]))},[_(f,{icon:e(n).isFavorite(e(a))?"vuesax-linear:heart-fill":"vuesax-linear:heart",size:"16"},null,8,["icon"])],10,H),e(b)?e(w)&&e(k)===0?(s(),i("span",K,"پیش‌سفارش")):d("",!0):(s(),i("span",J,"ناموجود"))]),t("div",Q,[t("h3",R,u(e(v)),1),t("div",T,[t("span",W,u(e(y))+" گرم",1),e(m)!=null?(s(),i("span",X,"اجرت "+u(C.value)+"٪",1)):d("",!0)])])]),_(e(O),{visible:l.value,"onUpdate:visible":o[2]||(o[2]=c=>l.value=c),placement:"bottom",closable:!1,class:"rtl",height:"100vh",bodyStyle:{padding:0,position:"relative"}},{default:N(()=>[l.value?(s(),V(L,{id:e(a),key:e(a),onCloseDrawer:o[1]||(o[1]=c=>l.value=!1)},null,8,["id"])):d("",!0)]),_:1},8,["visible"])],64)}}}),ae=j(Y,[["__scopeId","data-v-5658bc04"]]);export{ae as P};
import{d as D,m as P,g as s,c as i,F as S,b as t,u as e,h as z,e as _,I as f,k as B,n as I,f as d,t as u,w as N,s as V,j as E,l as $,_ as j}from"./index-CGo5tz1H.js";import{u as q,S as L}from"./SingleProduct-Bwwg0fYN.js";import{u as M}from"./cartStore-C7cRUw47.js";import{D as O}from"./index-BmmdHz27.js";const U={class:"pc__art"},A=["alt"],G={key:1,class:"pc__artEmpty","aria-hidden":"true"},H=["aria-label"],J={key:2,class:"pc__flag"},K={key:3,class:"pc__flag pc__flag--soft"},Q={class:"pc__body"},R={class:"pc__title"},T={class:"pc__meta"},W={class:"pc__weight"},X={key:0,class:"pc__wage"},Y=D({__name:"ProductCard",props:{value:{}},setup(g){const h=g,n=q(),{image:p,id:a,title:v,min_gram:y,wage:m,is_exist:b,qty:k,isPreOrder:w}=M(h.value),l=E(!1);function x(){l.value=!0}const C=$(()=>{const r=m.value;return r==null?"":r%1===0?String(r):r.toFixed(2)});return(r,o)=>{const F=P("lazy");return s(),i(S,null,[t("article",{class:"pc",onClick:x},[t("div",U,[e(p)?z((s(),i("img",{key:0,alt:e(v)},null,8,A)),[[F,e(p)]]):(s(),i("div",G,[_(f,{icon:"vuesax-linear:diamonds",size:"26"})])),t("button",{type:"button",class:I(["pc__fav",{"is-on":e(n).isFavorite(e(a))}]),"aria-label":e(n).isFavorite(e(a))?"حذف از علاقه‌مندی":"افزودن به علاقه‌مندی",onClick:o[0]||(o[0]=B(c=>e(n).toggle(e(a)),["stop"]))},[_(f,{icon:e(n).isFavorite(e(a))?"vuesax-linear:heart-fill":"vuesax-linear:heart",size:"16"},null,8,["icon"])],10,H),e(b)?e(w)&&e(k)===0?(s(),i("span",K,"پیش‌سفارش")):d("",!0):(s(),i("span",J,"ناموجود"))]),t("div",Q,[t("h3",R,u(e(v)),1),t("div",T,[t("span",W,u(e(y))+" گرم",1),e(m)!=null?(s(),i("span",X,"اجرت "+u(C.value)+"٪",1)):d("",!0)])])]),_(e(O),{visible:l.value,"onUpdate:visible":o[2]||(o[2]=c=>l.value=c),placement:"bottom",closable:!1,class:"rtl",height:"100vh",bodyStyle:{padding:0,position:"relative"}},{default:N(()=>[l.value?(s(),V(L,{id:e(a),key:e(a),onCloseDrawer:o[1]||(o[1]=c=>l.value=!1)},null,8,["id"])):d("",!0)]),_:1},8,["visible"])],64)}}}),ae=j(Y,[["__scopeId","data-v-5658bc04"]]);export{ae as P};
@@ -1 +1 @@
import{d as I,E as S,o as E,c as a,e as l,w as y,j as p,q as V,g as i,b as e,I as f,t,f as _,n as b,l as k,_ as C}from"./index-CtDx9pmc.js";import{P as N}from"./PageBar-5aeeoH1Q.js";import{S as T}from"./SectionHead-B3LfQC4D.js";import{a as g}from"./client-WIBW0tF5.js";const h={class:"prof"},B={class:"prof__identity"},P={class:"prof__avatar","aria-hidden":"true"},x={class:"prof__name"},D={key:0,class:"prof__mobile"},w={key:0,class:"prof__block"},R={class:"prof__specs"},F={class:"prof__spec"},z={class:"prof__spec"},M={class:"prof__spec"},O={class:"prof__spec"},U={key:1,class:"prof__empty"},A=I({__name:"ProfileView",setup(L){const c={UNVERIFIED:"احراز نشده",STEP_ONE_SUBMITTED:"مرحله اول ثبت شده",STEP_TWO_SUBMITTED:"مرحله دوم ثبت شده",VERIFIED:"تایید شده"},u=S(),s=p(null),n=p(!1),v=k(()=>{var r;return((r=s.value)==null?void 0:r.verificationStep)==="VERIFIED"});return E(async()=>{if(u.customerId){n.value=!0;try{s.value=await g.getCustomer(u.customerId)}finally{n.value=!1}}}),(r,o)=>{const m=V("container");return i(),a("div",h,[l(N,{title:"اطلاعات کاربری","back-to":"userPage::hasSubRoute"}),l(m,{class:"prof__body"},{default:y(()=>{var d;return[e("section",B,[e("div",P,[l(f,{icon:"vuesax-linear:user",size:"30"})]),e("h2",x,t(((d=s.value)==null?void 0:d.fullName)??"—"),1),s.value?(i(),a("p",D,t(s.value.mobile),1)):_("",!0),s.value?(i(),a("span",{key:1,class:b(["prof__seal",v.value?"is-ok":"is-pending"])},t(c[s.value.verificationStep]??s.value.verificationStep),3)):_("",!0)]),s.value?(i(),a("section",w,[l(T,{title:"مشخصات",subtitle:"اطلاعات ثبت‌شده حساب شما"}),e("dl",R,[e("div",F,[o[0]||(o[0]=e("dt",null,"نام و نام خانوادگی",-1)),e("dd",null,t(s.value.fullName),1)]),e("div",z,[o[1]||(o[1]=e("dt",null,"تلفن همراه",-1)),e("dd",null,t(s.value.mobile),1)]),e("div",M,[o[2]||(o[2]=e("dt",null,"کد ملی",-1)),e("dd",null,t(s.value.nationalCode),1)]),e("div",O,[o[3]||(o[3]=e("dt",null,"وضعیت احراز هویت",-1)),e("dd",null,t(c[s.value.verificationStep]??s.value.verificationStep),1)])])])):n.value?_("",!0):(i(),a("section",U,[l(f,{icon:"vuesax-linear:user",size:"26"}),o[4]||(o[4]=e("p",null,"اطلاعات حساب در دسترس نیست.",-1))]))]}),_:1})])}}}),G=C(A,[["__scopeId","data-v-7c544fc5"]]);export{G as default};
import{d as I,E as S,o as E,c as a,e as l,w as y,j as p,q as V,g as i,b as e,I as f,t,f as _,n as b,l as k,_ as C}from"./index-CGo5tz1H.js";import{P as N}from"./PageBar-B7OwbOZ2.js";import{S as T}from"./SectionHead-CxJqY2Fp.js";import{a as g}from"./client-WIBW0tF5.js";const h={class:"prof"},B={class:"prof__identity"},P={class:"prof__avatar","aria-hidden":"true"},x={class:"prof__name"},D={key:0,class:"prof__mobile"},w={key:0,class:"prof__block"},R={class:"prof__specs"},F={class:"prof__spec"},z={class:"prof__spec"},M={class:"prof__spec"},O={class:"prof__spec"},U={key:1,class:"prof__empty"},A=I({__name:"ProfileView",setup(L){const c={UNVERIFIED:"احراز نشده",STEP_ONE_SUBMITTED:"مرحله اول ثبت شده",STEP_TWO_SUBMITTED:"مرحله دوم ثبت شده",VERIFIED:"تایید شده"},u=S(),s=p(null),n=p(!1),v=k(()=>{var r;return((r=s.value)==null?void 0:r.verificationStep)==="VERIFIED"});return E(async()=>{if(u.customerId){n.value=!0;try{s.value=await g.getCustomer(u.customerId)}finally{n.value=!1}}}),(r,o)=>{const m=V("container");return i(),a("div",h,[l(N,{title:"اطلاعات کاربری","back-to":"userPage::hasSubRoute"}),l(m,{class:"prof__body"},{default:y(()=>{var d;return[e("section",B,[e("div",P,[l(f,{icon:"vuesax-linear:user",size:"30"})]),e("h2",x,t(((d=s.value)==null?void 0:d.fullName)??"—"),1),s.value?(i(),a("p",D,t(s.value.mobile),1)):_("",!0),s.value?(i(),a("span",{key:1,class:b(["prof__seal",v.value?"is-ok":"is-pending"])},t(c[s.value.verificationStep]??s.value.verificationStep),3)):_("",!0)]),s.value?(i(),a("section",w,[l(T,{title:"مشخصات",subtitle:"اطلاعات ثبت‌شده حساب شما"}),e("dl",R,[e("div",F,[o[0]||(o[0]=e("dt",null,"نام و نام خانوادگی",-1)),e("dd",null,t(s.value.fullName),1)]),e("div",z,[o[1]||(o[1]=e("dt",null,"تلفن همراه",-1)),e("dd",null,t(s.value.mobile),1)]),e("div",M,[o[2]||(o[2]=e("dt",null,"کد ملی",-1)),e("dd",null,t(s.value.nationalCode),1)]),e("div",O,[o[3]||(o[3]=e("dt",null,"وضعیت احراز هویت",-1)),e("dd",null,t(c[s.value.verificationStep]??s.value.verificationStep),1)])])])):n.value?_("",!0):(i(),a("section",U,[l(f,{icon:"vuesax-linear:user",size:"26"}),o[4]||(o[4]=e("p",null,"اطلاعات حساب در دسترس نیست.",-1))]))]}),_:1})])}}}),G=C(A,[["__scopeId","data-v-7c544fc5"]]);export{G as default};
@@ -1 +1 @@
import{p as c,j as d}from"./filters-CLL9nGZ2.js";import{d as l,c as s,n as u,b as a,i as _,t as i,u as n,f as m,l as v,g as r,_ as q}from"./index-CtDx9pmc.js";const f={key:0,class:"rate-strip__value"},k={class:"rate-strip__num"},y={key:1,class:"rate-strip__value rate-strip__value--muted"},x={key:2,class:"rate-strip__time"},R=l({__name:"RateStrip",props:{quote:{}},setup(t){const o=t,p=v(()=>o.quote?o.quote.pricePerGramRial.split(".")[0]:"");return(b,e)=>(r(),s("div",{class:u(["rate-strip",{"is-empty":!t.quote}])},[e[1]||(e[1]=a("div",{class:"rate-strip__label"},[a("span",{class:"rate-strip__dot","aria-hidden":"true"}),_(" نرخ طلای ۱۸ عیار ")],-1)),t.quote?(r(),s("div",f,[a("span",k,i(n(c)(p.value)),1),e[0]||(e[0]=a("span",{class:"rate-strip__unit"},"ریال / گرم",-1))])):(r(),s("div",y,"در انتظار اعلام نرخ")),t.quote?(r(),s("div",x,i(n(d)(t.quote.quotedAt)),1)):m("",!0)],2))}}),N=q(R,[["__scopeId","data-v-16b4c8d5"]]);export{N as R};
import{p as c,j as d}from"./filters-CLL9nGZ2.js";import{d as l,c as s,n as u,b as a,i as _,t as i,u as n,f as m,l as v,g as r,_ as q}from"./index-CGo5tz1H.js";const f={key:0,class:"rate-strip__value"},k={class:"rate-strip__num"},y={key:1,class:"rate-strip__value rate-strip__value--muted"},x={key:2,class:"rate-strip__time"},R=l({__name:"RateStrip",props:{quote:{}},setup(t){const o=t,p=v(()=>o.quote?o.quote.pricePerGramRial.split(".")[0]:"");return(b,e)=>(r(),s("div",{class:u(["rate-strip",{"is-empty":!t.quote}])},[e[1]||(e[1]=a("div",{class:"rate-strip__label"},[a("span",{class:"rate-strip__dot","aria-hidden":"true"}),_(" نرخ طلای ۱۸ عیار ")],-1)),t.quote?(r(),s("div",f,[a("span",k,i(n(c)(p.value)),1),e[0]||(e[0]=a("span",{class:"rate-strip__unit"},"ریال / گرم",-1))])):(r(),s("div",y,"در انتظار اعلام نرخ")),t.quote?(r(),s("div",x,i(n(d)(t.quote.quotedAt)),1)):m("",!0)],2))}}),N=q(R,[["__scopeId","data-v-16b4c8d5"]]);export{N as R};
@@ -1 +1 @@
import{d as v,a0 as h,G as m,g as t,c as l,e as n,I as r,h as f,a1 as b,b as x,a2 as k,f as C,C as I,j as y,_ as S}from"./index-CtDx9pmc.js";const V={class:"si"},w=["placeholder"],B=v({__name:"SearchInput",props:{placeHolder:{}},emits:["search"],setup(i,{emit:d}){const c=d,a=I({clear:!1}),e=y(void 0),s=()=>{c("search",e.value)},u=()=>{e.value=void 0,a.clear=!1,c("search",void 0)},p=h(e,700);return m(p,()=>{e?a.clear=!0:a.clear=!1,s()}),(N,o)=>(t(),l("div",V,[n(r,{icon:"vuesax-linear:search-normal-1",class:"si__icon",size:"18",onClick:s}),f(x("input",{"onUpdate:modelValue":o[0]||(o[0]=_=>e.value=_),class:"si__input",placeholder:i.placeHolder,onKeyup:k(s,["enter"])},null,40,w),[[b,e.value]]),a.clear?(t(),l("button",{key:0,type:"button",class:"si__clear","aria-label":"پاک کردن",onClick:u},[n(r,{icon:"vuesax-linear:add",size:"16"})])):C("",!0)]))}}),D=S(B,[["__scopeId","data-v-4c50067a"]]);export{D as S};
import{d as v,a0 as h,G as m,g as t,c as l,e as n,I as r,h as f,a1 as b,b as x,a2 as k,f as C,C as I,j as y,_ as S}from"./index-CGo5tz1H.js";const V={class:"si"},w=["placeholder"],B=v({__name:"SearchInput",props:{placeHolder:{}},emits:["search"],setup(i,{emit:d}){const c=d,a=I({clear:!1}),e=y(void 0),s=()=>{c("search",e.value)},u=()=>{e.value=void 0,a.clear=!1,c("search",void 0)},p=h(e,700);return m(p,()=>{e?a.clear=!0:a.clear=!1,s()}),(N,o)=>(t(),l("div",V,[n(r,{icon:"vuesax-linear:search-normal-1",class:"si__icon",size:"18",onClick:s}),f(x("input",{"onUpdate:modelValue":o[0]||(o[0]=_=>e.value=_),class:"si__input",placeholder:i.placeHolder,onKeyup:k(s,["enter"])},null,40,w),[[b,e.value]]),a.clear?(t(),l("button",{key:0,type:"button",class:"si__clear","aria-label":"پاک کردن",onClick:u},[n(r,{icon:"vuesax-linear:add",size:"16"})])):C("",!0)]))}}),D=S(B,[["__scopeId","data-v-4c50067a"]]);export{D as S};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{d as r,c as t,b as o,t as s,f as n,i as _,e as d,I as u,g as a,_ as b}from"./index-CtDx9pmc.js";const m={class:"sec"},f={class:"sec__text"},x={class:"sec__title"},h={key:0,class:"sec__sub"},k=r({__name:"SectionHead",props:{title:{},subtitle:{},actionLabel:{}},emits:["action"],setup(e,{emit:i}){const l=i;return(p,c)=>(a(),t("header",m,[o("div",f,[o("h2",x,s(e.title),1),e.subtitle?(a(),t("p",h,s(e.subtitle),1)):n("",!0)]),e.actionLabel?(a(),t("button",{key:0,type:"button",class:"sec__action",onClick:c[0]||(c[0]=v=>l("action"))},[_(s(e.actionLabel)+" ",1),d(u,{icon:"vuesax-linear:arrow-left-2",size:"15"})])):n("",!0)]))}}),N=b(k,[["__scopeId","data-v-e5c65b7c"]]);export{N as S};
import{d as r,c as t,b as o,t as s,f as n,i as _,e as d,I as u,g as a,_ as b}from"./index-CGo5tz1H.js";const m={class:"sec"},f={class:"sec__text"},x={class:"sec__title"},h={key:0,class:"sec__sub"},k=r({__name:"SectionHead",props:{title:{},subtitle:{},actionLabel:{}},emits:["action"],setup(e,{emit:i}){const l=i;return(p,c)=>(a(),t("header",m,[o("div",f,[o("h2",x,s(e.title),1),e.subtitle?(a(),t("p",h,s(e.subtitle),1)):n("",!0)]),e.actionLabel?(a(),t("button",{key:0,type:"button",class:"sec__action",onClick:c[0]||(c[0]=v=>l("action"))},[_(s(e.actionLabel)+" ",1),d(u,{icon:"vuesax-linear:arrow-left-2",size:"15"})])):n("",!0)]))}}),N=b(k,[["__scopeId","data-v-e5c65b7c"]]);export{N as S};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{d as k,E as A,o as C,c as i,e as r,w as f,s as w,u as m,f as E,j as u,g as l,F as R,b as s,r as D,I as T,t as o,n as p,q as N,_ as L}from"./index-CtDx9pmc.js";import{P}from"./PageBar-5aeeoH1Q.js";import{a as M}from"./Spinner.vue_vue_type_style_index_0_lang-DJDyZ-LG.js";import{S as O}from"./SectionHead-B3LfQC4D.js";import{j as g,p as B}from"./filters-CLL9nGZ2.js";import{a as I}from"./client-WIBW0tF5.js";import{D as U}from"./index-B698smgh.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./classCallCheck-DCKKMDGE.js";const V={class:"tx"},$={class:"tx__list"},Y=["onClick"],j={class:"tx__main"},z={class:"tx__head"},F={class:"tx__kind"},G={key:0,class:"tx__note"},H={class:"tx__foot"},q={class:"tx__date"},J={key:1,class:"tx__empty"},K={class:"sheet"},Q={class:"sheet__specs"},W={class:"sheet__spec"},X={class:"sheet__spec"},Z={class:"sheet__spec"},ss={class:"sheet__spec"},es={class:"sheet__spec"},ts=k({__name:"TransactionsView",setup(os){const x={ORDER_STOCK:"سفارش",ORDER_PRE_ORDER:"سفارش ساخت",REPAYMENT_MELTED_GOLD:"طلای آب‌شده",REPAYMENT_TRANSFER:"حواله",REPAYMENT_CHEQUE:"چک",REPAYMENT_CASH:"پولی",WALLET_BONUS:"پاداش",ADJUSTMENT:"اصلاحیه"},h=A(),_=u(!1),d=u([]),v=u(!1),n=u(null),c=a=>a.direction==="CREDIT",y=a=>a.currency==="GOLD_GRAM"?`${a.amount} گرم`:`${B(a.amount)} ریال`,S=a=>{n.value=a,v.value=!0};return C(async()=>{if(h.customerId){_.value=!0;try{d.value=await I.getLedgerEntries(h.customerId)}finally{_.value=!1}}}),(a,e)=>{const b=N("container");return l(),i("div",V,[r(P,{title:"اسناد","back-to":"userPage::hasSubRoute"}),r(M,{spinning:_.value,tip:"درحال دریافت اطلاعات"},{default:f(()=>[r(b,{class:"tx__body"},{default:f(()=>[d.value.length?(l(),i(R,{key:0},[r(O,{title:"گردش حساب",subtitle:`${d.value.length} سند`},null,8,["subtitle"]),s("div",$,[(l(!0),i(R,null,D(d.value,t=>(l(),i("article",{key:t.id,class:"tx__row",onClick:ns=>S(t)},[s("span",{class:p(["tx__mark",c(t)?"is-in":"is-out"]),"aria-hidden":"true"},[r(T,{icon:c(t)?"vuesax-linear:arrow-down":"vuesax-linear:arrow-up",size:"16"},null,8,["icon"])],2),s("div",j,[s("div",z,[s("h3",F,o(x[t.sourceType]??t.sourceType),1),s("span",{class:p(["tx__amount",c(t)?"is-in":"is-out"])},o(y(t)),3)]),t.note?(l(),i("p",G,o(t.note),1)):E("",!0),s("div",H,[s("span",q,o(m(g)(t.createdAt)),1),s("span",{class:p(["tx__state",{"is-pending":!t.confirmed}])},o(t.confirmed?"تایید شده":"در انتظار تایید"),3)])])],8,Y))),128))])],64)):_.value?E("",!0):(l(),i("section",J,[r(T,{icon:"vuesax-linear:receipt-text",size:"26"}),e[1]||(e[1]=s("p",null,"سندی برای حساب شما ثبت نشده است.",-1))]))]),_:1})]),_:1},8,["spinning"]),n.value?(l(),w(m(U),{key:0,visible:v.value,"onUpdate:visible":e[0]||(e[0]=t=>v.value=t),placement:"bottom",closable:!1,height:"420px",class:"rtl",bodyStyle:{padding:0}},{default:f(()=>[s("div",K,[e[7]||(e[7]=s("h3",{class:"sheet__title"},"جزئیات سند",-1)),s("dl",Q,[s("div",W,[e[2]||(e[2]=s("dt",null,"نوع سند",-1)),s("dd",null,o(x[n.value.sourceType]??n.value.sourceType),1)]),s("div",X,[e[3]||(e[3]=s("dt",null,"مبلغ",-1)),s("dd",{class:p(c(n.value)?"is-in":"is-out")},o(y(n.value)),3)]),s("div",Z,[e[4]||(e[4]=s("dt",null,"وضعیت",-1)),s("dd",null,o(n.value.confirmed?"تایید شده":"در انتظار تایید"),1)]),s("div",ss,[e[5]||(e[5]=s("dt",null,"تاریخ",-1)),s("dd",null,o(m(g)(n.value.createdAt)),1)]),s("div",es,[e[6]||(e[6]=s("dt",null,"توضیحات",-1)),s("dd",null,o(n.value.note||"—"),1)])])])]),_:1},8,["visible"])):E("",!0)])}}}),vs=L(ts,[["__scopeId","data-v-83b037a9"]]);export{vs as default};
import{d as k,E as A,o as C,c as i,e as r,w as f,s as w,u as m,f as E,j as u,g as l,F as R,b as s,r as D,I as T,t as o,n as p,q as N,_ as L}from"./index-CGo5tz1H.js";import{P}from"./PageBar-B7OwbOZ2.js";import{a as M}from"./Spinner.vue_vue_type_style_index_0_lang-OVIFoXDj.js";import{S as O}from"./SectionHead-CxJqY2Fp.js";import{j as g,p as B}from"./filters-CLL9nGZ2.js";import{a as I}from"./client-WIBW0tF5.js";import{D as U}from"./index-BmmdHz27.js";import"./_commonjsHelpers-Cpj98o6Y.js";import"./classCallCheck-Bw9dWuSE.js";const V={class:"tx"},$={class:"tx__list"},Y=["onClick"],j={class:"tx__main"},z={class:"tx__head"},F={class:"tx__kind"},G={key:0,class:"tx__note"},H={class:"tx__foot"},q={class:"tx__date"},J={key:1,class:"tx__empty"},K={class:"sheet"},Q={class:"sheet__specs"},W={class:"sheet__spec"},X={class:"sheet__spec"},Z={class:"sheet__spec"},ss={class:"sheet__spec"},es={class:"sheet__spec"},ts=k({__name:"TransactionsView",setup(os){const x={ORDER_STOCK:"سفارش",ORDER_PRE_ORDER:"سفارش ساخت",REPAYMENT_MELTED_GOLD:"طلای آب‌شده",REPAYMENT_TRANSFER:"حواله",REPAYMENT_CHEQUE:"چک",REPAYMENT_CASH:"پولی",WALLET_BONUS:"پاداش",ADJUSTMENT:"اصلاحیه"},h=A(),_=u(!1),d=u([]),v=u(!1),n=u(null),c=a=>a.direction==="CREDIT",y=a=>a.currency==="GOLD_GRAM"?`${a.amount} گرم`:`${B(a.amount)} ریال`,S=a=>{n.value=a,v.value=!0};return C(async()=>{if(h.customerId){_.value=!0;try{d.value=await I.getLedgerEntries(h.customerId)}finally{_.value=!1}}}),(a,e)=>{const b=N("container");return l(),i("div",V,[r(P,{title:"اسناد","back-to":"userPage::hasSubRoute"}),r(M,{spinning:_.value,tip:"درحال دریافت اطلاعات"},{default:f(()=>[r(b,{class:"tx__body"},{default:f(()=>[d.value.length?(l(),i(R,{key:0},[r(O,{title:"گردش حساب",subtitle:`${d.value.length} سند`},null,8,["subtitle"]),s("div",$,[(l(!0),i(R,null,D(d.value,t=>(l(),i("article",{key:t.id,class:"tx__row",onClick:ns=>S(t)},[s("span",{class:p(["tx__mark",c(t)?"is-in":"is-out"]),"aria-hidden":"true"},[r(T,{icon:c(t)?"vuesax-linear:arrow-down":"vuesax-linear:arrow-up",size:"16"},null,8,["icon"])],2),s("div",j,[s("div",z,[s("h3",F,o(x[t.sourceType]??t.sourceType),1),s("span",{class:p(["tx__amount",c(t)?"is-in":"is-out"])},o(y(t)),3)]),t.note?(l(),i("p",G,o(t.note),1)):E("",!0),s("div",H,[s("span",q,o(m(g)(t.createdAt)),1),s("span",{class:p(["tx__state",{"is-pending":!t.confirmed}])},o(t.confirmed?"تایید شده":"در انتظار تایید"),3)])])],8,Y))),128))])],64)):_.value?E("",!0):(l(),i("section",J,[r(T,{icon:"vuesax-linear:receipt-text",size:"26"}),e[1]||(e[1]=s("p",null,"سندی برای حساب شما ثبت نشده است.",-1))]))]),_:1})]),_:1},8,["spinning"]),n.value?(l(),w(m(U),{key:0,visible:v.value,"onUpdate:visible":e[0]||(e[0]=t=>v.value=t),placement:"bottom",closable:!1,height:"420px",class:"rtl",bodyStyle:{padding:0}},{default:f(()=>[s("div",K,[e[7]||(e[7]=s("h3",{class:"sheet__title"},"جزئیات سند",-1)),s("dl",Q,[s("div",W,[e[2]||(e[2]=s("dt",null,"نوع سند",-1)),s("dd",null,o(x[n.value.sourceType]??n.value.sourceType),1)]),s("div",X,[e[3]||(e[3]=s("dt",null,"مبلغ",-1)),s("dd",{class:p(c(n.value)?"is-in":"is-out")},o(y(n.value)),3)]),s("div",Z,[e[4]||(e[4]=s("dt",null,"وضعیت",-1)),s("dd",null,o(n.value.confirmed?"تایید شده":"در انتظار تایید"),1)]),s("div",ss,[e[5]||(e[5]=s("dt",null,"تاریخ",-1)),s("dd",null,o(m(g)(n.value.createdAt)),1)]),s("div",es,[e[6]||(e[6]=s("dt",null,"توضیحات",-1)),s("dd",null,o(n.value.note||"—"),1)])])])]),_:1},8,["visible"])):E("",!0)])}}}),vs=L(ts,[["__scopeId","data-v-83b037a9"]]);export{vs as default};
@@ -1 +1 @@
import{j as d,u as F,l as i,p as S}from"./index-CtDx9pmc.js";import{a as P}from"./client-WIBW0tF5.js";function W(t){return!t||t.length===0?null:t.reduce((e,s)=>parseFloat(s.defaultWagePercent)<parseFloat(e.defaultWagePercent)?s:e)}function I(t,e){const s=d(t),r=i(()=>{var n,p;return(p=(n=s.value.images)==null?void 0:n[0])==null?void 0:p.url}),o=i(()=>s.value.id),u=i(()=>s.value.title),l=i(()=>s.value.variants),a=d(e??W(F(l))),v=i(()=>a.value?parseFloat(a.value.rashWeightGrams):0),g=i(()=>a.value?parseFloat(a.value.defaultWagePercent):null),x=d(null),f=i(()=>{var n;return((n=a.value)==null?void 0:n.qty)??0}),h=i(()=>{var n;return((n=a.value)==null?void 0:n.isPreOrder)??!1}),y=i(()=>f.value>0||h.value),_=i(()=>s.value.productCode??null),C=d(!1);return{product:s,image:r,id:o,title:u,productCode:_,variants:l,selectedVariant:a,min_gram:v,wage:g,hasDiscountWage:x,qty:f,isPreOrder:h,is_exist:y,has_warranty:C}}const m="appCart";function q(){try{const t=localStorage.getItem(m);return t?JSON.parse(t):[]}catch{return[]}}function c(t){localStorage.setItem(m,JSON.stringify(t))}const G=S("cart",{state:()=>({items:q()}),actions:{async init(){try{const t=await P.listProducts(),e=[];for(const s of this.items){const r=t.find(u=>u.id===s.pid),o=r==null?void 0:r.variants.find(u=>u.id===s.vid);r&&o&&e.push({...s,product:r})}this.items=e,c(this.items)}catch(t){console.log(t)}},addToCart(t){const e=this.find_index(t);e===-1?this.items.push(t):(this.items[e].product=t.product,this.items[e].qty=t.qty),c(this.items)},remove(t){const e=this.find_index(t);e>-1&&this.items.splice(e,1),c(this.items)},updateFeild(t,e,s,r){if(!this.isInCart(s))return!1;const o=e??this.find_index(s);return this.items[o][r]=t,c(this.items),!0},find_index(t){return this.items.findIndex(e=>e.pid===t.pid&&e.vid===t.vid)},isInCart(t){return this.find_index(t)>-1},variant(t){return t.product.variants.find(e=>e.id===t.vid)},total(){return this.items.reduce((t,e)=>{const s=this.variant(e);return t+(s?parseFloat(s.rashWeightGrams)*e.qty:0)},0).toFixed(2)},clear(){this.items=[],c(this.items)}}});export{G as a,I as u};
import{j as d,u as F,l as i,p as S}from"./index-CGo5tz1H.js";import{a as P}from"./client-WIBW0tF5.js";function W(t){return!t||t.length===0?null:t.reduce((e,s)=>parseFloat(s.defaultWagePercent)<parseFloat(e.defaultWagePercent)?s:e)}function I(t,e){const s=d(t),r=i(()=>{var n,p;return(p=(n=s.value.images)==null?void 0:n[0])==null?void 0:p.url}),o=i(()=>s.value.id),u=i(()=>s.value.title),l=i(()=>s.value.variants),a=d(e??W(F(l))),v=i(()=>a.value?parseFloat(a.value.rashWeightGrams):0),g=i(()=>a.value?parseFloat(a.value.defaultWagePercent):null),x=d(null),f=i(()=>{var n;return((n=a.value)==null?void 0:n.qty)??0}),h=i(()=>{var n;return((n=a.value)==null?void 0:n.isPreOrder)??!1}),y=i(()=>f.value>0||h.value),_=i(()=>s.value.productCode??null),C=d(!1);return{product:s,image:r,id:o,title:u,productCode:_,variants:l,selectedVariant:a,min_gram:v,wage:g,hasDiscountWage:x,qty:f,isPreOrder:h,is_exist:y,has_warranty:C}}const m="appCart";function q(){try{const t=localStorage.getItem(m);return t?JSON.parse(t):[]}catch{return[]}}function c(t){localStorage.setItem(m,JSON.stringify(t))}const G=S("cart",{state:()=>({items:q()}),actions:{async init(){try{const t=await P.listProducts(),e=[];for(const s of this.items){const r=t.find(u=>u.id===s.pid),o=r==null?void 0:r.variants.find(u=>u.id===s.vid);r&&o&&e.push({...s,product:r})}this.items=e,c(this.items)}catch(t){console.log(t)}},addToCart(t){const e=this.find_index(t);e===-1?this.items.push(t):(this.items[e].product=t.product,this.items[e].qty=t.qty),c(this.items)},remove(t){const e=this.find_index(t);e>-1&&this.items.splice(e,1),c(this.items)},updateFeild(t,e,s,r){if(!this.isInCart(s))return!1;const o=e??this.find_index(s);return this.items[o][r]=t,c(this.items),!0},find_index(t){return this.items.findIndex(e=>e.pid===t.pid&&e.vid===t.vid)},isInCart(t){return this.find_index(t)>-1},variant(t){return t.product.variants.find(e=>e.id===t.vid)},total(){return this.items.reduce((t,e)=>{const s=this.variant(e);return t+(s?parseFloat(s.rashWeightGrams)*e.qty:0)},0).toFixed(2)},clear(){this.items=[],c(this.items)}}});export{G as a,I as u};
@@ -1 +1 @@
import{c as l}from"./Spinner.vue_vue_type_style_index_0_lang-DJDyZ-LG.js";var f=function(n){return setTimeout(n,16)},c=function(n){return clearTimeout(n)};typeof window<"u"&&"requestAnimationFrame"in window&&(f=function(n){return window.requestAnimationFrame(n)},c=function(n){return window.cancelAnimationFrame(n)});var i=0,o=new Map;function u(e){o.delete(e)}function w(e){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:1;i+=1;var r=i;function a(t){if(t===0)u(r),e();else{var s=f(function(){a(t-1)});o.set(r,s)}}return a(n),r}w.cancel=function(e){var n=o.get(e);return u(n),c(n)};function m(e,n){for(var r=l({},e),a=0;a<n.length;a+=1){var t=n[a];delete r[t]}return r}function p(e,n,r){return Object.defineProperty(e,"prototype",{writable:!1}),e}function v(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}export{p as _,v as a,m as o,w};
import{c as l}from"./Spinner.vue_vue_type_style_index_0_lang-OVIFoXDj.js";var f=function(n){return setTimeout(n,16)},c=function(n){return clearTimeout(n)};typeof window<"u"&&"requestAnimationFrame"in window&&(f=function(n){return window.requestAnimationFrame(n)},c=function(n){return window.cancelAnimationFrame(n)});var i=0,o=new Map;function u(e){o.delete(e)}function w(e){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:1;i+=1;var r=i;function a(t){if(t===0)u(r),e();else{var s=f(function(){a(t-1)});o.set(r,s)}}return a(n),r}w.cancel=function(e){var n=o.get(e);return u(n),c(n)};function m(e,n){for(var r=l({},e),a=0;a<n.length;a+=1){var t=n[a];delete r[t]}return r}function p(e,n,r){return Object.defineProperty(e,"prototype",{writable:!1}),e}function v(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}export{p as _,v as a,m as o,w};
+1
View File
@@ -0,0 +1 @@
const s="/assets/dialogEmpty1-DRc_s2oB.svg";export{s as l};

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

-1
View File
@@ -1 +0,0 @@
const s="/assets/dialogEmpty1-B2m57R6G.svg";export{s as l};

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

-1
View File
@@ -1 +0,0 @@
import{p as e}from"./index-CtDx9pmc.js";const t={colors:[],brands:[],ciny_id:[],limit_percent:[],limit_gram:[],has_discount:!1,text:void 0,cats:void 0,page:0},i=e("filters",{state:()=>({query:{...t}}),actions:{reset(){this.query={...t}}}});export{i as u};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{a3 as y,d as L,a4 as $,a5 as w,G as A,a6 as N,e as c,j as D,C as p,L as B,a7 as C,K as G,a8 as f,a9 as I,aa as M,ab as R}from"./index-CtDx9pmc.js";const[U,r,Y]=y("pull-refresh"),x=50,j=["pulling","loosing","success"],F={disabled:Boolean,modelValue:Boolean,headHeight:f(x),successText:String,pullingText:String,loosingText:String,loadingText:String,pullDistance:$,successDuration:f(500),animationDuration:f(300)};var K=L({name:U,props:F,emits:["change","refresh","update:modelValue"],setup(s,{emit:d,slots:o}){let u;const g=D(),T=D(),H=w(g),e=p({status:"normal",distance:0,duration:0}),i=M(),P=()=>{if(s.headHeight!==x)return{height:`${s.headHeight}px`}},h=()=>e.status!=="loading"&&e.status!=="success"&&!s.disabled,k=t=>{const a=+(s.pullDistance||s.headHeight);return t>a&&(t<a*2?t=a+(t-a)/2:t=a*1.5+(t-a*2)/4),Math.round(t)},n=(t,a)=>{const l=+(s.pullDistance||s.headHeight);e.distance=t,a?e.status="loading":t===0?e.status="normal":t<l?e.status="pulling":e.status="loosing",d("change",{status:e.status,distance:t})},m=()=>{const{status:t}=e;return t==="normal"?"":s[`${t}Text`]||Y(t)},E=()=>{const{status:t,distance:a}=e;if(o[t])return o[t]({distance:a});const l=[];return j.includes(t)&&l.push(c("div",{class:r("text")},[m()])),t==="loading"&&l.push(c(B,{class:r("loading")},{default:m})),l},V=()=>{e.status="success",setTimeout(()=>{n(0)},+s.successDuration)},v=t=>{u=I(H.value)===0,u&&(e.duration=0,i.start(t))},b=t=>{h()&&v(t)},_=t=>{if(h()){u||v(t);const{deltaY:a}=i;i.move(t),u&&a.value>=0&&i.isVertical()&&(C(t),n(k(a.value)))}},S=()=>{u&&i.deltaY.value&&h()&&(e.duration=+s.animationDuration,e.status==="loosing"?(n(+s.headHeight,!0),d("update:modelValue",!0),G(()=>d("refresh"))):n(0))};return A(()=>s.modelValue,t=>{e.duration=+s.animationDuration,t?n(+s.headHeight,!0):o.success||s.successText?V():n(0,!1)}),N("touchmove",_,{target:T}),()=>{var t;const a={transitionDuration:`${e.duration}ms`,transform:e.distance?`translate3d(0,${e.distance}px, 0)`:""};return c("div",{ref:g,class:r()},[c("div",{ref:T,class:r("track"),style:a,onTouchstartPassive:b,onTouchend:S,onTouchcancel:S},[c("div",{class:r("head"),style:P()},[E()]),(t=o.default)==null?void 0:t.call(o)])])}}});const q=R(K);export{q as P};
import{a3 as y,d as L,a4 as $,a5 as w,G as A,a6 as N,e as c,j as D,C as p,L as B,a7 as C,K as G,a8 as f,a9 as I,aa as M,ab as R}from"./index-CGo5tz1H.js";const[U,r,Y]=y("pull-refresh"),x=50,j=["pulling","loosing","success"],F={disabled:Boolean,modelValue:Boolean,headHeight:f(x),successText:String,pullingText:String,loosingText:String,loadingText:String,pullDistance:$,successDuration:f(500),animationDuration:f(300)};var K=L({name:U,props:F,emits:["change","refresh","update:modelValue"],setup(s,{emit:d,slots:o}){let u;const g=D(),T=D(),H=w(g),e=p({status:"normal",distance:0,duration:0}),i=M(),P=()=>{if(s.headHeight!==x)return{height:`${s.headHeight}px`}},h=()=>e.status!=="loading"&&e.status!=="success"&&!s.disabled,k=t=>{const a=+(s.pullDistance||s.headHeight);return t>a&&(t<a*2?t=a+(t-a)/2:t=a*1.5+(t-a*2)/4),Math.round(t)},n=(t,a)=>{const l=+(s.pullDistance||s.headHeight);e.distance=t,a?e.status="loading":t===0?e.status="normal":t<l?e.status="pulling":e.status="loosing",d("change",{status:e.status,distance:t})},m=()=>{const{status:t}=e;return t==="normal"?"":s[`${t}Text`]||Y(t)},E=()=>{const{status:t,distance:a}=e;if(o[t])return o[t]({distance:a});const l=[];return j.includes(t)&&l.push(c("div",{class:r("text")},[m()])),t==="loading"&&l.push(c(B,{class:r("loading")},{default:m})),l},V=()=>{e.status="success",setTimeout(()=>{n(0)},+s.successDuration)},v=t=>{u=I(H.value)===0,u&&(e.duration=0,i.start(t))},b=t=>{h()&&v(t)},_=t=>{if(h()){u||v(t);const{deltaY:a}=i;i.move(t),u&&a.value>=0&&i.isVertical()&&(C(t),n(k(a.value)))}},S=()=>{u&&i.deltaY.value&&h()&&(e.duration=+s.animationDuration,e.status==="loosing"?(n(+s.headHeight,!0),d("update:modelValue",!0),G(()=>d("refresh"))):n(0))};return A(()=>s.modelValue,t=>{e.duration=+s.animationDuration,t?n(+s.headHeight,!0):o.success||s.successText?V():n(0,!1)}),N("touchmove",_,{target:T}),()=>{var t;const a={transitionDuration:`${e.duration}ms`,transform:e.distance?`translate3d(0,${e.distance}px, 0)`:""};return c("div",{ref:g,class:r()},[c("div",{ref:T,class:r("track"),style:a,onTouchstartPassive:b,onTouchend:S,onTouchcancel:S},[c("div",{class:r("head"),style:P()},[E()]),(t=o.default)==null?void 0:t.call(o)])])}}});const q=R(K);export{q as P};

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

+2 -2
View File
@@ -9,8 +9,8 @@
<meta name="background-color" content="#1C2D56" />
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport" />
<title>طلای منتزر</title>
<script type="module" crossorigin src="/assets/index-CtDx9pmc.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-8vi5Klr2.css">
<script type="module" crossorigin src="/assets/index-CGo5tz1H.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-Bio3zTgc.css">
<link rel="manifest" href="/manifest.webmanifest"></head>
<body style="background-color: #1C2D56">
<div class="bg-white w-screen h-screen fixed"></div>
+1 -1
View File
File diff suppressed because one or more lines are too long
+30 -10
View File
@@ -3,7 +3,7 @@
</template>
<script lang="ts" setup>
import { onMounted, ref } from 'vue'
import { computed, nextTick, ref, watch } from 'vue'
import icons from './icons.json'
interface Props {
@@ -14,17 +14,37 @@ interface Props {
const props = withDefaults(defineProps<Props>(), {
color: null,
})
const tempIcon = ref<string>()
const refIcon = ref<HTMLSpanElement>()
tempIcon.value = (icons as Record<string, string>)[`${props.icon}`]
onMounted(() => {
if (props.size) {
const svg = refIcon.value?.children[0] as SVGElement
svg.setAttribute('width', props.size as string)
svg.setAttribute('height', props.size as string)
}
})
// FIXED: this used to be a plain ref, assigned once at setup —
// tempIcon.value = icons[props.icon]
// — instead of a computed. Vue reuses the same component instance across
// re-renders when an `Icon` sits in the same template position (which every
// caller in this app does; none pass a `:key` keyed to the icon name), so
// setup only runs once per mount and that assignment never ran again. Any
// caller that swaps `icon` on an already-mounted instance — the exact pattern
// the cart quantity steppers use, `:icon="qty === 1 ? 'trash' : 'minus'"` —
// had its SVG freeze on whichever icon happened to render first and silently
// stop tracking the prop after that: incrementing a cart line past 1 never
// swapped the frozen trash glyph back to minus, and the reverse (decrementing
// back down to 1) never swapped a frozen minus back to trash either. A
// computed re-evaluates on every `icon` change, so the markup — and, via the
// watcher below, the width/height attributes size() sets on it — now actually
// track the prop instead of only reading it once.
const tempIcon = computed(() => (icons as Record<string, string>)[`${props.icon}`])
function applySize() {
if (!props.size) return
const svg = refIcon.value?.children[0] as SVGElement | undefined
svg?.setAttribute('width', props.size as string)
svg?.setAttribute('height', props.size as string)
}
// v-html replaces refIcon's children synchronously with the DOM update, but
// that update itself is queued — nextTick() waits for it so applySize() finds
// the new <svg> already in the DOM rather than the previous one (or none, on
// the very first render).
watch(tempIcon, () => nextTick(applySize), { immediate: true })
</script>
<style scoped>
@@ -0,0 +1,287 @@
<!--
Swipeable image slider — a from-scratch rewrite of the gallery/preview
carousel that used to live inline in SingleProduct.vue.
WHY A REWRITE, NOT A PATCH: the old slider swiped correctly by feel but
visibly jumped mid-gesture, in both the inline gallery and the full-screen
preview. The root cause was structural, not a tunable number:
- The whole app sets `direction: rtl !important` on #app (see
src/App.vue). Under RTL, a flex row lays its children right-to-left —
slide 0 sits at the visual RIGHT edge, not the left.
- `transform: translate3d(X%, 0, 0)` is direction-agnostic: a positive X
always moves content toward the visual right, in RTL exactly as in LTR.
- The old track combined `translate3d(index * 100%, 0, 0)` with the page's
ambient RTL flex order. Those two systems don't agree on which way
"forward" is, so the settle position after a drag did not line up with
where the flex box had actually placed that slide — the visual result
was the image overshooting and snapping back, i.e. the reported "jump".
THE FIX: this component's slider track is an isolated `direction: ltr`
subtree (see .gs__track below). Once inside that subtree, slide order,
pointer-delta sign and `translateX` sign are all plain, ordinary LTR
arithmetic — index 0 first, positive X moves right, done — regardless of
what direction the rest of the page is in. The component's own controls
(dots, drag gesture) still read as natural "swipe right for previous
image" to an RTL user because the *gesture* is still interpreted in screen
space; only the slider's internal layout is pinned to LTR so its own maths
is self-consistent.
A few other correctness fixes bundled into the same rewrite, since they were
entangled with the same code:
- Pointer Events instead of Touch Events: one code path for touch, mouse
and pen, with proper pointer capture so a drag that leaves the element
(finger sliding off the edge) is still tracked to completion instead of
silently stopping — the old touch-only handlers dropped the gesture the
moment the finger crossed the element boundary.
- Position is settled against the track's OWN measured width
(getBoundingClientRect), not against `%` of an assumed-100%-per-slide
layout — immune to any box-sizing/padding mismatch between the measured
width and the CSS `flex: 0 0 100%` cell width.
- One component, two instances (the inline stage and the full-screen
preview both render a <GallerySlider>) instead of one set of drag state
manually re-entered for two different DOM subtrees via a `source` tag.
They stay in sync through `v-model:index`, a plain reactive prop/emit
binding — not shared mutable drag variables, which is what the "does a
drag started on A leak into B" bug class was ultimately rooted in.
-->
<template>
<div
ref="root"
class="gs"
:class="{ 'is-dragging': dragging }"
@pointerdown="onPointerDown"
@pointermove="onPointerMove"
@pointerup="onPointerUp"
@pointercancel="onPointerCancel"
@click="onClick"
>
<div class="gs__track" :style="trackStyle">
<div v-for="src in slides" :key="src" class="gs__cell">
<img :src="src" :alt="alt" class="gs__img" :class="fitClass" draggable="false" />
</div>
</div>
<div v-if="showCounter && slides.length > 1" class="gs__counter">{{ index + 1 }}/{{ slides.length }}</div>
<slot name="dots" :index="index" :go="go" />
</div>
</template>
<script setup lang="ts">
import { computed, onBeforeUnmount, ref } from 'vue'
const props = withDefaults(
defineProps<{
slides: string[]
alt: string
/** `cover` (the inline stage's default) or `contain` (the preview's). */
fit?: 'cover' | 'contain'
/** Show the built-in "n/N" pill, bottom-start of the slider.
*
* Off by default. FIXED: both call sites in SingleProduct.vue already
* draw their own overlay chrome in that same corner — the inline stage
* has .pd__expand there, and the preview has its own top-centre
* .pd__previewCounter — so this component's counter used to render on
* top of .pd__expand unconditionally, the two pieces of UI visibly
* overlapping into illegible stacked text/icons. Neither caller wants
* this counter today; a future bare usage that does can opt in. */
showCounter?: boolean
}>(),
{ fit: 'cover', showCounter: false },
)
const index = defineModel<number>('index', { default: 0 })
const emit = defineEmits<{
/** A plain tap — press and release without a real drag. Distinct from a
* native `click`, which a touch sequence also fires synthetically on
* release even after a drag; consumers that want "open on tap only"
* should use this instead of listening for `click` themselves. */
(e: 'tap'): void
}>()
const fitClass = computed(() => (props.fit === 'contain' ? 'gs__img--contain' : 'gs__img--cover'))
const root = ref<HTMLElement | null>(null)
// ── Drag state ────────────────────────────────────────────────
// All local to one instance — the inline stage and the full-screen preview
// each mount their own GallerySlider and so each get their own root, dragX,
// dragging, etc. Nothing here is shared across instances; only `index` is,
// via v-model, which is exactly the one thing that SHOULD stay in sync.
const dragging = ref(false)
const dragX = ref(0)
let pointerId: number | null = null
let startX = 0
let trackWidth = 0
// Past this many pixels of travel, the drag counts as a swipe rather than a
// tap — used both to decide whether to commit to the next/previous slide and
// to suppress the `tap` event so a swipe never also opens the preview.
const DRAG_COMMIT_RATIO = 0.18 // fraction of the track's own width
const TAP_MAX_PX = 6
function onPointerDown(e: PointerEvent) {
if (props.slides.length < 2 || pointerId !== null) return
const el = root.value
if (!el) return
pointerId = e.pointerId
startX = e.clientX
trackWidth = el.getBoundingClientRect().width || 1
dragX.value = 0
dragging.value = true
// Pointer capture keeps delivering move/up events to this element even once
// the pointer leaves it — the touch-events version of this component lost
// the gesture the instant a fast swipe crossed the element's edge.
el.setPointerCapture?.(e.pointerId)
}
function onPointerMove(e: PointerEvent) {
if (!dragging.value || e.pointerId !== pointerId) return
dragX.value = e.clientX - startX
}
function endDrag() {
if (!dragging.value) return
const dx = dragX.value
const ratio = dx / trackWidth
dragging.value = false
pointerId = null
dragX.value = 0
// Screen-space drag direction, translated to an index step. This is the one
// place RTL vs. LTR actually matters for *behaviour* (not layout): dragging
// a finger to the left (negative dx) is "next image" regardless of the
// track's own internal LTR layout, because that is what the gesture means
// to the person doing it, in either reading direction.
if (ratio <= -DRAG_COMMIT_RATIO && index.value < props.slides.length - 1) index.value++
else if (ratio >= DRAG_COMMIT_RATIO && index.value > 0) index.value--
if (Math.abs(dx) <= TAP_MAX_PX) emit('tap')
}
function onPointerUp(e: PointerEvent) {
if (e.pointerId !== pointerId) return
endDrag()
}
function onPointerCancel(e: PointerEvent) {
if (e.pointerId !== pointerId) return
// A cancelled gesture (e.g. the OS takes over for a system swipe) snaps back
// to the current slide rather than committing a possibly-partial drag.
dragging.value = false
pointerId = null
dragX.value = 0
}
// A touch sequence still fires a native `click` on release. `onPointerUp`
// already emits `tap` for a real tap and has already run by the time `click`
// fires, so this handler only needs to swallow the click's default double-
// firing — nothing further to do here, but the listener stays as documentation
// that `click` is deliberately NOT used for the tap-to-preview affordance
// (`tap` is) precisely because `click` also fires after a swipe.
function onClick() {
/* intentionally empty — see comment above */
}
function go(i: number) {
index.value = i
}
// ── Track position ───────────────────────────────────────────
// The whole point of isolating this in its own `direction: ltr` subtree (see
// .gs__track in <style>): inside it, "index 0 is first" and "positive X moves
// right" are both just true, with no page-level RTL to reconcile against.
const trackStyle = computed(() => {
const base = -index.value * 100
const dragPercent = trackWidth ? (dragX.value / trackWidth) * 100 : 0
return {
transform: `translate3d(${base + dragPercent}%, 0, 0)`,
transition: dragging.value ? 'none' : undefined,
}
})
onBeforeUnmount(() => {
if (pointerId !== null && root.value) {
try {
root.value.releasePointerCapture(pointerId)
} catch {
/* element may already be detached */
}
}
})
</script>
<style scoped lang="less">
.gs {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
touch-action: pan-y;
user-select: none;
-webkit-user-select: none;
}
// Isolated from the page's `direction: rtl` — see the file header. Everything
// under this node uses plain LTR layout and LTR-signed transforms.
.gs__track {
direction: ltr;
display: flex;
height: 100%;
width: 100%;
transition: transform 0.42s cubic-bezier(0.22, 0.61, 0.36, 1);
will-change: transform;
}
.gs.is-dragging .gs__track {
transition: none;
}
.gs__cell {
flex: 0 0 100%;
width: 100%;
height: 100%;
}
.gs__img {
width: 100%;
height: 100%;
display: block;
-webkit-user-drag: none;
user-select: none;
}
.gs__img--cover {
// The inline stage's own padding/background is supplied by the caller
// (.pd__stage); this component only sets the fit mode.
object-fit: contain;
padding: 46px 20px 20px;
}
.gs__img--contain {
object-fit: contain;
padding: 20px 22px;
}
.gs__counter {
position: absolute;
bottom: 14px;
// Placed with a logical property (so it sits at the trailing edge in the
// page's own RTL reading order) — this is UI chrome layered on top of the
// slider, not part of the isolated LTR track, so it should still follow the
// page's direction like everything else in the app.
inset-inline-start: 14px;
padding: 4px 9px;
border-radius: 999px;
font-size: 10.5px;
font-weight: 700;
color: #fff;
background: rgba(20, 22, 26, 0.45);
backdrop-filter: blur(4px);
direction: ltr;
pointer-events: none;
}
</style>
@@ -42,21 +42,29 @@
<Icon :icon="favorites.isFavorite(id) ? 'vuesax-linear:heart-fill' : 'vuesax-linear:heart'" size="19" />
</button>
<div v-if="hasImages" class="pd__stage">
<img :src="slides[imageIndex]" :alt="title" class="pd__art" />
<div v-if="slides.length > 1" class="pd__counter">{{ imageIndex + 1 }}/{{ slides.length }}</div>
<div v-if="slides.length > 1" class="pd__dots">
<button
v-for="(s, i) in slides"
:key="s"
type="button"
class="pd__dot"
:class="{ 'is-on': i === imageIndex }"
:aria-label="`تصویر ${i + 1}`"
@click="imageIndex = i"
/>
</div>
</div>
<GallerySlider
v-if="hasImages"
v-model:index="imageIndex"
:slides="slides"
:alt="title"
class="pd__stage"
@tap="openPreview"
>
<template #dots="{ index, go }">
<div v-if="slides.length > 1" class="pd__counter">{{ index + 1 }}/{{ slides.length }}</div>
<div v-if="slides.length > 1" class="pd__dots">
<button
v-for="(s, i) in slides"
:key="s"
type="button"
class="pd__dot"
:class="{ 'is-on': i === index }"
:aria-label="`تصویر ${i + 1}`"
@click.stop="go(i)"
/>
</div>
</template>
</GallerySlider>
<div v-else class="pd__stage pd__stage--empty">
<Icon icon="vuesax-linear:diamonds" size="46" />
</div>
@@ -148,12 +156,11 @@
</button>
</section>
<!-- Trust (hidden for now)
<!-- Trust -->
<div class="pd__trust">
<span><Icon icon="vuesax-linear:shield-tick" size="16" /> خرید امن</span>
<span><Icon icon="vuesax-linear:verify" size="16" /> اصالت کالا</span>
</div>
-->
</div>
<!-- Action bar -->
@@ -190,6 +197,43 @@
</div>
</article>
<!-- Full-screen image preview, teleported to <body> so it is never
clipped by this component's own scroll/overflow context (the drawer
mount, in particular). Opened by tapping the inline gallery. -->
<Teleport to="body">
<Transition name="pd-preview">
<div v-if="previewOpen" class="pd__preview" @click.self="closePreview">
<button type="button" class="pd__previewClose" aria-label="بستن" @click="closePreview">
<Icon icon="vuesax-linear:add" size="20" />
</button>
<div v-if="slides.length > 1" class="pd__previewCounter">{{ imageIndex + 1 }} / {{ slides.length }}</div>
<GallerySlider
v-model:index="imageIndex"
:slides="slides"
:alt="title"
class="pd__previewStage"
fit="contain"
/>
<div v-if="slides.length > 1" class="pd__previewThumbs no-scrollbar">
<button
v-for="(s, i) in slides"
:key="s"
type="button"
class="pd__previewThumb"
:class="{ 'is-on': i === imageIndex }"
:aria-label="`تصویر ${i + 1}`"
@click="imageIndex = i"
>
<img :src="s" :alt="`${title} ${i + 1}`" draggable="false" />
</button>
</div>
</div>
</Transition>
</Teleport>
<NotifyVant :timeOut="3000" v-model="notify" :color="'background-color: #14161A'">
<div class="font-bold text-right mb-2">ثبت سفارش</div>
<div>محصول با موفقیت به سبد خرید افزوده شد</div>
@@ -201,7 +245,7 @@
</template>
<template v-slot:title>
<div class="p-8 text-justify">
برای دسترسی به تمامی امکانات نرم افزار منتزر، ابتدا گزینه ورود/ثبت نام را لمس کنید و در صورت نداشتن حساب کاربری، ثبت نام نمایید.
برای دسترسی به تمامی امکانات نرم افزار هنزاگلد، ابتدا گزینه ورود/ثبت نام را لمس کنید و در صورت نداشتن حساب کاربری، ثبت نام نمایید.
</div>
</template>
<template v-slot:button>
@@ -213,9 +257,10 @@
</template>
<script setup lang="ts">
import { computed, onBeforeMount, ref, watch } from 'vue'
import { computed, onBeforeMount, onBeforeUnmount, ref, watch } from 'vue'
import { useRouter } from 'vue-router'
import Icon from '../icon/Icon.vue'
import GallerySlider from './GallerySlider.vue'
import Spinner from '../Spinner.vue'
import NotifyVant from '../NotifyVant.vue'
import DialogVant from '../DialogVant.vue'
@@ -291,6 +336,26 @@ watch(slides, (list) => {
if (imageIndex.value > list.length - 1) imageIndex.value = 0
})
// ── Full-screen preview ─────────────────────────────────────────
// Tapping the inline gallery (a plain tap, not a swipe — GallerySlider tells
// the two apart itself and only emits `tap` for the former) opens a
// full-screen viewer teleported to <body>, with its own GallerySlider kept in
// lockstep via the shared `imageIndex` v-model.
const previewOpen = ref(false)
function openPreview() {
if (!hasImages.value) return
previewOpen.value = true
// Teleported to <body>, so without this the page (or the Drawer) would
// still scroll behind the preview.
document.body.style.overflow = 'hidden'
}
function closePreview() {
previewOpen.value = false
document.body.style.overflow = ''
}
const wageLabel = computed(() => {
const w = wage.value
if (w == null) return ''
@@ -342,6 +407,13 @@ const toggleFav = (e: Event) => {
onBeforeMount(async () => {
await productDetail.load()
})
// If the preview is left open when this instance goes away — the drawer is
// closed, or the routed page is navigated away from — the body scroll lock it
// set would otherwise outlive it and leave the rest of the app unscrollable.
onBeforeUnmount(() => {
if (previewOpen.value) document.body.style.overflow = ''
})
</script>
<style scoped lang="less">
@@ -399,10 +471,10 @@ onBeforeMount(async () => {
transform: scale(0.92);
}
.pd__round--back {
inset-inline-end: 16px;
inset-inline-start: 16px;
}
.pd__round--fav {
inset-inline-start: 16px;
inset-inline-end: 16px;
}
.pd__round--fav.is-on {
color: @wine;
@@ -410,8 +482,9 @@ onBeforeMount(async () => {
.pd__counter {
position: absolute;
bottom: 14px;
inset-inline-start: 14px;
top: 16px;
inset-inline-start: 50%;
transform: translateX(-50%);
padding: 4px 10px;
border-radius: 999px;
font-size: 11px;
@@ -735,4 +808,112 @@ onBeforeMount(async () => {
background: @canvas;
border: 1px solid @ink;
}
/* ── Full-screen preview ─────────────────────────────────── */
/* Teleported to <body>, so it sits outside .pd entirely — see the template
comment on why. z-index cleared well above ant-design-vue's own Drawer
layer (@zindex-modal) so the preview is unconditionally topmost regardless
of which Teleport happens to mount last. */
.pd__preview {
position: fixed;
inset: 0;
z-index: 2000;
display: flex;
flex-direction: column;
background: rgba(10, 10, 12, 0.55);
backdrop-filter: blur(28px) saturate(140%);
}
.pd__previewClose {
position: absolute;
top: calc(14px + env(safe-area-inset-top, 0px));
inset-inline-end: 14px;
z-index: 2;
width: 38px;
height: 38px;
display: grid;
place-items: center;
border: 0;
border-radius: 12px;
cursor: pointer;
color: #fff;
background: rgba(0, 0, 0, 0.35);
backdrop-filter: blur(10px);
transform: rotate(45deg);
transition: transform 0.18s ease, background 0.18s ease;
}
.pd__previewClose:active {
transform: rotate(45deg) scale(0.92);
}
.pd__previewCounter {
position: absolute;
top: calc(24px + env(safe-area-inset-top, 0px));
inset-inline-start: 0;
inset-inline-end: 0;
z-index: 2;
text-align: center;
font-size: 12px;
font-weight: 700;
color: rgba(255, 255, 255, 0.75);
direction: ltr;
pointer-events: none;
}
.pd__previewStage {
flex: 1;
min-height: 0;
}
.pd__previewThumbs {
flex-shrink: 0;
display: flex;
justify-content: center;
gap: 8px;
overflow-x: auto;
scroll-snap-type: x proximity;
padding: 10px 16px calc(18px + env(safe-area-inset-bottom, 0px));
}
.pd__previewThumb {
scroll-snap-align: center;
flex: 0 0 auto;
width: 52px;
height: 52px;
padding: 6px;
border: 0;
border-radius: 12px;
cursor: pointer;
overflow: hidden;
background: #fff;
opacity: 0.65;
outline: 2px solid transparent;
outline-offset: 2px;
transition: opacity 0.2s ease, outline-color 0.2s ease, transform 0.18s ease;
}
.pd__previewThumb:active {
transform: scale(0.94);
}
.pd__previewThumb.is-on {
opacity: 1;
outline-color: #fff;
}
.pd__previewThumb img {
width: 100%;
height: 100%;
object-fit: contain;
display: block;
-webkit-user-drag: none;
user-select: none;
}
.pd-preview-enter-active,
.pd-preview-leave-active {
transition: opacity 0.24s ease;
}
.pd-preview-enter-from,
.pd-preview-leave-to {
opacity: 0;
}
</style>