Skip to content

Giao diện POS (Renderer)

1. Kiểm soát Tài liệu

Thuộc tínhGiá trị
Gói@nx-app/sale-renderer
Phiên bản0.0.1-0
LoạiỨng dụng Web (SPA)
RuntimeTauri WebView / Trình duyệt
FrameworkReact 19 + Vite 7

2. Phạm vi & Mục tiêu

2.1. Phạm vi

Giao diện POS là lớp hình ảnh và tương tác của hệ thống Điểm bán hàng. Nó chạy bên trong WebView được cung cấp bởi tiến trình host Tauri (sale-main) và xử lý tất cả các tương tác của người dùng, luồng nghiệp vụ và phản hồi hình ảnh.

2.2. Mục tiêu

  • Tối ưu hóa Cảm ứng: Các phần tử giao diện có kích thước phù hợp cho tương tác chạm (mục tiêu tối thiểu 44px).
  • Tốc độ: Phản hồi tức thì cho các thao tác giỏ hàng.
  • Rõ ràng: Thiết kế độ tương phản cao cho các điều kiện ánh sáng khác nhau.
  • Hỗ trợ Ngoại tuyến: Các tính năng cốt lõi hoạt động không cần mạng.
  • Cập nhật Thời gian thực: Tích hợp WebSocket cho trạng thái đơn hàng.

3. Ngăn xếp Công nghệ

3.1. Framework Cốt lõi

Công nghệPhiên bảnMục đích
React^19.2.0Thư viện Thành phần UI
React DOM^19.2.0Kết xuất DOM
React Router^7.11.0Định tuyến phía Client
TypeScript~6.0.2An toàn kiểu dữ liệu

3.2. Quản lý Trạng thái

Công nghệPhiên bảnMục đích
Redux Toolkit^2.11.2Quản lý Trạng thái Toàn cục
React Redux^9.2.0Liên kết React-Redux
TanStack Query^5.90.12Trạng thái Server & Caching
ra-core^5.13.4Lõi Framework Admin

3.3. Thành phần UI

Công nghệPhiên bảnMục đích
radix-ui^1.4.3Các thành phần cơ sở dễ tiếp cận (gói hợp nhất)
Tailwind CSS^4.1.18Utility-first Styling
Lucide React^0.562.0Thư viện Biểu tượng
shadcn^3.6.2Mẫu Thành phần
cmdk^1.1.1Bảng lệnh
vaul^1.1.2Thành phần Ngăn kéo
sonner^2.0.7Thông báo Toast

3.4. Tích hợp Tauri

Công nghệPhiên bảnMục đích
@tauri-apps/api^2.9.1Giao tiếp IPC
@tauri-apps/plugin-os^2.3.2Thông tin Hệ điều hành
@skipperndt/plugin-machine-uid^0.1.3Nhận dạng Thiết bị

3.5. Biểu mẫu

Công nghệPhiên bảnMục đích
React Hook Form^7.69.0Quản lý Trạng thái Biểu mẫu
@hookform/resolvers^5.2.2Tích hợp resolver schema

3.6. Trực quan hóa Dữ liệu

Công nghệPhiên bảnMục đích
Recharts2.15.4Biểu đồ & Đồ thị
react-qr-code^2.0.18Tạo Mã QR
react-day-picker^9.13.0Chọn ngày

3.7. Giao tiếp Thời gian thực

Công nghệPhiên bảnMục đích
socket.io-client^4.8.3Giao tiếp WebSocket
RxJS^7.8.2Reactive Streams

3.8. Bố cục & Tương tác

Công nghệPhiên bảnMục đích
react-grid-layout^2.2.2Bố cục Dashboard
react-resizable^3.1.3Bảng có thể thay đổi kích thước
react-virtuoso^4.17.0Danh sách ảo hóa
@tanstack/react-virtual^3.13.13Cuộn ảo

3.9. Build & Phát triển

