-
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 4 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; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,23 +5,18 @@ 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, | ||
| parent: student.parents?.[0]?.parent | ||
| ? { | ||
| id: student.parents[0].parent.id, | ||
| name: student.parents[0].parent.name, | ||
| } | ||
| : null, | ||
| class: student.enrollments?.[0]?.class | ||
| ? { | ||
| id: student.enrollments[0].class.id, | ||
| name: student.enrollments[0].class.name, | ||
| } | ||
| : null, | ||
| phone: student.phone, | ||
| address: student.address, | ||
| gender: student.gender, | ||
| dateOfBirth: student.dateOfBirth ? student.dateOfBirth.toISOString() : null, | ||
| parentId: student.parents?.[0]?.parent?.id ?? null, | ||
| classId: student.enrollments?.[0]?.class?.id ?? null, | ||
|
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 | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Check how reference modules (academic-years, classes) handle enrollment scoping.
rg -n 'academicYearId|enrollments' server/src/modules/academic-years/ server/src/modules/classes/ --type ts -C3Repository: thureinhtet99/student-os Length of output: 22399 🏁 Script executed: #!/bin/bash
set -euo pipefail
# Inspect the formatter and the student query paths that populate `student.enrollments`.
for f in \
server/src/common/formatters/student.formatter.ts \
server/src/modules/students/students.service.ts \
server/src/modules/students/students.controller.ts \
server/src/modules/students/dto/*.ts \
server/src/modules/enrollments/*.ts
do
[ -f "$f" ] && echo "### $f" && sed -n '1,260p' "$f" && echo
doneRepository: thureinhtet99/student-os Length of output: 23373 🏁 Script executed: #!/bin/bash
set -euo pipefail
# Check whether student queries ever scope enrollments by academic year or impose a stable order.
rg -n 'academicYearId|enrollments:\s*{|orderBy:.*enrollments|formatStudent\(' server/src/modules/students server/src/common -g '*.ts' -C3
# Inspect the Prisma model for enrollment ordering fields that might make `[0]` deterministic.
rg -n 'model Enrollment|createdAt|updatedAt|academicYearId|studentId|classId' prisma -g '*.prisma' -C3Repository: thureinhtet99/student-os Length of output: 345
🤖 Prompt for AI Agents |
||
| setPasswordToken: student.user.setPasswordToken, | ||
| setPasswordTokenExpires: student.user.setPasswordTokenExpires ?? null, | ||
| resetPasswordToken: student.user.resetPasswordToken, | ||
|
|
||
| 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