From a1f4d8054774007d9e74fa3bdc33f93cd617ab7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qu=E1=BB=91c=20Ch=C6=B0=C6=A1ng?= Date: Sun, 5 Jan 2025 13:39:25 +0700 Subject: [PATCH 01/10] update: api get all party with pagination --- .../src/domains/parties/parties.controller.ts | 31 ++++++++++++++++--- .../src/domains/parties/parties.service.ts | 30 ++++++++++++++++++ 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/backend/src/domains/parties/parties.controller.ts b/backend/src/domains/parties/parties.controller.ts index e34d27f..732c991 100644 --- a/backend/src/domains/parties/parties.controller.ts +++ b/backend/src/domains/parties/parties.controller.ts @@ -6,8 +6,14 @@ import { Param, Post, Put, + Query, } from '@nestjs/common'; -import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'; +import { + ApiBearerAuth, + ApiOperation, + ApiQuery, + ApiTags, +} from '@nestjs/swagger'; import { Public } from '@/domains/auth/decorators/public.decorator'; import { Roles } from '@/domains/auth/decorators/roles.decorator'; @@ -30,10 +36,27 @@ export class PartiesController { } @Public() - @ApiOperation({ summary: 'Fetch all parties' }) + @ApiOperation({ summary: 'Fetch all parties with pagination' }) + @ApiQuery({ + name: 'page', + required: false, + type: Number, + example: 1, + description: 'Page number, starts from 1', + }) + @ApiQuery({ + name: 'limit', + required: false, + type: Number, + example: 10, + description: 'Number of items per page', + }) @Get() - async getAll() { - return await this.partiesService.getAll(); + async getAll( + @Query('page') page: number = 1, + @Query('limit') limit: number = 10, + ) { + return await this.partiesService.getAllWithPagination(page, limit); } @Public() diff --git a/backend/src/domains/parties/parties.service.ts b/backend/src/domains/parties/parties.service.ts index 0711d12..8fa364f 100644 --- a/backend/src/domains/parties/parties.service.ts +++ b/backend/src/domains/parties/parties.service.ts @@ -90,6 +90,36 @@ export class PartiesService { }; } + async getAllWithPagination(page: number, limit: number) { + if (page < 1) page = 1; + if (limit < 1) limit = 10; + + const skip = (page - 1) * limit; + + const [parties, total] = await Promise.all([ + this.partyModel.find().skip(skip).limit(limit).exec(), + this.partyModel.countDocuments().exec(), + ]); + + this.logger.debug('Fetching all parties with pagination', parties); + + const totalPages = Math.ceil(total / limit); + + return { + success: true, + message: 'Parties fetched successfully.', + data: { + parties, + pagination: { + total, + page, + limit, + totalPages, + }, + }, + }; + } + async getOne(identifier: string) { const party = await this.findPartyByIdentifier(identifier); From 63f1df3d636706f0334184ba8817f2a21892158b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qu=E1=BB=91c=20Ch=C6=B0=C6=A1ng?= Date: Sun, 5 Jan 2025 13:52:49 +0700 Subject: [PATCH 02/10] update: api get all booking with pagination --- .../domains/bookings/bookings.controller.ts | 27 ++++++++++++++-- .../src/domains/bookings/bookings.service.ts | 32 +++++++++++++++++++ 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/backend/src/domains/bookings/bookings.controller.ts b/backend/src/domains/bookings/bookings.controller.ts index e3b992c..83fc283 100644 --- a/backend/src/domains/bookings/bookings.controller.ts +++ b/backend/src/domains/bookings/bookings.controller.ts @@ -6,11 +6,13 @@ import { Param, Post, Put, + Query, } from '@nestjs/common'; import { ApiBearerAuth, ApiOperation, ApiParam, + ApiQuery, ApiTags, } from '@nestjs/swagger'; @@ -33,10 +35,29 @@ export class BookingsController { } @Roles(Role.SUPER_ADMIN) - @ApiOperation({ summary: 'Fetch all bookings - Super Amin only' }) + @ApiOperation({ + summary: 'Fetch all bookings with pagination - Super Admin only', + }) + @ApiQuery({ + name: 'page', + required: false, + type: Number, + example: 1, + description: 'Page number, starts from 1', + }) + @ApiQuery({ + name: 'limit', + required: false, + type: Number, + example: 10, + description: 'Number of items per page', + }) @Get() - async getAll() { - return this.bookingsService.getAll(); + async getAll( + @Query('page') page: number = 1, + @Query('limit') limit: number = 10, + ) { + return this.bookingsService.getAllWithPagination(page, limit); } @ApiOperation({ summary: 'Fetch a booking by ID' }) diff --git a/backend/src/domains/bookings/bookings.service.ts b/backend/src/domains/bookings/bookings.service.ts index e6e8b40..733ef0d 100644 --- a/backend/src/domains/bookings/bookings.service.ts +++ b/backend/src/domains/bookings/bookings.service.ts @@ -57,6 +57,38 @@ export class BookingsService { }; } + async getAllWithPagination(page: number, limit: number) { + if (page < 1) page = 1; + if (limit < 1) limit = 10; + + const skip = (page - 1) * limit; + + const [bookings, total] = await Promise.all([ + this.bookingModel.find().skip(skip).limit(limit).exec(), + this.bookingModel.countDocuments().exec(), + ]); + + const totalPages = Math.ceil(total / limit); + + this.logger.debug( + `Fetched bookings with pagination: page ${page}, limit ${limit}`, + ); + + return { + success: true, + message: 'Bookings fetched successfully.', + data: { + bookings, + pagination: { + total, + page, + limit, + totalPages, + }, + }, + }; + } + async getById(id: string) { const booking = await this.bookingModel.findById(id).select('-__v'); From 4deab1b3e9ea0330625f765a1b6eb55c2558ca70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qu=E1=BB=91c=20Ch=C6=B0=C6=A1ng?= Date: Sun, 5 Jan 2025 13:57:34 +0700 Subject: [PATCH 03/10] update: api get all user with pagination --- backend/src/domains/users/users.controller.ts | 44 ++++++++++++++++--- backend/src/domains/users/users.service.ts | 32 ++++++++++++++ 2 files changed, 70 insertions(+), 6 deletions(-) diff --git a/backend/src/domains/users/users.controller.ts b/backend/src/domains/users/users.controller.ts index 7737d7f..c04fdef 100644 --- a/backend/src/domains/users/users.controller.ts +++ b/backend/src/domains/users/users.controller.ts @@ -1,5 +1,18 @@ -import { Body, Controller, Delete, Get, Param, Put } from '@nestjs/common'; -import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'; +import { + Body, + Controller, + Delete, + Get, + Param, + Put, + Query, +} from '@nestjs/common'; +import { + ApiBearerAuth, + ApiOperation, + ApiQuery, + ApiTags, +} from '@nestjs/swagger'; import { Public } from '@/domains/auth/decorators/public.decorator'; import { Roles } from '@/domains/auth/decorators/roles.decorator'; @@ -14,11 +27,30 @@ import { UsersService } from '@/domains/users/users.service'; export class UsersController { constructor(private readonly usersService: UsersService) {} - @Roles(Role.SUPER_ADMIN, Role.ADMIN) - @ApiOperation({ summary: 'Fetch all users - Super Admin & Admin only' }) + @Roles(Role.SUPER_ADMIN) + @ApiOperation({ + summary: 'Fetch all users with pagination - Super Admin only', + }) + @ApiQuery({ + name: 'page', + required: false, + type: Number, + example: 1, + description: 'Page number, starts from 1', + }) + @ApiQuery({ + name: 'limit', + required: false, + type: Number, + example: 10, + description: 'Number of items per page', + }) @Get() - async getAll() { - return await this.usersService.getAll(); + async getAll( + @Query('page') page: number = 1, + @Query('limit') limit: number = 10, + ) { + return await this.usersService.getAllWithPagination(page, limit); } @Public() diff --git a/backend/src/domains/users/users.service.ts b/backend/src/domains/users/users.service.ts index 2e85153..fb53c19 100644 --- a/backend/src/domains/users/users.service.ts +++ b/backend/src/domains/users/users.service.ts @@ -68,6 +68,38 @@ export class UsersService { }; } + async getAllWithPagination(page: number, limit: number) { + if (page < 1) page = 1; + if (limit < 1) limit = 10; + + const skip = (page - 1) * limit; + + const [users, total] = await Promise.all([ + this.userModel.find().skip(skip).limit(limit).exec(), + this.userModel.countDocuments().exec(), + ]); + + const totalPages = Math.ceil(total / limit); + + this.logger.debug( + `Fetched users with pagination: page ${page}, limit ${limit}`, + ); + + return { + success: true, + message: 'Users fetched successfully.', + data: { + users, + pagination: { + total, + page, + limit, + totalPages, + }, + }, + }; + } + async getOne(identifier: string, isEmail = false) { const user = await this.findUser(identifier, isEmail); From 55f6f05af884dd649e3bd825714f8f4475fe8dda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qu=E1=BB=91c=20Ch=C6=B0=C6=A1ng?= Date: Sun, 5 Jan 2025 14:02:23 +0700 Subject: [PATCH 04/10] update: api get all voucher with pagination --- .../domains/vouchers/vouchers.controller.ts | 31 +++++++++++++++--- .../src/domains/vouchers/vouchers.service.ts | 32 +++++++++++++++++++ 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/backend/src/domains/vouchers/vouchers.controller.ts b/backend/src/domains/vouchers/vouchers.controller.ts index 387d817..ba4e13d 100644 --- a/backend/src/domains/vouchers/vouchers.controller.ts +++ b/backend/src/domains/vouchers/vouchers.controller.ts @@ -6,8 +6,14 @@ import { Param, Post, Put, + Query, } from '@nestjs/common'; -import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'; +import { + ApiBearerAuth, + ApiOperation, + ApiQuery, + ApiTags, +} from '@nestjs/swagger'; import { Public } from '@/domains/auth/decorators/public.decorator'; import { Roles } from '@/domains/auth/decorators/roles.decorator'; @@ -30,10 +36,27 @@ export class VouchersController { } @Public() - @ApiOperation({ summary: 'Fetch all vouchers' }) + @ApiOperation({ summary: 'Fetch all vouchers with pagination' }) + @ApiQuery({ + name: 'page', + required: false, + type: Number, + example: 1, + description: 'Page number, starts from 1', + }) + @ApiQuery({ + name: 'limit', + required: false, + type: Number, + example: 10, + description: 'Number of items per page', + }) @Get() - async getAll() { - return await this.vouchersService.getAll(); + async getAll( + @Query('page') page: number = 1, + @Query('limit') limit: number = 10, + ) { + return await this.vouchersService.getAllWithPagination(page, limit); } @Public() diff --git a/backend/src/domains/vouchers/vouchers.service.ts b/backend/src/domains/vouchers/vouchers.service.ts index 423ab44..0273c95 100644 --- a/backend/src/domains/vouchers/vouchers.service.ts +++ b/backend/src/domains/vouchers/vouchers.service.ts @@ -62,6 +62,38 @@ export class VouchersService { }; } + async getAllWithPagination(page: number, limit: number) { + if (page < 1) page = 1; + if (limit < 1) limit = 10; + + const skip = (page - 1) * limit; + + const [vouchers, total] = await Promise.all([ + this.voucherModel.find().skip(skip).limit(limit).exec(), + this.voucherModel.countDocuments().exec(), + ]); + + const totalPages = Math.ceil(total / limit); + + this.logger.debug( + `Fetched vouchers with pagination: page ${page}, limit ${limit}`, + ); + + return { + success: true, + message: 'Vouchers fetched successfully.', + data: { + vouchers, + pagination: { + total, + page, + limit, + totalPages, + }, + }, + }; + } + async getOne(identifier: string) { const voucher = await this.findVoucherByIdentifier(identifier); From 208e987abef23c5921e6b0545fd836ba6bef0312 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qu=E1=BB=91c=20Ch=C6=B0=C6=A1ng?= Date: Sun, 5 Jan 2025 14:23:46 +0700 Subject: [PATCH 05/10] add: api reset password --- backend/src/domains/auth/auth.controller.ts | 7 +++++++ backend/src/domains/auth/auth.service.ts | 18 ++++++++++++++++++ backend/src/utils/hash.util.ts | 7 ------- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/backend/src/domains/auth/auth.controller.ts b/backend/src/domains/auth/auth.controller.ts index d07f14a..c234daf 100644 --- a/backend/src/domains/auth/auth.controller.ts +++ b/backend/src/domains/auth/auth.controller.ts @@ -33,6 +33,13 @@ export class AuthController { return await this.authService.login(user); } + @Public() + @HttpCode(HttpStatus.OK) + @Post('forgot-password') + async forgotPassword(@Body() loginDto: LoginDto) { + return this.authService.forgotPassword(loginDto); + } + @Public() @HttpCode(HttpStatus.OK) @ApiOperation({ diff --git a/backend/src/domains/auth/auth.service.ts b/backend/src/domains/auth/auth.service.ts index 0cb6cbd..377315c 100644 --- a/backend/src/domains/auth/auth.service.ts +++ b/backend/src/domains/auth/auth.service.ts @@ -10,6 +10,7 @@ import { Model } from 'mongoose'; import { LoginDto } from '@/domains/auth/dto/login.dto'; import { User } from '@/schemas/user.schema'; +import { hash } from '@/utils/hash.util'; import { verify } from '@/utils/verify.util'; @Injectable() @@ -70,6 +71,23 @@ export class AuthService { }; } + async forgotPassword(loginDto: LoginDto) { + const user = await this.userModel.findOne({ email: loginDto.email }); + + if (!user) { + throw new NotFoundException( + `Account with email: ${loginDto.email} does not exist`, + ); + } + + user.hashedPassword = await hash(loginDto.password); + await user.save(); + + return { + message: 'Password has been reset', + }; + } + async verifyJwt(token: string) { try { return this.jwtService.verify(token); diff --git a/backend/src/utils/hash.util.ts b/backend/src/utils/hash.util.ts index 4c14622..c56add1 100644 --- a/backend/src/utils/hash.util.ts +++ b/backend/src/utils/hash.util.ts @@ -3,10 +3,3 @@ import * as argon2 from 'argon2'; export const hash = async (plainPassword: string): Promise => { return await argon2.hash(plainPassword); }; - -export const verify = async ( - hashedPassword: string, - plainPassword: string, -): Promise => { - return await argon2.verify(hashedPassword, plainPassword); -}; From e9f196b5abf5e0df4840bd77884f61a8f68c39f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qu=E1=BB=91c=20Ch=C6=B0=C6=A1ng?= Date: Sun, 5 Jan 2025 14:29:17 +0700 Subject: [PATCH 06/10] update: api version to 1.5.0 --- backend/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/package.json b/backend/package.json index e4c8245..4060053 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "evora-backend", - "version": "1.4.5", + "version": "1.5.0", "description": "Evora connects customers with event organizers quickly through detailed online booking.", "repository": "https://github.com/bakaqc/evora-17c", "author": "Quốc Chương", From 9f0781ab4ebc4806edbcb438b4df97dab7553c10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qu=E1=BB=91c=20Ch=C6=B0=C6=A1ng?= Date: Sun, 5 Jan 2025 14:46:42 +0700 Subject: [PATCH 07/10] add: pagination decorator --- .../auth/decorators/pagination.decorator.ts | 21 +++++++++++++++++ .../domains/bookings/bookings.controller.ts | 17 ++------------ .../src/domains/parties/parties.controller.ts | 23 +++---------------- backend/src/domains/users/users.controller.ts | 23 +++---------------- .../domains/vouchers/vouchers.controller.ts | 23 +++---------------- 5 files changed, 32 insertions(+), 75 deletions(-) create mode 100644 backend/src/domains/auth/decorators/pagination.decorator.ts diff --git a/backend/src/domains/auth/decorators/pagination.decorator.ts b/backend/src/domains/auth/decorators/pagination.decorator.ts new file mode 100644 index 0000000..b996909 --- /dev/null +++ b/backend/src/domains/auth/decorators/pagination.decorator.ts @@ -0,0 +1,21 @@ +import { applyDecorators } from '@nestjs/common'; +import { ApiQuery } from '@nestjs/swagger'; + +export function ApiPagination() { + return applyDecorators( + ApiQuery({ + name: 'page', + required: false, + type: Number, + example: 1, + description: 'Page number, starts from 1', + }), + ApiQuery({ + name: 'limit', + required: false, + type: Number, + example: 10, + description: 'Number of items per page', + }), + ); +} diff --git a/backend/src/domains/bookings/bookings.controller.ts b/backend/src/domains/bookings/bookings.controller.ts index 83fc283..5cd4c7a 100644 --- a/backend/src/domains/bookings/bookings.controller.ts +++ b/backend/src/domains/bookings/bookings.controller.ts @@ -12,10 +12,10 @@ import { ApiBearerAuth, ApiOperation, ApiParam, - ApiQuery, ApiTags, } from '@nestjs/swagger'; +import { ApiPagination } from '@/domains/auth/decorators/pagination.decorator'; import { Roles } from '@/domains/auth/decorators/roles.decorator'; import { Role } from '@/domains/auth/enums/role.enum'; import { BookingsService } from '@/domains/bookings/bookings.service'; @@ -38,20 +38,7 @@ export class BookingsController { @ApiOperation({ summary: 'Fetch all bookings with pagination - Super Admin only', }) - @ApiQuery({ - name: 'page', - required: false, - type: Number, - example: 1, - description: 'Page number, starts from 1', - }) - @ApiQuery({ - name: 'limit', - required: false, - type: Number, - example: 10, - description: 'Number of items per page', - }) + @ApiPagination() @Get() async getAll( @Query('page') page: number = 1, diff --git a/backend/src/domains/parties/parties.controller.ts b/backend/src/domains/parties/parties.controller.ts index 732c991..3029f8d 100644 --- a/backend/src/domains/parties/parties.controller.ts +++ b/backend/src/domains/parties/parties.controller.ts @@ -8,13 +8,9 @@ import { Put, Query, } from '@nestjs/common'; -import { - ApiBearerAuth, - ApiOperation, - ApiQuery, - ApiTags, -} from '@nestjs/swagger'; +import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'; +import { ApiPagination } from '@/domains/auth/decorators/pagination.decorator'; import { Public } from '@/domains/auth/decorators/public.decorator'; import { Roles } from '@/domains/auth/decorators/roles.decorator'; import { Role } from '@/domains/auth/enums/role.enum'; @@ -37,20 +33,7 @@ export class PartiesController { @Public() @ApiOperation({ summary: 'Fetch all parties with pagination' }) - @ApiQuery({ - name: 'page', - required: false, - type: Number, - example: 1, - description: 'Page number, starts from 1', - }) - @ApiQuery({ - name: 'limit', - required: false, - type: Number, - example: 10, - description: 'Number of items per page', - }) + @ApiPagination() @Get() async getAll( @Query('page') page: number = 1, diff --git a/backend/src/domains/users/users.controller.ts b/backend/src/domains/users/users.controller.ts index c04fdef..5d9dfc1 100644 --- a/backend/src/domains/users/users.controller.ts +++ b/backend/src/domains/users/users.controller.ts @@ -7,13 +7,9 @@ import { Put, Query, } from '@nestjs/common'; -import { - ApiBearerAuth, - ApiOperation, - ApiQuery, - ApiTags, -} from '@nestjs/swagger'; +import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'; +import { ApiPagination } from '@/domains/auth/decorators/pagination.decorator'; import { Public } from '@/domains/auth/decorators/public.decorator'; import { Roles } from '@/domains/auth/decorators/roles.decorator'; import { Role } from '@/domains/auth/enums/role.enum'; @@ -31,20 +27,7 @@ export class UsersController { @ApiOperation({ summary: 'Fetch all users with pagination - Super Admin only', }) - @ApiQuery({ - name: 'page', - required: false, - type: Number, - example: 1, - description: 'Page number, starts from 1', - }) - @ApiQuery({ - name: 'limit', - required: false, - type: Number, - example: 10, - description: 'Number of items per page', - }) + @ApiPagination() @Get() async getAll( @Query('page') page: number = 1, diff --git a/backend/src/domains/vouchers/vouchers.controller.ts b/backend/src/domains/vouchers/vouchers.controller.ts index ba4e13d..d34e366 100644 --- a/backend/src/domains/vouchers/vouchers.controller.ts +++ b/backend/src/domains/vouchers/vouchers.controller.ts @@ -8,13 +8,9 @@ import { Put, Query, } from '@nestjs/common'; -import { - ApiBearerAuth, - ApiOperation, - ApiQuery, - ApiTags, -} from '@nestjs/swagger'; +import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'; +import { ApiPagination } from '@/domains/auth/decorators/pagination.decorator'; import { Public } from '@/domains/auth/decorators/public.decorator'; import { Roles } from '@/domains/auth/decorators/roles.decorator'; import { Role } from '@/domains/auth/enums/role.enum'; @@ -37,20 +33,7 @@ export class VouchersController { @Public() @ApiOperation({ summary: 'Fetch all vouchers with pagination' }) - @ApiQuery({ - name: 'page', - required: false, - type: Number, - example: 1, - description: 'Page number, starts from 1', - }) - @ApiQuery({ - name: 'limit', - required: false, - type: Number, - example: 10, - description: 'Number of items per page', - }) + @ApiPagination() @Get() async getAll( @Query('page') page: number = 1, From 255a5504fb6ed654a377c8535c0207c5e2ef7a03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qu=E1=BB=91c=20Ch=C6=B0=C6=A1ng?= Date: Sun, 5 Jan 2025 14:47:14 +0700 Subject: [PATCH 08/10] update: api version to 1.5.4 --- backend/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/package.json b/backend/package.json index 4060053..e66b160 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "evora-backend", - "version": "1.5.0", + "version": "1.5.4", "description": "Evora connects customers with event organizers quickly through detailed online booking.", "repository": "https://github.com/bakaqc/evora-17c", "author": "Quốc Chương", From b821a39b652c8b5bde252ff543d93e63683c338e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qu=E1=BB=91c=20Ch=C6=B0=C6=A1ng?= Date: Tue, 7 Jan 2025 12:38:32 +0700 Subject: [PATCH 09/10] update: format path constant --- frontend/pnpm-lock.yaml | 46 ++++++++++++++++++--------------- frontend/src/App.tsx | 2 +- frontend/src/ultils/constant.ts | 17 +++++++----- 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index bb277a6..62ff85d 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -38,12 +38,12 @@ importers: react-router-dom: specifier: 7.1.0 version: 7.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - recharts: - specifier: 2.15.0 - version: 2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-toastify: specifier: 11.0.2 version: 11.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + recharts: + specifier: 2.15.0 + version: 2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) slick-carousel: specifier: 1.8.1 version: 1.8.1(jquery@3.7.1) @@ -594,8 +594,8 @@ packages: '@types/d3-scale@4.0.8': resolution: {integrity: sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==} - '@types/d3-shape@3.1.6': - resolution: {integrity: sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==} + '@types/d3-shape@3.1.7': + resolution: {integrity: sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==} '@types/d3-time@3.0.4': resolution: {integrity: sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==} @@ -901,8 +901,10 @@ packages: dlv@1.1.3: resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + dom-helpers@5.2.1: resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} + dotenv@16.4.7: resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} engines: {node: '>=12'} @@ -991,8 +993,8 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-equals@5.0.1: - resolution: {integrity: sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==} + fast-equals@5.2.1: + resolution: {integrity: sha512-4DpZF7SS4GQO08ScYvTMuZSRik6Y+46ByOJOZR3yKjE69rooHcHB/UsO89qJyIlyvlya38296vypgnInFhRePA==} engines: {node: '>=6.0.0'} fast-glob@3.3.2: @@ -1460,18 +1462,18 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react-transition-group@4.4.5: - resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} - peerDependencies: - react: '>=16.6.0' - react-dom: '>=16.6.0' - react-toastify@11.0.2: resolution: {integrity: sha512-GjHuGaiXMvbls3ywqv8XdWONwrcO4DXCJIY1zVLkHU73gEElKvTTXNI5Vom3s/k/M8hnkrfsqgBSX3OwmlonbA==} peerDependencies: react: ^18 || ^19 react-dom: ^18 || ^19 + react-transition-group@4.4.5: + resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} + peerDependencies: + react: '>=16.6.0' + react-dom: '>=16.6.0' + react@18.3.1: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} @@ -2150,7 +2152,7 @@ snapshots: dependencies: '@types/d3-time': 3.0.4 - '@types/d3-shape@3.1.6': + '@types/d3-shape@3.1.7': dependencies: '@types/d3-path': 3.1.0 @@ -2586,7 +2588,7 @@ snapshots: fast-deep-equal@3.1.3: {} - fast-equals@5.0.1: {} + fast-equals@5.2.1: {} fast-glob@3.3.2: dependencies: @@ -2995,21 +2997,24 @@ snapshots: react-smooth@4.0.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - fast-equals: 5.0.1 + fast-equals: 5.2.1 prop-types: 15.8.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-transition-group: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react-toastify@11.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + clsx: 2.1.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-transition-group@4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 - react-toastify@11.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - clsx: 2.1.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -3259,7 +3264,7 @@ snapshots: '@types/d3-ease': 3.0.2 '@types/d3-interpolate': 3.0.4 '@types/d3-scale': 4.0.8 - '@types/d3-shape': 3.1.6 + '@types/d3-shape': 3.1.7 '@types/d3-time': 3.0.4 '@types/d3-timer': 3.0.2 d3-array: 3.2.4 @@ -3270,7 +3275,6 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite-tsconfig-paths@5.1.4(typescript@5.6.2)(vite@6.0.3(jiti@1.21.7)(yaml@2.6.1)): vite-tsconfig-paths@5.1.4(typescript@5.6.2)(vite@6.0.3(@types/node@22.10.2)(jiti@1.21.7)(yaml@2.6.1)): dependencies: debug: 4.4.0 diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 777eae7..ff8e699 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -18,7 +18,7 @@ const App: React.FC = () => {
} /> - } /> + } />
diff --git a/frontend/src/ultils/constant.ts b/frontend/src/ultils/constant.ts index ac6b4b6..5fd386f 100644 --- a/frontend/src/ultils/constant.ts +++ b/frontend/src/ultils/constant.ts @@ -1,8 +1,8 @@ export const path = { + // Path for user HOME: '/*', - LOGIN_USER: '/user/login', - REGISTER_USER: '/user/register', - LOGIN_ADMIN: '/login', + LOGIN_USER: '/dang-nhap', + REGISTER_USER: '/dang-ki', BIRTHDAY: '/sinh-nhat', EVENT: '/su-kien', WEDDING: '/dam-cuoi', @@ -12,16 +12,19 @@ export const path = { INTRO: '/gioi-thieu', CONTACT: '/lien-he', VERIFY_OTP: '/otp', + + // Path for admin ADMINPAGE: '/', - LISTUSER: '/nguoi-dung', + LOGIN_ADMIN: '/dang-nhap', + LISTUSER: '/danh-sach-nguoi-dung', LISTBOOKING: '/danh-sach-dat-tiec', LISTPARTIES: '/danh-sach-bua-tiec', - LISTVOUCHERS: '/vouchers', - LISTPAYMENTS: '/thanh-toan', + LISTVOUCHERS: '/danh-sach-ma-giam-gia', + LISTPAYMENTS: '/danh-sach-thanh-toan', NOTIFIES: '/thong-bao', PROFILE: '/trang-ca-nhan', SETTING: '/cai-dat', - LOGOUT: '/logout', + LOGOUT: '/', }; export const text = { From e497ef52498d29f9782c7c0d56ecb8dd9bcf94d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qu=E1=BB=91c=20Ch=C6=B0=C6=A1ng?= Date: Tue, 7 Jan 2025 12:46:27 +0700 Subject: [PATCH 10/10] update: folder name utils --- frontend/src/axiosConfig.ts | 4 +++- frontend/src/components/Banner.tsx | 2 +- frontend/src/components/InputField.tsx | 2 +- frontend/src/components/InputForLogin.tsx | 2 +- frontend/src/components/InputForOTP.tsx | 2 +- frontend/src/components/Intro.tsx | 4 ++-- frontend/src/components/Menu.tsx | 2 +- frontend/src/components/Select.tsx | 2 +- frontend/src/components/TopBar.tsx | 2 +- frontend/src/containers/public/Footer.tsx | 2 +- frontend/src/containers/public/Header.tsx | 2 +- frontend/src/containers/public/LoginUser.tsx | 6 +++--- frontend/src/containers/public/Navigation.tsx | 4 ++-- frontend/src/containers/public/RegisterUser.tsx | 6 +++--- frontend/src/containers/public/VerifyOTP.tsx | 4 ++-- frontend/src/containers/system/index.ts | 1 - frontend/src/routes/admin/AdminRoutes.tsx | 2 +- frontend/src/routes/user/UserRoutes.tsx | 2 +- frontend/src/services/auth.ts | 2 +- frontend/src/stores/actions/auth.ts | 2 +- frontend/src/stores/reducers/authReducer.ts | 2 +- frontend/src/stores/reducers/rootReducer.ts | 2 +- frontend/src/{ultils => utils}/apiBase.ts | 0 frontend/src/{ultils => utils}/constant.ts | 0 frontend/src/{ultils => utils}/dataIntro.ts | 0 frontend/src/{ultils => utils}/icons.ts | 0 frontend/src/{ultils => utils}/inputValidate.ts | 0 frontend/src/{ultils => utils}/loginManage.ts | 0 frontend/src/{ultils => utils}/type.ts | 0 frontend/src/{ultils => utils}/validateField.ts | 0 30 files changed, 30 insertions(+), 29 deletions(-) rename frontend/src/{ultils => utils}/apiBase.ts (100%) rename frontend/src/{ultils => utils}/constant.ts (100%) rename frontend/src/{ultils => utils}/dataIntro.ts (100%) rename frontend/src/{ultils => utils}/icons.ts (100%) rename frontend/src/{ultils => utils}/inputValidate.ts (100%) rename frontend/src/{ultils => utils}/loginManage.ts (100%) rename frontend/src/{ultils => utils}/type.ts (100%) rename frontend/src/{ultils => utils}/validateField.ts (100%) diff --git a/frontend/src/axiosConfig.ts b/frontend/src/axiosConfig.ts index d84d097..46f0e4b 100644 --- a/frontend/src/axiosConfig.ts +++ b/frontend/src/axiosConfig.ts @@ -1,7 +1,9 @@ import axios, { AxiosResponse, InternalAxiosRequestConfig } from 'axios'; +import { apiBaseUrl } from '@/utils/apiBase'; + const instance = axios.create({ - baseURL: import.meta.env.VITE_BACKEND_URL, + baseURL: apiBaseUrl, }); // Add a request interceptor diff --git a/frontend/src/components/Banner.tsx b/frontend/src/components/Banner.tsx index 90d6957..d8da0a0 100644 --- a/frontend/src/components/Banner.tsx +++ b/frontend/src/components/Banner.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { NavLink } from 'react-router-dom'; import hero from '@/assets/hero.jpg'; -import { path } from '@/ultils/constant'; +import { path } from '@/utils/constant'; const Banner: React.FC = () => { return ( diff --git a/frontend/src/components/InputField.tsx b/frontend/src/components/InputField.tsx index 84dc100..921aba5 100644 --- a/frontend/src/components/InputField.tsx +++ b/frontend/src/components/InputField.tsx @@ -1,4 +1,4 @@ -import { Payload } from '@/ultils/type'; +import { Payload } from '@/utils/type'; interface InputFieldProps { id: string; diff --git a/frontend/src/components/InputForLogin.tsx b/frontend/src/components/InputForLogin.tsx index fac0256..20b8aed 100644 --- a/frontend/src/components/InputForLogin.tsx +++ b/frontend/src/components/InputForLogin.tsx @@ -1,4 +1,4 @@ -import { PayloadForLogin } from '@/ultils/type'; +import { PayloadForLogin } from '@/utils/type'; interface InputFieldProps { id: string; diff --git a/frontend/src/components/InputForOTP.tsx b/frontend/src/components/InputForOTP.tsx index dba14ed..b90d7bb 100644 --- a/frontend/src/components/InputForOTP.tsx +++ b/frontend/src/components/InputForOTP.tsx @@ -1,4 +1,4 @@ -import { PayloadForOtp } from '@/ultils/type'; +import { PayloadForOtp } from '@/utils/type'; interface InputFieldProps { id: string; diff --git a/frontend/src/components/Intro.tsx b/frontend/src/components/Intro.tsx index 29b869e..4200dcd 100644 --- a/frontend/src/components/Intro.tsx +++ b/frontend/src/components/Intro.tsx @@ -1,5 +1,5 @@ -import { text } from '../ultils/dataIntro'; -import icons from '../ultils/icons'; +import { text } from '../utils/dataIntro'; +import icons from '../utils/icons'; import React, { memo } from 'react'; const { FaStar } = icons; diff --git a/frontend/src/components/Menu.tsx b/frontend/src/components/Menu.tsx index 7be8b46..956266c 100644 --- a/frontend/src/components/Menu.tsx +++ b/frontend/src/components/Menu.tsx @@ -12,7 +12,7 @@ import profile from '@/assets/profile.png'; import setting from '@/assets/setting.png'; import userIcon from '@/assets/user.png'; import voucher from '@/assets/voucher.png'; -import { path } from '@/ultils/constant'; +import { path } from '@/utils/constant'; const menuItems = [ { diff --git a/frontend/src/components/Select.tsx b/frontend/src/components/Select.tsx index 11bca6c..254d5ff 100644 --- a/frontend/src/components/Select.tsx +++ b/frontend/src/components/Select.tsx @@ -1,6 +1,6 @@ import React, { memo } from 'react'; -import { Payload } from '@/ultils/type'; +import { Payload } from '@/utils/type'; interface SelectProps { label?: string; diff --git a/frontend/src/components/TopBar.tsx b/frontend/src/components/TopBar.tsx index c5dad9a..a6ca3a0 100644 --- a/frontend/src/components/TopBar.tsx +++ b/frontend/src/components/TopBar.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import icons from '@/ultils/icons'; +import icons from '@/utils/icons'; const { FaBirthdayCake, BiPhoneCall, BiEnvelope } = icons; diff --git a/frontend/src/containers/public/Footer.tsx b/frontend/src/containers/public/Footer.tsx index 4177143..5553923 100644 --- a/frontend/src/containers/public/Footer.tsx +++ b/frontend/src/containers/public/Footer.tsx @@ -2,7 +2,7 @@ import React from 'react'; import bg from '@/assets/bg.jpg'; // Đảm bảo đường dẫn chính xác -import icons from '@/ultils/icons'; +import icons from '@/utils/icons'; const { FaBirthdayCake, diff --git a/frontend/src/containers/public/Header.tsx b/frontend/src/containers/public/Header.tsx index 07416ae..0aba0ea 100644 --- a/frontend/src/containers/public/Header.tsx +++ b/frontend/src/containers/public/Header.tsx @@ -3,7 +3,7 @@ import { Link } from 'react-router-dom'; import logo1 from '@/assets/logo1.png'; import { Button } from '@/components'; -import icons from '@/ultils/icons'; +import icons from '@/utils/icons'; const { CiLogin, RiAdminLine, RiUserLine } = icons; diff --git a/frontend/src/containers/public/LoginUser.tsx b/frontend/src/containers/public/LoginUser.tsx index acb8fd0..f05dfb5 100644 --- a/frontend/src/containers/public/LoginUser.tsx +++ b/frontend/src/containers/public/LoginUser.tsx @@ -7,9 +7,9 @@ import { ButtonForLogin, InputForLogin } from '@/components'; import { AppDispatch } from '@/redux'; import * as actions from '@/stores/actions'; import { RootState } from '@/stores/reducers/rootReducer'; -import { path } from '@/ultils/constant'; -import { PayloadForLogin } from '@/ultils/type'; -import validate from '@/ultils/validateField'; +import { path } from '@/utils/constant'; +import { PayloadForLogin } from '@/utils/type'; +import validate from '@/utils/validateField'; interface InvalidField { name: string; diff --git a/frontend/src/containers/public/Navigation.tsx b/frontend/src/containers/public/Navigation.tsx index 0eff3d7..4060835 100644 --- a/frontend/src/containers/public/Navigation.tsx +++ b/frontend/src/containers/public/Navigation.tsx @@ -3,8 +3,8 @@ import { useSelector } from 'react-redux'; import { Link, NavLink } from 'react-router-dom'; import { RootState } from '@/stores/reducers/rootReducer'; -import { path } from '@/ultils/constant'; -import icons from '@/ultils/icons'; +import { path } from '@/utils/constant'; +import icons from '@/utils/icons'; const { RiAdminLine, RiUserLine, IoIosLogOut } = icons; diff --git a/frontend/src/containers/public/RegisterUser.tsx b/frontend/src/containers/public/RegisterUser.tsx index 53f202b..1b33386 100644 --- a/frontend/src/containers/public/RegisterUser.tsx +++ b/frontend/src/containers/public/RegisterUser.tsx @@ -11,9 +11,9 @@ import { } from '@/components'; import { AppDispatch } from '@/redux'; import * as actions from '@/stores/actions'; -import { path } from '@/ultils/constant'; -import { Payload } from '@/ultils/type'; -import validate from '@/ultils/validateField'; +import { path } from '@/utils/constant'; +import { Payload } from '@/utils/type'; +import validate from '@/utils/validateField'; const RegisterUser: React.FC = () => { interface InvalidField { diff --git a/frontend/src/containers/public/VerifyOTP.tsx b/frontend/src/containers/public/VerifyOTP.tsx index 60a0a50..8960c57 100644 --- a/frontend/src/containers/public/VerifyOTP.tsx +++ b/frontend/src/containers/public/VerifyOTP.tsx @@ -8,8 +8,8 @@ import InputForOtp from '@/components/InputForOTP'; import { AppDispatch } from '@/redux'; import { verifyOTP } from '@/stores/actions'; import { RootState } from '@/stores/reducers/rootReducer'; -import { path } from '@/ultils/constant'; -import { PayloadForOtp } from '@/ultils/type'; +import { path } from '@/utils/constant'; +import { PayloadForOtp } from '@/utils/type'; const VerifyOTP: React.FC = () => { const dispatch: AppDispatch = useDispatch(); diff --git a/frontend/src/containers/system/index.ts b/frontend/src/containers/system/index.ts index 69aaca8..9689e66 100644 --- a/frontend/src/containers/system/index.ts +++ b/frontend/src/containers/system/index.ts @@ -1,2 +1 @@ export { default as AdminPage } from './AdminPage'; - diff --git a/frontend/src/routes/admin/AdminRoutes.tsx b/frontend/src/routes/admin/AdminRoutes.tsx index a5f2d98..fac1d01 100644 --- a/frontend/src/routes/admin/AdminRoutes.tsx +++ b/frontend/src/routes/admin/AdminRoutes.tsx @@ -3,7 +3,7 @@ import { Route, Routes } from 'react-router-dom'; import { LoginAdmin } from '@/containers/public'; import { AdminPage } from '@/containers/system'; -import { path } from '@/ultils/constant'; +import { path } from '@/utils/constant'; const AdminRoutes: React.FC = () => { return ( diff --git a/frontend/src/routes/user/UserRoutes.tsx b/frontend/src/routes/user/UserRoutes.tsx index cfae3a1..2867991 100644 --- a/frontend/src/routes/user/UserRoutes.tsx +++ b/frontend/src/routes/user/UserRoutes.tsx @@ -9,7 +9,7 @@ import { RegisterUser, VerifyOTP, } from '@/containers/public'; -import { path } from '@/ultils/constant'; +import { path } from '@/utils/constant'; const UserRoutes: React.FC = () => { return ( diff --git a/frontend/src/services/auth.ts b/frontend/src/services/auth.ts index 7014343..85f183d 100644 --- a/frontend/src/services/auth.ts +++ b/frontend/src/services/auth.ts @@ -1,5 +1,5 @@ import axiosConfig from '@/axiosConfig'; -import { Payload } from '@/ultils/type'; +import { Payload } from '@/utils/type'; interface LoginPayload { email: string; diff --git a/frontend/src/stores/actions/auth.ts b/frontend/src/stores/actions/auth.ts index 3cd2c56..0eea4e1 100644 --- a/frontend/src/stores/actions/auth.ts +++ b/frontend/src/stores/actions/auth.ts @@ -9,7 +9,7 @@ import { apiVerifyOTP, } from '@/services/auth'; import { actionTypes } from '@/stores/actions/actionTypes'; -import { Payload, PayloadForLogin } from '@/ultils/type'; +import { Payload, PayloadForLogin } from '@/utils/type'; interface RegisterSuccessAction { type: typeof actionTypes.REGISTER_SUCCES; diff --git a/frontend/src/stores/reducers/authReducer.ts b/frontend/src/stores/reducers/authReducer.ts index 4839015..2ade50c 100644 --- a/frontend/src/stores/reducers/authReducer.ts +++ b/frontend/src/stores/reducers/authReducer.ts @@ -1,6 +1,6 @@ import { actionTypes } from '../actions/actionTypes'; -import { Payload } from '@/ultils/type'; +import { Payload } from '@/utils/type'; type AuthState = { isLogin: boolean; diff --git a/frontend/src/stores/reducers/rootReducer.ts b/frontend/src/stores/reducers/rootReducer.ts index d3a5845..2ad921a 100644 --- a/frontend/src/stores/reducers/rootReducer.ts +++ b/frontend/src/stores/reducers/rootReducer.ts @@ -5,7 +5,7 @@ import storage from 'redux-persist/lib/storage'; import authReducer from '@/stores/reducers/authReducer'; import userReducer from '@/stores/reducers/userReducer'; -import { Payload } from '@/ultils/type'; +import { Payload } from '@/utils/type'; type AuthState = { isLogin: boolean; diff --git a/frontend/src/ultils/apiBase.ts b/frontend/src/utils/apiBase.ts similarity index 100% rename from frontend/src/ultils/apiBase.ts rename to frontend/src/utils/apiBase.ts diff --git a/frontend/src/ultils/constant.ts b/frontend/src/utils/constant.ts similarity index 100% rename from frontend/src/ultils/constant.ts rename to frontend/src/utils/constant.ts diff --git a/frontend/src/ultils/dataIntro.ts b/frontend/src/utils/dataIntro.ts similarity index 100% rename from frontend/src/ultils/dataIntro.ts rename to frontend/src/utils/dataIntro.ts diff --git a/frontend/src/ultils/icons.ts b/frontend/src/utils/icons.ts similarity index 100% rename from frontend/src/ultils/icons.ts rename to frontend/src/utils/icons.ts diff --git a/frontend/src/ultils/inputValidate.ts b/frontend/src/utils/inputValidate.ts similarity index 100% rename from frontend/src/ultils/inputValidate.ts rename to frontend/src/utils/inputValidate.ts diff --git a/frontend/src/ultils/loginManage.ts b/frontend/src/utils/loginManage.ts similarity index 100% rename from frontend/src/ultils/loginManage.ts rename to frontend/src/utils/loginManage.ts diff --git a/frontend/src/ultils/type.ts b/frontend/src/utils/type.ts similarity index 100% rename from frontend/src/ultils/type.ts rename to frontend/src/utils/type.ts diff --git a/frontend/src/ultils/validateField.ts b/frontend/src/utils/validateField.ts similarity index 100% rename from frontend/src/ultils/validateField.ts rename to frontend/src/utils/validateField.ts