Ad

Laravel Calendar Of Absences Problem With Displaying In Table

- 1 answer

I wanted to create team calendar of absences. Each user can define more than one absence in specific month.

Then I want to print it for each in table like this (example for 10 days):

Day   | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
-----------------------------------------------|
User1 | o | o | x | x | x | x | o | o | o | x  |
-----------------------------------------------|
User2 | x | o | o | o | x | x | o | x | o | x  |
-----------------------------------------------|

Where the "o" is for normal day and "x" is defined as absence.

I got Users table and Absences table:

Users
id | name 

Absences
id | user_id | start | end

I get the current month day value and iterate through all Users and then through the days in blade like that:

@foreach ($users as $user )
   <tr>
      <td> {{ $user->name }} </td>
   @if($user->absences != null)
      @foreach($days as $day)
         @foreach ($user->absences as $absence)
           @if($day >= $absence->start->format('d') && $day <= $absence->end->format('d'))
              <td style="background: red"> x </td>
           @else
              <td style="background: blue"> o </td>
           @endif
         @endforeach
       @endforeach
    @endif
  </tr>
@endforeach

The problem is that, If user have more than one absence defined, the days in his column are doubled and whole table is being crashed. When User has only 1 absence, it works OK.

Do you have any idea how do achieve that easier?

Ad

Answer

Your problem lies in @foreach ($user->absences as $absence) loop. You're checking all the absences for one day.

Instead, you should use a function to get all the absense days of users. I think keeping such functionality in controller is a better idea.

$users = $users->map(function ($user) {
    $user['absenseDays'] = $user->absences->reduce(function ($carry, $item) {
        return [...$carry, ...range($item['start'], $item['end'])];
    }, []);
    return $user;
});

This should create a new entry of absenseDays on each user, and the values should be an array of absense days. Let's say a user has 2 records 5-8 and 12-14, absenseDays should be [5,6,7,8,12,13,14].

In blade you need only:

@if (in_array($day, $user->absenseDays))
    <td style="background: red"> x </td>
@else
    <td style="background: blue"> o </td>
@endif

I wrote the function here directly. So it might not work, or can be a better way to produce the same output. But I can say that for sure, producing absenseDays array is the best approach that I can come up with.

Ad
source: stackoverflow.com
Ad