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,96 @@
1
+ import StarIcon from "@assets/icons/star-icon";
2
+ import useGetPointReward from "@hooks/order/use-get-point-reward";
3
+ import { useOrderDetail } from "@provider/pos-provider/order-detail-provider";
4
+ import { CartItemType } from "@store/states/cart.state";
5
+ import { formatCurrency } from "@utils/functions";
6
+ import { useMemo } from "react";
7
+ import { OrderLineItem } from "./order-line";
8
+
9
+ type TProps = {
10
+ orderDetailData: any;
11
+ cartItemsArr: CartItemType[];
12
+ };
13
+
14
+ const OrderDetailInformation = ({ orderDetailData, cartItemsArr }: TProps) => {
15
+ const orderState = useMemo(() => {
16
+ return orderDetailData?.state;
17
+ }, [orderDetailData]);
18
+
19
+ const amountTotal = useMemo(() => {
20
+ return orderDetailData?.amount_total;
21
+ }, [orderDetailData]);
22
+
23
+ const { pointReward } = useGetPointReward({
24
+ totalAmountWithoutTax: amountTotal,
25
+ });
26
+ const { taxAmount, totalAmount } = useOrderDetail();
27
+
28
+ return (
29
+ <div className="border-r border-stroke-disabled flex h-full flex-col overflow-auto w-full">
30
+ <div className="flex flex-col gap-4 flex-1 p-6 overflow-auto">
31
+ {cartItemsArr.length > 0 ? (
32
+ cartItemsArr?.map((item: CartItemType) => {
33
+ return <OrderLineItem item={item} key={item.lineId?.toString()} />;
34
+ })
35
+ ) : (
36
+ <div className="size-full flex items-center justify-center flex-col gap-3">
37
+ <img
38
+ src="/assets/images/empty-cart.svg"
39
+ alt=""
40
+ className="w-[280px] h-[168px] object-cover"
41
+ />
42
+
43
+ <p className="text-sm font-medium leading-5 tracking-[-0.12px] text-text-primary">
44
+ Đơn hàng không có sản phẩm nào
45
+ </p>
46
+ </div>
47
+ )}
48
+ </div>
49
+
50
+ <div className="border-t border-stroke-soft-200 relative">
51
+ {(orderState === "paid" || orderState === "invoiced") && (
52
+ <img
53
+ src="/assets/images/payment-success-label.png"
54
+ alt=""
55
+ draggable="false"
56
+ className="w-[157px] h-[134px] object-contain absolute bottom-[10px] left-[110px]"
57
+ />
58
+ )}
59
+
60
+ <div className="flex flex-col w-full">
61
+ <div className="flex w-full border-b h-[52px]">
62
+ <div className="border-r flex-[0.7] flex items-center justify-end">
63
+ <p className="text-sm font-medium leading-[18px] text-secondary tracking-[-0.3px] px-[10px]">
64
+ Điểm
65
+ </p>
66
+ </div>
67
+
68
+ <div className="flex-[0.3] flex items-center justify-end">
69
+ <div className="flex items-center gap-1 px-[10px]">
70
+ <StarIcon />
71
+ <p className="font-semibold leading-5 text-text-primary tracking-[-0.26px]">
72
+ {pointReward}
73
+ </p>
74
+ </div>
75
+ </div>
76
+ </div>
77
+
78
+ <div className="flex w-full border-b h-[52px]">
79
+ <div className="border-r flex-[0.7] flex items-center justify-end">
80
+ <p className="text-sm font-medium leading-[18px] text-secondary tracking-[-0.3px] px-[10px]">
81
+ Thành tiền (đã bao gồm VAT)
82
+ </p>
83
+ </div>
84
+ <div className="flex-[0.3] flex items-center justify-end">
85
+ <p className="font-semibold leading-5 text-primary px-[10px]">
86
+ {formatCurrency(taxAmount + totalAmount) || 0}đ
87
+ </p>
88
+ </div>
89
+ </div>
90
+ </div>
91
+ </div>
92
+ </div>
93
+ );
94
+ };
95
+
96
+ export default OrderDetailInformation;
@@ -0,0 +1,84 @@
1
+ import { QUERY_KEYS } from "@constants/query.constant";
2
+ import { useQueryParams } from "@hooks/common/use-query-params";
3
+ import { useKitchen } from "@provider/pos-provider/kitchen-provider";
4
+ import { useOrderDetail } from "@provider/pos-provider/order-detail-provider";
5
+ import { useOrder } from "@provider/pos-provider/order-provider";
6
+ import { CartItemType, useCartStore } from "@store/states/cart.state";
7
+ import { arraysEqual } from "@utils/functions";
8
+ import { useMemo } from "react";
9
+ import { OrderDetailInformation, OrderDetailSummary } from ".";
10
+ import Header from "./header";
11
+
12
+ const OrderDetail = () => {
13
+ const { displayDataQueryResult } = useKitchen();
14
+
15
+ const { items, customer } = useOrderDetail();
16
+ const customerName = customer?.name;
17
+ const { orderDetailById, onGetCurrentUser } = useOrder();
18
+ const { cartItems } = useCartStore();
19
+ const { getQuery, removeParam, updateMultipleQuery } = useQueryParams();
20
+
21
+ const orderId = getQuery(QUERY_KEYS.ORDER_ID);
22
+
23
+ const orderedLine = useMemo(() => {
24
+ const orders = displayDataQueryResult?.data?.orders
25
+ ?.filter((item: any) => item?.pos_order_id === Number(orderId))
26
+ ?.map((item: any) => item.orderlines)
27
+ ?.flat()
28
+ ?.reduce((acc: any, item: any) => {
29
+ if (!acc[item.product_id]) {
30
+ acc[item.product_id] = { ...item };
31
+ } else {
32
+ acc[item.product_id].product_quantity += item.product_quantity;
33
+ acc[item.product_id].product_cancelled += item.product_cancelled;
34
+ }
35
+ return acc;
36
+ }, {});
37
+ return orders;
38
+ }, [displayDataQueryResult, orderId]);
39
+ const cartItemsArr = useMemo(() => {
40
+ const items = Object.values(cartItems);
41
+ return items?.map((item: CartItemType) => {
42
+ const orderLine = orderedLine?.[item.product.id];
43
+ return {
44
+ ...item,
45
+ ordered:
46
+ orderLine?.product_id == item.product.id &&
47
+ orderLine.product_quantity - orderLine.product_cancelled ==
48
+ item.qty &&
49
+ arraysEqual(
50
+ orderLine?.attribute_ids ?? [],
51
+ item?.product?.attributeValueIds ?? []
52
+ ),
53
+ orderedNumber:
54
+ (orderLine?.product_quantity ?? 0) -
55
+ (orderLine?.product_cancelled ?? 0),
56
+ };
57
+ });
58
+ }, [cartItems, orderedLine]);
59
+ return (
60
+ orderDetailById && (
61
+ <div className="bg-white size-full flex flex-col h-screen">
62
+ <div className="w-full border-b border-stroke-disabled">
63
+ <Header orderDetailData={orderDetailById} />
64
+ </div>
65
+
66
+ <div className="flex items-start justify-center flex-1 overflow-y-auto w-full">
67
+ <OrderDetailInformation
68
+ cartItemsArr={cartItemsArr}
69
+ orderDetailData={orderDetailById}
70
+ />
71
+
72
+ <OrderDetailSummary
73
+ orderDetailData={orderDetailById}
74
+ customerName={customerName}
75
+ orderLinesData={items}
76
+ onGetCurrentUser={onGetCurrentUser}
77
+ />
78
+ </div>
79
+ </div>
80
+ )
81
+ );
82
+ };
83
+
84
+ export default OrderDetail;
@@ -0,0 +1,56 @@
1
+ import { CartItemType } from "@store/states/cart.state";
2
+ import { formatCurrency } from "@utils/functions";
3
+ import { useMemo } from "react";
4
+
5
+ export const OrderLineItem = ({ item }: { item: CartItemType }) => {
6
+ const attributeValue = useMemo(() => {
7
+ const pickAttributeValue = item?.product?.pickAttributeValue;
8
+ return pickAttributeValue?.filter((item) => item.value_string?.length > 0);
9
+ }, [item?.product?.pickAttributeValue]);
10
+
11
+ return (
12
+ <div
13
+ key={item.lineId?.toString()}
14
+ className="flex items-start justify-between gap-2"
15
+ >
16
+ <div className="flex items-start gap-4">
17
+ <img
18
+ src={item.product.image_128}
19
+ alt="product image"
20
+ className="w-20 h-20 object-cover rounded-lg border-[0.5px] border-stroke-disabled"
21
+ />
22
+
23
+ <div className="flex flex-col gap-[10px] justify-start">
24
+ <p className="font-medium leading-6 text-text-primary tracking-[-0.24px]">
25
+ {item.product.name}
26
+ </p>
27
+
28
+ {attributeValue &&
29
+ attributeValue?.length > 0 &&
30
+ attributeValue.map((item: any) => (
31
+ <p className="text-xs pt-2 flex gap-1 items-center">
32
+ <span className="text-tertiary font-semibold">
33
+ {item?.name}:{" "}
34
+ </span>
35
+ <span className="font-medium">
36
+ {item?.value_string
37
+ ?.map((item: any) => item?.name)
38
+ .join(", ")}
39
+ </span>
40
+ </p>
41
+ ))}
42
+ </div>
43
+ </div>
44
+
45
+ <div className="flex flex-col gap-[10px]">
46
+ <p className="text-lg font-semibold leading-[26px] text-primary">
47
+ {formatCurrency(item.product.lst_price)}đ
48
+ </p>
49
+
50
+ <p className="text-sm text-end font-medium leading-[18px] text-text-primary">
51
+ x{item.qty}
52
+ </p>
53
+ </div>
54
+ </div>
55
+ );
56
+ };
@@ -0,0 +1,221 @@
1
+ import ButtonAction from "@components/common/button-action";
2
+ import { ORDER_STATE } from "@constants/order-state";
3
+ import { QUERY_KEYS } from "@constants/query.constant";
4
+ import POSPath from "@constants/routes.constants";
5
+ import useGetBillInformation from "@hooks/bill/use-get-bill-information";
6
+ import { useQueryParams } from "@hooks/common/use-query-params";
7
+ import { usePosAppProvider } from "@provider/app-provider";
8
+ import { useOrderDetail } from "@provider/pos-provider/order-detail-provider";
9
+ import { LoadDataModel, useSale } from "@provider/pos-provider/sale-provider";
10
+ import { usePaymentStore } from "@store/states/payment.state";
11
+ import { OrderDetailItemType } from "@type/index";
12
+ import { add7Hours, onFindTable } from "@utils/functions";
13
+ import moment from "moment";
14
+ import { useEffect, useMemo, useState } from "react";
15
+ import { createSearchParams, useNavigate } from "react-router-dom";
16
+ import { toast } from "react-toastify";
17
+
18
+ type TProps = {
19
+ orderDetailData: any;
20
+ customerName: string;
21
+ orderLinesData: OrderDetailItemType[];
22
+ onGetCurrentUser: ({ userId }: { userId: number }) => Promise<any>;
23
+ };
24
+
25
+ const commonKeys = [
26
+ QUERY_KEYS.POS_ID,
27
+ QUERY_KEYS.SESSION_ID,
28
+ QUERY_KEYS.ORDER_ID,
29
+ QUERY_KEYS.TABLE_ID,
30
+ QUERY_KEYS.FLOOR,
31
+ ];
32
+
33
+ const OrderDetailSummary = ({
34
+ orderDetailData,
35
+ customerName,
36
+ orderLinesData,
37
+ onGetCurrentUser,
38
+ }: TProps) => {
39
+ const [cashierName, setCashierName] = useState<string>("");
40
+
41
+ const navigate = useNavigate();
42
+ const { formatQuery } = useQueryParams();
43
+ const { company, userProfile } = usePosAppProvider();
44
+ const { onCreateEInvoice, isEInvoiceCreating } = useOrderDetail();
45
+ const { setShowPayment } = usePaymentStore();
46
+ const { getData, isModePosRestaurant } = useSale();
47
+
48
+ const { brandLogo, addressFormat, paymentMethod, amountTotalWithoutTax } =
49
+ useGetBillInformation();
50
+
51
+ const isOrderCanPrint = useMemo(() => {
52
+ return ![ORDER_STATE.NEW].includes(orderDetailData?.state);
53
+ }, [orderDetailData]);
54
+
55
+ const isInPaidOrder = useMemo(() => {
56
+ return orderDetailData?.state === ORDER_STATE.IN_PAID;
57
+ }, [orderDetailData]);
58
+
59
+ const isOrderCanExportEInvoice = useMemo(() => {
60
+ return orderDetailData?.state === ORDER_STATE.PAID;
61
+ }, [orderDetailData]);
62
+
63
+ const floors = getData(LoadDataModel.RESTAURANT_FLOOR);
64
+ const tables = getData(LoadDataModel.RESTAURANT_TABLE);
65
+
66
+ const onAddDish = () => {
67
+ navigate({
68
+ pathname: POSPath.MENUS,
69
+ search: formatQuery(commonKeys).toString(),
70
+ });
71
+ };
72
+
73
+ const handlePrintBillByText = async () => {
74
+ return toast.info("Tính năng không hỗ trợ trên website");
75
+ };
76
+
77
+ const onPayment = () => {
78
+ const tableMatched = tables?.find(
79
+ (table: any) => table.id === orderDetailData?.table_id
80
+ );
81
+ const floorMatched = floors?.find(
82
+ (floor: any) => floor.id === tableMatched?.floor_id
83
+ );
84
+ setShowPayment(true);
85
+ navigate({
86
+ pathname: POSPath.MENUS,
87
+ search: `${formatQuery([
88
+ QUERY_KEYS.POS_ID,
89
+ QUERY_KEYS.SESSION_ID,
90
+ ])}&${createSearchParams({
91
+ [QUERY_KEYS.ORDER_ID]: orderDetailData?.id.toString(),
92
+ [QUERY_KEYS.TABLE_ID]: tableMatched.id.toString(),
93
+ [QUERY_KEYS.FLOOR]: floorMatched.id.toString(),
94
+ })}`,
95
+ });
96
+ };
97
+
98
+ useEffect(() => {
99
+ if (!orderDetailData) return;
100
+
101
+ const onFindCustomer = async () => {
102
+ const cashierName = await onGetCurrentUser({
103
+ userId: orderDetailData?.user_id,
104
+ });
105
+
106
+ setCashierName(cashierName);
107
+ };
108
+
109
+ onFindCustomer();
110
+ }, [orderDetailData?.user_id]);
111
+
112
+ return (
113
+ <div className="min-w-[35%] w-[35%] p-6 flex flex-col gap-4 size-full">
114
+ <p className="font-semibold leading-6 text-text-primary tracking-[-0.24px]">
115
+ Chi tiết đơn hàng
116
+ </p>
117
+
118
+ <div className="flex flex-col gap-1 flex-1">
119
+ {[
120
+ {
121
+ label: "Mã đơn hàng",
122
+ value: orderDetailData?.pos_reference,
123
+ },
124
+ {
125
+ label: "Số đơn hàng",
126
+ value: orderDetailData?.id,
127
+ },
128
+ {
129
+ label: "Mã tra cứu HĐĐT",
130
+ value: orderDetailData?.e_invoice_search_code,
131
+ },
132
+ {
133
+ label: "Bàn",
134
+ value: isModePosRestaurant
135
+ ? onFindTable({
136
+ order: orderDetailData,
137
+ tables,
138
+ floors,
139
+ })
140
+ : undefined,
141
+ },
142
+ {
143
+ label: "Thời gian tạo",
144
+ value: moment(add7Hours(orderDetailData?.date_order)).format(
145
+ "DD/MM/YYYY HH:mm:ss"
146
+ ),
147
+ },
148
+ {
149
+ label: "Khách hàng",
150
+ value: customerName,
151
+ },
152
+ {
153
+ label: "Phương thức thanh toán",
154
+ value: paymentMethod || "Chưa xác định",
155
+ },
156
+ {
157
+ label: "Nhân viên",
158
+ value: cashierName,
159
+ },
160
+ ]
161
+ .filter((item) => item.value)
162
+ .map((item, index) => (
163
+ <div
164
+ key={index}
165
+ className={`flex items-center justify-between rounded-lg px-2 py-[10px] ${
166
+ index % 2 !== 0 ? "bg-neutral-100-96" : "bg-white"
167
+ }`}
168
+ >
169
+ <p className="text-sm flex-1 font-medium leading-5 tracking-[-0.12px]">
170
+ {item.label}
171
+ </p>
172
+
173
+ <p className="text-sm flex-1 text-end font-semibold text-text-primary leading-5 tracking-[-0.12px]">
174
+ {item.value}
175
+ </p>
176
+ </div>
177
+ ))}
178
+ </div>
179
+
180
+ <div className="flex flex-col gap-2">
181
+ {orderDetailData?.state === ORDER_STATE.NEW && (
182
+ <ButtonAction onClick={onAddDish} className="button-primary">
183
+ Thêm món
184
+ </ButtonAction>
185
+ )}
186
+
187
+ {isOrderCanPrint && (
188
+ <button
189
+ style={{
190
+ boxShadow: "0 1px 2px 0 rgba(228, 229, 231, 0.24)",
191
+ }}
192
+ onClick={handlePrintBillByText}
193
+ className="rounded-lg border border-stroke-disabled bg-white px-3 py-[6px] h-12"
194
+ >
195
+ <span className="text-sm font-semibold leading-5 tracking-[-0.12px] text-text-primary">
196
+ {isInPaidOrder ? "In phiếu tạm tính" : "In đơn hàng"}
197
+ </span>
198
+ </button>
199
+ )}
200
+
201
+ {isOrderCanExportEInvoice && (
202
+ <ButtonAction
203
+ onClick={onCreateEInvoice}
204
+ disabled={isEInvoiceCreating}
205
+ className="button-primary"
206
+ >
207
+ Xuất hoá đơn
208
+ </ButtonAction>
209
+ )}
210
+
211
+ {orderDetailData?.state === ORDER_STATE.IN_PAID && (
212
+ <ButtonAction onClick={onPayment} className="button-primary">
213
+ Thanh toán
214
+ </ButtonAction>
215
+ )}
216
+ </div>
217
+ </div>
218
+ );
219
+ };
220
+
221
+ export default OrderDetailSummary;
@@ -0,0 +1,113 @@
1
+ import { IcSearch } from "@assets/icons/breadcrumbs-icon";
2
+ import { IcCheckFill } from "@assets/icons/common";
3
+ import { ButtonIcon } from "@components/common/button-icon";
4
+ import DropdownSelector from "@components/common/dropdown";
5
+ import RefreshButton from "@components/common/refresh-button";
6
+ import { TabsLayout } from "@components/common/tabs-layout";
7
+ import Search from "@components/pos-management/search";
8
+ import { ORDER_STATE } from "@constants/order-state";
9
+ import { useState } from "react";
10
+ import { OrderTab } from ".";
11
+
12
+ type TProps = {
13
+ onRefreshOrder: () => void;
14
+ searchValue: string;
15
+ setSearchValue: (value: string) => void;
16
+ onStatusChange: (value: ORDER_STATE) => void;
17
+ selectedStatus: string;
18
+ activeTab: string;
19
+ onActiveTabChange: (tab: string) => void;
20
+ };
21
+
22
+ const statusOptions: { key: ORDER_STATE; label: string }[] = [
23
+ { key: ORDER_STATE.ALL, label: "Tất cả" },
24
+ { key: ORDER_STATE.NEW, label: "Mới" },
25
+ { key: ORDER_STATE.CANCEL, label: "Đã huỷ" },
26
+ { key: ORDER_STATE.PAID, label: "Đã thanh toán" },
27
+ { key: ORDER_STATE.IN_PAID, label: "Đang thanh toán" },
28
+ { key: ORDER_STATE.INVOICED, label: "Đã xuất hóa đơn" },
29
+ ];
30
+ const OrderHeader = ({
31
+ onRefreshOrder,
32
+ searchValue,
33
+ setSearchValue,
34
+ onStatusChange,
35
+ activeTab,
36
+ onActiveTabChange,
37
+ selectedStatus,
38
+ }: TProps) => {
39
+ const currentStatus = statusOptions.find((s) => s.key === selectedStatus)!;
40
+ const [isSearchMode, setIsSearchMode] = useState(false);
41
+
42
+ return (
43
+ <div className="sticky top-0 z-[9999] items-center flex justify-between gap-3">
44
+ {isSearchMode ? (
45
+ <Search
46
+ placeholder="Tìm kiếm đơn hàng"
47
+ searchValue={searchValue}
48
+ onSearchChange={setSearchValue}
49
+ onClose={() => setIsSearchMode(false)}
50
+ isNumericMode={false}
51
+ />
52
+ ) : (
53
+ <div className="flex-1">
54
+ <TabsLayout
55
+ tabs={[
56
+ { id: OrderTab.ALL, name: "Tất cả" },
57
+ { id: OrderTab.AT_TABLE, name: "Tại bàn" },
58
+ { id: OrderTab.TAKE_AWAY, name: "Mang đi" },
59
+ ]}
60
+ queryKey="orderType"
61
+ activeValue={activeTab}
62
+ onClick={(tab: any) => onActiveTabChange(tab.id)}
63
+ rightButton={
64
+ <div className="flex items-center gap-4">
65
+ <ButtonIcon
66
+ iconSrc={<IcSearch />}
67
+ onClick={() => setIsSearchMode(true)}
68
+ />
69
+ <DropdownSelector
70
+ options={statusOptions}
71
+ selectedValue={{
72
+ label: currentStatus?.label,
73
+ }}
74
+ onSelect={(opt) => {
75
+ onStatusChange(opt.key);
76
+ }}
77
+ renderItem={(opt) => (
78
+ <>
79
+ <div className="flex justify-between" key={opt.key}>
80
+ <button
81
+ onClick={() => {
82
+ onStatusChange(opt.key);
83
+ }}
84
+ className={`w-full gap-2 px-2 py-[6px] flex items-center justify-between text-sm rounded-md ${
85
+ selectedStatus === opt.key
86
+ ? "bg-gray-100 text-primary font-medium"
87
+ : "hover:bg-gray-50 text-text-primary"
88
+ }`}
89
+ >
90
+ <span className="font-normal">{opt.label}</span>
91
+ {selectedStatus === opt.key && <IcCheckFill />}
92
+ </button>
93
+ </div>
94
+ {opt.key === "all" && (
95
+ <div className="border-t border-gray-200 mt-2" />
96
+ )}
97
+ </>
98
+ )}
99
+ buttonClassName="flex items-center justify-between gap-2 px-3 py-2 bg-white border border-gray-300 rounded-lg text-sm text-text-primary hover:bg-gray-50 focus:outline-none focus:ring-2 h-11 w-[170px]"
100
+ dropdownClassName="w-[170px] top-[calc(100%_+_4px)] p-2 flex flex-col gap-1"
101
+ />
102
+ <RefreshButton onRefresh={onRefreshOrder} />
103
+ </div>
104
+ }
105
+ className="h-[56px]"
106
+ />
107
+ </div>
108
+ )}
109
+ </div>
110
+ );
111
+ };
112
+
113
+ export default OrderHeader;
@@ -0,0 +1,49 @@
1
+ import DropdownSelector from "@components/common/dropdown";
2
+ import { Pagination } from "@components/common/pagination";
3
+
4
+ type TProps = {
5
+ page: number;
6
+ setPage: (page: number) => void;
7
+ pageSize: number;
8
+ setPageSize: (pageSize: number) => void;
9
+ totalPages: number;
10
+ };
11
+
12
+ const OrderPagination = ({
13
+ page,
14
+ setPage,
15
+ pageSize,
16
+ setPageSize,
17
+ totalPages,
18
+ }: TProps) => {
19
+ const options = [10, 20, 50, 100];
20
+ return (
21
+ <div className="flex justify-between items-center py-2">
22
+ <div />
23
+ <Pagination page={page} totalPages={totalPages} onPageChange={setPage} />
24
+ <div className="flex items-center text-sm text-gray-600 mr-4 gap-3">
25
+ <span>Số dòng</span>
26
+ <DropdownSelector<number>
27
+ options={options}
28
+ selectedValue={{
29
+ label: pageSize.toString(),
30
+ }}
31
+ onSelect={(value) => setPageSize(value)}
32
+ renderItem={(item) => (
33
+ <div
34
+ className={`px-3 py-2 text-sm hover:bg-gray-50 ${
35
+ pageSize === item ? "bg-gray-100 text-primary font-medium" : ""
36
+ }`}
37
+ >
38
+ {item}
39
+ </div>
40
+ )}
41
+ buttonClassName="px-2 py-1 border border-gray-300 rounded-md text-gray-700 bg-white w-[60px] flex justify-between items-center"
42
+ dropdownClassName="w-[60px] bottom-10"
43
+ />
44
+ </div>
45
+ </div>
46
+ );
47
+ };
48
+
49
+ export default OrderPagination;
@@ -0,0 +1,58 @@
1
+ import { ORDER_STATE } from "@constants/order-state";
2
+ import { useTranslation } from "react-i18next";
3
+
4
+ const STATUS = [
5
+ {
6
+ id: 1,
7
+ value: ORDER_STATE.NEW,
8
+ color: "#F6B51E",
9
+ background: "#FFFAEB",
10
+ },
11
+ {
12
+ id: 2,
13
+ value: ORDER_STATE.PAID,
14
+ color: "#1FC163",
15
+ background: "#E0FAEB",
16
+ },
17
+ {
18
+ id: 3,
19
+ value: ORDER_STATE.INVOICED,
20
+ color: "#35ADE9",
21
+ background: "#EBF1FF",
22
+ },
23
+ {
24
+ id: 4,
25
+ value: ORDER_STATE.CANCEL,
26
+ color: "#FB2B3D",
27
+ background: "#FFEBEC",
28
+ },
29
+ {
30
+ id: 5,
31
+ value: ORDER_STATE.IN_PAID,
32
+ color: "#1FC163",
33
+ background: "#E0FAEB",
34
+ },
35
+ ];
36
+
37
+ const OrderStatus = ({ status }: { status: string }) => {
38
+ const { t } = useTranslation();
39
+ const currentStatus = STATUS.find((item) => {
40
+ return item.value === status;
41
+ });
42
+ return (
43
+ <div
44
+ style={{
45
+ borderColor: currentStatus?.color,
46
+ backgroundColor: currentStatus?.background,
47
+ color: currentStatus?.color,
48
+ }}
49
+ className="px-2 py-1 rounded border w-fit"
50
+ >
51
+ <p className="text-xs font-medium leading-4">
52
+ {t(currentStatus?.value || "")}
53
+ </p>
54
+ </div>
55
+ );
56
+ };
57
+
58
+ export default OrderStatus;