diff --git a/app/Livewire/LeadSubmissionForm.php b/app/Livewire/LeadSubmissionForm.php index dfd391a2..2a9d6564 100644 --- a/app/Livewire/LeadSubmissionForm.php +++ b/app/Livewire/LeadSubmissionForm.php @@ -21,8 +21,6 @@ class LeadSubmissionForm extends Component public string $description = ''; - public string $budget = ''; - public string $turnstileToken = ''; #[Locked] @@ -35,7 +33,6 @@ protected function rules(): array 'email' => ['required', 'email', 'max:255'], 'company' => ['required', 'string', 'max:255'], 'description' => ['required', 'string', 'max:5000'], - 'budget' => ['required', 'string', 'in:'.implode(',', array_keys(Lead::BUDGETS))], ]; if (config('services.turnstile.secret_key')) { @@ -48,7 +45,6 @@ protected function rules(): array public function messages(): array { return [ - 'budget.in' => 'Please select a budget range.', 'turnstileToken.required' => 'Please complete the security check.', ]; } @@ -73,7 +69,6 @@ public function submit(): void 'email' => $this->email, 'company' => $this->company, 'description' => $this->description, - 'budget' => $this->budget, 'ip_address' => request()->ip(), ]); @@ -87,8 +82,6 @@ public function submit(): void public function render() { - return view('livewire.lead-submission-form', [ - 'budgets' => Lead::BUDGETS, - ]); + return view('livewire.lead-submission-form'); } } diff --git a/app/Notifications/LeadReceived.php b/app/Notifications/LeadReceived.php index 44b8b2ab..35593058 100644 --- a/app/Notifications/LeadReceived.php +++ b/app/Notifications/LeadReceived.php @@ -21,8 +21,8 @@ public function toMail(object $notifiable): MailMessage return (new MailMessage) ->subject('Thank you for your enquiry') ->greeting("Hi {$notifiable->name},") - ->line('Thank you for reaching out to NativePHP about your app development project.') - ->line('We have received your enquiry and one of our team members will be in touch soon to discuss your requirements.') + ->line('Thank you for reaching out to NativePHP about consulting.') + ->line('We have received your enquiry and one of our team will be in touch soon to discuss your project.') ->line('In the meantime, feel free to explore our documentation or join our Discord community.') ->action('Visit NativePHP', url('/')) ->salutation('Best regards,
The NativePHP Team'); diff --git a/app/Notifications/NewLeadSubmitted.php b/app/Notifications/NewLeadSubmitted.php index c6c15b16..b057e579 100644 --- a/app/Notifications/NewLeadSubmitted.php +++ b/app/Notifications/NewLeadSubmitted.php @@ -24,13 +24,13 @@ public function via(object $notifiable): array public function toMail(object $notifiable): MailMessage { return (new MailMessage) - ->subject('New Build My App Enquiry: '.$this->lead->company) + ->subject('New Consulting Enquiry: '.$this->lead->company) ->replyTo($this->lead->email, $this->lead->name) ->greeting('New lead received!') ->line("**Name:** {$this->lead->name}") ->line("**Email:** {$this->lead->email}") ->line("**Company:** {$this->lead->company}") - ->line("**Budget:** {$this->lead->budget_label}") + ->when($this->lead->budget, fn (MailMessage $message) => $message->line("**Budget:** {$this->lead->budget_label}")) ->line('**Project Description:**') ->line($this->lead->description); } diff --git a/database/factories/LeadFactory.php b/database/factories/LeadFactory.php index e21b7279..f5b6950b 100644 --- a/database/factories/LeadFactory.php +++ b/database/factories/LeadFactory.php @@ -22,7 +22,7 @@ public function definition(): array 'email' => fake()->safeEmail(), 'company' => fake()->company(), 'description' => fake()->paragraphs(2, true), - 'budget' => fake()->randomElement(array_keys(Lead::BUDGETS)), + 'budget' => fake()->optional()->randomElement(array_keys(Lead::BUDGETS)), 'ip_address' => fake()->ipv4(), ]; } diff --git a/database/migrations/2026_04_10_100726_make_leads_budget_nullable.php b/database/migrations/2026_04_10_100726_make_leads_budget_nullable.php new file mode 100644 index 00000000..06350f1a --- /dev/null +++ b/database/migrations/2026_04_10_100726_make_leads_budget_nullable.php @@ -0,0 +1,25 @@ +string('budget')->nullable()->change(); + }); + } + + public function down(): void + { + Schema::table('leads', function (Blueprint $table) { + $table->string('budget')->nullable(false)->change(); + }); + } +}; diff --git a/public/img/team/shanerosenthal.jpg b/public/img/team/shanerosenthal.jpg new file mode 100644 index 00000000..d1f6f2e0 Binary files /dev/null and b/public/img/team/shanerosenthal.jpg differ diff --git a/public/img/team/simonhamp.jpg b/public/img/team/simonhamp.jpg new file mode 100644 index 00000000..f02f86b3 Binary files /dev/null and b/public/img/team/simonhamp.jpg differ diff --git a/resources/views/build-my-app.blade.php b/resources/views/build-my-app.blade.php deleted file mode 100644 index 8f050af4..00000000 --- a/resources/views/build-my-app.blade.php +++ /dev/null @@ -1,30 +0,0 @@ - - @push('head') - @if (config('services.turnstile.site_key')) - - @endif - @endpush - -
-
-
-

