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

hjortur17's avatar

Redirect back from PUT

I am struggling to redirect to some route from PUT request or send some data back. I am basically trying to redirect back to the route and with flash message.

This is how I am trying to redirect back

return redirect('/edit/' . $booking->id)->with('success', 'Booking updated!');

Any idea how I can redirect back to the edit page after editing the booking (after PUT) or do this ->with('success', 'Booking updated!'); another way?

0 likes
31 replies
Sinnbeck's avatar

You can do

return redirect()->back()->with('success', 'Booking updated!');
//or 
return back()->with('success', 'Booking updated!');  
hjortur17's avatar

The issue I get when trying to redirect like this is this:

"The PUT method is not supported for this route. Supported methods: GET, HEAD."

But my routes are like this:

// web.php
// The route which displays the form
Route::prefix('dashboard')->group(function () {
        Route::prefix('reservations')->group(function () {
            Route::get('/edit/{booking:id}', [ReservationController::class, 'show'])->name('edit.booking');
			...
			...
        });
    });
// api.php
// The route which handles the form and updates the booking
Route::controller(BookingController::class)->group(function () {
    Route::patch('/booking/edit', 'edit');
    ...
    ...
    ...
});
hjortur17's avatar

@jlrdw - I would just prefer to use the route that I have already created

sos99's avatar

I don't know.

Did you try to clear the cache?

php artisan optimize:clear
hjortur17's avatar

Still getting 405 - The PUT method is not supported for this route. Supported methods: GET, HEAD.

hjortur17's avatar

So if I check the network tab, First I get 302 code, and then 405 - The PUT method is not supported for this route. Supported methods: GET, HEAD.

Any idea why it isn't allowing me to redirect after updating the booking?

If it helps, I use axios to send the put request. But all my frontend is Inertia and the backend Laravel

jlrdw's avatar

@hjortur17 with Ajax you haven't left the page so just show the message there and include a link for a page to go to after user sees the update was successful.

hjortur17's avatar

Do you guys have any solution? I was trying to use this.$inertia.put('/api/booking/update', this.updatedBooking);. Like the do in their demo, but no luck. Still same error, does the URL have to be the same to be able to use redirect?

Sinnbeck's avatar

@hjortur17 oh its inertia. Didn't notice any mention of this earlier. Inertia is an exception. That should work. Show the routes

1 like
hjortur17's avatar

@Sinnbeck - Here are my routes:

// api.php
Route::controller(BookingController::class)->group(function () {
    Route::post('/book/process', 'store');
    Route::put('/booking/update', 'update');
    Route::patch('/booking/edit', 'edit');
    Route::patch('/booking/cancel', 'destroy');
});
// web.php
Route::middleware(['auth', 'can:admin'])->group(function () {
    Route::prefix('dashboard')->group(function () {
         Route::prefix('reservations')->group(function () {
            Route::get('/pickup', [ReservationController::class, 'pickup']);
            Route::get('/dropoff', [ReservationController::class, 'dropoff']);
            Route::get('/edit/{booking:id}', [ReservationController::class, 'show'])->name('edit.booking');
        });
    });
});
hjortur17's avatar

So I have the route that handles the form stored in api.php, but the route that displays it is stored in web.php

hjortur17's avatar

@Snapey - Nope, just a single page (form) including all information about the booking. And in that form the admin can update some details and press a button to submit thoose changes and that is the PUT request

Sinnbeck's avatar

@hjortur17 I cannot recreate the problem. Show the form in vue/react please. And the full controller method

hjortur17's avatar

@Sinnbeck - Okay,

Here is the controller:

public function update(Request $request)
    {
        $booking = Booking::where('uuid', $request->uuid)->firstOrFail();

        $booking->pick_up_date = Carbon::parse($request->pick_up_date)->format('d/m/Y');
        $booking->pick_up_time = $request->pick_up_time;
        $booking->drop_off_date = Carbon::parse($request->drop_off_date)->format('d/m/Y');
        $booking->drop_off_time = $request->drop_off_time;

        // Updating additional information
        $booking->additional_pick_up_time = $request->additional_pick_up_time;
        $booking->additional_drop_off_time = $request->additional_drop_off_time;
        $booking->additional_flight_no = $request->additional_flight_no;
        $booking->additional_nr_of_pax = $request->additional_nr_of_pax;

        $booking->customer()->update($request->customer);

        $booking->carClass()->sync([CarClass::where('uuid', $request->carClass['uuid'])->firstOrFail()->id]);
        $booking->car()->sync([Car::where('uuid', $request->car['uuid'])->firstOrFail()->id]);

        foreach ($request->drivers as $driver) {
            $booking->drivers()->update($driver);
        }

        // Update Packages
        $arrayToBySynced = [];
        foreach ($request->packages as $package) {
            $arrayToBySynced[] = $package['id'];
        }

        $booking->packages()->sync($arrayToBySynced);

        // Update Insurance
        $arrayToBySynced = [];
        foreach ($request->insurances as $insurance) {
            $arrayToBySynced[] = $insurance['id'];
        }

        $booking->insurances()->sync($arrayToBySynced);

        // Update Extras
        $arrayToBySynced = [];
        foreach ($request->extras as $exrra) {
            $arrayToBySynced[] = $exrra['id'];
        }

        $booking->extras()->sync($arrayToBySynced);

        $booking->save();

        return Redirect::back()->with('success', 'Booking updated.');

//        return Redirect::route('edit.booking', [$booking])->with('success', 'Sucess message');
    }

And here is the form:

