@mohasinac/appkit 4.30.19 → 4.31.0

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 (417) hide show
  1. package/dist/_internal/client/features/layout/useSidebarSearch.d.ts +21 -5
  2. package/dist/_internal/client/features/layout/useSidebarSearch.js +27 -6
  3. package/dist/_internal/client/features/lottery/LotteryAdminEditView.d.ts +23 -3
  4. package/dist/_internal/client/features/lottery/LotteryAdminEditView.js +106 -87
  5. package/dist/_internal/client/features/lottery/LotteryPullForm.d.ts +16 -5
  6. package/dist/_internal/client/features/lottery/LotteryPullForm.js +65 -40
  7. package/dist/_internal/server/features/auth/permissions.d.ts +2 -0
  8. package/dist/_internal/server/features/auth/permissions.js +3 -2
  9. package/dist/_internal/server/features/categories/data.js +15 -4
  10. package/dist/_internal/server/features/classified/index.d.ts +0 -1
  11. package/dist/_internal/server/features/classified/index.js +0 -1
  12. package/dist/_internal/server/features/digital-code/index.d.ts +0 -1
  13. package/dist/_internal/server/features/digital-code/index.js +0 -1
  14. package/dist/_internal/server/features/live/index.d.ts +0 -1
  15. package/dist/_internal/server/features/live/index.js +0 -1
  16. package/dist/_internal/server/features/products/data.js +15 -5
  17. package/dist/_internal/server/features/products/list-public.d.ts +9 -0
  18. package/dist/_internal/server/features/products/list-public.js +95 -7
  19. package/dist/_internal/server/features/site-settings/adapters.d.ts +2 -2
  20. package/dist/_internal/server/features/site-settings/adapters.js +8 -5
  21. package/dist/_internal/server/features/tester/visibility.d.ts +2 -1
  22. package/dist/_internal/server/features/tester/visibility.js +2 -2
  23. package/dist/_internal/server/functions/scheduled.d.ts +3 -1
  24. package/dist/_internal/server/functions/scheduled.js +27 -1
  25. package/dist/_internal/server/jobs/core/hardBanCascade.js +4 -0
  26. package/dist/_internal/server/jobs/core/index.d.ts +2 -0
  27. package/dist/_internal/server/jobs/core/index.js +2 -0
  28. package/dist/_internal/server/jobs/core/pageViewPrune.d.ts +10 -0
  29. package/dist/_internal/server/jobs/core/pageViewPrune.js +44 -0
  30. package/dist/_internal/server/jobs/core/pageViewRollup.d.ts +2 -0
  31. package/dist/_internal/server/jobs/core/pageViewRollup.js +87 -0
  32. package/dist/_internal/server/jobs/handlers/index.d.ts +2 -0
  33. package/dist/_internal/server/jobs/handlers/index.js +2 -0
  34. package/dist/_internal/server/jobs/handlers/pageViewPrune.d.ts +2 -0
  35. package/dist/_internal/server/jobs/handlers/pageViewPrune.js +2 -0
  36. package/dist/_internal/server/jobs/handlers/pageViewRollup.d.ts +2 -0
  37. package/dist/_internal/server/jobs/handlers/pageViewRollup.js +2 -0
  38. package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
  39. package/dist/_internal/shared/actions/action-registry.js +69 -22
  40. package/dist/_internal/shared/checkout/rules/classified.rule.d.ts +9 -4
  41. package/dist/_internal/shared/checkout/rules/classified.rule.js +7 -2
  42. package/dist/_internal/shared/features/layout/matchesNavQuery.d.ts +14 -0
  43. package/dist/_internal/shared/features/layout/matchesNavQuery.js +72 -0
  44. package/dist/_internal/shared/features/layout/types.d.ts +37 -1
  45. package/dist/_internal/shared/features/layout/types.js +19 -1
  46. package/dist/_internal/shared/features/notifications/action-url.d.ts +9 -1
  47. package/dist/_internal/shared/features/notifications/action-url.js +47 -0
  48. package/dist/_internal/shared/features/offers/config.d.ts +65 -0
  49. package/dist/_internal/shared/features/offers/config.js +73 -2
  50. package/dist/_internal/shared/features/orders/schema.d.ts +19 -1
  51. package/dist/_internal/shared/features/orders/schema.js +22 -2
  52. package/dist/_internal/shared/features/site-settings/types.d.ts +12 -3
  53. package/dist/_internal/shared/listing-types/capabilities.d.ts +8 -2
  54. package/dist/_internal/shared/listing-types/capabilities.js +6 -1
  55. package/dist/_internal/shared/listing-types/classified/ctas.js +6 -1
  56. package/dist/_internal/shared/listing-types/feature-flags.d.ts +10 -5
  57. package/dist/_internal/shared/listing-types/feature-flags.js +11 -6
  58. package/dist/client.d.ts +37 -20
  59. package/dist/client.js +36 -14
  60. package/dist/configs/next.js +10 -2
  61. package/dist/constants/api-endpoints.d.ts +18 -54
  62. package/dist/constants/api-endpoints.js +6 -26
  63. package/dist/constants/field-names.d.ts +6 -24
  64. package/dist/constants/field-names.js +10 -27
  65. package/dist/constants/geo/countries.d.ts +50 -0
  66. package/dist/constants/geo/countries.js +129 -0
  67. package/dist/constants/geo/subdivisions.d.ts +13 -0
  68. package/dist/constants/geo/subdivisions.js +104 -0
  69. package/dist/constants/index.d.ts +2 -2
  70. package/dist/constants/index.js +2 -2
  71. package/dist/constants/table-keys.d.ts +24 -0
  72. package/dist/constants/table-keys.js +28 -0
  73. package/dist/contracts/extend.d.ts +0 -9
  74. package/dist/contracts/index.d.ts +1 -1
  75. package/dist/contracts/realtime-session.js +7 -0
  76. package/dist/core/browser.d.ts +1 -1
  77. package/dist/core/browser.js +1 -1
  78. package/dist/core/index.d.ts +1 -1
  79. package/dist/core/index.js +1 -1
  80. package/dist/core/site-config.d.ts +0 -3
  81. package/dist/core/site-config.js +0 -3
  82. package/dist/errors/messages.d.ts +0 -8
  83. package/dist/errors/messages.js +0 -9
  84. package/dist/features/about/schemas/index.d.ts +8 -8
  85. package/dist/features/account/components/AddressFilters.js +32 -11
  86. package/dist/features/account/components/AddressForm.d.ts +26 -25
  87. package/dist/features/account/components/AddressForm.js +81 -103
  88. package/dist/features/account/components/AddressesIndexListing.js +8 -4
  89. package/dist/features/account/components/UserSidebar.d.ts +3 -4
  90. package/dist/features/account/components/UserSupportView.js +89 -58
  91. package/dist/features/account/components/index.d.ts +1 -7
  92. package/dist/features/account/components/index.js +0 -3
  93. package/dist/features/account/hooks/useAddresses.d.ts +4 -3
  94. package/dist/features/account/hooks/useAddresses.js +4 -6
  95. package/dist/features/account/hooks/useCollapsedSections.d.ts +51 -10
  96. package/dist/features/account/hooks/useCollapsedSections.js +211 -38
  97. package/dist/features/account/hooks/useProfile.d.ts +8 -0
  98. package/dist/features/account/index.d.ts +0 -3
  99. package/dist/features/account/index.js +0 -3
  100. package/dist/features/account/schemas/index.d.ts +0 -92
  101. package/dist/features/account/schemas/index.js +42 -20
  102. package/dist/features/addresses/components/AddressLocationFields.d.ts +13 -0
  103. package/dist/features/addresses/components/AddressLocationFields.js +41 -0
  104. package/dist/features/addresses/hooks/usePostalLookup.d.ts +17 -0
  105. package/dist/features/addresses/hooks/usePostalLookup.js +133 -0
  106. package/dist/features/addresses/schemas/address-form.d.ts +423 -0
  107. package/dist/features/addresses/schemas/address-form.js +212 -0
  108. package/dist/features/addresses/schemas/index.d.ts +1 -0
  109. package/dist/features/addresses/schemas/index.js +8 -0
  110. package/dist/features/admin/actions/admin-read-actions.d.ts +1 -1
  111. package/dist/features/admin/actions/index.d.ts +0 -1
  112. package/dist/features/admin/actions/index.js +0 -1
  113. package/dist/features/admin/actions/notification-actions.js +1 -41
  114. package/dist/features/admin/components/AdminActionIndexView.d.ts +32 -0
  115. package/dist/features/admin/components/AdminActionIndexView.js +128 -0
  116. package/dist/features/admin/components/AdminAdEditorView.js +159 -163
  117. package/dist/features/admin/components/AdminAddressEditorView.js +97 -55
  118. package/dist/features/admin/components/AdminBrandEditorView.d.ts +15 -0
  119. package/dist/features/admin/components/AdminBrandEditorView.js +113 -77
  120. package/dist/features/admin/components/AdminBundleEditorView.d.ts +19 -9
  121. package/dist/features/admin/components/AdminBundleEditorView.js +136 -168
  122. package/dist/features/admin/components/AdminCategoryEditorView.js +120 -43
  123. package/dist/features/admin/components/AdminCouponEditorView.js +145 -109
  124. package/dist/features/admin/components/AdminEmployeeEditorView.js +125 -56
  125. package/dist/features/admin/components/AdminFaqEditorView.js +112 -58
  126. package/dist/features/admin/components/AdminFeatureEditorView.js +108 -68
  127. package/dist/features/admin/components/AdminNavEditorView.js +69 -44
  128. package/dist/features/admin/components/AdminOrderEditorView.js +47 -10
  129. package/dist/features/admin/components/AdminPrizeDrawsView.js +16 -2
  130. package/dist/features/admin/components/AdminSidebar.d.ts +11 -7
  131. package/dist/features/admin/components/AdminSiteSettingsView.js +37 -37
  132. package/dist/features/admin/components/AdminStoreEditorView.js +75 -52
  133. package/dist/features/admin/components/AdminSublistingCategoryEditorView.js +71 -30
  134. package/dist/features/admin/components/AdminTesterChecklistItemEditorView.js +95 -65
  135. package/dist/features/admin/components/BrandQuickCreateForm.d.ts +10 -0
  136. package/dist/features/admin/components/BrandQuickCreateForm.js +49 -26
  137. package/dist/features/admin/components/CategoryQuickCreateForm.d.ts +11 -0
  138. package/dist/features/admin/components/CategoryQuickCreateForm.js +48 -26
  139. package/dist/features/admin/components/index.d.ts +2 -2
  140. package/dist/features/admin/components/index.js +1 -1
  141. package/dist/features/admin/constants/site-settings-tabs.d.ts +120 -0
  142. package/dist/features/admin/constants/site-settings-tabs.js +152 -0
  143. package/dist/features/admin/index.d.ts +0 -3
  144. package/dist/features/admin/index.js +0 -2
  145. package/dist/features/admin/repository/analytics-rollup.repository.d.ts +35 -0
  146. package/dist/features/admin/repository/analytics-rollup.repository.js +30 -0
  147. package/dist/features/admin/schemas/admin-editor-forms.d.ts +56 -57
  148. package/dist/features/admin/schemas/admin-editor-forms.js +97 -54
  149. package/dist/features/admin/schemas/admin-ops-forms.d.ts +57 -5
  150. package/dist/features/admin/schemas/admin-ops-forms.js +104 -20
  151. package/dist/features/admin/schemas/admin-user-form.js +7 -0
  152. package/dist/features/admin/schemas/firestore.d.ts +48 -95
  153. package/dist/features/admin/schemas/firestore.js +15 -151
  154. package/dist/features/admin/schemas/nav-item-form.js +9 -2
  155. package/dist/features/admin/server.d.ts +0 -4
  156. package/dist/features/admin/server.js +0 -2
  157. package/dist/features/admin/types/index.d.ts +0 -7
  158. package/dist/features/analytics/repository/page-views.repository.d.ts +14 -0
  159. package/dist/features/analytics/repository/page-views.repository.js +24 -0
  160. package/dist/features/auth/actions/index.d.ts +0 -1
  161. package/dist/features/auth/actions/index.js +0 -1
  162. package/dist/features/auth/actions/realtime-token-actions.js +1 -12
  163. package/dist/features/auth/auth-helpers.js +5 -7
  164. package/dist/features/auth/components/Guards.js +2 -1
  165. package/dist/features/auth/components/LoginForm.d.ts +0 -2
  166. package/dist/features/auth/components/LoginForm.js +1 -3
  167. package/dist/features/auth/components/RegisterForm.js +62 -19
  168. package/dist/features/auth/permissions/constants.d.ts +27 -1
  169. package/dist/features/auth/role-predicates.d.ts +75 -7
  170. package/dist/features/auth/role-predicates.js +28 -2
  171. package/dist/features/auth/schemas/firestore.d.ts +22 -0
  172. package/dist/features/auth/schemas/index.d.ts +1 -1
  173. package/dist/features/auth/schemas/index.js +44 -8
  174. package/dist/features/auth/types/index.d.ts +14 -1
  175. package/dist/features/blog/api/route.js +10 -2
  176. package/dist/features/blog/components/BlogIndexListing.js +1 -1
  177. package/dist/features/blog/hooks/useBlog.js +2 -2
  178. package/dist/features/blog/schemas/index.d.ts +4 -0
  179. package/dist/features/blog/schemas/index.js +2 -0
  180. package/dist/features/blog/types/index.d.ts +1 -1
  181. package/dist/features/catalogue/components/CatalogueItemEditorView.d.ts +22 -0
  182. package/dist/features/catalogue/components/CatalogueItemEditorView.js +112 -52
  183. package/dist/features/catalogue/schemas/validation.d.ts +4 -4
  184. package/dist/features/catalogue/schemas/validation.js +47 -10
  185. package/dist/features/categories/schemas/bundle-form.d.ts +142 -0
  186. package/dist/features/categories/schemas/bundle-form.js +149 -0
  187. package/dist/features/classified/components/ClassifiedDetailPageView.d.ts +5 -4
  188. package/dist/features/classified/components/ClassifiedDetailPageView.js +37 -16
  189. package/dist/features/consultation/components/ConsultationForm.js +1 -1
  190. package/dist/features/consultation/schemas/index.js +34 -10
  191. package/dist/features/corporate/schemas/index.js +36 -15
  192. package/dist/features/filters/FilterPanel.js +3 -3
  193. package/dist/features/filters/RangeFilter.d.ts +10 -0
  194. package/dist/features/filters/RangeFilter.js +41 -4
  195. package/dist/features/homepage/components/MarketplaceHomepageView.js +24 -5
  196. package/dist/features/homepage/hooks/useBlogArticles.js +1 -1
  197. package/dist/features/layout/BottomActions.js +84 -11
  198. package/dist/features/layout/BottomActionsContext.d.ts +1 -6
  199. package/dist/features/layout/BottomActionsContext.js +1 -1
  200. package/dist/features/layout/hooks/useBottomActions.js +2 -2
  201. package/dist/features/layout/hooks/useFormBottomActions.d.ts +12 -1
  202. package/dist/features/layout/hooks/useFormBottomActions.js +12 -6
  203. package/dist/features/lottery/schemas/config-write.d.ts +9 -5
  204. package/dist/features/lottery/schemas/config-write.js +69 -9
  205. package/dist/features/orders/schemas/buyer-forms.d.ts +6 -3
  206. package/dist/features/orders/schemas/buyer-forms.js +31 -3
  207. package/dist/features/orders/schemas/index.d.ts +2 -2
  208. package/dist/features/products/components/GroupSettingsPanel.js +3 -1
  209. package/dist/features/products/components/MakeOfferButton.d.ts +13 -2
  210. package/dist/features/products/components/MakeOfferButton.js +33 -11
  211. package/dist/features/products/components/ProductDetailActions.js +0 -1
  212. package/dist/features/products/components/ProductDetailPageView.d.ts +7 -3
  213. package/dist/features/products/components/ProductDetailPageView.js +8 -5
  214. package/dist/features/products/constants/action-defs.d.ts +1 -2
  215. package/dist/features/products/constants/action-defs.js +40 -43
  216. package/dist/features/products/repository/products.repository.d.ts +5 -1
  217. package/dist/features/products/repository/products.repository.js +23 -1
  218. package/dist/features/products/schemas/firestore.d.ts +7 -3
  219. package/dist/features/products/schemas/product-features.validators.js +3 -0
  220. package/dist/features/promotions/components/CouponCard.js +8 -7
  221. package/dist/features/scams/schemas/firestore.d.ts +15 -1
  222. package/dist/features/scams/schemas/report-form.d.ts +5 -5
  223. package/dist/features/scams/schemas/report-form.js +18 -3
  224. package/dist/features/search/action-index/derive.d.ts +49 -0
  225. package/dist/features/search/action-index/derive.js +121 -0
  226. package/dist/features/search/action-index/repository.d.ts +42 -0
  227. package/dist/features/search/action-index/repository.js +100 -0
  228. package/dist/features/search/action-index/settings-entries.d.ts +41 -0
  229. package/dist/features/search/action-index/settings-entries.js +268 -0
  230. package/dist/features/search/action-index/types.d.ts +81 -0
  231. package/dist/features/search/action-index/types.js +102 -0
  232. package/dist/features/search/action-index/validate-entry.d.ts +34 -0
  233. package/dist/features/search/action-index/validate-entry.js +114 -0
  234. package/dist/features/search/hooks/useNavSuggestions.d.ts +5 -1
  235. package/dist/features/search/hooks/useNavSuggestions.js +23 -3
  236. package/dist/features/search/repository/search.repository.js +3 -1
  237. package/dist/features/seller/actions/offer-actions.js +43 -24
  238. package/dist/features/seller/actions/seller-actions.js +29 -5
  239. package/dist/features/seller/components/CategoryChipPicker.d.ts +9 -0
  240. package/dist/features/seller/components/CategoryChipPicker.js +12 -0
  241. package/dist/features/seller/components/SellerAddressesView.js +5 -1
  242. package/dist/features/seller/components/SellerAnalyticsAlertsView.js +83 -43
  243. package/dist/features/seller/components/SellerArtView.d.ts +14 -7
  244. package/dist/features/seller/components/SellerArtView.js +4 -119
  245. package/dist/features/seller/components/SellerClassifiedView.d.ts +14 -7
  246. package/dist/features/seller/components/SellerClassifiedView.js +4 -124
  247. package/dist/features/seller/components/SellerCouponEditorView.d.ts +22 -1
  248. package/dist/features/seller/components/SellerCouponEditorView.js +91 -45
  249. package/dist/features/seller/components/SellerDigitalCodesView.d.ts +14 -7
  250. package/dist/features/seller/components/SellerDigitalCodesView.js +4 -126
  251. package/dist/features/seller/components/SellerListingTypeView.d.ts +66 -0
  252. package/dist/features/seller/components/SellerListingTypeView.js +277 -0
  253. package/dist/features/seller/components/SellerLiveView.d.ts +14 -7
  254. package/dist/features/seller/components/SellerLiveView.js +4 -126
  255. package/dist/features/seller/components/SellerSidebar.d.ts +3 -6
  256. package/dist/features/seller/components/SellerStickersView.d.ts +14 -7
  257. package/dist/features/seller/components/SellerStickersView.js +4 -119
  258. package/dist/features/seller/components/SellerSupportView.d.ts +31 -0
  259. package/dist/features/seller/components/SellerSupportView.js +100 -0
  260. package/dist/features/seller/components/index.d.ts +4 -8
  261. package/dist/features/seller/components/index.js +2 -4
  262. package/dist/features/seller/index.d.ts +0 -1
  263. package/dist/features/seller/index.js +0 -1
  264. package/dist/features/seller/schemas/coupon-form.d.ts +214 -0
  265. package/dist/features/seller/schemas/coupon-form.js +155 -23
  266. package/dist/features/seller/schemas/offer-forms.d.ts +16 -7
  267. package/dist/features/seller/schemas/offer-forms.js +28 -12
  268. package/dist/features/shell/FormShell.js +2 -2
  269. package/dist/features/shell/QuickFormDrawer.js +2 -2
  270. package/dist/features/shell/SectionForm.d.ts +19 -1
  271. package/dist/features/shell/SectionForm.js +104 -17
  272. package/dist/features/shell/build-sections.d.ts +23 -0
  273. package/dist/features/shell/build-sections.js +106 -8
  274. package/dist/features/shell/field-ui-meta.d.ts +44 -0
  275. package/dist/features/shell/field-ui-meta.js +14 -7
  276. package/dist/features/shell/form-sections.d.ts +46 -0
  277. package/dist/features/shell/form-sections.js +114 -0
  278. package/dist/features/shipments/components/AdminShipmentEditorView.js +87 -64
  279. package/dist/features/shipments/schemas/validation.d.ts +2 -2
  280. package/dist/features/shipments/schemas/validation.js +44 -13
  281. package/dist/features/store-extensions/schemas/custom-role-form.js +6 -2
  282. package/dist/features/store-extensions/schemas/listing-template-form.d.ts +7 -7
  283. package/dist/features/store-extensions/schemas/payout-method-form.js +14 -0
  284. package/dist/features/stores/actions/store-query-actions.js +3 -2
  285. package/dist/features/stores/api/[storeSlug]/auctions/route.js +3 -1
  286. package/dist/features/stores/api/[storeSlug]/products/route.js +3 -1
  287. package/dist/features/support/repository/support.repository.d.ts +21 -0
  288. package/dist/features/support/repository/support.repository.js +63 -0
  289. package/dist/features/support/schemas/firestore.d.ts +27 -2
  290. package/dist/features/support/schemas/firestore.js +2 -0
  291. package/dist/features/support/schemas/ticket-create-form.js +7 -0
  292. package/dist/features/tester/schemas/checklist-item-form.d.ts +43 -0
  293. package/dist/features/tester/schemas/checklist-item-form.js +109 -0
  294. package/dist/features/tester/seed-data/blog-tester-seed-data.js +2 -2
  295. package/dist/features/tester/seed-data/categories-tester-seed-data.js +2 -2
  296. package/dist/features/tester/seed-data/events-tester-seed-data.js +5 -5
  297. package/dist/features/tester/seed-data/orders-tester-seed-data.js +2 -2
  298. package/dist/features/tester/seed-data/products-tester-seed-data.js +48 -49
  299. package/dist/features/tester/seed-data/stores-tester-seed-data.js +3 -3
  300. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +275 -29
  301. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +48 -12
  302. package/dist/http/api-handler.js +2 -1
  303. package/dist/index.d.ts +24 -103
  304. package/dist/index.js +33 -141
  305. package/dist/jobs.d.ts +1 -1
  306. package/dist/jobs.js +1 -1
  307. package/dist/monitoring/browser.d.ts +0 -2
  308. package/dist/monitoring/browser.js +12 -1
  309. package/dist/monitoring/index.d.ts +0 -2
  310. package/dist/monitoring/index.js +0 -1
  311. package/dist/next/api/routeHandler.js +6 -3
  312. package/dist/next/index.d.ts +1 -2
  313. package/dist/next/index.js +0 -1
  314. package/dist/next/middleware/index.d.ts +0 -2
  315. package/dist/next/middleware/index.js +0 -1
  316. package/dist/next/routing/route-map.d.ts +8 -7
  317. package/dist/next/routing/route-map.js +10 -3
  318. package/dist/providers/db-firebase/admin.js +15 -1
  319. package/dist/providers/db-firebase/sieve.d.ts +22 -0
  320. package/dist/react/hooks/useListingTypeFlags.d.ts +1 -1
  321. package/dist/react/hooks/useListingTypeFlags.js +1 -1
  322. package/dist/react/hooks/usePendingFilters.js +5 -3
  323. package/dist/react/hooks/usePendingTable.js +15 -3
  324. package/dist/repositories/index.d.ts +0 -1
  325. package/dist/repositories/index.js +0 -1
  326. package/dist/schemas/registry.d.ts +197 -232
  327. package/dist/schemas/registry.js +5 -6
  328. package/dist/schemas/webhooks/razorpay.d.ts +50 -50
  329. package/dist/security/authorization.d.ts +9 -0
  330. package/dist/security/authorization.js +16 -2
  331. package/dist/security/browser.d.ts +1 -3
  332. package/dist/security/browser.js +5 -2
  333. package/dist/security/index.d.ts +1 -3
  334. package/dist/security/index.js +19 -2
  335. package/dist/security/pii-encrypt.js +16 -0
  336. package/dist/security/pii-schemas.d.ts +0 -14
  337. package/dist/security/pii-schemas.js +7 -15
  338. package/dist/seed/_helpers/category-forest.js +2 -2
  339. package/dist/seed/_helpers/media.d.ts +19 -0
  340. package/dist/seed/_helpers/media.js +75 -0
  341. package/dist/seed/blog-posts-seed-data.js +17 -17
  342. package/dist/seed/carousel-slides-seed-data.js +7 -7
  343. package/dist/seed/cart-seed-data.js +13 -13
  344. package/dist/seed/categories-seed-data.js +10 -10
  345. package/dist/seed/events-seed-data.js +24 -24
  346. package/dist/seed/factories/product.factory.js +4 -4
  347. package/dist/seed/factories/store.factory.js +3 -3
  348. package/dist/seed/factories/user.factory.js +2 -2
  349. package/dist/seed/grouped-listings-seed-data.js +11 -11
  350. package/dist/seed/homepage-sections-seed-data.js +2 -2
  351. package/dist/seed/index.d.ts +0 -1
  352. package/dist/seed/index.js +0 -1
  353. package/dist/seed/manifest.d.ts +1 -1
  354. package/dist/seed/manifest.js +0 -5
  355. package/dist/seed/notifications-seed-data.js +20 -1
  356. package/dist/seed/orders-seed-data.js +2 -2
  357. package/dist/seed/products-art-seed-data.js +16 -16
  358. package/dist/seed/products-auctions-seed-data.js +34 -34
  359. package/dist/seed/products-classifieds-seed-data.js +35 -37
  360. package/dist/seed/products-digital-codes-seed-data.js +20 -20
  361. package/dist/seed/products-live-items-seed-data.js +11 -11
  362. package/dist/seed/products-preorders-seed-data.js +13 -13
  363. package/dist/seed/products-prize-draws-seed-data.js +43 -43
  364. package/dist/seed/products-standard-seed-data.js +54 -54
  365. package/dist/seed/products-stickers-seed-data.js +15 -15
  366. package/dist/seed/reviews-seed-data.js +4 -4
  367. package/dist/seed/scammers-seed-data.js +3 -3
  368. package/dist/seed/site-settings-seed-data.js +11 -24
  369. package/dist/seed/store-extensions-seed-data.js +10 -10
  370. package/dist/seed/stores-seed-data.js +11 -11
  371. package/dist/seed/support-tickets-seed-data.d.ts +14 -0
  372. package/dist/seed/support-tickets-seed-data.js +20 -1
  373. package/dist/seed/users-seed-data.js +20 -20
  374. package/dist/server-entry.d.ts +0 -1
  375. package/dist/server-entry.js +0 -1
  376. package/dist/server.d.ts +9 -6
  377. package/dist/server.js +7 -13
  378. package/dist/styles.css +248 -68
  379. package/dist/tailwind-utilities.css +1 -1
  380. package/dist/tokens/themes/default-dark.js +2 -2
  381. package/dist/tokens/themes/default-light.js +2 -2
  382. package/dist/tokens/tokens.css +24 -4
  383. package/dist/ui/components/ActionRow.d.ts +50 -0
  384. package/dist/ui/components/ActionRow.js +53 -0
  385. package/dist/ui/components/ActionRow.style.css +145 -0
  386. package/dist/ui/components/Drawer.d.ts +10 -0
  387. package/dist/ui/components/Drawer.js +2 -1
  388. package/dist/ui/components/FilterDrawer.js +4 -1
  389. package/dist/ui/components/FilterDrawer.style.css +6 -12
  390. package/dist/ui/components/FormActionBar.js +14 -1
  391. package/dist/ui/components/FormActionBar.style.css +12 -11
  392. package/dist/ui/components/ListingLayout.js +8 -1
  393. package/dist/ui/components/ListingLayout.style.css +6 -13
  394. package/dist/ui/components/Modal.d.ts +15 -1
  395. package/dist/ui/components/Modal.js +17 -3
  396. package/dist/ui/components/QuickCreateModal.js +2 -2
  397. package/dist/ui/components/QuickCreateModal.style.css +78 -84
  398. package/dist/ui/components/RecordDetailModal.js +2 -2
  399. package/dist/ui/components/SideDrawer.d.ts +8 -0
  400. package/dist/ui/components/SideDrawer.js +2 -1
  401. package/dist/ui/components/SideDrawer.style.css +6 -3
  402. package/dist/ui/components/SideModal.d.ts +11 -1
  403. package/dist/ui/components/SideModal.js +3 -2
  404. package/dist/ui/components/SideModal.style.css +14 -0
  405. package/dist/ui/components/Typography.style.css +33 -24
  406. package/dist/ui/components/index.style.css +1 -0
  407. package/dist/ui/forms/FormShell.style.css +260 -311
  408. package/dist/ui/index.d.ts +2 -0
  409. package/dist/ui/index.js +1 -0
  410. package/dist/utils/index.d.ts +0 -1
  411. package/dist/utils/index.js +0 -1
  412. package/dist/validation/index.d.ts +1 -1
  413. package/dist/validation/index.js +1 -1
  414. package/dist/validation/schemas.d.ts +0 -19
  415. package/dist/validation/schemas.js +8 -19
  416. package/package.json +1 -1
  417. package/scripts/seed-cli.mjs +3 -6
