| @@ -23,8 +23,9 @@ | ||
| 23 | 23 | } from "../components/ui/card"; |
| 24 | 24 | import { ConditionalRender } from "../components/ui/conditional-render"; |
| 25 | 25 | import { Switch } from "../components/ui/switch"; |
| 26 | 26 | import { IconPicker } from "../components/ui/icon-picker"; |
| 27 | +import type { IconPickerValue } from "../lib/icon-picker-types"; | |
| 27 | 28 | |
| 28 | 29 | type FieldOptionRow = { label: string; value: string }; |
| 29 | 30 | |
| 30 | 31 | function parseFieldOptionRows(raw: unknown): FieldOptionRow[] { |
| @@ -70,8 +71,49 @@ | ||
| 70 | 71 | } |
| 71 | 72 | return {}; |
| 72 | 73 | } |
| 73 | 74 | |
| 75 | +/** Map API / DB icon field to IconPicker state (must keep `provider` for Font Awesome). */ | |
| 76 | +function iconFromAttributeApiRaw(raw: unknown): IconPickerValue | null { | |
| 77 | + if (raw == null || raw === "") { | |
| 78 | + return null; | |
| 79 | + } | |
| 80 | + let ic: unknown = raw; | |
| 81 | + if (typeof ic === "string") { | |
| 82 | + const t = ic.trim(); | |
| 83 | + if (t.startsWith("{")) { | |
| 84 | + try { | |
| 85 | + ic = JSON.parse(t) as unknown; | |
| 86 | + } catch { | |
| 87 | + return t ? { type: "icon", value: t, provider: "yatra" } : null; | |
| 88 | + } | |
| 89 | + } else if (t !== "") { | |
| 90 | + return { type: "icon", value: t, provider: "yatra" }; | |
| 91 | + } else { | |
| 92 | + return null; | |
| 93 | + } | |
| 94 | + } | |
| 95 | + if (typeof ic !== "object" || ic === null || Array.isArray(ic)) { | |
| 96 | + return null; | |
| 97 | + } | |
| 98 | + const io = ic as { type?: string; value?: unknown; provider?: string }; | |
| 99 | + const val = | |
| 100 | + io.value !== undefined && io.value !== null ? String(io.value) : ""; | |
| 101 | + if (io.type === "image") { | |
| 102 | + if (!val) { | |
| 103 | + return null; | |
| 104 | + } | |
| 105 | + return { type: "image", value: val }; | |
| 106 | + } | |
| 107 | + if (val === "") { | |
| 108 | + return null; | |
| 109 | + } | |
| 110 | + const p = io.provider; | |
| 111 | + const provider = | |
| 112 | + p === "fa-solid" || p === "fa-regular" || p === "yatra" ? p : "yatra"; | |
| 113 | + return { type: "icon", value: val, provider }; | |
| 114 | +} | |
| 115 | + | |
| 74 | 116 | type AttributeStatusUi = "publish" | "draft" | "trash"; |
| 75 | 117 | |
| 76 | 118 | function normalizeAttributeStatusForForm(raw: unknown): AttributeStatusUi { |
| 77 | 119 | const s = typeof raw === "string" ? raw.trim().toLowerCase() : ""; |
| @@ -84,12 +126,9 @@ | ||
| 84 | 126 | interface AttributeFormData { |
| 85 | 127 | name: string; |
| 86 | 128 | slug: string; |
| 87 | 129 | description: string; |
| 88 | - icon: { | |
| 89 | - type: "icon" | "image"; | |
| 90 | - value: string; | |
| 91 | - } | null; | |
| 130 | + icon: IconPickerValue | null; | |
| 92 | 131 | field_type: string; |
| 93 | 132 | field_option_rows: FieldOptionRow[]; |
| 94 | 133 | default_value: string; |
| 95 | 134 | placeholder: string; |
| @@ -361,19 +400,9 @@ | ||
| 361 | 400 | const convertedData: AttributeFormData = { |
| 362 | 401 | name: String(finalAttribute.name ?? ""), |
| 363 | 402 | slug: String(finalAttribute.slug ?? ""), |
| 364 | 403 | description: String(finalAttribute.description ?? ""), |
| 365 | - icon: (() => { | |
| 366 | - const ic = finalAttribute.icon; | |
| 367 | - if (!ic || typeof ic !== "object" || Array.isArray(ic)) { | |
| 368 | - return null; | |
| 369 | - } | |
| 370 | - const io = ic as { type?: string; value?: string }; | |
| 371 | - return { | |
| 372 | - type: io.type === "image" ? "image" : "icon", | |
| 373 | - value: String(io.value ?? ""), | |
| 374 | - }; | |
| 375 | - })(), | |
| 404 | + icon: iconFromAttributeApiRaw(finalAttribute.icon), | |
| 376 | 405 | field_type: String(finalAttribute.field_type ?? "text_field"), |
| 377 | 406 | field_option_rows: (() => { |
| 378 | 407 | const rows = parseFieldOptionRows(finalAttribute.field_options); |
| 379 | 408 | return rows.length > 0 |