Add multi_value technical inputs and FA AI prompts.

Support duplicatable list fields in form builder and value UIs, and guide fill prompts to put leftover specs in سایر ویژگی‌ها.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-09-19 13:50:13 +03:30
co-authored by Cursor
parent 0bbc5bbc12
commit 592540cc7e
17 changed files with 527 additions and 76 deletions
@@ -4,7 +4,12 @@ import type { UserProductListItem } from '../types/userProduct'
export type UserProductCondition = 'new' | 'stock' | 'needs_repair' | 'scrap'
export type UserProductPriceCurrency = 'IRT' | 'USD' | 'EUR' | 'AED'
export type TechnicalFieldType = 'text' | 'textarea' | 'select' | 'multi_select'
export type TechnicalFieldType =
| 'text'
| 'textarea'
| 'select'
| 'multi_select'
| 'multi_value'
export interface UserProductCategoryOption {
id: string
@@ -97,6 +102,44 @@ function businessPath(suffix = '') {
return `/businesses/${businessId}/my-user-products${suffix}`
}
/** Decode free-text list values stored as JSON in text_value. */
export function decodeMultiValueText(raw: string | null | undefined): string[] {
if (raw == null) return []
const trimmed = raw.trim()
if (!trimmed) return []
if (trimmed.startsWith('[')) {
try {
const parsed = JSON.parse(trimmed) as unknown
if (Array.isArray(parsed)) {
return parsed.map((item) => String(item).trim()).filter(Boolean)
}
} catch {
// fall through
}
}
return [trimmed]
}
export function hydrateTechnicalFormValues(
fields: TechnicalFormField[],
values: TechnicalFormValues,
): TechnicalFormValues {
const next: TechnicalFormValues = { ...values }
for (const field of fields) {
if (field.type !== 'multi_value') continue
const current = next[field.id]
if (Array.isArray(current)) continue
if (typeof current === 'string') {
next[field.id] = decodeMultiValueText(current)
} else {
next[field.id] = []
}
}
return next
}
export function buildTechnicalValuesPayload(
fields: TechnicalFormField[],
values: TechnicalFormValues,
@@ -113,6 +156,15 @@ export function buildTechnicalValuesPayload(
continue
}
if (field.type === 'multi_value') {
const items = Array.isArray(value)
? value.map((item) => String(item).trim()).filter(Boolean)
: []
if (!items.length) continue
payload.push({ fieldId: field.id, textValue: JSON.stringify(items) })
continue
}
if (field.type === 'select') {
const optionId = typeof value === 'string' ? value.trim() : ''
if (!optionId) continue