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,130 @@
1
+ import Image from "@components/common/image";
2
+ import { CartItemType } from "@store/states/cart.state";
3
+ import { useState } from "react";
4
+ import CancelOrderLineConfirm from "./cancel-order-line-modal";
5
+ import { CartItem } from "./cart-item";
6
+ import { EmptyState } from "@components/common/empty-state";
7
+ import { VNCurrency } from "@components/common/header";
8
+ import { useOrder } from "@provider/pos-provider";
9
+
10
+ export const CartItems = ({
11
+ cartItemsArr,
12
+ showPayment,
13
+ }: {
14
+ cartItemsArr: CartItemType[];
15
+ showPayment?: boolean;
16
+ }) => {
17
+ const [showModal, setShowModal] = useState(false);
18
+ const [cancelOrder, setCancelOrder] = useState<CartItemType | undefined>(
19
+ undefined
20
+ );
21
+ const { onCallDish, onRemoveProduct } = useOrder();
22
+
23
+ const onCancelOrderLine = () => {
24
+ if (!cancelOrder) return;
25
+ onRemoveProduct(cancelOrder.product);
26
+ onCallDish();
27
+ };
28
+
29
+ return (
30
+ <div className="bg-white h-fit rounded-lg border border-stroke-default flex flex-col justify-between flex-1 overflow-hidden">
31
+ {cartItemsArr.length > 0 ? (
32
+ showPayment ? (
33
+ <CartTable cartItemsArr={cartItemsArr} />
34
+ ) : (
35
+ <div className="flex flex-col">
36
+ {cartItemsArr.map((item) => (
37
+ <CartItem
38
+ key={item.lineId?.toString()}
39
+ item={item}
40
+ setCancelOrder={setCancelOrder}
41
+ />
42
+ ))}
43
+ {showModal && (
44
+ <CancelOrderLineConfirm
45
+ onClose={() => setShowModal(false)}
46
+ onCancelOrderLine={onCancelOrderLine}
47
+ />
48
+ )}
49
+ </div>
50
+ )
51
+ ) : (
52
+ <div className="flex flex-col gap-3 justify-center items-center h-full">
53
+ <Image
54
+ imageUrl="/assets/images/empty-cart.png"
55
+ className="w-[164px] aspect-square"
56
+ />
57
+ <p className="text-sm font-medium text-text-primary">
58
+ Vui lòng thêm món để tiếp tục
59
+ </p>
60
+ </div>
61
+ )}
62
+ </div>
63
+ );
64
+ };
65
+
66
+ const CartTable = ({ cartItemsArr }: { cartItemsArr: CartItemType[] }) => {
67
+ const tableHeader = ["Sản phẩm", "SL", "Đơn giá", "Thành tiền"];
68
+ const isLoading = false;
69
+ return (
70
+ <table className="min-w-full divide-y divide-stroke-disabled table-fixed">
71
+ <thead className=" sticky top-0 z-10 border-b border-stroke-disabled">
72
+ <tr>
73
+ {tableHeader.map((header, idx) => (
74
+ <th
75
+ key={idx}
76
+ className="px-3 py-3 text-left text-sm font-semibold text-text-disable"
77
+ >
78
+ <div>{header}</div>
79
+ </th>
80
+ ))}
81
+ </tr>
82
+ </thead>
83
+
84
+ {/* Body */}
85
+ <tbody className="bg-white divide-y divide-stroke-disabled [&>tr]:h-11">
86
+ {cartItemsArr?.length ? (
87
+ cartItemsArr.map((orderLine) => {
88
+ return (
89
+ <tr
90
+ key={orderLine.lineId?.toString()}
91
+ className="text-sm text-text-primary font-semibold leading-5 tracking-[-0.12px] border-b border-stroke-disabled"
92
+ >
93
+ <td className="p-3">{orderLine.product.name}</td>
94
+ <td className="p-3">{orderLine.qty}</td>
95
+ <td className="p-3">
96
+ {orderLine.product.lst_price.toLocaleString()}
97
+ {VNCurrency}
98
+ </td>
99
+ <td className="p-3">
100
+ {(
101
+ orderLine.product.lst_price * orderLine.qty
102
+ ).toLocaleString()}{" "}
103
+ {VNCurrency}
104
+ </td>
105
+ </tr>
106
+ );
107
+ })
108
+ ) : (
109
+ <tr>
110
+ <td
111
+ colSpan={tableHeader.length}
112
+ className="text-center text-sm text-gray-500 py-6"
113
+ >
114
+ {isLoading ? (
115
+ "Đang tải đơn hàng..."
116
+ ) : (
117
+ <EmptyState
118
+ image="/assets/images/order-empty-state.png"
119
+ imageAlt="empty-order"
120
+ description="Chưa có đơn"
121
+ imageClassName="size-[200px]"
122
+ />
123
+ )}
124
+ </td>
125
+ </tr>
126
+ )}
127
+ </tbody>
128
+ </table>
129
+ );
130
+ };
@@ -0,0 +1,67 @@
1
+ import { IcDot } from "@assets/icons/common";
2
+ import { IcOrderList } from "@assets/icons/pos-icon";
3
+ import { VNCurrency } from "@components/common/header";
4
+ import { QUERY_KEYS } from "@constants/query.constant";
5
+ import { useQueryParams } from "@hooks/common/use-query-params";
6
+ import { useFloor } from "@provider/pos-provider/floor-provider";
7
+ import { TBasicOrder } from "@type/order";
8
+
9
+ export const DraftOrderLine = ({
10
+ order,
11
+ onBack,
12
+ onAppendDisplayedOrders,
13
+ }: {
14
+ order: TBasicOrder;
15
+ onBack: () => void;
16
+ onAppendDisplayedOrders?: (orderId: string) => void;
17
+ }) => {
18
+ const { updateMultipleQuery } = useQueryParams();
19
+ const { tableOfOrder } = useFloor();
20
+ const { floorId, tableId, fullName } = tableOfOrder(order.table_id, order.id);
21
+
22
+ const onSelectOrder = () => {
23
+ updateMultipleQuery([
24
+ {
25
+ key: QUERY_KEYS.ORDER_ID,
26
+ value: order.id.toString(),
27
+ },
28
+ {
29
+ key: QUERY_KEYS.TABLE_ID,
30
+ value: tableId?.toString(),
31
+ },
32
+ {
33
+ key: QUERY_KEYS.FLOOR,
34
+ value: floorId?.toString(),
35
+ },
36
+ ]);
37
+ onBack();
38
+ };
39
+
40
+ return (
41
+ <div
42
+ className="px-2 rounded-lg bg-white flex gap-3 items-center min-h-[60px] cursor-pointer"
43
+ onClick={() => onSelectOrder()}
44
+ >
45
+ <div className="flex items-center justify-center bg-bg-disabled h-12 size-11 rounded-lg text-primary">
46
+ <IcOrderList />
47
+ </div>
48
+ <div className="flex flex-col flex-1">
49
+ <p className="flex gap-[6px] items-center text-sm font-medium text-text-secondary">
50
+ <span className="text-text-primary">{fullName}</span>
51
+ <span>#{order.id}</span>
52
+ </p>
53
+ <p className="flex gap-[6px] items-center text-sm">
54
+ <span>
55
+ {order.create_date.getHours()}:{order.create_date.getMinutes()}
56
+ </span>
57
+ <IcDot />
58
+ <span>{order.create_date.toLocaleDateString()}</span>
59
+ </p>
60
+ </div>
61
+ <p>
62
+ {order.create_date.toLocaleString()}
63
+ {VNCurrency}
64
+ </p>
65
+ </div>
66
+ );
67
+ };
@@ -0,0 +1,40 @@
1
+ import { IcClose } from "@assets/icons/common";
2
+ import { ButtonIcon } from "@components/common/button-icon";
3
+ import { TBasicOrder } from "@type/order";
4
+ import { DraftOrderLine } from "./draft-order-line";
5
+
6
+ export const DraftOrders = ({
7
+ onBack,
8
+ orders,
9
+ onAppendDisplayedOrders,
10
+ }: {
11
+ onBack: () => void;
12
+ orders: TBasicOrder[];
13
+ onAppendDisplayedOrders?: (orderId: string) => void;
14
+ }) => {
15
+ return (
16
+ <div className="flex-1 flex flex-col overflow-y-auto h-full">
17
+ <div className="p-[6px] flex justify-between items-center bg-white h-15">
18
+ <ButtonIcon
19
+ iconSrc={<IcClose />}
20
+ onClick={() => onBack()}
21
+ className="bg-neutral-disabled"
22
+ />
23
+ <p className="text-lg font-semibold text-text-primary">
24
+ Đơn chưa thanh toán
25
+ </p>
26
+ <div className="size-12" />
27
+ </div>
28
+ <div className="flex flex-col gap-2 p-2 flex-1 overflow-y-auto">
29
+ {orders.map((order) => (
30
+ <DraftOrderLine
31
+ key={order.id}
32
+ order={order}
33
+ onBack={onBack}
34
+ onAppendDisplayedOrders={onAppendDisplayedOrders}
35
+ />
36
+ ))}
37
+ </div>
38
+ </div>
39
+ );
40
+ };
@@ -0,0 +1,11 @@
1
+ import { CartItemType } from "@store/states/cart.state"
2
+
3
+ export const EditCartModal = ({
4
+ cartItem
5
+ }:{
6
+ cartItem?: CartItemType
7
+ }) => {
8
+ return (
9
+ <div>EditCartModal</div>
10
+ )
11
+ }
@@ -0,0 +1,260 @@
1
+ import ProductDetailModal from "@components/pos-management/menu-content/product-detail/modal";
2
+ import { QUERY_KEYS } from "@constants/query.constant";
3
+ import { useQueryParams } from "@hooks/common/use-query-params";
4
+ import useGetPointReward from "@hooks/order/use-get-point-reward";
5
+ import { useFloor } from "@provider/pos-provider/floor-provider";
6
+ import { useKitchen } from "@provider/pos-provider/kitchen-provider";
7
+ import { useOrderDetail } from "@provider/pos-provider/order-detail-provider";
8
+ import { useOrder } from "@provider/pos-provider/order-provider";
9
+ import { LoadDataModel, useSale } from "@provider/pos-provider/sale-provider";
10
+ import { CartItemType, useCartStore } from "@store/states/cart.state";
11
+ import { usePaymentStore } from "@store/states/payment.state";
12
+ import { arraysEqual } from "@utils/functions";
13
+ import { useEffect, useMemo, useState } from "react";
14
+ import { useLocation } from "react-router-dom";
15
+ import { ActionLine } from "./action-line";
16
+ import { CartItems } from "./cart-items";
17
+ import { DraftOrders } from "./draft-orders";
18
+ import { NoSelectOrder } from "./no-select-order";
19
+ import { OrderInfo } from "./order-info";
20
+ import { OrderTotal } from "./order-total";
21
+ import { OrdersLine } from "./orders-line";
22
+ import POSPath from "@constants/routes.constants";
23
+
24
+ export const CartContent = () => {
25
+ const { showPayment, setShowPayment } = usePaymentStore();
26
+ const [displayedOrders, setDisplayedOrders] = useState<string[]>([]);
27
+ const [showDraftOrders, setShowDraftOrders] = useState(false);
28
+ const { getQuery, updateMultipleQuery } = useQueryParams();
29
+ const orderId = getQuery(QUERY_KEYS.ORDER_ID);
30
+ const tableId = getQuery(QUERY_KEYS.TABLE_ID);
31
+ const pathName = useLocation().pathname;
32
+
33
+ const {
34
+ orders,
35
+ draftOrders,
36
+ orderDetailById,
37
+ partnerIdQueryResult,
38
+ handleCreateOrder,
39
+ } = useOrder();
40
+
41
+ const { displayDataQueryResult } = useKitchen();
42
+ const { taxAmount, totalAmount, totalQty } = useOrderDetail();
43
+ const { pointReward } = useGetPointReward({
44
+ totalAmountWithoutTax: totalAmount - taxAmount,
45
+ });
46
+ const partnerId = useMemo(() => {
47
+ return orderDetailById?.partner_id;
48
+ }, [orderDetailById]);
49
+
50
+ const isGuest = useMemo(() => {
51
+ return Number(partnerId) === (partnerIdQueryResult?.data || 7);
52
+ }, [partnerId]);
53
+
54
+ const { cartItems } = useCartStore();
55
+ const orderedLine = useMemo(() => {
56
+ const orders = displayDataQueryResult?.data?.orders
57
+ ?.filter((item: any) => item?.pos_order_id === Number(orderId))
58
+ ?.map((item: any) => item.orderlines)
59
+ ?.flat()
60
+ ?.reduce((acc: any, item: any) => {
61
+ if (!acc[item.product_id]) {
62
+ acc[item.product_id] = { ...item };
63
+ } else {
64
+ acc[item.product_id].product_quantity += item.product_quantity;
65
+ acc[item.product_id].product_cancelled += item.product_cancelled;
66
+ }
67
+ return acc;
68
+ }, {});
69
+ return orders;
70
+ }, [displayDataQueryResult, orderId]);
71
+
72
+ const cartItemsArr = useMemo(() => {
73
+ const items = Object.values(cartItems);
74
+ return items?.map((item: CartItemType) => {
75
+ const orderLine = orderedLine?.[item.product.id];
76
+ return {
77
+ ...item,
78
+ ordered:
79
+ orderLine?.product_id == item.product.id &&
80
+ orderLine.product_quantity - orderLine.product_cancelled ==
81
+ item.qty &&
82
+ arraysEqual(
83
+ orderLine?.attribute_ids ?? [],
84
+ item?.product?.attributeValueIds ?? []
85
+ ),
86
+ orderedNumber:
87
+ (orderLine?.product_quantity ?? 0) -
88
+ (orderLine?.product_cancelled ?? 0),
89
+ };
90
+ });
91
+ }, [cartItems, orderedLine]);
92
+
93
+ const onFindDisplayedOrders = () => {
94
+ const takeAwayOrders = draftOrders.filter((order) => !order.table_id);
95
+ if (tableId) return tableId;
96
+ if (draftOrders.length == 0 || takeAwayOrders.length > 0) return "";
97
+ return draftOrders[0].table_id ? draftOrders[0].table_id : "";
98
+ };
99
+
100
+ useEffect(() => {
101
+ const tempTableId = onFindDisplayedOrders();
102
+ const orders = draftOrders.filter((order) => {
103
+ return tempTableId
104
+ ? order.table_id?.toString() === tempTableId?.toString()
105
+ : !order.table_id;
106
+ });
107
+ setDisplayedOrders(orders.slice(0, 3).map((order) => order.id.toString()));
108
+ }, [draftOrders, tableId]);
109
+
110
+ const onAppendDisplayedOrders = (orderId: string) => {
111
+ setDisplayedOrders((prev) => [orderId, ...prev]);
112
+ };
113
+ const {
114
+ queryResult: { data: posSession },
115
+ isModePosRestaurant,
116
+ } = useSale();
117
+ const categoriesData = posSession?.[LoadDataModel.POS_CATEGORY]?.data;
118
+ const floorId = getQuery(QUERY_KEYS.FLOOR);
119
+ const categoryId = getQuery(QUERY_KEYS.CATEGORY_ID);
120
+ const { pathname } = useLocation();
121
+ const { floors: floorData } = useFloor();
122
+
123
+ useEffect(() => {
124
+ const tableIdFirstOrder =
125
+ draftOrders?.find((order) => order.id.toString() === displayedOrders[0])
126
+ ?.table_id ?? "";
127
+
128
+ if (pathname === POSPath.TABLES && (!floorId || !tableId || !orderId)) {
129
+ updateMultipleQuery([
130
+ {
131
+ key: QUERY_KEYS.FLOOR,
132
+ value: floorId ?? String(floorData?.[0]?.id),
133
+ },
134
+ {
135
+ key: QUERY_KEYS.ORDER_ID,
136
+ value: orderId ?? String(displayedOrders[0]),
137
+ },
138
+ {
139
+ key: QUERY_KEYS.TABLE_ID,
140
+ value:
141
+ tableId ??
142
+ (tableIdFirstOrder == false ? "" : String(tableIdFirstOrder ?? "")),
143
+ },
144
+ ]);
145
+ } else if (
146
+ pathname === POSPath.MENUS &&
147
+ (!categoryId || !tableId || !orderId)
148
+ ) {
149
+ updateMultipleQuery([
150
+ {
151
+ key: QUERY_KEYS.CATEGORY_ID,
152
+ value: categoryId ?? String(categoriesData?.[0]?.id ?? ""),
153
+ },
154
+ {
155
+ key: QUERY_KEYS.ORDER_ID,
156
+ value: orderId ?? String(displayedOrders[0] ?? ""),
157
+ },
158
+ {
159
+ key: QUERY_KEYS.TABLE_ID,
160
+ value:
161
+ tableId ??
162
+ (tableIdFirstOrder == false ? "" : String(tableIdFirstOrder) ?? ""),
163
+ },
164
+ ]);
165
+ }
166
+ }, [
167
+ displayedOrders,
168
+ categoriesData,
169
+ floorData,
170
+ floorId,
171
+ categoryId,
172
+ pathname,
173
+ ]);
174
+
175
+ useEffect(() => {
176
+ updateMultipleQuery([
177
+ {
178
+ key: QUERY_KEYS.CATEGORY_ID,
179
+ value: categoryId ?? String(categoriesData?.[0]?.id ?? ""),
180
+ },
181
+ {
182
+ key: QUERY_KEYS.ORDER_ID,
183
+ value: String(displayedOrders[0] ?? ""),
184
+ },
185
+ ]);
186
+ }, [displayedOrders]);
187
+
188
+ // useEffect(() => {
189
+ // const currentOrder = orders?.find(
190
+ // (order) => order.id.toString() === orderId
191
+ // );
192
+ // if (
193
+ // currentOrder &&
194
+ // (currentOrder.state === ORDER_STATE.INVOICED ||
195
+ // currentOrder.state === ORDER_STATE.PAID)
196
+ // ) {
197
+ // navigate({
198
+ // pathname: POSPath.SUCCESS,
199
+ // search: `?${formatQuery([
200
+ // QUERY_KEYS.POS_ID,
201
+ // QUERY_KEYS.SESSION_ID,
202
+ // QUERY_KEYS.ORDER_ID,
203
+ // ])}`,
204
+ // });
205
+ // }
206
+ // }, [orderId]);
207
+
208
+ return (
209
+ <div className="w-[35%] border-r border-stroke-disabled bg-neutral-100-96">
210
+ {orders && draftOrders.length == 0 ? (
211
+ isModePosRestaurant ? (
212
+ <NoSelectOrder text="Vui lòng chọn bàn để tạo đơn" />
213
+ ) : (
214
+ <NoSelectOrder handleCreateOrder={handleCreateOrder} />
215
+ )
216
+ ) : showDraftOrders ? (
217
+ <DraftOrders
218
+ onBack={() => setShowDraftOrders(false)}
219
+ orders={draftOrders}
220
+ onAppendDisplayedOrders={onAppendDisplayedOrders}
221
+ />
222
+ ) : (
223
+ <div className="flex flex-col justify-between flex-1 h-full overflow-y-auto">
224
+ <div className="flex-1 flex flex-col overflow-y-auto">
225
+ <OrdersLine
226
+ draftOrders={draftOrders}
227
+ onShowDraftOrders={() => setShowDraftOrders(true)}
228
+ displayedOrders={displayedOrders}
229
+ setDisplayedOrders={setDisplayedOrders}
230
+ />
231
+ <div className="px-2 py-[6px] flex flex-1 flex-col gap-2 overflow-y-auto">
232
+ {orderDetailById && (
233
+ <>
234
+ <OrderInfo
235
+ orderDetail={orderDetailById}
236
+ showPayment={showPayment}
237
+ />
238
+ <CartItems
239
+ cartItemsArr={cartItemsArr}
240
+ showPayment={showPayment}
241
+ />
242
+ </>
243
+ )}
244
+ </div>
245
+ </div>
246
+
247
+ <div className="min-h-fit">
248
+ <OrderTotal />
249
+ <ActionLine
250
+ cartItemsArr={cartItemsArr}
251
+ showPayment={showPayment}
252
+ setShowPayment={setShowPayment}
253
+ />
254
+ </div>
255
+ </div>
256
+ )}
257
+ <ProductDetailModal />
258
+ </div>
259
+ );
260
+ };
@@ -0,0 +1,26 @@
1
+ import { IcPlus } from "@assets/icons/common";
2
+ import ButtonAction from "@components/common/button-action";
3
+
4
+ type Props = {
5
+ text?: string;
6
+ handleCreateOrder?: () => void;
7
+ };
8
+
9
+ export const NoSelectOrder = ({ text, handleCreateOrder }: Props) => {
10
+ return (
11
+ <div className="size-full flex flex-col gap-3 justify-center items-center bg-white">
12
+ <img src="/assets/images/empty-cart.svg" />
13
+ <p className="text-sm font-medium text-text-primary">
14
+ {text ?? "Vui lòng tạo đơn để tiếp tục bán"}
15
+ </p>
16
+ {handleCreateOrder && (
17
+ <ButtonAction
18
+ onClick={() => handleCreateOrder()}
19
+ iconSrc={<IcPlus />}
20
+ text="Tạo đơn"
21
+ className="button-primary h-12 min-w-fit px-3"
22
+ />
23
+ )}
24
+ </div>
25
+ );
26
+ };
@@ -0,0 +1,53 @@
1
+ import { IcCloseCircleFill } from "@assets/icons/common";
2
+ import { IcUserAddFill } from "@assets/icons/user-add-line-icon";
3
+ import ButtonAction from "@components/common/button-action";
4
+ import { useOrderDetail } from "@provider/pos-provider/order-detail-provider";
5
+ import { useOrder } from "@provider/pos-provider/order-provider";
6
+ import { TCustomer } from "@type/customer";
7
+
8
+ type TProps = {
9
+ onOpenChooseCustomerModal: () => void;
10
+ onEditCustomer: ({ customer }: { customer: TCustomer }) => void;
11
+ };
12
+
13
+ const CustomerInfo = ({
14
+ onOpenChooseCustomerModal,
15
+ onEditCustomer,
16
+ }: TProps) => {
17
+ const { customer } = useOrderDetail();
18
+ const { orderDetailById, partnerIdQueryResult, onRemoveCustomer } =
19
+ useOrder();
20
+
21
+ const partnerId = orderDetailById?.partner_id;
22
+ const isGuest = Number(partnerId) === (partnerIdQueryResult?.data || 7);
23
+ const customerName = customer?.name;
24
+ const showAddCustomerIcon = isGuest || !customerName;
25
+
26
+ return (
27
+ <div className="relative">
28
+ <ButtonAction
29
+ onClick={
30
+ !showAddCustomerIcon
31
+ ? () => onEditCustomer({ customer })
32
+ : onOpenChooseCustomerModal
33
+ }
34
+ iconSrc={showAddCustomerIcon ? <IcUserAddFill /> : undefined}
35
+ text={showAddCustomerIcon ? "" : customerName}
36
+ className={`h-11 min-h-11 ${
37
+ showAddCustomerIcon
38
+ ? "w-11 min-w-11 text-text-active"
39
+ : "w-full text-primary"
40
+ } rounded-lg border-[0.5px] border-stroke-disabled bg-white min-w-fit`}
41
+ textClassName="text-sm"
42
+ />
43
+
44
+ {!showAddCustomerIcon && (
45
+ <button onClick={onRemoveCustomer} className="absolute -right-1 -top-1">
46
+ <IcCloseCircleFill />
47
+ </button>
48
+ )}
49
+ </div>
50
+ );
51
+ };
52
+
53
+ export default CustomerInfo;