sme-pos-package 1.0.7 → 1.0.9

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 (318) hide show
  1. package/dist/index.d.mts +37 -2
  2. package/dist/index.mjs +17 -104
  3. package/dist/index.mjs.map +1 -1
  4. package/dist/tailwind.preset.d.mts +27 -0
  5. package/dist/tailwind.preset.mjs +2 -0
  6. package/dist/tailwind.preset.mjs.map +1 -0
  7. package/package.json +18 -30
  8. package/public/assets/images/bank-logos.png +0 -0
  9. package/public/assets/images/banner1.png +0 -0
  10. package/public/assets/images/banner2.png +0 -0
  11. package/public/assets/images/banner3.png +0 -0
  12. package/public/assets/images/banner4.png +0 -0
  13. package/public/assets/images/cashier.svg +9 -0
  14. package/public/assets/images/empty-cart.png +0 -0
  15. package/public/assets/images/empty-table-state.png +0 -0
  16. package/public/assets/images/layout-display/left-layout.png +0 -0
  17. package/public/assets/images/layout-display/right-layout.png +0 -0
  18. package/public/assets/images/modal-illustration.png +0 -0
  19. package/public/assets/images/order-empty-state.png +0 -0
  20. package/public/assets/images/order.png +0 -0
  21. package/public/assets/images/payment-success-label.png +0 -0
  22. package/public/assets/images/table-empty.png +0 -0
  23. package/public/assets/images/take-away.png +0 -0
  24. package/public/assets/lottie/loading.json +1 -0
  25. package/public/assets/lottie/soft_pos.json +1 -0
  26. package/public/assets/lottie/success.json +1 -0
  27. package/public/config.json +27 -0
  28. package/public/env.json +17 -0
  29. package/src/animations/success.json +9730 -0
  30. package/src/assets/icons/breadcrumbs-icon.tsx +85 -0
  31. package/src/assets/icons/cart-icon.tsx +14 -0
  32. package/src/assets/icons/common.tsx +270 -0
  33. package/src/assets/icons/customer-view-icon.tsx +20 -0
  34. package/src/assets/icons/dining-table.tsx +34 -0
  35. package/src/assets/icons/edit-line-icon.tsx +18 -0
  36. package/src/assets/icons/emenu-icon.tsx +39 -0
  37. package/src/assets/icons/file-close-line-icon.tsx +18 -0
  38. package/src/assets/icons/helper-icon.tsx +84 -0
  39. package/src/assets/icons/home-gear-line-icon.tsx +18 -0
  40. package/src/assets/icons/kanban-icon.tsx +16 -0
  41. package/src/assets/icons/loading-icon.tsx +45 -0
  42. package/src/assets/icons/logout-box-line-icon.tsx +18 -0
  43. package/src/assets/icons/order-icon.tsx +92 -0
  44. package/src/assets/icons/payment-icon.tsx +429 -0
  45. package/src/assets/icons/pincode.tsx +196 -0
  46. package/src/assets/icons/pos-connect-icon.tsx +67 -0
  47. package/src/assets/icons/pos-device-icon.tsx +52 -0
  48. package/src/assets/icons/pos-icon.tsx +75 -0
  49. package/src/assets/icons/printer-line-icon.tsx +18 -0
  50. package/src/assets/icons/star-icon.tsx +174 -0
  51. package/src/assets/icons/table-icon.tsx +77 -0
  52. package/src/assets/icons/user-add-line-icon.tsx +33 -0
  53. package/src/assets/icons/user-icon.tsx +65 -0
  54. package/src/components/common/button-action.tsx +46 -0
  55. package/src/components/common/button-icon.tsx +23 -0
  56. package/src/components/common/dropdown/index.tsx +79 -0
  57. package/src/components/common/empty-state.tsx +60 -0
  58. package/src/components/common/header/index.tsx +89 -0
  59. package/src/components/common/header/tabs.tsx +119 -0
  60. package/src/components/common/image.tsx +20 -0
  61. package/src/components/common/input/index.tsx +55 -0
  62. package/src/components/common/input/radio-group.tsx +75 -0
  63. package/src/components/common/input/text-area.tsx +28 -0
  64. package/src/components/common/modal/delete-confirm-modal-container.tsx +65 -0
  65. package/src/components/common/modal/index.ts +2 -0
  66. package/src/components/common/modal/modal-direction.tsx +125 -0
  67. package/src/components/common/modal/modal-header.tsx +37 -0
  68. package/src/components/common/modal/modal-wrapper.tsx +56 -0
  69. package/src/components/common/modal/modal-zoom.tsx +61 -0
  70. package/src/components/common/pagination.tsx +95 -0
  71. package/src/components/common/refresh-button.tsx +28 -0
  72. package/src/components/common/search-bar.tsx +27 -0
  73. package/src/components/common/search.tsx +59 -0
  74. package/src/components/common/skeleton.tsx +7 -0
  75. package/src/components/common/tabs-layout.tsx +98 -0
  76. package/src/components/common/use-check-session.tsx +19 -0
  77. package/src/components/customer-management/add-customer/add-customer-drawer.tsx +286 -0
  78. package/src/components/customer-management/add-customer/address-select.tsx +51 -0
  79. package/src/components/customer-management/choose-customer-drawer.tsx +177 -0
  80. package/src/components/customer-management/customer-info-drawer.tsx +166 -0
  81. package/src/components/customer-management/customer-no-data.tsx +18 -0
  82. package/src/components/emenu/emenu-qr-code.tsx +59 -0
  83. package/src/components/emenu/menu-link.tsx +67 -0
  84. package/src/components/index.ts +8 -0
  85. package/src/components/kanban-template/kitchen-template.tsx +60 -0
  86. package/src/components/kanban-template/pos-order-template.tsx +77 -0
  87. package/src/components/kanban-template/pos-template.tsx +170 -0
  88. package/src/components/kitchen-management/change-status-confirm-modal.tsx +61 -0
  89. package/src/components/kitchen-management/index.ts +1 -0
  90. package/src/components/kitchen-management/kitchen-order/index.tsx +153 -0
  91. package/src/components/kitchen-management/kitchen-order/line.tsx +78 -0
  92. package/src/components/kitchen-management/kitchen-order/state.tsx +52 -0
  93. package/src/components/kitchen-management/kitchen-status.tsx +69 -0
  94. package/src/components/kitchen-management/orders-kitchen-management.tsx +113 -0
  95. package/src/components/order-management/index.tsx +128 -0
  96. package/src/components/order-management/order-actions.tsx +46 -0
  97. package/src/components/order-management/order-detail/header.tsx +37 -0
  98. package/src/components/order-management/order-detail/index.ts +3 -0
  99. package/src/components/order-management/order-detail/information.tsx +96 -0
  100. package/src/components/order-management/order-detail/order-detail.tsx +84 -0
  101. package/src/components/order-management/order-detail/order-line.tsx +56 -0
  102. package/src/components/order-management/order-detail/summary.tsx +221 -0
  103. package/src/components/order-management/order-header.tsx +113 -0
  104. package/src/components/order-management/order-pagination.tsx +49 -0
  105. package/src/components/order-management/order-status.tsx +58 -0
  106. package/src/components/order-management/order-table.tsx +179 -0
  107. package/src/components/order-management/order-tabs.tsx +48 -0
  108. package/src/components/pos-management/add-product-from-barcode/index.tsx +97 -0
  109. package/src/components/pos-management/cart-content/action-line.tsx +81 -0
  110. package/src/components/pos-management/cart-content/cancel-order-line-modal.tsx +41 -0
  111. package/src/components/pos-management/cart-content/cart-item.tsx +173 -0
  112. package/src/components/pos-management/cart-content/cart-items.tsx +130 -0
  113. package/src/components/pos-management/cart-content/draft-orders/draft-order-line.tsx +67 -0
  114. package/src/components/pos-management/cart-content/draft-orders/index.tsx +40 -0
  115. package/src/components/pos-management/cart-content/edit-cart-modal.tsx +11 -0
  116. package/src/components/pos-management/cart-content/index.tsx +260 -0
  117. package/src/components/pos-management/cart-content/no-select-order.tsx +26 -0
  118. package/src/components/pos-management/cart-content/order-info/customer-info.tsx +53 -0
  119. package/src/components/pos-management/cart-content/order-info/index.tsx +109 -0
  120. package/src/components/pos-management/cart-content/order-total.tsx +36 -0
  121. package/src/components/pos-management/cart-content/orders-line.tsx +72 -0
  122. package/src/components/pos-management/menu-content/category-tab.tsx +38 -0
  123. package/src/components/pos-management/menu-content/create-order-modal.tsx +65 -0
  124. package/src/components/pos-management/menu-content/product-content.tsx +93 -0
  125. package/src/components/pos-management/menu-content/product-detail/info.tsx +28 -0
  126. package/src/components/pos-management/menu-content/product-detail/modal.tsx +148 -0
  127. package/src/components/pos-management/menu-content/product-detail/option.tsx +87 -0
  128. package/src/components/pos-management/menu-content/product-detail/quantity-control.tsx +155 -0
  129. package/src/components/pos-management/menu-content/product-detail/sale-keypad.tsx +100 -0
  130. package/src/components/pos-management/menu-content/product-item.tsx +65 -0
  131. package/src/components/pos-management/order-helper/cancel-order-confirm.tsx +43 -0
  132. package/src/components/pos-management/order-helper/history-call.tsx +105 -0
  133. package/src/components/pos-management/order-helper/order-helper-modal.tsx +116 -0
  134. package/src/components/pos-management/payment-content/bill/actions.tsx +46 -0
  135. package/src/components/pos-management/payment-content/bill/content.tsx +207 -0
  136. package/src/components/pos-management/payment-content/bill/index.tsx +18 -0
  137. package/src/components/pos-management/payment-content/card-payment/index.tsx +124 -0
  138. package/src/components/pos-management/payment-content/card-payment/pos-payment/pos-connect.tsx +183 -0
  139. package/src/components/pos-management/payment-content/card-payment/pos-payment/qr-connect.tsx +185 -0
  140. package/src/components/pos-management/payment-content/card-payment/waiting-for-payment-pos-modal.tsx +37 -0
  141. package/src/components/pos-management/payment-content/cash-payment/index.tsx +216 -0
  142. package/src/components/pos-management/payment-content/index.tsx +70 -0
  143. package/src/components/pos-management/payment-content/payment-info.tsx +67 -0
  144. package/src/components/pos-management/payment-content/payment-layout.tsx +16 -0
  145. package/src/components/pos-management/payment-content/payment-method-cards.tsx +99 -0
  146. package/src/components/pos-management/payment-content/qr-payment/index.tsx +118 -0
  147. package/src/components/pos-management/payment-content/qr-payment/qr_code.js +29 -0
  148. package/src/components/pos-management/payment-content/qr-payment/vietqr.js +436 -0
  149. package/src/components/pos-management/payment-content/session-close-modal.tsx +35 -0
  150. package/src/components/pos-management/payment-content/soft-pos-payment/index.tsx +48 -0
  151. package/src/components/pos-management/pos-helpers/back-confirm.tsx +45 -0
  152. package/src/components/pos-management/pos-helpers/index.tsx +135 -0
  153. package/src/components/pos-management/pos-helpers/layout-display-modal.tsx +99 -0
  154. package/src/components/pos-management/search.tsx +48 -0
  155. package/src/components/pos-management/table-content/filtered-tables.tsx +59 -0
  156. package/src/components/pos-management/table-content/floor-tabs.tsx +65 -0
  157. package/src/components/pos-management/table-content/index.tsx +76 -0
  158. package/src/components/pos-management/table-content/table-item.tsx +127 -0
  159. package/src/components/pos-management/table-content/tables.tsx +96 -0
  160. package/src/components/restaurant-management/add-floor-modal.tsx +133 -0
  161. package/src/components/restaurant-management/add-table-modal.tsx +198 -0
  162. package/src/components/restaurant-management/delete-floor-confirm-modal.tsx +42 -0
  163. package/src/components/restaurant-management/delete-table-confirm-modal.tsx +51 -0
  164. package/src/components/restaurant-management/header.tsx +22 -0
  165. package/src/components/restaurant-management/index.tsx +54 -0
  166. package/src/components/restaurant-management/left-side.tsx +51 -0
  167. package/src/components/restaurant-management/right-side.tsx +179 -0
  168. package/src/components/restaurant-management/table-empty.tsx +43 -0
  169. package/src/components/session-management/close-session-modal/actions.tsx +45 -0
  170. package/src/components/session-management/close-session-modal/close-session-confirm.tsx +157 -0
  171. package/src/components/session-management/close-session-modal/close-session-ticket.tsx +218 -0
  172. package/src/components/session-management/close-session-modal/container.tsx +25 -0
  173. package/src/components/session-management/close-session-modal/draft-orders-confirm.tsx +53 -0
  174. package/src/components/session-management/close-session-modal/draft-orders-summary.tsx +82 -0
  175. package/src/components/session-management/close-session-modal/draft-orders.tsx +34 -0
  176. package/src/components/session-management/close-session-modal/index.tsx +35 -0
  177. package/src/components/session-management/close-session-modal/order/index.ts +1 -0
  178. package/src/components/session-management/close-session-modal/order/order-line.tsx +64 -0
  179. package/src/components/session-management/close-session-modal/order/orders-in-draft.tsx +31 -0
  180. package/src/components/session-management/close-session-modal/session-summary.tsx +165 -0
  181. package/src/components/session-management/index.ts +1 -0
  182. package/src/components/session-management/open-shift/index.tsx +172 -0
  183. package/src/components/table-management/index.tsx +0 -0
  184. package/src/constants/api/index.ts +1 -0
  185. package/src/constants/headers.constant.tsx +24 -0
  186. package/src/constants/index.ts +1 -0
  187. package/src/constants/language.store.ts +21 -0
  188. package/src/constants/methods.constant.ts +10 -0
  189. package/src/constants/order-state.ts +8 -0
  190. package/src/constants/payment-color.constant.ts +26 -0
  191. package/src/constants/query.constant.ts +14 -0
  192. package/src/constants/routes.constants.ts +23 -0
  193. package/src/constants/template-name.constant.ts +9 -0
  194. package/src/hooks/bill/use-get-bill-information.ts +49 -0
  195. package/src/hooks/bill/use-print-bill.tsx +0 -0
  196. package/src/hooks/common/load-env-config.ts +98 -0
  197. package/src/hooks/common/use-back.ts +13 -0
  198. package/src/hooks/common/use-broadcast.ts +22 -0
  199. package/src/hooks/common/use-click-outside.ts +58 -0
  200. package/src/hooks/common/use-get-base64-photo.ts +71 -0
  201. package/src/hooks/common/use-get-query.ts +25 -0
  202. package/src/hooks/common/use-pos.ts +21 -0
  203. package/src/hooks/common/use-query-params.ts +89 -0
  204. package/src/hooks/common/use-speech.ts +36 -0
  205. package/src/hooks/customer/use-customer-provider.ts +247 -0
  206. package/src/hooks/floor/use-floor-provider.ts +172 -0
  207. package/src/hooks/kitchen/use-kitchen-provider.ts +80 -0
  208. package/src/hooks/order/use-get-point-reward.ts +50 -0
  209. package/src/hooks/order/use-loop-fetch-order.ts +30 -0
  210. package/src/hooks/order/use-order-items.ts +61 -0
  211. package/src/hooks/order/use-orders.ts +76 -0
  212. package/src/hooks/payment/use-payment-provider.ts +221 -0
  213. package/src/hooks/product/use-product-provider.ts +87 -0
  214. package/src/hooks/session/use-check-session.tsx +19 -0
  215. package/src/hooks/session/use-session-provider.ts +79 -0
  216. package/src/hooks/table/use-pos-table-provider.ts +193 -0
  217. package/src/index.css +5 -0
  218. package/src/index.ts +10 -0
  219. package/src/layouts/common.tsx +15 -0
  220. package/src/layouts/index.ts +4 -0
  221. package/src/layouts/pos-layout.tsx +33 -0
  222. package/src/layouts/pos-order-layout.tsx +43 -0
  223. package/src/layouts/sale-layout.tsx +25 -0
  224. package/src/locales/en.json +394 -0
  225. package/src/locales/vi.json +400 -0
  226. package/src/pages/index.ts +4 -0
  227. package/src/pages/login/index.tsx +128 -0
  228. package/src/pages/pincode/index.tsx +198 -0
  229. package/src/pages/pos/kitchen-management/layout.tsx +18 -0
  230. package/src/pages/pos/management-floor/index.tsx +7 -0
  231. package/src/pages/pos/management-order/index.tsx +7 -0
  232. package/src/pages/pos/management-order/order-detail/index.tsx +7 -0
  233. package/src/pages/pos/management-table/index.tsx +0 -0
  234. package/src/pages/pos/payment-success/index.tsx +75 -0
  235. package/src/provider/app-provider.tsx +56 -0
  236. package/src/provider/fallback/custom-error.tsx +26 -0
  237. package/src/provider/main-provider.tsx +41 -0
  238. package/src/provider/meta-provider.tsx +72 -0
  239. package/src/provider/modal-provider.tsx +48 -0
  240. package/src/provider/notification-provider.tsx +64 -0
  241. package/src/provider/pos-provider/close-session-provider/index.tsx +207 -0
  242. package/src/provider/pos-provider/customer-provider/index.tsx +30 -0
  243. package/src/provider/pos-provider/floor-provider/index.tsx +39 -0
  244. package/src/provider/pos-provider/index.ts +6 -0
  245. package/src/provider/pos-provider/kitchen-provider/index.tsx +30 -0
  246. package/src/provider/pos-provider/order-detail-provider/index.tsx +233 -0
  247. package/src/provider/pos-provider/order-provider/index.tsx +803 -0
  248. package/src/provider/pos-provider/payment-provider/index.tsx +30 -0
  249. package/src/provider/pos-provider/product-provider/index.tsx +30 -0
  250. package/src/provider/pos-provider/sale-provider/index.tsx +168 -0
  251. package/src/provider/pos-provider/session-provider/index.tsx +30 -0
  252. package/src/provider/pos-provider/socket-provider/index.tsx +118 -0
  253. package/src/provider/pos-provider/table-provider/index.tsx +30 -0
  254. package/src/provider/public-provider.tsx +104 -0
  255. package/src/provider/use-session-provider.ts +79 -0
  256. package/src/router/app-router.tsx +38 -0
  257. package/src/router/index.tsx +26 -0
  258. package/src/router/pos-route.tsx +75 -0
  259. package/src/router/protected-route.tsx +16 -0
  260. package/src/router/public-route.tsx +11 -0
  261. package/src/store/header/index.ts +21 -0
  262. package/src/store/session/index.ts +25 -0
  263. package/src/store/states/cart.state.ts +135 -0
  264. package/src/store/states/close-session.state.ts +20 -0
  265. package/src/store/states/customer.state.ts +19 -0
  266. package/src/store/states/payment.state.ts +14 -0
  267. package/src/styles/base.css +212 -0
  268. package/src/styles/common.css +65 -0
  269. package/src/styles/lib/tailwind.css +0 -0
  270. package/src/styles/lib/tailwind.theme.css +34 -0
  271. package/src/styles/loading.css +72 -0
  272. package/src/styles/main.css +5 -0
  273. package/src/styles/refreshing-content.css +55 -0
  274. package/src/styles/text.css +44 -0
  275. package/src/types/account.ts +61 -0
  276. package/src/types/branch.ts +6 -0
  277. package/src/types/category.ts +13 -0
  278. package/src/types/common.ts +4 -0
  279. package/src/types/customer.ts +52 -0
  280. package/src/types/dashboard.ts +18 -0
  281. package/src/types/edc.ts +37 -0
  282. package/src/types/export-e-invoice.ts +17 -0
  283. package/src/types/filter.d.ts +12 -0
  284. package/src/types/floor/floor.ts +16 -0
  285. package/src/types/floor.d.ts +36 -0
  286. package/src/types/index.ts +127 -0
  287. package/src/types/invoice.ts +32 -0
  288. package/src/types/modal.ts +15 -0
  289. package/src/types/notification.ts +12 -0
  290. package/src/types/order.ts +182 -0
  291. package/src/types/payment.ts +44 -0
  292. package/src/types/product/product.ts +47 -0
  293. package/src/types/product.ts +137 -0
  294. package/src/types/provider-info.d.ts +14 -0
  295. package/src/types/qr.d.ts +25 -0
  296. package/src/types/report.d.ts +43 -0
  297. package/src/types/sale.d.ts +68 -0
  298. package/src/types/search.d.ts +7 -0
  299. package/src/types/session.d.ts +30 -0
  300. package/src/types/shop-qr.d.ts +89 -0
  301. package/src/types/staff.d.ts +35 -0
  302. package/src/types/store.d.ts +25 -0
  303. package/src/types/table.d.ts +57 -0
  304. package/src/utils/close-session-ticket.tsx +129 -0
  305. package/src/utils/functions.ts +299 -0
  306. package/src/utils/i18n.ts +25 -0
  307. package/src/utils/pos/bill.ts +156 -0
  308. package/src/utils/pos/convert-order.ts +58 -0
  309. package/src/utils/pos/helpers.ts +48 -0
  310. package/src/utils/pos/session.ts +44 -0
  311. package/src/utils/storages/index.ts +1 -0
  312. package/src/utils/storages/local-storage.ts +72 -0
  313. package/tailwind.preset.ts +25 -0
  314. package/tsconfig.json +30 -0
  315. package/tsup.config.ts +30 -0
  316. package/dist/index.d.ts +0 -58
  317. package/dist/index.js +0 -145
  318. package/dist/index.js.map +0 -1