Công nghệPhiên bảnMục đích
Vite^7.2.4Công cụ Build
@vitejs/plugin-react^5.1.1Tích hợp React
lightningcss^1.30.2Xử lý CSS
ESLint^9.39.1Kiểm tra lỗi mã nguồn
Prettier^3.8.1Định dạng mã nguồn

4. Kiến trúc

4.1. Các lớp Ứng dụng

4.2. Giao tiếp IPC

Renderer giao tiếp với Tauri backend thông qua một dịch vụ IPC tùy chỉnh:

typescript
export class IpcRendererService {
  async invoke<TPayload, TResponse>(opts: {
    command: string;
    payload: TPayload;
  }): Promise<TResponse> {
    const res = await invoke(command, { payload });
    return { data: res } as TResponse;
  }
}

4.3. Mẫu Data Provider

Sử dụng TauriIpcDataProvider tùy chỉnh mở rộng mẫu REST provider:

typescript
export class TauriIpcDataProvider extends DefaultRestDataProvider {
  override send<TResponse>(opts: {
    resource: string;
    params: ISendParams;
  }): Promise<ISendResponse<TResponse>> {
    return ipcService.invoke({
      command: resource,
      payload: params,
    });
  }
}

5. Cấu trúc Dự án

apps/sale-renderer/
├── src/
│   ├── application/                # DI Container & Providers
│   │   ├── decorators/             # Decorator tùy chỉnh
│   │   ├── providers/              # Auth & IPC Providers
│   │   │   ├── auth.provider.ts    # Provider xác thực
│   │   │   └── ipc-data.provider.ts # Tauri IPC data provider
│   │   └── services/               # Dịch vụ API
│   │       ├── apis/               # Domain API clients (commerce / finance / identity / invoice / payment / sale)
│   │       ├── environment.service.ts
│   │       └── ipc.service.ts      # Tauri IPC wrapper
│   ├── components/                 # Thành phần UI tái sử dụng
│   │   └── ui/                     # Thành phần shadcn/ui
│   ├── constants/                  # Hằng số Ứng dụng
│   ├── helpers/                    # Các hàm Tiện ích
│   ├── hooks/                      # React Hooks tùy chỉnh
│   ├── interfaces/                 # Giao diện TypeScript
│   ├── layout/                     # Thành phần Bố cục
│   ├── libs/                       # Cấu hình Thư viện ngoài
│   ├── redux/                      # Redux Store
│   │   └── slices/                 # Redux Slices (16 slices)
│   ├── screens/                    # Thành phần Màn hình (14 modules)
│   └── socket/                     # Tích hợp WebSocket
│       ├── client/                 # Socket client
│       └── server/                 # Socket server handlers
├── scripts/                        # Script Build
└── public/                         # Tài sản Tĩnh

6. Màn hình & Định tuyến

6.1. Module Màn hình

Các route được khai báo trong App.tsx (công khai), screens/authenticatedscreens/restaurant (lồng nhau). Các thư mục trong src/screens:

ModuleRouteMô tả
home/Trang chủ / dashboard của merchant
sale-v2/sale/:saleOrderIdGiao diện POS chính (danh mục FnB + giỏ hàng)
order-checkout/order-checkout/:idCheckout đơn hàng & các bước thanh toán
invoice/invoice, /invoice/:id/showDanh sách & chi tiết hóa đơn
kitchen/kitchenMàn hình bếp (KDS)
restaurant-table/restaurant/*Sơ đồ mặt bằng / bàn & đặt chỗ
settings/settingCài đặt ứng dụng
customer/customerMàn hình hướng khách hàng (màn hình phụ)
sign-in/loginXác thực
privacy-policy/privacy-policyChính sách quyền riêng tư
terms-and-conditions/terms-and-conditionsĐiều khoản & điều kiện
errors/authentication-error, /access-denied, *Trang 401 / 403 / 404 / 500 / 503 / crash
authenticated(wrapper)Cây route được bảo vệ xác thực
restaurant(wrapper)Wrapper route nhà hàng (tải sơ đồ mặt bằng)

6.2. Thành phần Màn hình Bán hàng

Màn hình bán hàng (screens/sale-v2) là giao diện chính với các thành phần con phức tạp:

screens/sale-v2/
├── Sale.screen.tsx                 # Màn hình bán hàng chính
├── SaleMain.tsx                    # Bố cục bán hàng
├── SaleOrderAlertDialog.tsx        # Hộp thoại cảnh báo đơn hàng
├── index.tsx
├── fnb/                            # Danh mục Thực phẩm & Đồ uống
│   ├── category/                   # Điều hướng danh mục
│   ├── product/                    # Danh sách sản phẩm
│   ├── product-bundle/             # Lựa chọn combo
│   └── product-variant/            # Lựa chọn biến thể sản phẩm
├── cart/                           # Giỏ hàng mua sắm
│   ├── context/                    # Context giỏ hàng
│   ├── items/                      # Danh sách mục giỏ hàng
│   │   ├── header/                 # Tiêu đề giỏ hàng
│   │   └── item/                   # Mục riêng lẻ
│   ├── detail/                     # Xem chi tiết giỏ hàng
│   │   ├── customer/               # Gắn khách hàng
│   │   └── sale-channel/           # Chọn kênh bán hàng
│   └── summary/                    # Tóm tắt giỏ hàng
│       ├── details/                # Chi tiết giá
│       └── actions/                # Các hành động giỏ hàng
└── shift/                          # Điều khiển ca / phiên POS

7. Quản lý Trạng thái

7.1. Cấu hình Redux Store

typescript
const appReducer = combineReducers({
  temporary: temporaryReducer,
  common: commonReducer,
  userProfile: userProfileReducer,
  order: orderReducer,
  sale: saleReducer,
  product: productReducer,
  payment: paymentReducer,
  invoice: invoiceReducer,
  setting: settingReducer,
  kitchen: kitchenReducer,
  broadcast: broadcastReducer,
  session: sessionReducer,
  configuration: configurationReducer,
  restaurant: restaurantReducer,
  shift: shiftReducer,
  financeAccount: financeAccountReducer,
});

7.2. Redux Slices

SliceMục đích
orderĐơn hàng đang mở (giỏ hàng): các mục, số lượng & tổng giá
saleTrạng thái không gian bán hàng
productTrạng thái duyệt danh mục sản phẩm
paymentTrạng thái luồng thanh toán
invoiceTrạng thái danh sách / chi tiết hóa đơn
settingTrạng thái cài đặt ứng dụng
kitchenTrạng thái màn hình bếp (KDS)
broadcastTrạng thái kênh broadcast / signal thời gian thực
sessionTrạng thái phiên POS
configurationTrạng thái cấu hình merchant / commerce
restaurantTrạng thái sơ đồ mặt bằng & bàn nhà hàng
shiftTrạng thái điều khiển ca
financeAccountTrạng thái tài khoản tài chính (phương thức thanh toán)
userProfileHồ sơ người dùng đã xác thực
commonTrạng thái UI chung
temporaryDữ liệu UI tạm thời / thoáng qua

7.3. Cấu trúc Trạng thái Đơn hàng

Giỏ hàng được hậu thuẫn bởi slice order (IOrderState). Các mục được lưu theo khóa là bản ghi sale-order-item, và tổng giá được tính lại sau mỗi lần thay đổi:

typescript
interface IOrderState {
  saleOrderCount: number;
  saleOrderItemCount: number;
  saleOrderItems: { [saleOrderItemId: string]: ISaleOrderItem };
  itemToSaleOrderItemsMap: { [itemId: string]: string };
  lastModifySaleOrderItem: string;

  // Tính toán giá
  totalPrice: number;
  totalPurchaseVoucherPrice: number;
  totalDiscountVoucherPrice: number;
  totalTaxPrice: number;
  totalPaymentPrice: number;

  taxPercentage: string;
  paymentMethod: string;
  financeAccount: IFinanceAccount | null;
}

7.4. Hành động Đơn hàng

Hành độngMô tả
resetOrderĐặt lại về trạng thái ban đầu
resetOrderCheckoutXóa các mục đơn hàng & thông tin checkout
resetSaleOrderItemsChỉ xóa các mục sale-order
loadSaleOrderItemsTải các mục từ backend
addSaleOrderItemThêm mục vào đơn hàng
removeSaleOrderItemXóa mục khỏi đơn hàng
updateQuantitySaleOrderItemCập nhật số lượng mục
updateTaxPercentageĐặt thuế suất

8. Dịch vụ API

8.1. API Client IPC

Tất cả các API client giao tiếp qua Tauri IPC và kế thừa BaseCrudApiService (CRUD cùng các lệnh đặc thù theo domain). Chúng nằm dưới application/services/apis, được tổ chức theo domain backend:

DomainAPI Clients
identityAuthApi, PinAuthApi, UserApi
commerceCategoryApi, ProductApi, ProductVariantApi, MerchantApi, OrganizerApi, SaleChannelApi, ConfigurationApi, DeviceApi, ReceiptTemplateApi, SettingApi, AssetApi, AllocationLayoutApi, AllocationUnitApi, AllocationZoneApi
saleSaleOrderApi, SaleOrderItemApi, SaleCustomerApi, ReservationApi, AllocationUsageApi, KitchenTicketApi, KitchenTicketItemApi, SalesReportApi, ShiftApi
financeFinanceAccountApi, FinanceAssetApi, FinanceCategoryApi, FinanceWalletApi
paymentPaymentApi, PaymentAttemptApi
invoiceInvoiceApi

Các thao tác thêm/xóa/làm trống giỏ hàng và checkout được phục vụ bởi SaleOrderApi / SaleOrderItemApi (ánh xạ tới các lệnh sale_order / sale_order_item của host), không phải một client giỏ hàng riêng.

9. Tích hợp WebSocket

9.1. Kiến trúc Socket

socket/
├── client/                         # Client-side socket
│   ├── index.ts                    # Socket client exports
│   ├── socket-connection-manager.ts # Quản lý kết nối
│   └── socket-subscription-manager.ts # Xử lý đăng ký
├── server/                         # Server message handlers
│   ├── base/                       # Các lớp socket cơ sở
│   │   ├── base-socket.ts          # Lớp socket cơ sở
│   │   └── base-socket-subscription-manager.ts
│   ├── messages/                   # Trình xử lý tin nhắn
│   │   └── market-data-socket-message-handler.ts
│   └── order-socket.service.ts     # Dịch vụ socket đơn hàng
├── constants.ts                    # Hằng số socket
├── helper.ts                       # Tiện ích socket
├── types.ts                        # Kiểu dữ liệu socket
└── index.ts                        # Main exports

9.2. Tính năng Socket

  • Cập nhật Trạng thái Đơn hàng: Thay đổi trạng thái đơn hàng thời gian thực
  • Dữ liệu Thị trường: Cập nhật giá trực tiếp
  • Quản lý Kết nối: Tự động kết nối lại khi mất kết nối
  • Hệ thống Đăng ký: Đăng ký/hủy đăng ký các kênh

10. Thành phần Radix UI

10.1. Gói Hợp nhất

Các primitive Radix được dùng qua gói hợp nhất duy nhất radix-ui (^1.4.3) thay vì các gói @radix-ui/react-* riêng lẻ. Mỗi primitive được import từ một named export, ví dụ:

typescript
import { Dialog, DropdownMenu, Tooltip } from 'radix-ui';

Các thành phần shadcn/ui trong src/components/ui bọc các primitive này (Accordion, Alert Dialog, Avatar, Checkbox, Collapsible, Context Menu, Dialog, Dropdown Menu, Label, Popover, Radio Group, Scroll Area, Select, Separator, Slot, Switch, Tabs, Tooltip, và nhiều hơn nữa).

11. Hệ thống Giỏ hàng

11.1. Tính năng Giỏ hàng

  • Gộp mục: Nhóm các mục giống hệt nhau theo biến thể
  • Quản lý Số lượng: Tăng/giảm với xác thực
  • Tính toán Giá: Tổng phụ thời gian thực, thuế, chiết khấu
  • Phương thức Thanh toán: Hỗ trợ Tiền mặt, QR, Thẻ
  • Xử lý Thuế: Phần trăm thuế có thể cấu hình

11.2. Logic Tính toán Giá

typescript
// Tính tổng
totalPrice = items.reduce((sum, item) =>
  sum + item.unitPrice * item.quantity, 0);

// Áp dụng chiết khấu và thuế
const taxableAmount = Math.max(0, totalPrice - discount);
totalTaxPrice = Math.round(taxableAmount * (taxRate / 100));

totalPaymentPrice = totalPrice
  - totalDiscountVoucherPrice
  - totalPurchaseVoucherPrice
  + totalTaxPrice;

12. Luồng Thanh toán (Checkout Flow)

12.1. Sơ đồ Luồng

12.2. Các bước Thanh toán

  1. Xem lại Giỏ hàng: Xác minh cuối cùng các mục
  2. Liên kết Khách hàng: Liên kết khách hàng tùy chọn
  3. Lựa chọn Thanh toán: Chọn Tiền mặt, QR, hoặc Thẻ
  4. Thực thi Giao dịch: Xử lý qua Tauri IPC
  5. Tạo Biên lai: Định dạng cho máy in
  6. Hoàn tất Đơn hàng: Xóa giỏ hàng và cập nhật trạng thái

13. Điểm Tích hợp

13.1. Thượng nguồn (Tauri Backend)

  • Lệnh IPC: Gọi các hàm Rust qua @tauri-apps/api
  • Sự kiện: Lắng nghe init_ready, init_error, migration_error
  • API Cửa sổ: Quản lý cửa sổ, màn hình ngoài

13.2. Ngang hàng (Các gói Dùng chung)

  • @nx-app/core: Tiện ích và locales dùng chung
  • @minimaltech/ra-core-infra: Cơ sở hạ tầng dịch vụ cơ bản
  • @venizia/ignis-inversion: IoC container

13.3. Hạ nguồn (Backend API)

  • WebSocket: Cập nhật đơn hàng thời gian thực
  • Telemetry: Ghi log lỗi và phân tích

14. Build & Scripts

14.1. Các Script có sẵn

ScriptLệnhMục đích
devvite --mode devDevelopment server
buildsh ./scripts/build.shBuild sản xuất
build:developsh ./scripts/rebuild.sh developmentBuild phát triển
build:productionsh ./scripts/rebuild.sh productionBuild sản xuất
previewvite previewXem trước build
lintsh ./scripts/lint.shKiểm tra ESLint
prettierprettier '**/*.{js,ts,jsx,tsx}' --writeĐịnh dạng mã

Dev server chạy trên cổng 3002 (strictPort, từ vite.config.ts), được tiến trình host Tauri tải qua devUrl: http://localhost:3002/.

14.2. Đầu ra Build

Bản build được tiêu thụ bởi tiến trình host Tauri:

  • Thư mục đầu ra: dist/
  • Được phục vụ bởi plugin localhost của Tauri
  • Được nhúng trong ứng dụng desktop/mobile

15. Thống kê Mã nguồn

Chỉ sốSố lượng
Module Màn hình14
Redux Slices16
API Clientscác domain commerce / finance / identity / invoice / payment / sale
Radix UIgói hợp nhất radix-ui
Trình xử lý Socket5+
Custom Hooks10+

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.