@@ -300,15 +300,22 @@ export function inferFieldUiMeta(name, schema) {
300
300
  meta.derived = true;
301
301
  meta.tier = meta.tier ?? "t2-server";
302
302
  }
303
- // >5 options is the standing PaginatedSelect threshold. Recorded as `help`
304
- // rather than a separate flag so the renderer can decide without a second
305
- // source of truth about what "many options" means.
306
- const options = enumOptions(inner);
307
- if (meta.kind === "select" && options != null && options.length > 5) {
308
- meta.help = meta.help ?? "paginated";
309
- }
310
303
  return meta;
311
304
  }
305
+ /**
306
+ * Above this many options a select becomes a searchable `<PaginatedSelect>`.
307
+ * The standing UI rule (CLAUDE.md § UI Primitive Rules): more than five options
308
+ * and a plain dropdown is unscannable.
309
+ *
310
+ * 🛑 This is the WHOLE mechanism — there is deliberately no `paginated` flag on
311
+ * `FieldUiMeta`. It used to be smuggled through `help` as the literal string
312
+ * `"paginated"`, which broke in both directions: the assignment was
313
+ * `meta.help ?? "paginated"`, so a select that had real help text never became
314
+ * paginated; and the renderer had to blank `help` to avoid printing the
315
+ * sentinel, so one that DID become paginated could never show help. Counting
316
+ * the options at render time needs neither.
317
+ */
318
+ export const PAGINATED_SELECT_THRESHOLD = 5;
312
319
  /**
313
320
  * The field's final metadata: inference first, explicit registration on top.
314
321
  *
@@ -0,0 +1,46 @@
1
+ /**
2
+ * The canonical section ORDER vocabulary.
3
+ *
4
+ * ## Why this is a `group`, not a rename of `section`
5
+ *
6
+ * The plan called for collapsing the 58 free-form section ids in use across 30
7
+ * schemas onto a closed 12-value set. Measured before doing it, that merges
8
+ * sections in 7 files and 8 places — the scam report's `who` + `what` +
9
+ * `declare` become one blob, coupons' `limits` + `validity` collapse together,
10
+ * blog's `content` + `seo` merge, and payout methods lose the split between
11
+ * `method` and `bank`.
12
+ *
13
+ * The mistake was treating one identifier as two things. A section id is the
14
+ * RENDERED UNIT — fine-grained, form-specific, and the thing whose heading the
15
+ * user reads (`build-sections` falls back to `humaniseFieldName(sectionId)`, so
16
+ * 144 of the 228 annotations get their visible heading straight from the id).
17
+ * What the ordering rule actually needs is a PRIORITY BAND: required first,
18
+ * danger last, everything else in a predictable middle.
19
+ *
20
+ * So the id stays free-form and every section declares a `group` from this
21
+ * closed union. Order and default-open derive from the group; identity and
22
+ * heading stay with the id. Nothing merges, and the audit still has a closed
23
+ * set to check against.
24
+ *
25
+ * ## Ordering
26
+ *
27
+ * Array order IS render order. `required` is index 0 and is the section left
28
+ * open by default; `danger` is always last. That gives "1. Required → 2.
29
+ * Additional → … → least important last" mechanically, with no per-form
30
+ * `sectionOrder` to maintain.
31
+ */
32
+ export declare const FORM_SECTION_GROUP: readonly ["required", "identity", "classification", "pricing", "inventory", "media", "logistics", "relationships", "schedule", "visibility", "advanced", "danger"];
33
+ export type FormSectionGroup = (typeof FORM_SECTION_GROUP)[number];
34
+ /** Position of a group in render order; unknown groups sort just before danger. */
35
+ export declare function groupRank(group: FormSectionGroup | undefined): number;
36
+ /**
37
+ * Default group for each section id currently in use, so 30 schemas do not each
38
+ * need a hand-written `group`. A section id absent here must declare its own —
39
+ * `audit-form-sectionised` fails otherwise, which is what stops a new id
40
+ * silently defaulting into the middle of the form.
41
+ *
42
+ * Derived from the 58 ids actually present, counted rather than guessed.
43
+ */
44
+ export declare const SECTION_GROUP_DEFAULTS: Record<string, FormSectionGroup>;
45
+ /** The group for a section id — its declared group, else the default, else advanced. */
46
+ export declare function resolveSectionGroup(sectionId: string, declared?: FormSectionGroup): FormSectionGroup;
@@ -0,0 +1,114 @@
1
+ /**
2
+ * The canonical section ORDER vocabulary.
3
+ *
4
+ * ## Why this is a `group`, not a rename of `section`
5
+ *
6
+ * The plan called for collapsing the 58 free-form section ids in use across 30
7
+ * schemas onto a closed 12-value set. Measured before doing it, that merges
8
+ * sections in 7 files and 8 places — the scam report's `who` + `what` +
9
+ * `declare` become one blob, coupons' `limits` + `validity` collapse together,
10
+ * blog's `content` + `seo` merge, and payout methods lose the split between
11
+ * `method` and `bank`.
12
+ *
13
+ * The mistake was treating one identifier as two things. A section id is the
14
+ * RENDERED UNIT — fine-grained, form-specific, and the thing whose heading the
15
+ * user reads (`build-sections` falls back to `humaniseFieldName(sectionId)`, so
16
+ * 144 of the 228 annotations get their visible heading straight from the id).
17
+ * What the ordering rule actually needs is a PRIORITY BAND: required first,
18
+ * danger last, everything else in a predictable middle.
19
+ *
20
+ * So the id stays free-form and every section declares a `group` from this
21
+ * closed union. Order and default-open derive from the group; identity and
22
+ * heading stay with the id. Nothing merges, and the audit still has a closed
23
+ * set to check against.
24
+ *
25
+ * ## Ordering
26
+ *
27
+ * Array order IS render order. `required` is index 0 and is the section left
28
+ * open by default; `danger` is always last. That gives "1. Required → 2.
29
+ * Additional → … → least important last" mechanically, with no per-form
30
+ * `sectionOrder` to maintain.
31
+ */
32
+ export const FORM_SECTION_GROUP = [
33
+ /** Cannot save without it. Open by default; a required field of ANY kind
34
+ * belongs here, including a mandatory cover image. */
35
+ "required",
36
+ /** What the record is called and says — name, slug, description, SEO. */
37
+ "identity",
38
+ /** How it is filed — category, type, scope, tags, rules. */
39
+ "classification",
40
+ /** Money — price, rates, fees, tax. */
41
+ "pricing",
42
+ /** How many and until when — stock, limits, validity windows, slots. */
43
+ "inventory",
44
+ /** Optional media — gallery, video, creative, proof. */
45
+ "media",
46
+ /** Getting it there — address, shipping, delivery, routing. */
47
+ "logistics",
48
+ /** Links to other records — owner, members, linked accounts, sync. */
49
+ "relationships",
50
+ /** When — start/end dates, announcements, alerts. */
51
+ "schedule",
52
+ /** Who can see it and do what — publish state, placement, access, permissions. */
53
+ "visibility",
54
+ /** Everything a normal user never touches — config, defaults, layout. */
55
+ "advanced",
56
+ /** Destructive and irreversible. Always last, never open by default. */
57
+ "danger",
58
+ ];
59
+ /** Position of a group in render order; unknown groups sort just before danger. */
60
+ export function groupRank(group) {
61
+ if (!group)
62
+ return FORM_SECTION_GROUP.length - 2;
63
+ const i = FORM_SECTION_GROUP.indexOf(group);
64
+ return i === -1 ? FORM_SECTION_GROUP.length - 2 : i;
65
+ }
66
+ /**
67
+ * Default group for each section id currently in use, so 30 schemas do not each
68
+ * need a hand-written `group`. A section id absent here must declare its own —
69
+ * `audit-form-sectionised` fails otherwise, which is what stops a new id
70
+ * silently defaulting into the middle of the form.
71
+ *
72
+ * Derived from the 58 ids actually present, counted rather than guessed.
73
+ */
74
+ export const SECTION_GROUP_DEFAULTS = {
75
+ // required
76
+ basics: "required", what: "required", who: "required", entry: "required",
77
+ declare: "required", ticket: "required", method: "required", card: "required",
78
+ bank: "required", connection: "required", member: "required",
79
+ // identity
80
+ seo: "identity", profile: "identity", details: "identity", detail: "identity",
81
+ content: "identity", message: "identity",
82
+ // classification
83
+ scope: "classification", target: "classification", rule: "classification",
84
+ flags: "classification",
85
+ // pricing
86
+ rates: "pricing", pricing: "pricing", payment: "pricing",
87
+ // inventory
88
+ limits: "inventory", validity: "inventory", slots: "inventory",
89
+ standing: "inventory",
90
+ // media
91
+ media: "media", creative: "media", proof: "media",
92
+ // logistics
93
+ address: "logistics", shipping: "logistics", delivery: "logistics",
94
+ routing: "logistics",
95
+ // relationships
96
+ owner: "relationships", members: "relationships", link: "relationships",
97
+ google: "relationships", sync: "relationships", subscribe: "relationships",
98
+ review: "relationships",
99
+ // schedule
100
+ schedule: "schedule", announcement: "schedule", alert: "schedule",
101
+ // visibility
102
+ visibility: "visibility", publish: "visibility", placement: "visibility",
103
+ status: "visibility", access: "visibility", permissions: "visibility",
104
+ capabilities: "visibility",
105
+ // advanced
106
+ settings: "advanced", config: "advanced", defaults: "advanced",
107
+ layout: "advanced",
108
+ // danger
109
+ ban: "danger", cancel: "danger",
110
+ };
111
+ /** The group for a section id — its declared group, else the default, else advanced. */
112
+ export function resolveSectionGroup(sectionId, declared) {
113
+ return declared ?? SECTION_GROUP_DEFAULTS[sectionId] ?? "advanced";
114
+ }
@@ -1,9 +1,13 @@
1
1
  "use client";
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import React from "react";
4
4
  import { useQueryClient } from "@tanstack/react-query";
