@evershop/evershop 1.0.0 → 1.1.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 (214) hide show
  1. package/bin/build/client/index.js +1 -1
  2. package/bin/build/complie.js +1 -1
  3. package/bin/build/index.js +1 -1
  4. package/bin/build/server/index.js +1 -1
  5. package/bin/build/server/useDDL.js +1 -1
  6. package/bin/dev/index.js +2 -1
  7. package/bin/evershop +8 -7
  8. package/bin/extension/index.js +1 -1
  9. package/bin/install/index.js +1 -1
  10. package/bin/lib/addDefaultMiddlewareFuncs.js +2 -2
  11. package/bin/lib/app.js +1 -1
  12. package/bin/lib/bootstrap/migrate.js +1 -1
  13. package/bin/lib/buildEntry.js +1 -1
  14. package/bin/lib/onError.js +1 -1
  15. package/bin/lib/onListening.js +1 -1
  16. package/bin/lib/startUp.js +10 -9
  17. package/bin/lib/watch/watchComponents.js +16 -26
  18. package/bin/lib/watch/watchMF.js +1 -1
  19. package/bin/lib/watch/watchMR.js +1 -1
  20. package/bin/lib/watch/watchSchema.js +1 -1
  21. package/bin/user/changePassword.js +1 -1
  22. package/bin/user/create.js +1 -1
  23. package/package.json +2 -2
  24. package/src/components/admin/catalog/productEdit/category/CategoryItem.jsx +1 -1
  25. package/src/components/admin/catalog/productEdit/category/CategoryTree.jsx +1 -1
  26. package/src/components/admin/catalog/productEdit/variants/CreateVariantGroup.jsx +3 -8
  27. package/src/components/admin/catalog/productEdit/variants/Variant.jsx +1 -1
  28. package/src/components/admin/catalog/productEdit/variants/VariantModal.jsx +62 -6
  29. package/src/components/admin/catalog/productEdit/variants/Variants.jsx +1 -1
  30. package/src/components/admin/checkout/shippingSetting/Method.jsx +130 -0
  31. package/src/components/admin/{oms → checkout}/shippingSetting/MethodForm.jsx +124 -13
  32. package/src/components/admin/{oms → checkout}/shippingSetting/Methods.jsx +2 -2
  33. package/src/components/admin/checkout/shippingSetting/PriceBasedPrice.jsx +101 -0
  34. package/src/components/admin/checkout/shippingSetting/WeightBasedPrice.jsx +101 -0
  35. package/src/components/admin/{oms → checkout}/shippingSetting/Zone.jsx +34 -4
  36. package/src/components/admin/{oms → checkout}/shippingSetting/Zones.jsx +6 -3
  37. package/src/components/admin/promotion/couponEdit/AttributeGroupSelector.jsx +5 -5
  38. package/src/components/admin/promotion/couponEdit/CategorySelector.jsx +5 -5
  39. package/src/components/admin/promotion/couponEdit/CollectionSelector.jsx +5 -5
  40. package/src/components/admin/promotion/couponEdit/ProductSkuSelector.jsx +27 -6
  41. package/src/components/common/context/checkout.jsx +8 -14
  42. package/src/components/common/form/Field.jsx +1 -1
  43. package/src/components/common/form/fields/Input.jsx +2 -1
  44. package/src/components/common/form/validator.js +6 -2
  45. package/src/components/common/grid/headers/Dummy.jsx +1 -1
  46. package/src/components/common/grid/headers/Sortable.jsx +148 -0
  47. package/src/components/common/grid/rows/StatusRow.jsx +1 -1
  48. package/src/components/common/list/Filter.jsx +83 -0
  49. package/src/components/common/list/Filter.scss +39 -0
  50. package/src/components/frontStore/catalog/categoryView/filter/AttributeFilter.jsx +19 -5
  51. package/src/components/frontStore/catalog/categoryView/filter/CategoryFilter.jsx +59 -52
  52. package/src/components/frontStore/catalog/categoryView/filter/PriceFilter.jsx +20 -11
  53. package/src/components/frontStore/catalog/product/list/SortOptions.jsx +4 -2
  54. package/src/components/frontStore/catalog/product/list/Sorting.jsx +5 -5
  55. package/src/components/frontStore/checkout/checkout/payment/paymentStep/StepContent.jsx +9 -6
  56. package/src/components/frontStore/stripe/checkout/CheckoutForm.jsx +8 -4
  57. package/src/lib/event/callSubscibers.js +14 -11
  58. package/src/lib/event/event-manager.js +1 -1
  59. package/src/lib/event/loadSubscribers.js +2 -2
  60. package/src/lib/helpers.js +3 -1
  61. package/src/lib/log/CustomColorize.js +22 -0
  62. package/src/lib/log/logger.js +153 -19
  63. package/src/lib/middleware/Handler.js +2 -3
  64. package/src/lib/middleware/async.js +5 -9
  65. package/src/lib/middleware/sync.js +5 -10
  66. package/src/lib/middleware/tests/app/app.js +1 -1
  67. package/src/lib/router/buildAbsoluteUrl.js +1 -1
  68. package/src/lib/util/buildFilterFromUrl.js +31 -64
  69. package/src/lib/util/defaultPaginationFilters.js +102 -0
  70. package/src/lib/util/filterOperationMapp.js +16 -0
  71. package/src/lib/util/registry.js +44 -6
  72. package/src/lib/webpack/dev/createConfigClient.js +2 -0
  73. package/src/lib/webpack/loaders/AreaLoader.js +1 -1
  74. package/src/lib/webpack/loaders/loadTranslationFromCsv.js +1 -1
  75. package/src/lib/webpack/plugins/Tailwindcss.js +1 -1
  76. package/src/modules/auth/graphql/types/AdminUser/AdminUser.admin.resolvers.js +6 -6
  77. package/src/modules/auth/pages/admin/adminLogin/LoginForm.jsx +1 -15
  78. package/src/modules/base/api/global/[apiResponse]apiErrorHandler.js +2 -2
  79. package/src/modules/base/pages/global/[response]errorHandler.js +2 -2
  80. package/src/modules/catalog/api/addProductToCategory/addProducts.js +1 -1
  81. package/src/modules/catalog/api/addProductToCollection/addProducts.js +35 -22
  82. package/src/modules/catalog/api/removeProductFromCollection/removeProducts.js +20 -5
  83. package/src/modules/catalog/bootstrap.js +63 -0
  84. package/src/modules/catalog/graphql/types/Attribute/Attribute.admin.graphql +2 -2
  85. package/src/modules/catalog/graphql/types/Attribute/Attribute.admin.resolvers.js +48 -276
  86. package/src/modules/catalog/graphql/types/Category/Category.graphql +15 -2
  87. package/src/modules/catalog/graphql/types/Category/Category.resolvers.js +2 -2
  88. package/src/modules/catalog/graphql/types/Collection/Collection.resolvers.js +2 -2
  89. package/src/modules/catalog/graphql/types/Product/Product.resolvers.js +1 -1
  90. package/src/modules/catalog/graphql/types/Product/Variant/Variant.graphql +2 -2
  91. package/src/modules/catalog/graphql/types/Product/Variant/Variant.resolvers.js +68 -92
  92. package/src/modules/catalog/pages/admin/attributeEdit+attributeNew/General.jsx +13 -9
  93. package/src/modules/catalog/pages/admin/attributeGrid/Grid.jsx +82 -39
  94. package/src/modules/catalog/pages/admin/attributeGrid/index.js +1 -1
  95. package/src/modules/catalog/pages/admin/categoryEdit/Products.jsx +5 -5
  96. package/src/modules/catalog/pages/admin/categoryGrid/Grid.jsx +48 -16
  97. package/src/modules/catalog/pages/admin/categoryGrid/index.js +1 -1
  98. package/src/modules/catalog/pages/admin/collectionEdit/Products.jsx +5 -5
  99. package/src/modules/catalog/pages/admin/collectionGrid/Grid.jsx +46 -5
  100. package/src/modules/catalog/pages/admin/collectionGrid/index.js +1 -1
  101. package/src/modules/catalog/pages/admin/productEdit+productNew/Attributes.jsx +28 -24
  102. package/src/modules/catalog/pages/admin/productGrid/Grid.jsx +158 -26
  103. package/src/modules/catalog/pages/admin/productGrid/index.js +1 -2
  104. package/src/modules/catalog/pages/frontStore/all/SearchBox.jsx +2 -1
  105. package/src/modules/catalog/pages/frontStore/catalogSearch/[index]filters.js +4 -59
  106. package/src/modules/catalog/pages/frontStore/catalogSearch/index.js +11 -0
  107. package/src/modules/catalog/pages/frontStore/categoryView/Filter.jsx +22 -6
  108. package/src/modules/catalog/pages/frontStore/categoryView/Filter.scss +2 -0
  109. package/src/modules/catalog/pages/frontStore/categoryView/[index]filters.js +5 -105
  110. package/src/modules/catalog/pages/frontStore/homepage/FeaturedProducts.jsx +1 -1
  111. package/src/modules/catalog/pages/frontStore/productView/Form.jsx +8 -3
  112. package/src/modules/catalog/pages/frontStore/productView/Variants.jsx +102 -40
  113. package/src/modules/catalog/services/AttributeCollection.js +59 -0
  114. package/src/modules/catalog/services/AttributeGroupCollection.js +100 -0
  115. package/src/modules/catalog/services/CategoryCollection.js +27 -84
  116. package/src/modules/catalog/services/CollectionCollection.js +24 -72
  117. package/src/modules/catalog/services/ProductCollection.js +50 -216
  118. package/src/modules/catalog/services/attribute/deleteProductAttribute.js +15 -0
  119. package/src/modules/catalog/services/getAttributeGroupsBaseQuery.js +3 -0
  120. package/src/modules/catalog/services/getAttributesBaseQuery.js +3 -0
  121. package/src/modules/catalog/services/getCollectionsBaseQuery.js +0 -1
  122. package/src/modules/catalog/services/product/updateProduct.js +8 -2
  123. package/src/modules/catalog/services/registerDefaultAttributeCollectionFilters.js +149 -0
  124. package/src/modules/catalog/services/registerDefaultCategoryCollectionFilters.js +85 -0
  125. package/src/modules/catalog/services/registerDefaultCollectionCollectionFilters.js +65 -0
  126. package/src/modules/catalog/services/registerDefaultProductCollectionFilters.js +219 -0
  127. package/src/modules/catalog/subscribers/category_created/buildUrlRewrite.js +1 -1
  128. package/src/modules/catalog/subscribers/category_deleted/deleteUrlRewrite.js +1 -1
  129. package/src/modules/catalog/subscribers/category_updated/builUrlRewrite.js +1 -1
  130. package/src/modules/catalog/subscribers/product_created/builUrlRewrite.js +1 -1
  131. package/src/modules/catalog/subscribers/product_deleted/deleteUrlRewrite.js +1 -1
  132. package/src/modules/catalog/subscribers/product_image_added/localGenerateProductImageVariant.js +3 -3
  133. package/src/modules/checkout/api/addCartShippingMethod/saveShippingMethod.js +6 -1
  134. package/src/modules/checkout/api/createCart/[context]bodyParser[auth].js +5 -0
  135. package/src/modules/checkout/api/createCart/createNewCart.js +92 -0
  136. package/src/modules/checkout/api/createCart/payloadSchema.json +44 -0
  137. package/src/modules/checkout/api/createCart/route.json +5 -0
  138. package/src/modules/checkout/api/deleteShippingZone/deleteShippingZone.js +58 -0
  139. package/src/modules/checkout/api/deleteShippingZone/route.json +5 -0
  140. package/src/modules/checkout/api/deleteShippingZoneMethod/deleteShippingZoneMethod.js +85 -0
  141. package/src/modules/checkout/api/deleteShippingZoneMethod/route.json +5 -0
  142. package/src/modules/checkout/api/getShippingMethods/sendMethods.js +37 -0
  143. package/src/modules/checkout/api/updateShippingMethod/[context]borderParser[auth].js +5 -0
  144. package/src/modules/checkout/api/updateShippingMethod/payloadSchema.json +12 -0
  145. package/src/modules/checkout/api/updateShippingMethod/route.json +5 -0
  146. package/src/modules/checkout/api/updateShippingMethod/updateShippingMethod.js +64 -0
  147. package/src/modules/checkout/api/updateShippingZoneMethod/payloadSchema.json +43 -1
  148. package/src/modules/checkout/api/updateShippingZoneMethod/updateShippingZoneMethod.js +17 -3
  149. package/src/modules/checkout/bootstrap.js +1 -1
  150. package/src/modules/checkout/graphql/types/ShippingMethod/ShippingMethod.graphql +1 -0
  151. package/src/modules/checkout/graphql/types/ShippingMethod/ShippingMethod.resolvers.js +4 -0
  152. package/src/modules/checkout/graphql/types/ShippingZone/ShippingZone.graphql +21 -1
  153. package/src/modules/checkout/graphql/types/ShippingZone/ShippingZone.resolvers.js +34 -4
  154. package/src/modules/checkout/graphql/types/Weight/Weight.resolvers.js +8 -11
  155. package/src/modules/checkout/migration/Version-1.0.5.js +28 -0
  156. package/src/modules/{oms → checkout}/pages/admin/shippingSetting/ShippingSetting.jsx +66 -43
  157. package/src/modules/checkout/pages/frontStore/all/[auth]addCustomerToCart.js +3 -3
  158. package/src/modules/checkout/pages/frontStore/checkout/PaymentStep.jsx +3 -2
  159. package/src/modules/checkout/pages/frontStore/checkout/ShippingMethods.jsx +23 -10
  160. package/src/modules/checkout/pages/frontStore/checkout/SummaryMobile.jsx +132 -0
  161. package/src/modules/checkout/pages/frontStore/checkout/SummaryMobile.scss +7 -0
  162. package/src/modules/checkout/services/cart/Cart.js +23 -7
  163. package/src/modules/checkout/services/cart/DataObject.js +3 -3
  164. package/src/modules/checkout/services/cart/registerCartBaseFields.js +32 -0
  165. package/src/modules/checkout/services/cart/registerCartItemBaseFields.js +3 -2
  166. package/src/modules/cms/bootstrap.js +17 -0
  167. package/src/modules/cms/graphql/types/CmsPage/CmsPage.resolvers.js +2 -11
  168. package/src/modules/cms/pages/admin/all/Layout.scss +3 -2
  169. package/src/modules/cms/pages/admin/all/SearchBox.jsx +1 -1
  170. package/src/modules/cms/pages/admin/cmsPageGrid/Grid.jsx +62 -9
  171. package/src/modules/cms/pages/admin/cmsPageGrid/index.js +1 -2
  172. package/src/modules/cms/services/CMSPageCollection.js +23 -70
  173. package/src/modules/cms/services/registerDefaultPageCollectionFilters.js +62 -0
  174. package/src/modules/cms/services/tailwind.admin.config.js +6 -1
  175. package/src/modules/customer/api/createCustomer/[bodyParser]createCustomer.js +2 -2
  176. package/src/modules/customer/api/resetPassword/[bodyParser]resetPassword.js +2 -2
  177. package/src/modules/customer/api/updatePassword/[bodyParser]updatePassword.js +2 -2
  178. package/src/modules/customer/bootstrap.js +29 -0
  179. package/src/modules/customer/graphql/types/Customer/Customer.admin.resolvers.js +2 -4
  180. package/src/modules/customer/pages/admin/customerGrid/Grid.jsx +108 -14
  181. package/src/modules/customer/pages/admin/customerGrid/index.js +1 -2
  182. package/src/modules/customer/pages/frontStore/login/LoginForm.jsx +0 -1
  183. package/src/modules/customer/services/CustomerCollection.js +23 -104
  184. package/src/modules/customer/services/CustomerGroupCollection.js +21 -70
  185. package/src/modules/customer/services/registerDefaultCustomerCollectionFilters.js +90 -0
  186. package/src/modules/customer/services/registerDefaultCustomerGroupCollectionFilters.js +50 -0
  187. package/src/modules/graphql/pages/global/[bodyParser]buildQuery[graphql].js +1 -1
  188. package/src/modules/graphql/pages/global/[buildQuery]graphql[notification].js +1 -1
  189. package/src/modules/graphql/services/graphqlMiddleware.js +1 -1
  190. package/src/modules/oms/bootstrap.js +17 -0
  191. package/src/modules/oms/graphql/types/Order/Order.admin.resolvers.js +1 -1
  192. package/src/modules/oms/graphql/types/Order/Order.resolvers.js +2 -1
  193. package/src/modules/oms/pages/admin/orderGrid/Grid.jsx +152 -51
  194. package/src/modules/oms/pages/admin/orderGrid/index.js +1 -2
  195. package/src/modules/oms/services/OrderCollection.js +19 -139
  196. package/src/modules/oms/services/registerDefaultOrderCollectionFilters.js +121 -0
  197. package/src/modules/promotion/bootstrap.js +16 -0
  198. package/src/modules/promotion/graphql/types/Coupon/Coupon.admin.resolvers.js +2 -7
  199. package/src/modules/promotion/pages/admin/couponGrid/Grid.jsx +157 -33
  200. package/src/modules/promotion/pages/admin/couponGrid/index.js +1 -2
  201. package/src/modules/promotion/services/CouponCollection.js +21 -130
  202. package/src/modules/promotion/services/registerDefaultCouponCollectionFilters.js +72 -0
  203. package/src/modules/stripe/api/stripeWebHook/[bodyJson]webhook.js +4 -2
  204. package/src/modules/tax/bootstrap.js +17 -0
  205. package/src/modules/tax/services/TaxClassCollection.js +22 -56
  206. package/src/modules/tax/services/registerDefaultTaxClassCollectionFilters.js +49 -0
  207. package/src/components/admin/oms/shippingSetting/Method.jsx +0 -73
  208. package/src/components/common/grid/headers/Basic.jsx +0 -55
  209. package/src/lib/log/debuger.js +0 -89
  210. package/src/modules/customer/pages/frontStore/login/LoginButton.jsx +0 -27
  211. /package/src/components/admin/{oms → checkout}/shippingSetting/ZoneForm.jsx +0 -0
  212. /package/src/modules/{oms → checkout}/pages/admin/all/ShippingSettingMenu.jsx +0 -0
  213. /package/src/modules/{oms → checkout}/pages/admin/shippingSetting/index.js +0 -0
  214. /package/src/modules/{oms → checkout}/pages/admin/shippingSetting/route.json +0 -0
