Add category SEO description for storefront category pages.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
835c8a0ac1
commit
b661877d77
@@ -0,0 +1,2 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "Category" ADD COLUMN IF NOT EXISTS "seoDescription" TEXT NOT NULL DEFAULT '';
|
||||
@@ -151,6 +151,8 @@ model Category {
|
||||
packages String[] @default([])
|
||||
/// Ordered form-builder defs: [{ id, labelFa, labelEn?, type: "text", required? }]
|
||||
technicalFields Json @default("[]")
|
||||
/// Long-form SEO / category page copy shown on the storefront
|
||||
seoDescription String @default("")
|
||||
products Product[]
|
||||
|
||||
@@index([storeId])
|
||||
|
||||
@@ -44,6 +44,7 @@ export class CategoriesService {
|
||||
packages: dto.packages ?? [],
|
||||
technicalFields: (dto.technicalFields ??
|
||||
[]) as unknown as Prisma.InputJsonValue,
|
||||
seoDescription: dto.seoDescription ?? '',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -71,6 +72,9 @@ export class CategoriesService {
|
||||
dto.technicalFields as unknown as Prisma.InputJsonValue,
|
||||
}
|
||||
: {}),
|
||||
...(dto.seoDescription !== undefined
|
||||
? { seoDescription: dto.seoDescription }
|
||||
: {}),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -72,6 +72,10 @@ export class CreateCategoryDto {
|
||||
@Type(() => TechnicalFieldDto)
|
||||
technicalFields?: TechnicalFieldDto[];
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
seoDescription?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
storeId?: string;
|
||||
@@ -117,4 +121,8 @@ export class UpdateCategoryDto {
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => TechnicalFieldDto)
|
||||
technicalFields?: TechnicalFieldDto[];
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
seoDescription?: string;
|
||||
}
|
||||
|
||||
@@ -16,13 +16,17 @@ export class PublicController {
|
||||
@Query('storeSlug') storeSlug?: string,
|
||||
@Query('name') name?: string,
|
||||
@Query('categoryId') categoryId?: string,
|
||||
@Query('minPrice') minPrice?: number,
|
||||
@Query('maxPrice') maxPrice?: number,
|
||||
@Query('minPrice') minPrice?: string,
|
||||
@Query('maxPrice') maxPrice?: string,
|
||||
) {
|
||||
const parsedCategoryId =
|
||||
categoryId !== undefined && categoryId !== ''
|
||||
? Number(categoryId)
|
||||
: undefined;
|
||||
const parsedMin =
|
||||
minPrice !== undefined && minPrice !== '' ? Number(minPrice) : undefined;
|
||||
const parsedMax =
|
||||
maxPrice !== undefined && maxPrice !== '' ? Number(maxPrice) : undefined;
|
||||
return this.publicService.listProducts({
|
||||
storeId,
|
||||
storeSlug,
|
||||
@@ -31,8 +35,14 @@ export class PublicController {
|
||||
parsedCategoryId !== undefined && Number.isFinite(parsedCategoryId)
|
||||
? parsedCategoryId
|
||||
: undefined,
|
||||
minPrice,
|
||||
maxPrice,
|
||||
minPrice:
|
||||
parsedMin !== undefined && Number.isFinite(parsedMin)
|
||||
? parsedMin
|
||||
: undefined,
|
||||
maxPrice:
|
||||
parsedMax !== undefined && Number.isFinite(parsedMax)
|
||||
? parsedMax
|
||||
: undefined,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ export type PublicCategoryTreeNode = {
|
||||
nameEn: string;
|
||||
sortOrder: number;
|
||||
imageUrl: string | null;
|
||||
seoDescription: string;
|
||||
children: PublicCategoryTreeNode[];
|
||||
};
|
||||
|
||||
@@ -126,6 +127,7 @@ export class PublicService {
|
||||
nameFa: true,
|
||||
nameEn: true,
|
||||
sortOrder: true,
|
||||
seoDescription: true,
|
||||
products: {
|
||||
where: { published: true },
|
||||
take: 1,
|
||||
@@ -156,6 +158,7 @@ export class PublicService {
|
||||
nameEn: node.nameEn,
|
||||
sortOrder: node.sortOrder,
|
||||
imageUrl: cover,
|
||||
seoDescription: node.seoDescription ?? '',
|
||||
children: walk(node.id),
|
||||
};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user