5
5
  import { useApiMutation } from "@mohasinac/appkit/client";
6
- import { Alert, Button, Div, Form, FieldInput, FieldSelect, FieldTextarea, Grid, Heading, Stack, Table, Thead, Tbody, Tr, Th, Td, Text, TextLink, FormErrorSummary, } from "../../../ui";
6
+ import { Alert, Button, Div, FieldInput, Grid, Heading, Stack, Table, Thead, Tbody, Tr, Th, Td, Text, TextLink, FormErrorSummary, } from "../../../ui";
7
+ import { FormShellContext, useFormShellState } from "../../../ui/forms/FormShell";
8
+ import { applyZodIssues } from "../../../ui/forms/apply-zod-issues";
9
+ import { buildSectionsFromSchema, visibleValues } from "../../shell/build-sections";
10
+ import { SectionForm, useSectionFormNav } from "../../shell/SectionForm";
7
11
  import { apiClient } from "../../../http";
8
12
  import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
9
13
  import { ROUTES } from "../../../next/routing/route-map";
@@ -12,61 +16,72 @@ import { createShipmentSchema } from "../schemas/validation";
12
16
  import { useShipment } from "../hooks/useShipments";
13
17
  import { formatCurrency } from "../../../utils/number.formatter";
14
18
  import { RecordStatusTimeline } from "../../status-history/components/RecordStatusTimeline";
