[ '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.'); return; } $startYear = (int) $matches[1]; $endYear = (int) $matches[2]; if ($endYear !== $startYear + 1) { $fail('Tahun kedua harus selisih 1 tahun dari tahun pertama. Contoh: 2025/2026, 2026/2027.'); } }, ], 'semester' => [ 'required', 'string', Rule::in(Semester::values()), Rule::unique('academic_terms')->where(function ($query) { return $query->where('name', $this->input('name')); })->ignore($this->route('academic_term')), ], 'start_date' => [ 'required', 'date', function ($attribute, $value, $fail) { $name = $this->input('name'); $semester = $this->input('semester'); if ($name && preg_match('/^(\d{4})\/(\d{4})$/', $name, $matches)) { $startYear = (int) $matches[1]; $endYear = (int) $matches[2]; $dateYear = (int) date('Y', strtotime($value)); $expectedYear = $semester === 'even' ? $endYear : $startYear; if ($dateYear !== $expectedYear) { $fail('Start date harus berada di tahun '.$expectedYear.' untuk semester '.($semester === 'even' ? 'Genap' : 'Ganjil').'.'); } } }, ], 'end_date' => [ 'required', 'date', 'after_or_equal:start_date', function ($attribute, $value, $fail) { $name = $this->input('name'); $semester = $this->input('semester'); if ($name && preg_match('/^(\d{4})\/(\d{4})$/', $name, $matches)) { $startYear = (int) $matches[1]; $endYear = (int) $matches[2]; $dateYear = (int) date('Y', strtotime($value)); $expectedYear = $semester === 'even' ? $endYear : $startYear; if ($dateYear !== $expectedYear) { $fail('End date harus berada di tahun '.$expectedYear.' untuk semester '.($semester === 'even' ? 'Genap' : 'Ganjil').'.'); } } }, ], 'is_active' => ['boolean'], ]; } }