change UI & fix bugs

This commit is contained in:
2026-09-14 16:32:03 +03:30
parent 602da7f860
commit 4660b4f922
16 changed files with 693 additions and 63 deletions
+48
View File
@@ -0,0 +1,48 @@
export type ProductColorEntry = {
name: string;
imageUrl?: string;
};
export function parseColorEntries(
colorsJson: unknown,
fallbackColor?: string,
): ProductColorEntry[] {
if (!Array.isArray(colorsJson) || colorsJson.length === 0) {
const name = fallbackColor?.trim();
return name ? [{ name }] : [];
}
return colorsJson
.map((item): ProductColorEntry | null => {
if (typeof item === 'string') {
const name = item.trim();
return name ? { name } : null;
}
if (item && typeof item === 'object') {
const raw = item as { name?: unknown; imageUrl?: unknown };
const name = String(raw.name ?? '').trim();
if (!name) return null;
const imageUrl =
typeof raw.imageUrl === 'string' && raw.imageUrl.trim()
? raw.imageUrl
: undefined;
return { name, imageUrl };
}
return null;
})
.filter((entry): entry is ProductColorEntry => Boolean(entry));
}
export function mergeProductImages(
entries: ProductColorEntry[],
imageUrlsJson: unknown,
): string[] {
const extras = Array.isArray(imageUrlsJson)
? imageUrlsJson.filter((url): url is string => typeof url === 'string' && url.trim().length > 0)
: [];
const fromColors = entries
.map((entry) => entry.imageUrl)
.filter((url): url is string => Boolean(url));
const seen = new Set(fromColors);
return [...fromColors, ...extras.filter((url) => !seen.has(url))];
}
+2 -2
View File
@@ -128,7 +128,7 @@ export class CreateProductDto {
isNew?: boolean;
@IsOptional()
colorsJson?: string[];
colorsJson?: Array<string | { name: string; imageUrl?: string }>;
@IsOptional()
imageUrlsJson?: string[];
@@ -253,7 +253,7 @@ export class UpdateProductDto {
isNew?: boolean;
@IsOptional()
colorsJson?: string[];
colorsJson?: Array<string | { name: string; imageUrl?: string }>;
@IsOptional()
imageUrlsJson?: string[];
+17 -12
View File
@@ -7,6 +7,7 @@ import { Prisma } from '@prisma/client';
import { PrismaService } from '../prisma/prisma.service';
import { CreateProductDto, UpdateProductDto } from './dto/product.dto';
import { loadCatalogCategories } from '../catalog/category-defs';
import { mergeProductImages, parseColorEntries } from './color-entries';
@Injectable()
export class ProductsService {
@@ -107,8 +108,8 @@ export class ProductsService {
subtitle: dto.subtitle?.trim() || null,
rollMeters: dto.rollMeters,
isNew: dto.isNew,
colorsJson: dto.colorsJson ?? undefined,
imageUrlsJson: dto.imageUrlsJson ?? undefined,
colorsJson: (dto.colorsJson ?? undefined) as Prisma.InputJsonValue | undefined,
imageUrlsJson: (dto.imageUrlsJson ?? undefined) as Prisma.InputJsonValue | undefined,
tagsJson: dto.tagsJson ?? undefined,
},
include: {
@@ -188,8 +189,14 @@ export class ProductsService {
: dto.subtitle?.trim() || null,
rollMeters: dto.rollMeters,
isNew: dto.isNew,
colorsJson: dto.colorsJson,
imageUrlsJson: dto.imageUrlsJson,
colorsJson:
dto.colorsJson === undefined
? undefined
: (dto.colorsJson as Prisma.InputJsonValue),
imageUrlsJson:
dto.imageUrlsJson === undefined
? undefined
: (dto.imageUrlsJson as Prisma.InputJsonValue),
tagsJson: dto.tagsJson,
},
include: {
@@ -303,11 +310,10 @@ export class ProductsService {
},
hidePrice = false,
) {
const colors = Array.isArray(product.colorsJson)
? (product.colorsJson as string[])
: product.color
? [product.color]
: [];
const colorEntries = parseColorEntries(product.colorsJson, product.color);
const colors = colorEntries.map((entry) => entry.name);
const colorImages = colorEntries.map((entry) => entry.imageUrl ?? null);
const imageUrls = mergeProductImages(colorEntries, product.imageUrlsJson);
const tags = Array.isArray(product.tagsJson)
? (product.tagsJson as string[])
: [];
@@ -340,10 +346,9 @@ export class ProductsService {
weightGrams: product.weightGrams ?? undefined,
weaveType: product.weaveType ?? undefined,
colors,
colorImages,
tags,
imageUrls: Array.isArray(product.imageUrlsJson)
? product.imageUrlsJson
: [],
imageUrls,
subtitle: product.subtitle ?? undefined,
rollMeters: product.rollMeters ?? 50,
isNew: product.isNew ?? false,