mirror of
https://github.com/sergeyyarkov/educt-server.git
synced 2026-10-11 10:19:20 +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 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);
|
||||
|
||||
@ -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, {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
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 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,
|
||||
|
||||
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');
|
||||
|
||||
/**
|
||||
*
|
||||
* Categories module
|
||||
*
|
||||
*/
|
||||
require('./categories');
|
||||
}).middleware('auth');
|
||||
})
|
||||
.prefix('v1')
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user