diff --git a/src/application/classes/index.ts b/src/application/classes/index.ts new file mode 100644 index 0000000..40fd168 --- /dev/null +++ b/src/application/classes/index.ts @@ -0,0 +1,13 @@ +import { makeGetClassByIdQuery } from "./queries/get-class-by-id"; +import { makeListHightlightClassesQuery } from "./queries/list-highlight-classes"; +import { makeListShortClassesQuery } from "./queries/list-short-classes"; + +export function makeClassessUseCases(dependencies: Dependencies) { + return { + queries: { + listHightlightClasses: makeListHightlightClassesQuery(dependencies), + listShortClasses: makeListShortClassesQuery(dependencies), + getClassById: makeGetClassByIdQuery(dependencies), + }, + }; +} diff --git a/src/application/classes/queries/get-class-by-id/get-class-by-id-query-mapper.ts b/src/application/classes/queries/get-class-by-id/get-class-by-id-query-mapper.ts new file mode 100644 index 0000000..f1f54f8 --- /dev/null +++ b/src/application/classes/queries/get-class-by-id/get-class-by-id-query-mapper.ts @@ -0,0 +1,18 @@ +import { ClassDTO } from "@domain/dtos/class"; +import { ClassEntity } from "@domain/entities"; + +export function map(renamedClass: ClassEntity, language: string): ClassDTO { + return { + id: renamedClass.id?.toString() || '', + title: language === 'vi' ? renamedClass.vi_name : renamedClass.en_name, + description: language === 'vi' ? renamedClass.vi_description || '' : renamedClass.en_description || '', + content: language === 'vi' ? renamedClass.vi_content || '' : renamedClass.en_content || '', + image: renamedClass.image || null, + order: renamedClass.order || null, + status: renamedClass.status, + created_at: renamedClass.created_at?.toISOString() || null, + updated_at: renamedClass.updated_at?.toISOString() || null, + created_by: renamedClass.created_by || null, + updated_by: renamedClass.updated_by || null, + }; +} diff --git a/src/application/classes/queries/get-class-by-id/get-class-by-id-query-validator.ts b/src/application/classes/queries/get-class-by-id/get-class-by-id-query-validator.ts new file mode 100644 index 0000000..091cd7f --- /dev/null +++ b/src/application/classes/queries/get-class-by-id/get-class-by-id-query-validator.ts @@ -0,0 +1,17 @@ +import { ValidationException } from '@application/common/exceptions'; +import { ZodError, z } from 'zod'; + +import { GetClassByIdQuery } from './get-class-by-id-query'; + +export async function validate(query: GetClassByIdQuery) { + try { + const schema: z.ZodType = z.object({ + language: z.string(), + id: z.string() + }); + + await schema.parseAsync(query); + } catch (error) { + throw new ValidationException(error as ZodError); + } +} diff --git a/src/application/classes/queries/get-class-by-id/get-class-by-id-query.ts b/src/application/classes/queries/get-class-by-id/get-class-by-id-query.ts new file mode 100644 index 0000000..cb5b0ba --- /dev/null +++ b/src/application/classes/queries/get-class-by-id/get-class-by-id-query.ts @@ -0,0 +1,19 @@ +import { map } from "./get-class-by-id-query-mapper"; +import { validate } from "./get-class-by-id-query-validator"; + +export type GetClassByIdQuery = Readonly<{ + language: string; + id: string +}>; + +export function makeGetClassByIdQuery({ classesRepository }: Pick) { + return async function getClassByIdQuery(query: GetClassByIdQuery) { + await validate(query); + + const { language, id } = query; + + const renamedClass = await classesRepository.getById({ language, id }); + + return renamedClass ? map(renamedClass, language) : null; + }; +} diff --git a/src/application/classes/queries/get-class-by-id/index.ts b/src/application/classes/queries/get-class-by-id/index.ts new file mode 100644 index 0000000..2a8bd90 --- /dev/null +++ b/src/application/classes/queries/get-class-by-id/index.ts @@ -0,0 +1 @@ +export * from './get-class-by-id-query'; diff --git a/src/application/classes/queries/list-highlight-classes/index.ts b/src/application/classes/queries/list-highlight-classes/index.ts new file mode 100644 index 0000000..50d0074 --- /dev/null +++ b/src/application/classes/queries/list-highlight-classes/index.ts @@ -0,0 +1 @@ +export * from './list-highlight-classes-query'; diff --git a/src/application/classes/queries/list-highlight-classes/list-highlight-classes-query-mapper.ts b/src/application/classes/queries/list-highlight-classes/list-highlight-classes-query-mapper.ts new file mode 100644 index 0000000..f1f54f8 --- /dev/null +++ b/src/application/classes/queries/list-highlight-classes/list-highlight-classes-query-mapper.ts @@ -0,0 +1,18 @@ +import { ClassDTO } from "@domain/dtos/class"; +import { ClassEntity } from "@domain/entities"; + +export function map(renamedClass: ClassEntity, language: string): ClassDTO { + return { + id: renamedClass.id?.toString() || '', + title: language === 'vi' ? renamedClass.vi_name : renamedClass.en_name, + description: language === 'vi' ? renamedClass.vi_description || '' : renamedClass.en_description || '', + content: language === 'vi' ? renamedClass.vi_content || '' : renamedClass.en_content || '', + image: renamedClass.image || null, + order: renamedClass.order || null, + status: renamedClass.status, + created_at: renamedClass.created_at?.toISOString() || null, + updated_at: renamedClass.updated_at?.toISOString() || null, + created_by: renamedClass.created_by || null, + updated_by: renamedClass.updated_by || null, + }; +} diff --git a/src/application/classes/queries/list-highlight-classes/list-highlight-classes-query-validator.ts b/src/application/classes/queries/list-highlight-classes/list-highlight-classes-query-validator.ts new file mode 100644 index 0000000..762d14c --- /dev/null +++ b/src/application/classes/queries/list-highlight-classes/list-highlight-classes-query-validator.ts @@ -0,0 +1,18 @@ +import { ValidationException } from '@application/common/exceptions'; +import { ZodError, z } from 'zod'; + +import { ListHightlightClassesQuery } from './list-highlight-classes-query'; + +export async function validate(query: ListHightlightClassesQuery) { + try { + const schema: z.ZodType = z.object({ + language: z.string(), + size: z.number().optional(), + page: z.number().optional() + }); + + await schema.parseAsync(query); + } catch (error) { + throw new ValidationException(error as ZodError); + } +} diff --git a/src/application/classes/queries/list-highlight-classes/list-highlight-classes-query.ts b/src/application/classes/queries/list-highlight-classes/list-highlight-classes-query.ts new file mode 100644 index 0000000..6e0b35c --- /dev/null +++ b/src/application/classes/queries/list-highlight-classes/list-highlight-classes-query.ts @@ -0,0 +1,30 @@ +import { map } from "./list-highlight-classes-query-mapper"; +import { validate } from "./list-highlight-classes-query-validator"; + +export type ListHightlightClassesQuery = Readonly<{ + language: string; + size?: number; + page?: number +}>; + +export function makeListHightlightClassesQuery({ classesRepository }: Pick) { + return async function listHightlightClassesQuery(query: ListHightlightClassesQuery) { + await validate(query); + + const { language, size, page } = query; + + const { data, total } = await classesRepository.getHighlightClasses({ language, size, page }); + + const per_page = size; + const current_page = page; + const last_page = total && per_page ? Math.ceil(total / per_page) : 1; + + return { + data: data.map((classItem) => map(classItem, language)), + total, + per_page, + current_page, + last_page, + } + }; +} diff --git a/src/application/classes/queries/list-short-classes/index.ts b/src/application/classes/queries/list-short-classes/index.ts new file mode 100644 index 0000000..a93400a --- /dev/null +++ b/src/application/classes/queries/list-short-classes/index.ts @@ -0,0 +1 @@ +export * from './list-short-classes-query'; diff --git a/src/application/classes/queries/list-short-classes/list-short-classes-query-mapper.ts b/src/application/classes/queries/list-short-classes/list-short-classes-query-mapper.ts new file mode 100644 index 0000000..276fea9 --- /dev/null +++ b/src/application/classes/queries/list-short-classes/list-short-classes-query-mapper.ts @@ -0,0 +1,12 @@ +import { ClassDTO } from "@domain/dtos/class"; +import { ClassEntity } from "@domain/entities"; + +type HighlightClassDTO = Omit; + +export function map(renamedClass: ClassEntity, language: string): HighlightClassDTO { + return { + id: renamedClass.id?.toString() || '', + title: language === 'vi' ? renamedClass.vi_name : renamedClass.en_name, + order: renamedClass.order || null, + }; +} diff --git a/src/application/classes/queries/list-short-classes/list-short-classes-query-validator.ts b/src/application/classes/queries/list-short-classes/list-short-classes-query-validator.ts new file mode 100644 index 0000000..eb436e1 --- /dev/null +++ b/src/application/classes/queries/list-short-classes/list-short-classes-query-validator.ts @@ -0,0 +1,16 @@ +import { ValidationException } from '@application/common/exceptions'; +import { ZodError, z } from 'zod'; + +import { ListShortClassesQuery } from './list-short-classes-query'; + +export async function validate(query: ListShortClassesQuery) { + try { + const schema: z.ZodType = z.object({ + language: z.string(), + }); + + await schema.parseAsync(query); + } catch (error) { + throw new ValidationException(error as ZodError); + } +} diff --git a/src/application/classes/queries/list-short-classes/list-short-classes-query.ts b/src/application/classes/queries/list-short-classes/list-short-classes-query.ts new file mode 100644 index 0000000..1a2be1e --- /dev/null +++ b/src/application/classes/queries/list-short-classes/list-short-classes-query.ts @@ -0,0 +1,18 @@ +import { map } from "./list-short-classes-query-mapper"; +import { validate } from "./list-short-classes-query-validator"; + +export type ListShortClassesQuery = Readonly<{ + language: string; +}>; + +export function makeListShortClassesQuery({ classesRepository }: Pick) { + return async function listShortClassesQuery(query: ListShortClassesQuery) { + await validate(query); + + const { language } = query; + + const classes = await classesRepository.getListShort({ language }); + + return classes.map((classItem) => map(classItem, language)); + }; +} diff --git a/src/application/common/interfaces/classes-repository.ts b/src/application/common/interfaces/classes-repository.ts index a021951..ba792ad 100644 --- a/src/application/common/interfaces/classes-repository.ts +++ b/src/application/common/interfaces/classes-repository.ts @@ -1,7 +1,11 @@ -import { Class } from '@domain/entities'; +import { ClassEntity } from '@domain/entities'; export interface ClassesRepository { - highLight(): Promise<{ data: Array }>; - listShort(): Promise<{ data: Array }>; - getById(parameters: { language: string, page_id: string }): Promise; + getHighlightClasses(params: { + language: string; + size?: number; + page?: number + }): Promise<{ data: Array, total: number } | { data: [], total: null }>; + getListShort(params: { language: string }): Promise | []>; + getById(params: { language: string, id: string }): Promise; } diff --git a/src/application/common/interfaces/components-repository.ts b/src/application/common/interfaces/components-repository.ts index f54bc14..8992c03 100644 --- a/src/application/common/interfaces/components-repository.ts +++ b/src/application/common/interfaces/components-repository.ts @@ -1,5 +1,5 @@ -import { Component } from '@domain/entities'; +import { ComponentEntity } from '@domain/entities'; export interface ComponentsRepository { - getBySection(parameters: { language: string, section_id: string }): Promise; + getBySection(parameters: { language: string, section_id: string }): Promise | []>; } diff --git a/src/application/common/interfaces/document-types-repository.ts b/src/application/common/interfaces/document-types-repository.ts index c06e48d..1bd501c 100644 --- a/src/application/common/interfaces/document-types-repository.ts +++ b/src/application/common/interfaces/document-types-repository.ts @@ -1,5 +1,5 @@ -import { DocumentType } from '@domain/entities'; +import { DocumentTypeEntity } from '@domain/entities'; export interface DocumentTypesRepository { - list(): Promise<{ data: Array }>; + list(params: { language: string }): Promise>; } diff --git a/src/application/common/interfaces/documents-repository.ts b/src/application/common/interfaces/documents-repository.ts index 433915e..61b2879 100644 --- a/src/application/common/interfaces/documents-repository.ts +++ b/src/application/common/interfaces/documents-repository.ts @@ -1,6 +1,6 @@ -import { Document } from '@domain/entities'; +import { DocumentEntity } from '@domain/entities'; export interface DocumentsRepository { - getById(parameters: { language: string, id: number }): Promise<{ data: Array }>; - getByDocumentType(parameters: { language: string, document_type_id: number, size: number, page: number }): Promise<{ data: Array }>; + getById(params: { language: string, id: number }): Promise; + getByDocumentType(params: { language: string, document_type_id: number, size?: number; page?: number }): Promise<{ data: Array, total: number } | { data: [], total: null }>; } diff --git a/src/application/common/interfaces/feedbacks-repository.ts b/src/application/common/interfaces/feedbacks-repository.ts index c186cd8..aa9eff3 100644 --- a/src/application/common/interfaces/feedbacks-repository.ts +++ b/src/application/common/interfaces/feedbacks-repository.ts @@ -1,5 +1,9 @@ -import { Feedback } from '@domain/entities'; +import { FeedbackEntity } from '@domain/entities'; export interface FeedbacksRepository { - list(): Promise<{ data: Array }>; + list(params: { + language: string; + size?: number; + page?: number + }): Promise<{ data: Array, total: number } | { data: [], total: null }>; } diff --git a/src/application/common/interfaces/index.ts b/src/application/common/interfaces/index.ts index 429f05f..b9caf78 100644 --- a/src/application/common/interfaces/index.ts +++ b/src/application/common/interfaces/index.ts @@ -5,9 +5,11 @@ export * from './pages-repository'; export * from './sections-repository'; export * from './components-repository'; export * from './classes-repository'; -export * from './lecturers-repository'; -export * from './news-categories-repository'; -export * from './news-repository'; +export * from './documents-repository'; export * from './document-types-repository'; +export * from './lecturers-repository'; export * from './lectures-repository'; export * from './lecture-types-repository'; +export * from './feedbacks-repository'; +export * from './news-categories-repository'; +export * from './news-repository'; diff --git a/src/application/common/interfaces/lecture-types-repository.ts b/src/application/common/interfaces/lecture-types-repository.ts index d2578a4..f3316b2 100644 --- a/src/application/common/interfaces/lecture-types-repository.ts +++ b/src/application/common/interfaces/lecture-types-repository.ts @@ -1,5 +1,5 @@ -import { LectureType } from '@domain/entities'; +import { LectureTypeEntity } from '@domain/entities'; export interface LectureTypesRepository { - list(): Promise<{ data: Array }>; + list(params: { language: string }): Promise>; } diff --git a/src/application/common/interfaces/lecturers-repository.ts b/src/application/common/interfaces/lecturers-repository.ts index c4bbeed..f940486 100644 --- a/src/application/common/interfaces/lecturers-repository.ts +++ b/src/application/common/interfaces/lecturers-repository.ts @@ -1,5 +1,9 @@ -import { Lecturer } from '@domain/entities'; +import { LecturerEntity } from '@domain/entities'; export interface LecturersRepository { - list(): Promise<{ data: Array }>; + list(params: { + language: string; + size?: number; + page?: number + }): Promise<{ data: Array, total: number } | { data: [], total: null }>; } diff --git a/src/application/common/interfaces/lectures-repository.ts b/src/application/common/interfaces/lectures-repository.ts index 23d2f15..16791d2 100644 --- a/src/application/common/interfaces/lectures-repository.ts +++ b/src/application/common/interfaces/lectures-repository.ts @@ -1,6 +1,6 @@ -import { Lecture } from '@domain/entities'; +import { LectureEntity } from '@domain/entities'; export interface LecturesRepository { - getByLectureType(parameters: { language: string, lecture_type_id: number, size: number, page: number }): Promise<{ data: Array }>; - getById(parameters: { language: string, id: number }): Promise; + getByLectureType(params: { language: string, lecture_type_id: number, size?: number, page?: number }): Promise<{ data: Array, total: number } | { data: [], total: null }>; + getById(params: { language: string, id: number }): Promise; } diff --git a/src/application/common/interfaces/news-categories-repository.ts b/src/application/common/interfaces/news-categories-repository.ts index a526fe6..053260c 100644 --- a/src/application/common/interfaces/news-categories-repository.ts +++ b/src/application/common/interfaces/news-categories-repository.ts @@ -1,5 +1,5 @@ -import { NewsCategory } from '@domain/entities'; +import { NewsCategoryEntity } from '@domain/entities'; -export interface NewsCategorysRepository { - list(): Promise<{ data: Array }>; +export interface NewsCategoriesRepository { + list(params: { language: string; }): Promise | null>; } diff --git a/src/application/common/interfaces/news-repository.ts b/src/application/common/interfaces/news-repository.ts index 5c33fc8..49b0e35 100644 --- a/src/application/common/interfaces/news-repository.ts +++ b/src/application/common/interfaces/news-repository.ts @@ -1,7 +1,7 @@ -import { News } from '@domain/entities'; +import { NewsEntity } from '@domain/entities'; -export interface NewssRepository { - getRelated(parameters: { language: string, news_category_id: string, size: number, id: number }): Promise<{ data: Array }>; - getByCategory(parameters: { language: string, news_category_id: string, size: number, page: number }): Promise<{ data: Array }>; - getBySlug(parameters: { language: string, slug: string }): Promise; +export interface NewsRepository { + getRelated(params: { language: string, news_category_id: number, size?: number, page?: number, id: number }): Promise<{ data: Array, total: number } | { data: [], total: null }>; + getByCategory(params: { language: string, news_category_id: number, size?: number, page?: number }): Promise<{ data: Array, total: number } | { data: [], total: null }>; + getBySlug(params: { language: string, slug: string }): Promise; } diff --git a/src/application/common/interfaces/sections-repository.ts b/src/application/common/interfaces/sections-repository.ts index d8cafbc..505992b 100644 --- a/src/application/common/interfaces/sections-repository.ts +++ b/src/application/common/interfaces/sections-repository.ts @@ -1,6 +1,6 @@ -import { Section } from '@domain/entities'; +import { SectionEntity } from "@domain/entities"; export interface SectionsRepository { - getByPage(parameters: { language: string, page_id: string }): Promise<{ data: Array
}>; - getByPageUrl(parameters: { language: string, url: string }): Promise<{ data: Array
}>; + getByPage(parameters: { language: string, page_id: string }): Promise | []>; + getByPageUrl(parameters: { language: string, url: string }): Promise | []>; } diff --git a/src/application/common/response-base.ts b/src/application/common/response-base.ts index 22708c4..371c3a5 100644 --- a/src/application/common/response-base.ts +++ b/src/application/common/response-base.ts @@ -1,26 +1,30 @@ export default class ResponseBase { - static formatCountResponse(data: T, perPage: number, total: number) { + static formatPaginationResponse(status_code: number, data: T, total: number, per_page: number, current_page: number, last_page: number, message: string) { return { - content: data, - totalElements: perPage, - totalPages: total, + status_code, + data, + total, + per_page, + current_page, + last_page, + message, }; } - static formatBaseResponse(statusCode: number, data: T, message: string) { + static formatBaseResponse(status_code: number, data: T, message: string) { return { - statusCode: statusCode, - data: data, - message: message, + status_code, + data, + message, }; } - static formatBaseResponseWithTotal(statusCode: number, data: T, total: number, message: string) { + static formatBaseResponseWithTotal(status_code: number, data: T, total: number, message: string) { return { - statusCode: statusCode, - data: data, - total: total, - message: message, + status_code, + data, + total, + message, }; } } diff --git a/src/application/components/index.ts b/src/application/components/index.ts new file mode 100644 index 0000000..e7e9af8 --- /dev/null +++ b/src/application/components/index.ts @@ -0,0 +1,9 @@ +import { makeComponentGetBySection } from "./queries/get-by-section"; + +export function makeComponentsUseCases(dependencies: Dependencies) { + return { + queries: { + listComponentsBySection: makeComponentGetBySection(dependencies), + }, + }; +} diff --git a/src/application/components/queries/get-by-section/get-by-component-query-mapper.ts b/src/application/components/queries/get-by-section/get-by-component-query-mapper.ts new file mode 100644 index 0000000..f249dde --- /dev/null +++ b/src/application/components/queries/get-by-section/get-by-component-query-mapper.ts @@ -0,0 +1,23 @@ +import { ComponentDTO } from "@domain/dtos/component"; +import { ComponentEntity } from "@domain/entities"; + +export function map(component: ComponentEntity, language: string): ComponentDTO { + return { + id: component.id?.toString() || '', + image: component.image || '', + image_2: component.image_2 || '', + image_3: component.image_3 || '', + image_4: component.image_4 || '', + image_5: component.image_5 || '', + image_6: component.image_6 || '', + image_7: component.image_7 || '', + title: language === 'vi' ? component.vi_title : component.en_title, + content: language === 'vi' ? component?.vi_content || '' : component?.en_content || '', + order: component.order || null, + status: component.status, + created_at: component.created_at ? component.created_at.toISOString() : null, + updated_at: component.updated_at ? component.updated_at.toISOString() : null, + created_by: component.created_by || null, + updated_by: component.updated_by || null, + }; +} diff --git a/src/application/components/queries/get-by-section/get-by-component-query-validator.ts b/src/application/components/queries/get-by-section/get-by-component-query-validator.ts new file mode 100644 index 0000000..5d49683 --- /dev/null +++ b/src/application/components/queries/get-by-section/get-by-component-query-validator.ts @@ -0,0 +1,17 @@ +import { ValidationException } from '@application/common/exceptions'; +import { ZodError, z } from 'zod'; + +import { GetBySectionQuery } from './get-by-component-query'; + +export async function validate(query: GetBySectionQuery) { + try { + const schema: z.ZodType = z.object({ + language: z.string(), + section_id: z.string() + }); + + await schema.parseAsync(query); + } catch (error) { + throw new ValidationException(error as ZodError); + } +} diff --git a/src/application/components/queries/get-by-section/get-by-component-query.ts b/src/application/components/queries/get-by-section/get-by-component-query.ts new file mode 100644 index 0000000..e8e956f --- /dev/null +++ b/src/application/components/queries/get-by-section/get-by-component-query.ts @@ -0,0 +1,19 @@ +import { map } from "./get-by-component-query-mapper"; +import { validate } from "./get-by-component-query-validator"; + +export type GetBySectionQuery = Readonly<{ + language: string; + section_id: string; +}>; + +export function makeComponentGetBySection({ componentsRepository }: Pick) { + return async function listSectionsByPageQuery(query: GetBySectionQuery) { + await validate(query); + + const { language, section_id } = query; + + const components = await componentsRepository.getBySection({ language, section_id }); + + return components.map((component) => map(component, language)); + }; +} diff --git a/src/application/components/queries/get-by-section/index.ts b/src/application/components/queries/get-by-section/index.ts new file mode 100644 index 0000000..c1fe900 --- /dev/null +++ b/src/application/components/queries/get-by-section/index.ts @@ -0,0 +1 @@ +export * from './get-by-component-query'; diff --git a/src/application/document-types/index.ts b/src/application/document-types/index.ts new file mode 100644 index 0000000..10da2f0 --- /dev/null +++ b/src/application/document-types/index.ts @@ -0,0 +1,9 @@ +import { makeListDocumentTypesQuery } from "./queries/list-document-types"; + +export function makeDocumentTypesUseCases(dependencies: Dependencies) { + return { + queries: { + listDocumentTypes: makeListDocumentTypesQuery(dependencies), + }, + }; +} diff --git a/src/application/document-types/queries/list-document-types/index.ts b/src/application/document-types/queries/list-document-types/index.ts new file mode 100644 index 0000000..ac598a8 --- /dev/null +++ b/src/application/document-types/queries/list-document-types/index.ts @@ -0,0 +1 @@ +export * from './list-document-types-query'; diff --git a/src/application/document-types/queries/list-document-types/list-document-types-query-mapper.ts b/src/application/document-types/queries/list-document-types/list-document-types-query-mapper.ts new file mode 100644 index 0000000..7df636b --- /dev/null +++ b/src/application/document-types/queries/list-document-types/list-document-types-query-mapper.ts @@ -0,0 +1,16 @@ +import { DocumentTypeDTO } from "@domain/dtos/document-type"; +import { DocumentTypeEntity } from "@domain/entities"; + +export function map(documentType: DocumentTypeEntity, language: string): DocumentTypeDTO { + return { + id: documentType.id?.toString() || '', + name: language === 'vi' ? documentType.vi_name : documentType.en_name, + description: language === 'vi' ? documentType.vi_description ?? null : documentType.en_description ?? null, + order: documentType.order ?? null, + status: documentType.status, + created_at: documentType.created_at?.toISOString() ?? null, + updated_at: documentType.updated_at?.toISOString() ?? null, + created_by: documentType.created_by ?? null, + updated_by: documentType.updated_by ?? null, + }; +} diff --git a/src/application/document-types/queries/list-document-types/list-document-types-query-validator.ts b/src/application/document-types/queries/list-document-types/list-document-types-query-validator.ts new file mode 100644 index 0000000..6f5826c --- /dev/null +++ b/src/application/document-types/queries/list-document-types/list-document-types-query-validator.ts @@ -0,0 +1,16 @@ +import { ValidationException } from '@application/common/exceptions'; +import { ZodError, z } from 'zod'; + +import { ListDocumentTypesQuery } from './list-document-types-query'; + +export async function validate(query: ListDocumentTypesQuery) { + try { + const schema: z.ZodType = z.object({ + language: z.string() + }); + + await schema.parseAsync(query); + } catch (error) { + throw new ValidationException(error as ZodError); + } +} diff --git a/src/application/document-types/queries/list-document-types/list-document-types-query.ts b/src/application/document-types/queries/list-document-types/list-document-types-query.ts new file mode 100644 index 0000000..8a9901f --- /dev/null +++ b/src/application/document-types/queries/list-document-types/list-document-types-query.ts @@ -0,0 +1,18 @@ +import { map } from "./list-document-types-query-mapper"; +import { validate } from "./list-document-types-query-validator"; + +export type ListDocumentTypesQuery = Readonly<{ + language: string; +}>; + +export function makeListDocumentTypesQuery({ documentTypesRepository }: Pick) { + return async function listDocumentTypesQuery(query: ListDocumentTypesQuery) { + await validate(query); + + const { language } = query; + + const documentTypes = await documentTypesRepository.list({ language }); + + return documentTypes.map((documentType) => map(documentType, language)); + }; +} diff --git a/src/application/documents/index.ts b/src/application/documents/index.ts new file mode 100644 index 0000000..eab34de --- /dev/null +++ b/src/application/documents/index.ts @@ -0,0 +1,11 @@ +import { makeGetByDocumentTypeQuery } from "./queries/get-by-document-type"; +import { makeGetByIdQuery } from "./queries/get-by-id"; + +export function makeDocumentsUseCases(dependencies: Dependencies) { + return { + queries: { + getByDocumentType: makeGetByDocumentTypeQuery(dependencies), + getById: makeGetByIdQuery(dependencies), + }, + }; +} diff --git a/src/application/documents/queries/get-by-document-type/get-by-document-type-query-mapper.ts b/src/application/documents/queries/get-by-document-type/get-by-document-type-query-mapper.ts new file mode 100644 index 0000000..1395410 --- /dev/null +++ b/src/application/documents/queries/get-by-document-type/get-by-document-type-query-mapper.ts @@ -0,0 +1,21 @@ +import { DocumentDTO } from "@domain/dtos/document"; +import { DocumentEntity } from "@domain/entities"; + +export function map(documentType: DocumentEntity, language: string): DocumentDTO { + return { + id: documentType.id ?? 0, + document_type_id: documentType.document_type_id ?? 0, + link_file: documentType.link_file ?? '', + downloaded: documentType.downloaded ?? 0, + image: documentType.image ?? '', + order: documentType.order ?? null, + status: documentType.status ?? 0, + title: language === 'vi' ? documentType.vi_title || '' : documentType.en_title || '', + description: language === 'vi' ? documentType.vi_description || '' : documentType.en_description || '', + content: language === 'vi' ? documentType.vi_content || '' : documentType.en_content || '', + created_at: documentType.created_at?.toISOString() ?? null, + updated_at: documentType.updated_at?.toISOString() ?? null, + created_by: documentType.created_by ?? null, + updated_by: documentType.updated_by ?? null, + }; +} diff --git a/src/application/documents/queries/get-by-document-type/get-by-document-type-query-validator.ts b/src/application/documents/queries/get-by-document-type/get-by-document-type-query-validator.ts new file mode 100644 index 0000000..6285cd3 --- /dev/null +++ b/src/application/documents/queries/get-by-document-type/get-by-document-type-query-validator.ts @@ -0,0 +1,19 @@ +import { ValidationException } from '@application/common/exceptions'; +import { ZodError, z } from 'zod'; + +import { GetByDocumentTypeQuery } from './get-by-document-type-query'; + +export async function validate(query: GetByDocumentTypeQuery) { + try { + const schema: z.ZodType = z.object({ + language: z.string(), + document_type_id: z.number(), + size: z.number().optional(), + page: z.number().optional(), + }); + + await schema.parseAsync(query); + } catch (error) { + throw new ValidationException(error as ZodError); + } +} diff --git a/src/application/documents/queries/get-by-document-type/get-by-document-type-query.ts b/src/application/documents/queries/get-by-document-type/get-by-document-type-query.ts new file mode 100644 index 0000000..eb99c39 --- /dev/null +++ b/src/application/documents/queries/get-by-document-type/get-by-document-type-query.ts @@ -0,0 +1,31 @@ +import { map } from "./get-by-document-type-query-mapper"; +import { validate } from "./get-by-document-type-query-validator"; + +export type GetByDocumentTypeQuery = Readonly<{ + language: string; + document_type_id: number; + size?: number; + page?: number +}>; + +export function makeGetByDocumentTypeQuery({ documentsRepository }: Pick) { + return async function getByDocumentTypeQuery(query: GetByDocumentTypeQuery) { + await validate(query); + + const { language, document_type_id, size, page } = query; + + const { data, total } = await documentsRepository.getByDocumentType({ language, document_type_id, size, page }); + + const per_page = size; + const current_page = page; + const last_page = total && per_page ? Math.ceil(total / per_page) : 1; + + return { + data: data.map((documentItem) => map(documentItem, language)), + total, + per_page, + current_page, + last_page, + } + }; +} diff --git a/src/application/documents/queries/get-by-document-type/index.ts b/src/application/documents/queries/get-by-document-type/index.ts new file mode 100644 index 0000000..182ecf4 --- /dev/null +++ b/src/application/documents/queries/get-by-document-type/index.ts @@ -0,0 +1 @@ +export * from './get-by-document-type-query'; diff --git a/src/application/documents/queries/get-by-id/get-by-id-query-mapper.ts b/src/application/documents/queries/get-by-id/get-by-id-query-mapper.ts new file mode 100644 index 0000000..1395410 --- /dev/null +++ b/src/application/documents/queries/get-by-id/get-by-id-query-mapper.ts @@ -0,0 +1,21 @@ +import { DocumentDTO } from "@domain/dtos/document"; +import { DocumentEntity } from "@domain/entities"; + +export function map(documentType: DocumentEntity, language: string): DocumentDTO { + return { + id: documentType.id ?? 0, + document_type_id: documentType.document_type_id ?? 0, + link_file: documentType.link_file ?? '', + downloaded: documentType.downloaded ?? 0, + image: documentType.image ?? '', + order: documentType.order ?? null, + status: documentType.status ?? 0, + title: language === 'vi' ? documentType.vi_title || '' : documentType.en_title || '', + description: language === 'vi' ? documentType.vi_description || '' : documentType.en_description || '', + content: language === 'vi' ? documentType.vi_content || '' : documentType.en_content || '', + created_at: documentType.created_at?.toISOString() ?? null, + updated_at: documentType.updated_at?.toISOString() ?? null, + created_by: documentType.created_by ?? null, + updated_by: documentType.updated_by ?? null, + }; +} diff --git a/src/application/documents/queries/get-by-id/get-by-id-query-validator.ts b/src/application/documents/queries/get-by-id/get-by-id-query-validator.ts new file mode 100644 index 0000000..4d268d7 --- /dev/null +++ b/src/application/documents/queries/get-by-id/get-by-id-query-validator.ts @@ -0,0 +1,17 @@ +import { ValidationException } from '@application/common/exceptions'; +import { ZodError, z } from 'zod'; + +import { GetByIdQuery } from './get-by-id-query'; + +export async function validate(query: GetByIdQuery) { + try { + const schema: z.ZodType = z.object({ + language: z.string(), + id: z.number() + }); + + await schema.parseAsync(query); + } catch (error) { + throw new ValidationException(error as ZodError); + } +} diff --git a/src/application/documents/queries/get-by-id/get-by-id-query.ts b/src/application/documents/queries/get-by-id/get-by-id-query.ts new file mode 100644 index 0000000..a40a5d4 --- /dev/null +++ b/src/application/documents/queries/get-by-id/get-by-id-query.ts @@ -0,0 +1,19 @@ +import { map } from "./get-by-id-query-mapper"; +import { validate } from "./get-by-id-query-validator"; + +export type GetByIdQuery = Readonly<{ + language: string; + id: number +}>; + +export function makeGetByIdQuery({ documentsRepository }: Pick) { + return async function getByIdQuery(query: GetByIdQuery) { + await validate(query); + + const { id, language } = query; + + const document = await documentsRepository.getById({ id, language }); + + return document ? map(document, language) : null; + }; +} diff --git a/src/application/documents/queries/get-by-id/index.ts b/src/application/documents/queries/get-by-id/index.ts new file mode 100644 index 0000000..6fae336 --- /dev/null +++ b/src/application/documents/queries/get-by-id/index.ts @@ -0,0 +1 @@ +export * from './get-by-id-query'; diff --git a/src/application/feedbacks/index.ts b/src/application/feedbacks/index.ts new file mode 100644 index 0000000..9a0d3d4 --- /dev/null +++ b/src/application/feedbacks/index.ts @@ -0,0 +1,9 @@ +import { makeListFeedbacksQuery } from "./queries/list-feedbacks"; + +export function makeFeedbacksUseCases(dependencies: Dependencies) { + return { + queries: { + listFeedbacks: makeListFeedbacksQuery(dependencies), + }, + }; +} diff --git a/src/application/feedbacks/queries/list-feedbacks/index.ts b/src/application/feedbacks/queries/list-feedbacks/index.ts new file mode 100644 index 0000000..d3b4b0d --- /dev/null +++ b/src/application/feedbacks/queries/list-feedbacks/index.ts @@ -0,0 +1 @@ +export * from './list-feedbacks-query'; diff --git a/src/application/feedbacks/queries/list-feedbacks/list-feedbacks-query-mapper.ts b/src/application/feedbacks/queries/list-feedbacks/list-feedbacks-query-mapper.ts new file mode 100644 index 0000000..6bc3bd4 --- /dev/null +++ b/src/application/feedbacks/queries/list-feedbacks/list-feedbacks-query-mapper.ts @@ -0,0 +1,24 @@ +import { FeedbackDTO } from "@domain/dtos/feedback"; +import { FeedbackEntity } from "@domain/entities"; + +export function map(feedback: FeedbackEntity, language: string): FeedbackDTO { + return { + id: feedback.id?.toString() || '', + name: feedback.name ?? null, + address: feedback.address ?? null, + content: language === 'vi' ? feedback.vi_content || '' : feedback.en_content || '', + avatar: feedback.avatar ?? null, + image: feedback.image ?? null, + image_2: feedback.image_2 ?? null, + image_3: feedback.image_3 ?? null, + image_4: feedback.image_4 ?? null, + image_5: feedback.image_5 ?? null, + image_6: feedback.image_6 ?? null, + order: feedback.order ?? null, + status: feedback.status ?? 0, + created_at: feedback.created_at?.toISOString() ?? null, + updated_at: feedback.updated_at?.toISOString() ?? null, + created_by: feedback.created_by ?? null, + updated_by: feedback.updated_by ?? null, + }; +} diff --git a/src/application/feedbacks/queries/list-feedbacks/list-feedbacks-query-validator.ts b/src/application/feedbacks/queries/list-feedbacks/list-feedbacks-query-validator.ts new file mode 100644 index 0000000..6702fd4 --- /dev/null +++ b/src/application/feedbacks/queries/list-feedbacks/list-feedbacks-query-validator.ts @@ -0,0 +1,18 @@ +import { ValidationException } from '@application/common/exceptions'; +import { ZodError, z } from 'zod'; + +import { ListFeedbacksQuery } from './list-feedbacks-query'; + +export async function validate(query: ListFeedbacksQuery) { + try { + const schema: z.ZodType = z.object({ + language: z.string(), + size: z.number().optional(), + page: z.number().optional(), + }); + + await schema.parseAsync(query); + } catch (error) { + throw new ValidationException(error as ZodError); + } +} diff --git a/src/application/feedbacks/queries/list-feedbacks/list-feedbacks-query.ts b/src/application/feedbacks/queries/list-feedbacks/list-feedbacks-query.ts new file mode 100644 index 0000000..dc8751d --- /dev/null +++ b/src/application/feedbacks/queries/list-feedbacks/list-feedbacks-query.ts @@ -0,0 +1,30 @@ +import { map } from "./list-feedbacks-query-mapper"; +import { validate } from "./list-feedbacks-query-validator"; + +export type ListFeedbacksQuery = Readonly<{ + language: string; + size?: number; + page?: number +}>; + +export function makeListFeedbacksQuery({ feedbacksRepository }: Pick) { + return async function listFeedbacksQuery(query: ListFeedbacksQuery) { + await validate(query); + + const { language, size, page } = query; + + const { data, total } = await feedbacksRepository.list({ language, size, page }); + + const per_page = size; + const current_page = page; + const last_page = total && per_page ? Math.ceil(total / per_page) : 1; + + return { + data: data.map((feedbackItem) => map(feedbackItem, language)), + total, + per_page, + current_page, + last_page, + } + }; +} diff --git a/src/application/lecture-types/index.ts b/src/application/lecture-types/index.ts new file mode 100644 index 0000000..89d3c66 --- /dev/null +++ b/src/application/lecture-types/index.ts @@ -0,0 +1,9 @@ +import { makeListLectureTypesQuery } from "./queries/list-lecture-types"; + +export function makeLectureTypesUseCases(dependencies: Dependencies) { + return { + queries: { + listLectureTypes: makeListLectureTypesQuery(dependencies), + }, + }; +} diff --git a/src/application/lecture-types/queries/list-lecture-types/index.ts b/src/application/lecture-types/queries/list-lecture-types/index.ts new file mode 100644 index 0000000..1d26936 --- /dev/null +++ b/src/application/lecture-types/queries/list-lecture-types/index.ts @@ -0,0 +1 @@ +export * from './list-lecture-types-query'; diff --git a/src/application/lecture-types/queries/list-lecture-types/list-lecture-types-query-mapper.ts b/src/application/lecture-types/queries/list-lecture-types/list-lecture-types-query-mapper.ts new file mode 100644 index 0000000..4a56794 --- /dev/null +++ b/src/application/lecture-types/queries/list-lecture-types/list-lecture-types-query-mapper.ts @@ -0,0 +1,16 @@ +import { LectureTypeDTO } from "@domain/dtos/lecture-type"; +import { LectureTypeEntity } from "@domain/entities"; + +export function map(lectureTypes: LectureTypeEntity, language: string): LectureTypeDTO { + return { + id: lectureTypes.id?.toString() || '', + name: language === 'vi' ? lectureTypes.vi_name : lectureTypes.en_name, + description: language === 'vi' ? lectureTypes.vi_description || '' : lectureTypes.en_description || '', + order: lectureTypes.order || null, + status: lectureTypes.status, + created_at: lectureTypes.created_at ? lectureTypes.created_at.toISOString() : null, + updated_at: lectureTypes.updated_at ? lectureTypes.updated_at.toISOString() : null, + created_by: lectureTypes.created_by || null, + updated_by: lectureTypes.updated_by || null, + }; +} diff --git a/src/application/lecture-types/queries/list-lecture-types/list-lecture-types-query-validator.ts b/src/application/lecture-types/queries/list-lecture-types/list-lecture-types-query-validator.ts new file mode 100644 index 0000000..ed38a6a --- /dev/null +++ b/src/application/lecture-types/queries/list-lecture-types/list-lecture-types-query-validator.ts @@ -0,0 +1,16 @@ +import { ValidationException } from '@application/common/exceptions'; +import { ZodError, z } from 'zod'; + +import { ListLectureTypesQuery } from './list-lecture-types-query'; + +export async function validate(query: ListLectureTypesQuery) { + try { + const schema: z.ZodType = z.object({ + language: z.string() + }); + + await schema.parseAsync(query); + } catch (error) { + throw new ValidationException(error as ZodError); + } +} diff --git a/src/application/lecture-types/queries/list-lecture-types/list-lecture-types-query.ts b/src/application/lecture-types/queries/list-lecture-types/list-lecture-types-query.ts new file mode 100644 index 0000000..3201b55 --- /dev/null +++ b/src/application/lecture-types/queries/list-lecture-types/list-lecture-types-query.ts @@ -0,0 +1,18 @@ +import { map } from "./list-lecture-types-query-mapper"; +import { validate } from "./list-lecture-types-query-validator"; + +export type ListLectureTypesQuery = Readonly<{ + language: string; +}>; + +export function makeListLectureTypesQuery({ lectureTypesRepository }: Pick) { + return async function listPagesQuery(query: ListLectureTypesQuery) { + await validate(query); + + const { language } = query; + + const lectureTypes = await lectureTypesRepository.list({ language }); + + return lectureTypes.map((lectureType) => map(lectureType, language)); + }; +} diff --git a/src/application/lecturers/index.ts b/src/application/lecturers/index.ts new file mode 100644 index 0000000..2737830 --- /dev/null +++ b/src/application/lecturers/index.ts @@ -0,0 +1,9 @@ +import { makeListLecturersQuery } from "./queries/list-lecturers"; + +export function makeLecturersUseCases(dependencies: Dependencies) { + return { + queries: { + listLecturers: makeListLecturersQuery(dependencies), + }, + }; +} diff --git a/src/application/lecturers/queries/list-lecturers/index.ts b/src/application/lecturers/queries/list-lecturers/index.ts new file mode 100644 index 0000000..f89c162 --- /dev/null +++ b/src/application/lecturers/queries/list-lecturers/index.ts @@ -0,0 +1 @@ +export * from './list-lecturers-query'; diff --git a/src/application/lecturers/queries/list-lecturers/list-lecturers-query-mapper.ts b/src/application/lecturers/queries/list-lecturers/list-lecturers-query-mapper.ts new file mode 100644 index 0000000..dddfca2 --- /dev/null +++ b/src/application/lecturers/queries/list-lecturers/list-lecturers-query-mapper.ts @@ -0,0 +1,18 @@ +import { LecturerDTO } from "@domain/dtos/lecturer"; +import { LecturerEntity } from "@domain/entities"; + +export function map(lecturers: LecturerEntity, language: string): LecturerDTO { + return { + id: lecturers.id?.toString() || '', + avatar: lecturers.avatar, + name: lecturers.name, + title: language === 'vi' ? lecturers.vi_title || '' : lecturers.en_title || '', + content: language === 'vi' ? lecturers.vi_content || '' : lecturers.en_content || '', + order: lecturers.order || null, + status: lecturers.status, + created_at: lecturers.created_at ? lecturers.created_at.toISOString() : null, + updated_at: lecturers.updated_at ? lecturers.updated_at.toISOString() : null, + created_by: lecturers.created_by || null, + updated_by: lecturers.updated_by || null, + }; +} diff --git a/src/application/lecturers/queries/list-lecturers/list-lecturers-query-validator.ts b/src/application/lecturers/queries/list-lecturers/list-lecturers-query-validator.ts new file mode 100644 index 0000000..fbe7011 --- /dev/null +++ b/src/application/lecturers/queries/list-lecturers/list-lecturers-query-validator.ts @@ -0,0 +1,18 @@ +import { ValidationException } from '@application/common/exceptions'; +import { ZodError, z } from 'zod'; + +import { ListLecturersQuery } from './list-lecturers-query'; + +export async function validate(query: ListLecturersQuery) { + try { + const schema: z.ZodType = z.object({ + language: z.string(), + size: z.number().optional(), + page: z.number().optional(), + }); + + await schema.parseAsync(query); + } catch (error) { + throw new ValidationException(error as ZodError); + } +} diff --git a/src/application/lecturers/queries/list-lecturers/list-lecturers-query.ts b/src/application/lecturers/queries/list-lecturers/list-lecturers-query.ts new file mode 100644 index 0000000..fbd25c5 --- /dev/null +++ b/src/application/lecturers/queries/list-lecturers/list-lecturers-query.ts @@ -0,0 +1,30 @@ +import { map } from "./list-lecturers-query-mapper"; +import { validate } from "./list-lecturers-query-validator"; + +export type ListLecturersQuery = Readonly<{ + language: string; + size?: number; + page?: number +}>; + +export function makeListLecturersQuery({ lecturersRepository }: Pick) { + return async function listLecturersQuery(query: ListLecturersQuery) { + await validate(query); + + const { language, size, page } = query; + + const { data, total } = await lecturersRepository.list({ language, size, page }); + + const per_page = size; + const current_page = page; + const last_page = total && per_page ? Math.ceil(total / per_page) : 1; + + return { + data: data.map((feedbackItem) => map(feedbackItem, language)), + total, + per_page, + current_page, + last_page, + } + }; +} diff --git a/src/application/lectures/index.ts b/src/application/lectures/index.ts new file mode 100644 index 0000000..1d97894 --- /dev/null +++ b/src/application/lectures/index.ts @@ -0,0 +1,11 @@ +import { makeGetByIdQuery } from "./queries/get-by-id"; +import { makeGetByLectureTypeQuery } from "./queries/get-by-lecture-type"; + +export function makeLecturesUseCases(dependencies: Dependencies) { + return { + queries: { + getByLectureType: makeGetByLectureTypeQuery(dependencies), + getById: makeGetByIdQuery(dependencies), + }, + }; +} diff --git a/src/application/lectures/queries/get-by-id/get-by-id-query-mapper.ts b/src/application/lectures/queries/get-by-id/get-by-id-query-mapper.ts new file mode 100644 index 0000000..2a2547b --- /dev/null +++ b/src/application/lectures/queries/get-by-id/get-by-id-query-mapper.ts @@ -0,0 +1,21 @@ +import { LectureDTO } from "@domain/dtos/lecture"; +import { LectureEntity } from "@domain/entities"; + +export function map(lecture: LectureEntity, language: string): LectureDTO { + return { + id: lecture.id?.toString() || '', + lecture_type_id: lecture.lecture_type_id, + associcate_link: lecture.associcate_link || '', + viewer: lecture.viewer, + image: lecture.image || '', + title: language === 'vi' ? lecture.vi_title || '' : lecture.en_title || '', + description: language === 'vi' ? lecture.vi_description || '' : lecture.en_description || '', + content: language === 'vi' ? lecture.vi_content || '' : lecture.en_content || '', + order: lecture.order || null, + status: lecture.status, + created_at: lecture.created_at ? lecture.created_at.toISOString() : null, + updated_at: lecture.updated_at ? lecture.updated_at.toISOString() : null, + created_by: lecture.created_by || null, + updated_by: lecture.updated_by || null, + }; +} diff --git a/src/application/lectures/queries/get-by-id/get-by-id-query-validator.ts b/src/application/lectures/queries/get-by-id/get-by-id-query-validator.ts new file mode 100644 index 0000000..4d268d7 --- /dev/null +++ b/src/application/lectures/queries/get-by-id/get-by-id-query-validator.ts @@ -0,0 +1,17 @@ +import { ValidationException } from '@application/common/exceptions'; +import { ZodError, z } from 'zod'; + +import { GetByIdQuery } from './get-by-id-query'; + +export async function validate(query: GetByIdQuery) { + try { + const schema: z.ZodType = z.object({ + language: z.string(), + id: z.number() + }); + + await schema.parseAsync(query); + } catch (error) { + throw new ValidationException(error as ZodError); + } +} diff --git a/src/application/lectures/queries/get-by-id/get-by-id-query.ts b/src/application/lectures/queries/get-by-id/get-by-id-query.ts new file mode 100644 index 0000000..ed65772 --- /dev/null +++ b/src/application/lectures/queries/get-by-id/get-by-id-query.ts @@ -0,0 +1,19 @@ +import { map } from "./get-by-id-query-mapper"; +import { validate } from "./get-by-id-query-validator"; + +export type GetByIdQuery = Readonly<{ + language: string; + id: number +}>; + +export function makeGetByIdQuery({ lecturesRepository }: Pick) { + return async function getByIdQuery(query: GetByIdQuery) { + await validate(query); + + const { id, language } = query; + + const lecture = await lecturesRepository.getById({ id, language }); + + return lecture ? map(lecture, language) : null; + }; +} diff --git a/src/application/lectures/queries/get-by-id/index.ts b/src/application/lectures/queries/get-by-id/index.ts new file mode 100644 index 0000000..6fae336 --- /dev/null +++ b/src/application/lectures/queries/get-by-id/index.ts @@ -0,0 +1 @@ +export * from './get-by-id-query'; diff --git a/src/application/lectures/queries/get-by-lecture-type/get-by-lecture-type-query-mapper.ts b/src/application/lectures/queries/get-by-lecture-type/get-by-lecture-type-query-mapper.ts new file mode 100644 index 0000000..2a2547b --- /dev/null +++ b/src/application/lectures/queries/get-by-lecture-type/get-by-lecture-type-query-mapper.ts @@ -0,0 +1,21 @@ +import { LectureDTO } from "@domain/dtos/lecture"; +import { LectureEntity } from "@domain/entities"; + +export function map(lecture: LectureEntity, language: string): LectureDTO { + return { + id: lecture.id?.toString() || '', + lecture_type_id: lecture.lecture_type_id, + associcate_link: lecture.associcate_link || '', + viewer: lecture.viewer, + image: lecture.image || '', + title: language === 'vi' ? lecture.vi_title || '' : lecture.en_title || '', + description: language === 'vi' ? lecture.vi_description || '' : lecture.en_description || '', + content: language === 'vi' ? lecture.vi_content || '' : lecture.en_content || '', + order: lecture.order || null, + status: lecture.status, + created_at: lecture.created_at ? lecture.created_at.toISOString() : null, + updated_at: lecture.updated_at ? lecture.updated_at.toISOString() : null, + created_by: lecture.created_by || null, + updated_by: lecture.updated_by || null, + }; +} diff --git a/src/application/lectures/queries/get-by-lecture-type/get-by-lecture-type-query-validator.ts b/src/application/lectures/queries/get-by-lecture-type/get-by-lecture-type-query-validator.ts new file mode 100644 index 0000000..3ca2842 --- /dev/null +++ b/src/application/lectures/queries/get-by-lecture-type/get-by-lecture-type-query-validator.ts @@ -0,0 +1,19 @@ +import { ValidationException } from '@application/common/exceptions'; +import { ZodError, z } from 'zod'; + +import { GetByLectureTypeQuery } from './get-by-lecture-type-query'; + +export async function validate(query: GetByLectureTypeQuery) { + try { + const schema: z.ZodType = z.object({ + language: z.string(), + lecture_type_id: z.number(), + size: z.number().optional(), + page: z.number().optional(), + }); + + await schema.parseAsync(query); + } catch (error) { + throw new ValidationException(error as ZodError); + } +} diff --git a/src/application/lectures/queries/get-by-lecture-type/get-by-lecture-type-query.ts b/src/application/lectures/queries/get-by-lecture-type/get-by-lecture-type-query.ts new file mode 100644 index 0000000..3380c82 --- /dev/null +++ b/src/application/lectures/queries/get-by-lecture-type/get-by-lecture-type-query.ts @@ -0,0 +1,31 @@ +import { map } from "./get-by-lecture-type-query-mapper"; +import { validate } from "./get-by-lecture-type-query-validator"; + +export type GetByLectureTypeQuery = Readonly<{ + language: string; + lecture_type_id: number; + size?: number; + page?: number +}>; + +export function makeGetByLectureTypeQuery({ lecturesRepository }: Pick) { + return async function getByLectureTypeQuery(query: GetByLectureTypeQuery) { + await validate(query); + + const { lecture_type_id, language, size, page } = query; + + const { data, total } = await lecturesRepository.getByLectureType({ lecture_type_id, language, size, page }); + + const per_page = size; + const current_page = page; + const last_page = total && per_page ? Math.ceil(total / per_page) : 1; + + return { + data: data.map((lectureItem) => map(lectureItem, language)), + total, + per_page, + current_page, + last_page, + } + }; +} diff --git a/src/application/lectures/queries/get-by-lecture-type/index.ts b/src/application/lectures/queries/get-by-lecture-type/index.ts new file mode 100644 index 0000000..2e764a0 --- /dev/null +++ b/src/application/lectures/queries/get-by-lecture-type/index.ts @@ -0,0 +1 @@ +export * from './get-by-lecture-type-query'; diff --git a/src/application/news-categories/index.ts b/src/application/news-categories/index.ts new file mode 100644 index 0000000..eaaf3f1 --- /dev/null +++ b/src/application/news-categories/index.ts @@ -0,0 +1,9 @@ +import { makeListNewsCategoriesQuery } from "./queries/list-news-categories"; + +export function makeNewsCategoriesUseCases(dependencies: Dependencies) { + return { + queries: { + list: makeListNewsCategoriesQuery(dependencies), + }, + }; +} diff --git a/src/application/news-categories/queries/list-news-categories/index.ts b/src/application/news-categories/queries/list-news-categories/index.ts new file mode 100644 index 0000000..973dca5 --- /dev/null +++ b/src/application/news-categories/queries/list-news-categories/index.ts @@ -0,0 +1 @@ +export * from './list-news-categories-query'; diff --git a/src/application/news-categories/queries/list-news-categories/list-news-categories-query-mapper.ts b/src/application/news-categories/queries/list-news-categories/list-news-categories-query-mapper.ts new file mode 100644 index 0000000..5b41458 --- /dev/null +++ b/src/application/news-categories/queries/list-news-categories/list-news-categories-query-mapper.ts @@ -0,0 +1,16 @@ +import { NewsCategoryDTO } from "@domain/dtos/news-category"; +import { NewsCategoryEntity } from "@domain/entities"; + +export function map(newsCategory: NewsCategoryEntity, language: string): NewsCategoryDTO { + return { + id: newsCategory.id?.toString() || '', + name: language === 'vi' ? newsCategory.vi_name || '' : newsCategory.en_name || '', + description: language === 'vi' ? newsCategory.vi_description || '' : newsCategory.en_description || '', + order: newsCategory.order || null, + status: newsCategory.status, + created_at: newsCategory.created_at ? newsCategory.created_at.toISOString() : null, + updated_at: newsCategory.updated_at ? newsCategory.updated_at.toISOString() : null, + created_by: newsCategory.created_by || null, + updated_by: newsCategory.updated_by || null, + }; +} diff --git a/src/application/news-categories/queries/list-news-categories/list-news-categories-query-validator.ts b/src/application/news-categories/queries/list-news-categories/list-news-categories-query-validator.ts new file mode 100644 index 0000000..9e0c163 --- /dev/null +++ b/src/application/news-categories/queries/list-news-categories/list-news-categories-query-validator.ts @@ -0,0 +1,16 @@ +import { ValidationException } from '@application/common/exceptions'; +import { ZodError, z } from 'zod'; + +import { ListNewsCategoriesQuery } from './list-news-categories-query'; + +export async function validate(query: ListNewsCategoriesQuery) { + try { + const schema: z.ZodType = z.object({ + language: z.string(), + }); + + await schema.parseAsync(query); + } catch (error) { + throw new ValidationException(error as ZodError); + } +} diff --git a/src/application/news-categories/queries/list-news-categories/list-news-categories-query.ts b/src/application/news-categories/queries/list-news-categories/list-news-categories-query.ts new file mode 100644 index 0000000..e215a72 --- /dev/null +++ b/src/application/news-categories/queries/list-news-categories/list-news-categories-query.ts @@ -0,0 +1,18 @@ +import { map } from "./list-news-categories-query-mapper"; +import { validate } from "./list-news-categories-query-validator"; + +export type ListNewsCategoriesQuery = Readonly<{ + language: string; +}>; + +export function makeListNewsCategoriesQuery({ documentTypesRepository }: Pick) { + return async function listNewsCategoriesQuery(query: ListNewsCategoriesQuery) { + await validate(query); + + const { language } = query; + + const newsCategories = await documentTypesRepository.list({ language }); + + return newsCategories.map((newsCategory) => map(newsCategory, language)); + }; +} diff --git a/src/application/news/index.ts b/src/application/news/index.ts new file mode 100644 index 0000000..ab19aaf --- /dev/null +++ b/src/application/news/index.ts @@ -0,0 +1,13 @@ +import { makeGetByCategoryQuery } from "./queries/get-by-category"; +import { makeGetBySlugQuery } from "./queries/get-by-slug"; +import { makeGetRelatedQuery } from "./queries/get-related"; + +export function makeNewsUseCases(dependencies: Dependencies) { + return { + queries: { + getRelated: makeGetRelatedQuery(dependencies), + getByCategory: makeGetByCategoryQuery(dependencies), + getBySlug: makeGetBySlugQuery(dependencies), + }, + }; +} diff --git a/src/application/news/queries/get-by-category/get-by-category-query-mapper.ts b/src/application/news/queries/get-by-category/get-by-category-query-mapper.ts new file mode 100644 index 0000000..12049ac --- /dev/null +++ b/src/application/news/queries/get-by-category/get-by-category-query-mapper.ts @@ -0,0 +1,20 @@ +import { NewsDTO } from "@domain/dtos/news"; +import { NewsEntity } from "@domain/entities"; + +export function map(news: NewsEntity, language: string): NewsDTO { + return { + id: news.id?.toString() || '', + news_category_id: news.news_category_id, + slug: news.slug, + image: news.image || '', + read_time: news.read_time || 1, + title: language === 'vi' ? news.vi_title || '' : news.en_title || '', + description: language === 'vi' ? news.vi_description || '' : news.en_description || '', + order: news.order || null, + status: news.status, + created_at: news.created_at ? news.created_at.toISOString() : null, + updated_at: news.updated_at ? news.updated_at.toISOString() : null, + created_by: news.created_by || null, + updated_by: news.updated_by || null, + }; +} diff --git a/src/application/news/queries/get-by-category/get-by-category-query-validator.ts b/src/application/news/queries/get-by-category/get-by-category-query-validator.ts new file mode 100644 index 0000000..2e28929 --- /dev/null +++ b/src/application/news/queries/get-by-category/get-by-category-query-validator.ts @@ -0,0 +1,19 @@ +import { ValidationException } from '@application/common/exceptions'; +import { ZodError, z } from 'zod'; + +import { GetByCategoryQuery } from './get-by-category-query'; + +export async function validate(query: GetByCategoryQuery) { + try { + const schema: z.ZodType = z.object({ + language: z.string(), + news_category_id: z.number(), + size: z.number().optional(), + page: z.number().optional(), + }); + + await schema.parseAsync(query); + } catch (error) { + throw new ValidationException(error as ZodError); + } +} diff --git a/src/application/news/queries/get-by-category/get-by-category-query.ts b/src/application/news/queries/get-by-category/get-by-category-query.ts new file mode 100644 index 0000000..defec37 --- /dev/null +++ b/src/application/news/queries/get-by-category/get-by-category-query.ts @@ -0,0 +1,31 @@ +import { map } from "./get-by-category-query-mapper"; +import { validate } from "./get-by-category-query-validator"; + +export type GetByCategoryQuery = Readonly<{ + language: string; + news_category_id: number; + size?: number; + page?: number +}>; + +export function makeGetByCategoryQuery({ newsRepository }: Pick) { + return async function getByCategoryQuery(query: GetByCategoryQuery) { + await validate(query); + + const { news_category_id, language, size, page } = query; + + const { data, total } = await newsRepository.getByCategory({ news_category_id, language, size, page }); + + const per_page = size; + const current_page = page; + const last_page = total && per_page ? Math.ceil(total / per_page) : 1; + + return { + data: data.map((lectureItem) => map(lectureItem, language)), + total, + per_page, + current_page, + last_page, + } + }; +} diff --git a/src/application/news/queries/get-by-category/index.ts b/src/application/news/queries/get-by-category/index.ts new file mode 100644 index 0000000..3fb80f2 --- /dev/null +++ b/src/application/news/queries/get-by-category/index.ts @@ -0,0 +1 @@ +export * from './get-by-category-query'; diff --git a/src/application/news/queries/get-by-slug/get-by-slug-query-mapper.ts b/src/application/news/queries/get-by-slug/get-by-slug-query-mapper.ts new file mode 100644 index 0000000..12049ac --- /dev/null +++ b/src/application/news/queries/get-by-slug/get-by-slug-query-mapper.ts @@ -0,0 +1,20 @@ +import { NewsDTO } from "@domain/dtos/news"; +import { NewsEntity } from "@domain/entities"; + +export function map(news: NewsEntity, language: string): NewsDTO { + return { + id: news.id?.toString() || '', + news_category_id: news.news_category_id, + slug: news.slug, + image: news.image || '', + read_time: news.read_time || 1, + title: language === 'vi' ? news.vi_title || '' : news.en_title || '', + description: language === 'vi' ? news.vi_description || '' : news.en_description || '', + order: news.order || null, + status: news.status, + created_at: news.created_at ? news.created_at.toISOString() : null, + updated_at: news.updated_at ? news.updated_at.toISOString() : null, + created_by: news.created_by || null, + updated_by: news.updated_by || null, + }; +} diff --git a/src/application/news/queries/get-by-slug/get-by-slug-query-validator.ts b/src/application/news/queries/get-by-slug/get-by-slug-query-validator.ts new file mode 100644 index 0000000..3672c42 --- /dev/null +++ b/src/application/news/queries/get-by-slug/get-by-slug-query-validator.ts @@ -0,0 +1,17 @@ +import { ValidationException } from '@application/common/exceptions'; +import { ZodError, z } from 'zod'; + +import { GetBySlugQuery } from './get-by-slug-query'; + +export async function validate(query: GetBySlugQuery) { + try { + const schema: z.ZodType = z.object({ + language: z.string(), + slug: z.string() + }); + + await schema.parseAsync(query); + } catch (error) { + throw new ValidationException(error as ZodError); + } +} diff --git a/src/application/news/queries/get-by-slug/get-by-slug-query.ts b/src/application/news/queries/get-by-slug/get-by-slug-query.ts new file mode 100644 index 0000000..c93a86a --- /dev/null +++ b/src/application/news/queries/get-by-slug/get-by-slug-query.ts @@ -0,0 +1,19 @@ +import { map } from "./get-by-slug-query-mapper"; +import { validate } from "./get-by-slug-query-validator"; + +export type GetBySlugQuery = Readonly<{ + language: string; + slug: string +}>; + +export function makeGetBySlugQuery({ newsRepository }: Pick) { + return async function getBySlugQuery(query: GetBySlugQuery) { + await validate(query); + + const { slug, language } = query; + + const news = await newsRepository.getBySlug({ slug, language }); + + return news ? map(news, language) : null; + }; +} diff --git a/src/application/news/queries/get-by-slug/index.ts b/src/application/news/queries/get-by-slug/index.ts new file mode 100644 index 0000000..401e642 --- /dev/null +++ b/src/application/news/queries/get-by-slug/index.ts @@ -0,0 +1 @@ +export * from './get-by-slug-query'; diff --git a/src/application/news/queries/get-related/get-related-query-mapper.ts b/src/application/news/queries/get-related/get-related-query-mapper.ts new file mode 100644 index 0000000..12049ac --- /dev/null +++ b/src/application/news/queries/get-related/get-related-query-mapper.ts @@ -0,0 +1,20 @@ +import { NewsDTO } from "@domain/dtos/news"; +import { NewsEntity } from "@domain/entities"; + +export function map(news: NewsEntity, language: string): NewsDTO { + return { + id: news.id?.toString() || '', + news_category_id: news.news_category_id, + slug: news.slug, + image: news.image || '', + read_time: news.read_time || 1, + title: language === 'vi' ? news.vi_title || '' : news.en_title || '', + description: language === 'vi' ? news.vi_description || '' : news.en_description || '', + order: news.order || null, + status: news.status, + created_at: news.created_at ? news.created_at.toISOString() : null, + updated_at: news.updated_at ? news.updated_at.toISOString() : null, + created_by: news.created_by || null, + updated_by: news.updated_by || null, + }; +} diff --git a/src/application/news/queries/get-related/get-related-query-validator.ts b/src/application/news/queries/get-related/get-related-query-validator.ts new file mode 100644 index 0000000..f108c10 --- /dev/null +++ b/src/application/news/queries/get-related/get-related-query-validator.ts @@ -0,0 +1,20 @@ +import { ValidationException } from '@application/common/exceptions'; +import { ZodError, z } from 'zod'; + +import { GetRelatedQuery } from './get-related-query'; + +export async function validate(query: GetRelatedQuery) { + try { + const schema: z.ZodType = z.object({ + language: z.string(), + id: z.number(), + news_category_id: z.number(), + size: z.number().optional(), + page: z.number().optional(), + }); + + await schema.parseAsync(query); + } catch (error) { + throw new ValidationException(error as ZodError); + } +} diff --git a/src/application/news/queries/get-related/get-related-query.ts b/src/application/news/queries/get-related/get-related-query.ts new file mode 100644 index 0000000..c868797 --- /dev/null +++ b/src/application/news/queries/get-related/get-related-query.ts @@ -0,0 +1,32 @@ +import { map } from "./get-related-query-mapper"; +import { validate } from "./get-related-query-validator"; + +export type GetRelatedQuery = Readonly<{ + language: string; + id: number; + news_category_id: number; + size?: number; + page?: number +}>; + +export function makeGetRelatedQuery({ newsRepository }: Pick) { + return async function getRelatedQuery(query: GetRelatedQuery) { + await validate(query); + + const { news_category_id, id, language, size, page } = query; + + const { data, total } = await newsRepository.getRelated({ news_category_id, id, language, size, page }); + + const per_page = size; + const current_page = page; + const last_page = total && per_page ? Math.ceil(total / per_page) : 1; + + return { + data: data.map((newsItem) => map(newsItem, language)), + total, + per_page, + current_page, + last_page, + } + }; +} diff --git a/src/application/news/queries/get-related/index.ts b/src/application/news/queries/get-related/index.ts new file mode 100644 index 0000000..fd314ca --- /dev/null +++ b/src/application/news/queries/get-related/index.ts @@ -0,0 +1 @@ +export * from './get-related-query'; diff --git a/src/application/pages/queries/list-pages/list-pages-query-mapper.ts b/src/application/pages/queries/list-pages/list-pages-query-mapper.ts index 7ddc358..cc0cbf9 100644 --- a/src/application/pages/queries/list-pages/list-pages-query-mapper.ts +++ b/src/application/pages/queries/list-pages/list-pages-query-mapper.ts @@ -8,7 +8,7 @@ export function map(page: PageEntity, language: string): PageDTO { url: page.url, order: page.order || null, status: page.status, - created_at: page.created_at ? page.created_at.toISOString() : null, // Chuyển Date sang ISO string + created_at: page.created_at ? page.created_at.toISOString() : null, updated_at: page.updated_at ? page.updated_at.toISOString() : null, created_by: page.created_by || null, updated_by: page.updated_by || null, diff --git a/src/application/sections/index.ts b/src/application/sections/index.ts index b28b0da..848e6f7 100644 --- a/src/application/sections/index.ts +++ b/src/application/sections/index.ts @@ -1,9 +1,11 @@ -import { makeListSectionsQuery } from './queries/list-Sections'; +import { makeSectionGetByPage } from "./queries/get-by-page"; +import { makeSectionGetByUrl } from "./queries/get-by-url"; export function makeSectionsUseCases(dependencies: Dependencies) { return { queries: { - listSections: makeListSectionsQuery(dependencies), + listSectionsByPage: makeSectionGetByPage(dependencies), + listSectionsByPageUrl: makeSectionGetByUrl(dependencies), }, }; } diff --git a/src/application/sections/queries/get-by-page/get-by-page-query-validator.ts b/src/application/sections/queries/get-by-page/get-by-page-query-validator.ts index ddec062..37edb42 100644 --- a/src/application/sections/queries/get-by-page/get-by-page-query-validator.ts +++ b/src/application/sections/queries/get-by-page/get-by-page-query-validator.ts @@ -6,7 +6,8 @@ import { GetByPageQuery } from './get-by-page-query'; export async function validate(query: GetByPageQuery) { try { const schema: z.ZodType = z.object({ - language: z.string() + language: z.string(), + page_id: z.string() }); await schema.parseAsync(query); diff --git a/src/application/sections/queries/get-by-page/get-by-page-query.ts b/src/application/sections/queries/get-by-page/get-by-page-query.ts index 6beef31..2152916 100644 --- a/src/application/sections/queries/get-by-page/get-by-page-query.ts +++ b/src/application/sections/queries/get-by-page/get-by-page-query.ts @@ -3,15 +3,16 @@ import { validate } from "./get-by-page-query-validator"; export type GetByPageQuery = Readonly<{ language: string; + page_id: string; }>; -export function makeSectionGetByQuery({ sectionsRepository }: Pick) { - return async function listPagesQuery(query: GetByPageQuery) { +export function makeSectionGetByPage({ sectionsRepository }: Pick) { + return async function listSectionsByPageQuery(query: GetByPageQuery) { await validate(query); - const { language } = query; + const { language, page_id } = query; - const sections = await sectionsRepository.list({ language }); + const sections = await sectionsRepository.getByPage({ language, page_id }); return sections.map((section) => map(section, language)); }; diff --git a/src/application/sections/queries/get-by-url/get-by-url-query-mapper.ts b/src/application/sections/queries/get-by-url/get-by-url-query-mapper.ts new file mode 100644 index 0000000..c3964cb --- /dev/null +++ b/src/application/sections/queries/get-by-url/get-by-url-query-mapper.ts @@ -0,0 +1,17 @@ +import { SectionDTO } from "@domain/dtos/section"; +import { SectionEntity } from "@domain/entities"; + +export function map(section: SectionEntity, language: string): SectionDTO { + return { + id: section.id?.toString() || '', + image: section.image || '', + name: language === 'vi' ? section.vi_name : section.en_name, + description: language === 'vi' ? section?.vi_description || '' : section?.en_description || '', + order: section.order || null, + status: section.status, + created_at: section.created_at ? section.created_at.toISOString() : null, + updated_at: section.updated_at ? section.updated_at.toISOString() : null, + created_by: section.created_by || null, + updated_by: section.updated_by || null, + }; +} diff --git a/src/application/sections/queries/get-by-url/get-by-url-query-validator.ts b/src/application/sections/queries/get-by-url/get-by-url-query-validator.ts new file mode 100644 index 0000000..d591ed7 --- /dev/null +++ b/src/application/sections/queries/get-by-url/get-by-url-query-validator.ts @@ -0,0 +1,17 @@ +import { ValidationException } from '@application/common/exceptions'; +import { ZodError, z } from 'zod'; + +import { GetByUrlQuery } from './get-by-url-query'; + +export async function validate(query: GetByUrlQuery) { + try { + const schema: z.ZodType = z.object({ + language: z.string(), + url: z.string() + }); + + await schema.parseAsync(query); + } catch (error) { + throw new ValidationException(error as ZodError); + } +} diff --git a/src/application/sections/queries/get-by-url/get-by-url-query.ts b/src/application/sections/queries/get-by-url/get-by-url-query.ts new file mode 100644 index 0000000..8af8a13 --- /dev/null +++ b/src/application/sections/queries/get-by-url/get-by-url-query.ts @@ -0,0 +1,19 @@ +import { map } from "./get-by-url-query-mapper"; +import { validate } from "./get-by-url-query-validator"; + +export type GetByUrlQuery = Readonly<{ + language: string; + url: string; +}>; + +export function makeSectionGetByUrl({ sectionsRepository }: Pick) { + return async function listSectionsByUrlQuery(query: GetByUrlQuery) { + await validate(query); + + const { language, url } = query; + + const sections = await sectionsRepository.getByPageUrl({ language, url }); + + return sections.map((section) => map(section, language)); + }; +} diff --git a/src/application/sections/queries/get-by-url/index.ts b/src/application/sections/queries/get-by-url/index.ts new file mode 100644 index 0000000..c54ee45 --- /dev/null +++ b/src/application/sections/queries/get-by-url/index.ts @@ -0,0 +1 @@ +export * from './get-by-url-query'; diff --git a/src/domain/dtos/class.ts b/src/domain/dtos/class.ts new file mode 100644 index 0000000..d4d7310 --- /dev/null +++ b/src/domain/dtos/class.ts @@ -0,0 +1,13 @@ +export interface ClassDTO { + id: string; + title: string; + description: string; + content: string; + image: string | null; + order: number | null; + status: number; + created_at: string | null; + updated_at: string | null; + created_by: string | null; + updated_by: string | null; +} diff --git a/src/domain/dtos/component.ts b/src/domain/dtos/component.ts new file mode 100644 index 0000000..88dad77 --- /dev/null +++ b/src/domain/dtos/component.ts @@ -0,0 +1,18 @@ +export interface ComponentDTO { + id: string; + title: string | null; + content: string | null; + image: string | null; + image_2: string | null; + image_3: string | null; + image_4: string | null; + image_5: string | null; + image_6: string | null; + image_7: string | null; + order: number | null; + status: number; + created_at: string | null; + updated_at: string | null; + created_by: string | null; + updated_by: string | null; +} diff --git a/src/domain/dtos/document-type.ts b/src/domain/dtos/document-type.ts new file mode 100644 index 0000000..7900bad --- /dev/null +++ b/src/domain/dtos/document-type.ts @@ -0,0 +1,11 @@ +export interface DocumentTypeDTO { + id: string; + name: string | null; + description: string | null; + order: number | null; + status: number; + created_at: string | null; + updated_at: string | null; + created_by: string | null; + updated_by: string | null; +} diff --git a/src/domain/dtos/document.ts b/src/domain/dtos/document.ts new file mode 100644 index 0000000..f24bc7f --- /dev/null +++ b/src/domain/dtos/document.ts @@ -0,0 +1,16 @@ +export interface DocumentDTO { + id: number; + document_type_id: number; + link_file: string; + downloaded: number; + image: string; + order: number | null; + status: number; + title: string; + description: string; + content: string; + created_at: string | null; + updated_at: string | null; + created_by: string | null; + updated_by: string | null; +} diff --git a/src/domain/dtos/feedback.ts b/src/domain/dtos/feedback.ts new file mode 100644 index 0000000..5efdfd5 --- /dev/null +++ b/src/domain/dtos/feedback.ts @@ -0,0 +1,19 @@ +export interface FeedbackDTO { + id: string; + name: string | null; + address: string | null; + content: string | null; + avatar: string | null; + image: string | null; + image_2: string | null; + image_3: string | null; + image_4: string | null; + image_5: string | null; + image_6: string | null; + order: number | null; + status: number; + created_at: string | null; + updated_at: string | null; + created_by: string | null; + updated_by: string | null; +} diff --git a/src/domain/dtos/lecture-type.ts b/src/domain/dtos/lecture-type.ts new file mode 100644 index 0000000..7e2df39 --- /dev/null +++ b/src/domain/dtos/lecture-type.ts @@ -0,0 +1,11 @@ +export interface LectureTypeDTO { + id: string; + name: string | null; + description: string | null; + order: number | null; + status: number; + created_at: string | null; + updated_at: string | null; + created_by: string | null; + updated_by: string | null; +} diff --git a/src/domain/dtos/lecture.ts b/src/domain/dtos/lecture.ts new file mode 100644 index 0000000..3e1fe76 --- /dev/null +++ b/src/domain/dtos/lecture.ts @@ -0,0 +1,16 @@ +export interface LectureDTO { + id: string; + lecture_type_id: number; + associcate_link: string | null; + viewer: number; + image: string; + title: string | null; + description: string | null; + content: string | null; + order: number | null; + status: number; + created_at: string | null; + updated_at: string | null; + created_by: string | null; + updated_by: string | null; +} diff --git a/src/domain/dtos/lecturer.ts b/src/domain/dtos/lecturer.ts new file mode 100644 index 0000000..094b4d8 --- /dev/null +++ b/src/domain/dtos/lecturer.ts @@ -0,0 +1,13 @@ +export interface LecturerDTO { + id: string; + name: string; + avatar: string; + title: string | null; + content: string | null; + order: number | null; + status: number; + created_at: string | null; + updated_at: string | null; + created_by: string | null; + updated_by: string | null; +} diff --git a/src/domain/dtos/news-category.ts b/src/domain/dtos/news-category.ts new file mode 100644 index 0000000..901253e --- /dev/null +++ b/src/domain/dtos/news-category.ts @@ -0,0 +1,11 @@ +export interface NewsCategoryDTO { + id: string; + name: string; + description: string | null; + order: number | null; + status: number; + created_at: string | null; + updated_at: string | null; + created_by: string | null; + updated_by: string | null; +} diff --git a/src/domain/dtos/news.ts b/src/domain/dtos/news.ts new file mode 100644 index 0000000..52412de --- /dev/null +++ b/src/domain/dtos/news.ts @@ -0,0 +1,15 @@ +export interface NewsDTO { + id: string; + news_category_id: number; + slug: string; + read_time: number; + image: string; + title: string | null; + description: string | null; + order: number | null; + status: number; + created_at: string | null; + updated_at: string | null; + created_by: string | null; + updated_by: string | null; +} diff --git a/src/domain/entities/class.ts b/src/domain/entities/class.ts index 147e132..374aaed 100644 --- a/src/domain/entities/class.ts +++ b/src/domain/entities/class.ts @@ -1,48 +1,48 @@ -export class Class { +export class ClassEntity { public id?: number; - public viName: string; - public enName: string; - public viDescription?: string; - public enDescription?: string; - public viContent?: string; - public enContent?: string; - public image?: string; - public order?: number; + public vi_name: string; + public en_name: string; + public vi_description?: string | null; + public en_description?: string | null; + public vi_content?: string | null; + public en_content?: string | null; + public image?: string | null; + public order?: number | null; public status: number; - public createdAt?: Date; - public updatedAt?: Date; - public createdBy?: string; - public updatedBy?: string; + public created_at?: Date | null; + public updated_at?: Date | null; + public created_by?: string | null; + public updated_by?: string | null; constructor(classEntity: { id?: number; - viName: string; - enName: string; - viDescription?: string; - enDescription?: string; - viContent?: string; - enContent?: string; + vi_name: string; + en_name: string; + vi_description?: string; + en_description?: string; + vi_content?: string; + en_content?: string; image?: string; order?: number; status: number; - createdAt?: Date; - updatedAt?: Date; - createdBy?: string; - updatedBy?: string; + created_at?: Date; + updated_at?: Date; + created_by?: string; + updated_by?: string; }) { this.id = classEntity.id; - this.viName = classEntity.viName; - this.enName = classEntity.enName; - this.viDescription = classEntity.viDescription; - this.enDescription = classEntity.enDescription; - this.viContent = classEntity.viContent; - this.enContent = classEntity.enContent; + this.vi_name = classEntity.vi_name; + this.en_name = classEntity.en_name; + this.vi_description = classEntity.vi_description; + this.en_description = classEntity.en_description; + this.vi_content = classEntity.vi_content; + this.en_content = classEntity.en_content; this.image = classEntity.image; this.order = classEntity.order; this.status = classEntity.status; - this.createdAt = classEntity.createdAt; - this.updatedAt = classEntity.updatedAt; - this.createdBy = classEntity.createdBy; - this.updatedBy = classEntity.updatedBy; + this.created_at = classEntity.created_at; + this.updated_at = classEntity.updated_at; + this.created_by = classEntity.created_by; + this.updated_by = classEntity.updated_by; } } diff --git a/src/domain/entities/component.ts b/src/domain/entities/component.ts index dfdba6c..0d114f8 100644 --- a/src/domain/entities/component.ts +++ b/src/domain/entities/component.ts @@ -1,63 +1,63 @@ -export class Component { +export class ComponentEntity { public id?: number; - public sectionId: number; - public viTitle: string; - public enTitle: string; - public viContent?: string; - public enContent?: string; - public image?: string; - public image2?: string; - public image3?: string; - public image4?: string; - public image5?: string; - public image6?: string; - public image7?: string; - public order?: number; + public section_id: number; + public vi_title: string; + public en_title: string; + public vi_content?: string | null; + public en_content?: string | null; + public image?: string | null; + public image_2?: string | null; + public image_3?: string | null; + public image_4?: string | null; + public image_5?: string | null; + public image_6?: string | null; + public image_7?: string | null; + public order?: number | null; public status: number; - public createdAt?: Date; - public updatedAt?: Date; - public createdBy?: string; - public updatedBy?: string; + public created_at?: Date | null; + public updated_at?: Date | null; + public created_by?: string | null; + public updated_by?: string | null; - constructor(component: { + constructor(componentEntity: { id?: number; - sectionId: number; - viTitle: string; - enTitle: string; - viContent?: string; - enContent?: string; + section_id: number; + vi_title: string; + en_title: string; + vi_content?: string; + en_content?: string; image?: string; - image2?: string; - image3?: string; - image4?: string; - image5?: string; - image6?: string; - image7?: string; + image_2?: string; + image_3?: string; + image_4?: string; + image_5?: string; + image_6?: string; + image_7?: string; order?: number; status: number; - createdAt?: Date; - updatedAt?: Date; - createdBy?: string; - updatedBy?: string; + created_at?: Date; + updated_at?: Date; + created_by?: string; + updated_by?: string; }) { - this.id = component.id; - this.sectionId = component.sectionId; - this.viTitle = component.viTitle; - this.enTitle = component.enTitle; - this.viContent = component.viContent; - this.enContent = component.enContent; - this.image = component.image; - this.image2 = component.image2; - this.image3 = component.image3; - this.image4 = component.image4; - this.image5 = component.image5; - this.image6 = component.image6; - this.image7 = component.image7; - this.order = component.order; - this.status = component.status; - this.createdAt = component.createdAt; - this.updatedAt = component.updatedAt; - this.createdBy = component.createdBy; - this.updatedBy = component.updatedBy; + this.id = componentEntity.id; + this.section_id = componentEntity.section_id; + this.vi_title = componentEntity.vi_title; + this.en_title = componentEntity.en_title; + this.vi_content = componentEntity.vi_content; + this.en_content = componentEntity.en_content; + this.image = componentEntity.image; + this.image_2 = componentEntity.image_2; + this.image_3 = componentEntity.image_3; + this.image_4 = componentEntity.image_4; + this.image_5 = componentEntity.image_5; + this.image_6 = componentEntity.image_6; + this.image_7 = componentEntity.image_7; + this.order = componentEntity.order; + this.status = componentEntity.status; + this.created_at = componentEntity.created_at; + this.updated_at = componentEntity.updated_at; + this.created_by = componentEntity.created_by; + this.updated_by = componentEntity.updated_by; } } diff --git a/src/domain/entities/document-type.ts b/src/domain/entities/document-type.ts index 15d4633..58b5153 100644 --- a/src/domain/entities/document-type.ts +++ b/src/domain/entities/document-type.ts @@ -1,39 +1,39 @@ -export class DocumentType { +export class DocumentTypeEntity { public id?: number; - public viName: string; - public enName: string; - public viDescription?: string; - public enDescription?: string; - public order?: number; + public vi_name: string; + public en_name: string; + public vi_description?: string | null; + public en_description?: string | null; + public order?: number | null; public status: number; - public createdAt?: Date; - public updatedAt?: Date; - public createdBy?: string; - public updatedBy?: string; + public created_at?: Date | null; + public updated_at?: Date | null; + public created_by?: string | null; + public updated_by?: string | null; - constructor(documentType: { + constructor(documentTypeEntity: { id?: number; - viName: string; - enName: string; - viDescription?: string; - enDescription?: string; + vi_name: string; + en_name: string; + vi_description?: string; + en_description?: string; order?: number; status: number; - createdAt?: Date; - updatedAt?: Date; - createdBy?: string; - updatedBy?: string; + created_at?: Date; + updated_at?: Date; + created_by?: string; + updated_by?: string; }) { - this.id = documentType.id; - this.viName = documentType.viName; - this.enName = documentType.enName; - this.viDescription = documentType.viDescription; - this.enDescription = documentType.enDescription; - this.order = documentType.order; - this.status = documentType.status; - this.createdAt = documentType.createdAt; - this.updatedAt = documentType.updatedAt; - this.createdBy = documentType.createdBy; - this.updatedBy = documentType.updatedBy; + this.id = documentTypeEntity.id; + this.vi_name = documentTypeEntity.vi_name; + this.en_name = documentTypeEntity.en_name; + this.vi_description = documentTypeEntity.vi_description; + this.en_description = documentTypeEntity.en_description; + this.order = documentTypeEntity.order; + this.status = documentTypeEntity.status; + this.created_at = documentTypeEntity.created_at; + this.updated_at = documentTypeEntity.updated_at; + this.created_by = documentTypeEntity.created_by; + this.updated_by = documentTypeEntity.updated_by; } } diff --git a/src/domain/entities/document.ts b/src/domain/entities/document.ts index 1c94410..acec25b 100644 --- a/src/domain/entities/document.ts +++ b/src/domain/entities/document.ts @@ -1,60 +1,60 @@ -export class Document { +export class DocumentEntity { public id?: number; - public documentTypeId: number; - public viTitle: string; - public enTitle: string; - public viDescription?: string; - public enDescription?: string; - public viContent: string; - public enContent: string; - public linkFile?: string; + public document_type_id: number; + public vi_title: string; + public en_title: string; + public vi_description?: string | null; + public en_description?: string | null; + public vi_content: string; + public en_content: string; + public link_file?: string | null; public downloaded: number; - public image?: string; - public order?: number; + public image?: string | null; + public order?: number | null; public status: number; - public createdAt?: Date; - public updatedAt?: Date; - public createdBy?: string; - public updatedBy?: string; - public documentLink?: string; + public created_at?: Date | null; + public updated_at?: Date | null; + public created_by?: string | null; + public updated_by?: string | null; + public document_link?: string | null; - constructor(data: { + constructor(documentEntity: { id?: number; - documentTypeId: number; - viTitle: string; - enTitle: string; - viDescription?: string; - enDescription?: string; - viContent: string; - enContent: string; - linkFile?: string; + document_type_id: number; + vi_title: string; + en_title: string; + vi_description?: string; + en_description?: string; + vi_content: string; + en_content: string; + link_file?: string; downloaded: number; image?: string; order?: number; status: number; - createdAt?: Date; - updatedAt?: Date; - createdBy?: string; - updatedBy?: string; - documentLink?: string; + created_at?: Date; + updated_at?: Date; + created_by?: string; + updated_by?: string; + document_link?: string; }) { - this.id = data.id; - this.documentTypeId = data.documentTypeId; - this.viTitle = data.viTitle; - this.enTitle = data.enTitle; - this.viDescription = data.viDescription; - this.enDescription = data.enDescription; - this.viContent = data.viContent; - this.enContent = data.enContent; - this.linkFile = data.linkFile; - this.downloaded = data.downloaded; - this.image = data.image; - this.order = data.order; - this.status = data.status; - this.createdAt = data.createdAt; - this.updatedAt = data.updatedAt; - this.createdBy = data.createdBy; - this.updatedBy = data.updatedBy; - this.documentLink = data.documentLink; + this.id = documentEntity.id; + this.document_type_id = documentEntity.document_type_id; + this.vi_title = documentEntity.vi_title; + this.en_title = documentEntity.en_title; + this.vi_description = documentEntity.vi_description; + this.en_description = documentEntity.en_description; + this.vi_content = documentEntity.vi_content; + this.en_content = documentEntity.en_content; + this.link_file = documentEntity.link_file; + this.downloaded = documentEntity.downloaded; + this.image = documentEntity.image; + this.order = documentEntity.order; + this.status = documentEntity.status; + this.created_at = documentEntity.created_at; + this.updated_at = documentEntity.updated_at; + this.created_by = documentEntity.created_by; + this.updated_by = documentEntity.updated_by; + this.document_link = documentEntity.document_link; } } diff --git a/src/domain/entities/feedback.ts b/src/domain/entities/feedback.ts index 91927d5..efabd93 100644 --- a/src/domain/entities/feedback.ts +++ b/src/domain/entities/feedback.ts @@ -1,60 +1,60 @@ -export class Feedback { +export class FeedbackEntity { public id?: number; - public name?: string; - public address?: string; - public avatar?: string; - public viContent?: string; - public enContent?: string; - public image?: string; - public image2?: string; - public image3?: string; - public image4?: string; - public image5?: string; - public image6?: string; - public order?: number; + public name?: string | null; + public address?: string | null; + public avatar?: string | null; + public vi_content?: string | null; + public en_content?: string | null; + public image?: string | null; + public image_2?: string | null; + public image_3?: string | null; + public image_4?: string | null; + public image_5?: string | null; + public image_6?: string | null; + public order?: number | null; public status: number; - public createdAt?: Date; - public updatedAt?: Date; - public createdBy?: string; - public updatedBy?: string; + public created_at?: Date | null; + public updated_at?: Date | null; + public created_by?: string | null; + public updated_by?: string | null; - constructor(feedback: { + constructor(feedbackEntity: { id?: number; name?: string; address?: string; avatar?: string; - viContent?: string; - enContent?: string; + vi_content?: string; + en_content?: string; image?: string; - image2?: string; - image3?: string; - image4?: string; - image5?: string; - image6?: string; + image_2?: string; + image_3?: string; + image_4?: string; + image_5?: string; + image_6?: string; order?: number; status: number; - createdAt?: Date; - updatedAt?: Date; - createdBy?: string; - updatedBy?: string; + created_at?: Date; + updated_at?: Date; + created_by?: string; + updated_by?: string; }) { - this.id = feedback.id; - this.name = feedback.name; - this.address = feedback.address; - this.avatar = feedback.avatar; - this.viContent = feedback.viContent; - this.enContent = feedback.enContent; - this.image = feedback.image; - this.image2 = feedback.image2; - this.image3 = feedback.image3; - this.image4 = feedback.image4; - this.image5 = feedback.image5; - this.image6 = feedback.image6; - this.order = feedback.order; - this.status = feedback.status; - this.createdAt = feedback.createdAt; - this.updatedAt = feedback.updatedAt; - this.createdBy = feedback.createdBy; - this.updatedBy = feedback.updatedBy; + this.id = feedbackEntity.id; + this.name = feedbackEntity.name; + this.address = feedbackEntity.address; + this.avatar = feedbackEntity.avatar; + this.vi_content = feedbackEntity.vi_content; + this.en_content = feedbackEntity.en_content; + this.image = feedbackEntity.image; + this.image_2 = feedbackEntity.image_2; + this.image_3 = feedbackEntity.image_3; + this.image_4 = feedbackEntity.image_4; + this.image_5 = feedbackEntity.image_5; + this.image_6 = feedbackEntity.image_6; + this.order = feedbackEntity.order; + this.status = feedbackEntity.status; + this.created_at = feedbackEntity.created_at; + this.updated_at = feedbackEntity.updated_at; + this.created_by = feedbackEntity.created_by; + this.updated_by = feedbackEntity.updated_by; } } diff --git a/src/domain/entities/lecture-type.ts b/src/domain/entities/lecture-type.ts index ba0baeb..6e8d290 100644 --- a/src/domain/entities/lecture-type.ts +++ b/src/domain/entities/lecture-type.ts @@ -1,39 +1,39 @@ -export class LectureType { +export class LectureTypeEntity { public id?: number; - public viName: string; - public enName: string; - public viDescription?: string; - public enDescription?: string; - public order?: number; + public vi_name: string; + public en_name: string; + public vi_description?: string | null; + public en_description?: string | null; + public order?: number | null; public status: number; - public createdAt?: Date; - public updatedAt?: Date; - public createdBy?: string; - public updatedBy?: string; + public created_at?: Date | null; + public updated_at?: Date | null; + public created_by?: string | null; + public updated_by?: string | null; - constructor(lectureType: { + constructor(lectureTypeEntity: { id?: number; - viName: string; - enName: string; - viDescription?: string; - enDescription?: string; + vi_name: string; + en_name: string; + vi_description?: string; + en_description?: string; order?: number; status: number; - createdAt?: Date; - updatedAt?: Date; - createdBy?: string; - updatedBy?: string; + created_at?: Date; + updated_at?: Date; + created_by?: string; + updated_by?: string; }) { - this.id = lectureType.id; - this.viName = lectureType.viName; - this.enName = lectureType.enName; - this.viDescription = lectureType.viDescription; - this.enDescription = lectureType.enDescription; - this.order = lectureType.order; - this.status = lectureType.status; - this.createdAt = lectureType.createdAt; - this.updatedAt = lectureType.updatedAt; - this.createdBy = lectureType.createdBy; - this.updatedBy = lectureType.updatedBy; + this.id = lectureTypeEntity.id; + this.vi_name = lectureTypeEntity.vi_name; + this.en_name = lectureTypeEntity.en_name; + this.vi_description = lectureTypeEntity.vi_description; + this.en_description = lectureTypeEntity.en_description; + this.order = lectureTypeEntity.order; + this.status = lectureTypeEntity.status; + this.created_at = lectureTypeEntity.created_at; + this.updated_at = lectureTypeEntity.updated_at; + this.created_by = lectureTypeEntity.created_by; + this.updated_by = lectureTypeEntity.updated_by; } } diff --git a/src/domain/entities/lecture.ts b/src/domain/entities/lecture.ts index 437d76a..a174bcd 100644 --- a/src/domain/entities/lecture.ts +++ b/src/domain/entities/lecture.ts @@ -1,57 +1,57 @@ -export class Lecture { +export class LectureEntity { public id?: number; - public lectureTypeId: number; - public viTitle: string; - public enTitle: string; - public viDescription?: string; - public enDescription?: string; - public viContent: string; - public enContent: string; - public associcateLink?: string; + public lecture_type_id: number; + public vi_title: string; + public en_title: string; + public vi_description?: string | null; + public en_description?: string | null; + public vi_content: string; + public en_content: string; + public associcate_link?: string | null; public viewer: number; - public image?: string; - public order?: number; + public image?: string | null; + public order?: number | null; public status: number; - public createdAt?: Date; - public updatedAt?: Date; - public createdBy?: string; - public updatedBy?: string; + public created_at?: Date | null; + public updated_at?: Date | null; + public created_by?: string | null; + public updated_by?: string | null; - constructor(lecture: { + constructor(lectureEntity: { id?: number; - lectureTypeId: number; - viTitle: string; - enTitle: string; - viDescription?: string; - enDescription?: string; - viContent: string; - enContent: string; - associcateLink?: string; + lecture_type_id: number; + vi_title: string; + en_title: string; + vi_description?: string; + en_description?: string; + vi_content: string; + en_content: string; + associcate_link?: string; viewer: number; image?: string; order?: number; status: number; - createdAt?: Date; - updatedAt?: Date; - createdBy?: string; - updatedBy?: string; + created_at?: Date; + updated_at?: Date; + created_by?: string; + updated_by?: string; }) { - this.id = lecture.id; - this.lectureTypeId = lecture.lectureTypeId; - this.viTitle = lecture.viTitle; - this.enTitle = lecture.enTitle; - this.viDescription = lecture.viDescription; - this.enDescription = lecture.enDescription; - this.viContent = lecture.viContent; - this.enContent = lecture.enContent; - this.associcateLink = lecture.associcateLink; - this.viewer = lecture.viewer; - this.image = lecture.image; - this.order = lecture.order; - this.status = lecture.status; - this.createdAt = lecture.createdAt; - this.updatedAt = lecture.updatedAt; - this.createdBy = lecture.createdBy; - this.updatedBy = lecture.updatedBy; + this.id = lectureEntity.id; + this.lecture_type_id = lectureEntity.lecture_type_id; + this.vi_title = lectureEntity.vi_title; + this.en_title = lectureEntity.en_title; + this.vi_description = lectureEntity.vi_description; + this.en_description = lectureEntity.en_description; + this.vi_content = lectureEntity.vi_content; + this.en_content = lectureEntity.en_content; + this.associcate_link = lectureEntity.associcate_link; + this.viewer = lectureEntity.viewer; + this.image = lectureEntity.image; + this.order = lectureEntity.order; + this.status = lectureEntity.status; + this.created_at = lectureEntity.created_at; + this.updated_at = lectureEntity.updated_at; + this.created_by = lectureEntity.created_by; + this.updated_by = lectureEntity.updated_by; } } diff --git a/src/domain/entities/lecturer.ts b/src/domain/entities/lecturer.ts index 6c8381e..3d0ccd6 100644 --- a/src/domain/entities/lecturer.ts +++ b/src/domain/entities/lecturer.ts @@ -1,45 +1,45 @@ -export class Lecturer { +export class LecturerEntity { public id?: number; public avatar: string; public name: string; - public viTitle: string; - public enTitle?: string; - public viContent?: string; - public enContent?: string; - public order?: number; + public vi_title?: string | null; + public en_title?: string | null; + public vi_content?: string | null; + public en_content?: string | null; + public order?: number | null; public status: number; - public createdAt?: Date; - public updatedAt?: Date; - public createdBy?: string; - public updatedBy?: string; + public created_at?: Date | null; + public updated_at?: Date | null; + public created_by?: string | null; + public updated_by?: string | null; - constructor(lecturer: { + constructor(lecturerEntity: { id?: number; avatar: string; name: string; - viTitle: string; - enTitle?: string; - viContent?: string; - enContent?: string; + vi_title: string; + en_title?: string; + vi_content?: string; + en_content?: string; order?: number; status: number; - createdAt?: Date; - updatedAt?: Date; - createdBy?: string; - updatedBy?: string; + created_at?: Date; + updated_at?: Date; + created_by?: string; + updated_by?: string; }) { - this.id = lecturer.id; - this.avatar = lecturer.avatar; - this.name = lecturer.name; - this.viTitle = lecturer.viTitle; - this.enTitle = lecturer.enTitle; - this.viContent = lecturer.viContent; - this.enContent = lecturer.enContent; - this.order = lecturer.order; - this.status = lecturer.status; - this.createdAt = lecturer.createdAt; - this.updatedAt = lecturer.updatedAt; - this.createdBy = lecturer.createdBy; - this.updatedBy = lecturer.updatedBy; + this.id = lecturerEntity.id; + this.avatar = lecturerEntity.avatar; + this.name = lecturerEntity.name; + this.vi_title = lecturerEntity.vi_title; + this.en_title = lecturerEntity.en_title; + this.vi_content = lecturerEntity.vi_content; + this.en_content = lecturerEntity.en_content; + this.order = lecturerEntity.order; + this.status = lecturerEntity.status; + this.created_at = lecturerEntity.created_at; + this.updated_at = lecturerEntity.updated_at; + this.created_by = lecturerEntity.created_by; + this.updated_by = lecturerEntity.updated_by; } } diff --git a/src/domain/entities/news-category.ts b/src/domain/entities/news-category.ts index c167a95..7b64bf2 100644 --- a/src/domain/entities/news-category.ts +++ b/src/domain/entities/news-category.ts @@ -1,39 +1,39 @@ -export class NewsCategory { +export class NewsCategoryEntity { public id?: number; - public viName: string; - public enName: string; - public viDescription?: string; - public enDescription?: string; - public order?: number; + public vi_name: string; + public en_name: string; + public vi_description?: string | null; + public en_description?: string | null; + public order?: number | null; public status: number; - public createdAt?: Date; - public updatedAt?: Date; - public createdBy?: string; - public updatedBy?: string; + public created_at?: Date | null; + public updated_at?: Date | null; + public created_by?: string | null; + public updated_by?: string | null; - constructor(newsCategory: { + constructor(newsCategoryEntity: { id?: number; - viName: string; - enName: string; - viDescription?: string; - enDescription?: string; + vi_name: string; + en_name: string; + vi_description?: string; + en_description?: string; order?: number; status: number; - createdAt?: Date; - updatedAt?: Date; - createdBy?: string; - updatedBy?: string; + created_at?: Date; + updated_at?: Date; + created_by?: string; + updated_by?: string; }) { - this.id = newsCategory.id; - this.viName = newsCategory.viName; - this.enName = newsCategory.enName; - this.viDescription = newsCategory.viDescription; - this.enDescription = newsCategory.enDescription; - this.order = newsCategory.order; - this.status = newsCategory.status; - this.createdAt = newsCategory.createdAt; - this.updatedAt = newsCategory.updatedAt; - this.createdBy = newsCategory.createdBy; - this.updatedBy = newsCategory.updatedBy; + this.id = newsCategoryEntity.id; + this.vi_name = newsCategoryEntity.vi_name; + this.en_name = newsCategoryEntity.en_name; + this.vi_description = newsCategoryEntity.vi_description; + this.en_description = newsCategoryEntity.en_description; + this.order = newsCategoryEntity.order; + this.status = newsCategoryEntity.status; + this.created_at = newsCategoryEntity.created_at; + this.updated_at = newsCategoryEntity.updated_at; + this.created_by = newsCategoryEntity.created_by; + this.updated_by = newsCategoryEntity.updated_by; } } diff --git a/src/domain/entities/news.ts b/src/domain/entities/news.ts index 4402ad6..a431fa8 100644 --- a/src/domain/entities/news.ts +++ b/src/domain/entities/news.ts @@ -1,57 +1,57 @@ -export class News { +export class NewsEntity { public id?: number; - public newsCategoryId: number; - public viTitle: string; - public enTitle: string; - public viDescription?: string; - public enDescription?: string; - public viContent: string; - public enContent: string; + public news_category_id: number; + public vi_title: string; + public en_title: string; + public vi_description?: string | null; + public en_description?: string | null; + public vi_content: string; + public en_content: string; public slug: string; - public readTime?: number; - public image?: string; - public order?: number; + public read_time?: number | null; + public image?: string | null; + public order?: number | null; public status: number; - public createdAt?: Date; - public updatedAt?: Date; - public createdBy?: string; - public updatedBy?: string; + public created_at?: Date | null; + public updated_at?: Date | null; + public created_by?: string | null; + public updated_by?: string | null; - constructor(news: { + constructor(newsEntity: { id?: number; - newsCategoryId: number; - viTitle: string; - enTitle: string; - viDescription?: string; - enDescription?: string; - viContent: string; - enContent: string; + news_category_id: number; + vi_title: string; + en_title: string; + vi_description?: string; + en_description?: string; + vi_content: string; + en_content: string; slug: string; - readTime?: number; + read_time?: number; image?: string; order?: number; status: number; - createdAt?: Date; - updatedAt?: Date; - createdBy?: string; - updatedBy?: string; + created_at?: Date; + updated_at?: Date; + created_by?: string; + updated_by?: string; }) { - this.id = news.id; - this.newsCategoryId = news.newsCategoryId; - this.viTitle = news.viTitle; - this.enTitle = news.enTitle; - this.viDescription = news.viDescription; - this.enDescription = news.enDescription; - this.viContent = news.viContent; - this.enContent = news.enContent; - this.slug = news.slug; - this.readTime = news.readTime ?? 0; - this.image = news.image; - this.order = news.order; - this.status = news.status; - this.createdAt = news.createdAt; - this.updatedAt = news.updatedAt; - this.createdBy = news.createdBy; - this.updatedBy = news.updatedBy; + this.id = newsEntity.id; + this.news_category_id = newsEntity.news_category_id; + this.vi_title = newsEntity.vi_title; + this.en_title = newsEntity.en_title; + this.vi_description = newsEntity.vi_description; + this.en_description = newsEntity.en_description; + this.vi_content = newsEntity.vi_content; + this.en_content = newsEntity.en_content; + this.slug = newsEntity.slug; + this.read_time = newsEntity.read_time ?? 0; + this.image = newsEntity.image; + this.order = newsEntity.order; + this.status = newsEntity.status; + this.created_at = newsEntity.created_at; + this.updated_at = newsEntity.updated_at; + this.created_by = newsEntity.created_by; + this.updated_by = newsEntity.updated_by; } } diff --git a/src/infrastructure/di.ts b/src/infrastructure/di.ts index b256cf9..877af8c 100644 --- a/src/infrastructure/di.ts +++ b/src/infrastructure/di.ts @@ -13,6 +13,16 @@ export type Dependencies = { postsRepository: Interfaces.PostsRepository; pagesRepository: Interfaces.PagesRepository; sectionsRepository: Interfaces.SectionsRepository; + componentsRepository: Interfaces.ComponentsRepository; + classesRepository: Interfaces.ClassesRepository; + documentsRepository: Interfaces.DocumentsRepository; + documentTypesRepository: Interfaces.DocumentTypesRepository; + feedbacksRepository: Interfaces.FeedbacksRepository; + lectureTypesRepository: Interfaces.LectureTypesRepository; + lecturesRepository: Interfaces.LecturesRepository; + lecturersRepository: Interfaces.LecturersRepository; + newsCategoriesRepository: Interfaces.NewsCategoriesRepository; + newsRepository: Interfaces.NewsRepository; }; export function makeInfrastructureDependencies(): { @@ -33,6 +43,16 @@ export function makeInfrastructureDependencies(): { logger: asValue(logger), postsRepository: asFunction(repositories.makePostsRepository).singleton(), pagesRepository: asFunction(repositories.makePagesRepository).singleton(), - sectionsRepository: asFunction(repositories.m).singleton(), + sectionsRepository: asFunction(repositories.makeSectionsRepository).singleton(), + componentsRepository: asFunction(repositories.makeComponentsRepository).singleton(), + classesRepository: asFunction(repositories.makeClassesRepository).singleton(), + documentsRepository: asFunction(repositories.makeDocumentsRepository).singleton(), + documentTypesRepository: asFunction(repositories.makeDocumentTypesRepository).singleton(), + feedbacksRepository: asFunction(repositories.makeFeedbacksRepository).singleton(), + lectureTypesRepository: asFunction(repositories.makeLectureTypesRepository).singleton(), + lecturesRepository: asFunction(repositories.makeLecturesRepository).singleton(), + lecturersRepository: asFunction(repositories.makeLecturersRepository).singleton(), + newsCategoriesRepository: asFunction(repositories.makeNewsCategoriesRepository).singleton(), + newsRepository: asFunction(repositories.makeNewsRepository).singleton(), }; } diff --git a/src/infrastructure/repositories/classes-repository.ts b/src/infrastructure/repositories/classes-repository.ts new file mode 100644 index 0000000..0e09fb3 --- /dev/null +++ b/src/infrastructure/repositories/classes-repository.ts @@ -0,0 +1,65 @@ +import { ClassesRepository } from '@application/common/interfaces'; + +export function makeClassesRepository({ db }: Dependencies): ClassesRepository { + return { + async getHighlightClasses(params: { language: string; size?: number; page?: number }) { + const { size = 10, page = 1 } = params; + + const classes = await db.renamedclass.findMany({ + where: { + status: 1, + }, + orderBy: { + order: 'asc', + }, + skip: (page - 1) * size, + take: size, + }); + + const total = await db.renamedclass.count({ + where: { + status: 1, + }, + }); + + return { + data: classes.map((component) => ({ + ...component, + id: Number(component.id), + })), + total, + }; + }, + + async getListShort() { + const classes = await db.renamedclass.findMany({ + where: { + status: 1, + }, + orderBy: { + order: 'asc', + }, + }); + + return classes.map((component) => ({ + ...component, + id: Number(component.id), + })); + }, + + async getById(params: { language: string; id: string }) { + const { id } = params; + const renamedClass = await db.renamedclass.findFirst({ + where: { + id: Number(id), + status: 1 + } + }); + + return renamedClass ? { + ...renamedClass, + id: Number(renamedClass.id) + } : null; + } + } +} diff --git a/src/infrastructure/repositories/components-repository.ts b/src/infrastructure/repositories/components-repository.ts new file mode 100644 index 0000000..a98aefe --- /dev/null +++ b/src/infrastructure/repositories/components-repository.ts @@ -0,0 +1,18 @@ +import { ComponentsRepository } from '@application/common/interfaces'; + +export function makeComponentsRepository({ db }: Dependencies): ComponentsRepository { + return { + async getBySection(params: { language: string, section_id: string }) { + const components = await db.component.findMany({ + where: { status: 1, section_id: Number(params.section_id) }, + orderBy: { order: 'asc' }, + }); + + return components.map((component) => ({ + ...component, + id: Number(component.id), + section_id: Number(component.section_id) + })); + } + } +} diff --git a/src/infrastructure/repositories/document-repository.ts b/src/infrastructure/repositories/document-repository.ts new file mode 100644 index 0000000..75a64cb --- /dev/null +++ b/src/infrastructure/repositories/document-repository.ts @@ -0,0 +1,53 @@ +import { DocumentsRepository } from "@application/common/interfaces"; + +export function makeDocumentsRepository({ db }: Dependencies): DocumentsRepository { + return { + async getByDocumentType(params: { language: string; document_type_id: number; size?: number; page?: number }) { + const { document_type_id, size = 10, page = 1 } = params; + + const documents = await db.document.findMany({ + where: { + status: 1, + document_type_id + }, + orderBy: { + order: 'asc', + }, + skip: (page - 1) * size, + take: size, + }); + + const total = await db.document.count({ + where: { + status: 1, + document_type_id + }, + }); + + return { + data: documents.map((document) => ({ + ...document, + id: Number(document.id), + document_type_id: Number(document.document_type_id) + })), + total, + }; + }, + + async getById(params: { language: string; id: number }) { + const { id } = params; + const documents = await db.document.findFirst({ + where: { + id, + status: 1 + } + }); + + return documents ? { + ...documents, + id: Number(documents.id), + document_type_id: Number(documents.document_type_id) + } : null; + } + } +} diff --git a/src/infrastructure/repositories/document-types-repository.ts b/src/infrastructure/repositories/document-types-repository.ts new file mode 100644 index 0000000..927833e --- /dev/null +++ b/src/infrastructure/repositories/document-types-repository.ts @@ -0,0 +1,18 @@ +import { DocumentTypesRepository } from "@application/common/interfaces"; + +export function makeDocumentTypesRepository({ db }: Dependencies): DocumentTypesRepository { + return { + async list() { + const documentTypes = await db.document_type.findMany({ + where: { status: 1 }, + orderBy: { + order: 'asc', + }, + }); + return documentTypes.map(documentType => ({ + ...documentType, + id: Number(documentType.id), + })); + } + } +} diff --git a/src/infrastructure/repositories/feedback-repository.ts b/src/infrastructure/repositories/feedback-repository.ts new file mode 100644 index 0000000..a39b40c --- /dev/null +++ b/src/infrastructure/repositories/feedback-repository.ts @@ -0,0 +1,34 @@ +import { FeedbacksRepository } from "@application/common/interfaces"; + +export function makeFeedbacksRepository({ db }: Dependencies): FeedbacksRepository { + return { + async list(params: { language: string; size?: number; page?: number }) { + const { size = 10, page = 1 } = params; + + const feedbacks = await db.feedback.findMany({ + where: { + status: 1, + }, + orderBy: { + order: 'asc', + }, + skip: (page - 1) * size, + take: size, + }); + + const total = await db.feedback.count({ + where: { + status: 1, + }, + }); + + return { + data: feedbacks.map((feedback) => ({ + ...feedback, + id: Number(feedback.id), + })), + total, + }; + }, + } +} diff --git a/src/infrastructure/repositories/index.ts b/src/infrastructure/repositories/index.ts index 85da738..0f370fb 100644 --- a/src/infrastructure/repositories/index.ts +++ b/src/infrastructure/repositories/index.ts @@ -1,3 +1,13 @@ export * from './posts-repository'; export * from './pages-repository'; export * from './sections-repository'; +export * from './components-repository'; +export * from './classes-repository'; +export * from './document-repository'; +export * from './document-types-repository'; +export * from './feedback-repository'; +export * from './lecture-repository'; +export * from './lecture-type-repository'; +export * from './lecturer-repository'; +export * from './news-categories-repository'; +export * from './news-repository'; diff --git a/src/infrastructure/repositories/lecture-repository.ts b/src/infrastructure/repositories/lecture-repository.ts new file mode 100644 index 0000000..aa49938 --- /dev/null +++ b/src/infrastructure/repositories/lecture-repository.ts @@ -0,0 +1,52 @@ +import { LecturesRepository } from "@application/common/interfaces"; + +export function makeLecturesRepository({ db }: Dependencies): LecturesRepository { + return { + async getByLectureType(params: { language: string; lecture_type_id: number; size?: number; page?: number }) { + const { lecture_type_id, size = 10, page = 1 } = params; + + const lectures = await db.lecture.findMany({ + where: { + status: 1, + lecture_type_id + }, + orderBy: { + order: 'asc', + }, + skip: (page - 1) * size, + take: size, + }); + + const total = await db.lecture.count({ + where: { + status: 1, + }, + }); + + return { + data: lectures.map((lecture) => ({ + ...lecture, + id: Number(lecture.id), + lecture_type_id: Number(lecture.lecture_type_id) + })), + total, + }; + }, + + async getById(params: { language: string; id: number }) { + const { id } = params; + const lectures = await db.lecture.findFirst({ + where: { + id, + status: 1 + } + }); + + return lectures ? { + ...lectures, + id: Number(lectures.id), + lecture_type_id: Number(lectures.lecture_type_id) + } : null; + } + } +} diff --git a/src/infrastructure/repositories/lecture-type-repository.ts b/src/infrastructure/repositories/lecture-type-repository.ts new file mode 100644 index 0000000..9bc635e --- /dev/null +++ b/src/infrastructure/repositories/lecture-type-repository.ts @@ -0,0 +1,18 @@ +import { LectureTypesRepository } from "@application/common/interfaces"; + +export function makeLectureTypesRepository({ db }: Dependencies): LectureTypesRepository { + return { + async list() { + const lectureTypes = await db.lecture_type.findMany({ + where: { status: 1 }, + orderBy: { + order: 'asc', + }, + }); + return lectureTypes.map((lectureType) => ({ + ...lectureType, + id: Number(lectureType.id), + })); + } + } +} diff --git a/src/infrastructure/repositories/lecturer-repository.ts b/src/infrastructure/repositories/lecturer-repository.ts new file mode 100644 index 0000000..ade279e --- /dev/null +++ b/src/infrastructure/repositories/lecturer-repository.ts @@ -0,0 +1,34 @@ +import { LecturersRepository } from "@application/common/interfaces"; + +export function makeLecturersRepository({ db }: Dependencies): LecturersRepository { + return { + async list(params: { language: string; size?: number; page?: number }) { + const { size = 10, page = 1 } = params; + + const lecturers = await db.lecturer.findMany({ + where: { + status: 1, + }, + orderBy: { + order: 'asc', + }, + skip: (page - 1) * size, + take: size, + }); + + const total = await db.lecturer.count({ + where: { + status: 1, + }, + }); + + return { + data: lecturers.map((lecturer) => ({ + ...lecturer, + id: Number(lecturer.id), + })), + total, + }; + }, + } +} diff --git a/src/infrastructure/repositories/news-categories-repository.ts b/src/infrastructure/repositories/news-categories-repository.ts new file mode 100644 index 0000000..d04b5b7 --- /dev/null +++ b/src/infrastructure/repositories/news-categories-repository.ts @@ -0,0 +1,18 @@ +import { NewsCategoriesRepository } from "@application/common/interfaces"; + +export function makeNewsCategoriesRepository({ db }: Dependencies): NewsCategoriesRepository { + return { + async list() { + const newsCategories = await db.news_category.findMany({ + where: { status: 1 }, + orderBy: { + order: 'asc', + }, + }); + return newsCategories.map((newsCategory) => ({ + ...newsCategory, + id: Number(newsCategory.id) + })) + } + } +} diff --git a/src/infrastructure/repositories/news-repository.ts b/src/infrastructure/repositories/news-repository.ts new file mode 100644 index 0000000..306771c --- /dev/null +++ b/src/infrastructure/repositories/news-repository.ts @@ -0,0 +1,85 @@ +import { NewsRepository } from "@application/common/interfaces"; + +export function makeNewsRepository({ db }: Dependencies): NewsRepository { + return { + async getRelated(params: { language: string; news_category_id: number; id: number, size?: number; page?: number }) { + const { id, news_category_id, size = 10, page = 1 } = params; + + const news = await db.news.findMany({ + where: { + NOT: { id }, + status: 1, + news_category_id, + }, + orderBy: { + order: 'asc', + }, + skip: (page - 1) * size, + take: size, + }); + + const total = await db.news.count({ + where: { + status: 1, + }, + }); + + return { + data: news.map((newsItem) => ({ + ...newsItem, + id: Number(newsItem.id), + news_category_id: Number(newsItem.news_category_id), + })), + total, + }; + }, + + async getByCategory(params: { language: string; news_category_id: number; size?: number; page?: number }) { + const { news_category_id, size = 10, page = 1 } = params; + + const news = await db.news.findMany({ + where: { + status: 1, + news_category_id + }, + orderBy: { + order: 'asc', + }, + skip: (page - 1) * size, + take: size, + }); + + const total = await db.news.count({ + where: { + status: 1, + }, + }); + + return { + data: news.map((newsItem) => ({ + ...newsItem, + id: Number(newsItem.id), + news_category_id: Number(newsItem.news_category_id), + })), + total, + }; + }, + + async getBySlug(params: { language: string; slug: string }) { + const { slug } = params; + + const news = await db.news.findFirst({ + where: { + slug, + status: 1 + } + }); + + return news ? { + ...news, + id: Number(news.id), + news_category_id: Number(news.news_category_id), + } : null; + } + } +} diff --git a/src/infrastructure/repositories/sections-repository.ts b/src/infrastructure/repositories/sections-repository.ts index 778db92..668d8eb 100644 --- a/src/infrastructure/repositories/sections-repository.ts +++ b/src/infrastructure/repositories/sections-repository.ts @@ -2,43 +2,42 @@ import { SectionsRepository } from "@application/common/interfaces"; export function makeSectionsRepository({ db }: Dependencies): SectionsRepository { return { - async getByPage(params: { language: string, url: string }) { - if (params.language == "vi") { - const pages = await db.section.findFirst({ - where: { vi_name: params.language, status: 1, url: params.url, }, - orderBy: { - order: 'asc', - }, - }); - return pages - } else { - const pages = await db.page.findFirst({ - where: { en_name: params.language, status: 1, url: params.url }, - orderBy: { - order: 'asc', - }, - }); - return pages - } + async getByPage(params: { language: string; page_id: string }) { + const sections = await db.section.findMany({ + where: { + status: 1, + page_id: Number(params.page_id), + }, + orderBy: { order: "asc" }, + }); + + return sections.map((section) => ({ + ...section, + id: Number(section.id), + pageId: Number(section.page_id), + })); + }, + + async getByPageUrl(params: { language: string; url: string }) { + const page = await db.page.findFirst({ + where: { status: 1, url: params.url }, + }); + + if (!page) return []; + + const sections = await db.section.findMany({ + where: { + status: 1, + page_id: page.id, + }, + orderBy: { order: "asc" }, + }); + + return sections.map((section) => ({ + ...section, + id: Number(section.id), + pageId: Number(section.page_id), + })); }, - async getByPageUrl(params: { language: string }) { - if (params.language == "vi") { - const pages = await db.section.findMany({ - where: { status: 1 }, - orderBy: { - order: 'asc', - }, - }); - return pages - } else { - const pages = await db.page.findMany({ - where: { status: 1 }, - orderBy: { - order: 'asc', - }, - }); - return pages - } - } - } + }; } diff --git a/src/web/routes/classes.ts b/src/web/routes/classes.ts new file mode 100644 index 0000000..40d1dd0 --- /dev/null +++ b/src/web/routes/classes.ts @@ -0,0 +1,246 @@ +import { FastifyRequest } from 'fastify'; + +import { makeClassessUseCases } from '@application/classes'; +import ResponseBase from '@application/common/response-base'; + +interface ListHightlightClassesQuery { + language: string + size?: number + page?: number +} + +interface ListShortClassesQuery { + language: string +} + +interface GetClassByIdQuery { + language: string + id: number +} + +export default async function classRoutes(fastify: FastifyRouteInstance) { + const classes = makeClassessUseCases(fastify.diContainer.cradle); + + fastify.route({ + method: 'POST', + url: '/api/class/high-light', + schema: { + body: { + type: 'object', + properties: { + language: { type: 'string', description: 'Language code (e.g., vi, en, etc.)' }, + size: { type: 'number', description: 'Size number of records (e.g., 10.)' }, + page: { type: 'number', description: 'Page number of database (e.g., 1.)' } + }, + required: ['language', 'size', 'page'], + }, + response: { + 200: { + type: 'object', + properties: { + status_code: { type: 'integer', example: 200 }, + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { type: 'integer' }, + title: { type: 'string' }, + content: { type: 'string' }, + description: { type: 'string' }, + image: { type: 'string' }, + order: { type: 'integer' }, + status: { type: 'integer' }, + created_at: { type: 'string', format: 'date-time' }, + updated_at: { type: 'string', format: 'date-time' }, + created_by: { type: 'string' }, + updated_by: { type: 'string' }, + }, + }, + }, + total: { type: 'integer', }, + per_page: { type: 'integer', }, + current_page: { type: 'integer', }, + last_page: { type: 'integer', }, + message: { type: 'string', example: 'Classes fetched successfully' }, + }, + }, + 400: { $ref: 'ExceptionResponse#' }, + }, + tags: ['classes'], + }, + async handler( + req: FastifyRequest<{ Body: ListHightlightClassesQuery }>, + res + ) { + try { + const { data, total, per_page, current_page, last_page } = await classes.queries.listHightlightClasses({ + language: req.body.language, + size: req.body.size, + page: req.body.page, + }); + + const response = ResponseBase.formatPaginationResponse( + 200, + data, + total ?? 0, + per_page ?? 0, + current_page ?? 0, + last_page ?? 0, + 'Classes fetched successfully', + ); + + res.status(200).send(response); + } catch (error) { + fastify.log.error(error); + + const errorResponse = ResponseBase.formatPaginationResponse( + 400, + null, + 0, + 0, + 0, + 0, + 'Failed to fetch classes', + ); + + res.status(400).send(errorResponse); + } + }, + }); + + fastify.route({ + method: 'POST', + url: '/api/class/get-by-id', + schema: { + body: { + type: 'object', + properties: { + language: { type: 'string', description: 'Language code (e.g., vi, en, etc.)' }, + id: { type: 'number', description: 'Id number of class (e.g., 1.)' }, + }, + required: ['language', 'id'], + }, + response: { + 200: { + type: 'object', + properties: { + status_code: { type: 'integer', example: 200 }, + data: { + type: 'object', + properties: { + id: { type: 'integer' }, + title: { type: 'string' }, + content: { type: 'string' }, + description: { type: 'string' }, + image: { type: 'string' }, + order: { type: 'integer' }, + status: { type: 'integer' }, + created_at: { type: 'string', format: 'date-time' }, + updated_at: { type: 'string', format: 'date-time' }, + created_by: { type: 'string' }, + updated_by: { type: 'string' }, + }, + }, + message: { type: 'string', example: 'Class fetched successfully' }, + }, + }, + 400: { $ref: 'ExceptionResponse#' }, + }, + tags: ['classes'], + }, + async handler( + req: FastifyRequest<{ Body: GetClassByIdQuery }>, + res + ) { + try { + const data = await classes.queries.getClassById({ + language: req.body.language, + id: String(req.body.id), + }); + + const response = ResponseBase.formatBaseResponse( + 200, + data, + 'Class fetched successfully', + ); + + res.status(200).send(response); + } catch (error) { + fastify.log.error(error); + + const errorResponse = ResponseBase.formatBaseResponse( + 400, + null, + 'Failed to fetch classes', + ); + + res.status(400).send(errorResponse); + } + }, + }); + + fastify.route({ + method: 'POST', + url: '/api/class/all-short', + schema: { + body: { + type: 'object', + properties: { + language: { type: 'string', description: 'Language code (e.g., vi, en, etc.)' }, + }, + required: ['language'], + }, + response: { + 200: { + type: 'object', + properties: { + status_code: { type: 'integer', example: 200 }, + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { type: 'integer' }, + title: { type: 'string' }, + order: { type: 'integer' }, + }, + }, + }, + message: { type: 'string', example: 'Class fetched successfully' }, + }, + }, + 400: { $ref: 'ExceptionResponse#' }, + }, + tags: ['classes'], + }, + async handler( + req: FastifyRequest<{ Body: ListShortClassesQuery }>, + res + ) { + try { + const data = await classes.queries.listShortClasses({ + language: req.body.language, + }); + + const response = ResponseBase.formatBaseResponse( + 200, + data, + 'Class fetched successfully', + ); + + res.status(200).send(response); + } catch (error) { + fastify.log.error(error); + + const errorResponse = ResponseBase.formatBaseResponse( + 400, + null, + 'Failed to fetch classes', + ); + + res.status(400).send(errorResponse); + } + }, + }); +} diff --git a/src/web/routes/components.ts b/src/web/routes/components.ts new file mode 100644 index 0000000..baff7ec --- /dev/null +++ b/src/web/routes/components.ts @@ -0,0 +1,92 @@ +import { FastifyRequest } from 'fastify'; + +import { makeComponentsUseCases } from '@application/components'; +import ResponseBase from '@application/common/response-base'; + +interface ListComponentsByPageQuery { + language: string + section_id: string +} + +export default async function componentRoutes(fastify: FastifyRouteInstance) { + const components = makeComponentsUseCases(fastify.diContainer.cradle); + + fastify.route({ + method: 'POST', + url: '/api/component/get-by-section', + schema: { + body: { + type: 'object', + properties: { + language: { type: 'string', description: 'Language code (e.g., vi, en, etc.)' }, + section_id: { type: 'string', description: 'ID of pages database' } + }, + required: ['language', 'section_id'], + }, + response: { + 200: { + type: 'object', + properties: { + status_code: { type: 'integer', example: 200 }, + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { type: 'integer' }, + title: { type: 'string' }, + content: { type: 'string' }, + image: { type: 'string' }, + image_2: { type: 'string' }, + image_3: { type: 'string' }, + image_4: { type: 'string' }, + image_5: { type: 'string' }, + image_6: { type: 'string' }, + image_7: { type: 'string' }, + order: { type: 'integer' }, + status: { type: 'integer' }, + created_at: { type: 'string', format: 'date-time' }, + updated_at: { type: 'string', format: 'date-time' }, + created_by: { type: 'string' }, + updated_by: { type: 'string' }, + }, + }, + }, + message: { type: 'string', example: 'Components fetched successfully' }, + }, + }, + 400: { $ref: 'ExceptionResponse#' }, + }, + tags: ['sections'], + }, + async handler( + req: FastifyRequest<{ Body: ListComponentsByPageQuery }>, + res + ) { + try { + const componentsList = await components.queries.listComponentsBySection({ + language: req.body.language, + section_id: req.body.section_id + }); + + const response = ResponseBase.formatBaseResponse( + 200, + componentsList, + 'Components fetched successfully', + ); + + res.status(200).send(response); + } catch (error) { + fastify.log.error(error); + + const errorResponse = ResponseBase.formatBaseResponse( + 400, + null, + 'Failed to fetch components', + ); + + res.status(400).send(errorResponse); + } + }, + }); +} diff --git a/src/web/routes/document-types.ts b/src/web/routes/document-types.ts new file mode 100644 index 0000000..b997116 --- /dev/null +++ b/src/web/routes/document-types.ts @@ -0,0 +1,82 @@ +import { FastifyRequest } from 'fastify'; + +import { makeDocumentTypesUseCases } from '@application/document-types'; +import ResponseBase from '@application/common/response-base'; + +interface ListDocumentTypesQuery { + language: string +} + +export default async function documentTypeRoutes(fastify: FastifyRouteInstance) { + const documentTypes = makeDocumentTypesUseCases(fastify.diContainer.cradle); + + fastify.route({ + method: 'POST', + url: '/api/document-type/all', + schema: { + body: { + type: 'object', + properties: { + language: { type: 'string', description: 'Language code (e.g., vi, en, etc.)' }, + }, + required: ['language'], + }, + response: { + 200: { + type: 'object', + properties: { + status_code: { type: 'integer', example: 200 }, + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { type: 'integer' }, + name: { type: 'string' }, + description: { type: 'string' }, + order: { type: 'integer' }, + status: { type: 'integer' }, + created_at: { type: 'string', format: 'date-time' }, + updated_at: { type: 'string', format: 'date-time' }, + created_by: { type: 'string' }, + updated_by: { type: 'string' }, + }, + }, + }, + message: { type: 'string', example: 'Document types fetched successfully' }, + }, + }, + 400: { $ref: 'ExceptionResponse#' }, + }, + tags: ['sections'], + }, + async handler( + req: FastifyRequest<{ Body: ListDocumentTypesQuery }>, + res + ) { + try { + const documentTypesList = await documentTypes.queries.listDocumentTypes({ + language: req.body.language, + }); + + const response = ResponseBase.formatBaseResponse( + 200, + documentTypesList, + 'Document types fetched successfully', + ); + + res.status(200).send(response); + } catch (error) { + fastify.log.error(error); + + const errorResponse = ResponseBase.formatBaseResponse( + 400, + null, + 'Failed to fetch document types', + ); + + res.status(400).send(errorResponse); + } + }, + }); +} diff --git a/src/web/routes/documents.ts b/src/web/routes/documents.ts new file mode 100644 index 0000000..ffe3faa --- /dev/null +++ b/src/web/routes/documents.ts @@ -0,0 +1,100 @@ +import { FastifyRequest } from 'fastify'; + +import { makeDocumentsUseCases } from '@application/documents'; +import ResponseBase from '@application/common/response-base'; + +interface ListDocumentsQuery { + language: string; + document_type_id: number; + size?: number; + page?: number; +} + +export default async function documentRoutes(fastify: FastifyRouteInstance) { + const documents = makeDocumentsUseCases(fastify.diContainer.cradle); + + fastify.route({ + method: 'POST', + url: '/api/document/get-by-document-type', + schema: { + body: { + type: 'object', + properties: { + language: { type: 'string', description: 'Language code (e.g., vi, en, etc.)' }, + section_id: { type: 'string', description: 'ID of pages database' } + }, + required: ['language', 'section_id'], + }, + response: { + 200: { + type: 'object', + properties: { + status_code: { type: 'integer', example: 200 }, + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { type: 'integer' }, + title: { type: 'string' }, + content: { type: 'string' }, + image: { type: 'string' }, + image_2: { type: 'string' }, + image_3: { type: 'string' }, + image_4: { type: 'string' }, + image_5: { type: 'string' }, + image_6: { type: 'string' }, + image_7: { type: 'string' }, + order: { type: 'integer' }, + status: { type: 'integer' }, + created_at: { type: 'string', format: 'date-time' }, + updated_at: { type: 'string', format: 'date-time' }, + created_by: { type: 'string' }, + updated_by: { type: 'string' }, + }, + }, + }, + message: { type: 'string', example: 'Components fetched successfully' }, + }, + }, + 400: { $ref: 'ExceptionResponse#' }, + }, + tags: ['sections'], + }, + async handler( + req: FastifyRequest<{ Body: ListDocumentsQuery }>, + res + ) { + try { + const { data, total, per_page, current_page, last_page } = await documents.queries.getByDocumentType({ + language: req.body.language, + document_type_id: req.body.document_type_id, + size: req.body.size, + page: req.body.page, + }); + + const response = ResponseBase.formatPaginationResponse( + 200, + data, + total ?? 0, + per_page ?? 0, + current_page ?? 0, + last_page ?? 0, + 'Document types fetched successfully', + ); + + res.status(200).send(response); + } catch (error) { + fastify.log.error(error); + + const errorResponse = ResponseBase.formatBaseResponse( + 400, + null, + 'Failed to fetch document types', + ); + + res.status(400).send(errorResponse); + } + }, + }); +} diff --git a/src/web/routes/feedbacks.ts b/src/web/routes/feedbacks.ts new file mode 100644 index 0000000..2faa1a3 --- /dev/null +++ b/src/web/routes/feedbacks.ts @@ -0,0 +1,92 @@ +import { FastifyRequest } from 'fastify'; + +import { makeComponentsUseCases } from '@application/components'; +import ResponseBase from '@application/common/response-base'; + +interface ListComponentsByPageQuery { + language: string + section_id: string +} + +export default async function feedbackRoutes(fastify: FastifyRouteInstance) { + const components = makeComponentsUseCases(fastify.diContainer.cradle); + + fastify.route({ + method: 'POST', + url: '/api/component/get-by-section', + schema: { + body: { + type: 'object', + properties: { + language: { type: 'string', description: 'Language code (e.g., vi, en, etc.)' }, + section_id: { type: 'string', description: 'ID of pages database' } + }, + required: ['language', 'section_id'], + }, + response: { + 200: { + type: 'object', + properties: { + status_code: { type: 'integer', example: 200 }, + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { type: 'integer' }, + title: { type: 'string' }, + content: { type: 'string' }, + image: { type: 'string' }, + image_2: { type: 'string' }, + image_3: { type: 'string' }, + image_4: { type: 'string' }, + image_5: { type: 'string' }, + image_6: { type: 'string' }, + image_7: { type: 'string' }, + order: { type: 'integer' }, + status: { type: 'integer' }, + created_at: { type: 'string', format: 'date-time' }, + updated_at: { type: 'string', format: 'date-time' }, + created_by: { type: 'string' }, + updated_by: { type: 'string' }, + }, + }, + }, + message: { type: 'string', example: 'Components fetched successfully' }, + }, + }, + 400: { $ref: 'ExceptionResponse#' }, + }, + tags: ['sections'], + }, + async handler( + req: FastifyRequest<{ Body: ListComponentsByPageQuery }>, + res + ) { + try { + const componentsList = await components.queries.listComponentsBySection({ + language: req.body.language, + section_id: req.body.section_id + }); + + const response = ResponseBase.formatBaseResponse( + 200, + componentsList, + 'Components fetched successfully', + ); + + res.status(200).send(response); + } catch (error) { + fastify.log.error(error); + + const errorResponse = ResponseBase.formatBaseResponse( + 400, + null, + 'Failed to fetch components', + ); + + res.status(400).send(errorResponse); + } + }, + }); +} diff --git a/src/web/routes/lecture-types.ts b/src/web/routes/lecture-types.ts new file mode 100644 index 0000000..32eff96 --- /dev/null +++ b/src/web/routes/lecture-types.ts @@ -0,0 +1,82 @@ +import { FastifyRequest } from 'fastify'; + +import { makeLectureTypesUseCases } from '@application/lecture-types'; +import ResponseBase from '@application/common/response-base'; + +interface ListLectureTypesQuery { + language: string +} + +export default async function lectureTypeRoutes(fastify: FastifyRouteInstance) { + const lectureTypes = makeLectureTypesUseCases(fastify.diContainer.cradle); + + fastify.route({ + method: 'POST', + url: '/api/lecture-type/all', + schema: { + body: { + type: 'object', + properties: { + language: { type: 'string', description: 'Language code (e.g., vi, en, etc.)' }, + }, + required: ['language'], + }, + response: { + 200: { + type: 'object', + properties: { + status_code: { type: 'integer', example: 200 }, + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { type: 'integer' }, + name: { type: 'string' }, + description: { type: 'string' }, + order: { type: 'integer' }, + status: { type: 'integer' }, + created_at: { type: 'string', format: 'date-time' }, + updated_at: { type: 'string', format: 'date-time' }, + created_by: { type: 'string' }, + updated_by: { type: 'string' }, + }, + }, + }, + message: { type: 'string', example: 'Lecture types fetched successfully' }, + }, + }, + 400: { $ref: 'ExceptionResponse#' }, + }, + tags: ['lecture-types'], + }, + async handler( + req: FastifyRequest<{ Body: ListLectureTypesQuery }>, + res + ) { + try { + const lectureTypesList = await lectureTypes.queries.listLectureTypes({ + language: req.body.language, + }); + + const response = ResponseBase.formatBaseResponse( + 200, + lectureTypesList, + 'Lecture types fetched successfully', + ); + + res.status(200).send(response); + } catch (error) { + fastify.log.error(error); + + const errorResponse = ResponseBase.formatBaseResponse( + 400, + null, + 'Failed to fetch lecture types ', + ); + + res.status(400).send(errorResponse); + } + }, + }); +} diff --git a/src/web/routes/lecturers.ts b/src/web/routes/lecturers.ts new file mode 100644 index 0000000..40dfc6e --- /dev/null +++ b/src/web/routes/lecturers.ts @@ -0,0 +1,92 @@ +import { FastifyRequest } from 'fastify'; + +import { makeComponentsUseCases } from '@application/components'; +import ResponseBase from '@application/common/response-base'; + +interface ListComponentsByPageQuery { + language: string + section_id: string +} + +export default async function lecturerRoutes(fastify: FastifyRouteInstance) { + const components = makeComponentsUseCases(fastify.diContainer.cradle); + + fastify.route({ + method: 'POST', + url: '/api/component/get-by-section', + schema: { + body: { + type: 'object', + properties: { + language: { type: 'string', description: 'Language code (e.g., vi, en, etc.)' }, + section_id: { type: 'string', description: 'ID of pages database' } + }, + required: ['language', 'section_id'], + }, + response: { + 200: { + type: 'object', + properties: { + status_code: { type: 'integer', example: 200 }, + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { type: 'integer' }, + title: { type: 'string' }, + content: { type: 'string' }, + image: { type: 'string' }, + image_2: { type: 'string' }, + image_3: { type: 'string' }, + image_4: { type: 'string' }, + image_5: { type: 'string' }, + image_6: { type: 'string' }, + image_7: { type: 'string' }, + order: { type: 'integer' }, + status: { type: 'integer' }, + created_at: { type: 'string', format: 'date-time' }, + updated_at: { type: 'string', format: 'date-time' }, + created_by: { type: 'string' }, + updated_by: { type: 'string' }, + }, + }, + }, + message: { type: 'string', example: 'Components fetched successfully' }, + }, + }, + 400: { $ref: 'ExceptionResponse#' }, + }, + tags: ['sections'], + }, + async handler( + req: FastifyRequest<{ Body: ListComponentsByPageQuery }>, + res + ) { + try { + const componentsList = await components.queries.listComponentsBySection({ + language: req.body.language, + section_id: req.body.section_id + }); + + const response = ResponseBase.formatBaseResponse( + 200, + componentsList, + 'Components fetched successfully', + ); + + res.status(200).send(response); + } catch (error) { + fastify.log.error(error); + + const errorResponse = ResponseBase.formatBaseResponse( + 400, + null, + 'Failed to fetch components', + ); + + res.status(400).send(errorResponse); + } + }, + }); +} diff --git a/src/web/routes/lectures.ts b/src/web/routes/lectures.ts new file mode 100644 index 0000000..6abee13 --- /dev/null +++ b/src/web/routes/lectures.ts @@ -0,0 +1,92 @@ +import { FastifyRequest } from 'fastify'; + +import { makeComponentsUseCases } from '@application/components'; +import ResponseBase from '@application/common/response-base'; + +interface ListComponentsByPageQuery { + language: string + section_id: string +} + +export default async function lectureRoutes(fastify: FastifyRouteInstance) { + const components = makeComponentsUseCases(fastify.diContainer.cradle); + + fastify.route({ + method: 'POST', + url: '/api/component/get-by-section', + schema: { + body: { + type: 'object', + properties: { + language: { type: 'string', description: 'Language code (e.g., vi, en, etc.)' }, + section_id: { type: 'string', description: 'ID of pages database' } + }, + required: ['language', 'section_id'], + }, + response: { + 200: { + type: 'object', + properties: { + status_code: { type: 'integer', example: 200 }, + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { type: 'integer' }, + title: { type: 'string' }, + content: { type: 'string' }, + image: { type: 'string' }, + image_2: { type: 'string' }, + image_3: { type: 'string' }, + image_4: { type: 'string' }, + image_5: { type: 'string' }, + image_6: { type: 'string' }, + image_7: { type: 'string' }, + order: { type: 'integer' }, + status: { type: 'integer' }, + created_at: { type: 'string', format: 'date-time' }, + updated_at: { type: 'string', format: 'date-time' }, + created_by: { type: 'string' }, + updated_by: { type: 'string' }, + }, + }, + }, + message: { type: 'string', example: 'Components fetched successfully' }, + }, + }, + 400: { $ref: 'ExceptionResponse#' }, + }, + tags: ['sections'], + }, + async handler( + req: FastifyRequest<{ Body: ListComponentsByPageQuery }>, + res + ) { + try { + const componentsList = await components.queries.listComponentsBySection({ + language: req.body.language, + section_id: req.body.section_id + }); + + const response = ResponseBase.formatBaseResponse( + 200, + componentsList, + 'Components fetched successfully', + ); + + res.status(200).send(response); + } catch (error) { + fastify.log.error(error); + + const errorResponse = ResponseBase.formatBaseResponse( + 400, + null, + 'Failed to fetch components', + ); + + res.status(400).send(errorResponse); + } + }, + }); +} diff --git a/src/web/routes/news-categories.ts b/src/web/routes/news-categories.ts new file mode 100644 index 0000000..94d8d90 --- /dev/null +++ b/src/web/routes/news-categories.ts @@ -0,0 +1,92 @@ +import { FastifyRequest } from 'fastify'; + +import { makeComponentsUseCases } from '@application/components'; +import ResponseBase from '@application/common/response-base'; + +interface ListComponentsByPageQuery { + language: string + section_id: string +} + +export default async function newsCategoryRoutes(fastify: FastifyRouteInstance) { + const components = makeComponentsUseCases(fastify.diContainer.cradle); + + fastify.route({ + method: 'POST', + url: '/api/component/get-by-section', + schema: { + body: { + type: 'object', + properties: { + language: { type: 'string', description: 'Language code (e.g., vi, en, etc.)' }, + section_id: { type: 'string', description: 'ID of pages database' } + }, + required: ['language', 'section_id'], + }, + response: { + 200: { + type: 'object', + properties: { + status_code: { type: 'integer', example: 200 }, + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { type: 'integer' }, + title: { type: 'string' }, + content: { type: 'string' }, + image: { type: 'string' }, + image_2: { type: 'string' }, + image_3: { type: 'string' }, + image_4: { type: 'string' }, + image_5: { type: 'string' }, + image_6: { type: 'string' }, + image_7: { type: 'string' }, + order: { type: 'integer' }, + status: { type: 'integer' }, + created_at: { type: 'string', format: 'date-time' }, + updated_at: { type: 'string', format: 'date-time' }, + created_by: { type: 'string' }, + updated_by: { type: 'string' }, + }, + }, + }, + message: { type: 'string', example: 'Components fetched successfully' }, + }, + }, + 400: { $ref: 'ExceptionResponse#' }, + }, + tags: ['sections'], + }, + async handler( + req: FastifyRequest<{ Body: ListComponentsByPageQuery }>, + res + ) { + try { + const componentsList = await components.queries.listComponentsBySection({ + language: req.body.language, + section_id: req.body.section_id + }); + + const response = ResponseBase.formatBaseResponse( + 200, + componentsList, + 'Components fetched successfully', + ); + + res.status(200).send(response); + } catch (error) { + fastify.log.error(error); + + const errorResponse = ResponseBase.formatBaseResponse( + 400, + null, + 'Failed to fetch components', + ); + + res.status(400).send(errorResponse); + } + }, + }); +} diff --git a/src/web/routes/news.ts b/src/web/routes/news.ts new file mode 100644 index 0000000..defbc3b --- /dev/null +++ b/src/web/routes/news.ts @@ -0,0 +1,92 @@ +import { FastifyRequest } from 'fastify'; + +import { makeComponentsUseCases } from '@application/components'; +import ResponseBase from '@application/common/response-base'; + +interface ListComponentsByPageQuery { + language: string + section_id: string +} + +export default async function newsRoutes(fastify: FastifyRouteInstance) { + const components = makeComponentsUseCases(fastify.diContainer.cradle); + + fastify.route({ + method: 'POST', + url: '/api/component/get-by-section', + schema: { + body: { + type: 'object', + properties: { + language: { type: 'string', description: 'Language code (e.g., vi, en, etc.)' }, + section_id: { type: 'string', description: 'ID of pages database' } + }, + required: ['language', 'section_id'], + }, + response: { + 200: { + type: 'object', + properties: { + status_code: { type: 'integer', example: 200 }, + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { type: 'integer' }, + title: { type: 'string' }, + content: { type: 'string' }, + image: { type: 'string' }, + image_2: { type: 'string' }, + image_3: { type: 'string' }, + image_4: { type: 'string' }, + image_5: { type: 'string' }, + image_6: { type: 'string' }, + image_7: { type: 'string' }, + order: { type: 'integer' }, + status: { type: 'integer' }, + created_at: { type: 'string', format: 'date-time' }, + updated_at: { type: 'string', format: 'date-time' }, + created_by: { type: 'string' }, + updated_by: { type: 'string' }, + }, + }, + }, + message: { type: 'string', example: 'Components fetched successfully' }, + }, + }, + 400: { $ref: 'ExceptionResponse#' }, + }, + tags: ['sections'], + }, + async handler( + req: FastifyRequest<{ Body: ListComponentsByPageQuery }>, + res + ) { + try { + const componentsList = await components.queries.listComponentsBySection({ + language: req.body.language, + section_id: req.body.section_id + }); + + const response = ResponseBase.formatBaseResponse( + 200, + componentsList, + 'Components fetched successfully', + ); + + res.status(200).send(response); + } catch (error) { + fastify.log.error(error); + + const errorResponse = ResponseBase.formatBaseResponse( + 400, + null, + 'Failed to fetch components', + ); + + res.status(400).send(errorResponse); + } + }, + }); +} diff --git a/src/web/routes/pages.ts b/src/web/routes/pages.ts index 8c62d2f..6163ff3 100644 --- a/src/web/routes/pages.ts +++ b/src/web/routes/pages.ts @@ -25,13 +25,13 @@ export default async function pageRoutes(fastify: FastifyRouteInstance) { 200: { type: 'object', properties: { - statusCode: { type: 'integer', example: 200 }, + status_code: { type: 'integer', example: 200 }, data: { type: 'array', items: { type: 'object', properties: { - id: { type: 'string' }, + id: { type: 'integer' }, name: { type: 'string' }, url: { type: 'string' }, order: { type: 'integer' }, diff --git a/src/web/routes/sections.ts b/src/web/routes/sections.ts new file mode 100644 index 0000000..84dfe8c --- /dev/null +++ b/src/web/routes/sections.ts @@ -0,0 +1,164 @@ +import { FastifyRequest } from 'fastify'; + +import { makeSectionsUseCases } from '@application/sections'; +import ResponseBase from '@application/common/response-base'; + +interface ListSectionsByPageQuery { + language: string + page_id: string +} + +interface ListSectionsByPageUrlQuery { + language: string + url: string +} + +export default async function sectionRoutes(fastify: FastifyRouteInstance) { + const sections = makeSectionsUseCases(fastify.diContainer.cradle); + + fastify.route({ + method: 'POST', + url: '/api/section/get-by-page', + schema: { + body: { + type: 'object', + properties: { + language: { type: 'string', description: 'Language code (e.g., vi, en, etc.)' }, + page_id: { type: 'string', description: 'ID of pages database' } + }, + required: ['language', 'page_id'], + }, + response: { + 200: { + type: 'object', + properties: { + status_code: { type: 'integer', example: 200 }, + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { type: 'integer' }, + image: { type: 'string' }, + name: { type: 'string' }, + description: { type: 'string' }, + order: { type: 'integer' }, + status: { type: 'integer' }, + created_at: { type: 'string', format: 'date-time' }, + updated_at: { type: 'string', format: 'date-time' }, + created_by: { type: 'string' }, + updated_by: { type: 'string' }, + }, + }, + }, + message: { type: 'string', example: 'Sections fetched successfully' }, + }, + }, + 400: { $ref: 'ExceptionResponse#' }, + }, + tags: ['sections'], + }, + async handler( + req: FastifyRequest<{ Body: ListSectionsByPageQuery }>, + res + ) { + try { + const pagesList = await sections.queries.listSectionsByPage({ + language: req.body.language, + page_id: req.body.page_id + }); + + const response = ResponseBase.formatBaseResponse( + 200, + pagesList, + 'Sections fetched successfully', + ); + + res.status(200).send(response); + } catch (error) { + fastify.log.error(error); + + const errorResponse = ResponseBase.formatBaseResponse( + 400, + null, + 'Failed to fetch sections', + ); + + res.status(400).send(errorResponse); + } + }, + }); + + fastify.route({ + method: 'POST', + url: '/api/section/get-by-page-url', + schema: { + body: { + type: 'object', + properties: { + language: { type: 'string', description: 'Language code (e.g., vi, en, etc.)' }, + url: { type: 'string', description: 'Url of pages database' }, + }, + required: ['language', 'url'], + }, + response: { + 200: { + type: 'object', + properties: { + status_code: { type: 'integer', example: 200 }, + data: { + type: 'array', + items: { + type: 'object', + properties: { + id: { type: 'integer' }, + image: { type: 'string' }, + name: { type: 'string' }, + description: { type: 'string' }, + order: { type: 'integer' }, + status: { type: 'integer' }, + created_at: { type: 'string', format: 'date-time' }, + updated_at: { type: 'string', format: 'date-time' }, + created_by: { type: 'string' }, + updated_by: { type: 'string' }, + }, + }, + }, + message: { type: 'string', example: 'Sections fetched successfully' }, + }, + }, + 400: { $ref: 'ExceptionResponse#' }, + }, + tags: ['sections'], + }, + async handler( + req: FastifyRequest<{ Body: ListSectionsByPageUrlQuery }>, + res + ) { + try { + const pagesList = await sections.queries.listSectionsByPageUrl({ + language: req.body.language, + url: req.body.url + }); + + const response = ResponseBase.formatBaseResponse( + 200, + pagesList, + 'Sections fetched successfully', + ); + + res.status(200).send(response); + } catch (error) { + fastify.log.error(error); + + const errorResponse = ResponseBase.formatBaseResponse( + 400, + null, + 'Failed to fetch sections', + ); + + res.status(400).send(errorResponse); + } + }, + }); +}