@deenruv/admin-dashboard 1.0.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 (292) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +30 -0
  3. package/dist/@types/resources.js +51 -0
  4. package/dist/DeenruvAdminPanel.js +118 -0
  5. package/dist/DeenruvDeveloperIndicator.js +57 -0
  6. package/dist/components/Aexol.js +4 -0
  7. package/dist/components/BrandLogo.js +22 -0
  8. package/dist/components/CanLeaveRouteDialog.js +8 -0
  9. package/dist/components/DataTable.js +13 -0
  10. package/dist/components/DeleteDialog.js +6 -0
  11. package/dist/components/DuplicateEntry.js +46 -0
  12. package/dist/components/GlobalSearch.js +134 -0
  13. package/dist/components/History/AddEntryForm.js +29 -0
  14. package/dist/components/History/DeleteEntryDialog.js +25 -0
  15. package/dist/components/History/EditEntryDialog.js +32 -0
  16. package/dist/components/History/History.js +13 -0
  17. package/dist/components/History/ModifyHistoryInfo.js +6 -0
  18. package/dist/components/History/Timeline.js +53 -0
  19. package/dist/components/History/index.js +5 -0
  20. package/dist/components/Menu/ActiveAdmins.js +24 -0
  21. package/dist/components/Menu/ChannelSwitcher.js +20 -0
  22. package/dist/components/Menu/LanguagesDropdown.js +26 -0
  23. package/dist/components/Menu/Navigation.js +270 -0
  24. package/dist/components/Menu/NavigationFooter.js +12 -0
  25. package/dist/components/Menu/Notifications.js +90 -0
  26. package/dist/components/Menu/index.js +67 -0
  27. package/dist/components/index.js +6 -0
  28. package/dist/graphql/base.js +95 -0
  29. package/dist/graphql/collections.js +94 -0
  30. package/dist/graphql/draft_order.js +307 -0
  31. package/dist/graphql/orders.js +157 -0
  32. package/dist/graphql/products.js +230 -0
  33. package/dist/graphql/scalars.js +22 -0
  34. package/dist/i18.js +13 -0
  35. package/dist/index.css +161 -0
  36. package/dist/index.d.ts +11 -0
  37. package/dist/index.js +1 -0
  38. package/dist/locales/en/admins.json +57 -0
  39. package/dist/locales/en/assets.json +69 -0
  40. package/dist/locales/en/channels.json +66 -0
  41. package/dist/locales/en/collections.json +145 -0
  42. package/dist/locales/en/common.json +1127 -0
  43. package/dist/locales/en/countries.json +50 -0
  44. package/dist/locales/en/customerGroups.json +6 -0
  45. package/dist/locales/en/customers.json +109 -0
  46. package/dist/locales/en/dashboard.json +34 -0
  47. package/dist/locales/en/facets.json +78 -0
  48. package/dist/locales/en/globalSettings.json +15 -0
  49. package/dist/locales/en/index.js +52 -0
  50. package/dist/locales/en/orders.json +932 -0
  51. package/dist/locales/en/paymentMethods.json +59 -0
  52. package/dist/locales/en/permissions.json +94 -0
  53. package/dist/locales/en/products.json +194 -0
  54. package/dist/locales/en/promotions.json +65 -0
  55. package/dist/locales/en/roles.json +59 -0
  56. package/dist/locales/en/sellers.json +41 -0
  57. package/dist/locales/en/shippingMethods.json +84 -0
  58. package/dist/locales/en/stockLocations.json +40 -0
  59. package/dist/locales/en/system.json +41 -0
  60. package/dist/locales/en/table.json +201 -0
  61. package/dist/locales/en/taxCategories.json +47 -0
  62. package/dist/locales/en/taxRates.json +56 -0
  63. package/dist/locales/en/zones.json +47 -0
  64. package/dist/locales/index.js +2 -0
  65. package/dist/locales/pl/admins.json +57 -0
  66. package/dist/locales/pl/assets.json +69 -0
  67. package/dist/locales/pl/channels.json +66 -0
  68. package/dist/locales/pl/collections.json +145 -0
  69. package/dist/locales/pl/common.json +1128 -0
  70. package/dist/locales/pl/countries.json +50 -0
  71. package/dist/locales/pl/customerGroups.json +6 -0
  72. package/dist/locales/pl/customers.json +109 -0
  73. package/dist/locales/pl/dashboard.json +34 -0
  74. package/dist/locales/pl/facets.json +78 -0
  75. package/dist/locales/pl/globalSettings.json +15 -0
  76. package/dist/locales/pl/index.js +52 -0
  77. package/dist/locales/pl/orders.json +932 -0
  78. package/dist/locales/pl/paymentMethods.json +59 -0
  79. package/dist/locales/pl/permissions.json +94 -0
  80. package/dist/locales/pl/products.json +194 -0
  81. package/dist/locales/pl/promotions.json +65 -0
  82. package/dist/locales/pl/roles.json +59 -0
  83. package/dist/locales/pl/sellers.json +41 -0
  84. package/dist/locales/pl/shippingMethods.json +84 -0
  85. package/dist/locales/pl/stockLocations.json +40 -0
  86. package/dist/locales/pl/system.json +41 -0
  87. package/dist/locales/pl/table.json +201 -0
  88. package/dist/locales/pl/taxCategories.json +47 -0
  89. package/dist/locales/pl/taxRates.json +56 -0
  90. package/dist/locales/pl/zones.json +47 -0
  91. package/dist/notifications/OrderStatusNotification.js +47 -0
  92. package/dist/notifications/SystemStatusNotification.js +19 -0
  93. package/dist/pages/Custom404.js +5 -0
  94. package/dist/pages/LoginScreen.js +37 -0
  95. package/dist/pages/Root.js +252 -0
  96. package/dist/pages/admins/Detail.js +72 -0
  97. package/dist/pages/admins/List.js +56 -0
  98. package/dist/pages/admins/_components/AdminDetailView.js +34 -0
  99. package/dist/pages/admins/_components/RolesCard.js +31 -0
  100. package/dist/pages/admins/index.js +2 -0
  101. package/dist/pages/assets/List.js +82 -0
  102. package/dist/pages/assets/_components/Asset.js +114 -0
  103. package/dist/pages/assets/_components/AssetListView.js +29 -0
  104. package/dist/pages/assets/_components/EditAssetDialog.js +85 -0
  105. package/dist/pages/assets/_components/UploadAssetDialog.js +133 -0
  106. package/dist/pages/assets/_components/UploadProgress.js +20 -0
  107. package/dist/pages/assets/index.js +1 -0
  108. package/dist/pages/channels/Detail.js +149 -0
  109. package/dist/pages/channels/List.js +46 -0
  110. package/dist/pages/channels/_components/ChannelDetailView.js +51 -0
  111. package/dist/pages/channels/_components/DefaultsCard.js +25 -0
  112. package/dist/pages/channels/index.js +2 -0
  113. package/dist/pages/collections/Detail.js +61 -0
  114. package/dist/pages/collections/List.js +135 -0
  115. package/dist/pages/collections/_components/CollectionDetailView.js +52 -0
  116. package/dist/pages/collections/_components/CollectionProductVariantsDrawer.js +28 -0
  117. package/dist/pages/collections/_components/CombinationMode.js +6 -0
  118. package/dist/pages/collections/_components/ContentsCard.js +43 -0
  119. package/dist/pages/collections/_components/ContentsTable.js +102 -0
  120. package/dist/pages/collections/_components/DeleteCollectionsFromChannel.js +36 -0
  121. package/dist/pages/collections/_components/FacetsSelector.js +30 -0
  122. package/dist/pages/collections/_components/FiltersCard.js +101 -0
  123. package/dist/pages/collections/_components/MoveCollectionsToCollections.js +107 -0
  124. package/dist/pages/collections/_components/MoveEntityToChannels.js +115 -0
  125. package/dist/pages/collections/_components/PageHeader.js +11 -0
  126. package/dist/pages/collections/_components/SelectedCollectionsModal.js +22 -0
  127. package/dist/pages/collections/_components/VariantsSelector.js +43 -0
  128. package/dist/pages/collections/consts.js +7 -0
  129. package/dist/pages/collections/index.js +2 -0
  130. package/dist/pages/countries/Detail.js +57 -0
  131. package/dist/pages/countries/List.js +47 -0
  132. package/dist/pages/countries/_components/CountryDetailView.js +28 -0
  133. package/dist/pages/countries/index.js +2 -0
  134. package/dist/pages/customer-groups/Detail.js +76 -0
  135. package/dist/pages/customer-groups/List.js +41 -0
  136. package/dist/pages/customer-groups/_components/CustomerGroupsDetailView.js +21 -0
  137. package/dist/pages/customer-groups/index.js +2 -0
  138. package/dist/pages/customers/Detail.js +75 -0
  139. package/dist/pages/customers/List.js +60 -0
  140. package/dist/pages/customers/_components/Address.js +59 -0
  141. package/dist/pages/customers/_components/AddressDialog.js +56 -0
  142. package/dist/pages/customers/_components/AddressForm.js +77 -0
  143. package/dist/pages/customers/_components/AddressesCard.js +9 -0
  144. package/dist/pages/customers/_components/CustomerDetailSidebar.js +9 -0
  145. package/dist/pages/customers/_components/CustomerDetailView.js +41 -0
  146. package/dist/pages/customers/_components/CustomerGroupsCard.js +46 -0
  147. package/dist/pages/customers/_components/HistoryTab.js +65 -0
  148. package/dist/pages/customers/_components/OrdersTab.js +46 -0
  149. package/dist/pages/customers/_components/PersonalDataCard.js +6 -0
  150. package/dist/pages/customers/_components/VerifiedCard.js +6 -0
  151. package/dist/pages/customers/index.js +2 -0
  152. package/dist/pages/dashboard/Dashboard.js +10 -0
  153. package/dist/pages/dashboard/index.js +1 -0
  154. package/dist/pages/extensions/Extensions.js +74 -0
  155. package/dist/pages/extensions/index.js +1 -0
  156. package/dist/pages/facets/Detail.js +56 -0
  157. package/dist/pages/facets/List.js +48 -0
  158. package/dist/pages/facets/_components/AddFacetValueDialog.js +105 -0
  159. package/dist/pages/facets/_components/ColorSample.js +18 -0
  160. package/dist/pages/facets/_components/FacetDetailView.js +98 -0
  161. package/dist/pages/facets/index.js +2 -0
  162. package/dist/pages/global-settings/GlobalSettingsComponent.js +30 -0
  163. package/dist/pages/global-settings/index.js +71 -0
  164. package/dist/pages/index.js +25 -0
  165. package/dist/pages/orders/Detail.js +21 -0
  166. package/dist/pages/orders/List.js +132 -0
  167. package/dist/pages/orders/_components/AddPaymentDialog.js +50 -0
  168. package/dist/pages/orders/_components/AddressCard.js +260 -0
  169. package/dist/pages/orders/_components/CancelAndRefundDialog.js +29 -0
  170. package/dist/pages/orders/_components/ChangesRegister.js +68 -0
  171. package/dist/pages/orders/_components/ChangesRegisterTable.js +18 -0
  172. package/dist/pages/orders/_components/CouponCodesCard.js +85 -0
  173. package/dist/pages/orders/_components/CustomComponent.js +21 -0
  174. package/dist/pages/orders/_components/CustomerSelectCard.js +117 -0
  175. package/dist/pages/orders/_components/EditNoteButton.js +10 -0
  176. package/dist/pages/orders/_components/FulfillmentModal.js +85 -0
  177. package/dist/pages/orders/_components/LineItem.js +7 -0
  178. package/dist/pages/orders/_components/ManualOrderChangeModal.js +47 -0
  179. package/dist/pages/orders/_components/ModifyAcceptModal.js +22 -0
  180. package/dist/pages/orders/_components/ModifyingCard.js +77 -0
  181. package/dist/pages/orders/_components/OrderHistory.js +59 -0
  182. package/dist/pages/orders/_components/OrderLineActionModal/ActionQuantityPrice.js +58 -0
  183. package/dist/pages/orders/_components/OrderLineActionModal/index.js +7 -0
  184. package/dist/pages/orders/_components/OrderLineActionModal/types.js +1 -0
  185. package/dist/pages/orders/_components/OrderLineCustomFields.js +26 -0
  186. package/dist/pages/orders/_components/OrderSummary.js +10 -0
  187. package/dist/pages/orders/_components/PaymentMetadata.js +6 -0
  188. package/dist/pages/orders/_components/Payments.js +113 -0
  189. package/dist/pages/orders/_components/PossibleOrderStates.js +54 -0
  190. package/dist/pages/orders/_components/PriceChangedInfo.js +16 -0
  191. package/dist/pages/orders/_components/ProductsCard.js +308 -0
  192. package/dist/pages/orders/_components/ProductsTable.js +29 -0
  193. package/dist/pages/orders/_components/PromotionsList.js +73 -0
  194. package/dist/pages/orders/_components/RealizationCard.js +98 -0
  195. package/dist/pages/orders/_components/RefundCard.js +11 -0
  196. package/dist/pages/orders/_components/RefundPaymentCard.js +13 -0
  197. package/dist/pages/orders/_components/ShippingMethod.js +112 -0
  198. package/dist/pages/orders/_components/SpecialLineItem.js +7 -0
  199. package/dist/pages/orders/_components/SurchargeCard.js +99 -0
  200. package/dist/pages/orders/_components/SurchargeTable.js +8 -0
  201. package/dist/pages/orders/_components/TaxSummary.js +11 -0
  202. package/dist/pages/orders/_components/ToRealizationForm.js +64 -0
  203. package/dist/pages/orders/_components/TopActions.js +219 -0
  204. package/dist/pages/orders/_components/index.js +25 -0
  205. package/dist/pages/orders/index.js +2 -0
  206. package/dist/pages/payment-methods/Detail.js +67 -0
  207. package/dist/pages/payment-methods/List.js +41 -0
  208. package/dist/pages/payment-methods/_components/OptionsCard.js +60 -0
  209. package/dist/pages/payment-methods/_components/PaymentMethodDetailView.js +53 -0
  210. package/dist/pages/payment-methods/index.js +2 -0
  211. package/dist/pages/product-variants/Detail.js +4 -0
  212. package/dist/pages/product-variants/List.js +76 -0
  213. package/dist/pages/product-variants/index.js +2 -0
  214. package/dist/pages/products/Detail.js +75 -0
  215. package/dist/pages/products/List.js +79 -0
  216. package/dist/pages/products/_components/AddOptionGroupDialog.js +65 -0
  217. package/dist/pages/products/_components/AssetsCard.js +35 -0
  218. package/dist/pages/products/_components/BasicFieldsCard.js +6 -0
  219. package/dist/pages/products/_components/ChannelsCard.js +6 -0
  220. package/dist/pages/products/_components/CollectionsCard.js +6 -0
  221. package/dist/pages/products/_components/Container.js +4 -0
  222. package/dist/pages/products/_components/DiscountRatingCard.js +6 -0
  223. package/dist/pages/products/_components/FacetValuesCard.js +6 -0
  224. package/dist/pages/products/_components/ImagesCard.js +6 -0
  225. package/dist/pages/products/_components/OptionGroup.js +93 -0
  226. package/dist/pages/products/_components/OptionValueCard.js +59 -0
  227. package/dist/pages/products/_components/OptionsCard.js +38 -0
  228. package/dist/pages/products/_components/OptionsTab.js +40 -0
  229. package/dist/pages/products/_components/PriceCard.js +27 -0
  230. package/dist/pages/products/_components/ProductDetailSidebar.js +30 -0
  231. package/dist/pages/products/_components/ProductDetailView.js +54 -0
  232. package/dist/pages/products/_components/SettingsCard.js +6 -0
  233. package/dist/pages/products/_components/StockCard.js +40 -0
  234. package/dist/pages/products/_components/Variant.js +149 -0
  235. package/dist/pages/products/_components/VariantsTab.js +46 -0
  236. package/dist/pages/products/index.js +2 -0
  237. package/dist/pages/promotions/Detail.js +80 -0
  238. package/dist/pages/promotions/List.js +38 -0
  239. package/dist/pages/promotions/_components/ActionsCard.js +67 -0
  240. package/dist/pages/promotions/_components/BasicFieldsCard.js +6 -0
  241. package/dist/pages/promotions/_components/ConditionsCard.js +70 -0
  242. package/dist/pages/promotions/_components/CustomerGroupsSelector.js +25 -0
  243. package/dist/pages/promotions/_components/EnabledCard.js +6 -0
  244. package/dist/pages/promotions/_components/OptionsCard.js +6 -0
  245. package/dist/pages/promotions/_components/PromotionDetailSidebar.js +15 -0
  246. package/dist/pages/promotions/_components/PromotionDetailView.js +66 -0
  247. package/dist/pages/promotions/_components/PromotionFieldRender.js +4 -0
  248. package/dist/pages/promotions/index.js +2 -0
  249. package/dist/pages/roles/Detail.js +72 -0
  250. package/dist/pages/roles/List.js +70 -0
  251. package/dist/pages/roles/_components/PermissionsCard.js +7 -0
  252. package/dist/pages/roles/_components/PermissionsTable.js +42 -0
  253. package/dist/pages/roles/_components/RoleDetailView.js +49 -0
  254. package/dist/pages/roles/index.js +2 -0
  255. package/dist/pages/sellers/Detail.js +48 -0
  256. package/dist/pages/sellers/List.js +37 -0
  257. package/dist/pages/sellers/_components/SellerDetailView.js +20 -0
  258. package/dist/pages/sellers/index.js +2 -0
  259. package/dist/pages/shipping-methods/Detail.js +105 -0
  260. package/dist/pages/shipping-methods/List.js +40 -0
  261. package/dist/pages/shipping-methods/_components/CalculatorCard.js +79 -0
  262. package/dist/pages/shipping-methods/_components/CheckerCard.js +76 -0
  263. package/dist/pages/shipping-methods/_components/Lines.js +20 -0
  264. package/dist/pages/shipping-methods/_components/ShippingMethodDetailView.js +67 -0
  265. package/dist/pages/shipping-methods/_components/TestCard.js +62 -0
  266. package/dist/pages/shipping-methods/index.js +2 -0
  267. package/dist/pages/status/Status.js +6 -0
  268. package/dist/pages/status/_components/FilterToolbar.js +29 -0
  269. package/dist/pages/status/_components/Health.js +21 -0
  270. package/dist/pages/status/_components/JobResultPopover.js +8 -0
  271. package/dist/pages/status/_components/Jobs.js +199 -0
  272. package/dist/pages/status/_components/JsonExplorer.js +44 -0
  273. package/dist/pages/status/_components/JsonPopup.js +8 -0
  274. package/dist/pages/status/index.js +1 -0
  275. package/dist/pages/stock-locations/Detail.js +77 -0
  276. package/dist/pages/stock-locations/List.js +38 -0
  277. package/dist/pages/stock-locations/_components/StockLocationDetailView.js +22 -0
  278. package/dist/pages/stock-locations/index.js +2 -0
  279. package/dist/pages/tax-categories/Detail.js +85 -0
  280. package/dist/pages/tax-categories/List.js +46 -0
  281. package/dist/pages/tax-categories/_components/TaxCategoryDetailView.js +24 -0
  282. package/dist/pages/tax-categories/index.js +2 -0
  283. package/dist/pages/tax-rates/Detail.js +62 -0
  284. package/dist/pages/tax-rates/List.js +64 -0
  285. package/dist/pages/tax-rates/_components/TaxRateDetailView.js +64 -0
  286. package/dist/pages/tax-rates/index.js +2 -0
  287. package/dist/pages/zones/Detail.js +86 -0
  288. package/dist/pages/zones/List.js +52 -0
  289. package/dist/pages/zones/_components/ZoneDetailView.js +49 -0
  290. package/dist/pages/zones/index.js +2 -0
  291. package/dist/version.js +1 -0
  292. package/package.json +122 -0
