ServiceTitan-style pricebook management with live in-home quoting. Contractor screens using terracotta palette with Good-Better-Best tier generation.
CategoryList component with trade icons and counts
useQuery(api.pricebook.queries.getCategories)
SearchInput + TaskListItem results
useQuery(api.pricebook.queries.searchTasks, { query })
TaskListItem with subcategory pills and list/grid toggle
useQuery(api.pricebook.queries.getTasksByCategory)
TaskCard with tier badges, breakdown & complexity indicators
showBreakdown={true}, tier color borders from TIER_COLORS
No items added yet
NewQuoteScreen with customer form and featured quick-add
useMutation(api.pricebook.mutations.createQuoteSession)
QuoteItem with qty controls + QuoteSummary footer
handleQuantityChange, handleRemoveItem, handleAddCustomItem
QuoteSummary with Good-Better-Best tier selector
handleTierSelect, useMutation(api.pricebook.mutations.acceptQuote)
QuoteSessionScreen accepted state with tier confirmation
session.status === "accepted", selectedTier === "better"
PricebookImport component with DocumentPicker integration
expo-document-picker + expo-file-system for CSV parsing
PricebookImport parse results with stats & options
useMutation(api.pricebook.import.importPricebook)
pricebookCategories // Top-level trades
pricebookSubcategories // Water Heaters, Drains
pricebookTasks // Billable tasks + pricing
pricebookMaterials // Parts, supplies, SKUs
pricebookTaskMaterials // Task-material junction
pricebookLaborRates // Hourly/flat/per-task
pricebookSettings // Per-contractor config
pricebookQuoteSessions // Live quoting sessions
pricebookPriceHistory // Audit trail
pricebookServiceRegions // Zipcode pricing
getCategories // All categories + counts
getStats // categoryCount, taskCount, rate
getCategoryWithSubcategories
getTasksByCategory // + subcategory filter
searchTasks // name, code, tags
getFeaturedTasks // isFeatured === true
getMostUsedTasks // by usageCount
getQuoteSessions // recent quotes list
getQuoteSession // single session detail
getSettings // tax, markup, display
createQuoteSession
args: customerName, email, phone, address
addItemToQuote
args: sessionId, taskId?, name, qty, prices
presentQuote
args: sessionId // draft -> presented
acceptQuote
args: sessionId, selectedTier?
importPricebook
args: rows[], skipInvalid, updateExisting
CategoryList // FlatList + CategoryCard
TaskCard // Full card w/ breakdown
TaskListItem // Compact list row
QuoteItem // Line item + qty controls
QuoteSummary // Totals + tier selector
PricebookImport // CSV parse + import
draft // Being built by contractor
presented // Shown to customer on-site
accepted // Customer chose a tier
declined // Customer said no
expired // Session timed out
converted // Became a contract/bid
// Complexity levels
simple → 15-30 min, apprentice
standard → 30-90 min, journeyman
complex → 1-4 hours, senior tech
expert → 4+ hours, specialist
// Good-Better-Best pricing
good → goodTierDiscount (-15%)
better → base price (recommended)
best → bestTierUpcharge (+25%)