diff --git a/src/categories/category-technical-form-ai.service.ts b/src/categories/category-technical-form-ai.service.ts index 8da253a..014b170 100644 --- a/src/categories/category-technical-form-ai.service.ts +++ b/src/categories/category-technical-form-ai.service.ts @@ -131,6 +131,7 @@ export class CategoryTechnicalFormAiService { - multi_value یک لیست تکراری از مقادیر متنی آزاد است (بدون گزینه) برای مقادیر کوتاه چندتایی. - text برای مقادیر کوتاه (ابعاد، وزن، سال مدل). - textarea برای مشخصات طولانی‌تر (ویژگی‌ها، دستورالعمل نگهداری). +- اگر برای این دسته مناسب است، فیلدهای «ابعاد» و «وزن» را به‌صورت text اضافه کن (واحد متریک رایج ایران را در برچسب بیاور، مثلاً سانتی‌متر / کیلوگرم). اگر برای دسته بی‌معناست، اضافه نکن. - مشخصات مهم خریدار را الزامی علامت بزن. - برچسب‌ها باید یکتا و خوانا باشند. - همیشه برچسب‌ها و گزینه‌ها را به فارسی بنویس. diff --git a/src/categories/category-variations.service.ts b/src/categories/category-variations.service.ts index 54743ae..ff1b0e9 100644 --- a/src/categories/category-variations.service.ts +++ b/src/categories/category-variations.service.ts @@ -54,6 +54,31 @@ function uniqueSlug(base: string, used: Set, fallbackIndex: number): str return next; } +function normalizeHex(value: string | null | undefined): string | null { + if (value == null) return null; + const trimmed = value.trim(); + if (!isHexColor(trimmed)) return null; + return trimmed.toUpperCase(); +} + +/** Map value labels → provided hex (later entries win for duplicate labels). */ +function buildColorHexByLabel( + values: string[], + colorHexes: (string | null)[] | undefined, +): Map { + const map = new Map(); + if (!colorHexes?.length) return map; + + values.forEach((raw, index) => { + const label = raw.trim(); + if (!label) return; + const hex = normalizeHex(colorHexes[index] ?? null); + if (hex) map.set(label, hex); + }); + + return map; +} + type ExistingVariation = { id: bigint; name: string; @@ -126,6 +151,10 @@ export class CategoryVariationsService { const uniqueValues = [ ...new Set(variation.values.map((v) => v.trim()).filter(Boolean)), ]; + const hexByLabel = buildColorHexByLabel( + variation.values, + variation.colorHexes, + ); if (current) { matchedExistingIds.add(current.id); @@ -137,7 +166,7 @@ export class CategoryVariationsService { sortOrder: index, }, }); - await this.syncOptions(tx, current, variation.type, uniqueValues); + await this.syncOptions(tx, current, variation.type, uniqueValues, hexByLabel); } else { const created = await tx.categoryVariation.create({ data: { @@ -148,7 +177,13 @@ export class CategoryVariationsService { sortOrder: index, }, }); - await this.createOptions(tx, created.id, variation.type, uniqueValues); + await this.createOptions( + tx, + created.id, + variation.type, + uniqueValues, + hexByLabel, + ); } } @@ -203,6 +238,7 @@ export class CategoryVariationsService { current: ExistingVariation, type: CategoryVariationInputDto['type'], labels: string[], + hexByLabel: Map = new Map(), ) { const usedSlugs = new Set(); const matchedOptionIds = new Set(); @@ -215,7 +251,8 @@ export class CategoryVariationsService { const colorHex = type === 'color' - ? resolveColorHex(label) ?? + ? hexByLabel.get(label) ?? + resolveColorHex(label) ?? existingOption?.colorHex ?? (existingOption && isHexColor(existingOption.value) ? existingOption.value.trim() @@ -270,6 +307,7 @@ export class CategoryVariationsService { variationId: bigint, type: CategoryVariationInputDto['type'], labels: string[], + hexByLabel: Map = new Map(), ) { const usedSlugs = new Set(); await tx.categoryVariationOption.createMany({ @@ -277,7 +315,10 @@ export class CategoryVariationsService { variationId, label, value: uniqueSlug(slugifyValue(label), usedSlugs, optionIndex + 1), - colorHex: type === 'color' ? resolveColorHex(label) : null, + colorHex: + type === 'color' + ? hexByLabel.get(label) ?? resolveColorHex(label) + : null, sortOrder: optionIndex, })), }); diff --git a/src/categories/dto/category-variation.dto.ts b/src/categories/dto/category-variation.dto.ts index 5984dab..365a181 100644 --- a/src/categories/dto/category-variation.dto.ts +++ b/src/categories/dto/category-variation.dto.ts @@ -3,6 +3,7 @@ import { ArrayMinSize, IsArray, IsIn, + IsOptional, IsString, MinLength, ValidateNested, @@ -21,6 +22,11 @@ export class CategoryVariationInputDto { @ArrayMinSize(1) @IsString({ each: true }) values!: string[]; + + /** Optional parallel list of hex colors for `color` variations (same order as values). */ + @IsOptional() + @IsArray() + colorHexes?: (string | null)[]; } export class ReplaceCategoryVariationsDto {