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,53 @@
1
+ import { QUERY_KEYS } from "@constants/query.constant";
2
+ import { useQueryParams } from "@hooks/common/use-query-params";
3
+ import { useOrder } from "@provider/pos-provider/order-provider";
4
+ import { useSessionStore } from "@store/session";
5
+ import { useMemo } from "react";
6
+ import { useTranslation } from "react-i18next";
7
+ import Actions from "./actions";
8
+ import CloseSessionModalContainer from "./container";
9
+
10
+ export const DraftOrdersConfirm = () => {
11
+ const { setStep } = useSessionStore();
12
+ const { t } = useTranslation();
13
+ const { removeParam } = useQueryParams();
14
+ const { draftOrders } = useOrder();
15
+ const { cancelOrder } = useOrder();
16
+
17
+ const numberOfUnpaidOrders = useMemo(() => {
18
+ return draftOrders.length;
19
+ }, [draftOrders]);
20
+
21
+ const onContinue = async () => {
22
+ await cancelOrder.mutateAsync(draftOrders.map((order) => Number(order.id)));
23
+ setStep(3);
24
+ };
25
+
26
+ const handleClose = () => {
27
+ setStep(0);
28
+ removeParam([QUERY_KEYS.OPEN]);
29
+ };
30
+
31
+ return (
32
+ <CloseSessionModalContainer
33
+ isOpen={true}
34
+ onClose={handleClose}
35
+ title={t("close_session")}
36
+ >
37
+ <div className="flex flex-col h-full ">
38
+ <p className="text-sm leading-5 overflow-auto flex-1 tracking-[-0.12px] text-text-secondary">
39
+ {t("orders_left")}{" "}
40
+ <span className="font-bold tracking-[-0.2px] text-text-primary">
41
+ {numberOfUnpaidOrders.toString().padStart(2, "0")}{" "}
42
+ {t("orders_not_paid")}
43
+ </span>{" "}
44
+ {t("orders_left_content")}
45
+ <br /> <br />
46
+ <span>{t("confirm_sure")}</span>
47
+ </p>
48
+
49
+ <Actions onContinue={onContinue} buttonLabel={t("yes_button")} />
50
+ </div>
51
+ </CloseSessionModalContainer>
52
+ );
53
+ };
@@ -0,0 +1,82 @@
1
+ import { QUERY_KEYS } from "@constants/query.constant";
2
+ import { zodResolver } from "@hookform/resolvers/zod";
3
+ import { useQueryParams } from "@hooks/common/use-query-params";
4
+ import { useSessionStore } from "@store/session";
5
+ import { useCloseSessionStore } from "@store/states/close-session.state";
6
+ import { useForm } from "react-hook-form";
7
+ import { useTranslation } from "react-i18next";
8
+ import { z } from "zod";
9
+ import Actions from "./actions";
10
+ import CloseSessionModalContainer from "./container";
11
+ import SessionSummary from "./session-summary";
12
+
13
+ const schema = z.object({
14
+ cashCount: z.string().min(1, "Cash count is required"),
15
+ note: z.string(),
16
+ });
17
+
18
+ export const DraftOrdersSummary = () => {
19
+ const {
20
+ handleSubmit,
21
+ register,
22
+ watch,
23
+ formState: { errors },
24
+ setValue,
25
+ } = useForm({
26
+ defaultValues: {
27
+ cashCount: "",
28
+ note: "",
29
+ },
30
+ mode: "onChange",
31
+ resolver: zodResolver(schema),
32
+ });
33
+
34
+ const { setStep, setSessionConfirmParams } = useSessionStore();
35
+ const { setCloseSessionInfo } = useCloseSessionStore();
36
+ const { t } = useTranslation();
37
+ const { removeParam } = useQueryParams();
38
+
39
+ const onSubmit = handleSubmit((data) => {
40
+ setSessionConfirmParams({
41
+ cashCount: Number(data.cashCount),
42
+ note: data.note,
43
+ });
44
+ setCloseSessionInfo({
45
+ cashCount: Number(data.cashCount),
46
+ difference: 0,
47
+ });
48
+ setStep(4);
49
+ });
50
+
51
+ const handleClose = () => {
52
+ setStep(0);
53
+ removeParam([QUERY_KEYS.OPEN]);
54
+ };
55
+
56
+ return (
57
+ <CloseSessionModalContainer
58
+ isOpen={true}
59
+ onClose={handleClose}
60
+ title={t("close_session")}
61
+ >
62
+ <form onSubmit={onSubmit} className="flex flex-col h-full">
63
+ <SessionSummary
64
+ register={register}
65
+ errorMessage={errors.cashCount?.message}
66
+ cashCount={Number(watch("cashCount"))}
67
+ watch={watch}
68
+ setValue={setValue}
69
+ />
70
+
71
+ <Actions
72
+ onContinue={() => onSubmit()}
73
+ buttonLabel={t("yes_button")}
74
+ isDisabled={
75
+ errors.cashCount?.message !== undefined || watch("cashCount") === ""
76
+ }
77
+ className="flex items-center gap-2 w-full pt-6"
78
+ />
79
+ </form>
80
+ </CloseSessionModalContainer>
81
+ );
82
+ };
@@ -0,0 +1,34 @@
1
+ import { QUERY_KEYS } from "@constants/query.constant";
2
+ import { useQueryParams } from "@hooks/common/use-query-params";
3
+ import { useSessionStore } from "@store/session";
4
+ import { useTranslation } from "react-i18next";
5
+ import Actions from "./actions";
6
+ import CloseSessionModalContainer from "./container";
7
+ import { OrdersInDraft } from "./order";
8
+
9
+ export const DraftOrders = () => {
10
+ const { setStep } = useSessionStore();
11
+ const { t } = useTranslation();
12
+ const { removeParam } = useQueryParams();
13
+
14
+ const onContinue = () => setStep(2);
15
+
16
+ const handleClose = () => {
17
+ setStep(0);
18
+ removeParam([QUERY_KEYS.OPEN]);
19
+ };
20
+
21
+ return (
22
+ <CloseSessionModalContainer
23
+ isOpen={true}
24
+ onClose={handleClose}
25
+ title={t("close_session")}
26
+ >
27
+ <div className="flex flex-col h-full">
28
+ <OrdersInDraft />
29
+
30
+ <Actions onContinue={onContinue} buttonLabel={t("continue")} />
31
+ </div>
32
+ </CloseSessionModalContainer>
33
+ );
34
+ };
@@ -0,0 +1,35 @@
1
+ import { LoadDataModel, useSale } from "@provider/pos-provider/sale-provider"
2
+ import { useSessionStore } from "@store/session"
3
+ import { CloseSessionConfirm } from "./close-session-confirm"
4
+ import { DraftOrders } from "./draft-orders"
5
+ import { DraftOrdersConfirm } from "./draft-orders-confirm"
6
+ import { DraftOrdersSummary } from "./draft-orders-summary"
7
+
8
+ type TProps = {
9
+ onBack: () => void
10
+ }
11
+
12
+ const CloseSessionModal = () => {
13
+ const { step } = useSessionStore()
14
+ const { getData } = useSale()
15
+ const posName = getData(LoadDataModel.POS_CONFIG)?.[0]?.name
16
+
17
+ const onShowModal = () => {
18
+ switch (step) {
19
+ case 1:
20
+ return <DraftOrders />
21
+ case 2:
22
+ return <DraftOrdersConfirm />
23
+ case 3:
24
+ return <DraftOrdersSummary />
25
+ case 4:
26
+ return <CloseSessionConfirm posName={posName} />
27
+ default:
28
+ return <></>
29
+ }
30
+ }
31
+
32
+ return onShowModal()
33
+ }
34
+
35
+ export default CloseSessionModal
@@ -0,0 +1 @@
1
+ export { default as OrdersInDraft } from "./orders-in-draft";
@@ -0,0 +1,64 @@
1
+ import { FileListIcon } from "@assets/icons/order-icon";
2
+ import { VNCurrency } from "@components/common/header";
3
+ import { ORDER_STATE } from "@constants/order-state";
4
+ import { TBasicOrder } from "@type/order";
5
+ import { dd_mm_yyyy, hh_mm } from "@utils/functions";
6
+ import { useTranslation } from "react-i18next";
7
+
8
+ type TProps = {
9
+ order: TBasicOrder;
10
+ };
11
+
12
+ const OrderLine = (props: TProps) => {
13
+ const { order } = props;
14
+ const { t } = useTranslation();
15
+
16
+ return (
17
+ <div className="rounded-2xl border border-stroke-default bg-white flex items-center gap-3 p-4">
18
+ <div className="min-w-14 aspect-square rounded-lg bg-neutral-100-96 flex items-center justify-center">
19
+ <FileListIcon />
20
+ </div>
21
+
22
+ <div className="flex flex-col gap-2 w-full justify-center">
23
+ <div className="flex items-center justify-between">
24
+ <p className="font-semibold leading-6 text-text-primary tracking-[-0.16px]">
25
+ #{order.id}
26
+ </p>
27
+ <div
28
+ className={`rounded border ${
29
+ order.state === ORDER_STATE.IN_PAID
30
+ ? "border-stroke-warning bg-[#FFF5DC]"
31
+ : "border-colored-success bg-success"
32
+ } py-1 px-2`}
33
+ >
34
+ <p
35
+ className={`text-xs font-medium leading-4 ${
36
+ order.state === ORDER_STATE.NEW
37
+ ? "text-text-colored-warning"
38
+ : "text-colored-success"
39
+ }`}
40
+ >
41
+ {order.state === ORDER_STATE.NEW
42
+ ? `${t(ORDER_STATE.NEW)}`
43
+ : `${t(ORDER_STATE.IN_PAID)}`}
44
+ </p>
45
+ </div>
46
+ </div>
47
+
48
+ <div className="flex items-center justify-between">
49
+ <p className="text-text-secondary flex-1 text-sm leading-5 tracking-[-0.12px]">
50
+ {hh_mm(order.create_date) + " • " + dd_mm_yyyy(order.create_date)}
51
+ </p>
52
+ <p className="font-semibold text-end flex-1 line-clamp-1 leading-6 tracking-[-0.24px] text-text-primary">
53
+ {(order.amount_total + order.amount_tax).toLocaleString("vi-VN", {
54
+ maximumFractionDigits: 0,
55
+ })}{" "}
56
+ {VNCurrency}
57
+ </p>
58
+ </div>
59
+ </div>
60
+ </div>
61
+ );
62
+ };
63
+
64
+ export default OrderLine;
@@ -0,0 +1,31 @@
1
+ import { useCloseSession } from "@provider/pos-provider/close-session-provider";
2
+ import { useTranslation } from "react-i18next";
3
+ import OrderLine from "./order-line";
4
+
5
+ const OrdersInDraft = () => {
6
+ const { draftInPaidOrders } = useCloseSession();
7
+ const { t } = useTranslation();
8
+
9
+ if (!draftInPaidOrders.length) return null;
10
+
11
+ return (
12
+ <div className="flex flex-col flex-1 gap-6 overflow-auto justify-start">
13
+ <div className="flex flex-col gap-1">
14
+ <p className="text-lg font-semibold leading-[26px] text-text-primary">
15
+ {t("number_orders_left", {
16
+ numberOfOrders: draftInPaidOrders.length,
17
+ })}
18
+ </p>
19
+ <p className="text-sm leading-5 tracking-[-0.12px] text-text-secondary">
20
+ {t("confirm_close")}
21
+ </p>
22
+ </div>
23
+
24
+ {draftInPaidOrders.map((order) => (
25
+ <OrderLine key={order.id} order={order} />
26
+ ))}
27
+ </div>
28
+ );
29
+ };
30
+
31
+ export default OrdersInDraft;
@@ -0,0 +1,165 @@
1
+ import { IcBack } from "@assets/icons/common";
2
+ import { VNCurrency } from "@components/common/header";
3
+ import TextArea from "@components/common/input/text-area";
4
+ import { formatCurrency, unFormatCurrency } from "@utils/functions";
5
+ import { generateCloseSessionData } from "@utils/pos/session";
6
+ import { useState } from "react";
7
+ import {
8
+ UseFormRegister,
9
+ UseFormSetValue,
10
+ UseFormWatch,
11
+ } from "react-hook-form";
12
+ import { useTranslation } from "react-i18next";
13
+ import { toast } from "react-toastify";
14
+ import { useCloseSession } from "@provider/pos-provider/close-session-provider";
15
+
16
+ type Props = {
17
+ register: UseFormRegister<{ cashCount: string; note: string }>;
18
+ watch: UseFormWatch<{
19
+ cashCount: string;
20
+ note: string;
21
+ }>;
22
+ setValue: UseFormSetValue<{
23
+ cashCount: string;
24
+ note: string;
25
+ }>;
26
+ errorMessage?: string;
27
+ cashCount: number;
28
+ };
29
+
30
+ const SessionSummary = ({
31
+ register,
32
+ errorMessage,
33
+ watch,
34
+ setValue,
35
+ cashCount,
36
+ }: Props) => {
37
+ const {
38
+ getDataCloseSessionQuery: { data },
39
+ } = useCloseSession();
40
+
41
+ const closeSessionSummary = generateCloseSessionData(
42
+ data as TSessionData,
43
+ cashCount
44
+ );
45
+
46
+ const handleCashChange = (e: React.ChangeEvent<HTMLInputElement>) => {
47
+ const raw = unFormatCurrency(e.target.value);
48
+ if (!/^\d*$/.test(raw)) return;
49
+ setValue("cashCount", raw);
50
+ };
51
+
52
+ const { t } = useTranslation();
53
+
54
+ return (
55
+ <div className="flex flex-col flex-1 overflow-auto gap-3 hide-scrollbar">
56
+ {closeSessionSummary.map((item, index) => (
57
+ <SummaryCard key={index} item={item} />
58
+ ))}
59
+
60
+ <div className="flex flex-col gap-4 bg-white p-4 border border-stroke-disabled rounded-xl">
61
+ <div className="flex flex-col gap-[6px]">
62
+ <p className="text-text-primary text-sm font-medium leading-5 tracking-[-0.12px]">
63
+ {t("cash_count")}
64
+ <span className="text-state-error-base"> *</span>
65
+ </p>
66
+
67
+ <input
68
+ type="text"
69
+ inputMode="numeric"
70
+ value={formatCurrency(cashCount)}
71
+ onChange={handleCashChange}
72
+ placeholder="0"
73
+ className={`w-full px-3 py-2 border ${
74
+ errorMessage ? "border-state-error-base" : "border-stroke-default"
75
+ } rounded-md text-sm`}
76
+ />
77
+
78
+ {errorMessage && (
79
+ <p className="text-state-error-base text-xs">{errorMessage}</p>
80
+ )}
81
+ </div>
82
+
83
+ <TextArea
84
+ title={t("note")}
85
+ register={register("note")}
86
+ placeholder={t("close_session_note")}
87
+ />
88
+ </div>
89
+ </div>
90
+ );
91
+ };
92
+
93
+ export default SessionSummary;
94
+
95
+ const SummaryCard = ({ item }: { item: TCloseSessionItemProps }) => {
96
+ const { title, subItems, price } = item;
97
+ const { t } = useTranslation();
98
+ const [showContent, setShowContent] = useState(true);
99
+
100
+ return (
101
+ <div
102
+ style={{
103
+ boxShadow: "0 2px 4px 0 rgba(27, 28, 29, 0.04)",
104
+ }}
105
+ className="rounded-xl border border-stroke-disabled bg-white"
106
+ >
107
+ {/* title */}
108
+ <div
109
+ onClick={() => setShowContent(!showContent)}
110
+ className="flex cursor-pointer items-center justify-between p-3"
111
+ >
112
+ <div className="flex items-center justify-center gap-2">
113
+ <item.icon />
114
+
115
+ <span className="text-sm font-semibold leading-4 text-text-primary">
116
+ {t(`${title}` as any)}
117
+ </span>
118
+ </div>
119
+
120
+ <div className="flex items-center justify-center gap-1">
121
+ <span className="space-x-1 text-right text-sm font-semibold tracking-[-0.12px] text-strong-950">
122
+ {price.toLocaleString()}{" "}
123
+ <span className="text-stroke-soft-400">{VNCurrency}</span>
124
+ </span>
125
+
126
+ <div className={`${showContent ? "" : "rotate-180"}`}>
127
+ <IcBack />
128
+ </div>
129
+ </div>
130
+ </div>
131
+
132
+ {/* content */}
133
+ {showContent && (
134
+ <div className="overflow-hidden border-t border-stroke-disabled p-3">
135
+ {subItems.map((item, index) => (
136
+ <div key={index} className="flex items-center justify-between py-1">
137
+ <span className="text-xs font-medium leading-4 text-text-secondary">
138
+ {t(`${item.title}` as any)}
139
+ </span>
140
+
141
+ <span className="space-x-1 text-right text-xs leading-4 font-semibold tracking-[-0.12px] text-strong-950">
142
+ {item.price.toLocaleString()}{" "}
143
+ <span className="text-tertiary">{VNCurrency}</span>
144
+ </span>
145
+ </div>
146
+ ))}
147
+
148
+ {item.title.toLowerCase().includes("card") && (
149
+ <div
150
+ onClick={() => toast.success("Coming soon")}
151
+ className="w-full flex items-center justify-center py-[2px]"
152
+ >
153
+ <div className="flex items-center justify-center gap-4">
154
+ <div className="w-5 h-5 rounded border-[1.5px] border-stroke-disabled bg-white" />
155
+ <p className="text-sm font-medium text-text-primary leading-5 tracking-[-0.12px]">
156
+ {t("pos_auto_close_session")}
157
+ </p>
158
+ </div>
159
+ </div>
160
+ )}
161
+ </div>
162
+ )}
163
+ </div>
164
+ );
165
+ };
@@ -0,0 +1 @@
1
+ export * from "./close-session-modal";
@@ -0,0 +1,172 @@
1
+ import ButtonAction from "@components/common/button-action";
2
+ import ModalZoom from "@components/common/modal/modal-zoom";
3
+ import { QUERY_KEYS } from "@constants/query.constant";
4
+ import POSPath from "@constants/routes.constants";
5
+ import useSessionProvider from "@provider/use-session-provider";
6
+ import { formatCurrency } from "@utils/functions";
7
+ import { t } from "i18next";
8
+ import { useMemo, useState } from "react";
9
+ import { FormProvider } from "react-hook-form";
10
+ import { useNavigate } from "react-router-dom";
11
+
12
+ type RecordType = Record<string, any>;
13
+
14
+ type POSStatus =
15
+ | false
16
+ | "opened"
17
+ | "closed"
18
+ | "opening_control"
19
+ | "closing_control";
20
+
21
+ type TProps = {
22
+ openModal: boolean;
23
+ setOpenModal: (val: boolean) => void;
24
+ methods: any;
25
+ row: any;
26
+ record: RecordType;
27
+ };
28
+
29
+ const OpenSessionModal = (props: TProps) => {
30
+ const { openModal, setOpenModal, methods, row, record } = props;
31
+ const { openSession, setOpeningCashBox } = useSessionProvider();
32
+ const [money, setMoney] = useState("");
33
+ const [loading, setLoading] = useState(false);
34
+ const data = useMemo(() => {
35
+ return {
36
+ current_session_id: record["current_session_id"]?.id ?? "",
37
+ record_id: record?.id as number,
38
+ current_session_state: record["current_session_state"] as POSStatus,
39
+ module_pos_restaurant: record["module_pos_restaurant"] as boolean,
40
+ name: record.name as string,
41
+ id: record.id as number,
42
+ cash_control: record.cash_control as boolean,
43
+ };
44
+ }, [record]);
45
+ const onClose = () => props.setOpenModal(false);
46
+
47
+ const navigate = useNavigate();
48
+ const handleOpeningCashBoxSuccess = (sessionId: number) => {
49
+ onClose();
50
+ if (data.module_pos_restaurant)
51
+ return navigate(
52
+ `${POSPath.TABLES}?${QUERY_KEYS.POS_ID}=${data.id}&${QUERY_KEYS.SESSION_ID}=${sessionId}`
53
+ );
54
+ // return `/${PosPaths.MANAGEMENT_TABLE}?${QUERY_KEYS.POS_ID}=${data.id}&${QUERY_KEYS.SESSION_ID}=${sessionId}`;
55
+ return navigate(
56
+ `${POSPath.MENUS}?${QUERY_KEYS.POS_ID}=${data.id}&${QUERY_KEYS.SESSION_ID}=${sessionId}`
57
+ );
58
+ // else return toast.info("Đang phát triển");
59
+ };
60
+
61
+ const onSetOpeningCashBox = async (
62
+ cashBoxValue: number,
63
+ sessionId: number
64
+ ) => {
65
+ try {
66
+ await setOpeningCashBox.mutateAsync(
67
+ {
68
+ cashBoxValue,
69
+ sessionId: Number(sessionId),
70
+ },
71
+ {
72
+ onSuccess: () => {
73
+ handleOpeningCashBoxSuccess(sessionId);
74
+ },
75
+ }
76
+ );
77
+ } catch (error) {
78
+ console.error("Error setting opening cash box:", error);
79
+ }
80
+ };
81
+
82
+ const handleOpenSession = async () => {
83
+ setLoading(true);
84
+ try {
85
+ if (data.current_session_state == "opening_control") {
86
+ await onSetOpeningCashBox(
87
+ Number(money),
88
+ Number(data.current_session_id)
89
+ );
90
+ } else {
91
+ const res = await openSession.mutateAsync(Number(data.record_id));
92
+ const sessionIdNew = Object.keys(Object.fromEntries(res as any));
93
+ await onSetOpeningCashBox(Number(money), Number(sessionIdNew[0]));
94
+ }
95
+ } catch (error) {
96
+ console.error("Error opening session:", error);
97
+ } finally {
98
+ setLoading(false);
99
+ }
100
+ };
101
+ const handleAmountChange = (e: React.ChangeEvent<HTMLInputElement>) => {
102
+ const rawValue = e.target.value.replace(/\,/g, "");
103
+ if (!/^\d*$/.test(rawValue)) return;
104
+
105
+ setMoney(rawValue);
106
+ };
107
+ return (
108
+ <ModalZoom isOpen={openModal} onClose={onClose} className="">
109
+ <FormProvider {...methods}>
110
+ <div className="flex flex-col gap-6 border-b border-[--stroke-default] w-[500px] p-6 bg-white">
111
+ <div className="p-3 flex gap-5 items-center">
112
+ <img
113
+ src="/assets/images/cashier.svg"
114
+ alt="POS Icon"
115
+ className="size-12"
116
+ />
117
+ <p className="text-base text-[#0E121B] font-semibold">
118
+ {row["name"]}
119
+ </p>
120
+ </div>
121
+ <div className="flex flex-col gap-[6px]">
122
+ <p className="text-sm font-medium">
123
+ {t("starting_cash_float")}{" "}
124
+ <span className="text-[--color-error]">*</span>
125
+ </p>
126
+
127
+ <input
128
+ type="text"
129
+ value={formatCurrency(money)}
130
+ onChange={handleAmountChange}
131
+ onWheel={(e) => e.currentTarget.blur()}
132
+ className="border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring-1 focus:ring-gray-400 text-sm"
133
+ placeholder="0"
134
+ inputMode="numeric"
135
+ />
136
+ </div>
137
+ {/* <div className="flex flex-col gap-[6px]">
138
+ <p className="text-sm font-medium">Lưu ý</p>
139
+ <TextAreaField
140
+ {...{
141
+ defaultValue: "",
142
+ string: "Lưu ý ",
143
+ readOnly: false,
144
+ methods: methods,
145
+ isForm: true,
146
+ placeholder: "Lưu ý khi mở ca",
147
+ name: "note",
148
+ }}
149
+ />
150
+ </div> */}
151
+ </div>
152
+ <p className="p-4 flex justify-end gap-4 mt-auto">
153
+ <ButtonAction
154
+ onClick={() => setOpenModal(false)}
155
+ className="h-[36px] button-secondary"
156
+ >
157
+ {t("cancel_button")}
158
+ </ButtonAction>
159
+ <ButtonAction
160
+ disabled={!money || loading}
161
+ onClick={handleOpenSession}
162
+ className="h-[36px] button-primary"
163
+ >
164
+ {t("open_session")}
165
+ </ButtonAction>
166
+ </p>
167
+ </FormProvider>
168
+ </ModalZoom>
169
+ );
170
+ };
171
+
172
+ export default OpenSessionModal;
File without changes
@@ -0,0 +1 @@
1
+ export const FIND_PARTNER_CODE = "walk_in_customer";
@@ -0,0 +1,24 @@
1
+ import { IcMenu } from "@assets/icons/order-icon";
2
+ import { IcOrderList, IcTable } from "@assets/icons/pos-icon";
3
+ import POSPath from "./routes.constants";
4
+
5
+ export const headerTabs = [
6
+ {
7
+ id: 0,
8
+ name: "Danh sách bàn",
9
+ icon: <IcTable />,
10
+ path: POSPath.TABLES,
11
+ },
12
+ {
13
+ id: 1,
14
+ name: "Thực đơn",
15
+ icon: <IcMenu />,
16
+ path: POSPath.MENUS,
17
+ },
18
+ {
19
+ id: 2,
20
+ name: "Đơn hàng",
21
+ icon: <IcOrderList />,
22
+ path: POSPath.ORDERS,
23
+ },
24
+ ];
@@ -0,0 +1 @@
1
+ export { default as POSPath } from "./routes.constants";