feat: Add POST /api/v1/families endpoint for creating new families
Some checks failed
ParentFlow CI/CD Pipeline / Backend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Frontend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Security Scanning (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-app/maternal-app-backend dockerfile:Dockerfile.production name:backend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-web dockerfile:Dockerfile.production name:frontend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Development (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / Lint and Test (push) Has been cancelled
CI/CD Pipeline / E2E Tests (push) Has been cancelled
CI/CD Pipeline / Build Application (push) Has been cancelled
Some checks failed
ParentFlow CI/CD Pipeline / Backend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Frontend Tests (push) Has been cancelled
ParentFlow CI/CD Pipeline / Security Scanning (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-app/maternal-app-backend dockerfile:Dockerfile.production name:backend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Build Docker Images (map[context:maternal-web dockerfile:Dockerfile.production name:frontend]) (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Development (push) Has been cancelled
ParentFlow CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / Lint and Test (push) Has been cancelled
CI/CD Pipeline / E2E Tests (push) Has been cancelled
CI/CD Pipeline / Build Application (push) Has been cancelled
- Created CreateFamilyDto to validate family creation requests - Added createFamily() service method with duplicate family check - Implemented POST /api/v1/families controller endpoint - Auto-creates family with parent role and full permissions - Fixes 404 error during onboarding flow 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,8 @@
|
|||||||
|
import { IsString, IsNotEmpty, MaxLength } from 'class-validator';
|
||||||
|
|
||||||
|
export class CreateFamilyDto {
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
@MaxLength(100)
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
@@ -14,12 +14,33 @@ import {
|
|||||||
import { FamiliesService } from './families.service';
|
import { FamiliesService } from './families.service';
|
||||||
import { InviteFamilyMemberDto } from './dto/invite-family-member.dto';
|
import { InviteFamilyMemberDto } from './dto/invite-family-member.dto';
|
||||||
import { JoinFamilyDto } from './dto/join-family.dto';
|
import { JoinFamilyDto } from './dto/join-family.dto';
|
||||||
|
import { CreateFamilyDto } from './dto/create-family.dto';
|
||||||
import { FamilyRole } from '../../database/entities/family-member.entity';
|
import { FamilyRole } from '../../database/entities/family-member.entity';
|
||||||
|
|
||||||
@Controller('api/v1/families')
|
@Controller('api/v1/families')
|
||||||
export class FamiliesController {
|
export class FamiliesController {
|
||||||
constructor(private readonly familiesService: FamiliesService) {}
|
constructor(private readonly familiesService: FamiliesService) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new family
|
||||||
|
* POST /api/v1/families
|
||||||
|
* Body: { name: string }
|
||||||
|
*/
|
||||||
|
@Post()
|
||||||
|
async createFamily(@Req() req: any, @Body() createFamilyDto: CreateFamilyDto) {
|
||||||
|
const family = await this.familiesService.createFamily(
|
||||||
|
req.user.userId,
|
||||||
|
createFamilyDto,
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
data: {
|
||||||
|
family,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Post('invite')
|
@Post('invite')
|
||||||
async inviteMember(
|
async inviteMember(
|
||||||
@Req() req: any,
|
@Req() req: any,
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
import { User } from '../../database/entities/user.entity';
|
import { User } from '../../database/entities/user.entity';
|
||||||
import { InviteFamilyMemberDto } from './dto/invite-family-member.dto';
|
import { InviteFamilyMemberDto } from './dto/invite-family-member.dto';
|
||||||
import { JoinFamilyDto } from './dto/join-family.dto';
|
import { JoinFamilyDto } from './dto/join-family.dto';
|
||||||
|
import { CreateFamilyDto } from './dto/create-family.dto';
|
||||||
import { EmailService } from '../../common/services/email.service';
|
import { EmailService } from '../../common/services/email.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@@ -29,6 +30,53 @@ export class FamiliesService {
|
|||||||
private emailService: EmailService,
|
private emailService: EmailService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new family
|
||||||
|
*/
|
||||||
|
async createFamily(
|
||||||
|
userId: string,
|
||||||
|
createFamilyDto: CreateFamilyDto,
|
||||||
|
): Promise<Family> {
|
||||||
|
// Check if user already has a family
|
||||||
|
const existingMembership = await this.familyMemberRepository.findOne({
|
||||||
|
where: { userId },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (existingMembership) {
|
||||||
|
throw new ConflictException(
|
||||||
|
'You are already a member of a family. Leave your current family before creating a new one.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the family (ID and shareCode are auto-generated via @BeforeInsert)
|
||||||
|
const family = this.familyRepository.create({
|
||||||
|
name: createFamilyDto.name,
|
||||||
|
shareCodeExpiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days
|
||||||
|
createdBy: userId,
|
||||||
|
subscriptionTier: 'free', // Default tier
|
||||||
|
});
|
||||||
|
|
||||||
|
const savedFamily = await this.familyRepository.save(family);
|
||||||
|
|
||||||
|
// Add creator as a parent (admin) of the family
|
||||||
|
const creatorMembership = this.familyMemberRepository.create({
|
||||||
|
userId,
|
||||||
|
familyId: savedFamily.id,
|
||||||
|
role: FamilyRole.PARENT,
|
||||||
|
permissions: {
|
||||||
|
canAddChildren: true,
|
||||||
|
canEditChildren: true,
|
||||||
|
canLogActivities: true,
|
||||||
|
canViewReports: true,
|
||||||
|
canInviteMembers: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.familyMemberRepository.save(creatorMembership);
|
||||||
|
|
||||||
|
return savedFamily;
|
||||||
|
}
|
||||||
|
|
||||||
async inviteMember(
|
async inviteMember(
|
||||||
userId: string,
|
userId: string,
|
||||||
familyId: string,
|
familyId: string,
|
||||||
|
|||||||
Reference in New Issue
Block a user