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,179 @@
1
+ import { IcPlus, IcTrash } from "@assets/icons/common";
2
+ import DiningTableIcon from "@assets/icons/dining-table";
3
+ import EditLineIcon from "@assets/icons/edit-line-icon";
4
+ import ButtonAction from "@components/common/button-action";
5
+ import { ButtonIcon } from "@components/common/button-icon";
6
+ import { AddTableModal } from "@components/restaurant-management/add-table-modal";
7
+ import DeleteTableConfirmModal from "@components/restaurant-management/delete-table-confirm-modal";
8
+ import { LayerLoading } from "@fctc/sme-widget-ui";
9
+ import useGetLoadPosSession from "@provider/pos-provider/sale-provider";
10
+ import { usePosTable } from "@provider/pos-provider/table-provider";
11
+ import { TFloor } from "@type/floor/floor";
12
+ import { TBasicTable } from "@type/table";
13
+ import { useMemo, useState } from "react";
14
+ import { toast } from "react-toastify";
15
+ import DeleteFloorConfirmModal from "./delete-floor-confirm-modal";
16
+ import TableEmpty from "./table-empty";
17
+
18
+ type TProps = {
19
+ activeFloor: TFloor | undefined;
20
+ setIsOpenAddFloor: (isOpen: boolean) => void;
21
+ isOpenAddFloor: boolean;
22
+ setIsEditingFloor?: (val: number | undefined) => void;
23
+ };
24
+
25
+ const RightSide = ({
26
+ activeFloor,
27
+ setIsOpenAddFloor,
28
+ setIsEditingFloor,
29
+ }: TProps) => {
30
+ const [isOpenAddModal, setIsOpenAddModal] = useState(false);
31
+ const [tableSelected, setTableSelected] = useState<TBasicTable | undefined>(
32
+ undefined
33
+ );
34
+ const [openDeleteConfirmModal, setOpenDeleteConfirmModal] = useState(false);
35
+ const [isOpenDeleteTable, setIsOpenDeleteTable] = useState(false);
36
+ const { tablesByFloor, mapTablesWithOrder } = usePosTable();
37
+
38
+ const { queryResult: getLoadPosSessionQueryResult, getData } =
39
+ useGetLoadPosSession();
40
+
41
+ const onOpenAddTable = () => {
42
+ setIsOpenAddModal(true);
43
+ };
44
+
45
+ const isFloorHaveTableContainOrder = useMemo(() => {
46
+ return mapTablesWithOrder.some((table) => table?.currentOrder);
47
+ }, [mapTablesWithOrder]);
48
+
49
+ const handleDeleteFloor = () => {
50
+ if (isFloorHaveTableContainOrder) {
51
+ toast.error("Tầng đang có đơn hàng");
52
+ } else {
53
+ setOpenDeleteConfirmModal(true);
54
+ }
55
+ };
56
+
57
+ if (!activeFloor) {
58
+ return (
59
+ <div className="font-medium text-strong-950 leading-[26px] flex-1 bg-neutral-100-96 p-4">
60
+ Chưa có tầng nào được chọn
61
+ </div>
62
+ );
63
+ }
64
+
65
+ return getLoadPosSessionQueryResult.isPending ? (
66
+ <div className="flex-1 bg-neutral-100-96">
67
+ <LayerLoading />
68
+ </div>
69
+ ) : (
70
+ <div className="flex-1 p-4 flex flex-col gap-4 bg-neutral-100-96">
71
+ <div className="flex items-center justify-between">
72
+ <div className="flex items-center gap-4">
73
+ <p className="text-lg font-semibold leading-[26px] text-strong-950">
74
+ {activeFloor?.name}
75
+ </p>
76
+ <ButtonIcon
77
+ iconSrc={<EditLineIcon />}
78
+ onClick={() => {
79
+ setIsOpenAddFloor(true);
80
+ setIsEditingFloor && setIsEditingFloor(activeFloor.id);
81
+ }}
82
+ className="bg-inherit border-none shadow-none rounded-lg text-text-primary"
83
+ />
84
+ <ButtonIcon
85
+ iconSrc={<IcTrash />}
86
+ onClick={handleDeleteFloor}
87
+ className="bg-inherit border-none shadow-none rounded-lg text-state-error-base"
88
+ />
89
+ </div>
90
+
91
+ <ButtonAction
92
+ iconSrc={<IcPlus />}
93
+ onClick={onOpenAddTable}
94
+ className="button-primary"
95
+ text=" Thêm bàn"
96
+ />
97
+ </div>
98
+
99
+ {tablesByFloor.length ? (
100
+ <div className="grid gap-3 grid-cols-[repeat(auto-fill,minmax(178px,1fr))]">
101
+ {tablesByFloor?.map((table: TBasicTable) => (
102
+ <FloorItem
103
+ key={table.id}
104
+ table={table}
105
+ onTableSelected={setTableSelected}
106
+ onOpenAddTable={onOpenAddTable}
107
+ />
108
+ ))}
109
+ </div>
110
+ ) : (
111
+ <TableEmpty onOpenAddTable={onOpenAddTable} showAddTableAction />
112
+ )}
113
+
114
+ <AddTableModal
115
+ isOpen={isOpenAddModal}
116
+ onClose={() => setIsOpenAddModal(false)}
117
+ tableSelected={tableSelected}
118
+ editMode={Boolean(tableSelected)}
119
+ onOpenDeleteConfirmModal={() => setIsOpenDeleteTable(true)}
120
+ onTableSelected={setTableSelected}
121
+ />
122
+
123
+ <DeleteFloorConfirmModal
124
+ isOpen={openDeleteConfirmModal}
125
+ onClose={() => setOpenDeleteConfirmModal(false)}
126
+ floorId={activeFloor.id}
127
+ floorName={activeFloor.name}
128
+ />
129
+
130
+ <DeleteTableConfirmModal
131
+ isOpen={isOpenDeleteTable}
132
+ onClose={() => setIsOpenDeleteTable(false)}
133
+ tableSelected={tableSelected}
134
+ />
135
+ </div>
136
+ );
137
+ };
138
+
139
+ export default RightSide;
140
+
141
+ const FloorItem = ({
142
+ table,
143
+ onTableSelected,
144
+ onOpenAddTable,
145
+ }: {
146
+ table: TBasicTable;
147
+ onTableSelected: (table: TBasicTable) => void;
148
+ onOpenAddTable: () => void;
149
+ }) => {
150
+ return (
151
+ <div className="rounded-xl border border-primary-sub bg-white flex flex-col gap-2 items-center justify-center px-3 h-[100px]">
152
+ <div className="flex items-center justify-between w-full">
153
+ <p className="rounded-full text-text-primary font-semibold leading-6 tracking-[-0.24px]">
154
+ Bàn {table.table_number}
155
+ {/* TODO */}
156
+ </p>
157
+
158
+ <button
159
+ onClick={() => {
160
+ onOpenAddTable();
161
+ onTableSelected({
162
+ ...table,
163
+ });
164
+ }}
165
+ className="size-10 flex items-center justify-center text-neutral-400-68"
166
+ >
167
+ <EditLineIcon />
168
+ </button>
169
+ </div>
170
+
171
+ <div className="flex items-center justify-start w-full gap-1 text-colored-primary">
172
+ <DiningTableIcon />
173
+ <p className="font-semibold leading-6 tracking-[-0.24px]">
174
+ {table.seats}
175
+ </p>
176
+ </div>
177
+ </div>
178
+ );
179
+ };
@@ -0,0 +1,43 @@
1
+ import { IcPlus } from "@assets/icons/common";
2
+ import ButtonAction from "@components/common/button-action";
3
+ import Image from "@components/common/image";
4
+ import { useTranslation } from "react-i18next";
5
+
6
+ type TProps = {
7
+ showAddTableAction?: boolean;
8
+ onOpenAddTable?: () => void;
9
+ keyString?: string;
10
+ };
11
+
12
+ const TableEmpty = ({
13
+ onOpenAddTable,
14
+ showAddTableAction = false,
15
+ keyString,
16
+ }: TProps) => {
17
+ const { t } = useTranslation();
18
+ return (
19
+ <div className="flex flex-col gap-4 items-center justify-center h-full">
20
+ <Image
21
+ imageUrl="/assets/images/table-empty.png"
22
+ className="w-[136px] h-[106px]"
23
+ />
24
+
25
+ <div className="flex flex-col gap-2 items-center justify-center">
26
+ <p className="text-2xl font-semibold leading-8 text-text-primary tracking-[-0.24px]">
27
+ {t("no_table")} {keyString}
28
+ </p>
29
+ </div>
30
+
31
+ {showAddTableAction && (
32
+ <ButtonAction
33
+ text={t("create_table")}
34
+ iconSrc={<IcPlus />}
35
+ onClick={onOpenAddTable}
36
+ className="button-secondary bg-white"
37
+ />
38
+ )}
39
+ </div>
40
+ );
41
+ };
42
+
43
+ export default TableEmpty;
@@ -0,0 +1,45 @@
1
+ import ButtonAction from "@components/common/button-action";
2
+ import { useSessionStore } from "@store/session";
3
+ import { cn } from "@utils/functions";
4
+ import { useTranslation } from "react-i18next";
5
+
6
+ type TActionsProps = {
7
+ onContinue: () => void;
8
+ onClose?: () => void;
9
+ buttonLabel?: string;
10
+ isDisabled?: boolean;
11
+ className?: string;
12
+ };
13
+
14
+ const Actions = (props: TActionsProps) => {
15
+ const { onContinue, onClose, buttonLabel, isDisabled, className } = props;
16
+ const { setStep } = useSessionStore();
17
+ const { t } = useTranslation();
18
+
19
+ const handleClose = () => (onClose ? onClose() : setStep(0));
20
+
21
+ return (
22
+ <div
23
+ className={cn(
24
+ "flex pt-6 bg-white flex-col gap-2 w-full justify-center",
25
+ className
26
+ )}
27
+ {...props}
28
+ >
29
+ <ButtonAction
30
+ disabled={isDisabled}
31
+ onClick={onContinue}
32
+ text={buttonLabel}
33
+ className="button-primary w-full"
34
+ />
35
+
36
+ <ButtonAction
37
+ onClick={handleClose}
38
+ text={t("cancel")}
39
+ className="button-secondary w-full"
40
+ />
41
+ </div>
42
+ );
43
+ };
44
+
45
+ export default Actions;
@@ -0,0 +1,157 @@
1
+ import { QUERY_KEYS } from "@constants/query.constant";
2
+ import { useGetBase64Photo } from "@hooks/common/use-get-base64-photo";
3
+ import useGetQuery from "@hooks/common/use-get-query";
4
+ import { useQueryParams } from "@hooks/common/use-query-params";
5
+ import { usePosAppProvider } from "@provider/app-provider";
6
+ import { useCloseSession } from "@provider/pos-provider/close-session-provider";
7
+ import { LoadDataModel, useSale } from "@provider/pos-provider/sale-provider";
8
+ import { useSessionStore } from "@store/session";
9
+ import { useMemo, useRef, useState } from "react";
10
+ import { useTranslation } from "react-i18next";
11
+ import { useNavigate } from "react-router-dom";
12
+ import { toast } from "react-toastify";
13
+ import Actions from "./actions";
14
+ import CloseSessionModalContainer from "./container";
15
+
16
+ type TProps = {
17
+ posName: string;
18
+ };
19
+
20
+ export const CloseSessionConfirm = ({ posName }: TProps) => {
21
+ const { t } = useTranslation();
22
+ const navigate = useNavigate();
23
+ const { getData } = useSale();
24
+ const posSessionData = getData(LoadDataModel.POS_SESSION);
25
+
26
+ const { setStep, sessionConfirmParams } = useSessionStore();
27
+ const { removeParam } = useQueryParams();
28
+ const { user: userData, company } = usePosAppProvider();
29
+ const { data: brandLogo } = useGetBase64Photo(
30
+ company?.companyInfo.data[0]?.logo
31
+ );
32
+ const { posId } = useGetQuery();
33
+ const ref = useRef<HTMLDivElement>(null);
34
+
35
+ const {
36
+ getDataCloseSessionQuery: { data: dataCloseSession },
37
+ closeSession,
38
+ } = useCloseSession();
39
+
40
+ // const {
41
+ // getPosQueryResult: { data: posDetailInfo },
42
+ // } = usePosTableProvider();
43
+
44
+ const posDetailInfo = getData(LoadDataModel.POS_CONFIG);
45
+
46
+ const [isClosing, setIsClosing] = useState(false);
47
+
48
+ const onContinue = async () => {
49
+ try {
50
+ setIsClosing(true);
51
+ await closeSession({
52
+ countedCash: sessionConfirmParams.cashCount,
53
+ notes: sessionConfirmParams.note,
54
+ });
55
+ setIsClosing(false);
56
+ setStep(0);
57
+ navigate(
58
+ `/console${
59
+ sessionStorage.getItem("enter_pincode") ??
60
+ localStorage.getItem("backUrl")
61
+ }`
62
+ );
63
+ } catch (e: any) {
64
+ toast.error(e?.message);
65
+ console.log("error", e);
66
+ }
67
+ };
68
+
69
+ const handleClose = () => {
70
+ setStep(0);
71
+ removeParam([QUERY_KEYS.OPEN]);
72
+ };
73
+
74
+ // const handlePrintBase64 = async (imgSrc: string) => {
75
+ // if (!imgSrc) return
76
+ // try {
77
+ // await UsbPrinter.connect()
78
+ // await UsbPrinter.printBase64({
79
+ // data: imgSrc,
80
+ // })
81
+
82
+ // await UsbPrinter.disconnect()
83
+ // } catch (e) {
84
+ // console.error("USB Print failed:", e)
85
+ // }
86
+ // }
87
+
88
+ const cashDifference = useMemo(() => {
89
+ const totalAmount = dataCloseSession?.default_cash_details?.amount || 0;
90
+ const totalCash = sessionConfirmParams.cashCount || 0;
91
+ return totalAmount - totalCash;
92
+ }, [dataCloseSession, sessionConfirmParams]);
93
+
94
+ const handlePrintText = async () => {
95
+ // if (!isAndroid) return;
96
+ // try {
97
+ // await UsbPrinter.connect();
98
+ // const cleanBase64 = brandLogo?.replace(
99
+ // /^data:image\/[a-zA-Z]+;base64,/,
100
+ // ""
101
+ // );
102
+ // await UsbPrinter.disconnect();
103
+ // const textBill = await generateTextShift({
104
+ // sessionConfirmParams,
105
+ // userData,
106
+ // posId,
107
+ // dataCloseSession,
108
+ // posDetailInfo,
109
+ // cashDifference,
110
+ // company,
111
+ // openAt: posSessionData?.[0]?.start_at,
112
+ // });
113
+ // await UsbPrinter.printText({
114
+ // text: textBill,
115
+ // logoBase64: cleanBase64,
116
+ // });
117
+ // await UsbPrinter.disconnect();
118
+ // } catch (e) {
119
+ // toast.error(`USB Print failed: ${e}`);
120
+ // }
121
+ };
122
+
123
+ return (
124
+ <CloseSessionModalContainer
125
+ isOpen={true}
126
+ onClose={handleClose}
127
+ title={t("confirm_close_session_title")}
128
+ >
129
+ <div className="flex flex-col h-full relative overflow-auto gap-3">
130
+ <div className="flex flex-col gap-1 flex-1">
131
+ <p className="text-text-primary text-lg font-semibold leading-[26px]">
132
+ {t("confirm_close_session", { sessionId: posName })}
133
+ </p>
134
+ <p className="text-text-secondary text-sm leading-5 tracking-[-0.12px]">
135
+ {t("check_session_info_before_closing")}
136
+ </p>
137
+ </div>
138
+
139
+ {/* <div className="overflow-auto hide-scrollbar">
140
+ <div ref={ref}>
141
+ <CloseSessionTicket />
142
+ </div>
143
+ </div> */}
144
+
145
+ <Actions
146
+ isDisabled={isClosing}
147
+ onContinue={async () => {
148
+ onContinue();
149
+ handlePrintText();
150
+ }}
151
+ buttonLabel={isClosing ? t("is_closing") : t("yes_button")}
152
+ className="flex flex-row-reverse items-center gap-2 w-full pt-6 sticky bottom-0 bg-white"
153
+ />
154
+ </div>
155
+ </CloseSessionModalContainer>
156
+ );
157
+ };
@@ -0,0 +1,218 @@
1
+ import { useGetBase64Photo } from "@hooks/common/use-get-base64-photo";
2
+ import useGetQuery from "@hooks/common/use-get-query";
3
+ import { usePosAppProvider } from "@provider/app-provider";
4
+ import { useCloseSession } from "@provider/pos-provider/close-session-provider";
5
+ import { LoadDataModel, useSale } from "@provider/pos-provider/sale-provider";
6
+ import { useSessionStore } from "@store/session";
7
+ import { formatCurrency, getDate, hh_mm_dd_mm_yyyy } from "@utils/functions";
8
+ import { useMemo } from "react";
9
+
10
+ const CloseSessionTicket = () => {
11
+ const { posId } = useGetQuery();
12
+ const { getData } = useSale();
13
+ const { sessionConfirmParams } = useSessionStore();
14
+ const { user: userData } = usePosAppProvider();
15
+ const user = userData?.userProfile?.data;
16
+ const company = useMemo(() => user?.company, [user]);
17
+ const address = useMemo(() => user?.company?.address, [user?.company]);
18
+ const addressFormat = useMemo(() => {
19
+ return `${address?.street ?? ""} ${address?.street2 ?? ""}, ${
20
+ address?.ward ?? ""
21
+ }, Tỉnh ${address?.state ?? ""}`;
22
+ }, [address]);
23
+
24
+ const { data: brandLogo } = useGetBase64Photo(company?.logo);
25
+
26
+ const {
27
+ getDataCloseSessionQuery: { data: dataCloseSession },
28
+ } = useCloseSession();
29
+
30
+ const posDetailInfo = getData(LoadDataModel.POS_CONFIG);
31
+
32
+ const currentPos = posDetailInfo?.records?.find(
33
+ (item: any) => item.id === Number(posId)
34
+ );
35
+
36
+ const date = getDate(new Date());
37
+
38
+ const cashDifference = useMemo(() => {
39
+ const totalAmount = dataCloseSession?.default_cash_details?.amount || 0;
40
+ const totalCash = sessionConfirmParams.cashCount || 0;
41
+ return totalAmount - totalCash;
42
+ }, [dataCloseSession, sessionConfirmParams]);
43
+
44
+ return (
45
+ <div className="inline-flex w-full flex-col items-center gap-3 rounded-2xl bg-white">
46
+ <div className="flex flex-col items-center justify-center gap-2 self-stretch">
47
+ {brandLogo && <img className="w-[20%]" src={brandLogo} />}
48
+ <div className="flex flex-col items-center justify-center gap-2 self-stretch font-normal text-strong-950">
49
+ <div className="text-xs font-semibold">{company?.invoice_name}</div>
50
+ <div className="text-[10px]">{addressFormat}</div>
51
+ </div>
52
+ </div>
53
+
54
+ <div className="flex flex-col items-start justify-start gap-2 self-stretch">
55
+ <div className="flex flex-col items-center justify-center gap-1 self-stretch">
56
+ <div className="text-center text-xs font-bold leading-7 text-strong-950">
57
+ PHIẾU GIAO CA
58
+ </div>
59
+ {[
60
+ [
61
+ {
62
+ title: "Mã ca / Quầy",
63
+ value: [
64
+ currentPos?.current_session_id?.display_name,
65
+ currentPos?.name,
66
+ ].join(" / "),
67
+ },
68
+ undefined,
69
+ {
70
+ title: "Nhân viên",
71
+ value: currentPos?.current_user_id?.display_name,
72
+ },
73
+ ],
74
+ [
75
+ { title: "Giờ mở ca", value: hh_mm_dd_mm_yyyy(new Date()) },
76
+ undefined,
77
+ { title: "Giờ đóng ca", value: hh_mm_dd_mm_yyyy(new Date()) },
78
+ ],
79
+ ].map((row, i) => (
80
+ <div
81
+ key={i}
82
+ className="flex w-full items-stretch gap-2 text-[10px] font-normal text-strong-950"
83
+ >
84
+ {row.map((cell, idx) => {
85
+ if (!cell)
86
+ return (
87
+ <div key={idx} className="w-[1.5px] bg-soft-400"></div>
88
+ );
89
+ return (
90
+ <div
91
+ key={cell.title}
92
+ className="flex flex-1 items-center gap-1"
93
+ >
94
+ <div>{cell.title}:</div>
95
+ <div className="font-medium">{cell.value}</div>
96
+ </div>
97
+ );
98
+ })}
99
+ </div>
100
+ ))}
101
+ </div>
102
+
103
+ <div className="h-[1px] bg-soft-400"></div>
104
+
105
+ <div className="inline-flex self-stretch text-xs font-semibold text-strong-950">
106
+ <div className="flex-1">Tiền mặt đầu ca (1)</div>
107
+ <div>
108
+ {formatCurrency(dataCloseSession?.default_cash_details?.opening) ||
109
+ 0}
110
+ đ
111
+ </div>
112
+ </div>
113
+
114
+ <div className="h-[1px] bg-soft-400"></div>
115
+
116
+ {[
117
+ {
118
+ title: "Tiền mặt trong ca (2)",
119
+ value: `${
120
+ formatCurrency(
121
+ dataCloseSession?.default_cash_details?.payment_amount
122
+ ) || 0
123
+ }đ`,
124
+ items: [
125
+ {
126
+ title: "Bán hàng",
127
+ value: `${
128
+ formatCurrency(
129
+ dataCloseSession?.default_cash_details?.payment_amount
130
+ ) || 0
131
+ }đ`,
132
+ },
133
+ ],
134
+ },
135
+ undefined,
136
+ {
137
+ title: "Tiền mặt cuối ca (3)=(1)+(2)",
138
+ value: `${
139
+ formatCurrency(dataCloseSession?.default_cash_details?.amount) ||
140
+ 0
141
+ }đ`,
142
+ items: [
143
+ {
144
+ title: "Tiền mặt bàn giao thực tế",
145
+ value: `${
146
+ formatCurrency(sessionConfirmParams.cashCount) || 0
147
+ }đ`,
148
+ },
149
+ {
150
+ title: "Số tiền chênh lệch",
151
+ value: `${formatCurrency(cashDifference) || 0}đ`,
152
+ },
153
+ ],
154
+ },
155
+ undefined,
156
+ {
157
+ title: "Phương thức thanh toán khác",
158
+ value: `${
159
+ formatCurrency(
160
+ dataCloseSession?.non_cash_payment_methods?.reduce(
161
+ (a: number, b: any) => a + (b?.amount || 0),
162
+ 0
163
+ )
164
+ ) || 0
165
+ }đ`,
166
+ items:
167
+ dataCloseSession?.non_cash_payment_methods?.map((item: any) => ({
168
+ title: item?.name ?? "",
169
+ value: formatCurrency(item?.amount || 0),
170
+ })) || [],
171
+ },
172
+ ].map((section, idx) => {
173
+ if (!section)
174
+ return <div key={idx} className="h-[1px] bg-soft-400"></div>;
175
+ return (
176
+ <div
177
+ key={idx}
178
+ className="flex flex-col items-start gap-2 self-stretch"
179
+ >
180
+ <div className="inline-flex items-start justify-between self-stretch text-sm font-semibold text-strong-950">
181
+ <div className="text-xs w-full min-w-fit">{section.title}</div>
182
+ <div className="text-xs">{section.value}</div>
183
+ </div>
184
+ {section.items?.map((item: any) => (
185
+ <div
186
+ key={item.title}
187
+ className="inline-flex justify-between self-stretch text-[10px] font-normal text-strong-950"
188
+ >
189
+ <div>{item.title}</div>
190
+ <div className="font-semibold">{item.value}</div>
191
+ </div>
192
+ ))}
193
+ </div>
194
+ );
195
+ })}
196
+
197
+ <div className="h-[1px] bg-soft-400"></div>
198
+ </div>
199
+
200
+ <div className="flex flex-col items-center gap-4 self-stretch text-xs text-strong-950 flex-shrink-0">
201
+ <div className="w-full text-center font-normal">
202
+ Ngày {date.day} tháng {date.month} năm {date.year}
203
+ </div>
204
+ <div className="flex flex-col gap-20 items-center w-full">
205
+ <div className="flex w-full items-center gap-8 text-sm font-semibold text-strong-950">
206
+ <div className="flex-1 text-center">Người bàn giao</div>
207
+ <div className="flex-1 text-center">Người nhận bàn giao</div>
208
+ </div>
209
+ <div className="text-xs font-normal mt-4 text-center min-w-fit">
210
+ Powered by {company?.companyInfo?.data?.[0]?.display_name}
211
+ </div>
212
+ </div>
213
+ </div>
214
+ </div>
215
+ );
216
+ };
217
+
218
+ export default CloseSessionTicket;
@@ -0,0 +1,25 @@
1
+ import ModalDirection from "@components/common/modal/modal-direction";
2
+
3
+ type TProps = {
4
+ isOpen: boolean;
5
+ onClose: () => void;
6
+ children: React.ReactNode;
7
+ title: string;
8
+ };
9
+
10
+ function CloseSessionModalContainer(props: TProps) {
11
+ const { isOpen, onClose, children, title } = props;
12
+
13
+ return (
14
+ <ModalDirection
15
+ isOpen={isOpen}
16
+ onClose={onClose}
17
+ title={title}
18
+ className="overflow-hidden"
19
+ >
20
+ <div className="flex flex-col h-full">{children}</div>
21
+ </ModalDirection>
22
+ );
23
+ }
24
+
25
+ export default CloseSessionModalContainer;