@@ -0,0 +1,185 @@
1
+ import ModalZoom from "@components/common/modal/modal-zoom";
2
+ import { usePosAppProvider } from "@provider/app-provider";
3
+ import { useSocketData } from "@provider/pos-provider/socket-provider";
4
+ import { randomNumber } from "@utils/functions";
5
+ import { t } from "i18next";
6
+ import { QRCodeSVG } from "qrcode.react";
7
+ import { useEffect, useMemo } from "react";
8
+ const QrConnect = ({
9
+ posId,
10
+ name,
11
+ isOpen,
12
+ onClose,
13
+ setMqttConnect,
14
+ }: {
15
+ posId: number;
16
+ name: string;
17
+ isOpen: boolean;
18
+ onClose: () => void;
19
+ setMqttConnect?: (val: string) => void;
20
+ }) => {
21
+ const { user } = usePosAppProvider();
22
+ const dataUser = user?.userProfile?.data;
23
+ const { clientMtqq } = useSocketData();
24
+ const mqttConnect = useMemo(() => {
25
+ if (!dataUser?.company.cif) {
26
+ return undefined;
27
+ }
28
+ if (localStorage.getItem(`mttqQrConnect${posId}`)) {
29
+ return localStorage.getItem(`mttqQrConnect${posId}`);
30
+ }
31
+
32
+ const serialNumber = randomNumber();
33
+ localStorage.setItem(`serialNumber${posId}`, serialNumber);
34
+ const res: MqttConnectType = {
35
+ cif: dataUser?.company.cif,
36
+ platform: "web",
37
+ serialNumber: serialNumber,
38
+ posId: `${name}(${posId.toString()})`,
39
+ };
40
+ localStorage.setItem(`mttqQrConnect${posId}`, JSON.stringify(res));
41
+ return JSON.stringify(res);
42
+ }, [dataUser]);
43
+
44
+ useEffect(() => {
45
+ mqttConnect && setMqttConnect && setMqttConnect(mqttConnect);
46
+ }, [mqttConnect]);
47
+
48
+ // useEffect(() => {
49
+ // async function getSerialDevice() {
50
+ // await CapacitorPresentation.getDeviceInfo().then((info) => {
51
+ // console.log("Log ~ getSerialDevice ~ info:", info);
52
+ // });
53
+ // }
54
+ // getSerialDevice();
55
+ // }, [mqttConnect]);
56
+
57
+ useEffect(() => {
58
+ clientMtqq?.on("message", (topic: any, payload: any) => {
59
+ if (topic != mqttConnect) return;
60
+ const props = JSON.parse(payload.toString());
61
+ const handler: MessageHandlerType = {
62
+ // [PublishType.Ping]: (payload) => {
63
+ // if (typeof payload === "object") {
64
+ // clientMtqq?.publish(
65
+ // payload.topic,
66
+ // JSON.stringify({ type: PublishType.Ping, payload: true })
67
+ // );
68
+ // localStorage.setItem(
69
+ // `PosDevice${posId}`,
70
+ // JSON.stringify({
71
+ // name: payload.serialNumber,
72
+ // latest_date_connect: getTimeNow(),
73
+ // })
74
+ // );
75
+ // // mqttConnect &&
76
+ // // localStorage.setItem(`mttqQrConnect${posId}`, mqttConnect);
77
+ // onClose();
78
+ // }
79
+ // },
80
+ };
81
+ if (props?.payload && props?.type) {
82
+ handler[props?.type as PublishType]?.(props.payload);
83
+ }
84
+ });
85
+ // return () => {
86
+ // clientMtqq && onDisconnect();
87
+ // };
88
+ }, [clientMtqq, mqttConnect]);
89
+ return (
90
+ <ModalZoom
91
+ isOpen={isOpen}
92
+ onClose={onClose}
93
+ title={t("connect_new_device")}
94
+ className="pb-4 w-[420px]"
95
+ >
96
+ {mqttConnect && (
97
+ <div className="flex flex-col items-center gap-6">
98
+ <p className="text-sm font-medium text-secondary">
99
+ {t("qr_connect_description")}
100
+ </p>
101
+ <QRCodeSVG
102
+ value={mqttConnect}
103
+ size={220}
104
+ bgColor={"#ffffff"}
105
+ fgColor={"#000000"}
106
+ level={"L"}
107
+ />
108
+ <p className="text-base font-semibold">
109
+ {t("device_code")}: POS-{posId}
110
+ </p>
111
+ </div>
112
+ )}
113
+ </ModalZoom>
114
+ );
115
+ };
116
+
117
+ export default QrConnect;
118
+
119
+ export enum PublishType {
120
+ Ping = "ping",
121
+ Payment = "payment",
122
+ PaymentResult = "payment_result",
123
+ RequestPayment = "request_payment",
124
+ }
125
+ export type MqttConnectType = {
126
+ cif: string;
127
+ platform: "android" | "ios" | "web" | "other";
128
+ serialNumber: string;
129
+ posId?: string;
130
+ };
131
+
132
+ export type PublishPayload =
133
+ | {
134
+ type: PublishType.Ping;
135
+ payload:
136
+ | {
137
+ topic: string;
138
+ serialNumber: string;
139
+ }
140
+ | boolean;
141
+ }
142
+ | {
143
+ type: PublishType.Payment;
144
+ payload: WaitingOrderType | boolean;
145
+ }
146
+ | {
147
+ type: PublishType.PaymentResult;
148
+ payload: {
149
+ isSuccess: boolean;
150
+ orderId: string;
151
+ };
152
+ }
153
+ | {
154
+ type: PublishType.RequestPayment;
155
+ payload: {
156
+ orderId: string;
157
+ amount: number;
158
+ createdAt?: string;
159
+ };
160
+ };
161
+
162
+ export type MessageHandlerType = {
163
+ [PublishType.Ping]?: (
164
+ payload:
165
+ | { topic: string; serialNumber: string; showToast: boolean }
166
+ | boolean
167
+ ) => void;
168
+ [PublishType.Payment]?: (payload: WaitingOrderType | boolean) => void;
169
+ [PublishType.PaymentResult]?: (payload: {
170
+ isSuccess: boolean;
171
+ orderId: string;
172
+ }) => void;
173
+ [PublishType.RequestPayment]?: (payload: {
174
+ orderId: string;
175
+ amount: number;
176
+ createdAt?: string;
177
+ }) => void;
178
+ };
179
+
180
+ export type WaitingOrderType = {
181
+ topic: string;
182
+ orderId: string;
183
+ amount: number;
184
+ createdAt?: string;
185
+ };
@@ -0,0 +1,37 @@
1
+ import ButtonAction from "@components/common/button-action";
2
+ import ModalZoom from "@components/common/modal/modal-zoom";
3
+ import Lottie from "lottie-react";
4
+ import animationData from "../../../../../public/assets/lottie/loading.json";
5
+ type TProps = {
6
+ isOpen: boolean;
7
+ onClose: () => void;
8
+ onRetry: () => void;
9
+ };
10
+
11
+ const WaitingForPaymentPosModal = ({ isOpen, onClose, onRetry }: TProps) => {
12
+ return (
13
+ <ModalZoom
14
+ isOpen={isOpen}
15
+ onClose={() => onClose()}
16
+ className="rounded-2xl w-[420px] flex flex-col gap-6 items-center justify-center"
17
+ >
18
+ <div style={{ width: 248 }}>
19
+ <Lottie animationData={animationData} />
20
+ </div>
21
+
22
+ <p className="text-2xl font-semibold text-[--text-primary]">
23
+ Chờ thanh toán
24
+ </p>
25
+ <div className="w-full flex justify-between gap-2">
26
+ <ButtonAction
27
+ onClick={() => onRetry()}
28
+ className="button-secondary w-full"
29
+ >
30
+ Thử lại
31
+ </ButtonAction>
32
+ </div>
33
+ </ModalZoom>
34
+ );
35
+ };
36
+
37
+ export default WaitingForPaymentPosModal;
@@ -0,0 +1,216 @@
1
+ import ButtonAction from "@components/common/button-action";
2
+ import { VNCurrency } from "@components/common/header";
3
+ import useCheckSession from "@components/common/use-check-session";
4
+ import { QUERY_KEYS } from "@constants/query.constant";
5
+ import { useQueryParams } from "@hooks/common/use-query-params";
6
+ import { usePayment } from "@provider/pos-provider/payment-provider";
7
+ import { LoadDataModel, useSale } from "@provider/pos-provider/sale-provider";
8
+ import { formatCurrency } from "@utils/functions";
9
+ import { useEffect, useMemo, useState } from "react";
10
+ import { useTranslation } from "react-i18next";
11
+ import { InfoLine, PaymentInfo } from "../payment-info";
12
+ import { PaymentLayout } from "../payment-layout";
13
+ import SessionCloseModal from "../session-close-modal";
14
+
15
+ export const CashPayment = ({ total }: { total: number }) => {
16
+ const [customerAmount, setCustomerAmount] = useState("");
17
+ const [errorMessage, setErrorMessage] = useState("");
18
+ const [isPayingState, setIsPayingState] = useState(false);
19
+ const [showCloseSessionModal, setShowCloseSessionModal] = useState(false);
20
+ const { onCheckSession } = useCheckSession();
21
+ const { handlePayment } = usePayment();
22
+ const {
23
+ queryResult: { data },
24
+ } = useSale();
25
+
26
+ const { getQuery } = useQueryParams();
27
+ const orderId = getQuery(QUERY_KEYS.ORDER_ID);
28
+ const payment_method_ids = useMemo(() => {
29
+ if (!data) return [];
30
+ return (
31
+ (data?.[LoadDataModel.POS_SESSION].data?.[0]
32
+ ?.payment_method_ids as number[]) || []
33
+ );
34
+ }, [data]);
35
+
36
+ const payment_method = useMemo(() => {
37
+ return data && data[LoadDataModel.POS_PAYMENT_METHOD].data;
38
+ }, [data]);
39
+
40
+ const payment_method_ids_data = useMemo(() => {
41
+ if (!payment_method) return [];
42
+ return payment_method
43
+ ?.filter((item: any) => payment_method_ids.includes(item.id))
44
+ .map((item: any) => {
45
+ return {
46
+ id: item.id,
47
+ paymentType: item.payment_type,
48
+ };
49
+ });
50
+ }, [payment_method, payment_method_ids]);
51
+
52
+ const onPayment = async () => {
53
+ const amountNumber = Number(customerAmount);
54
+ if (customerAmount === "") return setErrorMessage("Vui lòng nhập số tiền");
55
+ if (isNaN(amountNumber) || amountNumber <= 0 || amountNumber < total) {
56
+ return setErrorMessage(
57
+ "Vui lòng nhập số tiền lớn hơn hoặc bằng số tiền cần thanh toán."
58
+ );
59
+ }
60
+
61
+ const isSessionOpened = await onCheckSession();
62
+
63
+ if (!isSessionOpened) {
64
+ setShowCloseSessionModal(true);
65
+ return;
66
+ }
67
+
68
+ try {
69
+ await handlePayment({
70
+ receivedAmount: amountNumber,
71
+ amount: total,
72
+ orderId: Number(orderId),
73
+ paymentMethodId: payment_method_ids_data.find(
74
+ (item: any) => item.paymentType === "cash"
75
+ )?.id,
76
+ paymentName: "cash",
77
+ });
78
+ } catch (error) {
79
+ console.log("error", error);
80
+ setIsPayingState(false);
81
+ setErrorMessage("");
82
+ }
83
+ };
84
+
85
+ const refund: number = useMemo(() => {
86
+ const amountRefund =
87
+ Number(customerAmount) - Number(total) > 0
88
+ ? Number(customerAmount) - Number(total)
89
+ : 0;
90
+
91
+ if (customerAmount) {
92
+ amountRefund >= 0
93
+ ? setErrorMessage("")
94
+ : setErrorMessage("Vui lòng nhập số tiền hợp lệ");
95
+ return amountRefund;
96
+ }
97
+ return 0;
98
+ }, [customerAmount, total]);
99
+
100
+ useEffect(() => {
101
+ setCustomerAmount(total.toString());
102
+ }, []);
103
+ // const { onPaymentSuccess } = useOrderDetail();
104
+
105
+ return (
106
+ <>
107
+ {/* <div onClick={() => onPaymentSuccess(123)}>dfdsfnsdnf</div> */}
108
+ <PaymentLayout
109
+ leftContent={
110
+ <LeftContent
111
+ customerAmount={customerAmount}
112
+ setIsPayingState={setIsPayingState}
113
+ setCustomerAmount={setCustomerAmount}
114
+ errorMessage={errorMessage}
115
+ setErrorMessage={setErrorMessage}
116
+ />
117
+ }
118
+ rightContent={
119
+ <RightContent
120
+ customerAmount={customerAmount}
121
+ refund={refund}
122
+ onPayment={onPayment}
123
+ isPayingState={isPayingState}
124
+ />
125
+ }
126
+ />
127
+ {showCloseSessionModal && (
128
+ <SessionCloseModal isOpen={showCloseSessionModal} onClose={() => {}} />
129
+ )}
130
+ </>
131
+ );
132
+ };
133
+
134
+ const LeftContent = ({
135
+ customerAmount,
136
+ setIsPayingState,
137
+ setCustomerAmount,
138
+ errorMessage,
139
+ setErrorMessage,
140
+ }: {
141
+ customerAmount: string;
142
+ setIsPayingState: React.Dispatch<React.SetStateAction<boolean>>;
143
+ setCustomerAmount: React.Dispatch<React.SetStateAction<string>>;
144
+ errorMessage?: string;
145
+ setErrorMessage: React.Dispatch<React.SetStateAction<string>>;
146
+ }) => {
147
+ const handleAmountChange = (e: React.ChangeEvent<HTMLInputElement>) => {
148
+ const rawValue = e.target.value.replace(/\,/g, "");
149
+ if (!/^\d*$/.test(rawValue)) return;
150
+
151
+ setCustomerAmount(rawValue);
152
+ };
153
+ return (
154
+ <div className="">
155
+ <p className="text-text-primary font-medium">Tiền khách đưa</p>
156
+ <div className="border-b-[2px] border-text-active max-w-[200px] flex justify-between items-center">
157
+ <input
158
+ type="text"
159
+ value={formatCurrency(customerAmount)}
160
+ onChange={handleAmountChange}
161
+ onWheel={(e) => e.currentTarget.blur()}
162
+ onFocus={() => {
163
+ setErrorMessage("");
164
+ setIsPayingState(false);
165
+ }}
166
+ className="text-[32px] font-semibold placeholder:text-neutral-400-68 outline-none text-text-primary max-w-full"
167
+ placeholder="0"
168
+ inputMode="numeric"
169
+ />
170
+ <p>{VNCurrency}</p>
171
+ </div>
172
+
173
+ <p className="text-sm leading-5 text-state-error-base mt-1">
174
+ {errorMessage}
175
+ </p>
176
+ </div>
177
+ );
178
+ };
179
+
180
+ const RightContent = ({
181
+ refund,
182
+ customerAmount,
183
+ onPayment,
184
+ isPayingState,
185
+ }: {
186
+ refund: number;
187
+ customerAmount: string;
188
+ onPayment: () => void;
189
+ isPayingState: boolean;
190
+ }) => {
191
+ const { t } = useTranslation();
192
+
193
+ return (
194
+ <div className="flex flex-col gap-3 h-full justify-center ">
195
+ <PaymentInfo />
196
+ <div className="flex flex-col gap-3">
197
+ <div className="w-full h-[1px] bg-stroke-disabled" />
198
+ <InfoLine
199
+ label="Tiền khách đưa"
200
+ value={`${Number(customerAmount).toLocaleString()}${VNCurrency}`}
201
+ />
202
+ <InfoLine
203
+ label="Tiền thừa"
204
+ value={`${refund.toLocaleString()}${VNCurrency}`}
205
+ valueClassName="text-colored-success"
206
+ />
207
+ <ButtonAction
208
+ disabled={isPayingState}
209
+ text={t("finish_payment")}
210
+ onClick={onPayment}
211
+ className="button-primary"
212
+ />
213
+ </div>
214
+ </div>
215
+ );
216
+ };
@@ -0,0 +1,70 @@
1
+ import { IcClose } from "@assets/icons/common";
2
+ import { ButtonIcon } from "@components/common/button-icon";
3
+ import { QUERY_KEYS } from "@constants/query.constant";
4
+ import { useQueryParams } from "@hooks/common/use-query-params";
5
+ import { useOrderDetail } from "@provider/pos-provider/order-detail-provider";
6
+ import { useEffect, useState } from "react";
7
+ import { CardPaymentMethod } from "./card-payment";
8
+ import { CashPayment } from "./cash-payment";
9
+ import { PaymentMethodCards } from "./payment-method-cards";
10
+ import { QRPayment } from "./qr-payment";
11
+ import { SoftPosPayment } from "./soft-pos-payment";
12
+
13
+ type Props = {
14
+ onHidePayment: () => void;
15
+ };
16
+
17
+ const enum PaymentMethod {
18
+ QR = "qr",
19
+ CARD = "card",
20
+ CASH = "cash",
21
+ SOFT_POS = "soft_pos",
22
+ }
23
+
24
+ export const PaymentContent = ({ onHidePayment }: Props) => {
25
+ const { taxAmount, totalAmount } = useOrderDetail();
26
+ const { removeParam } = useQueryParams();
27
+ const total = totalAmount + taxAmount;
28
+ const [paymentMethod, setPaymentMethod] = useState<string>("");
29
+ const renderPaymentContent = () => {
30
+ switch (paymentMethod) {
31
+ case PaymentMethod.QR:
32
+ return <QRPayment total={total} />;
33
+ case PaymentMethod.CASH:
34
+ return <CashPayment total={total} />;
35
+ case PaymentMethod.SOFT_POS:
36
+ return <SoftPosPayment total={total} />;
37
+ default:
38
+ return <CardPaymentMethod total={total} />;
39
+ }
40
+ };
41
+
42
+ useEffect(() => {
43
+ if (
44
+ paymentMethod !== PaymentMethod.QR &&
45
+ paymentMethod !== PaymentMethod.SOFT_POS
46
+ )
47
+ removeParam([QUERY_KEYS.SHOW_SCREEN]);
48
+ }, [paymentMethod]);
49
+
50
+ return (
51
+ <div className="overflow-y-auto flex-1 h-full flex flex-col">
52
+ <div className="flex justify-between items-center h-[60px] px-3 py-[6px] sticky top-0 bg-white">
53
+ <span />
54
+ <span className="font-semibold text-text-primary">
55
+ Phương thức thanh toán
56
+ </span>
57
+ <ButtonIcon onClick={() => onHidePayment()} iconSrc={<IcClose />} />
58
+ </div>
59
+ <div className="flex flex-col gap-4 py-4 px-3 flex-1 overflow-y-auto">
60
+ <PaymentMethodCards
61
+ currentPaymentMethod={paymentMethod}
62
+ setPaymentMethod={setPaymentMethod}
63
+ />
64
+ <div className="flex items-center flex-1 w-full">
65
+ {renderPaymentContent()}
66
+ </div>
67
+ </div>
68
+ </div>
69
+ );
70
+ };
@@ -0,0 +1,67 @@
1
+ import { VNCurrency } from "@components/common/header";
2
+ import { useOrderDetail } from "@provider/pos-provider/order-detail-provider";
3
+ import { ceilDecimal, cn } from "@utils/functions";
4
+
5
+ export const PaymentInfo = () => {
6
+ const { taxAmount, totalAmount, totalQty } = useOrderDetail();
7
+
8
+ return (
9
+ <div className="flex-1 flex flex-col gap-3">
10
+ <InfoLine
11
+ label="Tổng tiền"
12
+ value={`${ceilDecimal(totalAmount).toLocaleString()}${VNCurrency}`}
13
+ subLabel={
14
+ <div className="h-6 px-2 min-w-6 w-fit rounded-full bg-colored-info text-[#2597D0] text-xs flex justify-center items-center">
15
+ <span>{totalQty}</span>
16
+ </div>
17
+ }
18
+ />
19
+ {/* <InfoLine
20
+ label="Giảm giá"
21
+ value={totalQty.toString()}
22
+ valueClassName="text-colored-error"
23
+ /> */}
24
+ <InfoLine
25
+ label="Tiền thuế"
26
+ value={`${ceilDecimal(taxAmount).toLocaleString()}${VNCurrency}`}
27
+ />
28
+ <div className="w-full h-[1px] bg-stroke-disabled" />
29
+ <InfoLine
30
+ label="Tổng thanh toán"
31
+ value={`${ceilDecimal(
32
+ totalAmount + taxAmount
33
+ ).toLocaleString()}${VNCurrency}`}
34
+ labelClassName="text-[18px] text-text-primary"
35
+ valueClassName="text-[18px] text-text-active"
36
+ />
37
+ </div>
38
+ );
39
+ };
40
+
41
+ export const InfoLine = ({
42
+ label,
43
+ value,
44
+ subLabel,
45
+ labelClassName,
46
+ valueClassName,
47
+ }: {
48
+ label: string;
49
+ value: string;
50
+ subLabel?: React.ReactNode;
51
+ labelClassName?: string;
52
+ valueClassName?: string;
53
+ }) => {
54
+ return (
55
+ <div className="w-full flex justify-between items-center">
56
+ <div className="flex gap-[6px] items-center">
57
+ <p className={cn("text-text-disable font-medium", labelClassName)}>
58
+ {label}
59
+ </p>
60
+ {subLabel}
61
+ </div>
62
+ <p className={cn("text-text-primary font-semibold", valueClassName)}>
63
+ {value}
64
+ </p>
65
+ </div>
66
+ );
67
+ };
@@ -0,0 +1,16 @@
1
+ export const PaymentLayout = ({
2
+ leftContent,
3
+ rightContent,
4
+ }: {
5
+ leftContent: React.ReactNode;
6
+ rightContent: React.ReactNode;
7
+ }) => {
8
+ return (
9
+ <div className="grid grid-cols-2 bg-white px-4 py-6 rounded-xl items-center flex-1 min-h-[370px]">
10
+ <div className="flex justify-center w-full">{leftContent}</div>
11
+ <div className="px-6 size-full border-l border-dashed border-stroke-disabled flex flex-col justify-end">
12
+ {rightContent}
13
+ </div>
14
+ </div>
15
+ );
16
+ };
@@ -0,0 +1,99 @@
1
+ import { IcBankCard, IcQRCode, IcWallet } from "@assets/icons/payment-icon";
2
+ import { PAYMENT_COLORS } from "@constants/payment-color.constant";
3
+ import { LoadDataModel, useSale } from "@provider/pos-provider/sale-provider";
4
+ import { useEffect, useMemo } from "react";
5
+
6
+ const getIcon = (name: string) => {
7
+ switch (name) {
8
+ case "cash":
9
+ return IcWallet;
10
+ case "qr":
11
+ return IcQRCode;
12
+ case "card":
13
+ return IcBankCard;
14
+ default:
15
+ return IcWallet;
16
+ }
17
+ };
18
+
19
+ interface PaymentContentProps {
20
+ currentPaymentMethod: string;
21
+ setPaymentMethod: (id: string) => void;
22
+ }
23
+
24
+ export const PaymentMethodCards: React.FC<PaymentContentProps> = ({
25
+ currentPaymentMethod,
26
+ setPaymentMethod,
27
+ }) => {
28
+ const {
29
+ queryResult: { data },
30
+ } = useSale();
31
+ const payMethodIds = useMemo(() => {
32
+ if (!data) return [];
33
+ return (
34
+ (data?.[LoadDataModel.POS_SESSION].data?.[0]
35
+ ?.payment_method_ids as number[]) || []
36
+ );
37
+ }, [data]);
38
+
39
+ const paymentMethod = useMemo(() => {
40
+ return data && data[LoadDataModel.POS_PAYMENT_METHOD].data;
41
+ }, [data]);
42
+
43
+ const paymentMethods = useMemo(() => {
44
+ if (!paymentMethod) return [];
45
+ return paymentMethod
46
+ ?.filter((item: any) => payMethodIds.includes(item.id))
47
+ .map((item: any) => {
48
+ return {
49
+ id: item.id,
50
+ title: item.name,
51
+ icon: getIcon(item.payment_type),
52
+ payment_type: item.payment_type,
53
+ onclick: () => {
54
+ setPaymentMethod(item.payment_type);
55
+ },
56
+ colorCollection: PAYMENT_COLORS.find(
57
+ (color) => color.type === item.payment_type
58
+ ),
59
+ };
60
+ });
61
+ }, [paymentMethod, payMethodIds]);
62
+
63
+ useEffect(() => {
64
+ if (paymentMethods.length > 0) {
65
+ setPaymentMethod(paymentMethods[0].payment_type);
66
+ }
67
+ }, [paymentMethods]);
68
+
69
+ return (
70
+ <div className="flex items-center justify-center gap-4">
71
+ {paymentMethods.length > 0 &&
72
+ paymentMethods.map((payment: any) => {
73
+ const isActive = currentPaymentMethod === payment.payment_type;
74
+ return (
75
+ <button
76
+ key={payment.id}
77
+ onClick={payment.onclick}
78
+ className={`w-full h-[60px] flex items-center justify-start gap-4 rounded-xl border px-4
79
+ ${
80
+ isActive
81
+ ? `${payment.colorCollection?.activeBorder} ${payment.colorCollection?.background} border-2`
82
+ : "border-stroke-default bg-white hover:border-gray-300 p-[17px]"
83
+ }`}
84
+ >
85
+ <div
86
+ className={`flex h-10 w-10 items-center justify-center rounded-full
87
+ text-white ${payment.colorCollection?.iconBackground}`}
88
+ >
89
+ <payment.icon />
90
+ </div>
91
+ <span className="text-base font-semibold text-text-primary">
92
+ {payment.title}
93
+ </span>
94
+ </button>
95
+ );
96
+ })}
97
+ </div>
98
+ );
99
+ };