Skip to content

POS UI (Renderer)

1. Document Control

PropertyValue
Package@nx-app/sale-renderer
Version0.0.1-0
TypeWeb Application (SPA)
RuntimeTauri WebView / Browser
FrameworkReact 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

TechnologyVersionPurpose
React^19.2.0UI Component Library
React DOM^19.2.0DOM Rendering
React Router^7.11.0Client-side Routing
TypeScript~6.0.2Type Safety

3.2. State Management

TechnologyVersionPurpose
Redux Toolkit^2.11.2Global State Management
React Redux^9.2.0React-Redux Bindings
TanStack Query^5.90.12Server State & Caching
ra-core^5.13.4Admin Framework Core

3.3. UI Components

TechnologyVersionPurpose
radix-ui^1.4.3Accessible Primitives (unified package)
Tailwind CSS^4.1.18Utility-first Styling
Lucide React^0.562.0Icon Library
shadcn^3.6.2Component Templates
cmdk^1.1.1Command Palette
vaul^1.1.2Drawer Component
sonner^2.0.7Toast Notifications

3.4. Tauri Integration

TechnologyVersionPurpose
@tauri-apps/api^2.9.1IPC Communication
@tauri-apps/plugin-os^2.3.2OS Information
@skipperndt/plugin-machine-uid^0.1.3Device Identification

3.5. Forms

TechnologyVersionPurpose
React Hook Form^7.69.0Form State Management
@hookform/resolvers^5.2.2Schema resolver integration

3.6. Data Visualization

TechnologyVersionPurpose
Recharts2.15.4Charts & Graphs
react-qr-code^2.0.18QR Code Generation
react-day-picker^9.13.0Date Selection

3.7. Real-time Communication

TechnologyVersionPurpose
socket.io-client^4.8.3WebSocket Communication
RxJS^7.8.2Reactive Streams

3.8. Layout & Interaction

TechnologyVersionPurpose
react-grid-layout^2.2.2Dashboard Layouts
react-resizable^3.1.3Resizable Panels
react-virtuoso^4.17.0Virtualized Lists
@tanstack/react-virtual^3.13.13Virtual Scrolling

3.9. Build & Development

TechnologyVersionPurpose
Vite^7.2.4Build Tool
@vitejs/plugin-react^5.1.1React Integration
lightningcss^1.30.2CSS Processing
ESLint^9.39.1Code Linting
Prettier^3.8.1Code Formatting

4. Architecture

4.1. Application Layers

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 (commerce / finance / identity / invoice / payment / sale)
│   │       ├── 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 (16 slices)
│   ├── screens/                    # Screen Components (14 modules)
│   └── socket/                     # WebSocket Integration
│       ├── client/                 # Socket client
│       └── server/                 # Socket server handlers
├── scripts/                        # Build Scripts
└── public/                         # Static Assets

6. Screens & Routing

6.1. Screen Modules

Routes are declared in App.tsx (public), screens/authenticated and screens/restaurant (nested). Directories under src/screens:

ModuleRouteDescription
home/Merchant home / dashboard
sale-v2/sale/:saleOrderIdMain POS interface (FnB catalog + cart)
order-checkout/order-checkout/:idOrder checkout & payment stepper
invoice/invoice, /invoice/:id/showInvoice list & detail
kitchen/kitchenKitchen display (KDS)
restaurant-table/restaurant/*Floor / table map & reservations
settings/settingApplication settings
customer/customerCustomer-facing display (second screen)
sign-in/loginAuthentication
privacy-policy/privacy-policyPrivacy policy
terms-and-conditions/terms-and-conditionsTerms & conditions
errors/authentication-error, /access-denied, *401 / 403 / 404 / 500 / 503 / crash pages
authenticated(wrapper)Auth-guarded route tree
restaurant(wrapper)Restaurant route wrapper (loads floor layout)

6.2. Sale Screen Components

The sale screen (screens/sale-v2) is the primary interface with complex sub-components:

screens/sale-v2/
├── Sale.screen.tsx                 # Main sale screen
├── SaleMain.tsx                    # Sale layout
├── SaleOrderAlertDialog.tsx        # Order alert dialog
├── index.tsx
├── fnb/                            # Food & Beverage catalog
│   ├── category/                   # Category navigation
│   ├── product/                    # Product list
│   ├── product-bundle/             # Bundle selection
│   └── product-variant/            # Product variant selection
├── cart/                           # Shopping cart
│   ├── context/                    # Cart context
│   ├── items/                      # Cart item list
│   │   ├── header/                 # Cart header
│   │   └── item/                   # Individual item
│   ├── detail/                     # Cart detail view
│   │   ├── customer/               # Customer association
│   │   └── sale-channel/           # Sale channel selection
│   └── summary/                    # Cart summary
│       ├── details/                # Price breakdown
│       └── actions/                # Cart actions
└── shift/                          # Shift / POS session controls

7. State Management

7.1. Redux Store Configuration

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

SlicePurpose
orderActive sale order (the cart): line items, quantities & price totals
saleSale workspace state
productProduct catalog browsing state
paymentPayment flow state
invoiceInvoice list / detail state
settingApplication settings state
kitchenKitchen display (KDS) state
broadcastReal-time broadcast / signal channel state
sessionPOS session state
configurationMerchant / commerce configuration state
restaurantRestaurant floor plan & table state
shiftShift controls state
financeAccountFinance account (payment method) state
userProfileAuthenticated user profile
commonShared UI state
temporaryEphemeral / transient UI data

7.3. Order State Structure

The cart is backed by the order slice (IOrderState). Items are keyed sale-order-item records, and price totals are recomputed on every mutation:

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

  // Price calculations
  totalPrice: number;
  totalPurchaseVoucherPrice: number;
  totalDiscountVoucherPrice: number;
  totalTaxPrice: number;
  totalPaymentPrice: number;

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

7.4. Order Actions

ActionDescription
resetOrderReset to initial state
resetOrderCheckoutClear order items & checkout info
resetSaleOrderItemsClear sale-order items only
loadSaleOrderItemsLoad items from backend
addSaleOrderItemAdd item to the order
removeSaleOrderItemRemove item from the order
updateQuantitySaleOrderItemUpdate item quantity
updateTaxPercentageSet tax rate

8. API Services

8.1. IPC API Clients

All API clients communicate over Tauri IPC and extend BaseCrudApiService (CRUD plus domain-specific commands). They live under application/services/apis, organized by backend domain:

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

The cart's add/remove/clear and checkout operations are served by SaleOrderApi / SaleOrderItemApi (mapped to the host's sale_order / sale_order_item commands), not a dedicated cart client.

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 exports

9.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. Unified Package

Radix primitives are consumed via the single unified radix-ui package (^1.4.3) rather than individual @radix-ui/react-* packages. Each primitive is imported from a named export, e.g.:

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

The shadcn/ui components under src/components/ui wrap these primitives (Accordion, Alert Dialog, Avatar, Checkbox, Collapsible, Context Menu, Dialog, Dropdown Menu, Label, Popover, Radio Group, Scroll Area, Select, Separator, Slot, Switch, Tabs, Tooltip, and more).

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

12.2. Checkout Steps

  1. Cart Review: Final verification of items
  2. Customer Association: Optional customer linking
  3. Payment Selection: Choose Cash, QR, or Card
  4. Transaction Execution: Process via Tauri IPC
  5. Receipt Generation: Format for printer
  6. 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

ScriptCommandPurpose
devvite --mode devDevelopment server
buildsh ./scripts/build.shProduction build
build:developsh ./scripts/rebuild.sh developmentDev build
build:productionsh ./scripts/rebuild.sh productionProd build
previewvite previewPreview build
lintsh ./scripts/lint.shESLint check
prettierprettier '**/*.{js,ts,jsx,tsx}' --writeFormat code

The dev server runs on port 3002 (strictPort, from vite.config.ts), which the Tauri host loads via devUrl: http://localhost:3002/.

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

MetricCount
Screen Modules14
Redux Slices16
API Clientscommerce / finance / identity / invoice / payment / sale domains
Radix UIunified radix-ui package
Socket Handlers5+
Custom Hooks10+

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