feat: add optional slug field to UpdateSectionDto and update service to support manual slug overrides
This commit is contained in:
@@ -1,4 +1,18 @@
|
|||||||
import { PartialType } from '@nestjs/swagger';
|
import { PartialType, ApiPropertyOptional } from '@nestjs/swagger';
|
||||||
|
import { IsOptional, IsString, Matches, MaxLength, MinLength } from 'class-validator';
|
||||||
import { CreateSectionDto } from './create-section.dto';
|
import { CreateSectionDto } from './create-section.dto';
|
||||||
|
|
||||||
export class UpdateSectionDto extends PartialType(CreateSectionDto) {}
|
export class UpdateSectionDto extends PartialType(CreateSectionDto) {
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
description: 'URL-friendly slug (lowercase letters, digits, hyphens). Auto-regenerated from name if omitted.',
|
||||||
|
example: 'basic-information',
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
@MinLength(2)
|
||||||
|
@MaxLength(100)
|
||||||
|
@Matches(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, {
|
||||||
|
message: 'slug must contain only lowercase letters, digits, and hyphens (no leading/trailing/consecutive hyphens)',
|
||||||
|
})
|
||||||
|
slug?: string;
|
||||||
|
}
|
||||||
|
|||||||
@@ -108,22 +108,27 @@ export class ProfileSectionsService {
|
|||||||
|
|
||||||
const data: any = { ...updateSectionDto };
|
const data: any = { ...updateSectionDto };
|
||||||
|
|
||||||
// If name is being updated, update the slug too
|
// Resolve effective slug: explicit slug from DTO wins; otherwise regenerate from name if name changed
|
||||||
if (updateSectionDto.name) {
|
let effectiveSlug: string | undefined;
|
||||||
const newSlug = this.generateSlug(updateSectionDto.name);
|
if (updateSectionDto.slug) {
|
||||||
|
effectiveSlug = updateSectionDto.slug;
|
||||||
|
} else if (updateSectionDto.name) {
|
||||||
|
effectiveSlug = this.generateSlug(updateSectionDto.name);
|
||||||
|
}
|
||||||
|
|
||||||
// Check if new slug conflicts with another section
|
if (effectiveSlug) {
|
||||||
|
// Check if slug conflicts with another section
|
||||||
const existing = await this.prisma.profileSection.findFirst({
|
const existing = await this.prisma.profileSection.findFirst({
|
||||||
where: {
|
where: {
|
||||||
AND: [{ id: { not: id } }, { slug: newSlug }],
|
AND: [{ id: { not: id } }, { slug: effectiveSlug }],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (existing) {
|
if (existing) {
|
||||||
throw new ConflictException('A section with this name already exists');
|
throw new ConflictException('A section with this slug already exists');
|
||||||
}
|
}
|
||||||
|
|
||||||
data.slug = newSlug;
|
data.slug = effectiveSlug;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.prisma.profileSection.update({
|
return this.prisma.profileSection.update({
|
||||||
|
|||||||
Reference in New Issue
Block a user