15
- const STATUS_OPTIONS = [
16
- { label: "Planning", value: "planning" },
17
- { label: "Ordered", value: "ordered" },
18
- { label: "In Transit", value: "in_transit" },
19
- { label: "Customs", value: "customs" },
20
- { label: "Received", value: "received" },
21
- { label: "Processing", value: "processing" },
22
- { label: "Completed", value: "completed" },
23
- { label: "Cancelled", value: "cancelled" },
24
- ];
19
+ const EMPTY_SHIPMENT = {
20
+ shipmentNumber: "",
21
+ supplierName: "",
22
+ originCountry: "",
23
+ status: "planning",
24
+ trackingNumber: "",
25
+ carrier: "",
26
+ etaDate: "",
27
+ receivedDate: "",
28
+ customsTotal: 0,
29
+ shippingTotal: 0,
30
+ laborHoursSpent: 0,
31
+ laborRatePerHour: 0,
32
+ notes: "",
33
+ };
34
+ /** A Firestore date, as a `<input type="date">` value. */
35
+ function toDateInput(value) {
36
+ if (!value)
37
+ return "";
38
+ return new Date(value).toISOString().slice(0, 10);
39
+ }
25
40
  export function AdminShipmentEditorView({ shipmentId, onSaved }) {
26
41
  const isCreate = !shipmentId;
27
42
  const queryClient = useQueryClient();
28
43
  const { shipment, lots, refetchLots } = useShipment(shipmentId);
29
- const [shipmentNumber, setShipmentNumber] = React.useState("");
30
- const [supplierName, setSupplierName] = React.useState("");
31
- const [originCountry, setOriginCountry] = React.useState("");
32
- const [status, setStatus] = React.useState("planning");
33
- const [trackingNumber, setTrackingNumber] = React.useState("");
34
- const [carrier, setCarrier] = React.useState("");
35
- const [etaDate, setEtaDate] = React.useState("");
36
- const [notes, setNotes] = React.useState("");
37
- const [customsTotalRupees, setCustomsTotalRupees] = React.useState("0");
38
- const [shippingTotalRupees, setShippingTotalRupees] = React.useState("0");
39
- const [laborHoursSpent, setLaborHoursSpent] = React.useState("0");
44
+ const [form, setForm] = React.useState(EMPTY_SHIPMENT);
45
+ const patch = (partial) => setForm((prev) => Object.assign({}, prev, partial));
40
46
  React.useEffect(() => {
41
47
  if (!shipment)
42
48
  return;
43
- setShipmentNumber(shipment.shipmentNumber);
44
- setSupplierName(shipment.supplierName);
45
- setOriginCountry(shipment.originCountry ?? "");
46
- setStatus(shipment.status);
47
- setTrackingNumber(shipment.trackingNumber ?? "");
48
- setCarrier(shipment.carrier ?? "");
49
- setEtaDate(shipment.etaDate ? new Date(shipment.etaDate).toISOString().slice(0, 10) : "");
50
- setNotes(shipment.notes ?? "");
51
- setCustomsTotalRupees(String(shipment.customsTotal));
52
- setShippingTotalRupees(String(shipment.shippingTotal));
53
- setLaborHoursSpent(String(shipment.laborHoursSpent ?? 0));
49
+ const doc = shipment;
50
+ patch({
51
+ shipmentNumber: doc.shipmentNumber,
52
+ supplierName: doc.supplierName,
53
+ originCountry: doc.originCountry ?? "",
54
+ status: doc.status,
55
+ trackingNumber: doc.trackingNumber ?? "",
56
+ carrier: doc.carrier ?? "",
57
+ etaDate: toDateInput(doc.etaDate),
58
+ receivedDate: toDateInput(doc.receivedDate),
59
+ customsTotal: doc.customsTotal,
60
+ shippingTotal: doc.shippingTotal,
61
+ laborHoursSpent: doc.laborHoursSpent ?? 0,
62
+ laborRatePerHour: doc.laborRatePerHour ?? 0,
63
+ notes: doc.notes ?? "",
64
+ });
65
+ // eslint-disable-next-line react-hooks/exhaustive-deps
54
66
  }, [shipment]);
55
67
  const saveMutation = useApiMutation({
56
68
  successMessage: isCreate ? "Shipment created" : "Shipment updated",
57
69
  mutationFn: async () => {
70
+ const draft = visibleValues(createShipmentSchema, form);
58
71
  const payload = {
59
- shipmentNumber,
60
- supplierName,
61
- originCountry: originCountry || undefined,
62
- status,
63
- trackingNumber: trackingNumber || undefined,
64
- carrier: carrier || undefined,
65
- etaDate: etaDate || undefined,
66
- notes: notes || undefined,
67
- customsTotal: Math.round(Number(customsTotalRupees) * 100) / 100,
68
- shippingTotal: Math.round(Number(shippingTotalRupees) * 100) / 100,
69
- laborHoursSpent: Number(laborHoursSpent),
72
+ shipmentNumber: draft.shipmentNumber,
73
+ supplierName: draft.supplierName,
74
+ originCountry: draft.originCountry || undefined,
75
+ status: draft.status,
76
+ trackingNumber: draft.trackingNumber || undefined,
77
+ carrier: draft.carrier || undefined,
78
+ etaDate: draft.etaDate || undefined,
79
+ receivedDate: draft.receivedDate || undefined,
80
+ notes: draft.notes || undefined,
81
+ customsTotal: draft.customsTotal,
82
+ shippingTotal: draft.shippingTotal,
83
+ laborHoursSpent: draft.laborHoursSpent,
84
+ laborRatePerHour: draft.laborRatePerHour || undefined,
70
85
  };
71
86
  if (isCreate) {
72
87
  return apiClient.post(ADMIN_ENDPOINTS.SHIPMENTS, payload);
@@ -78,24 +93,32 @@ export function AdminShipmentEditorView({ shipmentId, onSaved }) {
78
93
  onSaved?.(saved.id);
79
94
  },
80
95
  });
81
- return (_jsx(Form, { schema: createShipmentSchema, spacing: "md", children: ({ setFieldError, markSubmitAttempted }) => (_jsxs(_Fragment, { children: [_jsxs(Grid, { cols: 2, gap: "md", children: [_jsx(FieldInput, { name: "shipmentNumber", label: "Shipment Number", required: true, value: shipmentNumber, onChange: setShipmentNumber, placeholder: "SH-2026-0001" }), _jsx(FieldInput, { name: "supplierName", label: "Supplier Name", required: true, value: supplierName, onChange: setSupplierName }), _jsx(FieldInput, { name: "originCountry", label: "Origin Country", value: originCountry, onChange: setOriginCountry }), _jsx(FieldSelect, { name: "status", label: "Status", required: true, value: status, onChange: setStatus, options: STATUS_OPTIONS }), _jsx(FieldInput, { name: "trackingNumber", label: "Tracking Number", value: trackingNumber, onChange: setTrackingNumber }), _jsx(FieldInput, { name: "carrier", label: "Carrier", value: carrier, onChange: setCarrier }), _jsx(FieldInput, { name: "etaDate", label: "ETA Date", type: "date", value: etaDate, onChange: setEtaDate }), _jsx(FieldInput, { name: "laborHoursSpent", label: "Labor Hours Spent", type: "number", min: "0", value: laborHoursSpent, onChange: setLaborHoursSpent }), _jsx(FieldInput, { name: "customsTotal", label: "Customs Total (\u20B9)", type: "number", min: "0", value: customsTotalRupees, onChange: setCustomsTotalRupees, hint: "Split across lots by declared value" }), _jsx(FieldInput, { name: "shippingTotal", label: "Shipping Total (\u20B9)", type: "number", min: "0", value: shippingTotalRupees, onChange: setShippingTotalRupees, hint: "Split across lots by weight" })] }), _jsx(FieldTextarea, { name: "notes", label: "Notes", value: notes, onChange: setNotes, rows: 3 }), _jsx(FormErrorSummary, {}), _jsx(Button, { type: "button", isLoading: saveMutation.isPending, onClick: () => {
82
- // type="button" — no native submit, so unhide the summary here.
83
- markSubmitAttempted();
84
- const parsed = createShipmentSchema.safeParse({
85
- shipmentNumber,
86
- supplierName,
87
- status,
88
- customsTotal: Math.round(Number(customsTotalRupees) * 100) / 100,
89
- shippingTotal: Math.round(Number(shippingTotalRupees) * 100) / 100,
90
- laborHoursSpent: Number(laborHoursSpent),
91
- });
92
- if (!parsed.success) {
93
- for (const issue of parsed.error.issues)
94
- setFieldError(String(issue.path[0]), issue.message);
95
- return;
96
- }
97
- saveMutation.mutate();
98
- }, children: isCreate ? "Create Shipment" : "Save Changes" }), !isCreate && shipmentId && (_jsx(ShipmentLotsSection, { shipmentId: shipmentId, lots: lots, onLotsChanged: refetchLots })), !isCreate && (_jsx(RecordStatusTimeline, { entries: shipment?.statusHistory, truncatedCount: shipment?.statusHistoryTruncated }))] })) }));
96
+ const sections = React.useMemo(() => buildSectionsFromSchema(createShipmentSchema), []);
97
+ const nav = useSectionFormNav(sections, form, { scope: "admin:shipment-editor" });
98
+ const { shellCtx, setFieldError, clearErrors } = useFormShellState(createShipmentSchema, {
99
+ sections: nav.sectionMeta,
100
+ onGoToSection: nav.goToSection,
101
+ fieldToSectionIndex: nav.fieldToSectionIndex,
102
+ });
103
+ const handleSubmit = () => {
104
+ clearErrors();
105
+ /*
106
+ * The whole draft, not six of its thirteen fields.
107
+ *
108
+ * The hand-rolled parse passed a literal covering `shipmentNumber`,
109
+ * `supplierName`, `status` and the three money fields — so `originCountry`,
110
+ * `trackingNumber`, `carrier`, `etaDate` and `notes` were never checked by
111
+ * anything, and `receivedDate` / `laborRatePerHour` had no control at all
112
+ * although the schema declares them and the route accepts them.
113
+ */
114
+ const parsed = createShipmentSchema.safeParse(visibleValues(createShipmentSchema, form));
115
+ if (!parsed.success) {
116
+ applyZodIssues(parsed.error.issues, setFieldError);
117
+ return;
118
+ }
119
+ saveMutation.mutate();
120
+ };
121
+ return (_jsxs(Stack, { gap: "md", children: [_jsxs(FormShellContext.Provider, { value: shellCtx, children: [_jsx(FormErrorSummary, {}), _jsx(SectionForm, { sections: sections, values: form, onChange: patch, onSubmit: handleSubmit, schema: createShipmentSchema, openIds: nav.openIds, onOpenChange: nav.setOpenIds, isLoading: saveMutation.isPending, submitLabel: isCreate ? "Create shipment" : "Save changes" })] }), !isCreate && shipmentId && (_jsx(ShipmentLotsSection, { shipmentId: shipmentId, lots: lots, onLotsChanged: refetchLots })), !isCreate && (_jsx(RecordStatusTimeline, { entries: shipment?.statusHistory, truncatedCount: shipment?.statusHistoryTruncated }))] }));
99
122
  }
100
123
  function ShipmentLotsSection({ shipmentId, lots, onLotsChanged, }) {
101
124
  const [showAddLot, setShowAddLot] = React.useState(false);
@@ -122,5 +145,5 @@ function ShipmentLotsSection({ shipmentId, lots, onLotsChanged, }) {
122
145
  mutationFn: (lotId) => apiClient.delete(ADMIN_ENDPOINTS.SHIPMENT_LOT_BY_ID(shipmentId, lotId)),
123
146
  onSuccess: () => onLotsChanged(),
124
147
  });
125
- return (_jsxs(Stack, { gap: "md", className: "border-t pt-[var(--appkit-space-4)]", children: [_jsxs(Div, { layout: "flex", align: "center", justify: "between", children: [_jsxs(Heading, { level: 4, children: ["Lots (", lots.length, "/10)"] }), lots.length < 10 && (_jsx(Button, { size: "sm", variant: "secondary", type: "button", onClick: () => setShowAddLot((v) => !v), children: showAddLot ? "Cancel" : "+ Add Lot" }))] }), showAddLot && (_jsxs(Grid, { cols: 3, gap: "sm", children: [_jsx(FieldInput, { name: "lotName", label: "Lot Name", value: lotName, onChange: setLotName }), _jsx(FieldInput, { name: "weightGrams", label: "Weight (g)", type: "number", min: "0", value: weightGrams, onChange: setWeightGrams }), _jsx(FieldInput, { name: "purchaseCost", label: "Purchase Cost (\u20B9)", type: "number", min: "0", value: purchaseCostRupees, onChange: setPurchaseCostRupees }), _jsx(Button, { type: "button", size: "sm", isLoading: addLotMutation.isPending, disabled: !lotName, onClick: () => addLotMutation.mutate(), children: "Save Lot" })] })), lots.length === 0 ? (_jsx(Text, { variant: "secondary", children: "No lots yet. Add a lot, then manage its items." })) : (_jsxs(Table, { children: [_jsx(Thead, { children: _jsxs(Tr, { children: [_jsx(Th, { children: "Lot" }), _jsx(Th, { children: "Weight (g)" }), _jsx(Th, { children: "Items" }), _jsx(Th, { children: "Projected Profit" }), _jsx(Th, {})] }) }), _jsx(Tbody, { children: lots.map((lot) => (_jsxs(Tr, { children: [_jsx(Td, { children: lot.lotName }), _jsx(Td, { children: lot.weightGrams }), _jsx(Td, { children: lot.itemCount }), _jsx(Td, { children: formatCurrency(lot.projectedProfit) }), _jsxs(Td, { className: "flex gap-[var(--appkit-space-2)]", children: [_jsx(TextLink, { href: ROUTES.ADMIN.SHIPMENT_LOT_ITEMS(shipmentId, lot.id), children: "Manage Items \u2192" }), _jsx(Button, { size: "sm", variant: "ghost", type: "button", action: ACTIONS.SHIPMENT["delete"], isLoading: deleteLotMutation.isPending, onClick: () => deleteLotMutation.mutate(lot.id), children: "Delete" })] })] }, lot.id))) })] })), lots.length > 0 && (_jsx(Alert, { variant: "info", children: "Customs/shipping allocation and profit totals recompute in the background a few seconds after any lot or item change \u2014 reload if a number looks stale." }))] }));
148
+ return (_jsxs(Stack, { gap: "md", className: "border-t pt-[var(--appkit-space-4)]", children: [_jsxs(Div, { layout: "flex", align: "center", justify: "between", children: [_jsxs(Heading, { level: 4, children: ["Lots (", lots.length, "/10)"] }), lots.length < 10 && (_jsx(Button, { size: "sm", variant: "secondary", type: "button", onClick: () => setShowAddLot((v) => !v), children: showAddLot ? "Cancel" : "+ Add Lot" }))] }), showAddLot && (_jsxs(Grid, { cols: 3, gap: "sm", children: [_jsx(FieldInput, { name: "lotName", label: "Lot Name", value: lotName, onChange: setLotName }), _jsx(FieldInput, { name: "weightGrams", label: "Weight (g)", type: "number", min: "0", value: weightGrams, onChange: setWeightGrams }), _jsx(FieldInput, { name: "purchaseCost", label: "Purchase Cost (\u20B9)", type: "number", min: "0", value: purchaseCostRupees, onChange: setPurchaseCostRupees }), _jsx(Button, { type: "button", size: "sm", isLoading: addLotMutation.isPending, disabled: !lotName, onClick: () => addLotMutation.mutate(), children: "Save Lot" })] })), lots.length === 0 ? (_jsx(Text, { variant: "secondary", children: "No lots yet. Add a lot, then manage its items." })) : (_jsxs(Table, { children: [_jsx(Thead, { children: _jsxs(Tr, { children: [_jsx(Th, { children: "Lot" }), _jsx(Th, { children: "Weight (g)" }), _jsx(Th, { children: "Items" }), _jsx(Th, { children: "Projected Profit" }), _jsx(Th, {})] }) }), _jsx(Tbody, { children: lots.map((lot) => (_jsxs(Tr, { children: [_jsx(Td, { children: lot.lotName }), _jsx(Td, { children: lot.weightGrams }), _jsx(Td, { children: lot.itemCount }), _jsx(Td, { children: formatCurrency(lot.projectedProfit) }), _jsxs(Td, { className: "flex gap-[var(--appkit-space-2)]", children: [_jsx(TextLink, { href: ROUTES.ADMIN.SHIPMENT_LOT_ITEMS(shipmentId, lot.id), children: "Manage Items \u2192" }), _jsx(Button, { size: "sm", variant: "ghost", type: "button", action: ACTIONS.SHIPMENT["delete-lot"], isLoading: deleteLotMutation.isPending, onClick: () => deleteLotMutation.mutate(lot.id), children: "Delete" })] })] }, lot.id))) })] })), lots.length > 0 && (_jsx(Alert, { variant: "info", children: "Customs/shipping allocation and profit totals recompute in the background a few seconds after any lot or item change \u2014 reload if a number looks stale." }))] }));
126
149
  }
@@ -9,11 +9,11 @@ export declare const createShipmentSchema: z.ZodObject<{
9
9
  carrier: z.ZodOptional<z.ZodString>;
10
10
  etaDate: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodDate]>>;
11
11
  receivedDate: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodDate]>>;
