diff --git a/apps/api/src/categories/categories.service.ts b/apps/api/src/categories/categories.service.ts index 4b883e0..b0cf100 100644 --- a/apps/api/src/categories/categories.service.ts +++ b/apps/api/src/categories/categories.service.ts @@ -1471,15 +1471,20 @@ export class CategoriesService { }; } - // PL24 BOM "bk. tablo:NNN-NNN" rows are cross-references to another - // illustration, not real parts (oem_code "N/A", target code in `remark`). - // Upstream gives us NO navigable link for them — only the text code — so we - // resolve it ourselves: every illustration's code lives in its category name - // as `{NNN-NNN}`, so we build a code→categoryId index for this vehicle and - // attach it. Codes whose target branch hasn't been lazily seeded yet resolve - // to null; the UI then falls back to a pre-filled catalog search. + // PL24 BOM cross-reference rows point to another illustration, not a real part + // (oem_code "N/A", target code in `remark`). Upstream gives us NO navigable + // link — only the text code — so we resolve it ourselves: every illustration's + // code lives in its category name as `{NNN-NNN}`, so we build a code→categoryId + // index for this vehicle and attach it. Codes whose target branch hasn't been + // lazily seeded yet resolve to null; the UI then drills on demand / falls back + // to a pre-filled catalog search. + // + // The "see table" phrasing varies by PL24's own translation: "bk. tablo:" and + // "bakınız tablo, konum:" both occur — match either (the code-in-remark gate + // below keeps this from flagging real parts that merely mention "tablo"). private static readonly REF_CODE_RE = /\d{3}-\d{3}/g; private static readonly REF_CODE_IN_NAME_RE = /\{(\d{3}-\d{3})\}/g; + private static readonly REF_NAME_RE = /b(?:k\.?|akınız)\s+tablo/i; // Build a code→categoryId index for a vehicle from the `{NNN-NNN}` illustration // codes embedded in category names. Reflects only what's been seeded so far. @@ -1502,7 +1507,7 @@ export class CategoriesService { rows: T[], vehicleId: string | null, ): Promise<(T & { references?: Array<{ code: string; categoryId: string | null }> })[]> { - const isRef = (p: T) => p.name?.includes("bk. tablo"); + const isRef = (p: T) => CategoriesService.REF_NAME_RE.test(p.name ?? ""); if (!vehicleId || !rows.some(isRef)) return rows; const index = await this.buildReferenceIndex(vehicleId); diff --git a/apps/web/src/components/schema/parts-panel.tsx b/apps/web/src/components/schema/parts-panel.tsx index c7e2927..ae50723 100644 --- a/apps/web/src/components/schema/parts-panel.tsx +++ b/apps/web/src/components/schema/parts-panel.tsx @@ -202,13 +202,14 @@ export function PartsPanel({ parts, vehicleId, categoryId, isLoading }: PartsPan const isSelected = group != null && selectedGroup === group; const isUnavailable = part.unavailable === true; - // PL24 "bk. tablo:" cross-reference row — not a real part, but a - // jump to another illustration. Render the target table code(s) - // as navigable links instead of a dead "N/A" OEM cell. + // PL24 cross-reference row ("bk. tablo:" / "bakınız tablo, konum:") + // — not a real part, but a jump to another illustration. Render + // the target table code(s) as navigable links instead of a dead + // "N/A" OEM cell, dropping the "see table" tail from the label. const refs = part.references; if (refs && refs.length > 0) { const label = part.name - .replace(/bk\.\s*tablo:?/i, "") + .replace(/b(?:k\.?|akınız)\s+tablo.*$/is, "") .replace(/\s*\/\s*$/, "") .trim(); return (