feat: categories controller & fetch courses params

This commit is contained in:
Sergey Yarkov 2021-10-09 21:06:33 +03:00
parent a5dfa1b3fa
commit c2b43d7ba2
11 changed files with 304 additions and 7 deletions

View 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);

View File

@ -14,6 +14,7 @@ import CreateCourseValidator from 'App/Validators/Course/CreateCourseValidator';
import DelCourseFromUserValidator from 'App/Validators/Course/DelCourseFromUserValidator';
import SetCourseStatusValidator from 'App/Validators/Course/SetCourseStatusValidator';
import UpdateCourseValidator from 'App/Validators/Course/UpdateCourseValidator';
import FetchCoursesValidator from 'App/Validators/Course/FetchCoursesValidator';
import BaseController from '../../BaseController';
@ -31,7 +32,8 @@ export default class CoursesController extends BaseController {
* GET /courses
*/
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) {
throw new Exception(result.message, result.status, result.error.code);

View File

@ -38,7 +38,7 @@ export default class Course extends BaseModel {
@column({ serializeAs: null })
public category_id: string;
@column({ serializeAs: null })
@column()
public status: CourseStatusEnum;
@belongsTo(() => Category, {

View File

@ -3,6 +3,11 @@
*/
import Category from 'App/Models/Category';
/**
* Validators
*/
import CreateCategoryValidator from 'App/Validators/Category/CreateCategoryValidator';
export default class CategoryRepository {
private Category: typeof Category;
@ -10,14 +15,56 @@ export default class CategoryRepository {
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
*
* @param id Category id
* @returns Caregory or null
* @returns Category or null
*/
public async getById(id: string | number): Promise<Category | null> {
const category = await this.Category.query().where('id', id).first();
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;
}
}

View File

@ -16,6 +16,7 @@ import User from 'App/Models/User';
* Validators
*/
import CreateCourseValidator from 'App/Validators/Course/CreateCourseValidator';
import FetchCoursesValidator from 'App/Validators/Course/FetchCoursesValidator';
import UpdateCourseValidator from 'App/Validators/Course/UpdateCourseValidator';
export default class CourseRepository {
@ -44,14 +45,17 @@ export default class CourseRepository {
*
* @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()
.preload('teacher')
.preload('category')
.preload('lessons')
.preload('students')
.preload('image')
.where('status', CourseStatusEnum.PUBLISHED);
.where('status', status);
return courses;
}

View 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);

View File

@ -23,6 +23,7 @@ import ImageRepository from 'App/Repositories/ImageRepository';
*/
import CreateCourseValidator from 'App/Validators/Course/CreateCourseValidator';
import UpdateCourseValidator from 'App/Validators/Course/UpdateCourseValidator';
import FetchCoursesValidator from 'App/Validators/Course/FetchCoursesValidator';
@inject()
export default class CourseService {
@ -51,8 +52,8 @@ export default class CourseService {
*
* @returns Response
*/
public async fetchCourses(): Promise<IResponse> {
const data = await this.courseRepository.getAll();
public async fetchCourses(params?: FetchCoursesValidator['schema']['props']): Promise<IResponse> {
const data = await this.courseRepository.getAll(params);
return {
success: true,

View 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 = {};
}

View 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 = {};
}

View 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');

View File

@ -55,6 +55,13 @@ Route.group(() => {
*
*/
require('./images');
/**
*
* Categories module
*
*/
require('./categories');
}).middleware('auth');
})
.prefix('v1')