12
- notes: z.ZodOptional<z.ZodString>;
13
12
  customsTotal: z.ZodNumber;
14
13
  shippingTotal: z.ZodNumber;
15
14
  laborHoursSpent: z.ZodOptional<z.ZodNumber>;
16
15
  laborRatePerHour: z.ZodOptional<z.ZodNumber>;
16
+ notes: z.ZodOptional<z.ZodString>;
17
17
  }, "strip", z.ZodTypeAny, {
18
18
  status: "received" | "cancelled" | "processing" | "completed" | "ordered" | "planning" | "in_transit" | "customs";
19
19
  shipmentNumber: string;
@@ -52,11 +52,11 @@ export declare const updateShipmentSchema: z.ZodObject<{
52
52
  carrier: z.ZodOptional<z.ZodOptional<z.ZodString>>;
53
53
  etaDate: z.ZodOptional<z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodDate]>>>;
54
54
  receivedDate: z.ZodOptional<z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodDate]>>>;
55
- notes: z.ZodOptional<z.ZodOptional<z.ZodString>>;
56
55
  customsTotal: z.ZodOptional<z.ZodNumber>;
57
56
  shippingTotal: z.ZodOptional<z.ZodNumber>;
58
57
  laborHoursSpent: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
59
58
  laborRatePerHour: z.ZodOptional<z.ZodOptional<z.ZodNumber>>;
