# Pricing Engine Panel URL: /docs/web/components/pricing-engine-panel Pricing Engine Panel component. **Demo:** ```tsx 'use client'; import { useState } from 'react'; import { PricingEnginePanel, type ICategoryCatalogItem, type IPricingDocumentData, type IProductCatalogItem } from '@docyrus/ui/components/pricing-engine-panel'; const PRODUCT_CATALOG: IProductCatalogItem[] = [ { id: 'prod-1', name: 'Web Development Services', category: 'Services', categoryId: 'cat-2', unitPrice: 150, vatRate: 18 }, { id: 'prod-2', name: 'UI/UX Design', category: 'Design', categoryId: 'cat-3', unitPrice: 120, vatRate: 18 }, { id: 'prod-3', name: 'Hosting (Annual)', category: 'Infrastructure', categoryId: 'cat-5', unitPrice: 480, vatRate: 8 }, { id: 'prod-4', name: 'Mobile App Development', category: 'Services', categoryId: 'cat-2', unitPrice: 180, vatRate: 18 }, { id: 'prod-5', name: 'SEO Optimization', category: 'Marketing', categoryId: 'cat-4', unitPrice: 90, vatRate: 18 }, { id: 'prod-6', name: 'Domain Registration', category: 'Infrastructure', categoryId: 'cat-5', unitPrice: 15, vatRate: 8 }, { id: 'prod-7', name: 'SSL Certificate', category: 'Infrastructure', categoryId: 'cat-6', unitPrice: 60, vatRate: 8 }, { id: 'prod-8', name: 'Logo Design', category: 'Design', categoryId: 'cat-3', unitPrice: 350 }, { id: 'prod-9', name: 'Social Media Management', category: 'Marketing', categoryId: 'cat-7', unitPrice: 200, vatRate: 18 }, { id: 'prod-10', name: 'Database Administration', category: 'Services', categoryId: 'cat-2', unitPrice: 160, vatRate: 18 } ]; const CATEGORY_CATALOG: ICategoryCatalogItem[] = [ { id: 'cat-1', name: 'Technology', parentId: null }, { id: 'cat-2', name: 'Development', parentId: 'cat-1' }, { id: 'cat-3', name: 'Design', parentId: 'cat-1' }, { id: 'cat-4', name: 'Marketing', parentId: null }, { id: 'cat-7', name: 'Social Media', parentId: 'cat-4' }, { id: 'cat-8', name: 'SEO & SEM', parentId: 'cat-4' }, { id: 'cat-5', name: 'Infrastructure', parentId: 'cat-1' }, { id: 'cat-6', name: 'Security', parentId: 'cat-5' }, { id: 'cat-9', name: 'Consulting', parentId: null }, { id: 'cat-10', name: 'Strategy', parentId: 'cat-9' }, { id: 'cat-11', name: 'Training', parentId: 'cat-9' } ]; export function PricingEnginePanelDemo() { const [lastSaved, setLastSaved] = useState(null); return (
setLastSaved(data)} onSaveDraft={data => setLastSaved(data)} size="full" /> {lastSaved && (

Last saved: {lastSaved.status} — Grand Total: {lastSaved.totals.grandTotal.toFixed(2)} {lastSaved.currency.code}

)}
); } ``` ## Installation ```bash pnpm dlx @docyrus/cli add @docyrus/ui-pricing-engine-panel ``` **Dependencies:** - [lucide-react](https://www.npmjs.com/package/lucide-react) - [class-variance-authority](https://www.npmjs.com/package/class-variance-authority) ## Usage ```tsx import { PricingEnginePanel } from "@docyrus/ui/components/pricing-engine-panel"; import type { PricingEnginePanelProps, TPricingViewMode, TDiscountMode, TPricingDocumentStatus, ILineItem, ILineItemCalculated, ILineItemRow, ITotals, IVatSummaryRow, ICurrencyConfig, IPricingConfig, IPricingDocumentData, IProductCatalogItem, ICategoryCatalogItem } from "@docyrus/ui/components/pricing-engine-panel"; {}} onSave={() => {}} onSaveDraft={() => {}} onProductSelect={() => {}} onCategorySelect={() => {}} productCatalog={IProductCatalogItem[]} categoryCatalog={ICategoryCatalogItem[]} title="..." showDescription={true} showTerms={true} showActions={true} /> ``` ## Variants | Variant | Description | |---------|-------------| | `default` | Default style | | `bordered` | Bordered — `border-2 shadow-sm` | | `compact` | Compact — `text-xs [&_input]:h-7 [&_input]:text-xs` | ## Sizes | Size | Description | |------|-------------| | `sm` | Small — `max-w-3xl mx-auto` | | `default` | Default — `max-w-5xl mx-auto` | | `lg` | Large | | `full` | full — `w-full` | ## API Reference | Prop | Type | Default | |------|------|---------| | `variant` | `"default"` \| `"bordered"` \| `"compact"` | `"default"` | | `size` | `"sm"` \| `"default"` \| `"lg"` \| `"full"` | `"default"` | | `ref` | `Ref` | — | | `value` | `Partial` | — | | `defaultValue` | `Partial` | — | | `showVatColumn` | `boolean` | `true` | | `showDiscountColumn` | `boolean` | `true` | | `showGrossColumn` | `boolean` | `true` | | `showCategoryColumn` | `boolean` | `true` | | `discountBeforeVat` | `boolean` | `true` | | `enableVat` | `boolean` | `true` | | `enableLineDiscount` | `boolean` | `true` | | `enableGlobalDiscount` | `boolean` | `true` | | `enableAdjustment` | `boolean` | `true` | | `defaultVatRate` | `number` | `18` | | `vatRates` | `number[]` | `[ 0` | | `defaultCurrency` | `string` | `'USD'` | | `viewMode` | `TPricingViewMode` | `'net'` | | `onLineItemsChange` | `(items: ILineItem[]) => void` | — | | `onTotalsChange` | `(totals: ITotals) => void` | — | | `onSave` | `(data: IPricingDocumentData) => void` | — | | `onSaveDraft` | `(data: IPricingDocumentData) => void` | — | | `onProductSelect` | `(lineId: string, callback: (product: IProductCatalogItem) => void) => void` | — | | `onCategorySelect` | `(lineId: string, callback: (category: ICategoryCatalogItem) => void) => void` | — | | `productCatalog` | `IProductCatalogItem[]` | — | | `categoryCatalog` | `ICategoryCatalogItem[]` | — | | `title` | `string` | — | | `readOnly` | `boolean` | `false` | | `showDescription` | `boolean` | `true` | | `showTerms` | `boolean` | `true` | | `showActions` | `boolean` | `true` | | `className` | `string` | — | ## Components | Component | Description | |-----------|-------------| | `PricingEnginePanel` | Public export | | `PricingActionsBar` | Internal — `pricing-actions-bar.tsx` | | `PricingCategoryCell` | Internal — `pricing-category-cell.tsx` | | `PricingConfigPopover` | Internal — `pricing-config-popover.tsx` | | `PricingContentSection` | Internal — `pricing-content-section.tsx` | | `PricingCurrencyBar` | Internal — `pricing-currency-bar.tsx` | | `PricingDiscountSection` | Internal — `pricing-discount-section.tsx` | | `PricingHeader` | Internal — `pricing-header.tsx` | | `PricingLineRowActions` | Internal — `pricing-line-row-actions.tsx` | | `PricingLineRow` | Internal — `pricing-line-row.tsx` | | `PricingLineTable` | Internal — `pricing-line-table.tsx` | | `PricingProductCell` | Internal — `pricing-product-cell.tsx` | | `PricingTotalsSection` | Internal — `pricing-totals-section.tsx` | | `PricingVatSummary` | Internal — `pricing-vat-summary.tsx` | | `PricingEngineProvider` | Internal — `contexts/pricing-context.tsx` | ## Type Exports | Type | Description | |------|-------------| | `PricingEnginePanelProps` | — | | `TPricingViewMode` | — | | `TDiscountMode` | — | | `TPricingDocumentStatus` | — | | `ILineItem` | — | | `ILineItemCalculated` | — | | `ILineItemRow` | — | | `ITotals` | — | | `IVatSummaryRow` | — | | `ICurrencyConfig` | — | | `IPricingConfig` | — | | `IPricingDocumentData` | — | | `IProductCatalogItem` | — | | `ICategoryCatalogItem` | — | ## Type Reference ### PricingEnginePanelProps | Field | Type | Description | |-------|------|-------------| | `ref` | `Ref` | — | | `value` | `Partial` | — | | `defaultValue` | `Partial` | — | | `showVatColumn` | `boolean` | — | | `showDiscountColumn` | `boolean` | — | | `showGrossColumn` | `boolean` | — | | `showCategoryColumn` | `boolean` | — | | `discountBeforeVat` | `boolean` | — | | `enableVat` | `boolean` | — | | `enableLineDiscount` | `boolean` | — | | `enableGlobalDiscount` | `boolean` | — | | `enableAdjustment` | `boolean` | — | | `defaultVatRate` | `number` | — | | `vatRates` | `number[]` | — | | `defaultCurrency` | `string` | — | | `viewMode` | `TPricingViewMode` | — | | `onLineItemsChange` | `(items: ILineItem[]) => void` | — | | `onTotalsChange` | `(totals: ITotals) => void` | — | | `onSave` | `(data: IPricingDocumentData) => void` | — | | `onSaveDraft` | `(data: IPricingDocumentData) => void` | — | | `onProductSelect` | `(lineId: string, callback: (product: IProductCatalogItem) => void) => void` | — | | `onCategorySelect` | `(lineId: string, callback: (category: ICategoryCatalogItem) => void) => void` | — | | `productCatalog` | `IProductCatalogItem[]` | — | | `categoryCatalog` | `ICategoryCatalogItem[]` | — | | `title` | `string` | — | | `readOnly` | `boolean` | — | | `showDescription` | `boolean` | — | | `showTerms` | `boolean` | — | | `showActions` | `boolean` | — | | `variant` | `'default' \| 'bordered' \| 'compact'` | — | | `size` | `'sm' \| 'default' \| 'lg' \| 'full'` | — | ### TPricingViewMode `"net"` | `"gross"` ### TDiscountMode `"before-vat"` | `"after-vat"` ### TPricingDocumentStatus `"draft"` | `"saved"` ### ILineItem | Field | Type | Description | |-------|------|-------------| | `id` | `string` | — | | `position` | `number` | — | | `productId` | `string \| null` | — | | `categoryId` | `string \| null` | — | | `name` | `string` | — | | `category` | `string` | — | | `quantity` | `number` | — | | `unitPrice` | `number` | — | | `vatRate` | `number` | — | | `discountPercent` | `number` | — | ### ILineItemCalculated | Field | Type | Description | |-------|------|-------------| | `lineSubtotal` | `number` | — | | `discountAmount` | `number` | — | | `netAfterDiscount` | `number` | — | | `vatAmount` | `number` | — | | `grossTotal` | `number` | — | ### ILineItemRow | Field | Type | Description | |-------|------|-------------| ### ITotals | Field | Type | Description | |-------|------|-------------| | `subtotal` | `number` | — | | `lineDiscountTotal` | `number` | — | | `globalDiscountAmount` | `number` | — | | `totalDiscount` | `number` | — | | `netTotal` | `number` | — | | `vatTotal` | `number` | — | | `adjustment` | `number` | — | | `grandTotal` | `number` | — | ### IVatSummaryRow | Field | Type | Description | |-------|------|-------------| | `rate` | `number` | — | | `taxableAmount` | `number` | — | | `vatAmount` | `number` | — | ### ICurrencyConfig | Field | Type | Description | |-------|------|-------------| | `code` | `string` | — | | `secondaryCurrencyCode` | `string \| null` | — | | `exchangeRate` | `number` | — | ### IPricingConfig | Field | Type | Description | |-------|------|-------------| | `showVatColumn` | `boolean` | — | | `showDiscountColumn` | `boolean` | — | | `showGrossColumn` | `boolean` | — | | `showCategoryColumn` | `boolean` | — | | `discountBeforeVat` | `boolean` | — | | `enableVat` | `boolean` | — | | `enableLineDiscount` | `boolean` | — | | `enableGlobalDiscount` | `boolean` | — | | `enableAdjustment` | `boolean` | — | | `defaultVatRate` | `number` | — | | `vatRates` | `number[]` | — | | `viewMode` | `TPricingViewMode` | — | ### IPricingDocumentData | Field | Type | Description | |-------|------|-------------| | `lineItems` | `ILineItem[]` | — | | `globalDiscountPercent` | `number` | — | | `adjustment` | `number` | — | | `currency` | `ICurrencyConfig` | — | | `config` | `IPricingConfig` | — | | `description` | `string` | — | | `termsAndConditions` | `string` | — | | `status` | `TPricingDocumentStatus` | — | | `totals` | `ITotals` | — | ### IProductCatalogItem | Field | Type | Description | |-------|------|-------------| | `id` | `string` | — | | `name` | `string` | — | | `category` | `string` | — | | `categoryId` | `string` | — | | `unitPrice` | `number` | — | | `vatRate` | `number` | — | ### ICategoryCatalogItem | Field | Type | Description | |-------|------|-------------| | `id` | `string` | — | | `name` | `string` | — | | `parentId` | `string \| null` | — | | `children` | `ICategoryCatalogItem[]` | — |