am trying to include a fullcalendar, to a timetable i developed in the backend with laravel, the data are being fetched but it does not render the timetable content.
i have tried including console debug and try catch to see i can pickup why the content is not rendering on the calendar, here is copy of my code,
@extends('admin.layouts.admin')
@section('title', 'Time Table Calendar')
@section('admin')
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/5.11.5/main.min.css" />
<div class="container">
<div class="card p-3">
<h1>Time Table Calendar</h1>
<div id='calendar'></div>
</div>
</div>
@endsection
@section('javascript')
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/5.11.5/main.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
try {
var calendarEl = document.getElementById('calendar');
// Parse the PHP-encoded JSON data
var timetables = @json($timetables);
console.log('Timetables:', timetables);
// Process timetables into FullCalendar events
var events = timetables.map(function(timetable) {
try {
// Parse start and end times
var startDateTime = new Date(timetable.start_time);
var endDateTime = new Date(timetable.end_time);
// Extract only the time part
var startTime = startDateTime.toTimeString().slice(0, 5);
var endTime = endDateTime.toTimeString().slice(0, 5);
// If end time is earlier than start time, assume it's the next day
if (endDateTime < startDateTime) {
endDateTime.setDate(endDateTime.getDate() + 1);
}
// Calculate duration in minutes
var durationMinutes = (endDateTime - startDateTime) / (1000 * 60);
return {
title: timetable.course.code + ' - ' + timetable.teacher.user.first_name + ' ' +
timetable.teacher.user.last_name,
startTime: startTime,
endTime: endTime,
daysOfWeek: [timetable.day_of_week %
7
], // Ensure it's 0-6 (0 = Sunday, 6 = Saturday)
startRecur: timetable.semester.start_date,
endRecur: timetable.semester.end_date,
duration: {
minutes: durationMinutes
},
extendedProps: {
department: timetable.department.name,
room: timetable.room,
course_name: timetable.course.title,
teacher_name: timetable.teacher.user.first_name + ' ' + timetable.teacher
.user.last_name
},
backgroundColor: getColorForDepartment(timetable.department_id),
borderColor: getColorForDepartment(timetable.department_id)
};
} catch (eventError) {
console.error('Error processing timetable entry:', eventError, timetable);
return null; // Return null for failed entries
}
}).filter(event => event !== null); // Remove any null entries
console.log('Processed events:', events);
var calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'timeGridWeek',
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay'
},
events: events,
slotMinTime: '06:00:00',
slotMaxTime: '24:00:00',
eventClick: function(info) {
alert('Course: ' + info.event.extendedProps.course_name + 'n' +
'Teacher: ' + info.event.extendedProps.teacher_name + 'n' +
'Department: ' + info.event.extendedProps.department + 'n' +
'Room: ' + info.event.extendedProps.room);
}
});
calendar.render();
} catch (error) {
console.error('Error setting up calendar:', error);
// Optionally, display an error message to the user
if (calendarEl) {
calendarEl.innerHTML =
'<p>An error occurred while loading the calendar. Please try refreshing the page.</p>';
}
}
});
function getColorForDepartment(departmentId) {
try {
const colors = [
'#FF5733', '#33FF57', '#3357FF', '#FF33F5', '#33FFF5', '#F5FF33',
'#FF3333', '#33FF33', '#3333FF', '#FF33F5', '#33FFFF', '#FF33FF'
];
return colors[departmentId % colors.length];
} catch (error) {
console.error('Error in getColorForDepartment:', error);
return '#CCCCCC'; // Default color in case of error
}
}
</script>
@endsection
<?php
namespace AppModels;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
class TimeTable extends Model
{
use HasFactory;
const STATUS_DRAFT = 'draft';
const STATUS_PENDING_APPROVAL = 'pending_approval';
const STATUS_APPROVED = 'approved';
const STATUS_ARCHIVED = 'archived';
protected $fillable = [
'academic_session_id',
'semester_id',
'department_id',
'level',
'day_of_week',
'start_time',
'end_time',
'course_id',
'teacher_id',
'room',
'status',
'created_by',
'updated_by',
'class_duration',
'is_current',
'class_date'
];
protected $casts = [
// 'start_time' => 'time',
// 'end_time' => 'time',
'day_of_week' => 'integer',
'level' => 'integer',
'class_duration' => 'integer',
'is_current' => 'boolean',
'start_time' => 'datetime',
'end_time' => 'datetime',
'class_date' => 'date',
];
public function creator()
{
return $this->belongsTo(User::class, 'created_by');
}
public function updater()
{
return $this->belongsTo(User::class, 'updated_by');
}
public function getClassDateAttribute()
{
return $this->attributes['class_date'] ? CarbonCarbon::parse($this->attributes['class_date'])->format('jS F Y') : null;
}
public function getDurationAttribute()
{
return $this->start_time->diffInMinutes($this->end_time);
}
public function getWeeklyHoursAttribute()
{
return $this->duration / 60;
}
public function academicSession()
{
return $this->belongsTo(AcademicSession::class);
}
public function semester()
{
return $this->belongsTo(Semester::class);
}
public function department()
{
return $this->belongsTo(Department::class);
}
public function course()
{
return $this->belongsTo(Course::class);
}
public function teacher()
{
return $this->belongsTo(Teacher::class);
}
public function hasConflict(Timetable $other)
{
return $this->day_of_week === $other->day_of_week &&
$this->start_time < $other->end_time &&
$this->end_time > $other->start_time &&
(($this->room === $other->room) ||
($this->teacher_id === $other->teacher_id) ||
($this->course_id === $other->course_id &&
$this->level === $other->level &&
$this->department_id === $other->department_id));
}
public static function getDayName($day)
{
$days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
return $days[$day - 1] ?? '';
}
public function approver()
{
return $this->belongsTo(User::class, 'approved_by');
}
public function isEditable()
{
return in_array($this->status, [self::STATUS_DRAFT, self::STATUS_PENDING_APPROVAL]);
}
}
public function calendarView()
{
$timetables = TimeTable::with(['course', 'teacher.user', 'department', 'academicSession', 'semester'])
// ->where('status', TimeTable::STATUS_APPROVED)
->get();
return view('admin.timeTable.calender', compact('timetables'));
}