@@ -0,0 +1,85 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useCallback, useState } from 'react';
4
+ import { MultipleSelector, useLazyQuery, useOrder, useMutation, OrderDetailSelector, EmptyState, CustomCard, ORDER_STATE, useTranslation, } from '@deenruv/react-ui-devkit';
5
+ import { typedGql, scalars, $ } from '@deenruv/admin-types';
6
+ import { toast } from 'sonner';
7
+ import { Ticket, Search } from 'lucide-react';
8
+ const PromotionCodesQuery = typedGql('query', { scalars })({
9
+ promotions: [
10
+ { options: { filter: { couponCode: { contains: $('code', 'String!') } } } },
11
+ { items: { couponCode: true, name: true } },
12
+ ],
13
+ });
14
+ const ApplyCouponCodeMutation = typedGql('mutation', { scalars })({
15
+ applyCouponCodeToDraftOrder: [
16
+ { orderId: $('orderId', 'ID!'), couponCode: $('couponCode', 'String!') },
17
+ { '...on CouponCodeExpiredError': { message: true }, __typename: true, '...on Order': OrderDetailSelector },
18
+ ],
19
+ });
20
+ const RemoveCouponCodeMutation = typedGql('mutation', { scalars })({
21
+ removeCouponCodeFromDraftOrder: [
22
+ { orderId: $('orderId', 'ID!'), couponCode: $('couponCode', 'String!') },
23
+ OrderDetailSelector,
24
+ ],
25
+ });
26
+ export const CouponCodesCard = () => {
27
+ const { t } = useTranslation('orders');
28
+ const { order, setOrder } = useOrder();
29
+ const [fetchPromotionCodes] = useLazyQuery(PromotionCodesQuery);
30
+ const [applyCoupon] = useMutation(ApplyCouponCodeMutation);
31
+ const [removeCoupon] = useMutation(RemoveCouponCodeMutation);
32
+ const [currentValue, setCurrentValue] = useState(order?.couponCodes.map((c) => ({ label: c, value: c })) || []);
33
+ const [isSearching, setIsSearching] = useState(false);
34
+ const handleChange = useCallback((e) => {
35
+ if (!order)
36
+ return;
37
+ const currentState = currentValue.map((v) => v.value) || [];
38
+ if (e.length > currentState?.length) {
39
+ const newCoupon = e[e.length - 1];
40
+ toast.promise(applyCoupon({ couponCode: newCoupon.value, orderId: order.id }).then((resp) => {
41
+ if (resp.applyCouponCodeToDraftOrder.__typename === 'Order') {
42
+ setOrder(resp.applyCouponCodeToDraftOrder);
43
+ setCurrentValue((prev) => [...prev, newCoupon]);
44
+ return true;
45
+ }
46
+ else {
47
+ throw new Error('Failed to apply coupon');
48
+ }
49
+ }), {
50
+ loading: t('couponCodes.addingCoupon', 'Applying coupon code...'),
51
+ success: t('couponCodes.addToastSuccess', 'Coupon code applied successfully'),
52
+ error: (err) => err.message,
53
+ });
54
+ }
55
+ else {
56
+ const couponToRemove = currentState.find((c) => !e.map((i) => i.value).includes(c));
57
+ if (couponToRemove) {
58
+ toast.promise(removeCoupon({ couponCode: couponToRemove, orderId: order.id }).then((resp) => {
59
+ if (resp.removeCouponCodeFromDraftOrder?.id) {
60
+ setOrder(resp.removeCouponCodeFromDraftOrder);
61
+ setCurrentValue((prev) => prev.filter((i) => i.value !== couponToRemove));
62
+ return true;
63
+ }
64
+ return false;
65
+ }), {
66
+ loading: t('couponCodes.removingCoupon', 'Removing coupon code...'),
67
+ success: t('couponCodes.removeToastSuccess', 'Coupon code removed successfully'),
68
+ error: t('couponCodes.removeToastError', 'Failed to remove coupon code'),
69
+ });
70
+ }
71
+ }
72
+ }, [order, currentValue, applyCoupon, removeCoupon, setOrder, t]);
73
+ return (_jsxs(CustomCard, { notCollapsible: true, wrapperClassName: "h-full", color: "purple", description: t('couponCodes.description', 'Apply coupon codes to this order'), title: t('couponCodes.title', 'Coupon Codes'), icon: _jsx(Ticket, {}), children: [_jsxs("div", { className: "relative", children: [_jsx(MultipleSelector, { hideClearAllButton: true, placeholder: t('couponCodes.placeholder', 'Search for coupon codes...'), value: currentValue, onChange: handleChange, disabled: order?.state === ORDER_STATE.DELIVERED || order?.state === ORDER_STATE.CANCELLED, onSearch: (searchString) => {
74
+ setIsSearching(true);
75
+ return fetchPromotionCodes({ code: searchString })
76
+ .then((resp) => resp.promotions.items
77
+ .filter((i) => i.couponCode)
78
+ .map((i) => ({
79
+ value: i.couponCode,
80
+ label: i.couponCode,
81
+ description: i.name,
82
+ })))
83
+ .finally(() => setIsSearching(false));
84
+ }, delay: 500 }), _jsx("div", { className: "text-muted-foreground absolute right-3 top-2.5", children: isSearching ? (_jsx("div", { className: "size-4 animate-spin rounded-full border-2 border-current border-t-transparent" })) : (_jsx(Search, { className: "size-4" })) })] }), currentValue.length === 0 && (_jsx("div", { className: "flex h-[240px] pt-12", children: _jsx(EmptyState, { columnsLength: 2, title: t('couponCodes.noCoupons', 'No coupon codes applied'), color: "purple", icon: _jsx(Ticket, {}), small: true }) }))] }));
85
+ };
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useTranslation, EntityCustomFields, Button } from '@deenruv/react-ui-devkit';
3
+ import { useEffect, useState } from 'react';
4
+ export const CustomComponent = ({ onVariantAdd, orderLine, }) => {
5
+ const { t } = useTranslation('orders');
6
+ const [customFields, setCustomFields] = useState({});
7
+ const [isSubmitting, setIsSubmitting] = useState(false);
8
+ useEffect(() => {
9
+ console.log('KUSTOM', customFields);
10
+ }, []);
11
+ const onSubmit = async () => {
12
+ try {
13
+ setIsSubmitting(true);
14
+ await onVariantAdd(customFields);
15
+ }
16
+ finally {
17
+ setIsSubmitting(false);
18
+ }
19
+ };
20
+ return (_jsxs("div", { className: "flex h-full flex-col rounded-md border", children: [_jsx("div", { className: "h-full grow space-y-4 overflow-y-auto p-4", children: _jsx(EntityCustomFields, { entityName: "orderLine", hideButton: true, initialValues: { customFields: {} }, onChange: setCustomFields, additionalData: { product: orderLine.product, variant: orderLine } }) }), _jsx("div", { className: "bg-muted/30 border-t p-4", children: _jsx("div", { className: "flex flex-col items-start justify-end gap-4 sm:flex-row sm:items-center", children: _jsx(Button, { onClick: onSubmit, disabled: isSubmitting, className: "min-w-[120px] self-end sm:self-auto", children: isSubmitting ? (_jsxs("span", { className: "flex items-center gap-2", children: [_jsx("span", { className: "size-4 animate-spin rounded-full border-2 border-current border-r-transparent" }), t('common:processing')] })) : (t('create.add')) }) }) })] }));
21
+ };
@@ -0,0 +1,117 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { Button, Tabs, TabsList, TabsTrigger, TabsContent, Input, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, apiClient, useOrder, cn, OrderDetailSelector, Label, useGFFLP, CustomCard, EntityCustomFields, useTranslation, CustomerSearch, } from '@deenruv/react-ui-devkit';
4
+ import { useEffect, useState } from 'react';
5
+ import { toast } from 'sonner';
6
+ import { Edit, User, Check, Mail, Phone, Loader2, UserPlus, Search, AlertCircle } from 'lucide-react';
7
+ export const CustomerSelectCard = () => {
8
+ const { t } = useTranslation('orders');
9
+ const { setOrder, mode, currentOrder: order, setCustomerAndAddressesForDraftOrder } = useOrder();
10
+ const [tab, setTab] = useState('select');
11
+ const [selected, setSelected] = useState(order?.customer);
12
+ const [open, setOpen] = useState(false);
13
+ const [isSubmitting, setIsSubmitting] = useState(false);
14
+ const { state, checkIfAllFieldsAreValid, setField, clearAllForm } = useGFFLP('CreateCustomerInput', 'firstName', 'lastName', 'title', 'phoneNumber', 'emailAddress', 'customFields')({
15
+ firstName: {
16
+ initialValue: '',
17
+ validate: (v) => {
18
+ if (!v || v === '')
19
+ return [t('form.requiredError')];
20
+ },
21
+ },
22
+ lastName: {
23
+ initialValue: '',
24
+ validate: (v) => {
25
+ if (!v || v === '')
26
+ return [t('form.requiredError')];
27
+ },
28
+ },
29
+ phoneNumber: {
30
+ initialValue: '',
31
+ validate: (v) => {
32
+ if (!v || v === '')
33
+ return [t('form.requiredError')];
34
+ // if (!phoneNumberRegExp.test(v)) return [t('form.phoneError')];
35
+ },
36
+ },
37
+ emailAddress: {
38
+ initialValue: '',
39
+ validate: (v) => {
40
+ if (!v || v === '')
41
+ return [t('form.requiredError')];
42
+ },
43
+ },
44
+ customFields: {
45
+ initialValue: {},
46
+ },
47
+ });
48
+ useEffect(() => setSelected(order?.customer), [order]);
49
+ useEffect(() => {
50
+ if (tab === 'create')
51
+ clearAllForm();
52
+ }, [tab]);
53
+ const validateAndSubmitIfCorrect = async () => {
54
+ if (!order?.id)
55
+ return;
56
+ if (tab === 'create' && !checkIfAllFieldsAreValid()) {
57
+ return;
58
+ }
59
+ setIsSubmitting(true);
60
+ try {
61
+ if (tab === 'select' && selected) {
62
+ setCustomerAndAddressesForDraftOrder(selected.id).then(() => {
63
+ setOpen(false);
64
+ toast.success(t('create.selectCustomer.success', 'Customer successfully assigned to order'));
65
+ setIsSubmitting(false);
66
+ });
67
+ }
68
+ else {
69
+ const { setCustomerForDraftOrder } = await apiClient('mutation')({
70
+ setCustomerForDraftOrder: [
71
+ {
72
+ orderId: order.id,
73
+ ...(tab === 'select'
74
+ ? { customerId: selected?.id }
75
+ : {
76
+ input: {
77
+ title: state.title?.validatedValue,
78
+ firstName: state.firstName?.validatedValue || '',
79
+ lastName: state.lastName?.validatedValue || '',
80
+ emailAddress: state.emailAddress?.validatedValue || '',
81
+ phoneNumber: state.phoneNumber?.validatedValue,
82
+ },
83
+ }),
84
+ },
85
+ {
86
+ __typename: true,
87
+ '...on Order': OrderDetailSelector,
88
+ '...on EmailAddressConflictError': { errorCode: true, message: true },
89
+ },
90
+ ],
91
+ });
92
+ if (setCustomerForDraftOrder.__typename === 'Order') {
93
+ setOpen(false);
94
+ setOrder(setCustomerForDraftOrder);
95
+ toast.success(t('create.selectCustomer.success', 'Customer successfully assigned to order'));
96
+ }
97
+ else {
98
+ toast.error(t('create.selectCustomer.error', 'Failed to assign customer to order'));
99
+ }
100
+ }
101
+ }
102
+ catch (error) {
103
+ toast.error(t('create.selectCustomer.error', 'Failed to assign customer to order'));
104
+ }
105
+ finally {
106
+ setIsSubmitting(false);
107
+ }
108
+ };
109
+ if (!order)
110
+ return null;
111
+ return (_jsx(CustomCard, { notCollapsible: true, color: order?.customer ? 'indigo' : 'gray', description: t('create.selectCustomer.description', 'Choose an existing customer or create a new one for this order'), title: t('create.selectCustomer.select', 'Customer Information'), icon: _jsx(User, {}), upperRight: mode !== 'view' &&
112
+ mode !== 'update' && (_jsxs(Dialog, { open: open, onOpenChange: setOpen, children: [_jsx(DialogTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon", className: "size-8", children: _jsx(Edit, { size: 16, className: "text-indigo-500 dark:text-indigo-400" }) }) }), _jsxs(DialogContent, { className: "min-w-max", children: [_jsxs(DialogHeader, { children: [_jsxs(DialogTitle, { className: "flex items-center gap-2 text-xl", children: [_jsx(User, { className: "size-5 text-indigo-500 dark:text-indigo-400" }), t('create.selectCustomer.label', 'Select Customer')] }), _jsx(DialogDescription, { className: "text-muted-foreground mt-2", children: t('create.selectCustomer.description', 'Choose an existing customer or create a new one for this order') })] }), _jsxs(Tabs, { value: tab, onValueChange: (e) => setTab(e), children: [_jsxs(TabsList, { className: "my-4 grid w-full grid-cols-2", children: [_jsx(TabsTrigger, { className: "w-full", value: "select", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Search, { className: "size-4" }), t('create.selectCustomer.selectTab', 'Find Customer')] }) }), _jsx(TabsTrigger, { className: "w-full", value: "create", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(UserPlus, { className: "size-4" }), t('create.selectCustomer.createTab', 'Create New')] }) })] }), _jsx(TabsContent, { className: "focus-visible:ring-transparent", value: "select", children: _jsx(CustomerSearch, { selectedCustomer: selected, onSelect: (selected) => setSelected(selected) }) }), _jsx(TabsContent, { value: "create", className: "h-fit max-h-[calc(80vh-230px)] overflow-y-auto pt-2", children: _jsxs("div", { className: "space-y-4 px-1", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "title", className: "text-sm font-medium", children: t('create.selectCustomer.titleLabel', 'Title') }), _jsx(Input, { id: "title", name: "title", placeholder: t('create.selectCustomer.titlePlaceholder', 'Mr., Mrs., Dr., etc.'), value: state.title?.value ?? undefined, onChange: (e) => setField('title', e.target.value), errors: state.title?.errors })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "space-y-1", children: [_jsxs(Label, { htmlFor: "firstName", className: "text-sm font-medium", children: [t('create.selectCustomer.firstNameLabel', 'First Name'), ' ', _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(Input, { id: "firstName", name: "firstName", placeholder: t('create.selectCustomer.firstNamePlaceholder', 'Enter first name'), value: state.firstName?.value, onChange: (e) => setField('firstName', e.target.value), className: cn(state.firstName?.errors?.length && 'border-red-300'), required: true, errors: state.firstName?.errors })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs(Label, { htmlFor: "lastName", className: "text-sm font-medium", children: [t('create.selectCustomer.lastNameLabel', 'Last Name'), ' ', _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(Input, { id: "lastName", name: "lastName", placeholder: t('create.selectCustomer.lastNamePlaceholder', 'Enter last name'), value: state.lastName?.value, onChange: (e) => setField('lastName', e.target.value), className: cn(state.lastName?.errors?.length && 'border-red-300'), required: true, errors: state.lastName?.errors })] })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs(Label, { htmlFor: "email", className: "text-sm font-medium", children: [t('create.selectCustomer.emailLabel', 'Email Address'), " ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(Input, { id: "email", name: "emailAddress", type: "email", placeholder: t('create.selectCustomer.emailPlaceholder', 'Enter email address'), value: state.emailAddress?.value, onChange: (e) => setField('emailAddress', e.target.value), className: cn(state.emailAddress?.errors?.length && 'border-red-300'), required: true, errors: state.emailAddress?.errors })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs(Label, { htmlFor: "phone", className: "text-sm font-medium", children: [t('create.selectCustomer.phoneNumberLabel', 'Phone Number'), ' ', _jsx("span", { className: "text-red-500", children: "*" })] }), _jsx(Input, { id: "phone", name: "phoneNumber", placeholder: t('create.selectCustomer.phonePlaceholder', 'Enter phone number'), value: state.phoneNumber?.value ?? undefined, onChange: (e) => setField('phoneNumber', e.target.value), className: cn(state.phoneNumber?.errors?.length && 'border-red-300'), required: true, errors: state.phoneNumber?.errors })] }), _jsx(EntityCustomFields, { id: selected?.id, entityName: "customer", hideButton: true, initialValues: selected && 'customFields' in selected
113
+ ? { customFields: selected.customFields }
114
+ : { customFields: {} }, onChange: (customFields, translations) => {
115
+ setField('customFields', customFields);
116
+ }, additionalData: {} })] }) })] }), _jsxs(DialogFooter, { className: "gap-2", children: [_jsx(Button, { variant: "outline", onClick: () => setOpen(false), disabled: isSubmitting, children: t('common.cancel', 'Cancel') }), _jsx(Button, { disabled: (tab === 'select' && !selected) || isSubmitting, className: "gap-2", onClick: validateAndSubmitIfCorrect, children: isSubmitting ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "size-4 animate-spin" }), t('common.processing', 'Processing...')] })) : (_jsxs(_Fragment, { children: [_jsx(Check, { className: "size-4" }), t(tab === 'create' ? 'create.selectCustomer.create' : 'create.selectCustomer.selectButton')] })) })] })] })] })), children: _jsx("div", { className: "border-border bg-muted/50 rounded-lg border p-3", children: _jsx("div", { className: "flex items-start gap-3", children: !order?.customer ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "bg-secondary mt-0.5 flex size-8 items-center justify-center rounded-full", children: _jsx(AlertCircle, { className: "size-4 text-green-500 dark:text-green-600" }) }), _jsxs("div", { className: "flex-1", children: [_jsx("p", { className: "text-muted-foreground text-sm italic", children: t('create.selectCustomer.noCustomer', 'No customer assigned to this order') }), mode !== 'view' && (_jsxs(Button, { variant: "outline", size: "sm", className: "mt-2 gap-2", onClick: () => setOpen(true), children: [_jsx(UserPlus, { className: "size-3.5" }), t('create.selectCustomer.addCustomer', 'Add Customer')] }))] })] })) : (_jsx(_Fragment, { children: _jsx("div", { className: "flex-1", children: _jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("p", { className: "text-sm font-medium", children: [order.customer.title && `${order.customer.title} `, order.customer.firstName, " ", order.customer.lastName] }), _jsx("span", { className: "rounded-full bg-indigo-100 px-2 py-0.5 text-xs text-indigo-800 dark:bg-indigo-900/50 dark:text-indigo-300", children: t('create.selectCustomer.customer', 'Customer') })] }), _jsxs("div", { className: "flex items-center gap-2 text-sm", children: [_jsx(Mail, { className: "size-3.5 text-indigo-500 dark:text-indigo-400" }), _jsx("span", { children: order.customer.emailAddress })] }), order.customer.phoneNumber && (_jsxs("div", { className: "flex items-center gap-2 text-sm", children: [_jsx(Phone, { className: "size-3.5 text-indigo-500 dark:text-indigo-400" }), _jsx("span", { children: order.customer.phoneNumber })] }))] }) }) })) }) }) }));
117
+ };
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { AlertDialogHeader, Textarea, AlertDialogFooter, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogTitle, AlertDialogTrigger, Checkbox, Label, Button, cn, useTranslation, } from '@deenruv/react-ui-devkit';
3
+ import { Pencil } from 'lucide-react';
4
+ import { useState } from 'react';
5
+ export const EditNoteButton = ({ note, updateConfirmed }) => {
6
+ const { t } = useTranslation('orders');
7
+ const [isPrivate, setIsPrivate] = useState(!note.isPublic);
8
+ const [text, setText] = useState(note.data?.note || '');
9
+ return (_jsxs(AlertDialog, { children: [_jsx(AlertDialogTrigger, { asChild: true, children: _jsxs(Button, { variant: "ghost", className: "flex w-full justify-start gap-2", children: [_jsx(Pencil, { className: "size-4" }), " ", t('history.edit')] }) }), _jsxs(AlertDialogContent, { className: "min-w-min", children: [_jsx(AlertDialogHeader, { children: _jsx(AlertDialogTitle, { children: t('history.editNoteHeader') }) }), _jsx(Textarea, { onChange: (e) => setText(e.currentTarget.value), value: text, className: "h-[60vh] w-auto min-w-[50vh] resize-none overflow-auto rounded-md p-2" }), _jsxs("div", { className: "flex items-center gap-2 pb-4", children: [_jsx(Checkbox, { id: "isPublic", name: "isPublic", checked: isPrivate, onClick: () => setIsPrivate((p) => !p) }), _jsxs(Label, { htmlFor: "isPublic", className: "cursor-pointer", children: [t('history.isPrivate'), _jsx("span", { className: "ml-2 text-gray-500", children: t('history.isPrivateDescription') })] }), _jsx(Label, { className: cn('ml-auto', isPrivate ? 'text-green-600' : 'text-yellow-600'), children: t(isPrivate ? 'history.toAdmins' : 'history.toAdminsAndCustomer') })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: t('history.cancel') }), _jsx(AlertDialogAction, { disabled: text === '', onClick: () => updateConfirmed({ noteId: note.id, isPublic: !isPrivate, note: text }), children: t('history.edit') })] })] })] }));
10
+ };
@@ -0,0 +1,85 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { TableHeader, TableRow, TableHead, TableBody, TableCell, Button, ScrollArea, Table, Input, Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger, useServer, Badge, priceFormatter, ArgumentFieldsComponent, CustomCard, useGFFLP, useTranslation, } from '@deenruv/react-ui-devkit';
4
+ import { LineItem } from './LineItem.js';
5
+ import { useState } from 'react';
6
+ import { Package, Truck, MapPin, User, Building, Phone, Box, CheckCircle2, AlertCircle, Loader2 } from 'lucide-react';
7
+ export const FulfillmentModal = ({ order, onSubmitted, disabled }) => {
8
+ const { t } = useTranslation('orders');
9
+ const [open, setOpen] = useState(false);
10
+ const [isSubmitting, setIsSubmitting] = useState(false);
11
+ const neededFulfillmentHandlers = order?.shippingLines?.map((line) => line.shippingMethod.fulfillmentHandlerCode);
12
+ const filteredFulfillmentHandlers = useServer((p) => {
13
+ return p.fulfillmentHandlers.filter((handler) => neededFulfillmentHandlers.includes(handler?.code));
14
+ });
15
+ const { state, setField } = useGFFLP('FulfillOrderInput')({
16
+ lines: {
17
+ initialValue: order.lines.map((line) => ({
18
+ orderLineId: line.id,
19
+ quantity: line.quantity || 1,
20
+ customFields: {},
21
+ })),
22
+ },
23
+ handler: {
24
+ initialValue: {
25
+ code: filteredFulfillmentHandlers[0]?.code,
26
+ arguments: filteredFulfillmentHandlers[0]?.args.map((arg) => ({
27
+ name: arg.name,
28
+ value: JSON.stringify(arg.defaultValue),
29
+ })),
30
+ },
31
+ },
32
+ });
33
+ const handleSubmit = async (e) => {
34
+ e.preventDefault();
35
+ if (!state.lines?.value || !state.handler?.value)
36
+ return;
37
+ const lines = state.lines?.value.map((line) => ({
38
+ orderLineId: line.orderLineId,
39
+ quantity: line.quantity,
40
+ }));
41
+ setIsSubmitting(true);
42
+ try {
43
+ await onSubmitted({ lines, handler: state.handler?.value });
44
+ setOpen(false);
45
+ }
46
+ catch (error) {
47
+ console.error(error);
48
+ }
49
+ finally {
50
+ setIsSubmitting(false);
51
+ }
52
+ };
53
+ return (_jsxs(Dialog, { open: open, onOpenChange: setOpen, children: [_jsx(DialogTrigger, { asChild: true, children: _jsxs(Button, { disabled: disabled, size: "sm", className: "gap-2", children: [_jsx(Package, { className: "size-4" }), t('fulfillment.completeOrderButton', 'Fulfill Order')] }) }), _jsxs(DialogContent, { className: "flex h-[80vh] max-w-[80vw] flex-col gap-0 overflow-hidden p-0", children: [_jsxs(DialogHeader, { className: "border-b px-6 py-4", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Truck, { className: "text-primary size-5" }), _jsx(DialogTitle, { children: t('fulfillment.completeDialogTitle', 'Complete Order Fulfillment') })] }), _jsx(DialogDescription, { children: t('fulfillment.completeDialogDescription', 'Prepare items for shipping and complete the fulfillment process') })] }), _jsxs("div", { className: "flex size-full flex-col overflow-hidden md:flex-row", children: [_jsxs("div", { className: "flex size-full flex-col border-r p-6 md:w-1/2", children: [_jsxs("div", { className: "mb-4 flex items-center gap-2", children: [_jsx(Box, { className: "size-5 text-blue-500 dark:text-blue-400" }), _jsx("h3", { className: "text-lg font-medium", children: t('fulfillment.itemsToFulfill', 'Items to Fulfill') })] }), _jsx(ScrollArea, { className: "h-[calc(100%-3rem)] w-full rounded-md border", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { noHover: true, className: "bg-muted/50", children: [_jsx(TableHead, { className: "py-3", children: t('fulfillment.product', 'Product') }), _jsx(TableHead, { className: "py-3", children: t('fulfillment.sku', 'SKU') }), _jsx(TableHead, { className: "py-3", children: t('fulfillment.fulfilled', 'Quantity') })] }) }), _jsx(TableBody, { className: "w-full", children: order?.lines.length ? (order.lines.map((line) => {
54
+ const onStock = line.productVariant.stockLevels.reduce((acc, stock) => acc + stock.stockOnHand, 0);
55
+ const stateLine = state.lines?.value?.find((l) => l.orderLineId === line.id);
56
+ const isLowStock = onStock < line.quantity;
57
+ return (_jsx(LineItem, { variant: line.productVariant, children: _jsx(TableCell, { className: "py-3", children: _jsx("div", { className: "flex items-center", children: _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("div", { className: "flex items-center gap-2", children: _jsx(Input, { type: "number", className: "w-20", value: stateLine?.quantity, onChange: (e) => {
58
+ const value = state.lines?.value;
59
+ if (!value)
60
+ return;
61
+ const index = value.findIndex((v) => v.orderLineId === line.id);
62
+ if (index === -1)
63
+ return;
64
+ if (Number.parseInt(e.target.value) < 1)
65
+ return;
66
+ if (Number.parseInt(e.target.value) <= line.quantity) {
67
+ value[index].quantity = Number.parseInt(e.target.value);
68
+ setField('lines', value);
69
+ }
70
+ }, endAdornment: _jsxs("span", { className: "text-sm", children: ["/ ", line.quantity] }) }) }), _jsx("div", { className: "flex items-center gap-1", children: isLowStock ? (_jsxs("div", { className: "flex items-center gap-1 text-amber-500", children: [_jsx(AlertCircle, { className: "size-4" }), _jsx("p", { className: "text-xs font-medium", children: t('fulfillment.lowStock', 'Low stock') })] })) : (_jsxs("div", { className: "flex items-center gap-1 text-green-500", children: [_jsx(CheckCircle2, { className: "size-4" }), _jsx("p", { className: "text-xs font-medium", children: t('fulfillment.inStock', 'In stock') })] })) }), _jsxs("p", { className: "text-muted-foreground text-xs", children: ["(", t('fulfillment.onStockValue', { value: onStock }), ")"] })] }) }) }) }, line.id));
71
+ })) : (_jsx(TableRow, { noHover: true, children: _jsx(TableCell, { colSpan: 4, className: "text-muted-foreground py-6 text-center", children: _jsxs("div", { className: "flex flex-col items-center justify-center gap-2", children: [_jsx("div", { className: "rounded-full bg-blue-100 p-3 dark:bg-blue-900/30", children: _jsx(Box, { className: "size-6 text-blue-500 dark:text-blue-400" }) }), _jsx("p", { children: t('fulfillment.emptyState', 'No items to fulfill') }), _jsx("p", { className: "text-muted-foreground text-xs", children: t('fulfillment.emptyStateHint', 'Add products to the order before fulfillment') })] }) }) })) })] }) })] }), _jsx(ScrollArea, { className: "flex h-full md:w-1/2", children: _jsx("div", { className: "flex size-full flex-col p-6", children: _jsxs("form", { onSubmit: handleSubmit, className: "flex h-full flex-col gap-6", children: [_jsxs(CustomCard, { title: t('fulfillment.shippingAddress', 'Shipping Address'), color: "blue", icon: _jsx(MapPin, {}), children: [_jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2", children: [_jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(User, { className: "text-muted-foreground size-4" }), _jsx("p", { className: "text-muted-foreground text-xs font-medium", children: t('fullName', 'Full Name') })] }), _jsx("p", { className: "text-sm font-medium", children: order.shippingAddress?.fullName || '—' })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Building, { className: "text-muted-foreground size-4" }), _jsx("p", { className: "text-muted-foreground text-xs font-medium", children: t('company', 'Company') })] }), _jsx("p", { className: "text-sm font-medium", children: order.shippingAddress?.company || '—' })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(MapPin, { className: "text-muted-foreground size-4" }), _jsx("p", { className: "text-muted-foreground text-xs font-medium", children: t('street1', 'Street Address') })] }), _jsx("p", { className: "text-sm font-medium", children: order.shippingAddress?.streetLine1 || '—' })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-xs font-medium", children: t('street2', 'Street Address 2') }), _jsx("p", { className: "text-sm font-medium", children: order.shippingAddress?.streetLine2 || '—' })] })] }), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-xs font-medium", children: t('city', 'City') }), _jsx("p", { className: "text-sm font-medium", children: order.shippingAddress?.city || '—' })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-xs font-medium", children: t('postalCode', 'Postal Code') }), _jsx("p", { className: "text-sm font-medium", children: order.shippingAddress?.postalCode || '—' })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-xs font-medium", children: t('country', 'Country') }), _jsx("p", { className: "text-sm font-medium", children: order.shippingAddress?.country || '—' })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Phone, { className: "text-muted-foreground size-4" }), _jsx("p", { className: "text-muted-foreground text-xs font-medium", children: t('phoneNumber', 'Phone Number') })] }), _jsx("p", { className: "text-sm font-medium", children: order.shippingAddress?.phoneNumber || '—' })] })] })] }), _jsxs("div", { className: "mt-4 border-t pt-4", children: [_jsx("p", { className: "text-muted-foreground mb-2 text-xs font-medium", children: t('fulfillment.shippingMethod', 'Shipping Method') }), order.shippingLines.map((line) => (_jsxs("div", { className: "bg-muted/50 flex items-center justify-between rounded-md p-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Truck, { className: "size-4 text-blue-500 dark:text-blue-400" }), _jsx("span", { className: "font-medium", children: line.shippingMethod.name })] }), _jsx(Badge, { variant: "outline", className: "font-mono", children: priceFormatter(line.priceWithTax, order.currencyCode) })] }, line.id)))] })] }), _jsx(CustomCard, { color: "green", title: t('fulfillment.fulfillmentOptions', 'Fulfillment Options'), icon: _jsx(Package, {}), bottomRight: _jsx(Button, { type: "submit", className: "w-full gap-2", disabled: isSubmitting, children: isSubmitting ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "size-4 animate-spin" }), t('fulfillment.processing', 'Processing...')] })) : (_jsxs(_Fragment, { children: [_jsx(CheckCircle2, { className: "size-4" }), t('fulfillment.fulfill', 'Complete Fulfillment')] })) }), children: _jsx(ArgumentFieldsComponent, { actions: filteredFulfillmentHandlers, args: state.handler?.value.arguments?.length
72
+ ? state.handler.value.arguments
73
+ : state.handler?.initialValue?.arguments?.length
74
+ ? state.handler.initialValue.arguments
75
+ : [], setArg: (argument, data) => {
76
+ const newArgs = state.handler?.value.arguments.map((arg) => {
77
+ if (arg.name === argument.name)
78
+ return { ...arg, value: data.value };
79
+ return arg;
80
+ });
81
+ if (!state.handler?.value.code || !newArgs)
82
+ return;
83
+ setField('handler', { code: state.handler?.value.code, arguments: newArgs });
84
+ } }) })] }) }) })] })] })] }));
85
+ };
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { TableRow, TableCell, Button } from '@deenruv/react-ui-devkit';
3
+ import { Minus, Plus, Package } from 'lucide-react';
4
+ export const LineItem = ({ noBorder, noHover, children, variant, adjustLineItem }) => {
5
+ const imageUrl = variant?.featuredAsset?.preview || variant?.product?.featuredAsset?.preview;
6
+ return (_jsxs(TableRow, { noHover: noHover, noBorder: noBorder, className: "group transition-colors", children: [_jsx(TableCell, { className: "py-3", children: _jsxs("div", { className: "flex items-center gap-3", children: [imageUrl ? (_jsx("img", { alt: `${variant?.product.name} image`, className: "aspect-square size-12 rounded-md border bg-white object-cover shadow-sm", height: "48", width: "48", src: imageUrl || '/placeholder.svg' })) : (_jsx("div", { className: "bg-muted/30 flex size-12 items-center justify-center rounded-md border", children: _jsx(Package, { className: "text-muted-foreground size-6" }) })), _jsxs("div", { className: "flex flex-col", children: [_jsx("span", { className: "line-clamp-1 text-sm font-medium md:text-base", children: variant?.product.name }), variant?.name && variant.name !== variant?.product.name && (_jsx("span", { className: "text-muted-foreground line-clamp-1 text-xs", children: variant.name }))] })] }) }), _jsx(TableCell, { className: "text-muted-foreground font-mono text-sm", children: variant?.sku }), variant?.quantity ? (_jsx(TableCell, { children: adjustLineItem ? (_jsx("div", { className: "flex items-center", children: _jsxs("div", { className: "bg-background inline-flex items-center rounded-md border shadow-sm", children: [_jsx(Button, { variant: "ghost", size: "sm", type: "button", onClick: () => adjustLineItem(Math.max(1, (variant.quantity || 1) - 1)), className: "hover:bg-muted h-8 rounded-r-none border-r px-2", "aria-label": "Decrease quantity", children: _jsx(Minus, { className: "size-3.5" }) }), _jsx("span", { className: "px-3 py-1 text-sm font-medium tabular-nums", children: variant?.quantity }), _jsx(Button, { variant: "ghost", size: "sm", type: "button", onClick: () => adjustLineItem((variant.quantity || 0) + 1), className: "hover:bg-muted h-8 rounded-l-none border-l px-2", "aria-label": "Increase quantity", children: _jsx(Plus, { className: "size-3.5" }) })] }) })) : (_jsx("span", { className: "bg-primary/10 text-primary inline-flex min-w-8 items-center justify-center rounded-full px-2 py-0.5 text-xs font-medium", children: variant?.quantity })) })) : null, children] }));
7
+ };
@@ -0,0 +1,47 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React, { useEffect, useRef, useState } from 'react';
3
+ import { Button, Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue, Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, OrderStateBadge, usePluginStore, useTranslation, } from '@deenruv/react-ui-devkit';
4
+ import { toast } from 'sonner';
5
+ export const ManualOrderChangeModal = ({ currentPossibilities, wantedState, order, open, setOpen, onConfirm }) => {
6
+ const [components, setComponents] = useState([]);
7
+ const beforeSubmit = useRef();
8
+ const { getModalComponents } = usePluginStore();
9
+ const { t } = useTranslation('orders');
10
+ const [value, setValue] = useState(() => {
11
+ if (wantedState) {
12
+ const stateIndex = currentPossibilities.to.indexOf(wantedState);
13
+ return stateIndex === -1 ? currentPossibilities.to[0] : currentPossibilities.to[stateIndex];
14
+ }
15
+ else {
16
+ const stateIndex = currentPossibilities.to.indexOf(order.state);
17
+ return stateIndex === -1 ? currentPossibilities.to[0] : currentPossibilities.to[stateIndex + 1];
18
+ }
19
+ });
20
+ const submit = async () => {
21
+ try {
22
+ if (beforeSubmit.current) {
23
+ await beforeSubmit.current?.();
24
+ }
25
+ await onConfirm(value);
26
+ }
27
+ catch (e) {
28
+ toast.error(t('changeStatus.error'));
29
+ }
30
+ };
31
+ useEffect(() => {
32
+ const stored = getModalComponents('manual-order-state');
33
+ setComponents(stored.map((component, index) => {
34
+ const data = {
35
+ state: value,
36
+ setState: setValue,
37
+ order,
38
+ beforeSubmit,
39
+ };
40
+ return _jsx(React.Fragment, { children: React.createElement(component, { data }) }, index);
41
+ }));
42
+ return () => {
43
+ setComponents([]);
44
+ };
45
+ }, [value]);
46
+ return (_jsx(Dialog, { open: open, modal: open, onOpenChange: (state) => setOpen({ state }), children: _jsxs(DialogContent, { className: "min-w-fit max-w-[50vw]", children: [_jsx(DialogHeader, { children: _jsxs(DialogTitle, { className: "flex items-center gap-2", children: [t('changeStatus.header'), _jsx(OrderStateBadge, { state: order.state })] }) }), _jsx(DialogDescription, { children: t('changeStatus.description') }), _jsxs(Select, { name: "orderState", value: value, onValueChange: (e) => setValue(e), children: [_jsx(SelectTrigger, { className: "w-[180px]", children: _jsx(SelectValue, { placeholder: "Status.." }) }), _jsx(SelectContent, { children: _jsx(SelectGroup, { children: [currentPossibilities.name, ...currentPossibilities.to].map((state) => (_jsx(SelectItem, { value: state, disabled: state === order.state, children: state }, state))) }) })] }), components, _jsx(Button, { className: "ml-auto w-min", onClick: submit, children: t('changeStatus.button') })] }) }));
47
+ };
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useOrder, Button, Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, useTranslation, } from '@deenruv/react-ui-devkit';
3
+ import { useCallback, useEffect, useState } from 'react';
4
+ import { ModifyingCard } from './ModifyingCard.js';
5
+ import { ChangesRegister } from './ChangesRegister';
6
+ export const ModifyAcceptModal = () => {
7
+ const { t } = useTranslation('orders');
8
+ const [open, setOpen] = useState(false);
9
+ const { isOrderModified, getChangesRegistry } = useOrder();
10
+ const [changes, setChanges] = useState();
11
+ const getAndSetChanges = useCallback((options) => {
12
+ setChanges(undefined);
13
+ getChangesRegistry(options).then(setChanges);
14
+ }, [getChangesRegistry]);
15
+ useEffect(() => {
16
+ if (open)
17
+ getAndSetChanges();
18
+ else
19
+ setChanges(undefined);
20
+ }, [open]);
21
+ return (_jsxs(Dialog, { open: open, onOpenChange: setOpen, children: [_jsx(DialogTrigger, { asChild: true, children: _jsx(Button, { className: "w-full justify-start", disabled: !isOrderModified(), children: t('applyChanges') }) }), _jsxs(DialogContent, { className: "h-[90dvh] max-w-[90vw] grid-rows-[auto_1fr_auto]", children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { className: "text-muted-foreground", children: t('reviewChanges') }) }), _jsxs("div", { className: "grid grow grid-cols-3 gap-4", children: [_jsx("div", { className: "col-span-2 flex h-full flex-col", children: _jsx("div", { className: "h-0 grow overflow-y-auto pr-2", children: _jsx(ChangesRegister, { changes }) }) }), _jsx(ModifyingCard, { onNoteModified: (bool) => setOpen(bool), onOptionsChange: getAndSetChanges, changes })] })] })] }));
22
+ };
@@ -0,0 +1,77 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useEffect, useMemo, useState } from 'react';
4
+ import { useOrder, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Checkbox, Label, Textarea, Tooltip, TooltipContent, TooltipTrigger, Separator, useGFFLP, useTranslation, } from '@deenruv/react-ui-devkit';
5
+ import { toast } from 'sonner';
6
+ import { PriceChangedInfo } from "./PriceChangedInfo.js";
7
+ import { FileEdit, Truck, Tag, CreditCard, AlertCircle, Save, Loader2, RefreshCw } from 'lucide-react';
8
+ import { RefundCard } from "./RefundCard.js";
9
+ export const ModifyingCard = ({ onNoteModified, onOptionsChange, changes }) => {
10
+ const { t } = useTranslation('orders');
11
+ const { modifiedOrder, setModifyOrderInput, modifyOrder, modifyOrderInput } = useOrder();
12
+ const [isSubmitting, setIsSubmitting] = useState(false);
13
+ const { state, setField } = useGFFLP('ModifyOrderInput')({});
14
+ const [noteAdded, setNoteAdded] = useState(false);
15
+ const [sendRefund, setSendRefund] = useState(false);
16
+ const [refundReason, setRefundReason] = useState('');
17
+ const priceDifference = useMemo(() => {
18
+ const totalWithTaxChange = changes?.rest.find((ch) => ch.path === 'totalWithTax');
19
+ if (!totalWithTaxChange)
20
+ return 0;
21
+ return +totalWithTaxChange.added - +totalWithTaxChange.removed;
22
+ }, [changes]);
23
+ const currentPayment = modifiedOrder?.payments?.[0];
24
+ useEffect(() => {
25
+ if (priceDifference < 0)
26
+ setSendRefund(true);
27
+ }, [priceDifference]);
28
+ useEffect(() => setNoteAdded(!!state.note?.value), [state.note?.value]);
29
+ useEffect(() => {
30
+ if (modifiedOrder && state.note?.value) {
31
+ setModifyOrderInput({
32
+ ...modifyOrderInput,
33
+ note: state.note?.value,
34
+ options: state.options?.value,
35
+ refund: sendRefund && currentPayment?.transactionId
36
+ ? {
37
+ paymentId: currentPayment.transactionId,
38
+ amount: priceDifference,
39
+ reason: refundReason,
40
+ }
41
+ : undefined,
42
+ });
43
+ }
44
+ }, [state, modifiedOrder]);
45
+ const acceptModifiedChanges = async () => {
46
+ if (!noteAdded)
47
+ return;
48
+ setIsSubmitting(true);
49
+ try {
50
+ await modifyOrder();
51
+ toast.success(t('modifySuccess', 'Order modifications applied successfully'));
52
+ onNoteModified && onNoteModified(false);
53
+ }
54
+ catch (e) {
55
+ const message = e instanceof Error ? e.message : t('modifyError', 'Failed to apply order modifications');
56
+ toast.error(message);
57
+ }
58
+ finally {
59
+ setIsSubmitting(false);
60
+ }
61
+ };
62
+ return (_jsx("form", { className: "h-full max-h-[calc(100vh-200px)]", children: _jsxs(Card, { className: "flex h-full flex-col border-l-4 border-l-blue-500 shadow-sm transition-shadow duration-200 hover:shadow dark:border-l-blue-400", children: [_jsx(CardHeader, { className: "pb-4", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(FileEdit, { className: "size-5 text-blue-500 dark:text-blue-400" }), _jsxs("div", { children: [_jsx(CardTitle, { children: t('orderModification', 'Order Modification') }), _jsx(CardDescription, { className: "mt-1", children: t('orderModificationDescription', 'Modify order details and apply changes') })] })] }) }), _jsxs(CardContent, { className: "flex-1 space-y-6 overflow-y-auto", children: [_jsxs("div", { className: "space-y-3", children: [_jsxs(Label, { htmlFor: "note", className: "text-sm font-medium", children: [t('note', 'Modification Note'), " ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsxs("div", { className: "relative", children: [_jsx(Textarea, { id: "note", placeholder: t('notePlaceholder', 'Enter a note explaining the reason for these modifications...'), value: state.note?.value ?? '', onChange: (e) => setField('note', e.target.value), className: "min-h-[60px] resize-y" }), !state.note?.value && (_jsx("div", { className: "absolute right-3 top-3 text-amber-500", children: _jsx(AlertCircle, { className: "size-4" }) }))] }), _jsx("p", { className: "text-muted-foreground text-xs", children: t('noteRequired', 'A note is required to explain why these changes are being made') })] }), _jsx(Separator, {}), _jsxs("div", { className: "space-y-3", children: [_jsx("h3", { className: "text-muted-foreground text-sm font-medium", children: t('modificationOptions', 'Modification Options') }), _jsxs("div", { className: "flex flex-col space-y-4", children: [_jsxs("div", { className: "border-border bg-muted/20 space-y-4 rounded-md border p-4", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex size-8 items-center justify-center rounded-full bg-blue-100 dark:bg-blue-900/30", children: _jsx(RefreshCw, { className: "size-4 text-blue-500 dark:text-blue-400" }) }), _jsx("h4", { className: "font-medium", children: t('processingOptions', 'Processing Options') })] }), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "flex items-center space-x-2", children: [_jsx(Checkbox, { id: "recalculateShipping", checked: state.options?.value?.recalculateShipping ?? false, onCheckedChange: (e) => {
63
+ const optionsObj = {
64
+ freezePromotions: state?.options?.value?.freezePromotions || false,
65
+ recalculateShipping: !!e,
66
+ };
67
+ setField('options', optionsObj);
68
+ onOptionsChange(optionsObj);
69
+ } }), _jsxs(Label, { htmlFor: "recalculateShipping", className: "flex cursor-pointer items-center gap-2 text-sm font-medium", children: [_jsx(Truck, { className: "size-4 text-blue-500 dark:text-blue-400" }), t('recalculateShipping', 'Recalculate Shipping')] })] }), _jsxs("div", { className: "flex items-center space-x-2", children: [_jsx(Checkbox, { id: "freezePromotions", checked: state.options?.value?.freezePromotions ?? false, onCheckedChange: (e) => {
70
+ const optionsObj = {
71
+ freezePromotions: !!e,
72
+ recalculateShipping: state?.options?.value?.recalculateShipping || false,
73
+ };
74
+ setField('options', optionsObj);
75
+ onOptionsChange(optionsObj);
76
+ } }), _jsxs(Label, { htmlFor: "freezePromotions", className: "flex cursor-pointer items-center gap-2 text-sm font-medium", children: [_jsx(Tag, { className: "size-4 text-blue-500 dark:text-blue-400" }), t('freezePromotions', 'Freeze Promotions')] })] }), !!priceDifference && (_jsxs("div", { className: "flex items-center space-x-2", children: [_jsx(Checkbox, { id: "refund", checked: sendRefund, onCheckedChange: (e) => setSendRefund(e) }), _jsxs(Label, { htmlFor: "refund", className: "flex cursor-pointer items-center gap-2 text-sm font-medium", children: [_jsx(CreditCard, { className: "size-4 text-blue-500 dark:text-blue-400" }), t('refund', 'Process Refund')] })] }))] })] }), sendRefund && (_jsx(RefundCard, { priceDifference: priceDifference, refundReason: refundReason, setRefundReason: setRefundReason }))] })] }), _jsx("div", { className: "flex justify-end", children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { tabIndex: 0, children: _jsx(Button, { onClick: acceptModifiedChanges, disabled: !noteAdded || isSubmitting, type: "button", className: "gap-2", children: isSubmitting ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "size-4 animate-spin" }), t('processing', 'Processing...')] })) : (_jsxs(_Fragment, { children: [_jsx(Save, { className: "size-4" }), t('applyChanges', 'Apply Changes')] })) }) }) }), !noteAdded && (_jsx(TooltipContent, { className: "border border-amber-200 bg-amber-50 text-amber-800 dark:border-amber-800 dark:bg-amber-900/50 dark:text-amber-200", children: _jsxs("div", { className: "flex items-center gap-2 px-1", children: [_jsx(AlertCircle, { className: "size-4" }), t('disabledBtnTooltip', 'A note is required to apply changes')] }) }))] }) })] }), _jsx(PriceChangedInfo, { changes })] }) }));
77
+ };
@@ -0,0 +1,59 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useTranslation, useOrder, apiClient, CustomCard } from '@deenruv/react-ui-devkit';
3
+ import { DeletionResult } from '@deenruv/admin-types';
4
+ import { toast } from 'sonner';
5
+ import { History } from "../../../components";
6
+ import { ClipboardList, AlertCircle } from 'lucide-react';
7
+ export const OrderHistory = () => {
8
+ const { order, orderHistory: { data, error, loading }, fetchOrderHistory, } = useOrder();
9
+ const { t } = useTranslation('orders');
10
+ const addMessageToOrder = async (input) => {
11
+ if (!order)
12
+ return;
13
+ try {
14
+ const { addNoteToOrder } = await apiClient('mutation')({
15
+ addNoteToOrder: [{ input: input }, { id: true }],
16
+ });
17
+ if (addNoteToOrder?.id) {
18
+ await fetchOrderHistory();
19
+ toast.success(t('history.addSuccess', 'Note added successfully'));
20
+ }
21
+ else {
22
+ toast.error(t('history.addError'), { position: 'top-center' });
23
+ }
24
+ }
25
+ catch (error) {
26
+ toast.error(t('history.addError'), { position: 'top-center' });
27
+ }
28
+ };
29
+ const deleteMessageFromOrder = async (id) => {
30
+ try {
31
+ const { deleteOrderNote } = await apiClient('mutation')({
32
+ deleteOrderNote: [{ id }, { message: true, result: true }],
33
+ });
34
+ if (deleteOrderNote.result === DeletionResult.DELETED) {
35
+ await fetchOrderHistory();
36
+ toast.success(t('history.deleteSuccess', 'Note deleted successfully'));
37
+ }
38
+ else {
39
+ toast.error(t('history.deleteError', { value: deleteOrderNote.message }), { position: 'top-center' });
40
+ }
41
+ }
42
+ catch (error) {
43
+ toast.error(t('history.deleteError', { value: error instanceof Error ? error.message : 'Unknown error' }), {
44
+ position: 'top-center',
45
+ });
46
+ }
47
+ };
48
+ const editMessageInOrder = async (input) => {
49
+ try {
50
+ await apiClient('mutation')({ updateOrderNote: [{ input }, { id: true }] });
51
+ await fetchOrderHistory();
52
+ toast.success(t('history.editSuccess', 'Note updated successfully'));
53
+ }
54
+ catch (error) {
55
+ toast.error(t('history.editError'), { position: 'top-center' });
56
+ }
57
+ };
58
+ return (_jsxs(CustomCard, { color: "amber", description: t('history.description', 'Timeline of order events and notes'), title: t('history.title', 'Order History'), icon: _jsx(ClipboardList, {}), collapsed: true, children: [loading && (_jsxs("div", { className: "flex flex-col items-center justify-center py-16 text-center", children: [_jsx("div", { className: "size-8 animate-spin rounded-full border-4 border-amber-200 border-t-amber-500" }), _jsx("p", { className: "text-muted-foreground mt-4 text-sm", children: t('history.loading', 'Loading order history...') })] })), error && (_jsxs("div", { className: "flex flex-col items-center justify-center gap-3 py-16 text-center", children: [_jsx("div", { className: "rounded-full bg-red-100 p-3 dark:bg-red-900/30", children: _jsx(AlertCircle, { className: "size-6 text-red-500 dark:text-red-400" }) }), _jsxs("div", { children: [_jsx("p", { className: "font-medium text-red-600", children: t('toasts.orderHistoryLoadingError', { value: order?.id }) }), _jsx("p", { className: "text-muted-foreground mt-2 text-sm", children: t('history.tryAgain', 'Please try refreshing the page') })] })] })), !loading && !error && (_jsx(History, { data: data, onNoteAdd: addMessageToOrder, onNoteDelete: deleteMessageFromOrder, onNoteEdit: editMessageInOrder }))] }));
59
+ };