<template>
    <Head :title="'Booking #' + booking.id" />
    <div class="mb-6 flex w-full items-center justify-between">
        <div class="flex items-center space-x-6">
            <h2>Booking #{{ booking.id }}</h2>

            <p
                class="text-sm text-neutral-400"
                v-if="updatedBooking.status !== 'Created'"
            >
                This booking has been
                <span v-if="updatedBooking.status === 'Rented'">rented.</span>
                <span v-if="updatedBooking.status === 'Returned'">closed.</span>
                <span v-if="updatedBooking.status === 'Cancelled'">cancelled.</span>
            </p>
        </div>

        <div class="flex space-x-4">
            <button
                class="mx-auto h-10 w-10 cursor-pointer rounded-full bg-red-200 p-2.5 text-red-900 duration-150 ease-in-out hover:bg-red-400 hover:text-red-50"
                @click="cancelBooking($event)"
                v-if="
                    updatedBooking.status !== 'Rented' ||
                    updatedBooking.status !== 'Returned' ||
                    updatedBooking.status !== 'Cancelled'
                "
                title="Cancel booking"
            >
                <svg
                    xmlns="http://www.w3.org/2000/svg"
                    viewBox="0 0 320 512"
                    class="h-full w-full fill-current"
                >
                    <!-- Font Awesome Pro 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
                    <path
                        d="M193.94 256L296.5 153.44l21.15-21.15c3.12-3.12 3.12-8.19 0-11.31l-22.63-22.63c-3.12-3.12-8.19-3.12-11.31 0L160 222.06 36.29 98.34c-3.12-3.12-8.19-3.12-11.31 0L2.34 120.97c-3.12 3.12-3.12 8.19 0 11.31L126.06 256 2.34 379.71c-3.12 3.12-3.12 8.19 0 11.31l22.63 22.63c3.12 3.12 8.19 3.12 11.31 0L160 289.94 262.56 392.5l21.15 21.15c3.12 3.12 8.19 3.12 11.31 0l22.63-22.63c3.12-3.12 3.12-8.19 0-11.31L193.94 256z"
                    />
                </svg>
            </button>

            <button
                class="mx-auto h-10 w-10 cursor-pointer rounded-full bg-indigo-200 p-2.5 text-indigo-900 duration-150 ease-in-out hover:bg-indigo-400 hover:text-indigo-50"
                @click="editBooking($event, 'end')"
                v-if="updatedBooking.status === 'Rented'"
                title="End rental"
            >
                <svg
                    xmlns="http://www.w3.org/2000/svg"
                    viewBox="0 0 384 512"
                    class="h-full w-full fill-current"
                >
                    <!-- Font Awesome Pro 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
                    <path
                        d="M349.5 475.5l-211.1-211c-4.7-4.7-4.7-12.3 0-17l211.1-211c4.7-4.7 12.3-4.7 17 0l7.1 7.1c4.7 4.7 4.7 12.3 0 17L178.1 256l195.5 195.5c4.7 4.7 4.7 12.3 0 17l-7.1 7.1c-4.7 4.6-12.3 4.6-17-.1zm-111 0l7.1-7.1c4.7-4.7 4.7-12.3 0-17L50.1 256 245.5 60.5c4.7-4.7 4.7-12.3 0-17l-7.1-7.1c-4.7-4.7-12.3-4.7-17 0l-211.1 211c-4.7 4.7-4.7 12.3 0 17l211.1 211c4.8 4.8 12.4 4.8 17.1.1z"
                    />
                </svg>
            </button>

            <button
                class="mx-auto h-10 w-10 cursor-pointer rounded-full bg-green-200 p-2.5 text-green-900 duration-150 ease-in-out hover:bg-green-400 hover:text-green-50"
                @click="editBooking($event, 'start')"
                v-if="updatedBooking.status === 'Created'"
                title="Start rental"
            >
                <svg
                    xmlns="http://www.w3.org/2000/svg"
                    viewBox="0 0 384 512"
                    class="h-full w-full fill-current"
                >
                    <!-- Font Awesome Pro 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
                    <path
                        d="M34.5 36.5l211.1 211c4.7 4.7 4.7 12.3 0 17l-211.1 211c-4.7 4.7-12.3 4.7-17 0l-7.1-7.1c-4.7-4.7-4.7-12.3 0-17L205.9 256 10.5 60.5c-4.7-4.7-4.7-12.3 0-17l7.1-7.1c4.6-4.6 12.2-4.6 16.9.1zm111 0l-7.1 7.1c-4.7 4.7-4.7 12.3 0 17L333.9 256 138.5 451.5c-4.7 4.7-4.7 12.3 0 17l7.1 7.1c4.7 4.7 12.3 4.7 17 0l211.1-211c4.7-4.7 4.7-12.3 0-17l-211.1-211c-4.8-4.8-12.4-4.8-17.1-.1z"
                    />
                </svg>
            </button>

            <button
                class="mx-auto h-10 w-10 cursor-pointer rounded-full bg-sky-200 p-2.5 text-sky-900 duration-150 ease-in-out hover:bg-sky-400 hover:text-sky-50"
                @click="updateBooking($event)"
                title="Save booking"
            >
                <svg
                    xmlns="http://www.w3.org/2000/svg"
                    viewBox="0 0 448 512"
                    class="h-full w-full fill-current"
                >
                    <!-- Font Awesome Pro 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
                    <path
                        d="M433.941 129.941l-83.882-83.882A48 48 0 0 0 316.118 32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h352c26.51 0 48-21.49 48-48V163.882a48 48 0 0 0-14.059-33.941zM288 64v96H96V64h192zm128 368c0 8.822-7.178 16-16 16H48c-8.822 0-16-7.178-16-16V80c0-8.822 7.178-16 16-16h16v104c0 13.255 10.745 24 24 24h208c13.255 0 24-10.745 24-24V64.491a15.888 15.888 0 0 1 7.432 4.195l83.882 83.882A15.895 15.895 0 0 1 416 163.882V432zM224 232c-48.523 0-88 39.477-88 88s39.477 88 88 88 88-39.477 88-88-39.477-88-88-88zm0 144c-30.879 0-56-25.121-56-56s25.121-56 56-56 56 25.121 56 56-25.121 56-56 56z"
                    />
                </svg>
            </button>

            <button
                class="mx-auto h-10 w-10 cursor-pointer rounded-full bg-pink-200 p-2.5 text-pink-900 duration-150 ease-in-out hover:bg-pink-400 hover:text-pink-50"
                @click="sendRentalAgreement()"
                title="Send Rental Agreement"
            >
                <svg
                    xmlns="http://www.w3.org/2000/svg"
                    viewBox="0 0 512 512"
                    class="h-full w-full fill-current"
                >
                    <!-- Font Awesome Pro 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
                    <path
                        d="M149.106 512c-33.076 0-66.153-12.59-91.333-37.771-50.364-50.361-50.364-132.305-.002-182.665L319.842 29.498c39.331-39.331 103.328-39.331 142.66 0 39.331 39.332 39.331 103.327 0 142.657l-222.63 222.626c-28.297 28.301-74.347 28.303-102.65 0-28.3-28.301-28.3-74.349 0-102.649l170.301-170.298c4.686-4.686 12.284-4.686 16.97 0l5.661 5.661c4.686 4.686 4.686 12.284 0 16.971l-170.3 170.297c-15.821 15.821-15.821 41.563.001 57.385 15.821 15.82 41.564 15.82 57.385 0l222.63-222.626c26.851-26.851 26.851-70.541 0-97.394-26.855-26.851-70.544-26.849-97.395 0L80.404 314.196c-37.882 37.882-37.882 99.519 0 137.401 37.884 37.881 99.523 37.882 137.404.001l217.743-217.739c4.686-4.686 12.284-4.686 16.97 0l5.661 5.661c4.686 4.686 4.686 12.284 0 16.971L240.44 474.229C215.26 499.41 182.183 512 149.106 512z"
                    />
                </svg>
            </button>
        </div>
    </div>

    <div class="space-y-8">
        <div class="rounded-lg border-2 border-neutral-100 bg-white">
            <div
                class="w-full border-b-2 border-neutral-100 bg-neutral-100 px-8 py-3"
            >
                <h5 class="text-neutral-800">Order information</h5>
            </div>
            <div class="flex w-full items-end space-x-4 p-8">
                <div class="flex w-1/3 flex-col">
                    <label
                        for="vehicle_class"
                        class="mb-2 block text-sm font-black uppercase text-gray-900 dark:text-gray-400"
                        >Class</label
                    >
                    <select
                        id="vehicle_class"
                        class="min-w-full rounded-lg border bg-white p-2 focus:border-blue-400"
                        v-model="updatedBooking.carClass"
                    >
                        <option>Choose a class</option>
                        <option v-for="vc in vehicleClasses" :value="vc">
                            {{ vc.title }}
                        </option>
                    </select>
                </div>
                <div class="flex w-1/3 flex-col">
                    <label
                        for="vehicle_class"
                        class="mb-2 block text-sm font-black uppercase text-gray-900 dark:text-gray-400"
                        >Unit</label
                    >
                    <select
                        id="vehicle_class"
                        class="min-w-full rounded-lg border bg-white p-2 focus:border-blue-400"
                        v-model="updatedBooking.car"
                    >
                        <option value="Choose a unit">Choose a unit</option>
                        <option v-for="car in units" :value="car">
                            {{ car.license_plate }} - {{ car.make }}
                            {{ car.model }}
                        </option>
                    </select>
                </div>

                <div class="flex w-auto flex-col">
                    <label
                        for="booking_type"
                        class="mb-2 block text-sm font-black uppercase text-gray-900 dark:text-gray-400"
                        >Booking Type</label
                    >
                    <select
                        id="booking_type"
                        class="min-w-full rounded-lg border bg-white p-2 focus:border-blue-400"
                    >
                        <option
                            v-for="type in booking_type"
                            :selected="type === booking.booking_type"
                        >
                            {{ type }}
                        </option>
                    </select>
                </div>

                <div class="flex w-52 flex-col">
                    <label
                        for="ref_id"
                        class="mb-2 block text-sm font-black uppercase text-gray-900 dark:text-gray-400"
                        >Reference Id</label
                    >

                    <input
                        type="text"
                        id="ref_id"
                        class="min-w-full rounded-lg border bg-white p-2 outline-none focus:border-blue-400"
                        :value="booking.random_key"
                    />
                </div>

                <div class="flex w-24 flex-col">
                    <label
                        for="acriss"
                        class="mb-2 block text-sm font-black uppercase text-gray-900 dark:text-gray-400"
                        >ACRISS</label
                    >

                    <input
                        type="text"
                        id="acriss"
                        class="w-full rounded-lg border bg-white p-2 outline-none focus:border-blue-400"
                        value=""
                    />
                </div>
            </div>
        </div>

        <div class="rounded-lg border-2 border-neutral-100 bg-white">
            <div
                class="w-full border-b-2 border-neutral-100 bg-neutral-100 px-8 py-3"
            >
                <h5 class="text-neutral-800">Date information</h5>
            </div>
            <div class="flex w-full flex-col space-y-4 p-8">
                <div class="flex w-full items-center space-x-6">
                    <div class="w-48 text-right">
                        <h5
                            class="text-sm font-medium uppercase text-neutral-600"
                        >
                            Pick Up
                        </h5>
                    </div>
                    <div class="flex w-full space-x-4">
                        <div class="w-auto">
                            <datepicker
                                class="w-auto rounded-lg border bg-white p-2 focus:border-blue-400"
                                v-model="updatedBooking.pick_up_date"
                                :lowerLimit="new Date()"
                                inputFormat="dd/MM/yyyy"
                            />
                        </div>
                        <div class="w-32">
                            <TimeDropdown
                                class="min-w-full rounded-lg border bg-white p-2 focus:border-blue-400"
                                name="pick_up_time"
                                label="pick-up-time"
                                v-model="updatedBooking.pick_up_time"
                            />
                        </div>
                    </div>
                </div>
                <div class="flex w-full items-center space-x-6">
                    <div class="w-48 text-right">
                        <h5
                            class="text-sm font-medium uppercase text-neutral-600"
                        >
                            Drop Off
                        </h5>
                    </div>
                    <div class="flex w-full space-x-4">
                        <div class="w-auto">
                            <datepicker
                                class="w-auto rounded-lg border bg-white p-2 focus:border-blue-400"
                                v-model="updatedBooking.drop_off_date"
                                :lowerLimit="minDay"
                                inputFormat="dd/MM/yyyy"
                            />
                        </div>
                        <div class="w-32">
                            <TimeDropdown
                                class="min-w-full rounded-lg border bg-white p-2 focus:border-blue-400"
                                name="drop_off_time"
                                label="drop-off-time"
                                v-model="updatedBooking.drop_off_time"
                            />
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="rounded-lg border-2 border-neutral-100 bg-white">
            <div
                class="w-full border-b-2 border-neutral-100 bg-neutral-100 px-8 py-3"
            >
                <h5 class="text-neutral-800">Insurances and Extras</h5>
            </div>
            <div class="flex w-full flex-col space-y-4 p-8">
                <div class="flex w-full items-center space-x-6">
                    <div class="w-48 text-right">
                        <h5
                            class="text-sm font-medium uppercase text-neutral-600"
                        >
                            Packages
                        </h5>
                    </div>
                    <div class="flex w-full space-x-4">
                        <div class="w-auto" v-for="pack in packages">
                            <label class="block">
                                <input
                                    class="mr-2 leading-tight"
                                    type="checkbox"
                                    :aria-label="pack.title"
                                    :value="{ id: pack.id, title: pack.title }"
                                    v-model="updatedBooking.packages"
                                    @change="
                                        recalculatePrice(
                                            pack.title,
                                            pack.price_per_day
                                        )
                                    "
                                />
                                <span>{{ pack.title }}</span>
                            </label>
                        </div>
                    </div>
                </div>
                <div class="flex w-full items-center space-x-6">
                    <div class="w-48 text-right">
                        <h5
                            class="text-sm font-medium uppercase text-neutral-600"
                        >
                            Insurances
                        </h5>
                    </div>
                    <div class="flex w-full space-x-4">
                        <div class="w-auto" v-for="insurance in insurances">
                            <label class="block">
                                <input
                                    class="mr-2 leading-tight"
                                    type="checkbox"
                                    :aria-label="insurance.title"
                                    :value="{
                                        id: insurance.id,
                                        title: insurance.title,
                                    }"
                                    v-model="updatedBooking.insurances"
                                    @change="
                                        recalculatePrice(
                                            insurance.title,
                                            insurance.price_per_day
                                        )
                                    "
                                />
                                <span>{{ insurance.title }}</span>
                            </label>
                        </div>
                    </div>
                </div>
                <div class="flex w-full items-center space-x-6">
                    <div class="w-48 text-right">
                        <h5
                            class="text-sm font-medium uppercase text-neutral-600"
                        >
                            Extras
                        </h5>
                    </div>
                    <div class="flex w-full space-x-4">
                        <div class="w-auto" v-for="extra in extras">
                            <label class="block">
                                <input
                                    class="mr-2 leading-tight"
                                    type="checkbox"
                                    :aria-label="extra.title"
                                    :value="{
                                        id: extra.id,
                                        title: extra.title,
                                    }"
                                    v-model="updatedBooking.extras"
                                    @change="
                                        recalculatePrice(
                                            extra.title,
                                            extra.price_per_day
                                        )
                                    "
                                />
                                <span>{{ extra.title }}</span>
                            </label>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="rounded-lg border-2 border-neutral-100 bg-white">
            <div
                class="w-full border-b-2 border-neutral-100 bg-neutral-100 px-8 py-3"
            >
                <h5 class="text-neutral-800">Prices</h5>
            </div>
            <div class="flex w-full flex-col space-y-4 p-8">
                <table class="w-full table-auto">
                    <thead
                        class="border-b border-neutral-200 bg-transparent text-xs font-semibold uppercase text-neutral-900"
                    >
                        <tr>
                            <th></th>
                            <th class="p-2">
                                <div class="text-right">Price</div>
                            </th>
                            <th class="p-2">
                                <div class="text-right font-semibold">
                                    Discount
                                </div>
                            </th>
                            <th class="p-2">
                                <div class="text-right font-semibold">
                                    Price Per Day
                                </div>
                            </th>
                            <th class="p-2">
                                <div class="text-right font-semibold">
                                    Total
                                </div>
                            </th>
                        </tr>
                    </thead>

                    <tbody class="border border-neutral-200 text-sm">
                        <tr
                            class="border-b border-neutral-200 odd:bg-neutral-50"
                            v-for="(data, index) in JSON.parse(
                                updatedBooking.price.data
                            )"
                        >
                            <td class="p-2">
                                <div class="font-bold text-gray-800">
                                    {{ data.title }}
                                </div>
                            </td>
                            <td class="p-2">
                                <div class="text-right">
                                    {{ parseFloat(data.price) }} kr
                                </div>
                            </td>
                            <td class="p-2">
                                <div class="text-right font-medium">
                                    <input
                                        type="number"
                                        :value="data.discount"
                                        :disabled="!changePrice"
                                        min="0"
                                        max="100"
                                        @change="
                                            manuallyChangePrice(
                                                data.title,
                                                $event.target.value,
                                                data.price_per_day
                                            )
                                        "
                                        class="w-12 border border-blue-400 bg-white text-right outline-none disabled:border-0 disabled:bg-transparent"
                                    />%
                                </div>
                            </td>
                            <td class="p-2">
                                <div class="text-right font-medium">
                                    <input
                                        type="number"
                                        :value="parseFloat(data.price_per_day)"
                                        :disabled="!changePrice"
                                        @change="
                                            manuallyChangePrice(
                                                data.title,
                                                data.discount,
                                                $event.target.value
                                            )
                                        "
                                        class="w-20 border border-blue-400 bg-white text-right outline-none disabled:border-0 disabled:bg-transparent"
                                    />
                                    kr
                                </div>
                            </td>
                            <td class="p-2">
                                <div class="text-right font-medium">
                                    {{
                                        data.discount
                                            ? parseFloat(
                                                  data.price -
                                                      data.price *
                                                          (data.discount / 100)
                                              )
                                            : data.price
                                    }}
                                    kr
                                </div>
                            </td>
                        </tr>
                    </tbody>
                </table>

                <div class="flex items-start justify-between">
                    <div class="flex flex-1">
                        <label class="block">
                            <input
                                class="mr-2 leading-tight"
                                type="checkbox"
                                v-model="changePrice"
                                aria-label="Manually change price"
                            />
                            <span> Manually change price </span>
                        </label>
                    </div>
                    <div class="flex max-w-max flex-col">
                        <div class="flex w-64 items-center justify-end">
                            <div class="w-1/2 text-right text-sm">
                                <strong class="uppercase">Total:</strong>
                            </div>
                            <div class="w-5/12 text-right">
                                <p>
                                    {{
                                        parseFloat(
                                            updatedBooking.price.total_price
                                        )
                                    }}
                                    kr
                                </p>
                            </div>
                        </div>
                        <div class="flex w-64 items-center justify-end">
                            <div class="w-1/2 text-right text-sm">
                                <strong class="uppercase">Total paid:</strong>
                            </div>
                            <div class="w-5/12 text-right">
                                <p>
                                    {{
                                        parseFloat(
                                            updatedBooking.price.total_paid
                                        )
                                    }}
                                    kr
                                </p>
                            </div>
                        </div>
                        <div class="flex w-64 items-center justify-end">
                            <div class="w-1/2 text-right text-sm">
                                <strong class="uppercase"
                                    >Total balance:</strong
                                >
                            </div>
                            <div class="w-5/12 text-right">
                                <p>
                                    {{
                                        parseFloat(
                                            updatedBooking.price.total_balance
                                        )
                                    }}
                                    kr
                                </p>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="rounded-lg border-2 border-neutral-100 bg-white">
            <div
                class="w-full border-b-2 border-neutral-100 bg-neutral-100 px-8 py-3"
            >
                <h5 class="text-neutral-800">Customer Information</h5>
            </div>
            <div class="flex w-full flex-col space-y-4 p-8">
                <div class="flex w-full items-center space-x-6">
                    <div class="w-48 text-right">
                        <h5
                            class="text-sm font-medium uppercase text-neutral-600"
                        >
                            Full Name
                        </h5>
                    </div>
                    <div class="flex w-full space-x-4">
                        <div class="w-1/2">
                            <input
                                type="text"
                                name="full_name"
                                class="w-auto rounded-lg border bg-white p-2 focus:border-blue-400"
                                v-model="updatedBooking.customer.full_name"
                            />
                        </div>
                    </div>
                </div>
                <div class="flex w-full items-center space-x-6">
                    <div class="w-48 text-right">
                        <h5
                            class="text-sm font-medium uppercase text-neutral-600"
                        >
                            Email
                        </h5>
                    </div>
                    <div class="flex w-full space-x-4">
                        <div class="w-1/2">
                            <input
                                type="email"
                                name="email"
                                class="w-auto rounded-lg border bg-white p-2 focus:border-blue-400"
                                v-model="updatedBooking.customer.email_address"
                            />
                        </div>
                    </div>
                </div>
                <div class="flex w-full items-center space-x-6">
                    <div class="w-48 text-right">
                        <h5
                            class="text-sm font-medium uppercase text-neutral-600"
                        >
                            Phone
                        </h5>
                    </div>
                    <div class="flex w-full space-x-4">
                        <div class="w-1/2">
                            <input
                                type="tel"
                                name="phone"
                                class="w-auto rounded-lg border bg-white p-2 focus:border-blue-400"
                                v-model="updatedBooking.customer.phone_number"
                            />
                        </div>
                    </div>
                </div>
                <div class="flex w-full items-center space-x-6">
                    <div class="w-48 text-right">
                        <h5
                            class="text-sm font-medium uppercase text-neutral-600"
                        >
                            Street Address
                        </h5>
                    </div>
                    <div class="flex w-full space-x-4">
                        <div class="w-1/2">
                            <input
                                type="text"
                                name="streeet_address"
                                class="w-auto rounded-lg border bg-white p-2 focus:border-blue-400"
                                v-model="updatedBooking.customer.street_address"
                            />
                        </div>
                    </div>
                </div>

                <div class="flex w-full items-center space-x-6">
                    <div class="w-48 text-right">
                        <h5
                            class="text-sm font-medium uppercase text-neutral-600"
                        >
                            Town
                        </h5>
                    </div>
                    <div class="flex w-full space-x-4">
                        <div class="w-1/2">
                            <input
                                type="text"
                                name="town"
                                class="w-auto rounded-lg border bg-white p-2 focus:border-blue-400"
                                v-model="updatedBooking.customer.town"
                            />
                        </div>
                    </div>
                </div>

                <div class="flex w-full items-center space-x-6">
                    <div class="w-48 text-right">
                        <h5
                            class="text-sm font-medium uppercase text-neutral-600"
                        >
                            ZIP Code
                        </h5>
                    </div>
                    <div class="flex w-full space-x-4">
                        <div class="w-1/2">
                            <input
                                type="text"
                                name="zip_code"
                                class="w-auto rounded-lg border bg-white p-2 focus:border-blue-400"
                                v-model="updatedBooking.customer.zip_code"
                            />
                        </div>
                    </div>
                </div>

                <div class="flex w-full items-center space-x-6">
                    <div class="w-48 text-right">
                        <h5
                            class="text-sm font-medium uppercase text-neutral-600"
                        >
                            Country
                        </h5>
                    </div>
                    <div class="flex w-full space-x-4">
                        <div class="w-1/2">
                            <input
                                type="text"
                                name="country"
                                class="w-auto rounded-lg border bg-white p-2 focus:border-blue-400"
                                v-model="updatedBooking.customer.country"
                            />
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="rounded-lg border-2 border-neutral-100 bg-white">
            <div
                class="w-full border-b-2 border-neutral-100 bg-neutral-100 px-8 py-3"
            >
                <h5 class="text-neutral-800">Drivers Information</h5>
            </div>
            <div
                class="flex w-full flex-col space-y-4 p-8"
                v-for="(driver, index) in booking.drivers"
            >
                <span v-if="booking.drivers.length > 1"
                    >Driver #{{ index + 1 }}</span
                >
                <div class="flex w-full items-center space-x-6">
                    <div class="w-48 text-right">
                        <h5
                            class="text-sm font-medium uppercase text-neutral-600"
                        >
                            Driver's name
                        </h5>
                    </div>
                    <div class="flex w-full space-x-4">
                        <div class="w-1/2">
                            <input
                                type="text"
                                name="drivers_full_name"
                                class="w-auto rounded-lg border bg-white p-2 focus:border-blue-400"
                                v-model="
                                    updatedBooking.drivers[index].full_name
                                "
                            />
                        </div>
                    </div>
                </div>
                <div class="flex w-full items-center space-x-6">
                    <div class="w-48 text-right">
                        <h5
                            class="text-sm font-medium uppercase text-neutral-600"
                        >
                            License number
                        </h5>
                    </div>
                    <div class="flex w-full space-x-4">
                        <div class="w-1/2">
                            <input
                                type="text"
                                name="drivers_license_number"
                                class="w-auto rounded-lg border bg-white p-2 focus:border-blue-400"
                                v-model="
                                    updatedBooking.drivers[index].license_no
                                "
                            />
                        </div>
                    </div>
                </div>
                <div class="flex w-full items-center space-x-6">
                    <div class="w-48 text-right">
                        <h5
                            class="text-sm font-medium uppercase text-neutral-600"
                        >
                            Date of Birth
                        </h5>
                    </div>
                    <div class="flex w-full space-x-4">
                        <div class="w-1/2">
                            <datepicker
                                class="w-auto rounded-lg border bg-white p-2 focus:border-blue-400"
                                v-model="
                                    updatedBooking.drivers[index].date_of_birth
                                "
                                inputFormat="dd/MM/yyyy"
                            />
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="rounded-lg border-2 border-neutral-100 bg-white">
            <div
                class="w-full border-b-2 border-neutral-100 bg-neutral-100 px-8 py-3"
            >
                <h5 class="text-neutral-800">Additional Information</h5>
            </div>
            <div class="flex w-full flex-col space-y-4 p-8">
                <div class="flex w-full items-center space-x-6">
                    <div class="w-48 text-right">
                        <h5
                            class="text-sm font-medium uppercase text-neutral-600"
                        >
                            Flight number
                        </h5>
                    </div>
                    <div class="flex w-full space-x-4">
                        <div class="w-1/2">
                            <input
                                type="text"
                                name="flight_number"
                                class="w-auto rounded-lg border bg-white p-2 focus:border-blue-400"
                                v-model="updatedBooking.additional_flight_no"
                            />
                        </div>
                    </div>
                </div>
                <div class="flex w-full items-center space-x-6">
                    <div class="w-48 text-right">
                        <h5
                            class="text-sm font-medium uppercase text-neutral-600"
                        >
                            Pick Up
                        </h5>
                    </div>
                    <div class="flex w-full space-x-4">
                        <div class="w-1/2">
                            <input
                                type="text"
                                name="additional_pick_up_time"
                                class="w-auto rounded-lg border bg-white p-2 focus:border-blue-400"
                                v-model="updatedBooking.additional_pick_up_time"
                            />
                        </div>
                    </div>
                </div>
                <div class="flex w-full items-center space-x-6">
                    <div class="w-48 text-right">
                        <h5
                            class="text-sm font-medium uppercase text-neutral-600"
                        >
                            Drop Off
                        </h5>
                    </div>
                    <div class="flex w-full space-x-4">
                        <div class="w-1/2">
                            <input
                                type="text"
                                name="additional_drop_off_time"
                                class="w-auto rounded-lg border bg-white p-2 focus:border-blue-400"
                                v-model="
                                    updatedBooking.additional_drop_off_time
                                "
                            />
                        </div>
                    </div>
                </div>
                <div class="flex w-full items-center space-x-6">
                    <div class="w-48 text-right">
                        <h5
                            class="text-sm font-medium uppercase text-neutral-600"
                        >
                            Nr of Passengers
                        </h5>
                    </div>
                    <div class="flex w-full space-x-4">
                        <div class="w-1/2">
                            <input
                                type="text"
                                name="additional_nr_of_pax"
                                class="w-auto rounded-lg border bg-white p-2 focus:border-blue-400"
                                v-model="updatedBooking.additional_nr_of_pax"
                            />
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
import Datepicker from "vue3-datepicker";
import TimeDropdown from "../../../Shared/TimeDropdown";
import dayjs from "dayjs";

