mirror of
https://github.com/sergeyyarkov/educt-server.git
synced 2026-10-11 18:29:15 +03:00
feat: categories controller & fetch courses params
This commit is contained in:
parent
a5dfa1b3fa
commit
c2b43d7ba2
83
app/Controllers/Http/Api/v1/CategoriesController.ts
Normal file
83
app/Controllers/Http/Api/v1/CategoriesController.ts
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
|
||||||
|
import { Exception, inject, Ioc } from '@adonisjs/core/build/standalone';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Services
|
||||||
|
*/
|
||||||
|
import CategoryService from 'App/Services/CategoryService';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validatoes
|
||||||
|
*/
|
||||||
|
import CreateCategoryValidator from 'App/Validators/Category/CreateCategoryValidator';
|
||||||
|
|
||||||
|
import BaseController from '../../BaseController';
|
||||||
|
|
||||||
|
@inject()
|
||||||
|
export default class CategoriesController extends BaseController {
|
||||||
|
private categoryService: CategoryService;
|
||||||
|
|
||||||
|
constructor(categoryService: CategoryService) {
|
||||||
|
super();
|
||||||
|
this.categoryService = categoryService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of Categories
|
||||||
|
* GET /categories
|
||||||
|
*/
|
||||||
|
public async list(ctx: HttpContextContract) {
|
||||||
|
const result = await this.categoryService.fetchCategories();
|
||||||
|
|
||||||
|
if (!result.success && result.error) {
|
||||||
|
throw new Exception(result.message, result.status, result.error.code);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.sendResponse(ctx, result.data, result.message, result.status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show category by id
|
||||||
|
* GET /category/:id
|
||||||
|
*/
|
||||||
|
public async show(ctx: HttpContextContract) {
|
||||||
|
const result = await this.categoryService.fetchCategory(ctx.params.id);
|
||||||
|
|
||||||
|
if (!result.success && result.error) {
|
||||||
|
throw new Exception(result.message, result.status, result.error.code);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.sendResponse(ctx, result.data, result.message, result.status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new category
|
||||||
|
* POST /categories/:id
|
||||||
|
*/
|
||||||
|
public async create(ctx: HttpContextContract) {
|
||||||
|
const payload = await ctx.request.validate(CreateCategoryValidator);
|
||||||
|
const result = await this.categoryService.createCategory(payload);
|
||||||
|
|
||||||
|
if (!result.success && result.error) {
|
||||||
|
throw new Exception(result.message, result.status, result.error.code);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.sendResponse(ctx, result.data, result.message, result.status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete category by id
|
||||||
|
* DELETE /categories/:id
|
||||||
|
*/
|
||||||
|
public async delete(ctx: HttpContextContract) {
|
||||||
|
const result = await this.categoryService.deleteCategory(ctx.params.id);
|
||||||
|
|
||||||
|
if (!result.success && result.error) {
|
||||||
|
throw new Exception(result.message, result.status, result.error.code);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.sendResponse(ctx, result.data, result.message, result.status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new Ioc().make(CategoriesController);
|
||||||
@ -14,6 +14,7 @@ import CreateCourseValidator from 'App/Validators/Course/CreateCourseValidator';
|
|||||||
import DelCourseFromUserValidator from 'App/Validators/Course/DelCourseFromUserValidator';
|
import DelCourseFromUserValidator from 'App/Validators/Course/DelCourseFromUserValidator';
|
||||||
import SetCourseStatusValidator from 'App/Validators/Course/SetCourseStatusValidator';
|
import SetCourseStatusValidator from 'App/Validators/Course/SetCourseStatusValidator';
|
||||||
import UpdateCourseValidator from 'App/Validators/Course/UpdateCourseValidator';
|
import UpdateCourseValidator from 'App/Validators/Course/UpdateCourseValidator';
|
||||||
|
import FetchCoursesValidator from 'App/Validators/Course/FetchCoursesValidator';
|
||||||
|
|
||||||
import BaseController from '../../BaseController';
|
import BaseController from '../../BaseController';
|
||||||
|
|
||||||
@ -31,7 +32,8 @@ export default class CoursesController extends BaseController {
|
|||||||
* GET /courses
|
* GET /courses
|
||||||
*/
|
*/
|
||||||
public async list(ctx: HttpContextContract) {
|
public async list(ctx: HttpContextContract) {
|
||||||
const result = await this.courseService.fetchCourses();
|
const payload = await ctx.request.validate(FetchCoursesValidator);
|
||||||
|
const result = await this.courseService.fetchCourses(payload);
|
||||||
|
|
||||||
if (!result.success && result.error) {
|
if (!result.success && result.error) {
|
||||||
throw new Exception(result.message, result.status, result.error.code);
|
throw new Exception(result.message, result.status, result.error.code);
|
||||||
|
|||||||
@ -38,7 +38,7 @@ export default class Course extends BaseModel {
|
|||||||
@column({ serializeAs: null })
|
@column({ serializeAs: null })
|
||||||
public category_id: string;
|
public category_id: string;
|
||||||
|
|
||||||
@column({ serializeAs: null })
|
@column()
|
||||||
public status: CourseStatusEnum;
|
public status: CourseStatusEnum;
|
||||||
|
|
||||||
@belongsTo(() => Category, {
|
@belongsTo(() => Category, {
|
||||||
|
|||||||
@ -3,6 +3,11 @@
|
|||||||
*/
|
*/
|
||||||
import Category from 'App/Models/Category';
|
import Category from 'App/Models/Category';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validators
|
||||||
|
*/
|
||||||
|
import CreateCategoryValidator from 'App/Validators/Category/CreateCategoryValidator';
|
||||||
|
|
||||||
export default class CategoryRepository {
|
export default class CategoryRepository {
|
||||||
private Category: typeof Category;
|
private Category: typeof Category;
|
||||||
|
|
||||||
@ -10,14 +15,56 @@ export default class CategoryRepository {
|
|||||||
this.Category = Category;
|
this.Category = Category;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all categories
|
||||||
|
*
|
||||||
|
* @returns Array of categories
|
||||||
|
*/
|
||||||
|
public async getAll(): Promise<Category[]> {
|
||||||
|
const categories = await this.Category.query();
|
||||||
|
return categories;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get category by id
|
* Get category by id
|
||||||
*
|
*
|
||||||
* @param id Category id
|
* @param id Category id
|
||||||
* @returns Caregory or null
|
* @returns Category or null
|
||||||
*/
|
*/
|
||||||
public async getById(id: string | number): Promise<Category | null> {
|
public async getById(id: string | number): Promise<Category | null> {
|
||||||
const category = await this.Category.query().where('id', id).first();
|
const category = await this.Category.query().where('id', id).first();
|
||||||
return category;
|
return category;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new category
|
||||||
|
*
|
||||||
|
* @param data Data input
|
||||||
|
* @returns Created category
|
||||||
|
*/
|
||||||
|
public async create(data: CreateCategoryValidator['schema']['props']): Promise<Category> {
|
||||||
|
const category = await this.Category.create({
|
||||||
|
title: data.title,
|
||||||
|
description: data.description,
|
||||||
|
});
|
||||||
|
|
||||||
|
return category;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete Category
|
||||||
|
*
|
||||||
|
* @param id Category id
|
||||||
|
* @returns Deleted category or null
|
||||||
|
*/
|
||||||
|
public async delete(id: string | number): Promise<Category | null> {
|
||||||
|
const category = await this.Category.query().where('id', id).first();
|
||||||
|
|
||||||
|
if (category) {
|
||||||
|
await category.delete();
|
||||||
|
return category;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import User from 'App/Models/User';
|
|||||||
* Validators
|
* Validators
|
||||||
*/
|
*/
|
||||||
import CreateCourseValidator from 'App/Validators/Course/CreateCourseValidator';
|
import CreateCourseValidator from 'App/Validators/Course/CreateCourseValidator';
|
||||||
|
import FetchCoursesValidator from 'App/Validators/Course/FetchCoursesValidator';
|
||||||
import UpdateCourseValidator from 'App/Validators/Course/UpdateCourseValidator';
|
import UpdateCourseValidator from 'App/Validators/Course/UpdateCourseValidator';
|
||||||
|
|
||||||
export default class CourseRepository {
|
export default class CourseRepository {
|
||||||
@ -44,14 +45,17 @@ export default class CourseRepository {
|
|||||||
*
|
*
|
||||||
* @returns List of courses
|
* @returns List of courses
|
||||||
*/
|
*/
|
||||||
public async getAll(): Promise<Course[]> {
|
public async getAll(params?: FetchCoursesValidator['schema']['props']): Promise<Course[]> {
|
||||||
|
const { status = CourseStatusEnum.PUBLISHED } = params || {};
|
||||||
|
|
||||||
const courses = await this.Course.query()
|
const courses = await this.Course.query()
|
||||||
.preload('teacher')
|
.preload('teacher')
|
||||||
.preload('category')
|
.preload('category')
|
||||||
.preload('lessons')
|
.preload('lessons')
|
||||||
.preload('students')
|
.preload('students')
|
||||||
.preload('image')
|
.preload('image')
|
||||||
.where('status', CourseStatusEnum.PUBLISHED);
|
.where('status', status);
|
||||||
|
|
||||||
return courses;
|
return courses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
119
app/Services/CategoryService.ts
Normal file
119
app/Services/CategoryService.ts
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
import { inject, Ioc } from '@adonisjs/core/build/standalone';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Datatypes
|
||||||
|
*/
|
||||||
|
import IResponse from 'App/Datatypes/Interfaces/IResponse';
|
||||||
|
import HttpStatusEnum from 'App/Datatypes/Enums/HttpStatusEnum';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repositories
|
||||||
|
*/
|
||||||
|
import CategoryRepository from 'App/Repositories/CategoryRepository';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validators
|
||||||
|
*/
|
||||||
|
import CreateCategoryValidator from 'App/Validators/Category/CreateCategoryValidator';
|
||||||
|
|
||||||
|
@inject()
|
||||||
|
export default class CategoryService {
|
||||||
|
private categoryRepository: CategoryRepository;
|
||||||
|
|
||||||
|
constructor(categoryRepository: CategoryRepository) {
|
||||||
|
this.categoryRepository = categoryRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch list of categories
|
||||||
|
*
|
||||||
|
* @returns Response
|
||||||
|
*/
|
||||||
|
public async fetchCategories(): Promise<IResponse> {
|
||||||
|
const data = await this.categoryRepository.getAll();
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
status: HttpStatusEnum.OK,
|
||||||
|
message: 'Fetched all categories.',
|
||||||
|
data,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch category by id
|
||||||
|
*
|
||||||
|
* @param id Category id
|
||||||
|
* @returns Response
|
||||||
|
*/
|
||||||
|
public async fetchCategory(id: string | number): Promise<IResponse> {
|
||||||
|
const data = await this.categoryRepository.getById(id);
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
status: HttpStatusEnum.NOT_FOUND,
|
||||||
|
message: 'Category not found.',
|
||||||
|
data: {},
|
||||||
|
error: {
|
||||||
|
code: 'E_NOT_FOUND',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
status: HttpStatusEnum.OK,
|
||||||
|
message: 'Fetched category.',
|
||||||
|
data,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new category
|
||||||
|
*
|
||||||
|
* @param data Data for create category
|
||||||
|
* @returns Response
|
||||||
|
*/
|
||||||
|
public async createCategory(data: CreateCategoryValidator['schema']['props']): Promise<IResponse> {
|
||||||
|
const category = await this.categoryRepository.create(data);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
status: HttpStatusEnum.CREATED,
|
||||||
|
message: 'Category created.',
|
||||||
|
data: category,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete category by id
|
||||||
|
*
|
||||||
|
* @param id Category id
|
||||||
|
* @returns Deleted category
|
||||||
|
*/
|
||||||
|
public async deleteCategory(id: string | number): Promise<IResponse> {
|
||||||
|
const data = await this.categoryRepository.delete(id);
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
status: HttpStatusEnum.NOT_FOUND,
|
||||||
|
message: 'Category not found.',
|
||||||
|
data: {},
|
||||||
|
error: {
|
||||||
|
code: 'E_NOT_FOUND',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
status: HttpStatusEnum.OK,
|
||||||
|
message: 'Category deleted.',
|
||||||
|
data,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new Ioc().make(CategoryService);
|
||||||
@ -23,6 +23,7 @@ import ImageRepository from 'App/Repositories/ImageRepository';
|
|||||||
*/
|
*/
|
||||||
import CreateCourseValidator from 'App/Validators/Course/CreateCourseValidator';
|
import CreateCourseValidator from 'App/Validators/Course/CreateCourseValidator';
|
||||||
import UpdateCourseValidator from 'App/Validators/Course/UpdateCourseValidator';
|
import UpdateCourseValidator from 'App/Validators/Course/UpdateCourseValidator';
|
||||||
|
import FetchCoursesValidator from 'App/Validators/Course/FetchCoursesValidator';
|
||||||
|
|
||||||
@inject()
|
@inject()
|
||||||
export default class CourseService {
|
export default class CourseService {
|
||||||
@ -51,8 +52,8 @@ export default class CourseService {
|
|||||||
*
|
*
|
||||||
* @returns Response
|
* @returns Response
|
||||||
*/
|
*/
|
||||||
public async fetchCourses(): Promise<IResponse> {
|
public async fetchCourses(params?: FetchCoursesValidator['schema']['props']): Promise<IResponse> {
|
||||||
const data = await this.courseRepository.getAll();
|
const data = await this.courseRepository.getAll(params);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
|
|||||||
13
app/Validators/Category/CreateCategoryValidator.ts
Normal file
13
app/Validators/Category/CreateCategoryValidator.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { schema } from '@ioc:Adonis/Core/Validator';
|
||||||
|
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
|
||||||
|
|
||||||
|
export default class CreateCategoryValidator {
|
||||||
|
constructor(protected ctx: HttpContextContract) {}
|
||||||
|
|
||||||
|
public schema = schema.create({
|
||||||
|
title: schema.string(),
|
||||||
|
description: schema.string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
public messages = {};
|
||||||
|
}
|
||||||
13
app/Validators/Course/FetchCoursesValidator.ts
Normal file
13
app/Validators/Course/FetchCoursesValidator.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { schema } from '@ioc:Adonis/Core/Validator';
|
||||||
|
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
|
||||||
|
import CourseStatusEnum from 'App/Datatypes/Enums/CourseStatusEnum';
|
||||||
|
|
||||||
|
export default class FetchCoursesValidator {
|
||||||
|
constructor(protected ctx: HttpContextContract) {}
|
||||||
|
|
||||||
|
public schema = schema.create({
|
||||||
|
status: schema.enum.optional(Object.values(CourseStatusEnum)),
|
||||||
|
});
|
||||||
|
|
||||||
|
public messages = {};
|
||||||
|
}
|
||||||
8
routes/apis/v1/categories.ts
Normal file
8
routes/apis/v1/categories.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import Route from '@ioc:Adonis/Core/Route';
|
||||||
|
|
||||||
|
Route.group(() => {
|
||||||
|
Route.get('/', 'Api/v1/CategoriesController.list').middleware('role:admin,teacher,student').as('categories.list');
|
||||||
|
Route.get('/:id', 'Api/v1/CategoriesController.show').middleware('role:admin,teacher,student').as('categories.show');
|
||||||
|
Route.post('/', 'Api/v1/CategoriesController.create').middleware('role:admin,teacher').as('categories.create');
|
||||||
|
Route.delete('/:id', 'Api/v1/CategoriesController.delete').middleware('role:admin,teacher').as('categories.delete');
|
||||||
|
}).prefix('categories');
|
||||||
@ -55,6 +55,13 @@ Route.group(() => {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
require('./images');
|
require('./images');
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Categories module
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
require('./categories');
|
||||||
}).middleware('auth');
|
}).middleware('auth');
|
||||||
})
|
})
|
||||||
.prefix('v1')
|
.prefix('v1')
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user