-
Notifications
You must be signed in to change notification settings - Fork 0
Server/feat/student api #34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
536fc21
a5a0563
a1d56e8
b0df773
02b3f98
deee748
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -13,10 +13,35 @@ export interface Student { | |||||||||||||||||||||||
| // Add other fields as needed | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| export type StudentGender = 'MALE' | 'FEMALE' | 'OTHER'; | ||||||||||||||||||||||||
| export type StudentRole = 'STUDENT'; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| export interface CreateStudentPayload { | ||||||||||||||||||||||||
| name: string; | ||||||||||||||||||||||||
| email: string; | ||||||||||||||||||||||||
| password: string; | ||||||||||||||||||||||||
| gender: StudentGender; | ||||||||||||||||||||||||
| academicYearId: string; | ||||||||||||||||||||||||
| role?: StudentRole; | ||||||||||||||||||||||||
| phone?: string; | ||||||||||||||||||||||||
| address?: string; | ||||||||||||||||||||||||
| dateOfBirth?: string; // ISO date string | ||||||||||||||||||||||||
| image?: string; | ||||||||||||||||||||||||
| parentId?: string; | ||||||||||||||||||||||||
| classId?: string; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| export async function getStudents(page = 1, limit = 10): Promise<PaginatedResponse<Student>> { | ||||||||||||||||||||||||
| return apiRequest<PaginatedResponse<Student>>(`/students?page=${page}&limit=${limit}`); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| export async function getStudent(id: string): Promise<Student> { | ||||||||||||||||||||||||
| return apiRequest<Student>(`/students/${id}`); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| export async function createStudent(payload: CreateStudentPayload): Promise<Student> { | ||||||||||||||||||||||||
| return apiRequest<Student>('/students', { | ||||||||||||||||||||||||
| method: 'POST', | ||||||||||||||||||||||||
| body: payload, | ||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||
|
Comment on lines
+42
to
+46
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win Serialize the POST body before calling
return apiRequest<Student>('/students', {
method: 'POST',
- body: payload,
+ body: JSON.stringify(payload),
});📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
Large diffs are not rendered by default.
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,50 +1,94 @@ | ||
| import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; | ||
| import { | ||
| IsDateString, | ||
| IsEmail, | ||
| IsEnum, | ||
| IsNotEmpty, | ||
| IsOptional, | ||
| IsString, | ||
| IsStrongPassword, | ||
| MaxLength, | ||
| } from 'class-validator'; | ||
| import { UserGender, UserRole } from '../../../prisma/generated/prisma/client'; | ||
| import { UserGender } from '../../../prisma/generated/prisma/client'; | ||
|
|
||
| export class CreateUserDto { | ||
| @ApiProperty({ | ||
| type: String, | ||
| example: 'john doe', | ||
| }) | ||
| @IsString() | ||
| @IsNotEmpty() | ||
| @MaxLength(200) | ||
| @MaxLength(400) | ||
| name!: string; | ||
|
|
||
| @ApiProperty({ | ||
| type: String, | ||
| example: 'johndoe@example.com', | ||
| }) | ||
| @IsNotEmpty() | ||
| @IsEmail() | ||
| email!: string; | ||
|
|
||
| @ApiProperty({ | ||
| type: String, | ||
| example: 'password123', | ||
| }) | ||
| @IsString() | ||
| @IsStrongPassword() | ||
| @IsNotEmpty() | ||
| password!: string; | ||
|
Comment on lines
+32
to
39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '\n== File context ==\n'
git ls-files server/src/common/dto/create-user.dto.ts
wc -l server/src/common/dto/create-user.dto.ts
cat -n server/src/common/dto/create-user.dto.ts | sed -n '1,120p'
printf '\n== class-validator version refs ==\n'
rg -n '"class-validator"|from '\''class-validator'\''|from \"class-validator\"' -S package.json server package-lock.json yarn.lock pnpm-lock.yaml 2>/dev/null || true
printf '\n== StrongPassword usages ==\n'
rg -n "`@IsStrongPassword`\(" server -S || true
printf '\n== Nearby DTO patterns ==\n'
rg -n "`@ApiProperty`\\(|example:" server/src/common/dto -S || trueRepository: thureinhtet99/student-os Length of output: 5154 Use a strong-password-compliant example 🤖 Prompt for AI Agents |
||
|
|
||
| @ApiPropertyOptional({ | ||
| type: String, | ||
| example: '123456789', | ||
| nullable: true, | ||
| }) | ||
| @IsString() | ||
| @IsNotEmpty() | ||
| @IsOptional() | ||
| @MaxLength(15) | ||
| phone!: string | null; | ||
| phone?: string | null; | ||
|
|
||
| @ApiPropertyOptional({ | ||
| type: String, | ||
| example: '123 Main St, Anytown', | ||
| nullable: true, | ||
| }) | ||
| @IsString() | ||
| @IsOptional() | ||
| @MaxLength(500) | ||
| address!: string | null; | ||
| @MaxLength(200) | ||
| address?: string | null; | ||
|
|
||
| @ApiProperty({ | ||
| type: String, | ||
| example: 'MALE', | ||
| }) | ||
| @IsNotEmpty() | ||
| @IsEnum(UserGender) | ||
| gender!: UserGender; | ||
|
|
||
| @ApiPropertyOptional({ | ||
| type: String, | ||
| example: '2005-08-24T00:00:00.000Z', | ||
| nullable: true, | ||
| }) | ||
| @IsDateString() | ||
| @IsOptional() | ||
| dateOfBirth!: string | null; | ||
| dateOfBirth?: string | null; | ||
|
|
||
| @ApiPropertyOptional({ | ||
| type: String, | ||
| example: 'http://example.com/image.png', | ||
| nullable: true, | ||
| }) | ||
| @IsString() | ||
| @IsOptional() | ||
| image!: string | null; | ||
| image?: string | null; | ||
|
|
||
| @IsEnum(UserRole) | ||
| @IsOptional() | ||
| role!: UserRole; | ||
| // @ApiProperty({ | ||
| // type: String, | ||
| // example: 'STUDENT', | ||
| // }) | ||
| // @IsNotEmpty() | ||
| // @IsEnum(UserRole) | ||
| // role!: UserRole; | ||
| } | ||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,21 +5,27 @@ export function formatStudent( | |
| student: StudentWithRelations, | ||
| ): StudentResponseDto { | ||
| return { | ||
| id: student.user.id, | ||
| id: student.id, | ||
| userId: student.user.id, | ||
| name: student.user.name, | ||
| email: student.user.email, | ||
| studentId: student.studentNumber, | ||
| studentNumber: student.studentNumber, | ||
| image: student.user.image, | ||
| phone: student.phone, | ||
| address: student.address, | ||
| gender: student.gender, | ||
| dateOfBirth: student.dateOfBirth ? student.dateOfBirth.toISOString() : null, | ||
| parent_student_relationship: student.parents?.[0]?.relationship ?? null, | ||
| parent: student.parents?.[0]?.parent | ||
| ? { | ||
| id: student.parents[0].parent.id, | ||
| name: student.parents[0].parent.name, | ||
| phone: student.parents[0].parent.phone, | ||
| address: student.parents[0].parent.address, | ||
| } | ||
| : null, | ||
| class: student.enrollments?.[0]?.class | ||
| ? { | ||
| id: student.enrollments[0].class.id, | ||
| name: student.enrollments[0].class.name, | ||
| name: student.enrollments?.[0].class.name, | ||
| } | ||
| : null, | ||
|
Comment on lines
26
to
30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Unresolved from a previous review (previously about 🤖 Prompt for AI Agents |
||
| setPasswordToken: student.user.setPasswordToken, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| import { UserGender } from '../../../prisma/generated/prisma/client'; | ||
|
|
||
| export function formatGender(gender: string): UserGender { | ||
| export function formatGender(gender: UserGender): UserGender { | ||
| return gender.toUpperCase() as UserGender; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: thureinhtet99/student-os
Length of output: 50380
🏁 Script executed:
Repository: thureinhtet99/student-os
Length of output: 10287
🏁 Script executed:
Repository: thureinhtet99/student-os
Length of output: 5622
Serialize the student-create payload before sending it.
createStudentpasses a plain object asbody, butfetchexpects serialized JSON here. Stringify the payload before callingapiRequest(or handle serialization centrally inapiRequest).🤖 Prompt for AI Agents