@salla.sa/twilight-theme-engine 1.0.85 → 1.0.87

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (390) hide show
  1. package/README.md +4 -3
  2. package/bin/twilight-check-manifest.mjs +16 -0
  3. package/dist/{AddToCartForm-B5C2M4OZ.js → AddToCartForm-P644O2QL.js} +4 -4
  4. package/dist/{AddToCartForm-B5C2M4OZ.js.map → AddToCartForm-P644O2QL.js.map} +1 -1
  5. package/dist/{BlogAuthorPage-GTF4UGSS.js → BlogAuthorPage-VWSO6MPY.js} +13 -11
  6. package/dist/BlogAuthorPage-VWSO6MPY.js.map +1 -0
  7. package/dist/{BlogCategoryPage-TN7Y4NBP.js → BlogCategoryPage-K2KSQ6T6.js} +13 -11
  8. package/dist/BlogCategoryPage-K2KSQ6T6.js.map +1 -0
  9. package/dist/{BlogPage-TDB3M3PI.js → BlogPage-XRM7VWOZ.js} +12 -10
  10. package/dist/BlogPage-XRM7VWOZ.js.map +1 -0
  11. package/dist/{BlogSinglePage-4A52Q5QW.js → BlogSinglePage-XIAXT54H.js} +12 -10
  12. package/dist/BlogSinglePage-XIAXT54H.js.map +1 -0
  13. package/dist/{BlogTagPage-TOVPBETA.js → BlogTagPage-IHOA267V.js} +13 -11
  14. package/dist/BlogTagPage-IHOA267V.js.map +1 -0
  15. package/dist/{BrandsPage-VUDGYSQI.js → BrandsPage-ZFEILRT3.js} +12 -10
  16. package/dist/BrandsPage-ZFEILRT3.js.map +1 -0
  17. package/dist/{Breadcrumb-CI3SN5YR.js → Breadcrumb-CVSISL2K.js} +12 -10
  18. package/dist/Breadcrumb-CVSISL2K.js.map +1 -0
  19. package/dist/{CartItem-BHLEURAB.js → CartItem-EOI7P3JA.js} +12 -10
  20. package/dist/CartItem-EOI7P3JA.js.map +1 -0
  21. package/dist/{CartSummary-QERVESYN.js → CartSummary-RZGUBDKJ.js} +12 -10
  22. package/dist/CartSummary-RZGUBDKJ.js.map +1 -0
  23. package/dist/{Copyright-RL6ALKRC.js → Copyright-5BLYSP24.js} +4 -4
  24. package/dist/{Copyright-RL6ALKRC.js.map → Copyright-5BLYSP24.js.map} +1 -1
  25. package/dist/{CustomerLayout-VRZUWGQK.js → CustomerLayout-6F4BJAMU.js} +12 -10
  26. package/dist/CustomerLayout-6F4BJAMU.js.map +1 -0
  27. package/dist/{Footer-ZWBZCMDL.js → Footer-NF2NLDLR.js} +6 -6
  28. package/dist/{Footer-ZWBZCMDL.js.map → Footer-NF2NLDLR.js.map} +1 -1
  29. package/dist/{Header-WNK4O66B.js → Header-6DQJ5X7J.js} +9 -7
  30. package/dist/{Header-WNK4O66B.js.map → Header-6DQJ5X7J.js.map} +1 -1
  31. package/dist/{LoyaltyPage-CGTHWJ76.js → LoyaltyPage-YHWHIWCS.js} +12 -10
  32. package/dist/LoyaltyPage-YHWHIWCS.js.map +1 -0
  33. package/dist/{LoyaltyPointsPage-QSU6K3PW.js → LoyaltyPointsPage-T6K3H5A5.js} +10 -3
  34. package/dist/LoyaltyPointsPage-T6K3H5A5.js.map +1 -0
  35. package/dist/{MainMenu-V3T7F32R.js → MainMenu-Y2TAM7DK.js} +4 -4
  36. package/dist/{MainMenu-V3T7F32R.js.map → MainMenu-Y2TAM7DK.js.map} +1 -1
  37. package/dist/{MasterLayout-XQF644LD.js → MasterLayout-GBEEFFPG.js} +12 -10
  38. package/dist/{MasterLayout-XQF644LD.js.map → MasterLayout-GBEEFFPG.js.map} +1 -1
  39. package/dist/{MobileMenu-U4BVQYKH.js → MobileMenu-RE5XVGZL.js} +12 -10
  40. package/dist/MobileMenu-RE5XVGZL.js.map +1 -0
  41. package/dist/{NotificationsPage-ZRRQY7TF.js → NotificationsPage-QAFWZAS3.js} +12 -10
  42. package/dist/NotificationsPage-QAFWZAS3.js.map +1 -0
  43. package/dist/{OrderSinglePage-O3XYVMG5.js → OrderSinglePage-T4PRXTKG.js} +12 -10
  44. package/dist/OrderSinglePage-T4PRXTKG.js.map +1 -0
  45. package/dist/{OrdersPage-CMXZF5MI.js → OrdersPage-3S6ZS56E.js} +12 -10
  46. package/dist/OrdersPage-3S6ZS56E.js.map +1 -0
  47. package/dist/{PageSingle-IIG2US43.js → PageSingle-W3UTXDOW.js} +4 -4
  48. package/dist/{PageSingle-IIG2US43.js.map → PageSingle-W3UTXDOW.js.map} +1 -1
  49. package/dist/{ProductDetails-65GDABI7.js → ProductDetails-X5A7TG3F.js} +14 -7
  50. package/dist/ProductDetails-X5A7TG3F.js.map +1 -0
  51. package/dist/{ProfilePage-SNJ4WXU4.js → ProfilePage-DUH3AILJ.js} +12 -10
  52. package/dist/ProfilePage-DUH3AILJ.js.map +1 -0
  53. package/dist/{ReviewsPage-UT7UT55J.js → ReviewsPage-2C2P7VS3.js} +4 -4
  54. package/dist/{ReviewsPage-UT7UT55J.js.map → ReviewsPage-2C2P7VS3.js.map} +1 -1
  55. package/dist/{SeoCartWidget-DBJAXJKT.js → SeoCartWidget-VYLGEW2I.js} +12 -10
  56. package/dist/SeoCartWidget-VYLGEW2I.js.map +1 -0
  57. package/dist/{SettingsPage-FLTIOPU5.js → SettingsPage-OZJEW6CW.js} +12 -10
  58. package/dist/SettingsPage-OZJEW6CW.js.map +1 -0
  59. package/dist/{StoreClosedNotification-ZT3QKDKS.js → StoreClosedNotification-QHIZBNXO.js} +13 -11
  60. package/dist/{StoreClosedNotification-ZT3QKDKS.js.map → StoreClosedNotification-QHIZBNXO.js.map} +1 -1
  61. package/dist/{TestimonialsPage-CU7HKU4O.js → TestimonialsPage-K6WJKKME.js} +4 -4
  62. package/dist/{TestimonialsPage-CU7HKU4O.js.map → TestimonialsPage-K6WJKKME.js.map} +1 -1
  63. package/dist/{ThankYouPage-5X6B4X3T.js → ThankYouPage-H6QQEI5R.js} +12 -10
  64. package/dist/ThankYouPage-H6QQEI5R.js.map +1 -0
  65. package/dist/{WalletPage-H2BKIDPA.js → WalletPage-G5IBGN6B.js} +12 -10
  66. package/dist/WalletPage-G5IBGN6B.js.map +1 -0
  67. package/dist/{WishlistPage-RS5UCIQ3.js → WishlistPage-AIOTAB6L.js} +12 -10
  68. package/dist/WishlistPage-AIOTAB6L.js.map +1 -0
  69. package/dist/api/advertisement.d.ts +33 -0
  70. package/dist/api/advertisement.d.ts.map +1 -0
  71. package/dist/api/advertisement.js +8 -0
  72. package/dist/api/advertisement.js.map +1 -0
  73. package/dist/boot/critical-style.d.ts +3 -0
  74. package/dist/boot/critical-style.d.ts.map +1 -0
  75. package/dist/boot/index.d.ts +15 -0
  76. package/dist/boot/index.d.ts.map +1 -0
  77. package/dist/boot.d.ts +1 -0
  78. package/dist/boot.js +69 -0
  79. package/dist/boot.js.map +1 -0
  80. package/dist/chunk-4FJGZQD3.js +6 -0
  81. package/dist/chunk-4FJGZQD3.js.map +1 -0
  82. package/dist/{chunk-SDFDS4Q3.js → chunk-BCJTF3V7.js} +20 -4
  83. package/dist/chunk-BCJTF3V7.js.map +1 -0
  84. package/dist/chunk-DBW7XXNE.js +103 -0
  85. package/dist/chunk-DBW7XXNE.js.map +1 -0
  86. package/dist/{chunk-22SH7OVF.js → chunk-E7WWO3V3.js} +3 -3
  87. package/dist/{chunk-22SH7OVF.js.map → chunk-E7WWO3V3.js.map} +1 -1
  88. package/dist/{chunk-SE5JYWOK.js → chunk-EZHXVHXY.js} +4 -4
  89. package/dist/{chunk-SE5JYWOK.js.map → chunk-EZHXVHXY.js.map} +1 -1
  90. package/dist/{chunk-JO7JWV34.js → chunk-FWYKOQV5.js} +5 -5
  91. package/dist/chunk-FWYKOQV5.js.map +1 -0
  92. package/dist/{chunk-JRNH3FUF.js → chunk-FYHF62KI.js} +4 -4
  93. package/dist/{chunk-JRNH3FUF.js.map → chunk-FYHF62KI.js.map} +1 -1
  94. package/dist/{chunk-UJKFBZFJ.js → chunk-GJ5IMPNY.js} +7 -7
  95. package/dist/{chunk-UJKFBZFJ.js.map → chunk-GJ5IMPNY.js.map} +1 -1
  96. package/dist/chunk-IVBOLREE.js +29 -0
  97. package/dist/chunk-IVBOLREE.js.map +1 -0
  98. package/dist/chunk-LWPKBVIE.js +14 -0
  99. package/dist/{chunk-7WAXN2PP.js.map → chunk-LWPKBVIE.js.map} +1 -1
  100. package/dist/{chunk-SX5MF2YA.js → chunk-N3BCZIGS.js} +4 -4
  101. package/dist/{chunk-SX5MF2YA.js.map → chunk-N3BCZIGS.js.map} +1 -1
  102. package/dist/{chunk-NZVR4OF7.js → chunk-NXQZ4RLM.js} +8 -8
  103. package/dist/chunk-NXQZ4RLM.js.map +1 -0
  104. package/dist/{chunk-NXQJA7D3.js → chunk-PCURRKIH.js} +3 -3
  105. package/dist/{chunk-NXQJA7D3.js.map → chunk-PCURRKIH.js.map} +1 -1
  106. package/dist/{chunk-4CZRUAZB.js → chunk-PU2LHFDQ.js} +10 -11
  107. package/dist/chunk-PU2LHFDQ.js.map +1 -0
  108. package/dist/{chunk-OWX2CPNQ.js → chunk-UQIVX4YA.js} +3 -3
  109. package/dist/{chunk-OWX2CPNQ.js.map → chunk-UQIVX4YA.js.map} +1 -1
  110. package/dist/chunk-X5NK4TZH.js +228 -0
  111. package/dist/chunk-X5NK4TZH.js.map +1 -0
  112. package/dist/{chunk-6SWDSRIL.js → chunk-XKNXYQ2K.js} +6 -6
  113. package/dist/{chunk-6SWDSRIL.js.map → chunk-XKNXYQ2K.js.map} +1 -1
  114. package/dist/{chunk-KHBSGD2D.js → chunk-XO7B3VWS.js} +3 -3
  115. package/dist/{chunk-KHBSGD2D.js.map → chunk-XO7B3VWS.js.map} +1 -1
  116. package/dist/cli/check-manifest.d.ts +10 -0
  117. package/dist/cli/check-manifest.d.ts.map +1 -0
  118. package/dist/cli/check-manifest.js +44 -0
  119. package/dist/cli/check-manifest.js.map +1 -0
  120. package/dist/components/cart/index.js +1 -1
  121. package/dist/components/common/index.js +2 -2
  122. package/dist/components/drawer/index.js +10 -8
  123. package/dist/components/home/index.js +12 -10
  124. package/dist/components/layout/Footer.d.ts.map +1 -1
  125. package/dist/components/layout/MasterLayout.d.ts.map +1 -1
  126. package/dist/components/layout/PageAdvertisements.d.ts +7 -0
  127. package/dist/components/layout/PageAdvertisements.d.ts.map +1 -0
  128. package/dist/components/layout/index.d.ts +1 -0
  129. package/dist/components/layout/index.d.ts.map +1 -1
  130. package/dist/components/layout/index.js +8 -1
  131. package/dist/components/product/index.js +11 -9
  132. package/dist/components/store/index.js +12 -10
  133. package/dist/components/store/index.js.map +1 -1
  134. package/dist/{document-class-67HTP45G.js → document-class-FRL7JHWD.js} +6 -5
  135. package/dist/{document-class-67HTP45G.js.map → document-class-FRL7JHWD.js.map} +1 -1
  136. package/dist/hooks/index.js +10 -8
  137. package/dist/hooks/useGtm.js +10 -8
  138. package/dist/hooks/useMoney.js +10 -8
  139. package/dist/hooks/useStore.js +10 -8
  140. package/dist/index.js +10 -8
  141. package/dist/index.js.map +1 -1
  142. package/dist/{not-found-QTHBFPNT.js → not-found-E6AR4CZ4.js} +12 -10
  143. package/dist/not-found-E6AR4CZ4.js.map +1 -0
  144. package/dist/providers/index.js +10 -8
  145. package/dist/routes/account/orders.js +1 -1
  146. package/dist/routes/account.js +6 -6
  147. package/dist/routes/blog.js +5 -5
  148. package/dist/routes/brands.js +1 -1
  149. package/dist/routes/cart.js +14 -12
  150. package/dist/routes/cart.js.map +1 -1
  151. package/dist/routes/home.js +13 -11
  152. package/dist/routes/loyalty.js +2 -2
  153. package/dist/routes/page.js +1 -1
  154. package/dist/routes/product-listing.js +12 -10
  155. package/dist/routes/product-listing.js.map +1 -1
  156. package/dist/routes/product.js +12 -10
  157. package/dist/routes/product.js.map +1 -1
  158. package/dist/routes/root/beforeLoad.d.ts +2 -2
  159. package/dist/routes/root/beforeLoad.d.ts.map +1 -1
  160. package/dist/routes/root/head.d.ts.map +1 -1
  161. package/dist/routes/testimonials.js +2 -2
  162. package/dist/routes/thank-you.js +1 -1
  163. package/dist/skeleton.js +13 -11
  164. package/dist/tanstack/document-class.d.ts.map +1 -1
  165. package/dist/tanstack/index.d.ts +1 -0
  166. package/dist/tanstack/index.d.ts.map +1 -1
  167. package/dist/tanstack/stylesheet.d.ts +15 -0
  168. package/dist/tanstack/stylesheet.d.ts.map +1 -0
  169. package/dist/tanstack.js +33 -4
  170. package/dist/tanstack.js.map +1 -1
  171. package/dist/utils/index.js +2 -2
  172. package/dist/vite/index.d.ts +1 -1
  173. package/dist/vite/index.d.ts.map +1 -1
  174. package/dist/vite/index.js +14 -25
  175. package/dist/vite/index.js.map +1 -1
  176. package/dist/vite/plugins/twilight-manifest.d.ts +23 -0
  177. package/dist/vite/plugins/twilight-manifest.d.ts.map +1 -1
  178. package/dist/vite/plugins/twilight-schema.plugin.d.ts.map +1 -1
  179. package/package.json +16 -3
  180. package/tailwind/components/Component.tsx.txt +21 -0
  181. package/tailwind/components/ComponentRegistry.ts.txt +66 -0
  182. package/tailwind/components/cart/CartItem.tsx.txt +211 -0
  183. package/tailwind/components/cart/CartSummary.tsx.txt +269 -0
  184. package/tailwind/components/cart/PreOrderNotification.tsx.txt +16 -0
  185. package/tailwind/components/cart/PriceQuoteButton.tsx.txt +21 -0
  186. package/tailwind/components/cart/SeoCartWidget.tsx.txt +99 -0
  187. package/tailwind/components/cart/index.ts.txt +11 -0
  188. package/tailwind/components/cart/lazy.ts.txt +15 -0
  189. package/tailwind/components/collapse/Collapse.tsx.txt +95 -0
  190. package/tailwind/components/collapse/index.ts.txt +41 -0
  191. package/tailwind/components/common/Breadcrumb.tsx.txt +27 -0
  192. package/tailwind/components/common/BreadcrumbJsonLd.tsx.txt +40 -0
  193. package/tailwind/components/common/BreadcrumbTrail.tsx.txt +97 -0
  194. package/tailwind/components/common/CurrencySymbol.tsx.txt +8 -0
  195. package/tailwind/components/common/DeferredData.tsx.txt +122 -0
  196. package/tailwind/components/common/ErrorPage.tsx.txt +69 -0
  197. package/tailwind/components/common/Image.tsx.txt +119 -0
  198. package/tailwind/components/common/Link.tsx.txt +36 -0
  199. package/tailwind/components/common/Link.types.ts.txt +85 -0
  200. package/tailwind/components/common/NoContent.tsx.txt +27 -0
  201. package/tailwind/components/common/RenderWhenVisible.tsx.txt +92 -0
  202. package/tailwind/components/common/index.ts.txt +42 -0
  203. package/tailwind/components/common/lazy.ts.txt +28 -0
  204. package/tailwind/components/defineComponent.ts.txt +32 -0
  205. package/tailwind/components/drawer/Drawer.tsx.txt +219 -0
  206. package/tailwind/components/drawer/index.ts.txt +38 -0
  207. package/tailwind/components/dropdown/Dropdown.tsx.txt +166 -0
  208. package/tailwind/components/dropdown/index.ts.txt +40 -0
  209. package/tailwind/components/home/BundleComponent.tsx.txt +35 -0
  210. package/tailwind/components/home/ComponentErrorBoundary.tsx.txt +98 -0
  211. package/tailwind/components/home/FeaturedProductsStyle1.tsx.txt +125 -0
  212. package/tailwind/components/home/FeaturedProductsStyle2.tsx.txt +127 -0
  213. package/tailwind/components/home/FeaturedProductsStyle3.tsx.txt +71 -0
  214. package/tailwind/components/home/FixedBanner.tsx.txt +68 -0
  215. package/tailwind/components/home/FixedProducts.tsx.txt +72 -0
  216. package/tailwind/components/home/HomePageRenderer.tsx.txt +284 -0
  217. package/tailwind/components/home/PageBlocks.tsx.txt +24 -0
  218. package/tailwind/components/home/ParallaxBackground.tsx.txt +50 -0
  219. package/tailwind/components/home/PhotosSlider.tsx.txt +61 -0
  220. package/tailwind/components/home/ProductsSlider.tsx.txt +87 -0
  221. package/tailwind/components/home/ReorderProducts.tsx.txt +38 -0
  222. package/tailwind/components/home/SquarePhotos.tsx.txt +68 -0
  223. package/tailwind/components/home/StoreFeatures.tsx.txt +34 -0
  224. package/tailwind/components/home/Testimonials.tsx.txt +36 -0
  225. package/tailwind/components/home/Youtube.tsx.txt +48 -0
  226. package/tailwind/components/home/index.ts.txt +50 -0
  227. package/tailwind/components/home/lazy.ts.txt +17 -0
  228. package/tailwind/components/home/register.ts.txt +44 -0
  229. package/tailwind/components/home/reorder-hooks.ts.txt +52 -0
  230. package/tailwind/components/home/types.ts.txt +4 -0
  231. package/tailwind/components/layout/Copyright.tsx.txt +23 -0
  232. package/tailwind/components/layout/CustomerLayout.tsx.txt +91 -0
  233. package/tailwind/components/layout/Footer.tsx.txt +341 -0
  234. package/tailwind/components/layout/Header.tsx.txt +154 -0
  235. package/tailwind/components/layout/MasterLayout.tsx.txt +62 -0
  236. package/tailwind/components/layout/PageAdvertisements.tsx.txt +131 -0
  237. package/tailwind/components/layout/WidgetHead.tsx.txt +53 -0
  238. package/tailwind/components/layout/index.ts.txt +27 -0
  239. package/tailwind/components/layout/lazy.ts.txt +25 -0
  240. package/tailwind/components/layout/types.ts.txt +11 -0
  241. package/tailwind/components/modal/ImageModal.tsx.txt +70 -0
  242. package/tailwind/components/modal/Modal.tsx.txt +245 -0
  243. package/tailwind/components/modal/index.ts.txt +39 -0
  244. package/tailwind/components/modal/lazy.ts.txt +10 -0
  245. package/tailwind/components/navigation/MainMenu.tsx.txt +94 -0
  246. package/tailwind/components/navigation/MobileMenu.tsx.txt +160 -0
  247. package/tailwind/components/navigation/index.ts.txt +4 -0
  248. package/tailwind/components/navigation/lazy.ts.txt +11 -0
  249. package/tailwind/components/product/AddToCartForm.tsx.txt +365 -0
  250. package/tailwind/components/product/ProductCard.tsx.txt +305 -0
  251. package/tailwind/components/product/ProductDetails.tsx.txt +267 -0
  252. package/tailwind/components/product/ProductGallery.tsx.txt +234 -0
  253. package/tailwind/components/product/index.ts.txt +15 -0
  254. package/tailwind/components/product/lazy.ts.txt +9 -0
  255. package/tailwind/components/snippets/AppsSnippets.tsx.txt +225 -0
  256. package/tailwind/components/snippets/SallaSdkScripts.tsx.txt +14 -0
  257. package/tailwind/components/snippets/index.ts.txt +4 -0
  258. package/tailwind/components/store/StoreClosedNotification.tsx.txt +73 -0
  259. package/tailwind/components/store/index.ts.txt +8 -0
  260. package/tailwind/components/store/lazy.ts.txt +8 -0
  261. package/tailwind/components/toast/Toaster.tsx.txt +177 -0
  262. package/tailwind/components/toast/index.ts.txt +10 -0
  263. package/tailwind/components/toast/types.ts.txt +38 -0
  264. package/tailwind/components/toast/useToast.ts.txt +61 -0
  265. package/tailwind/components/tracking/GoogleTag.tsx.txt +77 -0
  266. package/tailwind/components/tracking/SiftSnippet.tsx.txt +49 -0
  267. package/tailwind/components/tracking/TwilightBundles.tsx.txt +67 -0
  268. package/tailwind/components/tracking/index.ts.txt +11 -0
  269. package/tailwind/components/tracking/lazy.ts.txt +11 -0
  270. package/tailwind/components/useComponent.ts.txt +12 -0
  271. package/tailwind/routes/account/index.tsx.txt +16 -0
  272. package/tailwind/routes/account/notifications/NotificationsPage.tsx.txt +54 -0
  273. package/tailwind/routes/account/notifications/index.tsx.txt +39 -0
  274. package/tailwind/routes/account/notifications/loader.ts.txt +22 -0
  275. package/tailwind/routes/account/notifications/types.ts.txt +18 -0
  276. package/tailwind/routes/account/orders/OrderSinglePage.tsx.txt +181 -0
  277. package/tailwind/routes/account/orders/OrdersPage.tsx.txt +28 -0
  278. package/tailwind/routes/account/orders/index.tsx.txt +86 -0
  279. package/tailwind/routes/account/orders/loader.ts.txt +66 -0
  280. package/tailwind/routes/account/orders/single/OrderActions.tsx.txt +197 -0
  281. package/tailwind/routes/account/orders/single/OrderHeader.tsx.txt +143 -0
  282. package/tailwind/routes/account/orders/single/OrderItemRow.tsx.txt +209 -0
  283. package/tailwind/routes/account/orders/single/OrderSections.tsx.txt +215 -0
  284. package/tailwind/routes/account/orders/single/types.ts.txt +38 -0
  285. package/tailwind/routes/account/orders/types.ts.txt +29 -0
  286. package/tailwind/routes/account/profile/ProfilePage.tsx.txt +30 -0
  287. package/tailwind/routes/account/profile/index.tsx.txt +39 -0
  288. package/tailwind/routes/account/profile/loader.ts.txt +16 -0
  289. package/tailwind/routes/account/profile/types.ts.txt +5 -0
  290. package/tailwind/routes/account/settings/SettingsPage.tsx.txt +13 -0
  291. package/tailwind/routes/account/settings/index.tsx.txt +39 -0
  292. package/tailwind/routes/account/settings/loader.ts.txt +13 -0
  293. package/tailwind/routes/account/settings/types.ts.txt +5 -0
  294. package/tailwind/routes/account/types.ts.txt +320 -0
  295. package/tailwind/routes/account/wallet/WalletPage.tsx.txt +195 -0
  296. package/tailwind/routes/account/wallet/index.tsx.txt +38 -0
  297. package/tailwind/routes/account/wallet/loader.ts.txt +27 -0
  298. package/tailwind/routes/account/wallet/types.ts.txt +11 -0
  299. package/tailwind/routes/account/wishlist/WishlistPage.tsx.txt +314 -0
  300. package/tailwind/routes/account/wishlist/WishlistShare.tsx.txt +248 -0
  301. package/tailwind/routes/account/wishlist/index.tsx.txt +40 -0
  302. package/tailwind/routes/account/wishlist/loader.ts.txt +26 -0
  303. package/tailwind/routes/account/wishlist/types.ts.txt +9 -0
  304. package/tailwind/routes/blog/BlogAuthorPage.tsx.txt +82 -0
  305. package/tailwind/routes/blog/BlogCategoryPage.tsx.txt +84 -0
  306. package/tailwind/routes/blog/BlogPage.tsx.txt +191 -0
  307. package/tailwind/routes/blog/BlogSinglePage.tsx.txt +168 -0
  308. package/tailwind/routes/blog/BlogTagPage.tsx.txt +84 -0
  309. package/tailwind/routes/blog/BlogTags.tsx.txt +54 -0
  310. package/tailwind/routes/blog/components.tsx.txt +87 -0
  311. package/tailwind/routes/blog/index.tsx.txt +238 -0
  312. package/tailwind/routes/blog/loader.ts.txt +173 -0
  313. package/tailwind/routes/blog/types.ts.txt +106 -0
  314. package/tailwind/routes/brands/BrandsPage.tsx.txt +179 -0
  315. package/tailwind/routes/brands/index.tsx.txt +47 -0
  316. package/tailwind/routes/brands/loader.ts.txt +14 -0
  317. package/tailwind/routes/brands/types.ts.txt +53 -0
  318. package/tailwind/routes/cart/CartPage.tsx.txt +112 -0
  319. package/tailwind/routes/cart/index.tsx.txt +39 -0
  320. package/tailwind/routes/cart/loader.ts.txt +15 -0
  321. package/tailwind/routes/cart/types.ts.txt +6 -0
  322. package/tailwind/routes/home/HomePage.tsx.txt +53 -0
  323. package/tailwind/routes/home/index.tsx.txt +56 -0
  324. package/tailwind/routes/home/loader.ts.txt +24 -0
  325. package/tailwind/routes/home/types.ts.txt +11 -0
  326. package/tailwind/routes/index.ts.txt +94 -0
  327. package/tailwind/routes/lazy.ts.txt +105 -0
  328. package/tailwind/routes/loyalty/LoyaltyPage.tsx.txt +17 -0
  329. package/tailwind/routes/loyalty/LoyaltyPointsPage.tsx.txt +11 -0
  330. package/tailwind/routes/loyalty/index.tsx.txt +81 -0
  331. package/tailwind/routes/loyalty/loader.ts.txt +53 -0
  332. package/tailwind/routes/loyalty/types.ts.txt +109 -0
  333. package/tailwind/routes/not-found.tsx.txt +50 -0
  334. package/tailwind/routes/page/PageSingle.tsx.txt +34 -0
  335. package/tailwind/routes/page/index.tsx.txt +60 -0
  336. package/tailwind/routes/page/loader.ts.txt +19 -0
  337. package/tailwind/routes/page/types.ts.txt +34 -0
  338. package/tailwind/routes/product/ProductPage.tsx.txt +77 -0
  339. package/tailwind/routes/product/index.tsx.txt +157 -0
  340. package/tailwind/routes/product/loader.ts.txt +35 -0
  341. package/tailwind/routes/product/types.ts.txt +6 -0
  342. package/tailwind/routes/product-listing/ProductListPage.tsx.txt +321 -0
  343. package/tailwind/routes/product-listing/index.tsx.txt +95 -0
  344. package/tailwind/routes/product-listing/loader.ts.txt +323 -0
  345. package/tailwind/routes/product-listing/types.ts.txt +96 -0
  346. package/tailwind/routes/product-listing/useAppliedFilters.ts.txt +130 -0
  347. package/tailwind/routes/product-short-link.ts.txt +104 -0
  348. package/tailwind/routes/root/beforeLoad.ts.txt +354 -0
  349. package/tailwind/routes/root/head.ts.txt +424 -0
  350. package/tailwind/routes/root/index.ts.txt +2 -0
  351. package/tailwind/routes/seo-redirects.ts.txt +82 -0
  352. package/tailwind/routes/testimonials/ReviewsPage.tsx.txt +12 -0
  353. package/tailwind/routes/testimonials/TestimonialsPage.tsx.txt +80 -0
  354. package/tailwind/routes/testimonials/index.tsx.txt +80 -0
  355. package/tailwind/routes/testimonials/loader.ts.txt +29 -0
  356. package/tailwind/routes/testimonials/types.ts.txt +9 -0
  357. package/tailwind/routes/thank-you/ThankYouPage.tsx.txt +241 -0
  358. package/tailwind/routes/thank-you/index.tsx.txt +49 -0
  359. package/tailwind/routes/thank-you/loader.ts.txt +40 -0
  360. package/tailwind/routes/thank-you/types.ts.txt +16 -0
  361. package/tailwind/routes/types.ts.txt +41 -0
  362. package/dist/BlogAuthorPage-GTF4UGSS.js.map +0 -1
  363. package/dist/BlogCategoryPage-TN7Y4NBP.js.map +0 -1
  364. package/dist/BlogPage-TDB3M3PI.js.map +0 -1
  365. package/dist/BlogSinglePage-4A52Q5QW.js.map +0 -1
  366. package/dist/BlogTagPage-TOVPBETA.js.map +0 -1
  367. package/dist/BrandsPage-VUDGYSQI.js.map +0 -1
  368. package/dist/Breadcrumb-CI3SN5YR.js.map +0 -1
  369. package/dist/CartItem-BHLEURAB.js.map +0 -1
  370. package/dist/CartSummary-QERVESYN.js.map +0 -1
  371. package/dist/CustomerLayout-VRZUWGQK.js.map +0 -1
  372. package/dist/LoyaltyPage-CGTHWJ76.js.map +0 -1
  373. package/dist/LoyaltyPointsPage-QSU6K3PW.js.map +0 -1
  374. package/dist/MobileMenu-U4BVQYKH.js.map +0 -1
  375. package/dist/NotificationsPage-ZRRQY7TF.js.map +0 -1
  376. package/dist/OrderSinglePage-O3XYVMG5.js.map +0 -1
  377. package/dist/OrdersPage-CMXZF5MI.js.map +0 -1
  378. package/dist/ProductDetails-65GDABI7.js.map +0 -1
  379. package/dist/ProfilePage-SNJ4WXU4.js.map +0 -1
  380. package/dist/SeoCartWidget-DBJAXJKT.js.map +0 -1
  381. package/dist/SettingsPage-FLTIOPU5.js.map +0 -1
  382. package/dist/ThankYouPage-5X6B4X3T.js.map +0 -1
  383. package/dist/WalletPage-H2BKIDPA.js.map +0 -1
  384. package/dist/WishlistPage-RS5UCIQ3.js.map +0 -1
  385. package/dist/chunk-4CZRUAZB.js.map +0 -1
  386. package/dist/chunk-7WAXN2PP.js +0 -14
  387. package/dist/chunk-JO7JWV34.js.map +0 -1
  388. package/dist/chunk-NZVR4OF7.js.map +0 -1
  389. package/dist/chunk-SDFDS4Q3.js.map +0 -1
  390. package/dist/not-found-QTHBFPNT.js.map +0 -1
