diff --git a/apps/api/src/chapter/adminChapter.service.ts b/apps/api/src/chapter/adminChapter.service.ts index a965531d..6e457ca3 100644 --- a/apps/api/src/chapter/adminChapter.service.ts +++ b/apps/api/src/chapter/adminChapter.service.ts @@ -63,7 +63,7 @@ export class AdminChapterService { // }, // }; // } - // async processLessonItems(lessonItemsList: LessonItemWithContentSchema[]) { + // async processLessonItems(lessonItemsList: AdminLessonWithContentSchema[]) { // const getFileUrl = async (url: string) => { // if (!url || url.startsWith("https://")) return url; // return await this.s3Service.getSignedUrl(url); @@ -123,7 +123,7 @@ export class AdminChapterService { // const lessonItemsList = await this.adminChapterRepository.getLessonItems(id); - // const items = await this.processLessonItems(lessonItemsList as LessonItemWithContentSchema[]); + // const items = await this.processLessonItems(lessonItemsList as AdminLessonWithContentSchema[]); // return { // ...lesson, diff --git a/apps/api/src/chapter/repositories/adminChapter.repository.ts b/apps/api/src/chapter/repositories/adminChapter.repository.ts index c4c34660..06b20ddc 100644 --- a/apps/api/src/chapter/repositories/adminChapter.repository.ts +++ b/apps/api/src/chapter/repositories/adminChapter.repository.ts @@ -6,7 +6,7 @@ import { chapters, lessons, questionAnswerOptions, questions } from "src/storage import type { UpdateChapterBody } from "../schemas/chapter.schema"; import type { PostgresJsDatabase } from "drizzle-orm/postgres-js"; -import type { LessonItemWithContentSchema, QuestionSchema } from "src/lesson/lesson.schema"; +import type { AdminLessonWithContentSchema, QuestionSchema } from "src/lesson/lesson.schema"; import type * as schema from "src/storage/schema"; @Injectable() @@ -209,7 +209,7 @@ export class AdminChapterRepository { // // : await this.fileService.getFileUrl(lesson.imageUrl), // // }; - async getBetaChapterLessons(chapterId: UUIDType): Promise { + async getBetaChapterLessons(chapterId: UUIDType): Promise { return await this.db .select({ updatedAt: sql`${lessons.updatedAt}`, diff --git a/apps/api/src/courses/course.service.ts b/apps/api/src/courses/course.service.ts index 6f3c1678..6ecd1182 100644 --- a/apps/api/src/courses/course.service.ts +++ b/apps/api/src/courses/course.service.ts @@ -57,7 +57,7 @@ import type { CommonShowCourse } from "./schemas/showCourseCommon.schema"; import type { UpdateCourseBody } from "./schemas/updateCourse.schema"; import type { PostgresJsDatabase } from "drizzle-orm/postgres-js"; import type { Pagination, UUIDType } from "src/common"; -import type { LessonItemWithContentSchema } from "src/lesson/lesson.schema"; +import type { AdminLessonWithContentSchema } from "src/lesson/lesson.schema"; import type * as schema from "src/storage/schema"; import type { ProgressStatus } from "src/utils/types/progress.type"; @@ -490,7 +490,7 @@ export class CourseService { const updatedCourseLessonList = await Promise.all( courseChapterList?.map(async (chapter) => { - const lessons: LessonItemWithContentSchema[] = + const lessons: AdminLessonWithContentSchema[] = await this.adminChapterRepository.getBetaChapterLessons(chapter.id); const lessonsWithSignedUrls = await this.addS3SignedUrlsToLessonsAndQuestions(lessons); @@ -928,7 +928,7 @@ export class CourseService { ); } - private async addS3SignedUrlsToLessonsAndQuestions(lessons: LessonItemWithContentSchema[]) { + private async addS3SignedUrlsToLessonsAndQuestions(lessons: AdminLessonWithContentSchema[]) { return await Promise.all( lessons.map(async (lesson) => { const updatedLesson = { ...lesson }; diff --git a/apps/api/src/lesson/lesson.controller.ts b/apps/api/src/lesson/lesson.controller.ts index 864c0715..046a44e2 100644 --- a/apps/api/src/lesson/lesson.controller.ts +++ b/apps/api/src/lesson/lesson.controller.ts @@ -32,8 +32,7 @@ import { import { AdminLessonService } from "./services/adminLesson.service"; import { LessonService } from "./services/lesson.service"; -import type { - LessonShow} from "./lesson.schema"; +import type { LessonShow } from "./lesson.schema"; @Controller("lesson") @UseGuards(RolesGuard) diff --git a/apps/api/src/lesson/lesson.schema.ts b/apps/api/src/lesson/lesson.schema.ts index 59f4aa12..e4c9c7ab 100644 --- a/apps/api/src/lesson/lesson.schema.ts +++ b/apps/api/src/lesson/lesson.schema.ts @@ -2,7 +2,7 @@ import { Type } from "@sinclair/typebox"; import { UUIDSchema } from "src/common"; -import { PhotoQuestionType, QuestionType } from "./lesson.type"; +import { LESSON_TYPES, PhotoQuestionType, QuestionType } from "./lesson.type"; import type { Static } from "@sinclair/typebox"; @@ -24,7 +24,6 @@ export const questionSchema = Type.Object({ }); export const lessonSchema = Type.Object({ - updatedAt: Type.Optional(Type.String()), id: UUIDSchema, title: Type.String(), type: Type.String(), @@ -33,6 +32,7 @@ export const lessonSchema = Type.Object({ fileS3Key: Type.Optional(Type.String()), fileType: Type.Optional(Type.String()), questions: Type.Optional(Type.Array(questionSchema)), + updatedAt: Type.Optional(Type.String()), }); const lessonQuizSchema = Type.Object({ @@ -46,7 +46,7 @@ const lessonQuizSchema = Type.Object({ questions: Type.Optional(Type.Array(questionSchema)), }); -export const lessonItemSchema = Type.Object({ +export const adminLessonSchema = Type.Object({ id: UUIDSchema, type: Type.String(), displayOrder: Type.Number(), @@ -84,17 +84,18 @@ export const questionDetails = Type.Object({ export const lessonShowSchema = Type.Object({ id: UUIDSchema, title: Type.String(), - type: Type.String(), + type: Type.Enum(LESSON_TYPES), description: Type.String(), fileType: Type.Union([Type.String(), Type.Null()]), fileUrl: Type.Union([Type.String(), Type.Null()]), quizDetails: Type.Optional(questionDetails), + displayOrder: Type.Number(), }); export const updateLessonSchema = Type.Partial(createLessonSchema); export const updateQuizLessonSchema = Type.Partial(createQuizLessonSchema); -export type LessonItemWithContentSchema = Static; +export type AdminLessonWithContentSchema = Static; export type CreateLessonBody = Static; export type UpdateLessonBody = Static; export type UpdateQuizLessonBody = Static; diff --git a/apps/api/src/lesson/services/lesson.service.ts b/apps/api/src/lesson/services/lesson.service.ts index ad1baffe..0f2d223c 100644 --- a/apps/api/src/lesson/services/lesson.service.ts +++ b/apps/api/src/lesson/services/lesson.service.ts @@ -13,9 +13,8 @@ import { import { LESSON_TYPES } from "../lesson.type"; - import type { LessonShow, OptionBody, QuestionBody } from "../lesson.schema"; -import type { PhotoQuestionType, QuestionType } from "../lesson.type"; +import type { LessonTypes, PhotoQuestionType, QuestionType } from "../lesson.type"; import type { UUIDType } from "src/common"; @Injectable() @@ -23,18 +22,20 @@ export class LessonService { constructor( @Inject("DB") private readonly db: DatabasePg, private readonly fileService: FileService, // TODO: add event bus + ) { // private readonly eventBus: EventBus, - ) {} + } async getLessonById(id: UUIDType): Promise { const [lesson] = await this.db .select({ id: lessons.id, - type: lessons.type, + type: sql`${lessons.type}`, title: lessons.title, description: sql`${lessons.description}`, fileUrl: lessons.fileS3Key, fileType: lessons.fileType, + displayOrder: sql`${lessons.displayOrder}`, }) .from(lessons) .where(eq(lessons.id, id)); diff --git a/apps/api/src/scorm/services/scorm.service.ts b/apps/api/src/scorm/services/scorm.service.ts index 785dd6cc..438454d6 100644 --- a/apps/api/src/scorm/services/scorm.service.ts +++ b/apps/api/src/scorm/services/scorm.service.ts @@ -11,13 +11,13 @@ import { AdminChapterService } from "src/chapter/adminChapter.service"; import { DatabasePg } from "src/common"; import { FileService } from "src/file/file.service"; import { LESSON_TYPES } from "src/lesson/lesson.type"; +import { AdminLessonService } from "src/lesson/services/adminLesson.service"; import { S3Service } from "src/s3/s3.service"; import { SCORM } from "../constants/scorm.consts"; import { ScormRepository } from "../repositories/scorm.repository"; import type { UUIDType } from "src/common"; -import { AdminLessonService } from "src/lesson/services/adminLesson.service"; type ScormChapter = { title: string; diff --git a/apps/api/src/seed/nice-data-seeds.ts b/apps/api/src/seed/nice-data-seeds.ts index 84eb1c6e..98c35ffe 100644 --- a/apps/api/src/seed/nice-data-seeds.ts +++ b/apps/api/src/seed/nice-data-seeds.ts @@ -1476,7 +1476,7 @@ export const niceCourses: NiceCourseData[] = [ { title: "Understanding AI Basics", isPublished: true, - isFreemium: true, + isFreemium: false, displayOrder: 1, lessons: [ { @@ -1490,7 +1490,7 @@ export const niceCourses: NiceCourseData[] = [ type: LESSON_TYPES.TEXT, title: "Key Concepts and Terminologies in AI", description: - "Learn the foundational terminologies of AI, including Machine Learning, Neural Networks, NLP, and more.", + '

Artificial Intelligence (AI) refers to the simulation of human intelligence in machines programmed to think, learn, and make decisions. Below are some key concepts and terminologies essential to understanding AI:

\n\n
    \n
  • Machine Learning (ML): A subset of AI focused on creating algorithms that allow computers to learn from and make predictions based on data. Example: A recommendation system suggesting movies based on your viewing history.
  • \n
  • Neural Networks: Inspired by the human brain, these are algorithms designed to recognize patterns and process data in layers, enabling tasks like image and speech recognition.
  • \n
  • Natural Language Processing (NLP): This involves teaching machines to understand, interpret, and generate human language. Example: Virtual assistants like Alexa or Siri.
  • \n
  • Computer Vision: A field of AI that enables computers to interpret and process visual data, such as images and videos. Example: Facial recognition technology.
  • \n
  • Deep Learning: A more complex subset of ML that uses large neural networks to analyze massive amounts of data and solve intricate problems, such as self-driving cars.
  • \n
  • Supervised vs. Unsupervised Learning:
    - Supervised Learning: The AI is trained on labeled data (e.g., images labeled as "cat" or "dog").
    - Unsupervised Learning: The AI identifies patterns in unlabeled data without explicit instructions.
  • \n
  • Big Data: The large volume of structured and unstructured data generated by businesses and devices, which is essential for training AI models.
  • \n
  • Automation: AI is often used to automate repetitive tasks, freeing up human resources for more complex activities.
  • \n
  • Ethics in AI: As AI becomes more powerful, ensuring its ethical use (e.g., avoiding bias in decision-making) is critical for building trust.
  • \n
\n\n

Why These Concepts Matter

\n

Understanding these basic AI terms is the first step toward recognizing how AI can be applied in business. Each concept represents a building block of AI\'s potential to transform industries by increasing efficiency, improving decision-making, and creating innovative solutions.

', displayOrder: 2, }, { @@ -1512,9 +1512,9 @@ export const niceCourses: NiceCourseData[] = [ title: "What is the primary goal of AI in business?", options: [ { optionText: "Replace human workers", isCorrect: false, position: 0 }, - { optionText: "Fully automate all tasks", isCorrect: false, position: 1 }, + { optionText: "Automate repetitive tasks", isCorrect: false, position: 1 }, { optionText: "Improve decision-making", isCorrect: true, position: 2 }, - { optionText: "Eliminate all business costs", isCorrect: false, position: 3 }, + { optionText: "Eliminate operational costs", isCorrect: false, position: 3 }, ], }, ], @@ -1581,13 +1581,11 @@ export const niceCourses: NiceCourseData[] = [ type: QuestionType.FillInTheBlanks, title: "Complete the blanks: Artificial [word] refers to the ability of machines to mimic [word] intelligence.", - description: - "

Complete the blanks: Artificial Intelligence refers to the ability of machines to mimic Human intelligence.

", options: [ { optionText: "Intelligence", isCorrect: true, position: 0 }, - { optionText: "Human", isCorrect: true, position: 1 }, - { optionText: "Automation", isCorrect: false, position: 2 }, - { optionText: "Learning", isCorrect: false, position: 3 }, + { optionText: "Automation", isCorrect: false, position: 1 }, + { optionText: "Learning", isCorrect: false, position: 2 }, + { optionText: "Human", isCorrect: true, position: 3 }, { optionText: "Animal", isCorrect: false, position: 4 }, ], }, diff --git a/apps/api/src/studentLessonProgress/studentLessonProgress.service.ts b/apps/api/src/studentLessonProgress/studentLessonProgress.service.ts index a9d214ed..dbbd08dd 100644 --- a/apps/api/src/studentLessonProgress/studentLessonProgress.service.ts +++ b/apps/api/src/studentLessonProgress/studentLessonProgress.service.ts @@ -16,7 +16,6 @@ import { PROGRESS_STATUSES } from "src/utils/types/progress.type"; import type { UUIDType } from "src/common"; import type { ProgressStatus } from "src/utils/types/progress.type"; - @Injectable() export class StudentLessonProgressService { constructor( diff --git a/apps/api/src/swagger/api-schema.json b/apps/api/src/swagger/api-schema.json index 35e9780c..30e282c5 100644 --- a/apps/api/src/swagger/api-schema.json +++ b/apps/api/src/swagger/api-schema.json @@ -4251,7 +4251,28 @@ "type": "string" }, "type": { - "type": "string" + "anyOf": [ + { + "const": "text", + "type": "string" + }, + { + "const": "file", + "type": "string" + }, + { + "const": "presentation", + "type": "string" + }, + { + "const": "video", + "type": "string" + }, + { + "const": "quiz", + "type": "string" + } + ] }, "description": { "type": "string" @@ -4324,6 +4345,9 @@ "wrongAnswerCount", "score" ] + }, + "displayOrder": { + "type": "number" } }, "required": [ @@ -4332,7 +4356,8 @@ "type", "description", "fileType", - "fileUrl" + "fileUrl", + "displayOrder" ] } }, @@ -4346,9 +4371,6 @@ { "type": "object", "properties": { - "updatedAt": { - "type": "string" - }, "title": { "type": "string" }, @@ -4458,6 +4480,9 @@ "title" ] } + }, + "updatedAt": { + "type": "string" } }, "required": [ @@ -4827,9 +4852,6 @@ { "type": "object", "properties": { - "updatedAt": { - "type": "string" - }, "title": { "type": "string" }, @@ -4939,6 +4961,9 @@ "title" ] } + }, + "updatedAt": { + "type": "string" } } }, @@ -5090,9 +5115,6 @@ "items": { "type": "object", "properties": { - "updatedAt": { - "type": "string" - }, "id": { "format": "uuid", "type": "string" @@ -5209,6 +5231,9 @@ "title" ] } + }, + "updatedAt": { + "type": "string" } }, "required": [