I am new to Laravel and Vue 3.
I have a create and update form for pages.
The created page works 100% with or without uploading images.
I copied and pasted and changed the page object to the prop.page, updated the form route and a few other small changes but nothing else.
When submitting the form without an image everything works fine, but if you submit a form, no input fields are submitted.
I get no errors, from laravel, vue or console.log.
Here is my page controller:
<?php

namespace App\Http\Controllers;

use App\Models\Page;
use Inertia\Inertia;
use Inertia\Response;
use Intervention\Image\ImageManager;
use Illuminate\Http\RedirectResponse;
use App\Http\Requests\StorePageRequest;
use Illuminate\Support\Facades\Storage;
use App\Http\Requests\UpdatePageRequest;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redirect;
use Intervention\Image\Drivers\Gd\Driver;

class PageController extends Controller
{
    public function __construct()
    {
        $this->authorizeResource(Page::class, 'page');
    }

    /**
     * Display a listing of the resource.
     */
    public function index(): Response
    {
        $pages = Page::select('id', 'name', 'in_menu', 'position')->paginate(20);
        return Inertia::render('Admin/Pages/Index', compact('pages'));
    }

    /**
     * Show the form for creating a new resource.
     */
    public function create()
    {
        return Inertia::render('Admin/Pages/Create', ['status' => session('status')]);
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(StorePageRequest $request): RedirectResponse
    {
        $page = new Page();

        $newImageName = '';

        if($request->hasFile('header')){
            $image = $request->file('header');

            $originalName = pathinfo(str_replace(' ', '', $image->getClientOriginalName()), PATHINFO_FILENAME);
            $newImageName = time().'-'.$originalName.'.'.$image->guessClientExtension();

            $manager = new ImageManager(
                new Driver()
            );

            $image = $manager->read($image);

            $image->coverDown(1200, 675)->save(public_path('storage/uploads/page/images/full/'.$newImageName));
            $image->coverDown(600, 338)->save(public_path('storage/uploads/page/images/medium/'.$newImageName));
            $image->coverDown(100, 100)->save(public_path('storage/uploads/page/images/thumb/'.$newImageName));
        }

        $page->name = $request->name;
        $page->title = $request->title;
        $page->description = $request->description;
        $page->content = $request->content;
        $page->header = $newImageName;
        $page->in_menu = $request->in_menu;
        $page->position = $request->position;

        $page->save();

        return Redirect::route('admin.pages.index')->with('success', 'page created successfully');
    }

    /**
     * Display the specified resource.
     */
    public function show(Page $page)
    {
        
    }

    /**
     * Show the form for editing the specified resource.
     */
    public function edit(Page $page)
    {
        return Inertia::render('Admin/Pages/Edit', compact('page'));
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(UpdatePageRequest $request, Page $page): RedirectResponse
    {
        dd([$request, $page]);
        $newImageName = $page->header;

        if($request->hasFile('header')){
            $image = $request->file('header');

            $originalName = pathinfo(str_replace(' ', '', $image->getClientOriginalName()), PATHINFO_FILENAME);
            $newImageName = time().'-'.$originalName.'.'.$image->guessClientExtension();

            $manager = new ImageManager(
                new Driver()
            );

            $image = $manager->read($image);

            $image->coverDown(1200, 675)->save(public_path('storage/uploads/page/images/full/'.$newImageName));
            $image->coverDown(600, 338)->save(public_path('storage/uploads/page/images/medium/'.$newImageName));
            $image->coverDown(100, 100)->save(public_path('storage/uploads/page/images/thumb/'.$newImageName));
            
            Storage::delete('/uploads/page/images/full/'.$page->header);
            Storage::delete('/uploads/page/images/medium/'.$page->header);
            Storage::delete('/uploads/page/images/thumb/'.$page->header);
        }

        $page->name = $request->name;
        $page->title = $request->title;
        $page->description = $request->description;
        $page->content = $request->content;
        $page->header = $newImageName;
        $page->in_menu = $request->in_menu;
        $page->position = $request->position;

        $page->save();

        return Redirect::route('admin.pages.index')->with('success', 'page update successfully');
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(Page $page)
    {
        //
    }
}

Here is my routes:
<?php

use App\Http\Controllers\PageController;
use Illuminate\Support\Facades\Route;

Route::middleware('auth')->group(function () {
    Route::controller(PageController::class)->group(function () {
        Route::get('/admin/pages', 'index')->name('admin.pages.index');

        Route::get('/admin/pages/create', 'create')->name('admin.pages.create');
        Route::post('/admin/pages/store', 'store')->name('admin.pages.store');

        Route::get('/admin/pages/{page}/edit', 'edit')->name('admin.pages.edit');
        Route::put('/admin/pages/{page}/update', 'update')->name('admin.pages.update');
    });
});

My UpdatePageRequest:
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

class UpdatePageRequest extends FormRequest
{
    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
     */
    public function rules(): array
    {
        return [
            'name' => ['required', 'string', 'max:50', 'min:4'],
            'title' => ['required', 'string', 'max:150', 'min:4'],
            'description' => ['required', 'string', 'max:200', 'min:20'],
            'content' => ['required', 'string', 'min:4'],
            'header' => ['sometimes', 'image'],
            'in_menu' => ['required', 'numeric', Rule::in([0,1])],
            'position' => ['required', 'numeric'],
        ];
    }
}

Page Policy:
<?php

namespace App\Policies;

use App\Models\Page;
use App\Models\User;
use Illuminate\Auth\Access\Response;

class PagePolicy
{
    /**
     * Determine whether the user can view any models.
     */
    public function viewAny(User $user): bool
    {
        return (bool)$user->is_admin;
    }

    /**
     * Determine whether the user can view the model.
     */
    public function view(User $user, Page $page): bool
    {
        return (bool)$user->is_admin;
    }

    /**
     * Determine whether the user can create models.
     */
    public function create(User $user): bool
    {
        return (bool)$user->is_admin;
    }

    /**
     * Determine whether the user can update the model.
     */
    public function update(User $user, Page $page): bool
    {
        return true;
        // return (bool)$user->is_admin;
    }

    /**
     * Determine whether the user can delete the model.
     */
    public function delete(User $user, Page $page): bool
    {
        return (bool)$user->is_admin;
    }

    /**
     * Determine whether the user can restore the model.
     */
    public function restore(User $user, Page $page): bool
    {
        return (bool)$user->is_admin;
    }

    /**
     * Determine whether the user can permanently delete the model.
     */
    public function forceDelete(User $user, Page $page): bool
    {
        return (bool)$user->is_admin;
    }
}

And Finally my Vue:
<template>
    <Head title="Create New Page" />

    <AuthenticatedLayout>
        <template #header>
            <h2 class="font-semibold text-xl text-gray-800 leading-tight">Create New Page</h2>
        </template>

        <div class="py-12">
            <div class="max-w-7xl mx-auto sm:px-6 lg:px-8 flex gap-4">
                <AdminLeftColumn />

                <div class="p-4 sm:p-8 bg-white shadow sm:rounded-lg w-2/3">

                    <div class="text-end mb-4 pb-6 border-b border-gray-200">
                        <Link href="/admin/pages" class="py-2 px-2 rounded-sm bg-blue-400 text-white text-sm hover:ring-4 hover:ring-blue-500">Back</Link>
                    </div>
                    
                    <form @submit.prevent="form.put(route('admin.pages.update', page))" enctype="multipart/form-data" class="mt-6 space-y-6">
                        <div class="flex gap-4">
                            <div class="w-1/2">
                                    <InputLabel for="name" value="Page Name" />

                                    <TextInput
                                        id="name"
                                        type="text"
                                        class="mt-1 block w-full"
                                        v-model="form.name"
                                        required
                                        autocomplete="name"
                                    />

                                    <InputError class="mt-2" :message="form.errors.name" />
                            </div>

                            <div class="w-1/2">
                                    <InputLabel for="title" value="Page Title" />

                                    <TextInput
                                        id="title"
                                        type="text"
                                        class="mt-1 block w-full"
                                        v-model="form.title"
                                        required
                                        autocomplete="title"
                                    />

                                    <InputError class="mt-2" :message="form.errors.title" />
                            </div>
                        </div>

                        <div class="pt-2">
                            <InputLabel for="header" value="Header Image" />

                            <TextInput
                                id="header"
                                type="file"
                                class="mt-1 block w-full text-sm text-gray-900 border border-gray-300 rounded-lg cursor-pointer focus:outline-none p-2"
                                @input="form.header = $event.target.files[0]"
                            />

                            <InputError class="mt-2" :message="form.errors.header" />
                        </div>

                        <div class="pt-2">
                            <InputLabel for="description" value="Page Description" />

                            <TextArea
                                rows="3"
                                id="description"
                                type="text"
                                class="mt-1 block w-full"
                                v-model="form.description"
                                required
                                autocomplete="description"
                            />

                            <InputError class="mt-2" :message="form.errors.description" />
                        </div>

                        <div class="pt-4">
                            <InputLabel for="content" value="Page Content" />

                            <Editor 
                            id="content" 
                            v-model="form.content" 
                            :mode="form.content"
                            required
                            autocomplete="content"
                            />

                            <InputError class="mt-2" :message="form.errors.content" />
                        </div>

                        <div v-if="mustVerifyEmail && user.email_verified_at === null">
                            <p class="text-sm mt-2 text-gray-800">
                                Your email address is unverified.
                                <Link
                                    :href="route('verification.send')"
                                    method="post"
                                    as="button"
                                    class="underline text-sm text-gray-600 hover:text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
                                >
                                    Click here to re-send the verification email.
                                </Link>
                            </p>

                            <div
                                v-show="status === 'verification-link-sent'"
                                class="mt-2 font-medium text-sm text-green-600"
                            >
                                A new verification link has been sent to your email address.
                            </div>
                        </div>

                        <div class="flex justify-end">
                            <PrimaryButton :disabled="form.processing">Save</PrimaryButton>

                            <Transition
                                enter-active-class="transition ease-in-out"
                                enter-from-class="opacity-0"
                                leave-active-class="transition ease-in-out"
                                leave-to-class="opacity-0"
                            >
                                <p v-if="form.recentlySuccessful" class="text-sm text-gray-600">Saved.</p>
                            </Transition>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </AuthenticatedLayout>
</template>

<script setup>
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout.vue';
import AdminLeftColumn from '@/Pages/Profile/Partials/AdminLeftColumn.vue';
import PrimaryButton from '@/Components/PrimaryButton.vue';
import TextInput from '@/Components/TextInput.vue';
import TextArea from '@/Components/TextArea.vue';
import InputLabel from '@/Components/InputLabel.vue';
import InputError from '@/Components/InputError.vue';
import Editor from '@/Components/Editor.vue';
import { Link, Head, usePage, useForm } from '@inertiajs/vue3';

const page = usePage().props.page;

defineProps({
    mustVerifyEmail: {
        type: Boolean,
    },
    status: {
        type: String,
    }
});

const form = useForm({
    name: page.name,
    title: page.title,
    description: page.description,
    content: page.content,
    header: page.header,
    in_menu: page.in_menu,
    position: page.position
});
</script>

I have been trying everything on the internet I can find that is remotely plausable to this issue, 5 hours in total.
I have used Chat GPT with very little help. It just tells me to make sure the routes and validations are correct.
The validation works because it is the same as the create, no differences.
The permissions from the policy look good and to make sure I even set them all to true to make sure it wasnt that.
I did a console.log() of the form after it has been sent and it shows that the form.name, form.title etc was within the form.
But when it lands in the PageController@update it has nothing.
Here is the dump when file is not uploaded:
array:2 [▼ // app\Http\Controllers\PageController.php:101
  0 => 
Illuminate\Http
\
Request {#37 ▼
    +attributes: 
Symfony\Component\HttpFoundation
\
ParameterBag {#42 ▼
      #parameters: []
    }
    +request: 
Symfony\Component\HttpFoundation
\
InputBag {#41 ▼
      #parameters: array:6 [▼
        "name" => "About Us Page"
        "title" => "This is a title for about us page"
        "description" => "This is a little description about the about us page"
        "content" => "<p>sdasdasdasdasdasdasdasdasd</p>"
        "in_menu" => 1
        "position" => 0
      ]
    }
    +query: 
Symfony\Component\HttpFoundation
\
InputBag {#45 ▶}
    +server: 
Symfony\Component\HttpFoundation
\
ServerBag {#40 ▶}
    +files: 
Symfony\Component\HttpFoundation
\
FileBag {#44 ▶}
    +cookies: 
Symfony\Component\HttpFoundation
\
InputBag {#43 ▶}
    +headers: 
Symfony\Component\HttpFoundation
\
HeaderBag {#39 ▶}
    #content: "
{"name":"About Us Page","title":"This is a title for about us page","description":"This is a little description about the about us page","content":"<p>sdasdasda
 ▶
"
    #languages: null
    #charsets: null
    #encodings: null
    #acceptableContentTypes: null
    #pathInfo: "/admin/pages/5/update"
    #requestUri: "/admin/pages/5/update"
    #baseUrl: ""
    #basePath: null
    #method: "PUT"
    #format: null
    #session: 
Illuminate\Session
\
Store {#322 ▶}
    #locale: null
    #defaultLocale: "en"
    -preferredFormat: null
    -isHostValid: true
    -isForwardedValid: true
    -isSafeContentPreferred: ? bool
    -trustedValuesCache: []
    -isIisRewrite: false
    #json: 
Symfony\Component\HttpFoundation
\
InputBag {#41 ▶}
    #convertedFiles: null
    #userResolver: Closure($guard = null) {#285 ▶}
    #routeResolver: Closure() {#294 ▶}
    basePath: ""
    format: "html"
  }
  1 => 
App\Models
\
Page {#1324 ▼
    #connection: "mysql"
    #table: "pages"
    #primaryKey: "id"
    #keyType: "int"
    +incrementing: true
    #with: []
    #withCount: []
    +preventsLazyLoading: false
    #perPage: 15
    +exists: true
    +wasRecentlyCreated: false
    #escapeWhenCastingToString: false
    #attributes: array:10 [▶]
    #original: array:10 [▶]
    #changes: []
    #casts: []
    #classCastCache: []
    #attributeCastCache: []
    #dateFormat: null
    #appends: []
    #dispatchesEvents: []
    #observables: []
    #relations: []
    #touches: []
    +timestamps: true
    +usesUniqueIds: false
    #hidden: []
    #visible: []
    #fillable: array:7 [▼
      0 => "name"
      1 => "title"
      2 => "description"
      3 => "content"
      4 => "header"
      5 => "in_menu"
      6 => "position"
    ]
    #guarded: array:1 [▼
      0 => "*"
    ]
  }
]

This is with the image uploaded:
array:2 [▼ // app\Http\Controllers\PageController.php:101
  0 => 
Illuminate\Http
\
Request {#37 ▼
    +attributes: 
Symfony\Component\HttpFoundation
\
ParameterBag {#42 ▼
      #parameters: []
    }
    +request: 
Symfony\Component\HttpFoundation
\
InputBag {#38 ▼
      #parameters: []
    }
    +query: 
Symfony\Component\HttpFoundation
\
InputBag {#45 ▶}
    +server: 
Symfony\Component\HttpFoundation
\
ServerBag {#40 ▶}
    +files: 
Symfony\Component\HttpFoundation
\
FileBag {#44 ▶}
    +cookies: 
Symfony\Component\HttpFoundation
\
InputBag {#43 ▶}
    +headers: 
Symfony\Component\HttpFoundation
\
HeaderBag {#39 ▶}
    #content: null
    #languages: null
    #charsets: null
    #encodings: null
    #acceptableContentTypes: null
    #pathInfo: "/admin/pages/5/update"
    #requestUri: "/admin/pages/5/update"
    #baseUrl: ""
    #basePath: null
    #method: "PUT"
    #format: null
    #session: 
Illuminate\Session
\
Store {#322 ▶}
    #locale: null
    #defaultLocale: "en"
    -preferredFormat: null
    -isHostValid: true
    -isForwardedValid: true
    -isSafeContentPreferred: ? bool
    -trustedValuesCache: []
    -isIisRewrite: false
    #json: null
    #convertedFiles: null
    #userResolver: Closure($guard = null) {#285 ▶}
    #routeResolver: Closure() {#294 ▶}
    basePath: ""
    format: "html"
  }
  1 => 
App\Models
\
Page {#1324 ▼
    #connection: "mysql"
    #table: "pages"
    #primaryKey: "id"
    #keyType: "int"
    +incrementing: true
    #with: []
    #withCount: []
    +preventsLazyLoading: false
    #perPage: 15
    +exists: true
    +wasRecentlyCreated: false
    #escapeWhenCastingToString: false
    #attributes: array:10 [▼
      "id" => 5
      "name" => "About Us Page"
      "title" => "This is a title for about us page"
      "description" => "This is a little description about the about us page"
      "content" => "<p>sdasdasdasdasdasdasdasdasd</p>"
      "header" => ""
      "in_menu" => 1
      "position" => 0
      "created_at" => "2024-02-15 16:15:13"
      "updated_at" => "2024-02-15 18:56:48"
    ]
    #original: array:10 [▶]
    #changes: []
    #casts: []
    #classCastCache: []
    #attributeCastCache: []
    #dateFormat: null
    #appends: []
    #dispatchesEvents: []
    #observables: []
    #relations: []
    #touches: []
    +timestamps: true
    +usesUniqueIds: false
    #hidden: []
    #visible: []
    #fillable: array:7 [▼
      0 => "name"
      1 => "title"
      2 => "description"
      3 => "content"
      4 => "header"
      5 => "in_menu"
      6 => "position"
    ]
    #guarded: array:1 [▼
      0 => "*"
    ]
  }
]

Any help would be highly appreciated.