import axios from "axios";
import { Inertia } from "@inertiajs/inertia";

export default {
    layout: "Dashboard",

    components: { Datepicker, TimeDropdown },

    props: ["booking", "vehicleClasses", "insurances", "packages", "extras"],

    data() {
        return {
            updatedBooking: JSON.parse(
                JSON.stringify({
                    ...this.booking,
                    car: this.booking.car[0],
                    carClass: this.booking.carClass[0],
                    packages: this.booking.packages.map((x) =>
                        this._selectFewerProps(x)
                    ),
                    insurances: this.booking.insurances.map((x) =>
                        this._selectFewerProps(x)
                    ),
                    extras: this.booking.extras.map((x) =>
                        this._selectFewerProps(x)
                    ),
                })
            ),
            booking_type: [
                "Online",
                "By email",
                "By phone",
                "Walk in",
                "Invoice",
                "Broker",
            ],
            minDay: new Date(dayjs(new Date()).add(2, "day")),
            units: [],
            changed: false,
            changePrice: false,
        };
    },

    methods: {
        recalculatePrice(title, price_per_day) {
            const days = dayjs(this.updatedBooking.drop_off_date).diff(
                this.updatedBooking.pick_up_date,
                "day"
            );

            const data = JSON.parse(this.updatedBooking.price.data);
            let totalPrice = this.updatedBooking.price.total_price;
            let totalBalance = this.updatedBooking.price.total_balance;

            const price = price_per_day * days;

            const looking = data.find((d) => d.title === title);

            if (looking !== undefined) {
                totalPrice = Math.round(
                    parseFloat(totalPrice) - parseFloat(looking.total_price)
                );
                totalBalance = Math.round(
                    parseFloat(totalBalance) - parseFloat(looking.total_price)
                );

                data.splice(
                    data.findIndex((d) => d.title === title),
                    1
                );
            } else {
                totalPrice = Math.round(parseFloat(totalPrice) + price);
                totalBalance = Math.round(parseFloat(totalBalance) + price);

                data.push({
                    title,
                    price,
                    discount: 0,
                    price_per_day,
                    total_price: price,
                });
            }

            this.updatedBooking.price.total_price = totalPrice;
            this.updatedBooking.price.total_balance = totalBalance;
            this.updatedBooking.price.data = JSON.stringify(data);
        },

        manuallyChangePrice(title, discount, price_per_day) {
            const days = dayjs(this.updatedBooking.drop_off_date).diff(
                this.updatedBooking.pick_up_date,
                "day"
            );

            const data = JSON.parse(this.updatedBooking.price.data);
            let totalPrice = this.updatedBooking.price.total_price;
            let totalBalance = this.updatedBooking.price.total_balance;
            let total_price;

            const price = price_per_day * days;

            if (discount === undefined || discount === 0) {
                total_price = price;
            } else {
                total_price = price - price * (discount / 100);
            }

            const looking = data.find((d) => d.title === title);
            const updatedPricePerDay = total_price / days;

            totalPrice = total_price;
            totalBalance = total_price - this.updatedBooking.price.total_paid;

            looking.discount = discount;
            looking.price_per_day = updatedPricePerDay;
            looking.total_price = total_price;

            // noinspection EqualityComparisonWithCoercionJS
            if (looking && discount == 0) {
                totalPrice = this.booking.price.total_price;
                totalBalance =
                    totalPrice - this.updatedBooking.price.total_paid;

                const oldVal = JSON.parse(this.booking.price.data);

                looking.discount = discount;
                looking.price_per_day =
                    oldVal[
                        data.findIndex((d) => d.title === title)
                    ].price_per_day;
                looking.total_price =
                    oldVal[
                        data.findIndex((d) => d.title === title)
                    ].total_price;
            }

            // FIXME: Not override price, add to
            this.updatedBooking.price.total_price = totalPrice;
            this.updatedBooking.price.total_balance = totalBalance;
            this.updatedBooking.price.data = JSON.stringify(data);
        },

        updateBooking() {
            // TODO: Figure out a way to recalculate the prices
            if (confirm("Are you sure you want to update this booking?")) {
                this.$inertia.put("/api/booking/update", this.updatedBooking);
            }
        },

        editBooking(e, status) {
            e.preventDefault();

            // TODO: Add loader
            if (confirm("Are you sure you want to update this booking?")) {
                axios
                    .patch("/api/booking/edit", {
                        uuid: this.updatedBooking.uuid,
                        carClass: this.booking.carClass[0],
                        status,
                    })
                    .then((resp) => this.updatedBooking.status = resp.data);
            }
        },

        cancelBooking(e) {
            e.preventDefault();

            // TODO: Add loader
            // TODO: Figure out a way to recalculate the prices
            if (
                confirm(
                    "Are you sure you want to cancel booking: #" +
                        this.updatedBooking.id
                )
            ) {
                axios
                    .patch("/api/booking/cancel", {
                        uuid: this.booking.uuid,
                        carClass: this.booking.carClass[0],
                    })
                    .then(function (data) {})
                    .finally(() => Inertia.visit("/dashboard"));
            }
        },

        async sendRentalAgreement() {
            if (confirm("Are you sure you want to update this booking?")) {
                await axios
                    .post("/api/mail/rental-agreement", {
                        uuid: this.booking.uuid,
                    })
                    .then(function (data) {
                        console.log(data);
                    });
            }
        },

        async _collectUnits(newVal, oldVal) {
            // TODO: Add spam protection
            await this._getCars();

            if (newVal === undefined) {
                this.units.push(this.booking.car[0]);
            }
        },

        _getCars: function () {
            return axios
                .get(
                    window.location.origin +
                        "/api/cars/vehicleClass/" +
                        this.updatedBooking.carClass.slug,
                    {
                        params: {
                            pick_up_date: this.updatedBooking.pick_up_date,
                            drop_off_date: this.updatedBooking.drop_off_date,
                        },
                    }
                )
                .then((resp) => {
                    this.units = resp.data;
                });
        },

        _selectFewerProps(item) {
            const { id, title } = item;
            return { id, title };
        },

        _updatePickUpDate() {
            const [day, month, year] = this.booking.pick_up_date.split("/");

            this.updatedBooking.pick_up_date = new Date(
                +year,
                +month - 1,
                +day
            );
        },

        _updateDropOffDate() {
            const [day, month, year] = this.booking.drop_off_date.split("/");

            this.updatedBooking.drop_off_date = new Date(
                +year,
                +month - 1,
                +day
            );
        },

        _updateDriversDOB() {
            this.booking.drivers.forEach((driver, index) => {
                this.updatedBooking.drivers[index].date_of_birth = new Date(
                    driver.date_of_birth
                );
            });
        },
    },

    mounted: function () {
        this._collectUnits();
        this._updatePickUpDate();
        this._updateDropOffDate();
        this._updateDriversDOB();
    },

    watch: {
        "updatedBooking.carClass"(newVal, oldVal) {
            this._collectUnits(newVal, oldVal);
        },
        "updatedBooking.pick_up_date"(val) {
            if (
                dayjs(this.updatedBooking.drop_off_date).diff(
                    this.updatedBooking.pick_up_date,
                    "day"
                ) < 2
            ) {
                const newDate = dayjs(val).add(2, "day");

                this.minDay = newDate.$d;
                this.updatedBooking.drop_off_date = newDate.$d;
            }
        },
        updatedBooking() {
            this.changed = true;
        },
    },
};
</script>

