PricingEnginePanel
Invoice / quote builder with line items, product and category catalogs, line and global discounts, per-rate VAT summary, secondary currency and draft / save actions — same data model and totals as the web panel.
Installation
pnpm dlx @docyrus/cli add @docyrus/rn-pricing-engine-panelUsage
import {
PricingEnginePanel,
type IPricingDocumentData
} from '@/components/docyrus-native/pricing-engine-panel';
<PricingEnginePanel
title="Project Proposal"
defaultCurrency="EUR"
defaultValue={{
lineItems: [
{
id: 'line-1', position: 0, productId: null, categoryId: null,
name: 'Web Development', category: 'Development',
quantity: 40, unitPrice: 150, vatRate: 18, discountPercent: 10
}
],
globalDiscountPercent: 5,
currency: { code: 'EUR', secondaryCurrencyCode: 'USD', exchangeRate: 1.08 }
}}
productCatalog={products}
categoryCatalog={categories}
onSave={(data: IPricingDocumentData) => saveQuote(data)}
onSaveDraft={data => saveDraft(data)}
/>The panel shares interfaces.ts, types.ts, constants.ts, lib/calculations.ts and lib/line-item-helpers.ts byte-for-byte with the web @docyrus/ui panel, so a document gives identical totals to the cent on both platforms (banker's rounding, FINANCIAL_PRECISION = 2).
Mobile behaviour
- Lines render as cards (position, name, category,
qty × unit price, net or gross headline followingviewMode, subtotal / discount / VAT chips). Tap a card to edit it in a bottom sheet (numeric keyboards, live subtotal → discount → net → VAT → gross breakdown);Donecommits,Canceldiscards. Add Line opens the same sheet for a new line. - Row menu — the
⋯button (or a long press) opens Move Up / Move Down / Duplicate Line / Delete Line. - Products — with a
productCatalogthe product field opens a searchable list inside the sheet; picking fills name, category, unit price and VAT rate. Without a catalog the field is free text, plus a picker button that callsonProductSelectwhen provided. - Categories — with a
categoryCatalog(flatparentIdlist or nestedchildren) the category field opens a drill-down list: tap a row to pick it, tap its chevron to open its children; searching shows matches with their path. Without a catalog: free text + optionalonCategorySelectbutton. - Settings sheet (header slider button, hidden when
readOnly) — the same nine switches as the web config popover, a VAT-rates editor (add / remove rates, tap a rate to make it the default for new lines) and the secondary currency. - Currency — the header currency chip picks the primary currency; when a secondary currency is set, a currency bar shows the exchange-rate field and the converted grand total.
- Formatting — amounts use the tenant formatter from
<NumberFormatProvider>(installed by<DocyrusTenantProvider>) when it is mounted, otherwise the device-localeIntlcurrency formatter. size="full"fills the available screen: the sections scroll and the actions bar stays pinned at the bottom (safe-area aware).- Copy comes from
useUiTranslation()with the webui.pricing.*keys and English fallbacks.
API Reference
PricingEnginePanelProps
| Prop | Type | Default | Description |
|---|---|---|---|
value | Partial<IPricingDocumentData> | — | Controlled document state. Every change of the object is applied to the internal state |
defaultValue | Partial<IPricingDocumentData> | — | Initial document state (uncontrolled) |
showVatColumn | boolean | true | Show the VAT chip on line cards and the VAT-rate field in the line editor |
showDiscountColumn | boolean | true | Show the line-discount chip and the discount field |
showGrossColumn | boolean | true | Show the gross amount under the net headline (net view) |
showCategoryColumn | boolean | true | Show the line category and the category field |
discountBeforeVat | boolean | true | true: discount the net subtotal, then add VAT. false: VAT on the subtotal, discount applied to the VAT-inclusive amount |
enableVat | boolean | true | Enable VAT calculation, VAT total and VAT summary |
enableLineDiscount | boolean | true | Enable per-line discount % |
enableGlobalDiscount | boolean | true | Enable the document-level discount % (applied after line discounts) |
enableAdjustment | boolean | true | Enable the signed adjustment amount added to the grand total |
defaultVatRate | number | 18 | VAT rate for new lines and for products without vatRate |
vatRates | number[] | [0, 1, 8, 10, 18, 20] | Selectable VAT rates |
defaultCurrency | string | 'USD' | Primary ISO 4217 currency code |
viewMode | 'net' | 'gross' | 'net' | Which amount the line cards headline (toggled from the header) |
onLineItemsChange | (items: ILineItem[]) => void | — | Called when line items change |
onTotalsChange | (totals: ITotals) => void | — | Called when the calculated totals change |
onSave | (data: IPricingDocumentData) => void | — | Save button. Sets status to 'saved' |
onSaveDraft | (data: IPricingDocumentData) => void | — | Save Draft button. Sets status to 'draft' |
onProductSelect | (lineId: string, callback: (product: IProductCatalogItem) => void) => void | — | Remote product picker, used when productCatalog is empty. Call callback with the picked product |
onCategorySelect | (lineId: string, callback: (category: ICategoryCatalogItem) => void) => void | — | Remote category picker, used when categoryCatalog is empty |
productCatalog | IProductCatalogItem[] | — | Static product list. Enables the searchable product picker |
categoryCatalog | ICategoryCatalogItem[] | — | Static categories (flat with parentId, or nested children). Enables the drill-down category picker |
title | string | — | Header title (a Draft / Saved status badge is shown next to it) |
readOnly | boolean | false | Disable editing: no editor sheet, row menu, settings, add or actions |
showDescription | boolean | true | Show the description editor |
showTerms | boolean | true | Show the terms & conditions editor (tabs when both are shown) |
showActions | boolean | true | Show the Save Draft / Save bar |
variant | 'default' | 'bordered' | 'compact' | 'default' | Visual style. compact tightens section padding and type |
size | 'sm' | 'default' | 'lg' | 'full' | 'default' | sm ≤ 480px, default ≤ 720px (centered), lg full width, full fills the screen with a pinned actions bar |
ref | Ref<View> | — | Ref to the root View |
className | string | — | Additional root classes |
style | StyleProp<ViewStyle> | — | Root style |
IPricingDocumentData
| Field | Type | Description |
|---|---|---|
lineItems | ILineItem[] | Line items |
globalDiscountPercent | number | Document discount % (clamped 0–100) |
adjustment | number | Signed adjustment amount |
currency | ICurrencyConfig | Currency configuration |
config | IPricingConfig | Feature flags / display config |
description | string | Description text |
termsAndConditions | string | Terms text |
status | TPricingDocumentStatus | 'draft' or 'saved' |
totals | ITotals | Calculated totals (output) |
ILineItem
| Field | Type | Description |
|---|---|---|
id | string | Unique id |
position | number | Zero-based order |
productId | string | null | Catalog product id |
categoryId | string | null | Catalog category id |
name | string | Product / service name |
category | string | Category name |
quantity | number | Quantity |
unitPrice | number | Price per unit |
vatRate | number | VAT rate % |
discountPercent | number | Line discount % |
ILineItemCalculated adds the derived lineSubtotal, discountAmount, netAfterDiscount, vatAmount, grossTotal; ILineItemRow is ILineItem & ILineItemCalculated.
ITotals
| Field | Type | Description |
|---|---|---|
subtotal | number | Σ quantity × unit price |
lineDiscountTotal | number | Σ line discounts |
globalDiscountAmount | number | Global discount amount |
totalDiscount | number | Line + global discount |
netTotal | number | Subtotal − total discount |
vatTotal | number | VAT total (scaled by the global discount) |
adjustment | number | Effective adjustment (0 when disabled) |
grandTotal | number | Net + VAT + adjustment |
ICurrencyConfig
| Field | Type | Description |
|---|---|---|
code | string | Primary currency code |
secondaryCurrencyCode | string | null | Secondary currency; null hides the currency bar |
exchangeRate | number | Primary → secondary rate (must be > 0) |
IPricingConfig
showVatColumn, showDiscountColumn, showGrossColumn, showCategoryColumn, discountBeforeVat, enableVat, enableLineDiscount, enableGlobalDiscount, enableAdjustment (boolean), defaultVatRate (number), vatRates (number[]), viewMode (TPricingViewMode) — the same keys as the panel props above.
IProductCatalogItem
| Field | Type | Description |
|---|---|---|
id | string | Product id |
name | string | Name |
category | string | Category name |
categoryId | string | Optional category id |
unitPrice | number | Unit price |
vatRate | number | Optional VAT rate (falls back to defaultVatRate) |
ICategoryCatalogItem
| Field | Type | Description |
|---|---|---|
id | string | Category id |
name | string | Name |
parentId | string | null | Parent id (flat lists) |
children | ICategoryCatalogItem[] | Optional nested children |
IVatSummaryRow
| Field | Type | Description |
|---|---|---|
rate | number | VAT rate % (0 % rows are omitted) |
taxableAmount | number | Taxable base after all discounts |
vatAmount | number | VAT for the rate |
Components
| Component | Description |
|---|---|
PricingEnginePanel | The full panel |
PricingEngineProvider | State provider (same props as web) for building a custom layout |
usePricingEngine | Reads the provider: state, lineItemRows, totals, vatSummary and all mutators (addLineItem, updateLineItem, reorderLineItems, setConfig, save, saveDraft, …) |
pricingEnginePanelVariants | tv() root variants (variant, size) |
DEFAULT_PRICING_CONFIG, DEFAULT_CURRENCY_CONFIG and FINANCIAL_PRECISION are exported too.
Type Exports
| Type | Description |
|---|---|
PricingEnginePanelProps | Props for PricingEnginePanel |
PricingEngineProviderProps / IPricingEngineContext | Provider props / context value |
TPricingViewMode | 'net' | 'gross' |
TDiscountMode | 'before-vat' | 'after-vat' |
TPricingDocumentStatus | 'draft' | 'saved' |
ILineItem, ILineItemCalculated, ILineItemRow | Line item shapes |
ITotals, IVatSummaryRow | Totals / VAT summary |
ICurrencyConfig, IPricingConfig, IPricingDocumentData | Document configuration + snapshot |
IProductCatalogItem, ICategoryCatalogItem | Catalog items |
PricingLineItem, PricingTotals | Deprecated aliases of ILineItem / ITotals |