59
+ notes: z.ZodOptional<z.ZodOptional<z.ZodString>>;
60
60
  }, "strip", z.ZodTypeAny, {
61
61
  status?: "received" | "cancelled" | "processing" | "completed" | "ordered" | "planning" | "in_transit" | "customs" | undefined;
62
62
  notes?: string | undefined;
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ import { annotate } from "../../shell/field-ui-meta";
2
3
  import { mediaFieldSchema } from "../../media/types/index";
3
4
  import { MAX_ITEMS_PER_LOT } from "./firestore";
4
5
  export const shipmentStatusSchema = z.enum([
@@ -36,19 +37,49 @@ const listingTypeSchema = z.enum([
36
37
  "stickers",
37
38
  ]);
38
39
  export const createShipmentSchema = z.object({
39
- shipmentNumber: z.string().min(1, "Shipment number is required"),
40
- supplierName: z.string().min(1, "Supplier name is required"),
41
- originCountry: z.string().optional(),
42
- status: shipmentStatusSchema,
43
- trackingNumber: z.string().optional(),
44
- carrier: z.string().optional(),
45
- etaDate: z.union([z.string(), z.date()]).optional(),
46
- receivedDate: z.union([z.string(), z.date()]).optional(),
47
- notes: z.string().optional(),
48
- customsTotal: z.number().min(0),
49
- shippingTotal: z.number().min(0),
50
- laborHoursSpent: z.number().min(0).optional(),
51
- laborRatePerHour: z.number().min(0).optional(),
40
+ shipmentNumber: annotate(z.string().min(1, "Shipment number is required"), {
41
+ section: "basics", sectionLabel: "Shipment", sectionRequired: true,
42
+ order: 1, row: "pair", label: "Shipment number",
43
+ }),
44
+ supplierName: annotate(z.string().min(1, "Supplier name is required"), {
45
+ section: "basics", order: 2, row: "pair", label: "Supplier",
46
+ }),
47
+ originCountry: annotate(z.string().optional(), {
48
+ section: "basics", order: 3, row: "pair", label: "Origin country",
49
+ }),
50
+ status: annotate(shipmentStatusSchema, {
51
+ section: "basics", order: 4, row: "pair", kind: "select", label: "Status",
52
+ }),
53
+ trackingNumber: annotate(z.string().optional(), {
54
+ section: "logistics", sectionLabel: "Tracking & dates",
55
+ order: 1, row: "pair", label: "Tracking number",
56
+ }),
57
+ carrier: annotate(z.string().optional(), {
58
+ section: "logistics", order: 2, row: "pair", label: "Carrier",
59
+ }),
60
+ etaDate: annotate(z.union([z.string(), z.date()]).optional(), {
61
+ section: "logistics", order: 3, row: "pair", kind: "date", label: "ETA",
62
+ }),
63
+ receivedDate: annotate(z.union([z.string(), z.date()]).optional(), {
64
+ section: "logistics", order: 4, row: "pair", kind: "date", label: "Received on",
65
+ }),
66
+ customsTotal: annotate(z.number().min(0), {
67
+ section: "pricing", sectionLabel: "Landed cost",
68
+ order: 1, row: "pair", kind: "number", label: "Customs total (₹)",
69
+ }),
70
+ shippingTotal: annotate(z.number().min(0), {
71
+ section: "pricing", order: 2, row: "pair", kind: "number", label: "Shipping total (₹)",
72
+ }),
73
+ laborHoursSpent: annotate(z.number().min(0).optional(), {
74
+ section: "pricing", order: 3, row: "pair", kind: "number", label: "Labour hours",
75
+ }),
76
+ laborRatePerHour: annotate(z.number().min(0).optional(), {
77
+ section: "pricing", order: 4, row: "pair", kind: "number", label: "Labour rate (₹/hr)",
78
+ }),
79
+ notes: annotate(z.string().optional(), {
80
+ section: "detail", sectionLabel: "Notes", order: 1, row: "full", kind: "textarea",
81
+ label: "Notes",
82
+ }),
52
83
  });
53
84
  export const updateShipmentSchema = createShipmentSchema.partial();
54
85
  export const createShipmentLotSchema = z.object({
@@ -19,8 +19,12 @@
19
19
  * it grants nothing — it silently never matches — so a role built from typos
20
20
  * looks configured and does nothing, which is worse than being rejected.
21
21
  *
22
- * `"*"` is accepted deliberately: `security/rbac/types.ts` defines it as the
23
- * wildcard, and rejecting it here would break a legitimate super-role.
22
+ * `"*"` is accepted deliberately as a super-role wildcard. It used to be
23
+ * defined by `security/rbac/types.ts`, which was deleted 2026-08-29 as a dead
24
+ * second permission system — so today NOTHING expands it: `checkPermission`
25
+ * does a plain `includes()`. A role carrying `"*"` therefore grants exactly
26
+ * nothing. Kept accepted so existing stored roles still validate; make it
27
+ * expand, or reject it, before advertising it as a feature.
24
28
  *
25
29
  * ## What is NOT accepted from the body
26
30
  *
@@ -18,15 +18,15 @@ export declare const listingTemplateFormSchema: z.ZodObject<{
18
18
  name: string;
19
19
  listingType: "art" | "stickers" | "classified" | "standard" | "auction" | "pre-order" | "prize-draw" | "digital-code" | "live" | "bundle";
20
20
  isActive: boolean;
21
- isShared: boolean;
22
21
  defaults: Record<string, import("../../..").FirestoreValue>;
22
+ isShared: boolean;
23
23
  description?: string | undefined;
24
24
  }, {
25
25
  name: string;
26
26
  listingType: "art" | "stickers" | "classified" | "standard" | "auction" | "pre-order" | "prize-draw" | "digital-code" | "live" | "bundle";
27
27
  isActive: boolean;
28
- isShared: boolean;
29
28
  defaults: Record<string, import("../../..").FirestoreValue>;
29
+ isShared: boolean;
30
30
  description?: string | undefined;
31
31
  }>;
32
32
  export type ListingTemplateFormValues = z.infer<typeof listingTemplateFormSchema>;
@@ -40,22 +40,22 @@ export declare const listingTemplateCreateSchema: z.ZodObject<{
40
40
  listingType: z.ZodEnum<["standard", "auction", "pre-order", "prize-draw", "bundle", "classified", "digital-code", "live", "art", "stickers"]>;
41
41
  description: z.ZodOptional<z.ZodOptional<z.ZodString>>;
42
42
  isActive: z.ZodOptional<z.ZodBoolean>;
43
- isShared: z.ZodOptional<z.ZodBoolean>;
44
43
  defaults: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodType<import("../../..").FirestoreValue, z.ZodTypeDef, import("../../..").FirestoreValue>>>;
44
+ isShared: z.ZodOptional<z.ZodBoolean>;
45
45
  }, "strip", z.ZodTypeAny, {
46
46
  name: string;
47
47
  listingType: "art" | "stickers" | "classified" | "standard" | "auction" | "pre-order" | "prize-draw" | "digital-code" | "live" | "bundle";
48
48
  description?: string | undefined;
49
49
  isActive?: boolean | undefined;
50
- isShared?: boolean | undefined;
51
50
  defaults?: Record<string, import("../../..").FirestoreValue> | undefined;
51
+ isShared?: boolean | undefined;
52
52
  }, {
53
53
  name: string;
54
54
  listingType: "art" | "stickers" | "classified" | "standard" | "auction" | "pre-order" | "prize-draw" | "digital-code" | "live" | "bundle";
55
55
  description?: string | undefined;
56
56
  isActive?: boolean | undefined;
57
- isShared?: boolean | undefined;
58
57
  defaults?: Record<string, import("../../..").FirestoreValue> | undefined;
58
+ isShared?: boolean | undefined;
59
59
  }>;
60
60
  /** Update contract — every field optional, and the same ownership fields absent. */
61
61
  /**
@@ -84,13 +84,13 @@ export declare const listingTemplateUpdateSchema: z.ZodObject<{
84
84
  listingType?: "art" | "stickers" | "classified" | "standard" | "auction" | "pre-order" | "prize-draw" | "digital-code" | "live" | "bundle" | undefined;
85
85
  description?: string | undefined;
86
86
  isActive?: boolean | undefined;
87
- isShared?: boolean | undefined;
88
87
  defaults?: Record<string, import("../../..").FirestoreValue> | undefined;
88
+ isShared?: boolean | undefined;
89
89
  }, {
90
90
  name?: string | undefined;
91
91
  listingType?: "art" | "stickers" | "classified" | "standard" | "auction" | "pre-order" | "prize-draw" | "digital-code" | "live" | "bundle" | undefined;
92
92
  description?: string | undefined;
93
93
  isActive?: boolean | undefined;
94
- isShared?: boolean | undefined;
95
94
  defaults?: Record<string, import("../../..").FirestoreValue> | undefined;
95
+ isShared?: boolean | undefined;
96
96
  }>;
@@ -56,21 +56,35 @@ export const payoutMethodFormSchema = z
56
56
  label: annotate(z.string().min(1, "Give this method a name you'll recognise.").max(80), {
57
57
  section: "method", quick: true, order: 2, row: "pair",
58
58
  }),
59
+ /*
60
+ * `when` carries the branching the PAGE used to hold as JSX conditionals,
61
+ * so the generated form is the same form.
62
+ *
63
+ * Every one of these is already `.optional()` at the type level and made
64
+ * conditionally required by the `superRefine` below — which is the pairing
65
+ * `FieldUiMeta.when` demands, because hiding a field does NOT relax its
66
+ * schema. A required field hidden by `when` fails validation invisibly.
67
+ */
59
68
  upiVpa: annotate(z.string().max(256).optional(), {
60
69
  section: "method", order: 3, row: "full",
61
70
  help: "For UPI methods, e.g. name@bank.",
71
+ when: (v) => v.type === "upi",
62
72
  }),
63
73
  accountHolderName: annotate(z.string().max(120).optional(), {
64
74
  section: "bank", sectionLabel: "Bank Account", order: 1, row: "full",
75
+ when: (v) => v.type === "bank",
65
76
  }),
66
77
  accountNumber: annotate(z.string().max(34).optional(), {
67
78
  section: "bank", order: 2, row: "pair",
79
+ when: (v) => v.type === "bank",
68
80
  }),
69
81
  ifscCode: annotate(z.string().max(11).optional(), {
70
82
  section: "bank", order: 3, row: "pair",
83
+ when: (v) => v.type === "bank",
71
84
  }),
72
85
  bankName: annotate(z.string().max(120).optional(), {
73
86
  section: "bank", order: 4, row: "pair",
87
+ when: (v) => v.type === "bank",
74
88
  }),
75
89
  isDefault: annotate(z.boolean(), {
76
90
  section: "visibility", sectionLabel: "Visibility", order: 1, row: "quarter",
@@ -15,6 +15,7 @@ import { STORE_FIELDS } from "../schemas";
15
15
  import { productRepository } from "../../products/repository/products.repository";
16
16
  import { ProductStatusValues } from "../../products/schemas";
17
17
  import { reviewRepository } from "../../reviews/repository/reviews.repository";
18
+ import { PRODUCT_FIELDS } from "../../../constants/field-names";
18
19
  export async function listStores(params = {}, viewer) {
19
20
  const { filters, sorts = "-createdAt", page = 1, pageSize = 24, q } = params;
20
21
  const model = { filters, sorts, page, pageSize };
@@ -65,7 +66,7 @@ export async function getStoreProducts(storeSlug, params = {}, viewer) {
65
66
  const filtersArr = [
66
67
  sieveFilter("storeId", SIEVE_OP.EQ, storeDoc.id),
67
68
  "status==published",
68
- "listingType==standard",
69
+ sieveFilter(PRODUCT_FIELDS.LISTING_TYPE, SIEVE_OP.EQ, "standard"),
69
70
  ];
70
71
  if (filters)
71
72
  filtersArr.push(filters);
@@ -87,7 +88,7 @@ export async function getStoreAuctions(storeSlug, params = {}, viewer) {
87
88
  const filtersArr = [
88
89
  sieveFilter("storeId", SIEVE_OP.EQ, storeDoc.id),
89
90
  "status==published",
90
- "listingType==auction",
91
+ sieveFilter(PRODUCT_FIELDS.LISTING_TYPE, SIEVE_OP.EQ, "auction"),
91
92
  ];
92
93
  if (filters)
93
94
  filtersArr.push(filters);