<style>
.dropdown:hover .dropdown-menu {
    display: block;
}

/* Chrome, Safari, Edge, Opera */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

/* Firefox */
input[type="number"] {
    -moz-appearance: textfield;
}
</style>
Sinnbeck's avatar

@hjortur17 Ah I just noticed you put routes inside api.php. All routes goes in web.php. Inertia isnt an api

hjortur17's avatar

@Sinnbeck - So their is no way to make Inertia talk to /api? So I should move all my routes to web.php

Sinnbeck's avatar

@hjortur17 it's because inertia uses sessions and api is stateless. Also I'm unsure if inertia binds to the api middleware at all. You can try setting api.php to use the web middleware

Why would you want them in api.php anyways? An api would never redirect back

1 like
hjortur17's avatar

@Sinnbeck - So most of my code base so it's no longer trying to redirect from the api.php. But the issue I am getting now is that when I try to edit my rental I get 21 302 requests and if I refresh the page I get the flash message. Any idea what can causing this?

Here is the routes (web.php):

Route::middleware(['auth', 'can:admin'])->prefix('dashboard')->group(function () {
    Route::prefix('reservations')->group(function () {
        Route::get('pickup', [ReservationController::class, 'pickup']);
        Route::get('dropoff', [ReservationController::class, 'dropoff']);
        Route::get('edit/{rental}', [ReservationController::class, 'edit'])->name('edit.rental');
        Route::patch('edit', [RentalController::class, 'edit']);

        Route::put('update', [RentalController::class, 'update']);
        Route::patch('cancel', [RentalController::class, 'destroy']);
    });
});

Here is the edit method:

public function edit(Rental $rental, Request $request)
    {
        if ($request->status === 'start') {
            $rental->status = BookingStatusEnum::RENTED;
        } else if ($request->status === 'end') {
            $carClass = CarClass::where('uuid', $request->carClass['uuid'])->firstOrFail();

            $carClass->available = $carClass->available + 1;

            $carClass->save();

            $rental->status = BookingStatusEnum::RETURNED;
        }

        $rental->save();

        return Redirect::route('edit.rental', $rental)->with('success', 'Rental ' . $rental->status->value . '.');
    }
hjortur17's avatar

It looks like it trying to redirect and then update the rental. Because now I'm getting 405 error because It's trying to send put request to dashboard/reservations/edit/18.

Any idea why that is happening?

fabioselau077's avatar

This happens because you are doing back() on a PUT route, which causes it to be redirected to the previous route but passing the same HTTP method, in this case PUT.

To solve this, you return a JSON from the backend and on the frontend validate or change it to the route in addition to GET receiving PUT as well.

I believe that this should not actually exist, because if you receive a PUT and do redirect()->back(), logically it should automatically convert the request to HTTP, but for some reason when it is a PUT it does not do this.

Please or to participate in this conversation.