Add new quote form redesign spec

This commit is contained in:
SJCoetz 2026-07-09 17:53:44 +02:00
parent 18334721cb
commit 1992b0f4af

View file

@ -0,0 +1,266 @@
# New Quote Form Redesign
**Goal:** Redesign the `New Quote` sheet so operators can select a customer/company in one combined field, capture item descriptions without pricing noise, and attach photos or voice notes directly to each quote item.
## Scope
### In Scope
- Replace the separate `Customer` and `Company` dropdowns in `New Quote` with one combined searchable picker
- Reuse the same interaction pattern already used on the `New Order` form
- Show customer choices in a company-first visual hierarchy
- Auto-link the selected customer to its company
- Keep company-only selection available when there is no customer/contact record
- Remove `Supplier`, `Cost`, and `Sell` from quote item creation
- Change quote item entry from a dense pricing table into stacked item cards
- Make each quote item description a multi-line field
- Keep one small quote-level summary field for overall RFQ context
- Allow per-item uploads for photos, voice notes, and other supporting files
- Persist per-item uploads into the existing `quote_item_attachments` collection
### Out of Scope
- Redesigning the quote detail page or quote process page
- AI transcription of voice notes
- Auto-splitting one pasted block into multiple quote items
- Quote-level attachment redesign
- Changes to sprint pricing workflow beyond supporting attachments created from `New Quote`
## Current State
- `New Quote` currently uses two separate dropdowns:
- `Customer`
- `Company`
- The customer dropdown shows only one label per option, which hides the company/customer relationship
- Quote items currently ask for:
- description
- qty
- supplier
- cost
- sell
- That layout assumes the operator is pricing the quote at creation time, which does not match the intended workflow
- The app already has:
- a combined customer/company picker on `New Order`
- an existing `quote_item_attachments` collection
- an existing server upload route pattern for `quote_item_attachments`
## User Decisions Locked In
- Use a combined customer/company field, not two separate dropdowns
- Follow the same pattern as the `New Order` form
- Keep a small quote-level summary instead of removing it entirely
- Use quote item descriptions as the main place for the requested items
- Quote item descriptions should be multi-line
- Photos and voice notes should attach to individual quote items
## Proposed UX
### Header Fields
The quote header becomes:
- `Customer or Company`
- `RFQ Number`
- `Customer Request` (rename from the current generic quote description)
- `Internal Notes`
`Customer or Company` is the primary selector and replaces the current split header fields.
### Combined Customer / Company Picker
Use the same searchable popover + command list pattern already used in `New Order`.
#### Option Types
1. Customer-linked option
- Visual format:
- line 1: company name
- line 2: customer name
- Selecting it sets:
- `customer = selected customer id`
- `company = linked company id`
2. Company-only option
- Used when a company exists without a customer/contact record
- Visual format:
- line 1: company name
- line 2: `No contact`
- Selecting it sets:
- `company = selected company id`
- `customer = ""`
#### Display Rules
- The trigger button must show readable names, never raw ids
- After selection, the sheet should show a compact summary of:
- selected company
- selected customer, when present
- Search should match both company and customer names
## Quote Item Entry
### Replace the Table With Item Cards
The current compact table is too constrained for:
- multi-line descriptions
- per-item notes
- uploads
Replace it with vertically stacked item cards inside the sheet.
Each card contains:
- `Qty`
- `Item Description` (multi-line textarea)
- `Item Notes` (optional, smaller textarea)
- `Attachments`
- remove button
### Fields Removed From New Quote
Do not capture these at quote-creation time:
- supplier
- cost price
- selling price
Those belong later in the pricing workflow, not during intake.
### Description Behavior
- `Item Description` is the main capture field
- It must support messy RFQ input
- One card can hold one long request if the operator wants to keep everything together
- Quantity defaults to `1`
## Attachments
### Per-Item Uploads
Each quote item card gets its own upload area.
Supported intent:
- photos
- voice notes
- PDFs
- screenshots
- other common operator proof/reference files
### Storage Model
Reuse the existing `quote_item_attachments` collection.
For items created from `New Quote`:
- files are uploaded only after the quote and quote items are successfully created
- each uploaded file creates a `quote_item_attachments` row pointing to the created `quote_item`
- `source` should use `"manual"`
### Upload Timing
Recommended flow:
1. operator fills the quote form
2. operator picks files on one or more item cards
3. submit creates:
- the `quotes` record
- the `quote_items` records
4. after each quote item exists, upload its files through a server route that writes to `quote_item_attachments`
5. if an attachment upload fails:
- the quote still exists
- the operator gets a clear partial-failure message naming the affected item/file
## Data Model
### Quote Record
Keep the current relational shape:
- `customer`: PocketBase relation id
- `company`: PocketBase relation id
Do not switch the quote record to plain-text-only customer/company storage.
Reason:
- relational links are still required for downstream quote, order, and reporting flows
- the UI problem is display and selection, not the underlying relation model
### Quote Item Record
Create `quote_items` with:
- `quote`
- `description`
- `quantity`
- `notes`
- `user_edited = true`
Do not write supplier/cost/sell from `New Quote`.
## Validation
- `Customer or Company` selection is required
- At least one quote item is required
- Every quote item needs a non-empty description
- Quantity must be `>= 1`
- Files are optional
## Error Handling
### Form Load
- If customer/company data fails to load, show the existing toast error and disable submission
### Create Flow
- If quote creation fails, stop and show error
- If quote creation succeeds but some item creation fails:
- stop creating additional items
- do not upload any attachments
- keep the created quote and any already-created items
- show a blocking error that the quote was only partially created and must be reviewed manually
- If item creation succeeds but some attachment uploads fail:
- keep the created quote/items
- show a partial-success toast summarizing which uploads failed
### Upload UX
- Show selected files inside the relevant item card before save
- Allow removing a pending file before save
- Show lightweight file chips/list, not a heavy gallery UI
## Testing
### Form Behavior
- selecting a customer option auto-fills the linked company
- selecting a company-only option leaves customer blank
- combined picker renders company/customer labels in the right hierarchy
- submit requires at least one valid item
### Shape Changes
- new quote form no longer renders supplier/cost/sell item fields
- item description uses a textarea, not a one-line input
- item cards support pending attachment display
### Submit Flow
- quote record is created before quote item attachments upload
- created item attachments are associated with the right quote item ids
- item creation failure stops later uploads and reports partial creation clearly
- partial attachment failure reports correctly without deleting the quote
## Acceptance Criteria
- Operators can create a quote using one combined `Customer or Company` field
- Customer options clearly show the company/customer relationship
- The selected UI shows readable names rather than ids
- Quote intake no longer asks for supplier/cost/sell
- Operators can type detailed multi-line item descriptions
- Operators can attach photos or voice notes directly to a quote item
- Attachments are stored against `quote_item_attachments`
- The form remains usable on smaller screens inside the existing sheet pattern