@@ -50,6 +50,7 @@ export class ProductController {
|
|||||||
@ApiQuery({ name: 'orderBy', required: false, type: String })
|
@ApiQuery({ name: 'orderBy', required: false, type: String })
|
||||||
@ApiQuery({ name: 'order', required: false, enum: ['asc', 'desc'] })
|
@ApiQuery({ name: 'order', required: false, enum: ['asc', 'desc'] })
|
||||||
@ApiQuery({ name: 'isActive', required: false, type: Boolean })
|
@ApiQuery({ name: 'isActive', required: false, type: Boolean })
|
||||||
|
@ApiQuery({ name: 'parentId', required: false, type: String, description: 'Parent category id, or "null" for roots' })
|
||||||
async findAllCategories(@Query() dto: FindCategoriesDto) {
|
async findAllCategories(@Query() dto: FindCategoriesDto) {
|
||||||
const result = await this.categoryService.findAll(dto);
|
const result = await this.categoryService.findAll(dto);
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -36,4 +36,12 @@ export class FindCategoriesDto {
|
|||||||
@Type(() => Boolean)
|
@Type(() => Boolean)
|
||||||
@ApiPropertyOptional({ example: true })
|
@ApiPropertyOptional({ example: true })
|
||||||
isActive?: boolean;
|
isActive?: boolean;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
description: 'Filter by parent category id. Use "null" for root categories only.',
|
||||||
|
example: 'null',
|
||||||
|
})
|
||||||
|
parentId?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ type FindCategoriesOpts = {
|
|||||||
orderBy?: string;
|
orderBy?: string;
|
||||||
order?: 'asc' | 'desc';
|
order?: 'asc' | 'desc';
|
||||||
isActive?: boolean;
|
isActive?: boolean;
|
||||||
|
parentId?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CategoryTreeNode = {
|
export type CategoryTreeNode = {
|
||||||
@@ -73,7 +74,7 @@ export class CategoryRepository extends EntityRepository<Category> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async findAllPaginated(opts: FindCategoriesOpts = {}): Promise<PaginatedResult<Category>> {
|
async findAllPaginated(opts: FindCategoriesOpts = {}): Promise<PaginatedResult<Category>> {
|
||||||
const { page = 1, limit = 10, search, orderBy = 'createdAt', order = 'desc', isActive } = opts;
|
const { page = 1, limit = 10, search, orderBy = 'order', order = 'asc', isActive, parentId } = opts;
|
||||||
|
|
||||||
const offset = (page - 1) * limit;
|
const offset = (page - 1) * limit;
|
||||||
|
|
||||||
@@ -83,6 +84,12 @@ export class CategoryRepository extends EntityRepository<Category> {
|
|||||||
where.isActive = isActive;
|
where.isActive = isActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parentId === 'null') {
|
||||||
|
where.parent = null;
|
||||||
|
} else if (parentId) {
|
||||||
|
where.parent = parentId;
|
||||||
|
}
|
||||||
|
|
||||||
if (search) {
|
if (search) {
|
||||||
where.$or = [
|
where.$or = [
|
||||||
{ title: { $ilike: `%${search}%` } },
|
{ title: { $ilike: `%${search}%` } },
|
||||||
@@ -91,7 +98,7 @@ export class CategoryRepository extends EntityRepository<Category> {
|
|||||||
|
|
||||||
const allCategories = await this.find(where, {
|
const allCategories = await this.find(where, {
|
||||||
orderBy: { [orderBy]: order.toLowerCase() as 'asc' | 'desc' },
|
orderBy: { [orderBy]: order.toLowerCase() as 'asc' | 'desc' },
|
||||||
populate: ['parent'],
|
populate: ['parent', 'children'],
|
||||||
});
|
});
|
||||||
|
|
||||||
const total = allCategories.length;
|
const total = allCategories.length;
|
||||||
|
|||||||
Reference in New Issue
Block a user