feat: Add public endpoint and service to retrieve and merge filterable profile fields with options.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user