{{-- Shared Teaching Schedule: actual time position, compact 30-minute grid and separate overlap lanes. --}} @php $scheduleDayRows = $gridRows->filter(function ($item) use ($day) { return strtoupper(trim((string) ($item->timetable_date ?? ''))) === strtoupper($day); })->sortBy(function ($item) use ($timeToMinutes) { return $timeToMinutes($item->timetable_time_start ?? null) ?? PHP_INT_MAX; })->values(); $scheduleSpan = max(1, (int) ($gridEnd - $gridStart)); $scheduleLaneEnds = []; $scheduleEvents = []; foreach ($scheduleDayRows as $scheduleRow) { $actualStart = $timeToMinutes($scheduleRow->timetable_time_start ?? null); $actualEnd = $timeToMinutes($scheduleRow->timetable_time_end ?? null); if ($actualStart === null || $actualEnd === null || $actualEnd <= $actualStart) { continue; } // The coordinate must be the *course's* own start/end, not another course's colspan. $visibleStart = max((int) $gridStart, $actualStart); $visibleEnd = min((int) $gridEnd, $actualEnd); if ($visibleEnd <= $visibleStart) { continue; } // Overlapping courses use separate vertical lanes; nonoverlapping courses reuse lanes. $assignedLane = null; foreach ($scheduleLaneEnds as $laneNumber => $laneEnd) { if ($laneEnd <= $actualStart) { $assignedLane = $laneNumber; break; } } if ($assignedLane === null) { $assignedLane = count($scheduleLaneEnds); } $scheduleLaneEnds[$assignedLane] = $actualEnd; $scheduleEvents[] = [ 'course' => $scheduleRow, 'left' => ($visibleStart - $gridStart) * 100 / $scheduleSpan, 'width' => ($visibleEnd - $visibleStart) * 100 / $scheduleSpan, 'top' => $assignedLane * 130 + 5, ]; } $scheduleTrackHeight = count($scheduleEvents) > 0 ? (count($scheduleLaneEnds) * 130 + 8) : 56; $lunchStart = max((int) $gridStart, 12 * 60); $lunchEnd = min((int) $gridEnd, 13 * 60); $showLunch = $lunchEnd > $lunchStart; $lunchLeft = ($lunchStart - $gridStart) * 100 / $scheduleSpan; $lunchWidth = ($lunchEnd - $lunchStart) * 100 / $scheduleSpan; // Do not allow the lunch label to peek through or overlap the course card. // The real course time is never split: lunch is a visual reference only. $scheduleLunchOccupied = false; if ($showLunch) { foreach ($scheduleEvents as $scheduleEvent) { $eventStart = $timeToMinutes($scheduleEvent['course']->timetable_time_start ?? null); $eventEnd = $timeToMinutes($scheduleEvent['course']->timetable_time_end ?? null); if ($eventStart !== null && $eventEnd !== null && $eventStart < $lunchEnd && $eventEnd > $lunchStart) { $scheduleLunchOccupied = true; break; } } } @endphp {{ $day }}
@if($showLunch)
@if(!$scheduleLunchOccupied) {{-- Inline SVG: always visible even if an icon-font stylesheet is unavailable. --}} Lunch 12:00–13:00 @endif
@endif @foreach($scheduleEvents as $scheduleEvent) @php $class = $scheduleEvent['course']; $courseStartMinutes = $timeToMinutes($class->timetable_time_start ?? null); $courseEndMinutes = $timeToMinutes($class->timetable_time_end ?? null); $overlapsLunch = $showLunch && $courseStartMinutes !== null && $courseEndMinutes !== null && $courseStartMinutes < $lunchEnd && $courseEndMinutes > $lunchStart; @endphp
{{ $class->timetable_course_code }}
{{ $class->timetable_course_name }}
{{ substr((string) $class->timetable_time_start, 0, 5) }}–{{ substr((string) $class->timetable_time_end, 0, 5) }}
@if(!empty($class->timetable_room))
{{ $class->timetable_room }}
@endif
@if(($class->timetable_activity ?? '') === 'Regular Teaching Schedule') Regular @else Extra @endif @if(($class->timetable_teaching_type ?? '') === 'Lecture') Lecture @elseif(($class->timetable_teaching_type ?? '') === 'Laboratory') Laboratory @endif @if(($class->source ?? 'AUTO') === 'MANUAL') MANUAL @endif @if($overlapsLunch) Overlaps Lunch 12:00–13:00 @endif
@endforeach