feat: Add public endpoint and service to retrieve and merge filterable profile fields with options.

This commit is contained in:
pradeepkumar
2026-02-01 15:04:28 +05:30
parent 2e6b3662af
commit 91d4625fcd
2 changed files with 75 additions and 1 deletions

View File

@@ -16,6 +16,7 @@ import { CreateFieldDto, UpdateFieldDto } from './dto';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { RolesGuard } from '../auth/guards/roles.guard';
import { Roles } from '../auth/decorators/roles.decorator';
import { Public } from '../auth/decorators/public.decorator';
import { UserRole } from '@prisma/client';
@ApiTags('Profile Fields')
@@ -23,6 +24,13 @@ import { UserRole } from '@prisma/client';
export class ProfileFieldsController {
constructor(private readonly fieldsService: ProfileFieldsService) {}
@Public()
@Get('filterable')
@ApiOperation({ summary: 'Get all filterable fields with options (Public)' })
getFilterableFields() {
return this.fieldsService.getFilterableFields();
}
@Post()
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles(UserRole.ADMIN)

View File

@@ -1,5 +1,5 @@
import { Injectable, NotFoundException, ConflictException, BadRequestException } from '@nestjs/common';
import { Prisma } from '@prisma/client';
import { Prisma, FieldType } from '@prisma/client';
import { PrismaService } from '../prisma';
import { CreateFieldDto, UpdateFieldDto } from './dto';
@@ -230,4 +230,70 @@ export class ProfileFieldsService {
return { success: true, updated: updates.length };
}
/**
* Get all filterable fields (public endpoint for search filters)
* Returns fields with CHECKBOX_GROUP, SELECT, MULTI_SELECT types that have options
*/
async getFilterableFields() {
const filterableTypes: FieldType[] = [FieldType.CHECKBOX_GROUP, FieldType.SELECT, FieldType.MULTI_SELECT];
const fields = await this.prisma.profileField.findMany({
where: {
isActive: true,
fieldType: { in: filterableTypes },
options: { not: Prisma.JsonNull },
},
select: {
id: true,
name: true,
slug: true,
fieldType: true,
options: true,
section: {
select: {
id: true,
name: true,
slug: true,
},
},
},
orderBy: [
{ section: { sortOrder: 'asc' } },
{ sortOrder: 'asc' },
],
});
// Group fields by slug to merge options from different sections (same field in different agent types)
const mergedFields = new Map<string, {
slug: string;
name: string;
fieldType: string;
options: { label: string; value: string }[];
}>();
for (const field of fields) {
const existingField = mergedFields.get(field.slug);
const fieldOptions = (field.options as { label: string; value: string }[]) || [];
if (existingField) {
// Merge options, avoiding duplicates by value
const existingValues = new Set(existingField.options.map(o => o.value));
for (const opt of fieldOptions) {
if (!existingValues.has(opt.value)) {
existingField.options.push(opt);
}
}
} else {
mergedFields.set(field.slug, {
slug: field.slug,
name: field.name,
fieldType: field.fieldType,
options: [...fieldOptions],
});
}
}
return Array.from(mergedFields.values());
}
}