Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

JazzMaster's avatar

Booking and making a modal

I have been at this one for quite some time now, and i can't seem to figure out, how to make this work.

I have this code here:

 <button onclick="openForm(event)"
     class="flex justify-center text-center bg-gray-50 h-14 w-full
          {{ $bookings->some(fn($booking) => $booking->isHourBooked($hour->hour)) ? 'bg-red-600 cursor-not-allowed ' : 'bg-white-500' }}}">
          @if($bookings->some(fn($booking) => $booking->isHourBooked($hour->hour)))
                     booked
          @endif
   </button>

What this does, is, if there is an existing booking in the database table, it will make sure, that cursor is not allowed, which is fine. But i want to have my first as clickable, because i want to make that into a modal, where the admin can see relevant information about the specific booking. I feel like i need to compare the bookings (with id and start_time), but since the statement here:

$bookings->some(fn($booking) => $booking->isHourBooked($hour->hour))

Is a boolean, then that is not possible to compare the values. Does anyone have a suggest about how this could be done? It would be neat, if the timeslot where the booking exists could be easily styled (for example if it was a or a ).

0 likes
8 replies
Tray2's avatar

So open the modal on the click event.

 <article class="w-full flex justify-end cursor-pointer" onclick="openModal('#record-edit-modal')">
   <img src="{{ asset('storage/edit.svg') }}"
     alt="Edit Record Information" class="w-6 inline">
 </article>

 <dialog id="record-edit-modal"
            class="p-4 rounded-lg backdrop:bg-gray-500 backdrop:bg-opacity-50 bg-gray-900">
			Modal content goes here.
</dialog>
function getElement(el) {
            return document.querySelector(el);
 }

function openModal(modal) {
            getElement(modal).showModal();
}
 ``
JazzMaster's avatar

I am having difficulty seeing how your suggestion aligns with my goal. My goal is to have the modal appear only on the first time slot, with the rest having the cursor set to 'not-allowed'. Would you maybe clarify?

Tray2's avatar

@JazzMaster You put the onclick on the first item then, or of you use event listeners you add it there.

JazzMaster's avatar

Ah okay, i see. It might be relevant to give you some additional code, because i am not sure that i can just put it on the first item, since it is a loop (so, if i did put it in the loop, it would end up on all of them, which is not ideal). Sorry for not providing this in the first place!

Here is the additional code:

   @foreach($weekdays as $weekday)
            <div class="flex justify-center ">
                <div id="days">
                    {{ $weekday->weekday->format('l jS \ F') }}
                    <div id="day" class="static "> <!-- HERE -->
                        @foreach($weekday->hours as $hour)
                            <div class="block relative timeslot timeslot{{ $hour->hour }} text-center"
                                 data-value="{{ $hour->hour->toDateTimeString() }}">
                                <div class="z-40 grid-cols-1">
                                    <!-- Popup ved første klik skal laves med JS. -->
                                    <button onclick="openForm(event)"
                                            class="flex justify-center text-center bg-gray-50 h-14 w-full
                                            {{ $bookings->some(fn($booking) => $booking->isHourBooked($hour->hour)) ? 'bg-red-600 cursor-not-allowed ' : 'bg-white-500' }}}">
                                        @if($bookings->some(fn($booking) => $booking->isHourBooked($hour->hour)))
                                            booked
                                        @endif
                                    </button>
                                </div>
                                @unless($bookings->some(fn ($booking) => $booking->isHourBooked($hour->hour)))
                                    <x-popupform class="openClose" :user="$user" :hour="$hour"></x-popupform>
                                @endunless
                            </div>
                        @endforeach
                    </div>
                </div>
            </div>
        @endforeach
Tray2's avatar

@JazzMaster In your foreach loop you have access to a $loop object, and from that you can determine which iteration you are on, and just add the code on the first iteration.

@foreach ($users as $user)
    @if ($loop->first)
        This is the first iteration.
    @endif
 
    @if ($loop->last)
        This is the last iteration.
    @endif
 
    <p>This is user {{ $user->id }}</p>
@endforeach 

https://laravel.com/docs/11.x/blade#the-loop-variable

jaseofspades88's avatar

I don't read your question and instantly understand your problem. Is the problem with your inability to do something to the first element of your loop? In this case there is a loop variable available to you in blade and that has a property, first. $loop->first will identify if it's the first iterable. Failing that, @foreach($weekdays as $index => $weekday) would provide you with an index.

JazzMaster's avatar

Okay, so i have been playing around with it, and i still don't get the result. Thank you very much for the already suggested solutions!

It's a little difficult to explain it, without adding a picture, but i'll try anyways. So, right now what i have is, lets say that there is a booking from 10:00 - 12:00 - all the time slots says "booked", so: 08:00 - free 09:00 - free 10:00 - booked <---- This one should have a modal instead of the text booked. 11:00 - booked 12:00 - free 13:00 - free\

What i achieved by adding $loop->first, is, if we say i have a booking again from 10:00 - 12:00, the i get this: 08:00 - free 09:00 - free 10:00 - modal 11:00 - booked 12:00 - free 13:00 - free But if there is a booking, lets say from 16:00 - 18:00

14:00 - free 15:00 - free 16:00 - booked <---- We are back at booked, because it only check the first one. 17:00 - booked 18:00 - free 19:00 - free

I think the problem might be my function here:

  @if($bookings->some(fn($booking) => $booking->isHourBooked($hour->hour)))

This is the isHourBooked function:

public function isHourBooked(Carbon $hour)
{
    return $this->start_time->lessThanOrEqualTo($hour) && $this->end_time->greaterThanOrEqualTo($hour); 
}

So, as we can see, this will return a boolean. I have tried to include the start_time with this function:

public function isHourStartOfBooking(Carbon $hour)
{
    return $this->start_time->eq($hour);
}

And did this in the view:

 @if($bookings->some(fn($booking) => $booking->isHourBooked($hour->hour)))
       booked
  @if($bookings->some(fn($booking) => $booking->isHourStartOfBooking($hour->hour)))
       <p>Hi </p>
   @endif
   @endif

But still no luck.

Edit: I really tried to add some linebreaks (with \ and \n), but i simply can't get it to work.

Tray2's avatar

So basically you need something like this.

@if($timeSlot->status === 'free')
 	<article onclick="openModal(this)">
    	{{ $timeSlot->time }}
	</article>
@else
   <article class="booked">
    	{{ $timeSlot->time }}
   </article>        
@endif

Please or to participate in this conversation.