Docyrus

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.

iOSAndroid
Preview PricingEnginePanel on your device

Scan with Expo Go

Download Expo Go, then scan the QR code to preview native components.

Installation

pnpm dlx @docyrus/cli add @docyrus/rn-pricing-engine-panel

Usage

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 following viewMode, subtotal / discount / VAT chips). Tap a card to edit it in a bottom sheet (numeric keyboards, live subtotal → discount → net → VAT → gross breakdown); Done commits, Cancel discards. 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 productCatalog the 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 calls onProductSelect when provided.
  • Categories — with a categoryCatalog (flat parentId list or nested children) 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 + optional onCategorySelect button.
  • 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-locale Intl currency 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 web ui.pricing.* keys and English fallbacks.

API Reference

PricingEnginePanelProps

PropTypeDefaultDescription
valuePartial<IPricingDocumentData>—Controlled document state. Every change of the object is applied to the internal state
defaultValuePartial<IPricingDocumentData>—Initial document state (uncontrolled)
showVatColumnbooleantrueShow the VAT chip on line cards and the VAT-rate field in the line editor
showDiscountColumnbooleantrueShow the line-discount chip and the discount field
showGrossColumnbooleantrueShow the gross amount under the net headline (net view)
showCategoryColumnbooleantrueShow the line category and the category field
discountBeforeVatbooleantruetrue: discount the net subtotal, then add VAT. false: VAT on the subtotal, discount applied to the VAT-inclusive amount
enableVatbooleantrueEnable VAT calculation, VAT total and VAT summary
enableLineDiscountbooleantrueEnable per-line discount %
enableGlobalDiscountbooleantrueEnable the document-level discount % (applied after line discounts)
enableAdjustmentbooleantrueEnable the signed adjustment amount added to the grand total
defaultVatRatenumber18VAT rate for new lines and for products without vatRate
vatRatesnumber[][0, 1, 8, 10, 18, 20]Selectable VAT rates
defaultCurrencystring'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
productCatalogIProductCatalogItem[]—Static product list. Enables the searchable product picker
categoryCatalogICategoryCatalogItem[]—Static categories (flat with parentId, or nested children). Enables the drill-down category picker
titlestring—Header title (a Draft / Saved status badge is shown next to it)
readOnlybooleanfalseDisable editing: no editor sheet, row menu, settings, add or actions
showDescriptionbooleantrueShow the description editor
showTermsbooleantrueShow the terms & conditions editor (tabs when both are shown)
showActionsbooleantrueShow 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
refRef<View>—Ref to the root View
classNamestring—Additional root classes
styleStyleProp<ViewStyle>—Root style

IPricingDocumentData

FieldTypeDescription
lineItemsILineItem[]Line items
globalDiscountPercentnumberDocument discount % (clamped 0–100)
adjustmentnumberSigned adjustment amount
currencyICurrencyConfigCurrency configuration
configIPricingConfigFeature flags / display config
descriptionstringDescription text
termsAndConditionsstringTerms text
statusTPricingDocumentStatus'draft' or 'saved'
totalsITotalsCalculated totals (output)

ILineItem

FieldTypeDescription
idstringUnique id
positionnumberZero-based order
productIdstring | nullCatalog product id
categoryIdstring | nullCatalog category id
namestringProduct / service name
categorystringCategory name
quantitynumberQuantity
unitPricenumberPrice per unit
vatRatenumberVAT rate %
discountPercentnumberLine discount %

ILineItemCalculated adds the derived lineSubtotal, discountAmount, netAfterDiscount, vatAmount, grossTotal; ILineItemRow is ILineItem & ILineItemCalculated.

ITotals

FieldTypeDescription
subtotalnumberΣ quantity × unit price
lineDiscountTotalnumberΣ line discounts
globalDiscountAmountnumberGlobal discount amount
totalDiscountnumberLine + global discount
netTotalnumberSubtotal − total discount
vatTotalnumberVAT total (scaled by the global discount)
adjustmentnumberEffective adjustment (0 when disabled)
grandTotalnumberNet + VAT + adjustment

ICurrencyConfig

FieldTypeDescription
codestringPrimary currency code
secondaryCurrencyCodestring | nullSecondary currency; null hides the currency bar
exchangeRatenumberPrimary → 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

FieldTypeDescription
idstringProduct id
namestringName
categorystringCategory name
categoryIdstringOptional category id
unitPricenumberUnit price
vatRatenumberOptional VAT rate (falls back to defaultVatRate)

ICategoryCatalogItem

FieldTypeDescription
idstringCategory id
namestringName
parentIdstring | nullParent id (flat lists)
childrenICategoryCatalogItem[]Optional nested children

IVatSummaryRow

FieldTypeDescription
ratenumberVAT rate % (0 % rows are omitted)
taxableAmountnumberTaxable base after all discounts
vatAmountnumberVAT for the rate

Components

ComponentDescription
PricingEnginePanelThe full panel
PricingEngineProviderState provider (same props as web) for building a custom layout
usePricingEngineReads the provider: state, lineItemRows, totals, vatSummary and all mutators (addLineItem, updateLineItem, reorderLineItems, setConfig, save, saveDraft, …)
pricingEnginePanelVariantstv() root variants (variant, size)

DEFAULT_PRICING_CONFIG, DEFAULT_CURRENCY_CONFIG and FINANCIAL_PRECISION are exported too.

Type Exports

TypeDescription
PricingEnginePanelPropsProps for PricingEnginePanel
PricingEngineProviderProps / IPricingEngineContextProvider props / context value
TPricingViewMode'net' | 'gross'
TDiscountMode'before-vat' | 'after-vat'
TPricingDocumentStatus'draft' | 'saved'
ILineItem, ILineItemCalculated, ILineItemRowLine item shapes
ITotals, IVatSummaryRowTotals / VAT summary
ICurrencyConfig, IPricingConfig, IPricingDocumentDataDocument configuration + snapshot
IProductCatalogItem, ICategoryCatalogItemCatalog items
PricingLineItem, PricingTotalsDeprecated aliases of ILineItem / ITotals

On this page