@@ -0,0 +1,143 @@
1
+ import { useState } from 'react';
2
+ import { SallaButton } from '@salla.sa/twilight-components-react/button';
3
+ import { useDate, useNumber } from '../../../../hooks';
4
+ import { useTranslation } from '../../../../providers/I18nProvider';
5
+ import { useTwilight } from '../../../../providers/twilight-context';
6
+ import type { Order, TwigOrder } from './types';
7
+
8
+ const PRINT_WINDOW = 'noopener, toolbar=yes, scrollbars=yes, resizable=yes, width=900, height=700';
9
+
10
+ function OrderStatus({ order, paymentExpired }: { order: Order; paymentExpired: boolean }) {
11
+ const { t } = useTranslation();
12
+ if (paymentExpired) {
13
+ return <span className="text-red-500">{t('pages.orders.pending_payment_expired')}</span>;
14
+ }
15
+ return (
16
+ <span
17
+ className="text-primary inline-flex items-center rtl:space-x-reverse space-x-1"
18
+ style={{ color: order.status.color }}
19
+ >
20
+ <i className={`mt-1 ${order.status.icon}`}></i>
21
+ <span> {order.status.name}</span>
22
+ </span>
23
+ );
24
+ }
25
+
26
+ /** Twig's `order.print_url()`; `urls.receipt` is the buyer's bank-transfer image. */
27
+ function PrintAction({ order }: { order: Order }) {
28
+ const { t } = useTranslation();
29
+ const { store } = useTwilight();
30
+ const [printNoticeOpen, setPrintNoticeOpen] = useState(false);
31
+ const print = () =>
32
+ window.open(
33
+ order.urls.print ??
34
+ `${(store?.url ?? '').replace(/\/$/, '')}/account/orders/${order.id}/print`,
35
+ '_blank',
36
+ PRINT_WINDOW
37
+ );
38
+
39
+ return order.actions.invoice_printable === false ? (
40
+ <div
41
+ className={`tooltip-toggle tooltip-toggle--clickable inline-block${printNoticeOpen ? ' visible' : ''}`}
42
+ >
43
+ <button
44
+ type="button"
45
+ className="text-primary border border-primary rounded text-center px-4 py-2 cursor-pointer"
46
+ onClick={() => setPrintNoticeOpen(true)}
47
+ >
48
+ <i className="sicon-printer2 v-align"></i> {t('pages.orders.print')}
49
+ </button>
50
+ <div className="tooltip-content shadow-md rounded text-gray-500">
51
+ <small>
52
+ {' '}
53
+ {t('pages.orders.to_order_invoice_contact_vendor')}
54
+ <br />
55
+ {t('pages.orders.print_order_details')}{' '}
56
+ <button type="button" className="text-primary underline cursor-pointer" onClick={print}>
57
+ {t('pages.orders.click_here')}
58
+ </button>
59
+ </small>
60
+ <SallaButton
61
+ shape="link"
62
+ color="danger"
63
+ size="small"
64
+ className="close-tooltip"
65
+ onClick={() => setPrintNoticeOpen(false)}
66
+ >
67
+ <i className="sicon-cancel"></i>
68
+ </SallaButton>
69
+ </div>
70
+ </div>
71
+ ) : (
72
+ <SallaButton fill="outline" size="small" onClick={print}>
73
+ <i className="sicon-printer2 v-align"></i> {t('pages.orders.print')}
74
+ </SallaButton>
75
+ );
76
+ }
77
+
78
+ /** The date / status / links / print row at the top of the order page. */
79
+ export function OrderHeader({
80
+ order,
81
+ links,
82
+ paymentExpired,
83
+ }: {
84
+ order: Order;
85
+ links: TwigOrder['links'];
86
+ paymentExpired: boolean;
87
+ }) {
88
+ const { t, direction } = useTranslation();
89
+ const { format: formatDate } = useDate();
90
+ const { format: formatNumber } = useNumber();
91
+
92
+ return (
93
+ <table className="min-w-full rounded-md overflow-hidden">
94
+ <tbody>
95
+ <tr className="bg-white overflow-hidden flex md:table-row flex-row md:flex-row flex-wrap md:flex-no-wrap py-1.5 md:py-0">
96
+ <td
97
+ data-testid="store-order-status"
98
+ className="single-order-header-item w-full md:w-auto px-3 md:px-6 py-2 md:py-4 md:h-20 whitespace-nowrap text-sm "
99
+ >
100
+ <div className="rtl:ml-2 ltr:mr-2 font-normal text-gray-400">
101
+ {t('pages.orders.date')}
102
+ </div>
103
+ <b>{formatNumber(formatDate(order.created_at.date))}</b>
104
+ </td>
105
+
106
+ <td className="single-order-header-item flex justify-between items-center w-full md:w-auto px-3 md:px-6 py-2 md:py-4 md:h-20 whitespace-nowrap text-sm ">
107
+ <OrderStatus order={order} paymentExpired={paymentExpired} />
108
+
109
+ <div className="flex items-center justify-between">
110
+ {order.type === 'quote' && (
111
+ <span className="text-red-500 ml-4">
112
+ {t('pages.orders.your_order_is_under_review')}
113
+ </span>
114
+ )}
115
+
116
+ {!!links?.length && (
117
+ <div className="flex space-x-2 rtl:space-x-reverse text-start flex-none px-2">
118
+ {links.map((link) => (
119
+ <a
120
+ key={link.url}
121
+ href={link.url}
122
+ className="text-primary-reverse bg-primary px-4 py-2 rounded"
123
+ target="_blank"
124
+ rel="noreferrer"
125
+ >
126
+ {link.label}{' '}
127
+ <i
128
+ className={
129
+ direction === 'rtl' ? 'sicon-arrow-up-left' : 'sicon-arrow-up-right'
130
+ }
131
+ ></i>
132
+ </a>
133
+ ))}
134
+ </div>
135
+ )}
136
+ <PrintAction order={order} />
137
+ </div>
138
+ </td>
139
+ </tr>
140
+ </tbody>
141
+ </table>
142
+ );
143
+ }
@@ -0,0 +1,209 @@
1
+ import { createElement } from 'react';
2
+ import { SallaOrderDetails } from '@salla.sa/twilight-components-react/order-details';
3
+ import { useDate, useNumber } from '../../../../hooks';
4
+ import { useTranslation } from '../../../../providers/I18nProvider';
5
+ import type { FormatMoney, OrderItem, TwigItem } from './types';
6
+
7
+ function ItemAttachments({ item }: { item: OrderItem }) {
8
+ const { t } = useTranslation();
9
+ if (!item.attachments?.length) return null;
10
+ return (
11
+ <div className="flow-root rounded-md px-4 border border-gray-200">
12
+ <dl className="text-sm text-dark divide-y divide-border-color">
13
+ {item.attachments.map((attachment) => (
14
+ <div
15
+ key={`${attachment.type}:${attachment.url}`}
16
+ className="py-3.5 md:flex items-center justify-between"
17
+ >
18
+ <dt className="mb-2 md:mb-0">{t('pages.products.attachments')}</dt>
19
+ <dd
20
+ className={`font-medium ${attachment.type === 'image' ? 'text-gray-900' : 'text-xs'}`}
21
+ >
22
+ {attachment.type === 'image' ? (
23
+ <div className="flex rtl:space-x-reverse space-x-2.5">
24
+ <a href={attachment.url} target="_blank" rel="noreferrer">
25
+ <img
26
+ className="h-7 w-7 object-cover rounded-md"
27
+ src={attachment.url}
28
+ alt={item.name}
29
+ />
30
+ </a>
31
+ </div>
32
+ ) : (
33
+ <a href={attachment.url}>{t('pages.orders.file_url')}</a>
34
+ )}
35
+ </dd>
36
+ </div>
37
+ ))}
38
+ </dl>
39
+ </div>
40
+ );
41
+ }
42
+
43
+ /** A date-only day (`2026-09-20`) as that calendar day wherever it is formatted, not UTC midnight. */
44
+ function calendarDay(day: unknown): Date | string {
45
+ const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(String(day));
46
+ return match ? new Date(+match[1], +match[2] - 1, +match[3]) : String(day);
47
+ }
48
+
49
+ /** Twig's booking block: the location and each reservation's day and time. */
50
+ function ItemReservations({ item, productType }: { item: OrderItem; productType?: string }) {
51
+ const { t } = useTranslation();
52
+ const { format: formatDate } = useDate();
53
+ const { format: formatNumber, useArabicNumerals } = useNumber();
54
+ const reservations = item.product_reservations ?? [];
55
+ if (productType !== 'booking' || !reservations.length) return null;
56
+ const time = (value: unknown) =>
57
+ useArabicNumerals
58
+ ? formatNumber(String(value)).replace(/PM/g, 'م').replace(/AM/g, 'ص')
59
+ : String(value);
60
+
61
+ return (
62
+ <>
63
+ {item.booking_location && (
64
+ <ul className="font-medium text-xs text-gray-600">
65
+ <li className="py-1 flex justify-between items-baseline">
66
+ <span className="mt-5 mb-3.5 text-sm font-bold">{t('common.elements.location')}</span>
67
+ <span className="text-unicode">{item.booking_location}</span>
68
+ </li>
69
+ </ul>
70
+ )}
71
+ <h2 className="mt-5 mb-3.5 text-sm font-bold">
72
+ {reservations.length > 1 ? t('pages.cart.reservations') : t('pages.cart.item_options')}
73
+ </h2>
74
+ <div className="rounded-md p-4 border border-gray-200 mb-2">
75
+ <ul className="font-medium text-xs text-gray-600">
76
+ {reservations.map((reservation) => (
77
+ <li key={`${reservation.day}:${reservation.from}`} className="py-1">
78
+ <span className="text-unicode">
79
+ {formatNumber(formatDate(calendarDay(reservation.day)))}
80
+ {reservation.from_timestamp
81
+ ? ` (${time(reservation.from)} - ${time(reservation.to)})`
82
+ : ''}
83
+ </span>
84
+ </li>
85
+ ))}
86
+ </ul>
87
+ </div>
88
+ </>
89
+ );
90
+ }
91
+
92
+ function ItemSummary({
93
+ item,
94
+ twigItem,
95
+ money,
96
+ currency,
97
+ }: {
98
+ item: OrderItem;
99
+ twigItem?: TwigItem;
100
+ money: FormatMoney;
101
+ currency: string;
102
+ }) {
103
+ const { t } = useTranslation();
104
+ const product = twigItem?.product;
105
+ const image = product?.image?.url || item.image || item.thumbnail;
106
+ const price = item.amounts.amount ?? { amount: 0, currency };
107
+ const priceText = money(price.amount, price.currency);
108
+ const total = item.amounts.total ?? { amount: 0, currency };
109
+
110
+ return (
111
+ <div className="mb-5 last:mb-0">
112
+ {product ? (
113
+ <div className="flex rtl:space-x-reverse space-x-5 mb-4">
114
+ <a href={product.url} className="shrink-0">
115
+ <img
116
+ src={image || '/images/placeholder.png'}
117
+ alt={item.name}
118
+ className={`w-18 h-14 object-${image ? 'cover' : 'contain'} rounded-md`}
119
+ />
120
+ </a>
121
+ <div>
122
+ <a
123
+ href={product.url}
124
+ className="block leading-5 mb-1.5 md:text-base font-semibold transition-colors text-gray-500 hover:text-primary"
125
+ >
126
+ {item.name}
127
+ </a>
128
+ <b>{priceText}</b>
129
+ </div>
130
+ </div>
131
+ ) : (
132
+ <div className="w-full flex justify-between text-sm py-2.5">
133
+ <span className="w-40 inline-block font-normal">{item.name}</span>
134
+ <b>{priceText}</b>
135
+ </div>
136
+ )}
137
+
138
+ <div className="w-full flex justify-between text-sm py-2.5">
139
+ <span className="w-40 inline-block font-normal">{t('pages.products.quantity')}</span>
140
+ <b>{item.quantity}</b>
141
+ </div>
142
+ <div className="flex justify-between text-sm py-2.5">
143
+ <span className=" w-40 inline-block font-normal">{t('pages.products.price')}</span>
144
+ <b>{priceText}</b>
145
+ </div>
146
+ <div className="flex justify-between text-sm py-2.5">
147
+ <span className="w-40 inline-block font-normal">{t('pages.orders.total')}</span>
148
+ <b>{money(total.amount, total.currency)}</b>
149
+ </div>
150
+ </div>
151
+ );
152
+ }
153
+
154
+ /** One item of the order page (the body of `{% for item in package.items %}`). */
155
+ export function OrderItemRow({
156
+ item,
157
+ twigItem,
158
+ money,
159
+ currency,
160
+ }: {
161
+ item: OrderItem;
162
+ twigItem?: TwigItem;
163
+ money: FormatMoney;
164
+ currency: string;
165
+ }) {
166
+ const { t } = useTranslation();
167
+ const productId = twigItem?.product?.id;
168
+
169
+ return (
170
+ <div
171
+ data-testid={`store-order-item-${item.id}`}
172
+ data-order-item-id={item.id}
173
+ data-order-item-product-id={productId}
174
+ className="order-item bg-white p-5 border-b border-gray-100 first:rounded-t-md last:rounded-b-md last:border-none"
175
+ >
176
+ <ItemSummary item={item} twigItem={twigItem} money={money} currency={currency} />
177
+
178
+ {item.availability_date && (
179
+ <div className="flex gap-2 text-sm py-2.5 text-blue-500">
180
+ <i className="sicon-info"></i>
181
+ <span>
182
+ {t('pages.products.expected_to_be')}:{' '}
183
+ <b>{String(item.availability_date).slice(0, 10)}</b>
184
+ </span>
185
+ </div>
186
+ )}
187
+
188
+ <ItemReservations item={item} productType={twigItem?.product?.type ?? item.product?.type} />
189
+
190
+ <SallaOrderDetails orderDetails={JSON.stringify(twigItem ?? item)} />
191
+
192
+ {item.note && (
193
+ <p className="mt-3 text-sm text-gray-500">
194
+ <span>{t('common.elements.note')} : </span>
195
+ {item.note}
196
+ </p>
197
+ )}
198
+
199
+ <ItemAttachments item={item} />
200
+
201
+ {/* No React wrapper yet; Twilight upgrades it (adds `hydrated`) before React hydrates. */}
202
+ {productId &&
203
+ createElement('salla-review-order-item', {
204
+ 'product-id': productId,
205
+ suppressHydrationWarning: true,
206
+ })}
207
+ </div>
208
+ );
209
+ }
@@ -0,0 +1,215 @@
1
+ import { SallaButton } from '@salla.sa/twilight-components-react/button';
2
+ import { SallaRatingStars } from '@salla.sa/twilight-components-react/rating-stars';
3
+ import { useTranslation } from '../../../../providers/I18nProvider';
4
+ import { useQuery } from '@tanstack/react-query';
5
+ import { order as orderApi } from '../../../../api/order';
6
+ import type { FormatMoney, Order, TwigOrder, TwigRating } from './types';
7
+
8
+ function RatingAction({
9
+ disabled,
10
+ endedKey,
11
+ color,
12
+ fill,
13
+ icon,
14
+ onClick,
15
+ }: {
16
+ disabled: boolean;
17
+ endedKey: string;
18
+ color: 'dark' | 'danger';
19
+ fill: 'outline';
20
+ icon: string;
21
+ onClick: () => void;
22
+ }) {
23
+ const { t } = useTranslation();
24
+ return (
25
+ <div className="tooltip-toggle tooltip-toggle--hover icon-trigger mobile-shifted">
26
+ {disabled && (
27
+ <div className="tooltip-content shadow-md rounded">
28
+ <small> {t(endedKey)}.</small>
29
+ </div>
30
+ )}
31
+ <SallaButton
32
+ loaderPosition="center"
33
+ disabled={disabled}
34
+ shape="icon"
35
+ fill={fill}
36
+ color={color}
37
+ size="medium"
38
+ onClick={disabled ? undefined : onClick}
39
+ >
40
+ <i className={`${icon} text-xl`}></i>
41
+ </SallaButton>
42
+ </div>
43
+ );
44
+ }
45
+
46
+ /** A store or shipping rating the customer left, with its edit / delete buttons. */
47
+ export function RatingSection({
48
+ title,
49
+ rating,
50
+ type,
51
+ allowUpdate,
52
+ }: {
53
+ title: string;
54
+ rating: TwigRating;
55
+ type: 'store' | 'shipping';
56
+ allowUpdate: boolean;
57
+ }) {
58
+ const dispatch = (event: string, payload: Record<string, unknown>) =>
59
+ window.salla?.event?.dispatch(event, payload);
60
+ const locked = !rating.can_update;
61
+
62
+ return (
63
+ <section className="flex justify-between items-start bg-white p-5 rounded-md">
64
+ <div>
65
+ <h2 className="text-lg font-bold mb-5">{title}</h2>
66
+ <p className="mb-2">{rating.content}</p>
67
+ <SallaRatingStars withLabel value={rating.stars} />
68
+ </div>
69
+ <div className="rating-actions">
70
+ {allowUpdate && (
71
+ <>
72
+ <RatingAction
73
+ disabled={locked}
74
+ endedKey="pages.order.edit_period_ended"
75
+ color="dark"
76
+ fill="outline"
77
+ icon="sicon-format-border-color"
78
+ onClick={() => dispatch('rating::edit', { type, feedback_id: String(rating.id) })}
79
+ />
80
+ <RatingAction
81
+ disabled={locked}
82
+ endedKey="pages.order.delete_period_ended"
83
+ color="danger"
84
+ fill="outline"
85
+ icon="sicon-trash-2"
86
+ onClick={() => dispatch('rating::delete', { feedback_id: String(rating.id) })}
87
+ />
88
+ </>
89
+ )}
90
+ </div>
91
+ </section>
92
+ );
93
+ }
94
+
95
+ interface Shipment {
96
+ id?: number;
97
+ name?: string;
98
+ logo?: string;
99
+ number?: string;
100
+ tracking?: string | null;
101
+ }
102
+
103
+ function ShippingRow({ shipment }: { shipment: Shipment }) {
104
+ const { t } = useTranslation();
105
+ // Twig treats the string "0" as empty.
106
+ const hasNumber = !!shipment.number && shipment.number !== '0';
107
+
108
+ return (
109
+ <div className="flex flex-col md:flex-row justify-between md:items-center bg-white px-5 py-3 border-b border-gray-100 rounded-t-md text-sm space-y-4 md:space-y-0">
110
+ <div className="flex items-center space-x-2 rtl:space-x-reverse">
111
+ {shipment.logo && (
112
+ <img src={shipment.logo} className="max-w-16 max-h-8" alt={shipment.name} />
113
+ )}
114
+ <span>{shipment.name}</span>
115
+ </div>
116
+ <div className="flex space-x-5 rtl:space-x-reverse">
117
+ {hasNumber && (
118
+ <span>
119
+ {t('pages.orders.shipment_no')}: <span className="font-bold">{shipment.number}</span>
120
+ </span>
121
+ )}
122
+ {shipment.tracking && (
123
+ <a
124
+ className="font-bold text-primary hover:opacity-80 flex items-center"
125
+ href={shipment.tracking}
126
+ target="_blank"
127
+ rel="noreferrer"
128
+ >
129
+ <span className="sicon-shipping rtl:ml-1 ltr:mr-1"></span>
130
+ {t('pages.orders.tracking_url')}
131
+ </a>
132
+ )}
133
+ </div>
134
+ </div>
135
+ );
136
+ }
137
+
138
+ /**
139
+ * The shipping company rows above the items (Twig's per-package titles). The order carries only
140
+ * its first shipment, so the rest come from the shipments endpoint.
141
+ */
142
+ export function ShippingHeader({ twig, order }: { twig: TwigOrder; order: Order }) {
143
+ const { data } = useQuery({
144
+ ...orderApi.queries.shipments(String(order.id)),
145
+ enabled: order.features.shippable && !twig.is_pickable,
146
+ });
147
+ if (twig.is_pickable) return null;
148
+
149
+ const shipments: Shipment[] = data?.length
150
+ ? data.map((shipment) => ({ ...shipment, tracking: shipment.tracking_url }))
151
+ : twig.shipping
152
+ ? [{ ...twig.shipping, tracking: twig.shipping.tracing_link }]
153
+ : [];
154
+
155
+ return (
156
+ <>
157
+ {shipments.map((shipment) => (
158
+ <ShippingRow key={shipment.id ?? shipment.name} shipment={shipment} />
159
+ ))}
160
+ </>
161
+ );
162
+ }
163
+
164
+ /** An option's price as a number: the API sends a number, `{ amount }` or an empty array. */
165
+ const optionPrice = (price: unknown): number =>
166
+ typeof price === 'number' ? price : ((price as { amount?: number } | null)?.amount ?? 0);
167
+
168
+ /** The order-level options table (`order.options`). */
169
+ export function OrderOptionsTable({
170
+ options,
171
+ money,
172
+ currency,
173
+ }: {
174
+ options: NonNullable<TwigOrder['options']>;
175
+ money: FormatMoney;
176
+ currency: string;
177
+ }) {
178
+ const { t } = useTranslation();
179
+ return (
180
+ <div className="bg-white p-5 rounded-md">
181
+ <h2 className="mb-3.5 text-sm font-bold">{t('pages.checkout.cart_options_title')}</h2>
182
+ <table className="table-fixed w-full border border-gray-200">
183
+ <thead>
184
+ <tr className="border-b border-gray-200">
185
+ <th scope="col" className="p-3 text-start text-sm">
186
+ {t('pages.order.option_name')}
187
+ </th>
188
+ <th scope="col" className="p-3 text-sm">
189
+ {t('pages.order.option_content')}
190
+ </th>
191
+ <th scope="col" className="p-3 rtl:text-left ltr:text-right text-sm">
192
+ {t('pages.products.price')}
193
+ </th>
194
+ </tr>
195
+ </thead>
196
+ <tbody>
197
+ {options.flatMap((option) =>
198
+ (option.options ?? []).map((value) => (
199
+ <tr
200
+ key={`${value.name}:${value.value}`}
201
+ className="border-b last:border-b-0 border-gray-200"
202
+ >
203
+ <td className="text-sm p-3">{value.name} :</td>
204
+ <td className="text-center p-3 font-medium text-xs">{value.value}</td>
205
+ <td className="rtl:text-start ltr:text-end p-3 font-medium text-xs">
206
+ <strong>{money(optionPrice(value.price), currency)}</strong>
207
+ </td>
208
+ </tr>
209
+ ))
210
+ )}
211
+ </tbody>
212
+ </table>
213
+ </div>
214
+ );
215
+ }
@@ -0,0 +1,38 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { OrderSinglePageProps } from '../types';
3
+
4
+ export type Order = OrderSinglePageProps['order'];
5
+ export type OrderItem = Order['items'][number];
6
+
7
+ export interface TwigRating {
8
+ id?: number;
9
+ stars?: number;
10
+ content?: string;
11
+ can_update?: boolean;
12
+ }
13
+
14
+ export interface TwigItem {
15
+ name: string;
16
+ quantity: number;
17
+ product?: { id: number; url?: string; type?: string; image?: { url?: string } };
18
+ options?: unknown[];
19
+ }
20
+
21
+ /** The order as `orders/{id}` answers a non-React theme: what the Twig templates read. */
22
+ export interface TwigOrder {
23
+ items: TwigItem[];
24
+ links?: Array<{ url: string; label: string }>;
25
+ shipping?: {
26
+ id?: number;
27
+ name?: string;
28
+ logo?: string;
29
+ number?: string;
30
+ tracing_link?: string | null;
31
+ };
32
+ rating?: { store?: TwigRating; shipping?: TwigRating } | unknown[];
33
+ can_rate?: boolean;
34
+ is_pickable?: boolean;
35
+ options?: Array<{ options?: Array<{ name: string; value: string; price?: unknown }> }>;
36
+ }
37
+
38
+ export type FormatMoney = (amount: number, currency?: string) => ReactNode;
@@ -0,0 +1,29 @@
1
+ import type { Page } from '../../../types';
2
+ import type { Pagination } from '../../../api/types';
3
+ import type { TwilightOrder } from '../../../api/order';
4
+ import type { Order, OrderListItem } from '../types';
5
+
6
+ export type { Order, OrderListItem };
7
+
8
+ /** URL query parameters for orders page */
9
+ export interface OrdersQuery {
10
+ status?: string;
11
+ feedback_status?: string;
12
+ }
13
+
14
+ export interface OrdersPageProps {
15
+ page: Page;
16
+ orders: OrderListItem[];
17
+ cursor?: Pagination;
18
+ query?: OrdersQuery;
19
+ }
20
+
21
+ export interface OrderSinglePageProps {
22
+ page: Page;
23
+ order: Order;
24
+ /** The same order as the Twilight components read it; null when it could not be loaded. */
25
+ componentsOrder?: TwilightOrder | null;
26
+ }
27
+
28
+ /** URL search params for orders routes - aliases OrdersQuery */
29
+ export type OrdersSearchParams = OrdersQuery;
@@ -0,0 +1,30 @@
1
+ import { SallaUserProfile } from '@salla.sa/twilight-components-react/user-profile';
2
+ import { SallaVerify } from '@salla.sa/twilight-components-react/verify';
3
+ import { SallaUserSettings } from '@salla.sa/twilight-components-react/user-settings';
4
+ import { HookSlot, useUser } from '../../../hooks';
5
+ import type { ProfilePageProps } from './types';
6
+
7
+ export function ProfilePage(_props: ProfilePageProps) {
8
+ const { data: user } = useUser();
9
+
10
+ return (
11
+ <>
12
+ <HookSlot name="customer:profile.start" />
13
+
14
+ <HookSlot name="customer:profile.form.start" />
15
+
16
+ <SallaUserProfile />
17
+
18
+ <HookSlot name="customer:profile.form.end" />
19
+
20
+ <SallaVerify />
21
+
22
+ <SallaUserSettings
23
+ {...(user?.preferences?.notifications_enabled ? { isNotifiable: true } : {})}
24
+ className="mt-10 block"
25
+ />
26
+
27
+ <HookSlot name="customer:profile.end" />
28
+ </>
29
+ );
30
+ }