@@ -10,12 +10,16 @@ import CreatableSelect from 'react-select/creatable';
10
10
  import Spinner from '@components/common/Spinner';
11
11
  import { useQuery } from 'urql';
12
12
  import { toast } from 'react-toastify';
13
+ import PriceBasedPrice from '@components/admin/checkout/shippingSetting/PriceBasedPrice';
14
+ import WeightBasedPrice from '@components/admin/checkout/shippingSetting/WeightBasedPrice';
15
+ import { Input } from '@components/common/form/fields/Input';
13
16
 
14
17
  const MethodsQuery = `
15
18
  query Methods {
16
19
  shippingMethods {
17
20
  value: shippingMethodId
18
21
  label: name
22
+ updateApi
19
23
  }
20
24
  createShippingMethodApi: url(routeId: "createShippingMethod")
21
25
  }
@@ -83,9 +87,18 @@ Condition.defaultProps = {
83
87
  };
84
88
 
85
89
  function MethodForm({ saveMethodApi, closeModal, getZones, method }) {
86
- const [type, setType] = React.useState(
87
- method?.calculateApi ? 'api' : 'flat_rate'
88
- );
90
+ const [type, setType] = React.useState(() => {
91
+ if (method?.calculateApi) {
92
+ return 'api';
93
+ }
94
+ if (method?.priceBasedCost) {
95
+ return 'price_based_rate';
96
+ }
97
+ if (method?.weightBasedCost) {
98
+ return 'weight_based_rate';
99
+ }
100
+ return 'flat_rate';
101
+ });
89
102
  const [isLoading, setIsLoading] = React.useState(false);
90
103
  const [shippingMethod, setMethod] = React.useState(
91
104
  method
@@ -98,6 +111,8 @@ function MethodForm({ saveMethodApi, closeModal, getZones, method }) {
98
111
  const [hasCondition, setHasCondition] = React.useState(
99
112
  !!method?.conditionType
100
113
  );
114
+ const [name, setName] = React.useState(method?.name || '');
115
+ const [updatingName, setUpdatingName] = React.useState(false);
101
116
 
102
117
  const [result, reexecuteQuery] = useQuery({
103
118
  query: MethodsQuery
@@ -127,6 +142,10 @@ function MethodForm({ saveMethodApi, closeModal, getZones, method }) {
127
142
  );
128
143
  }
129
144
 
145
+ const currentMethod = result.data.shippingMethods.find(
146
+ (m) => m.value === shippingMethod?.value
147
+ );
148
+
130
149
  return (
131
150
  <Card title="Shipping method">
132
151
  <Form
@@ -138,21 +157,78 @@ function MethodForm({ saveMethodApi, closeModal, getZones, method }) {
138
157
  if (!response.error) {
139
158
  await getZones({ requestPolicy: 'network-only' });
140
159
  closeModal();
160
+ toast.success('Shipping method saved successfully');
141
161
  } else {
142
162
  toast.error(response.error.message);
143
163
  }
144
164
  }}
145
165
  >
146
166
  <Card.Session title="Method name">
147
- <CreatableSelect
148
- isClearable
149
- isDisabled={isLoading}
150
- isLoading={isLoading}
151
- onChange={(newValue) => setMethod(newValue)}
152
- onCreateOption={handleCreate}
153
- options={result.data.shippingMethods}
154
- value={shippingMethod}
155
- />
167
+ {!method ? (
168
+ <CreatableSelect
169
+ isClearable
170
+ isDisabled={isLoading}
171
+ isLoading={isLoading}
172
+ onChange={(newValue) => setMethod(newValue)}
173
+ onCreateOption={handleCreate}
174
+ options={result.data.shippingMethods}
175
+ value={shippingMethod}
176
+ />
177
+ ) : (
178
+ <div className="flex gap-1 justify-start items-center">
179
+ <Input
180
+ name="name"
181
+ type="text"
182
+ placeholder="Method name"
183
+ validationRules={['notEmpty']}
184
+ value={name}
185
+ disabled={!updatingName}
186
+ suffix={
187
+ <a
188
+ href="#"
189
+ onClick={(e) => {
190
+ e.preventDefault();
191
+ if (updatingName) setName(method.name);
192
+ setUpdatingName(!updatingName);
193
+ }}
194
+ >
195
+ <span className="text-interactive">
196
+ {updatingName ? 'Cancel' : 'Edit'}
197
+ </span>
198
+ </a>
199
+ }
200
+ onChange={(e) => setName(e.target.value)}
201
+ />
202
+ {updatingName && (
203
+ <Button
204
+ title="Save"
205
+ variant="primary"
206
+ onAction={async () => {
207
+ // Use fetch to call the API (method.updateApi) to update the method name
208
+ // The API should accept a PATCH request with the new name as the payload
209
+ // The API should return the updated method object
210
+ const response = await fetch(currentMethod.updateApi, {
211
+ method: 'PATCH',
212
+ headers: {
213
+ 'Content-Type': 'application/json'
214
+ },
215
+ credentials: 'same-origin',
216
+ body: JSON.stringify({
217
+ name
218
+ })
219
+ });
220
+ const data = await response.json();
221
+ if (response.ok) {
222
+ setName(data.name);
223
+ setUpdatingName(false);
224
+ } else {
225
+ toast.error(data.error.message);
226
+ }
227
+ }}
228
+ />
229
+ )}
230
+ </div>
231
+ )}
156
232
  <Field
157
233
  type="hidden"
158
234
  name="method_id"
@@ -166,6 +242,8 @@ function MethodForm({ saveMethodApi, closeModal, getZones, method }) {
166
242
  name="calculation_type"
167
243
  options={[
168
244
  { text: 'Flat rate', value: 'flat_rate' },
245
+ { text: 'Price based rate', value: 'price_based_rate' },
246
+ { text: 'Weight based rate', value: 'weight_based_rate' },
169
247
  { text: 'API calculate', value: 'api' }
170
248
  ]}
171
249
  defaultValue={method?.calculateApi ? 'api' : 'flat_rate'}
@@ -183,6 +261,12 @@ function MethodForm({ saveMethodApi, closeModal, getZones, method }) {
183
261
  value={method?.cost?.value}
184
262
  />
185
263
  )}
264
+ {type === 'price_based_rate' && (
265
+ <PriceBasedPrice lines={method?.priceBasedCost || []} />
266
+ )}
267
+ {type === 'weight_based_rate' && (
268
+ <WeightBasedPrice lines={method?.weightBasedCost || []} />
269
+ )}
186
270
  {type === 'api' && (
187
271
  <Field
188
272
  name="calculate_api"
@@ -210,7 +294,14 @@ function MethodForm({ saveMethodApi, closeModal, getZones, method }) {
210
294
  </Card.Session>
211
295
  <Card.Session>
212
296
  <div className="flex justify-end gap-1">
213
- <Button title="Cancel" variant="secondary" onAction={closeModal} />
297
+ <Button
298
+ title="Cancel"
299
+ variant="secondary"
300
+ onAction={async () => {
301
+ await getZones({ requestPolicy: 'network-only' });
302
+ closeModal();
303
+ }}
304
+ />
214
305
  <Button
215
306
  title="Save"
216
307
  variant="primary"
@@ -242,6 +333,26 @@ MethodForm.propTypes = {
242
333
  cost: PropTypes.shape({
243
334
  value: PropTypes.string
244
335
  }),
336
+ priceBasedCost: PropTypes.arrayOf(
337
+ PropTypes.shape({
338
+ minPrice: PropTypes.shape({
339
+ value: PropTypes.number
340
+ }),
341
+ cost: PropTypes.shape({
342
+ value: PropTypes.number
343
+ })
344
+ })
345
+ ),
346
+ weightBasedCost: PropTypes.arrayOf(
347
+ PropTypes.shape({
348
+ minWeight: PropTypes.shape({
349
+ value: PropTypes.number
350
+ }),
351
+ cost: PropTypes.shape({
352
+ value: PropTypes.number
353
+ })
354
+ })
355
+ ),
245
356
  conditionType: PropTypes.string,
246
357
  min: PropTypes.string,
247
358
  max: PropTypes.string
@@ -1,8 +1,8 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { useModal } from '@components/common/modal/useModal';
4
- import Method from './Method';
5
- import MethodForm from './MethodForm';
4
+ import Method from '@components/admin/checkout/shippingSetting/Method';
5
+ import MethodForm from '@components/admin/checkout/shippingSetting/MethodForm';
6
6
 
7
7
  export function Methods({ getZones, methods, addMethodApi }) {
8
8
  const modal = useModal();
@@ -0,0 +1,101 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Field } from '@components/common/form/Field';
4
+
5
+ export default function PriceBasedPrice({ lines }) {
6
+ // This is a table with 3 columns: Min Price, Shipping Cost, and Action
7
+ const [rows, setRows] = React.useState(
8
+ lines.map((line) => ({
9
+ ...line,
10
+ key: Math.random().toString(36).substring(7)
11
+ }))
12
+ );
13
+ return (
14
+ <div className="my-2">
15
+ <table className="border-collapse divide-y">
16
+ <thead>
17
+ <tr>
18
+ <th className="border-none">Min Price</th>
19
+ <th className="border-none">Shipping Cost</th>
20
+ <th className="border-none">Action</th>
21
+ </tr>
22
+ </thead>
23
+ <tbody>
24
+ {rows.map((row, index) => (
25
+ // Create a random key for each row
26
+ <tr key={row.key} className="border-divider py-2">
27
+ <td className="border-none">
28
+ <Field
29
+ name={`price_based_cost[${index}][min_price]`}
30
+ placeholder="Min Price"
31
+ type="text"
32
+ value={row.minPrice?.value}
33
+ validationRules={['notEmpty', 'number']}
34
+ />
35
+ </td>
36
+ <td className="border-none">
37
+ <Field
38
+ name={`price_based_cost[${index}][cost]`}
39
+ placeholder="Shipping Cost"
40
+ type="text"
41
+ value={row.cost?.value}
42
+ validationRules={['notEmpty', 'number']}
43
+ />
44
+ </td>
45
+ <td className="border-none">
46
+ <a
47
+ href="#"
48
+ onClick={() => {
49
+ setRows(rows.filter((r) => r.key !== row.key));
50
+ }}
51
+ className="text-critical"
52
+ >
53
+ Delete
54
+ </a>
55
+ </td>
56
+ </tr>
57
+ ))}
58
+ </tbody>
59
+ <tfoot>
60
+ <tr>
61
+ <td colSpan="3" className="border-none">
62
+ <a
63
+ href="#"
64
+ className="text-interactive"
65
+ onClick={() => {
66
+ setRows([
67
+ ...rows,
68
+ {
69
+ min_price: '',
70
+ shipping_cost: '',
71
+ key: Math.random().toString(36).substring(7)
72
+ }
73
+ ]);
74
+ }}
75
+ >
76
+ + Add Line
77
+ </a>
78
+ </td>
79
+ </tr>
80
+ </tfoot>
81
+ </table>
82
+ </div>
83
+ );
84
+ }
85
+
86
+ PriceBasedPrice.propTypes = {
87
+ lines: PropTypes.arrayOf(
88
+ PropTypes.shape({
89
+ minPrice: PropTypes.shape({
90
+ value: PropTypes.number.isRequired
91
+ }),
92
+ cost: PropTypes.shape({
93
+ value: PropTypes.number.isRequired
94
+ })
95
+ })
96
+ )
97
+ };
98
+
99
+ PriceBasedPrice.defaultProps = {
100
+ lines: []
101
+ };
@@ -0,0 +1,101 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Field } from '@components/common/form/Field';
4
+
5
+ export default function WeightBasedPrice({ lines }) {
6
+ // This is a table with 3 columns: Min Price, Shipping Cost, and Action
7
+ const [rows, setRows] = React.useState(
8
+ lines.map((line) => ({
9
+ ...line,
10
+ key: Math.random().toString(36).substring(7)
11
+ }))
12
+ );
13
+ return (
14
+ <div className="my-2">
15
+ <table className="border-collapse divide-y">
16
+ <thead>
17
+ <tr>
18
+ <th className="border-none">Min Weight</th>
19
+ <th className="border-none">Shipping Cost</th>
20
+ <th className="border-none">Action</th>
21
+ </tr>
22
+ </thead>
23
+ <tbody>
24
+ {rows.map((row, index) => (
25
+ // Create a random key for each row
26
+ <tr key={row.key} className="border-divider py-2">
27
+ <td className="border-none">
28
+ <Field
29
+ name={`weight_based_cost[${index}][min_weight]`}
30
+ placeholder="Min Weight"
31
+ type="text"
32
+ value={row.minWeight?.value}
33
+ validationRules={['notEmpty', 'number']}
34
+ />
35
+ </td>
36
+ <td className="border-none">
37
+ <Field
38
+ name={`weight_based_cost[${index}][cost]`}
39
+ placeholder="Shipping Cost"
40
+ type="text"
41
+ value={row.cost?.value}
42
+ validationRules={['notEmpty', 'number']}
43
+ />
44
+ </td>
45
+ <td className="border-none">
46
+ <a
47
+ href="#"
48
+ onClick={() => {
49
+ setRows(rows.filter((r) => r.key !== row.key));
50
+ }}
51
+ className="text-critical"
52
+ >
53
+ Delete
54
+ </a>
55
+ </td>
56
+ </tr>
57
+ ))}
58
+ </tbody>
59
+ <tfoot>
60
+ <tr>
61
+ <td colSpan="3" className="border-none">
62
+ <a
63
+ href="#"
64
+ className="text-interactive"
65
+ onClick={() => {
66
+ setRows([
67
+ ...rows,
68
+ {
69
+ min_price: '',
70
+ shipping_cost: '',
71
+ key: Math.random().toString(36).substring(7)
72
+ }
73
+ ]);
74
+ }}
75
+ >
76
+ + Add Line
77
+ </a>
78
+ </td>
79
+ </tr>
80
+ </tfoot>
81
+ </table>
82
+ </div>
83
+ );
84
+ }
85
+
86
+ WeightBasedPrice.propTypes = {
87
+ lines: PropTypes.arrayOf(
88
+ PropTypes.shape({
89
+ minWeight: PropTypes.shape({
90
+ value: PropTypes.number.isRequired
91
+ }),
92
+ cost: PropTypes.shape({
93
+ value: PropTypes.number.isRequired
94
+ })
95
+ })
96
+ )
97
+ };
98
+
99
+ WeightBasedPrice.defaultProps = {
100
+ lines: []
101
+ };
@@ -1,10 +1,12 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
+ import axios from 'axios';
4
+ import { toast } from 'react-toastify';
3
5
  import { Card } from '@components/admin/cms/Card';
4
6
  import MapIcon from '@heroicons/react/solid/esm/LocationMarkerIcon';
5
7
  import { useModal } from '@components/common/modal/useModal';
6
- import ZoneForm from './ZoneForm';
7
- import { Methods } from './Methods';
8
+ import ZoneForm from '@components/admin/checkout/shippingSetting/ZoneForm';
9
+ import { Methods } from '@components/admin/checkout/shippingSetting/Methods';
8
10
 
9
11
  function Zone({ zone, countries, getZones }) {
10
12
  const modal = useModal();
@@ -13,7 +15,7 @@ function Zone({ zone, countries, getZones }) {
13
15
  title={
14
16
  <div className="flex justify-between items-center gap-2">
15
17
  <div>{zone.name}</div>
16
- <div>
18
+ <div className="flex justify-between gap-2">
17
19
  <a
18
20
  href="#"
19
21
  className="text-interactive"
@@ -24,6 +26,33 @@ function Zone({ zone, countries, getZones }) {
24
26
  >
25
27
  Edit Zone
26
28
  </a>
29
+ <a
30
+ className="text-critical"
31
+ href="#"
32
+ onClick={async (e) => {
33
+ e.preventDefault();
34
+ try {
35
+ const response = await axios.delete(zone.deleteApi);
36
+ if (response.status === 200) {
37
+ // Toast success
38
+ toast.success('Zone removed successfully');
39
+ // Delay for 2 seconds
40
+ setTimeout(() => {
41
+ // Reload page
42
+ window.location.reload();
43
+ }, 1500);
44
+ } else {
45
+ // Toast error
46
+ toast.error('Failed to remove zone');
47
+ }
48
+ } catch (error) {
49
+ // Toast error
50
+ toast.error('Failed to remove zone');
51
+ }
52
+ }}
53
+ >
54
+ Remove Zone
55
+ </a>
27
56
  </div>
28
57
  </div>
29
58
  }
@@ -35,7 +64,7 @@ function Zone({ zone, countries, getZones }) {
35
64
  </div>
36
65
  <div className="flex-grow px-1">
37
66
  <div>
38
- <b>{zone.country.name}</b>
67
+ <b>{zone.country?.name || 'Worldwide'}</b>
39
68
  </div>
40
69
  <div>
41
70
  {zone.provinces
@@ -97,6 +126,7 @@ Zone.propTypes = {
97
126
  })
98
127
  ),
99
128
  addMethodApi: PropTypes.string,
129
+ deleteApi: PropTypes.string,
100
130
  updateApi: PropTypes.string
101
131
  }).isRequired,
102
132
  countries: PropTypes.arrayOf(
@@ -1,11 +1,13 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import Zone from './Zone';
3
+ import Zone from '@components/admin/checkout/shippingSetting/Zone';
4
4
 
5
5
  export function Zones({ countries, getZones, zones }) {
6
6
  return (
7
7
  <>
8
- {zones.map((zone) => <Zone zone={zone} getZones={getZones} countries={countries} />)}
8
+ {zones.map((zone) => (
9
+ <Zone zone={zone} getZones={getZones} countries={countries} />
10
+ ))}
9
11
  </>
10
12
  );
11
13
  }
@@ -34,7 +36,8 @@ Zones.propTypes = {
34
36
  uuid: PropTypes.string.isRequired,
35
37
  name: PropTypes.string.isRequired
36
38
  })
37
- ).isRequired
39
+ ).isRequired,
40
+ deleteApi: PropTypes.string.isRequired
38
41
  })
39
42
  ).isRequired,
40
43
  getZones: PropTypes.func.isRequired
@@ -37,13 +37,13 @@ function AttributeGroupSelector({
37
37
  variables: {
38
38
  filters: inputValue
39
39
  ? [
40
- { key: 'name', operation: '=', value: inputValue },
41
- { key: 'page', operation: '=', value: page.toString() },
42
- { key: 'limit', operation: '=', value: limit.toString() }
40
+ { key: 'name', operation: 'eq', value: inputValue },
41
+ { key: 'page', operation: 'eq', value: page.toString() },
42
+ { key: 'limit', operation: 'eq', value: limit.toString() }
43
43
  ]
44
44
  : [
45
- { key: 'limit', operation: '=', value: limit.toString() },
46
- { key: 'page', operation: '=', value: page.toString() }
45
+ { key: 'limit', operation: 'eq', value: limit.toString() },
46
+ { key: 'page', operation: 'eq', value: page.toString() }
47
47
  ]
48
48
  },
49
49
  pause: true
@@ -30,13 +30,13 @@ function CategorySelector({ onSelect, onUnSelect, selectedIDs, closeModal }) {
30
30
  variables: {
31
31
  filters: inputValue
32
32
  ? [
33
- { key: 'name', operation: '=', value: inputValue },
34
- { key: 'page', operation: '=', value: page.toString() },
35
- { key: 'limit', operation: '=', value: limit.toString() }
33
+ { key: 'name', operation: 'eq', value: inputValue },
34
+ { key: 'page', operation: 'eq', value: page.toString() },
35
+ { key: 'limit', operation: 'eq', value: limit.toString() }
36
36
  ]
37
37
  : [
38
- { key: 'limit', operation: '=', value: limit.toString() },
39
- { key: 'page', operation: '=', value: page.toString() }
38
+ { key: 'limit', operation: 'eq', value: limit.toString() },
39
+ { key: 'page', operation: 'eq', value: page.toString() }
40
40
  ]
41
41
  },
42
42
  pause: true
@@ -30,13 +30,13 @@ function CollectionSelector({ onSelect, onUnSelect, selectedIDs, closeModal }) {
30
30
  variables: {
31
31
  filters: inputValue
32
32
  ? [
33
- { key: 'name', operation: '=', value: inputValue },
34
- { key: 'page', operation: '=', value: page.toString() },
35
- { key: 'limit', operation: '=', value: limit.toString() }
33
+ { key: 'name', operation: 'eq', value: inputValue },
34
+ { key: 'page', operation: 'eq', value: page.toString() },
35
+ { key: 'limit', operation: 'eq', value: limit.toString() }
36
36
  ]
37
37
  : [
38
- { key: 'limit', operation: '=', value: limit.toString() },
39
- { key: 'page', operation: '=', value: page.toString() }
38
+ { key: 'limit', operation: 'eq', value: limit.toString() },
39
+ { key: 'page', operation: 'eq', value: page.toString() }
40
40
  ]
41
41
  },
42
42
  pause: true
@@ -46,13 +46,13 @@ function ProductSkuSelector({
46
46
  variables: {
47
47
  filters: inputValue
48
48
  ? [
49
- { key: 'keyword', operation: '=', value: inputValue },
50
- { key: 'page', operation: '=', value: page.toString() },
51
- { key: 'limit', operation: '=', value: limit.toString() }
49
+ { key: 'keyword', operation: 'eq', value: inputValue },
50
+ { key: 'page', operation: 'eq', value: page.toString() },
51
+ { key: 'limit', operation: 'eq', value: limit.toString() }
52
52
  ]
53
53
  : [
54
- { key: 'limit', operation: '=', value: limit.toString() },
55
- { key: 'page', operation: '=', value: page.toString() }
54
+ { key: 'limit', operation: 'eq', value: limit.toString() },
55
+ { key: 'page', operation: 'eq', value: page.toString() }
56
56
  ]
57
57
  },
58
58
  pause: true
@@ -144,7 +144,28 @@ function ProductSkuSelector({
144
144
  className="grid grid-cols-8 gap-2 py-1 border-divider items-center"
145
145
  >
146
146
  <div className="col-span-1">
147
- <img src={product.image?.url} alt={product.name} />
147
+ <div className="text-border border border-divider p-075 rounded flex justify-center">
148
+ {product.image?.url && (
149
+ <img src={product.image?.url} alt={product.name} />
150
+ )}
151
+ {!product.image?.url && (
152
+ <svg
153
+ className="self-center"
154
+ xmlns="http://www.w3.org/2000/svg"
155
+ width="2rem"
156
+ fill="none"
157
+ viewBox="0 0 24 24"
158
+ stroke="currentColor"
159
+ >
160
+ <path
161
+ strokeLinecap="round"
162
+ strokeLinejoin="round"
163
+ strokeWidth={2}
164
+ d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
165
+ />
166
+ </svg>
167
+ )}
168
+ </div>
148
169
  </div>
149
170
  <div className="col-span-5">
150
171
  <h3>{product.name}</h3>
@@ -21,16 +21,6 @@ export function CheckoutProvider({
21
21
  const [, setError] = useState(null);
22
22
 
23
23
  // Call api to current url when steps change
24
- useEffect(() => {
25
- const reload = async () => {
26
- const url = new URL(window.location.href, window.location.origin);
27
- url.searchParams.append('ajax', true);
28
- await AppContextDispatch.fetchPageData(url);
29
- url.searchParams.delete('ajax');
30
- };
31
- reload();
32
- }, [steps]);
33
-
34
24
  useEffect(() => {
35
25
  const placeOrder = async () => {
36
26
  // If order is placed, do nothing
@@ -49,14 +39,18 @@ export function CheckoutProvider({
49
39
  setOrderPlaced(true);
50
40
  setOrderId(response.data.data.uuid);
51
41
  setError(null);
52
- // let redirectUrl = response.data.data.redirect || checkoutSuccessUrl;
53
-
54
- // window.location.href = redirectUrl;
55
42
  } else {
56
43
  setError(response.data.error.message);
57
44
  }
58
45
  };
59
- placeOrder();
46
+ const reload = async () => {
47
+ const url = new URL(window.location.href, window.location.origin);
48
+ url.searchParams.append('ajax', true);
49
+ await AppContextDispatch.fetchPageData(url);
50
+ url.searchParams.delete('ajax');
51
+ await placeOrder();
52
+ };
53
+ reload();
60
54
  }, [steps]);
61
55
 
62
56
  const getPaymentMethods = async () => {