POS UI (Renderer)
1. Document Control
| Property | Value |
|---|---|
| Package | @nx-app/sale-renderer |
| Version | 0.0.0 |
| Type | Web Application (SPA) |
| Runtime | Tauri WebView / Browser |
| Framework | React 19 + Vite 7 |
2. Scope & Objectives
2.1. Scope
The POS UI is the visual and interactive layer of the Point-of-Sale system. It runs inside the WebView provided by the Tauri host process (sale-main) and handles all user interactions, business flows, and visual feedback.
2.2. Objectives
- Touch Optimization: UI elements sized for touch interaction (minimum 44px target).
- Speed: Instant feedback for cart operations.
- Clarity: High-contrast design for various lighting conditions.
- Offline Support: Functional core features without network.
- Real-time Updates: WebSocket integration for order status.
3. Technology Stack
3.1. Core Framework
| Technology | Version | Purpose |
|---|---|---|
| React | ^19.2.0 | UI Component Library |
| React DOM | ^19.2.0 | DOM Rendering |
| React Router | ^7.11.0 | Client-side Routing |
| TypeScript | ~5.9.3 | Type Safety |
3.2. State Management
| Technology | Version | Purpose |
|---|---|---|
| Redux Toolkit | ^2.11.2 | Global State Management |
| React Redux | ^9.2.0 | React-Redux Bindings |
| TanStack Query | ^5.90.12 | Server State & Caching |
| ra-core | ^5.13.4 | Admin Framework Core |
3.3. UI Components
| Technology | Version | Purpose |
|---|---|---|
| Radix UI | Various | Accessible Primitives |
| Tailwind CSS | ^4.1.18 | Utility-first Styling |
| Lucide React | ^0.562.0 | Icon Library |
| shadcn | ^3.6.2 | Component Templates |
| cmdk | ^1.1.1 | Command Palette |
| vaul | ^1.1.2 | Drawer Component |
| sonner | ^2.0.7 | Toast Notifications |
3.4. Tauri Integration
| Technology | Version | Purpose |
|---|---|---|
| @tauri-apps/api | ^2.9.1 | IPC Communication |
| @tauri-apps/plugin-os | ^2.3.2 | OS Information |
| @skipperndt/plugin-machine-uid | ^0.1.3 | Device Identification |
3.5. Forms & Validation
| Technology | Version | Purpose |
|---|---|---|
| React Hook Form | ^7.69.0 | Form State Management |
| @hookform/resolvers | ^5.2.2 | Schema Integration |
| Zod | ^4.2.1 | Runtime Validation |
3.6. Data Visualization
| Technology | Version | Purpose |
|---|---|---|
| Recharts | 2.15.4 | Charts & Graphs |
| react-qr-code | ^2.0.18 | QR Code Generation |
| react-day-picker | ^9.13.0 | Date Selection |
3.7. Real-time Communication
| Technology | Version | Purpose |
|---|---|---|
| socket.io-client | ^4.8.3 | WebSocket Communication |
| RxJS | ^7.8.2 | Reactive Streams |
3.8. Layout & Interaction
| Technology | Version | Purpose |
|---|---|---|
| react-grid-layout | ^2.2.2 | Dashboard Layouts |
| react-resizable | ^3.1.3 | Resizable Panels |
| react-virtuoso | ^4.17.0 | Virtualized Lists |
| @tanstack/react-virtual | ^3.13.13 | Virtual Scrolling |
3.9. Build & Development
| Technology | Version | Purpose |
|---|---|---|
| Vite | ^7.2.4 | Build Tool |
| @vitejs/plugin-react | ^5.1.1 | React Integration |
| lightningcss | ^1.30.2 | CSS Processing |
| ESLint | ^9.39.1 | Code Linting |
| Prettier | 3.6.2 | Code Formatting |
4. Architecture
4.1. Application Layers
User Touch
→
React UI
→
IPC Service
→
Tauri Backend
4.2. IPC Communication
The renderer communicates with the Tauri backend via a custom IPC service:
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. Data Provider Pattern
Uses a custom TauriIpcDataProvider that extends the REST provider pattern:
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. Project Structure
apps/sale-renderer/
├── src/
│ ├── application/ # DI Container & Providers
│ │ ├── decorators/ # Custom Decorators
│ │ ├── providers/ # Auth & IPC Providers
│ │ │ ├── auth.provider.ts # Authentication provider
│ │ │ └── ipc-data.provider.ts # Tauri IPC data provider
│ │ └── services/ # API Services
│ │ ├── apis/ # Domain API Clients (15 files)
│ │ ├── environment.service.ts
│ │ └── ipc.service.ts # Tauri IPC wrapper
│ ├── components/ # Reusable UI Components
│ │ └── ui/ # shadcn/ui components
│ ├── constants/ # Application Constants
│ ├── helpers/ # Utility Functions
│ ├── hooks/ # Custom React Hooks
│ ├── interfaces/ # TypeScript Interfaces
│ ├── layout/ # Layout Components
│ ├── libs/ # External Library Configs
│ ├── redux/ # Redux Store
│ │ └── slices/ # Redux Slices (8 slices)
│ ├── screens/ # Screen Components (8 modules)
│ └── socket/ # WebSocket Integration
│ ├── client/ # Socket client
│ └── server/ # Socket server handlers
├── scripts/ # Build Scripts
└── public/ # Static Assets6. Screens & Routing
6.1. Screen Modules
| Module | Path | Description |
|---|---|---|
| home | / | Dashboard with widgets and stats |
| sale | /sale | Main POS interface with cart |
| customer | /customer | Customer management |
| settings | /settings | Application settings |
| sign-in | /sign-in | Authentication |
| errors | /401, /403, /404 | Error pages |
6.2. Sale Screen Components
The sale screen is the primary interface with complex sub-components:
screens/sale/
├── index.tsx # Main sale screen
├── fnb/ # Food & Beverage catalog
│ ├── category/ # Category navigation
│ └── product-variant/ # Product variant selection
├── cart/ # Shopping cart
│ ├── items/ # Cart item list
│ │ ├── header/ # Cart header
│ │ └── item/ # Individual item
│ ├── detail/ # Cart detail view
│ └── summary/ # Cart summary
│ ├── details/ # Price breakdown
│ └── actions/ # Cart actions
│ ├── order-checkout/ # Checkout button
│ └── payment-dialog/ # Payment modal
│ ├── order-detail/ # Order summary
│ └── stepper/ # Payment stepper
│ ├── methods/ # Payment methods
│ └── actions/ # Step actions
└── manual-form/ # Manual entry form7. State Management
7.1. Redux Store Configuration
typescript
const appReducer = combineReducers({
temporary: temporaryReducer,
common: commonReducer,
userProfile: userProfileReducer,
order: orderReducer,
sale: saleReducer,
cart: cartReducer,
product: productReducer,
payment: paymentReducer,
});7.2. Redux Slices
| Slice | Purpose | Key State |
|---|---|---|
| cart | Shopping cart management | Items, totals, tax, payment method |
| order | Order processing | Current order, order history |
| payment | Payment state | Payment method, status, attempt |
| product | Product catalog state | Active product, selection |
| sale | Sale session state | Active session, mode |
| userProfile | User information | Profile, preferences |
| common | Shared UI state | Flags, settings |
| temporary | Ephemeral data | Form drafts |
7.3. Cart State Structure
typescript
interface ICartState {
cartList: [];
cartItems: { [id: string]: ICartItem };
productVariantToCartItemsMap: { [variantId: string]: string };
// Price calculations
totalPrice: number;
totalPurchaseVoucherPrice: number;
totalDiscountVoucherPrice: number;
totalTaxPrice: number;
totalPaymentPrice: number;
taxPercentage: string;
paymentMethod: PaymentMethod;
}7.4. Cart Actions
| Action | Description |
|---|---|
resetCart | Reset to initial state |
resetCartAfterPayment | Clear cart after successful payment |
loadCartItems | Load items from backend |
addCartItem | Add item to cart |
removeCartItem | Remove item from cart |
updateQuantityCartItem | Update item quantity |
updateTaxPercentage | Set tax rate |
8. API Services
8.1. IPC API Services
All API services communicate via Tauri IPC:
| Service | Commands | Description |
|---|---|---|
| AuthApi | sign_in, sign_out, who_am_i | Authentication |
| UserApi | get_user_profile | User profile |
| CategoryApi | CRUD operations | Categories |
| ProductApi | CRUD operations | Products |
| ProductVariantApi | CRUD operations | Variants |
| MerchantApi | CRUD operations | Merchants |
| OrganizerApi | CRUD operations | Organizers |
| SaleChannelApi | CRUD operations | Sales channels |
| CartApi | cart_items, add_item, clear | Cart management |
| CartItemApi | update_quantity | Item operations |
| OrderApi | checkout, revert_checkout | Order processing |
| PaymentApi | checkout, cancel, system_ipn | Payments |
| PaymentAttemptApi | find_by_id | Payment attempts |
| AssetApi | i18n_file, vnpay_qr_frame | Assets |
9. WebSocket Integration
9.1. Socket Architecture
socket/
├── client/ # Client-side socket
│ ├── index.ts # Socket client exports
│ ├── socket-connection-manager.ts # Connection management
│ └── socket-subscription-manager.ts # Subscription handling
├── server/ # Server message handlers
│ ├── base/ # Base socket classes
│ │ ├── base-socket.ts # Base socket class
│ │ └── base-socket-subscription-manager.ts
│ ├── messages/ # Message handlers
│ │ └── market-data-socket-message-handler.ts
│ └── order-socket.service.ts # Order socket service
├── constants.ts # Socket constants
├── helper.ts # Socket utilities
├── types.ts # Socket types
└── index.ts # Main exports9.2. Socket Features
- Order Status Updates: Real-time order state changes
- Market Data: Live pricing updates
- Connection Management: Auto-reconnect on disconnect
- Subscription System: Subscribe/unsubscribe to channels
10. Radix UI Components
10.1. Installed Primitives
| Component | Version | Usage |
|---|---|---|
| Accordion | ^1.2.12 | Collapsible sections |
| Alert Dialog | ^1.1.15 | Confirmation modals |
| Avatar | ^1.1.11 | User avatars |
| Checkbox | ^1.3.3 | Form checkboxes |
| Collapsible | ^1.1.12 | Expandable panels |
| Context Menu | ^2.2.16 | Right-click menus |
| Dialog | ^1.1.15 | Modal dialogs |
| Dropdown Menu | ^2.1.16 | Dropdown menus |
| Label | ^2.1.8 | Form labels |
| Popover | ^1.1.15 | Floating panels |
| Radio Group | ^1.3.8 | Radio selections |
| Scroll Area | ^1.2.10 | Custom scrollbars |
| Select | ^2.2.6 | Dropdown selects |
| Separator | ^1.1.8 | Visual dividers |
| Slot | ^1.2.4 | Component slots |
| Switch | ^1.2.6 | Toggle switches |
| Tabs | ^1.1.13 | Tab navigation |
| Tooltip | ^1.2.8 | Hover tooltips |
11. The Cart System
11.1. Cart Features
- Item Aggregation: Group identical items by variant
- Quantity Management: Increment/decrement with validation
- Price Calculations: Real-time subtotal, tax, discounts
- Payment Methods: Cash, QR, Card support
- Tax Handling: Configurable tax percentage
11.2. Price Calculation Logic
typescript
// Calculate totals
totalPrice = items.reduce((sum, item) =>
sum + item.unitPrice * item.quantity, 0);
// Apply discounts and tax
const taxableAmount = Math.max(0, totalPrice - discount);
totalTaxPrice = Math.round(taxableAmount * (taxRate / 100));
totalPaymentPrice = totalPrice
- totalDiscountVoucherPrice
- totalPurchaseVoucherPrice
+ totalTaxPrice;12. Checkout Flow
12.1. Flow Diagram
Cart Review
→
Customer Link
→
Payment Select
→
Process Payment
12.2. Checkout Steps
- Cart Review: Final verification of items
- Customer Association: Optional customer linking
- Payment Selection: Choose Cash, QR, or Card
- Transaction Execution: Process via Tauri IPC
- Receipt Generation: Format for printer
- Order Completion: Clear cart and update state
13. Integration Points
13.1. Upstream (Tauri Backend)
- IPC Commands: Invoke Rust functions via
@tauri-apps/api - Events: Listen for
init_ready,init_error,migration_error - Window API: Manage windows, external display
13.2. Lateral (Shared Packages)
- @nx-app/core: Shared utilities and locales
- @minimaltech/ra-core-infra: Base service infrastructure
- @venizia/ignis-inversion: IoC container
13.3. Downstream (Backend API)
- WebSocket: Real-time order updates
- Telemetry: Error logging and analytics
14. Build & Scripts
14.1. Available Scripts
| Script | Command | Purpose |
|---|---|---|
dev | vite --mode dev | Development server |
build | sh ./scripts/build.sh | Production build |
build:develop | sh ./scripts/rebuild.sh development | Dev build |
build:production | sh ./scripts/rebuild.sh production | Prod build |
preview | vite preview | Preview build |
lint | sh ./scripts/lint.sh | ESLint check |
prettier | prettier '**/*.{js,ts,jsx,tsx}' --write | Format code |
14.2. Build Output
The build is consumed by the Tauri host process:
- Output directory:
dist/ - Served by Tauri's localhost plugin
- Embedded in desktop/mobile app
15. Code Statistics
| Metric | Count |
|---|---|
| Source Files | ~337 |
| Screen Modules | 8 |
| Redux Slices | 8 |
| API Services | 15 |
| Radix Components | 18 |
| Socket Handlers | 5+ |
| Custom Hooks | 10+ |