From 33af04db1be2c15a10c99423ef03291f45822a63 Mon Sep 17 00:00:00 2001 From: Codex Agent Date: Tue, 6 Jan 2026 09:23:01 +0100 Subject: [PATCH] Checkout: minimize registration data --- app/Http/Controllers/CheckoutController.php | 6 +- .../Checkout/CheckoutRegisterRequest.php | 15 ++- ...06_090545_update_users_username_length.php | 52 ++++++++ resources/js/pages/auth/RegisterForm.tsx | 112 +----------------- tests/Feature/Checkout/CheckoutAuthTest.php | 32 ++--- tests/Feature/CheckoutRegisterRoleTest.php | 4 +- tests/Feature/FullUserFlowTest.php | 6 - tests/ui/purchase/paddle-sandbox-full.test.ts | 16 ++- .../standard-package-checkout.test.ts | 19 ++- 9 files changed, 105 insertions(+), 157 deletions(-) create mode 100644 database/migrations/2026_01_06_090545_update_users_username_length.php diff --git a/app/Http/Controllers/CheckoutController.php b/app/Http/Controllers/CheckoutController.php index 974ef1b..2bac445 100644 --- a/app/Http/Controllers/CheckoutController.php +++ b/app/Http/Controllers/CheckoutController.php @@ -82,12 +82,12 @@ class CheckoutController extends Controller // User erstellen $user = User::create([ 'email' => $validated['email'], - 'username' => $validated['username'], + 'username' => Str::lower($validated['email']), 'first_name' => $validated['first_name'], 'last_name' => $validated['last_name'], 'name' => trim($validated['first_name'].' '.$validated['last_name']), - 'address' => $validated['address'], - 'phone' => $validated['phone'], + 'address' => $validated['address'] ?? null, + 'phone' => $validated['phone'] ?? null, 'preferred_locale' => $validated['locale'] ?? null, 'role' => 'user', 'password' => Hash::make($validated['password']), diff --git a/app/Http/Requests/Checkout/CheckoutRegisterRequest.php b/app/Http/Requests/Checkout/CheckoutRegisterRequest.php index a36f387..62941cd 100644 --- a/app/Http/Requests/Checkout/CheckoutRegisterRequest.php +++ b/app/Http/Requests/Checkout/CheckoutRegisterRequest.php @@ -3,6 +3,7 @@ namespace App\Http\Requests\Checkout; use Illuminate\Foundation\Http\FormRequest; +use Illuminate\Validation\Rule; use Illuminate\Validation\Rules\Password; class CheckoutRegisterRequest extends FormRequest @@ -23,13 +24,18 @@ class CheckoutRegisterRequest extends FormRequest public function rules(): array { return [ - 'email' => ['required', 'email', 'max:255', 'unique:users,email'], - 'username' => ['required', 'string', 'max:255', 'unique:users,username'], + 'email' => [ + 'required', + 'email', + 'max:255', + Rule::unique('users', 'email'), + Rule::unique('users', 'username'), + ], 'password' => ['required', 'confirmed', Password::defaults()], 'first_name' => ['required', 'string', 'max:255'], 'last_name' => ['required', 'string', 'max:255'], - 'address' => ['required', 'string', 'max:500'], - 'phone' => ['required', 'string', 'max:255'], + 'address' => ['nullable', 'string', 'max:500'], + 'phone' => ['nullable', 'string', 'max:255'], 'package_id' => ['required', 'exists:packages,id'], 'terms' => ['required', 'accepted'], 'privacy_consent' => ['required', 'accepted'], @@ -44,7 +50,6 @@ class CheckoutRegisterRequest extends FormRequest { return [ 'email.unique' => 'Diese E-Mail-Adresse wird bereits verwendet.', - 'username.unique' => 'Dieser Benutzername ist bereits vergeben.', 'password.confirmed' => 'Die Passwortbestätigung stimmt nicht überein.', 'package_id.exists' => 'Das ausgewählte Paket ist ungültig.', 'terms.accepted' => 'Bitte akzeptiere die Nutzungsbedingungen.', diff --git a/database/migrations/2026_01_06_090545_update_users_username_length.php b/database/migrations/2026_01_06_090545_update_users_username_length.php new file mode 100644 index 0000000..5386f54 --- /dev/null +++ b/database/migrations/2026_01_06_090545_update_users_username_length.php @@ -0,0 +1,52 @@ +({ - username: '', email: '', password: '', password_confirmation: '', first_name: '', last_name: '', - address: '', - phone: '', privacy_consent: false, terms: false, package_id: packageId || null, @@ -87,7 +81,7 @@ export default function RegisterForm({ packageId, onSuccess, privacyHtml, locale const registerEndpoint = '/checkout/register'; const requiredStringFields: Array = useMemo(() => ( - ['first_name', 'last_name', 'username', 'email', 'password', 'password_confirmation', 'address', 'phone'] + ['first_name', 'last_name', 'email', 'password', 'password_confirmation'] ), []); const isFormValid = useMemo(() => { @@ -121,27 +115,6 @@ export default function RegisterForm({ packageId, onSuccess, privacyHtml, locale }; }, [prefill]); - const suggestedUsername = useMemo(() => { - if (prefill?.email) { - const localPart = prefill.email.split('@')[0]; - if (localPart) { - return localPart.slice(0, 30); - } - } - - const first = prefill?.given_name ?? prefill?.name?.split(' ')[0] ?? ''; - const last = prefill?.family_name ?? prefill?.name?.split(' ').slice(1).join(' ') ?? ''; - const combined = `${first}${last}`.trim(); - if (!combined) { - return undefined; - } - - return combined - .toLowerCase() - .replace(/[^a-z0-9]+/g, '') - .slice(0, 30) || undefined; - }, [prefill]); - useEffect(() => { if (!prefill || prefillApplied) { return; @@ -159,12 +132,8 @@ export default function RegisterForm({ packageId, onSuccess, privacyHtml, locale setData('email', prefill.email); } - if (suggestedUsername && !data.username) { - setData('username', suggestedUsername); - } - setPrefillApplied(true); - }, [prefill, namePrefill.first, namePrefill.last, data.first_name, data.last_name, data.email, data.username, prefillApplied, setData, suggestedUsername]); + }, [prefill, namePrefill.first, namePrefill.last, data.first_name, data.last_name, data.email, prefillApplied, setData]); const submit = async (event: React.FormEvent) => { event.preventDefault(); @@ -357,81 +326,6 @@ export default function RegisterForm({ packageId, onSuccess, privacyHtml, locale {errors.email &&