- { - Build My App - } -

- -

- Need help bringing your app idea to life?
- Tell us about your project! We'd love to help. -

-
-
- -
-
- -
-
-
-
diff --git a/resources/views/components/footer.blade.php b/resources/views/components/footer.blade.php index 77d3c86b..44adb8d8 100644 --- a/resources/views/components/footer.blade.php +++ b/resources/views/components/footer.blade.php @@ -244,10 +244,13 @@ class="inline-block px-px py-1.5 transition duration-300 will-change-transform h
  • - Develop + + Consulting + New +
  • diff --git a/resources/views/components/navbar/mobile-menu.blade.php b/resources/views/components/navbar/mobile-menu.blade.php index 5afaf4b2..a7f84af8 100644 --- a/resources/views/components/navbar/mobile-menu.blade.php +++ b/resources/views/components/navbar/mobile-menu.blade.php @@ -96,7 +96,7 @@ class="@md:grid-cols-3 grid grid-cols-2 text-xl" $isUltraActive = request()->routeIs('pricing'); $isBlogActive = request()->routeIs('blog*'); $isPartnersActive = request()->routeIs('partners*'); - $isServicesActive = request()->routeIs('build-my-app'); + $isServicesActive = request()->routeIs('consulting'); $isCourseActive = request()->routeIs('course'); $isSupportActive = request()->routeIs('support.*'); $isSponsorActive = request()->routeIs('sponsoring*'); @@ -231,10 +231,10 @@ class="size-4 shrink-0" - {{-- Services Link --}} -
    + {{-- Consulting Link (mobile only, shown in navbar on desktop) --}} + diff --git a/resources/views/components/navigation-bar.blade.php b/resources/views/components/navigation-bar.blade.php index 9f04ad33..c89e1cd3 100644 --- a/resources/views/components/navigation-bar.blade.php +++ b/resources/views/components/navigation-bar.blade.php @@ -94,6 +94,14 @@ class="hidden items-center gap-1.5 rounded-full bg-emerald-500/10 px-3 py-1.5 te Masterclass + {{-- Consulting link (desktop only) --}} + + {{-- Bifrost button (visible on large screens) --}} @@ -36,7 +36,7 @@ class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue- wire:model="email" type="email" id="email" - class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700 dark:text-white sm:text-sm" + class="mt-1 block w-full rounded-md border-gray-300 focus:border-gray-500 focus:ring-gray-500 dark:border-gray-600 dark:bg-gray-700 dark:text-white sm:text-sm" > @error('email')

    {{ $message }}

    @enderror
    @@ -49,42 +49,25 @@ class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue- wire:model="company" type="text" id="company" - class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700 dark:text-white sm:text-sm" + class="mt-1 block w-full rounded-md border-gray-300 focus:border-gray-500 focus:ring-gray-500 dark:border-gray-600 dark:bg-gray-700 dark:text-white sm:text-sm" > @error('company')

    {{ $message }}

    @enderror
    @error('description')

    {{ $message }}

    @enderror
    -
    - - - @error('budget')

    {{ $message }}

    @enderror -
    -
    @if (config('services.turnstile.site_key'))
    diff --git a/routes/web.php b/routes/web.php index 1b1d19f1..b476bdc5 100644 --- a/routes/web.php +++ b/routes/web.php @@ -171,7 +171,8 @@ Route::view('terms-of-service', 'terms-of-service')->name('terms-of-service'); Route::view('developer-terms', 'developer-terms')->name('developer-terms'); Route::view('partners', 'partners')->name('partners'); -Route::view('build-my-app', 'build-my-app')->name('build-my-app'); +Route::redirect('build-my-app', '/consulting', 301); +Route::view('consulting', 'consulting')->name('consulting'); Route::view('the-vibes', 'the-vibes')->name('the-vibes'); // Public plugin directory routes diff --git a/tests/Feature/LeadSubmissionTest.php b/tests/Feature/LeadSubmissionTest.php index 96989f1f..cc08edf0 100644 --- a/tests/Feature/LeadSubmissionTest.php +++ b/tests/Feature/LeadSubmissionTest.php @@ -26,13 +26,21 @@ protected function setUp(): void } #[Test] - public function build_my_app_page_is_accessible(): void + public function consulting_page_is_accessible(): void { - $this->get(route('build-my-app')) + $this->get(route('consulting')) ->assertOk() ->assertSeeLivewire(LeadSubmissionForm::class); } + #[Test] + public function build_my_app_redirects_to_consulting(): void + { + $this->get('/build-my-app') + ->assertRedirect('/consulting') + ->assertStatus(301); + } + #[Test] public function lead_can_be_submitted_successfully(): void { @@ -43,7 +51,6 @@ public function lead_can_be_submitted_successfully(): void ->set('email', 'john@example.com') ->set('company', 'Acme Corp') ->set('description', 'I need a mobile app for my business.') - ->set('budget', 'less_than_5k') ->set('turnstileToken', 'test-token') ->call('submit') ->assertSet('submitted', true) @@ -54,7 +61,6 @@ public function lead_can_be_submitted_successfully(): void 'email' => 'john@example.com', 'company' => 'Acme Corp', 'description' => 'I need a mobile app for my business.', - 'budget' => 'less_than_5k', ]); Notification::assertSentTo( @@ -78,10 +84,9 @@ public function all_fields_are_required(): void ->set('email', '') ->set('company', '') ->set('description', '') - ->set('budget', '') ->set('turnstileToken', 'test-token') ->call('submit') - ->assertHasErrors(['name', 'email', 'company', 'description', 'budget']); + ->assertHasErrors(['name', 'email', 'company', 'description']); } #[Test] @@ -92,26 +97,11 @@ public function email_must_be_valid(): void ->set('email', 'not-an-email') ->set('company', 'Acme Corp') ->set('description', 'I need a mobile app.') - ->set('budget', 'less_than_5k') ->set('turnstileToken', 'test-token') ->call('submit') ->assertHasErrors(['email']); } - #[Test] - public function budget_must_be_a_valid_option(): void - { - Livewire::test(LeadSubmissionForm::class) - ->set('name', 'John Doe') - ->set('email', 'john@example.com') - ->set('company', 'Acme Corp') - ->set('description', 'I need a mobile app.') - ->set('budget', 'invalid-budget') - ->set('turnstileToken', 'test-token') - ->call('submit') - ->assertHasErrors(['budget']); - } - #[Test] public function rate_limiting_is_enforced(): void { @@ -123,7 +113,6 @@ public function rate_limiting_is_enforced(): void ->set('email', "john{$i}@example.com") ->set('company', 'Acme Corp') ->set('description', 'I need a mobile app.') - ->set('budget', 'less_than_5k') ->set('turnstileToken', 'test-token') ->call('submit') ->assertSet('submitted', true); @@ -136,7 +125,6 @@ public function rate_limiting_is_enforced(): void ->set('email', 'limited@example.com') ->set('company', 'Acme Corp') ->set('description', 'I need a mobile app.') - ->set('budget', 'less_than_5k') ->set('turnstileToken', 'test-token') ->call('submit') ->assertHasErrors(['form']); @@ -156,7 +144,6 @@ public function turnstile_validation_passes_when_secret_key_is_not_configured(): ->set('email', 'john@example.com') ->set('company', 'Acme Corp') ->set('description', 'I need a mobile app.') - ->set('budget', 'less_than_5k') ->set('turnstileToken', '') ->call('submit') ->assertSet('submitted', true); @@ -180,7 +167,6 @@ public function turnstile_validation_fails_with_invalid_token(): void ->set('email', 'john@example.com') ->set('company', 'Acme Corp') ->set('description', 'I need a mobile app.') - ->set('budget', 'less_than_5k') ->set('turnstileToken', 'invalid-token') ->call('submit') ->assertHasErrors(['turnstileToken']); @@ -206,7 +192,6 @@ public function turnstile_validation_passes_with_valid_token(): void ->set('email', 'john@example.com') ->set('company', 'Acme Corp') ->set('description', 'I need a mobile app.') - ->set('budget', 'less_than_5k') ->set('turnstileToken', 'valid-token') ->call('submit') ->assertSet('submitted', true); @@ -214,13 +199,6 @@ public function turnstile_validation_passes_with_valid_token(): void $this->assertDatabaseCount('leads', 1); } - #[Test] - public function budgets_are_passed_to_the_view(): void - { - Livewire::test(LeadSubmissionForm::class) - ->assertViewHas('budgets', Lead::BUDGETS); - } - #[Test] public function ip_address_is_recorded_with_submission(): void { @@ -231,7 +209,6 @@ public function ip_address_is_recorded_with_submission(): void ->set('email', 'john@example.com') ->set('company', 'Acme Corp') ->set('description', 'I need a mobile app.') - ->set('budget', 'less_than_5k') ->set('turnstileToken', 'test-token') ->call('submit');