feat: rename 'name' to 'academic_year' in AcademicTerm and related components for consistency
This commit is contained in:
parent
6c55fb5f36
commit
ded7217dbc
@ -16,13 +16,13 @@ public function authorize(): bool
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => [
|
||||
'academic_year' => [
|
||||
'required',
|
||||
'string',
|
||||
'max:20',
|
||||
function ($attribute, $value, $fail) {
|
||||
if (! preg_match('/^(\d{4})\/(\d{4})$/', $value, $matches)) {
|
||||
$fail('Format name harus YYYY/YYYY, contoh: 2025/2026.');
|
||||
$fail('Format tahun ajaran harus YYYY/YYYY, contoh: 2025/2026.');
|
||||
|
||||
return;
|
||||
}
|
||||
@ -40,16 +40,16 @@ function ($attribute, $value, $fail) {
|
||||
'string',
|
||||
Rule::in(Semester::values()),
|
||||
Rule::unique('academic_terms')->where(function ($query) {
|
||||
return $query->where('name', $this->input('name'));
|
||||
return $query->where('academic_year', $this->input('academic_year'));
|
||||
})->ignore($this->route('academic_term')),
|
||||
],
|
||||
'start_date' => [
|
||||
'required',
|
||||
'date',
|
||||
function ($attribute, $value, $fail) {
|
||||
$name = $this->input('name');
|
||||
$academicYear = $this->input('academic_year');
|
||||
$semester = $this->input('semester');
|
||||
if ($name && preg_match('/^(\d{4})\/(\d{4})$/', $name, $matches)) {
|
||||
if ($academicYear && preg_match('/^(\d{4})\/(\d{4})$/', $academicYear, $matches)) {
|
||||
$startYear = (int) $matches[1];
|
||||
$endYear = (int) $matches[2];
|
||||
$dateYear = (int) date('Y', strtotime($value));
|
||||
@ -65,9 +65,9 @@ function ($attribute, $value, $fail) {
|
||||
'date',
|
||||
'after_or_equal:start_date',
|
||||
function ($attribute, $value, $fail) {
|
||||
$name = $this->input('name');
|
||||
$academicYear = $this->input('academic_year');
|
||||
$semester = $this->input('semester');
|
||||
if ($name && preg_match('/^(\d{4})\/(\d{4})$/', $name, $matches)) {
|
||||
if ($academicYear && preg_match('/^(\d{4})\/(\d{4})$/', $academicYear, $matches)) {
|
||||
$startYear = (int) $matches[1];
|
||||
$endYear = (int) $matches[2];
|
||||
$dateYear = (int) date('Y', strtotime($value));
|
||||
|
||||
@ -33,7 +33,7 @@ public function paginated(
|
||||
->select(['id', 'student_id', 'academic_term_id', 'amount_due', 'due_date'])
|
||||
->withSum('payments as paid_total', 'amount_paid')
|
||||
->withCount('payments')
|
||||
->with(['student.user.profile', 'student.department', 'academicTerm:id,name,semester,start_date,end_date'])
|
||||
->with(['student.user.profile', 'student.department', 'academicTerm:id,academic_year,semester,start_date,end_date'])
|
||||
->when($status, fn ($q) => match ($status) {
|
||||
'paid' => $q->havingRaw('COALESCE(paid_total, 0) >= amount_due'),
|
||||
'partial' => $q->havingRaw('COALESCE(paid_total, 0) > 0 AND COALESCE(paid_total, 0) < amount_due'),
|
||||
|
||||
@ -20,7 +20,7 @@ public function paginated(int $perPage = 25, string $search = '', ?int $academic
|
||||
return CourseClass::query()
|
||||
->select(['id', 'course_id', 'lecturer_id', 'academic_term_id', 'method'])
|
||||
->withCount('enrollments')
|
||||
->with(['course:id,code,name,department_id', 'lecturer.user.profile', 'academicTerm:id,name,semester,start_date,end_date'])
|
||||
->with(['course:id,code,name,department_id', 'lecturer.user.profile', 'academicTerm:id,academic_year,semester,start_date,end_date'])
|
||||
->when($search, fn ($q) => $q->whereHas('course', fn ($q) => $q->where('name', 'like', "%{$search}%")->orWhere('code', 'like', "%{$search}%")))
|
||||
->when($academicTermId, fn ($q) => $q->where('academic_term_id', $academicTermId))
|
||||
->when($method, fn ($q) => $q->where('method', $method))
|
||||
|
||||
@ -113,7 +113,7 @@ public function withDetails(CourseRegistrationSubmission $submission): CourseReg
|
||||
'student.user.profile',
|
||||
'student.department.currentLeader.lecturer.user.profile',
|
||||
'student.academicAdvisor.user.profile',
|
||||
'academicTerm:id,name,semester,start_date,end_date',
|
||||
'academicTerm:id,academic_year,semester,start_date,end_date',
|
||||
'reviewer.profile',
|
||||
'courseRegistrations.courseClass.course',
|
||||
'logs' => fn ($q) => $q->oldest(),
|
||||
|
||||
@ -11,7 +11,7 @@ class AcademicTermService
|
||||
{
|
||||
public function getAllForSelect(): Collection
|
||||
{
|
||||
return AcademicTerm::select(['id', 'name', 'semester', 'start_date', 'end_date', 'is_active', 'open_semesters'])->latest()->get();
|
||||
return AcademicTerm::select(['id', 'academic_year', 'semester', 'start_date', 'end_date', 'is_active', 'open_semesters'])->latest()->get();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -27,8 +27,8 @@ public function getActive(): ?AcademicTerm
|
||||
public function paginated(int $perPage = 25, string $search = '', ?string $semester = null, ?bool $isActive = null): LengthAwarePaginator
|
||||
{
|
||||
return AcademicTerm::query()
|
||||
->select(['id', 'name', 'semester', 'start_date', 'end_date', 'is_active', 'open_semesters'])
|
||||
->when($search, fn($q) => $q->where('name', 'like', "%{$search}%"))
|
||||
->select(['id', 'academic_year', 'semester', 'start_date', 'end_date', 'is_active', 'open_semesters'])
|
||||
->when($search, fn($q) => $q->where('academic_year', 'like', "%{$search}%"))
|
||||
->when($semester, fn($q) => $q->where('semester', $semester))
|
||||
->when($isActive !== null, fn($q) => $q->where('is_active', $isActive))
|
||||
->latest()
|
||||
@ -45,7 +45,7 @@ public function create(array $data): AcademicTerm
|
||||
|
||||
public function update(AcademicTerm $academicTerm, array $data): AcademicTerm
|
||||
{
|
||||
$academicTerm->name = $data['name'];
|
||||
$academicTerm->academic_year = $data['academic_year'];
|
||||
$academicTerm->semester = $data['semester'];
|
||||
$academicTerm->start_date = $data['start_date'];
|
||||
$academicTerm->end_date = $data['end_date'];
|
||||
|
||||
@ -11,7 +11,7 @@ public function up(): void
|
||||
{
|
||||
Schema::create('academic_terms', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name', 20);
|
||||
$table->string('academic_year', 20);
|
||||
$table->enum('semester', Semester::values());
|
||||
$table->date('start_date');
|
||||
$table->date('end_date');
|
||||
|
||||
@ -12,7 +12,7 @@ public function run(): void
|
||||
{
|
||||
AcademicTerm::insert([
|
||||
[
|
||||
'name' => '2026/2027',
|
||||
'academic_year' => '2026/2027',
|
||||
'semester' => Semester::odd->value,
|
||||
'start_date' => '2026-08-01',
|
||||
'end_date' => '2027-01-15',
|
||||
@ -21,7 +21,7 @@ public function run(): void
|
||||
'updated_at' => now(),
|
||||
],
|
||||
[
|
||||
'name' => '2026/2027',
|
||||
'academic_year' => '2026/2027',
|
||||
'semester' => Semester::even->value,
|
||||
'start_date' => '2027-02-01',
|
||||
'end_date' => '2027-07-15',
|
||||
|
||||
@ -51,7 +51,7 @@ export function createTuitionInvoiceColumns(
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: 'academic_term.name',
|
||||
accessorKey: 'academic_term.academic_year',
|
||||
header: () => <span>Periode</span>,
|
||||
cell: ({ row }) => {
|
||||
const term = row.original.academic_term;
|
||||
|
||||
@ -69,7 +69,11 @@ import {
|
||||
} from '@/types/tuition-payment';
|
||||
import { createTuitionInvoiceColumns } from './columns';
|
||||
|
||||
type AcademicTermOption = { id: number; name: string; semester: string };
|
||||
type AcademicTermOption = {
|
||||
id: number;
|
||||
academic_year: string;
|
||||
semester: string;
|
||||
};
|
||||
|
||||
type InvoiceSummary = {
|
||||
unpaid_students: number;
|
||||
|
||||
@ -45,7 +45,7 @@ export function createCourseClassColumns(
|
||||
row.original.lecturer?.user?.profile?.full_name ?? '-',
|
||||
},
|
||||
{
|
||||
accessorKey: 'academic_term.name',
|
||||
accessorKey: 'academic_term.academic_year',
|
||||
header: () => <span>Periode</span>,
|
||||
cell: ({ row }) => {
|
||||
const term = row.original.academic_term;
|
||||
|
||||
@ -46,7 +46,11 @@ type Lecturer = {
|
||||
departments: { id: number; name: string }[];
|
||||
user: { profile: { full_name: string } | null } | null;
|
||||
};
|
||||
type AcademicTerm = { id: number; name: string; semester: string };
|
||||
type AcademicTerm = {
|
||||
id: number;
|
||||
academic_year: string;
|
||||
semester: string;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
courseClasses: {
|
||||
|
||||
@ -32,11 +32,11 @@ export function createAcademicTermColumns(
|
||||
|
||||
const columns: ColumnDef<AcademicTerm>[] = [
|
||||
{
|
||||
accessorKey: 'name',
|
||||
header: () => <span>Nama</span>,
|
||||
accessorKey: 'academic_year',
|
||||
header: () => <span>Tahun Ajaran</span>,
|
||||
cell: ({ row }) => (
|
||||
<span className="font-medium">
|
||||
{row.getValue('name') as string}
|
||||
{row.getValue('academic_year') as string}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
|
||||
@ -182,7 +182,7 @@ export default function AcademicTermIndex({
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={academicTerms.data}
|
||||
searchKey="name"
|
||||
searchKey="academic_year"
|
||||
pagination={pagination}
|
||||
onPageChange={handlePageChange}
|
||||
onPerPageChange={handlePerPageChange}
|
||||
@ -206,7 +206,7 @@ export default function AcademicTermIndex({
|
||||
}}
|
||||
title="Hapus Periode Akademik"
|
||||
description={(academicTerm) =>
|
||||
`Apakah Anda yakin ingin menghapus periode akademik "${academicTerm.name}"? Tindakan ini tidak dapat dibatalkan.`
|
||||
`Apakah Anda yakin ingin menghapus periode akademik "${academicTerm.academic_year}"? Tindakan ini tidak dapat dibatalkan.`
|
||||
}
|
||||
onConfirm={handleDelete}
|
||||
/>
|
||||
@ -241,15 +241,16 @@ function CreateForm({
|
||||
{({ errors }) => (
|
||||
<div className="grid gap-4">
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="name">
|
||||
Nama <span className="text-destructive">*</span>
|
||||
<Label htmlFor="academic_year">
|
||||
Tahun Ajaran{' '}
|
||||
<span className="text-destructive">*</span>
|
||||
</Label>
|
||||
<Input
|
||||
id="name"
|
||||
name="name"
|
||||
placeholder="Masukkan nama periode akademik"
|
||||
id="academic_year"
|
||||
name="academic_year"
|
||||
placeholder="Masukkan tahun ajaran, contoh: 2025/2026"
|
||||
/>
|
||||
<InputError message={errors.name} />
|
||||
<InputError message={errors.academic_year} />
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<Label>
|
||||
@ -369,16 +370,17 @@ function EditForm({
|
||||
editing && (
|
||||
<div className="grid gap-4">
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="edit-name">
|
||||
Nama <span className="text-destructive">*</span>
|
||||
<Label htmlFor="edit-academic_year">
|
||||
Tahun Ajaran{' '}
|
||||
<span className="text-destructive">*</span>
|
||||
</Label>
|
||||
<Input
|
||||
id="edit-name"
|
||||
name="name"
|
||||
placeholder="Masukkan nama periode akademik"
|
||||
defaultValue={editing.name}
|
||||
id="edit-academic_year"
|
||||
name="academic_year"
|
||||
placeholder="Masukkan tahun ajaran, contoh: 2025/2026"
|
||||
defaultValue={editing.academic_year}
|
||||
/>
|
||||
<InputError message={errors.name} />
|
||||
<InputError message={errors.academic_year} />
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<Label>
|
||||
|
||||
@ -10,7 +10,7 @@ export const SemesterLabels: Record<Semester, string> = {
|
||||
|
||||
export type AcademicTerm = {
|
||||
id: number;
|
||||
name: string;
|
||||
academic_year: string;
|
||||
semester: Semester;
|
||||
start_date: string;
|
||||
formatted_start_date: string;
|
||||
@ -23,10 +23,10 @@ export type AcademicTerm = {
|
||||
};
|
||||
|
||||
export function formatAcademicTermLabel(term: {
|
||||
name: string;
|
||||
academic_year: string;
|
||||
semester: string;
|
||||
}): string {
|
||||
const label = SemesterLabels[term.semester as Semester];
|
||||
|
||||
return label ? `${term.name} (${label})` : term.name;
|
||||
return label ? `${term.academic_year} (${label})` : term.academic_year;
|
||||
}
|
||||
|
||||
@ -25,7 +25,11 @@ export type CourseClass = {
|
||||
user: { profile: { full_name: string } | null } | null;
|
||||
} | null;
|
||||
academic_term_id: number;
|
||||
academic_term: { id: number; name: string; semester: string } | null;
|
||||
academic_term: {
|
||||
id: number;
|
||||
academic_year: string;
|
||||
semester: string;
|
||||
} | null;
|
||||
method: ClassMethod | null;
|
||||
enrollments_count: number;
|
||||
created_at: string;
|
||||
|
||||
@ -82,7 +82,11 @@ export type CourseRegistrationSubmission = {
|
||||
advisor_signature_url: string | null;
|
||||
has_registrations: boolean;
|
||||
student: CourseRegistrationSubmissionStudent | null;
|
||||
academic_term: { id: number; name: string; semester: string } | null;
|
||||
academic_term: {
|
||||
id: number;
|
||||
academic_year: string;
|
||||
semester: string;
|
||||
} | null;
|
||||
course_registrations: CourseRegistrationSubmissionEntry[];
|
||||
logs: CourseRegistrationSubmissionLog[];
|
||||
};
|
||||
|
||||
@ -11,7 +11,11 @@ export type TuitionInvoice = {
|
||||
student_id: number;
|
||||
student: TuitionInvoiceStudent | null;
|
||||
academic_term_id: number;
|
||||
academic_term: { id: number; name: string; semester: string } | null;
|
||||
academic_term: {
|
||||
id: number;
|
||||
academic_year: string;
|
||||
semester: string;
|
||||
} | null;
|
||||
amount_due: string;
|
||||
due_date: string | null;
|
||||
paid_total: string | null;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user