{errors.email}

} -
- -
- - { - setData('address', e.target.value); - if (e.target.value.trim() && errors.address) { - clearErrors('address'); - } - }} - className={`block w-full pl-10 pr-3 py-3 border rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-[#FFB6C1] focus:border-[#FFB6C1] sm:text-sm ${errors.address ? 'border-red-500' : 'border-gray-300'}`} - placeholder={t('register.address_placeholder')} - /> -
- {errors.address &&

{errors.address}

} -
- -
- -
- - { - setData('phone', e.target.value); - if (e.target.value.trim() && errors.phone) { - clearErrors('phone'); - } - }} - className={`block w-full pl-10 pr-3 py-3 border rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-[#FFB6C1] focus:border-[#FFB6C1] sm:text-sm ${errors.phone ? 'border-red-500' : 'border-gray-300'}`} - placeholder={t('register.phone_placeholder')} - /> -
- {errors.phone &&

{errors.phone}

} -
- -
- -
- - { - setData('username', e.target.value); - if (e.target.value.trim() && errors.username) { - clearErrors('username'); - } - }} - className={`block w-full pl-10 pr-3 py-3 border rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-[#FFB6C1] focus:border-[#FFB6C1] sm:text-sm ${errors.username ? 'border-red-500' : 'border-gray-300'}`} - placeholder={t('register.username_placeholder')} - /> -
- {errors.username &&

{errors.username}

} -
-