Merge pull request 'feat: add Course management functionality with CRUD operations and UI integration' (#59) from refactor/move-course-form-manage-to-master into dev
Reviewed-on: #59
This commit is contained in:
commit
6c28782484
@ -7,8 +7,8 @@
|
|||||||
use App\Http\Requests\PaginatedRequest;
|
use App\Http\Requests\PaginatedRequest;
|
||||||
use App\Models\CourseClass;
|
use App\Models\CourseClass;
|
||||||
use App\Services\Admin\Manage\CourseClassService;
|
use App\Services\Admin\Manage\CourseClassService;
|
||||||
use App\Services\Admin\Manage\CourseService;
|
|
||||||
use App\Services\Admin\Master\AcademicTermService;
|
use App\Services\Admin\Master\AcademicTermService;
|
||||||
|
use App\Services\Admin\Master\CourseService;
|
||||||
use App\Services\Admin\Users\LecturerService;
|
use App\Services\Admin\Users\LecturerService;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Inertia\Inertia;
|
use Inertia\Inertia;
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Http\Controllers\Admin\Manage;
|
namespace App\Http\Controllers\Admin\Master;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Http\Requests\Admin\Manage\CourseRequest;
|
use App\Http\Requests\Admin\Master\CourseRequest;
|
||||||
use App\Http\Requests\PaginatedRequest;
|
use App\Http\Requests\PaginatedRequest;
|
||||||
use App\Models\Course;
|
use App\Models\Course;
|
||||||
use App\Services\Admin\Manage\CourseService;
|
use App\Services\Admin\Master\CourseService;
|
||||||
use App\Services\Admin\Master\DepartmentService;
|
use App\Services\Admin\Master\DepartmentService;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Inertia\Inertia;
|
use Inertia\Inertia;
|
||||||
@ -21,13 +21,15 @@ public function __construct(
|
|||||||
|
|
||||||
public function index(PaginatedRequest $request): Response
|
public function index(PaginatedRequest $request): Response
|
||||||
{
|
{
|
||||||
return Inertia::render('admin/manage/courses/index', [
|
return Inertia::render('admin/master/courses/index', [
|
||||||
'courses' => $this->service->paginated(
|
'courses' => $this->service->paginated(
|
||||||
...$request->validatedWithDefaults(),
|
...$request->validatedWithDefaults(),
|
||||||
departmentId: $request->validated('department_id'),
|
departmentId: $request->validated('department_id'),
|
||||||
|
semesterNumber: $request->validated('semester_number'),
|
||||||
),
|
),
|
||||||
'departments' => $this->departmentService->getAllForSelect(),
|
'departments' => $this->departmentService->getAllForSelect(),
|
||||||
'filters' => $request->only(['department_id']),
|
'semesterNumbers' => $this->service->getSemesterNumbers(),
|
||||||
|
'filters' => $request->only(['department_id', 'semester_number']),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,7 +39,7 @@ public function store(CourseRequest $request): RedirectResponse
|
|||||||
|
|
||||||
Inertia::flash('toast', ['type' => 'success', 'message' => 'Mata kuliah berhasil ditambahkan.']);
|
Inertia::flash('toast', ['type' => 'success', 'message' => 'Mata kuliah berhasil ditambahkan.']);
|
||||||
|
|
||||||
return to_route('admin.manage.courses.index');
|
return to_route('admin.master.courses.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update(CourseRequest $request, Course $course): RedirectResponse
|
public function update(CourseRequest $request, Course $course): RedirectResponse
|
||||||
@ -46,7 +48,7 @@ public function update(CourseRequest $request, Course $course): RedirectResponse
|
|||||||
|
|
||||||
Inertia::flash('toast', ['type' => 'success', 'message' => 'Mata kuliah berhasil diperbarui.']);
|
Inertia::flash('toast', ['type' => 'success', 'message' => 'Mata kuliah berhasil diperbarui.']);
|
||||||
|
|
||||||
return to_route('admin.manage.courses.index');
|
return to_route('admin.master.courses.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function destroy(Course $course): RedirectResponse
|
public function destroy(Course $course): RedirectResponse
|
||||||
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Http\Requests\Admin\Manage;
|
namespace App\Http\Requests\Admin\Master;
|
||||||
|
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
use Illuminate\Validation\Rule;
|
use Illuminate\Validation\Rule;
|
||||||
@ -25,6 +25,7 @@ public function rules(): array
|
|||||||
'department_id' => ['nullable', 'integer'],
|
'department_id' => ['nullable', 'integer'],
|
||||||
'status' => ['nullable', 'string'],
|
'status' => ['nullable', 'string'],
|
||||||
'enrollment_year' => ['nullable', 'integer'],
|
'enrollment_year' => ['nullable', 'integer'],
|
||||||
|
'semester_number' => ['nullable', 'integer'],
|
||||||
'semester' => ['nullable', 'string', Rule::in(Semester::values())],
|
'semester' => ['nullable', 'string', Rule::in(Semester::values())],
|
||||||
'is_active' => ['nullable', Rule::in(['true', 'false'])],
|
'is_active' => ['nullable', Rule::in(['true', 'false'])],
|
||||||
'academic_term_id' => ['nullable', 'integer'],
|
'academic_term_id' => ['nullable', 'integer'],
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Services\Admin\Manage;
|
namespace App\Services\Admin\Master;
|
||||||
|
|
||||||
use App\Models\Course;
|
use App\Models\Course;
|
||||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||||
@ -13,13 +13,25 @@ public function getAllForSelect(): Collection
|
|||||||
return Course::select(['id', 'code', 'name', 'department_id'])->get();
|
return Course::select(['id', 'code', 'name', 'department_id'])->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function paginated(int $perPage = 25, string $search = '', ?int $departmentId = null): LengthAwarePaginator
|
public function getSemesterNumbers(): array
|
||||||
|
{
|
||||||
|
return Course::query()
|
||||||
|
->select('semester_number')
|
||||||
|
->whereNotNull('semester_number')
|
||||||
|
->distinct()
|
||||||
|
->orderBy('semester_number')
|
||||||
|
->pluck('semester_number')
|
||||||
|
->all();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function paginated(int $perPage = 25, string $search = '', ?int $departmentId = null, ?int $semesterNumber = null): LengthAwarePaginator
|
||||||
{
|
{
|
||||||
return Course::query()
|
return Course::query()
|
||||||
->select(['id', 'code', 'name', 'credits', 'department_id', 'semester_number'])
|
->select(['id', 'code', 'name', 'credits', 'department_id', 'semester_number'])
|
||||||
->with('department:id,name')
|
->with('department:id,name')
|
||||||
->when($search, fn ($q) => $q->where('name', 'like', "%{$search}%")->orWhere('code', 'like', "%{$search}%"))
|
->when($search, fn ($q) => $q->where('name', 'like', "%{$search}%")->orWhere('code', 'like', "%{$search}%"))
|
||||||
->when($departmentId, fn ($q) => $q->where('department_id', $departmentId))
|
->when($departmentId, fn ($q) => $q->where('department_id', $departmentId))
|
||||||
|
->when($semesterNumber, fn ($q) => $q->where('semester_number', $semesterNumber))
|
||||||
->latest()
|
->latest()
|
||||||
->paginate($perPage);
|
->paginate($perPage);
|
||||||
}
|
}
|
||||||
@ -1,10 +1,6 @@
|
|||||||
import { usePage } from '@inertiajs/react';
|
import { usePage } from '@inertiajs/react';
|
||||||
import type { Icon } from '@tabler/icons-react';
|
import type { Icon } from '@tabler/icons-react';
|
||||||
import {
|
import { IconGridDots, IconHelp, IconMessageDots } from '@tabler/icons-react';
|
||||||
IconGridDots,
|
|
||||||
IconHelp,
|
|
||||||
IconMessageDots
|
|
||||||
} from '@tabler/icons-react';
|
|
||||||
import {
|
import {
|
||||||
BookOpen,
|
BookOpen,
|
||||||
Building2,
|
Building2,
|
||||||
@ -49,8 +45,8 @@ import { index as announcementsRoute } from '@/routes/admin/announcements';
|
|||||||
import { index as feedbackRoute } from '@/routes/admin/feedback';
|
import { index as feedbackRoute } from '@/routes/admin/feedback';
|
||||||
import { index as tuitionInvoicesRoute } from '@/routes/admin/finances/tuition-invoices';
|
import { index as tuitionInvoicesRoute } from '@/routes/admin/finances/tuition-invoices';
|
||||||
import { index as courseClassesRoute } from '@/routes/admin/manage/course-classes';
|
import { index as courseClassesRoute } from '@/routes/admin/manage/course-classes';
|
||||||
import { index as coursesRoute } from '@/routes/admin/manage/courses';
|
|
||||||
import { index as academicTerm } from '@/routes/admin/master/academic-terms';
|
import { index as academicTerm } from '@/routes/admin/master/academic-terms';
|
||||||
|
import { index as coursesRoute } from '@/routes/admin/master/courses';
|
||||||
import { index as departmentsRoute } from '@/routes/admin/master/departments';
|
import { index as departmentsRoute } from '@/routes/admin/master/departments';
|
||||||
import { index as academicAdvisingLogsRoute } from '@/routes/admin/services/academic-advising-logs';
|
import { index as academicAdvisingLogsRoute } from '@/routes/admin/services/academic-advising-logs';
|
||||||
import { index as letterRequestsRoute } from '@/routes/admin/services/letter-requests';
|
import { index as letterRequestsRoute } from '@/routes/admin/services/letter-requests';
|
||||||
@ -104,6 +100,11 @@ const data: {
|
|||||||
url: departmentsRoute.url(),
|
url: departmentsRoute.url(),
|
||||||
icon: Building2,
|
icon: Building2,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Mata Kuliah',
|
||||||
|
url: coursesRoute.url(),
|
||||||
|
icon: BookOpen,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -139,11 +140,6 @@ const data: {
|
|||||||
{
|
{
|
||||||
label: 'Kelola',
|
label: 'Kelola',
|
||||||
items: [
|
items: [
|
||||||
{
|
|
||||||
name: 'Mata Kuliah',
|
|
||||||
url: coursesRoute.url(),
|
|
||||||
icon: BookOpen,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'Kelas Mata Kuliah',
|
name: 'Kelas Mata Kuliah',
|
||||||
url: courseClassesRoute.url(),
|
url: courseClassesRoute.url(),
|
||||||
|
|||||||
@ -25,7 +25,7 @@ import {
|
|||||||
destroy,
|
destroy,
|
||||||
store,
|
store,
|
||||||
update,
|
update,
|
||||||
} from '@/routes/admin/manage/courses';
|
} from '@/routes/admin/master/courses';
|
||||||
import type { Course } from '@/types/course';
|
import type { Course } from '@/types/course';
|
||||||
import { formatDepartmentLabel } from '@/types/department';
|
import { formatDepartmentLabel } from '@/types/department';
|
||||||
import { createCourseColumns } from './columns';
|
import { createCourseColumns } from './columns';
|
||||||
@ -41,15 +41,18 @@ type Props = {
|
|||||||
total: number;
|
total: number;
|
||||||
};
|
};
|
||||||
departments: Department[];
|
departments: Department[];
|
||||||
|
semesterNumbers: number[];
|
||||||
highlight?: number;
|
highlight?: number;
|
||||||
filters: {
|
filters: {
|
||||||
department_id?: string;
|
department_id?: string;
|
||||||
|
semester_number?: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function CourseIndex({
|
export default function CourseIndex({
|
||||||
courses,
|
courses,
|
||||||
departments,
|
departments,
|
||||||
|
semesterNumbers,
|
||||||
highlight,
|
highlight,
|
||||||
filters,
|
filters,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
@ -66,6 +69,14 @@ export default function CourseIndex({
|
|||||||
label: formatDepartmentLabel(department),
|
label: formatDepartmentLabel(department),
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'semester_number',
|
||||||
|
label: 'Semester',
|
||||||
|
options: semesterNumbers.map((semester) => ({
|
||||||
|
value: String(semester),
|
||||||
|
label: String(semester),
|
||||||
|
})),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const pagination: PaginationState = {
|
const pagination: PaginationState = {
|
||||||
@ -12,8 +12,8 @@
|
|||||||
use App\Http\Controllers\Admin\Finances\TuitionPaymentController;
|
use App\Http\Controllers\Admin\Finances\TuitionPaymentController;
|
||||||
use App\Http\Controllers\Admin\Manage\ClassEnrollmentController;
|
use App\Http\Controllers\Admin\Manage\ClassEnrollmentController;
|
||||||
use App\Http\Controllers\Admin\Manage\CourseClassController;
|
use App\Http\Controllers\Admin\Manage\CourseClassController;
|
||||||
use App\Http\Controllers\Admin\Manage\CourseController;
|
|
||||||
use App\Http\Controllers\Admin\Master\AcademicTermController;
|
use App\Http\Controllers\Admin\Master\AcademicTermController;
|
||||||
|
use App\Http\Controllers\Admin\Master\CourseController;
|
||||||
use App\Http\Controllers\Admin\Master\DepartmentController;
|
use App\Http\Controllers\Admin\Master\DepartmentController;
|
||||||
use App\Http\Controllers\Admin\Services\AcademicAdvisingLogController;
|
use App\Http\Controllers\Admin\Services\AcademicAdvisingLogController;
|
||||||
use App\Http\Controllers\Admin\Services\LetterRequestController;
|
use App\Http\Controllers\Admin\Services\LetterRequestController;
|
||||||
@ -29,6 +29,7 @@
|
|||||||
Route::resource('academic-terms', AcademicTermController::class)->except(['create', 'edit', 'show']);
|
Route::resource('academic-terms', AcademicTermController::class)->except(['create', 'edit', 'show']);
|
||||||
Route::patch('academic-terms/{academic_term}/status', [AcademicTermController::class, 'updateStatus'])->name('academic-terms.update_status');
|
Route::patch('academic-terms/{academic_term}/status', [AcademicTermController::class, 'updateStatus'])->name('academic-terms.update_status');
|
||||||
Route::resource('departments', DepartmentController::class)->except(['create', 'edit', 'show']);
|
Route::resource('departments', DepartmentController::class)->except(['create', 'edit', 'show']);
|
||||||
|
Route::resource('courses', CourseController::class)->except(['create', 'edit', 'show']);
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::prefix('admin/academic-classes')->name('admin.academic-classes.')->group(function () {
|
Route::prefix('admin/academic-classes')->name('admin.academic-classes.')->group(function () {
|
||||||
@ -62,7 +63,6 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
Route::prefix('admin/manage')->name('admin.manage.')->group(function () {
|
Route::prefix('admin/manage')->name('admin.manage.')->group(function () {
|
||||||
Route::resource('courses', CourseController::class)->except(['create', 'edit', 'show']);
|
|
||||||
Route::resource('course-classes', CourseClassController::class)->except(['create', 'edit', 'show']);
|
Route::resource('course-classes', CourseClassController::class)->except(['create', 'edit', 'show']);
|
||||||
|
|
||||||
Route::prefix('course-classes/{course_class}/enrollments')->name('course-classes.enrollments.')->group(function () {
|
Route::prefix('course-classes/{course_class}/enrollments')->name('course-classes.enrollments.')->group(function () {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user