Files
hub/app/Http/Controllers/Buyer/RegistrationController.php
Jon Leopard 7e5ea2bc10 checkpoint: marketplace and operational features complete, ready for Week 4 data migration
Summary of completed work:
- Complete buyer portal (browse, cart, checkout, orders, invoices)
- Complete seller portal (orders, manifests, fleet, picking)
- Business onboarding wizards (buyer 4-step, seller 5-step)
- Email verification and registration flows
- Notification system for buyers and sellers
- Payment term surcharges and pickup/delivery workflows
- Filament admin resources (Business, Brand, Product, Order, Invoice, User)
- 51 migrations executed successfully

Renamed Company -> Business throughout codebase for consistency.
Unified authentication flows with password reset.
Added audit trail and telescope for debugging.

Next: Week 4 Data Migration (Days 22-28)
- Product migration (883 products from cannabrands_crm)
- Company migration (81 buyer companies)
- User migration (preserve password hashes)
- Order history migration
2025-10-15 11:17:15 -07:00

156 lines
5.5 KiB
PHP

<?php
namespace App\Http\Controllers\Buyer;
use App\Http\Controllers\Controller;
use App\Http\Requests\Buyer\CompleteRegistrationRequest;
use App\Services\EmailVerificationService;
use App\Services\ContactToUserService;
use App\Models\User;
use App\Models\Contact;
use App\Enums\ContactType;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\View\View;
class RegistrationController extends Controller
{
public function __construct(
protected EmailVerificationService $emailVerificationService,
protected ContactToUserService $contactToUserService
) {}
/**
* STEP 1: Show the email collection form
*/
public function showEmailForm(): View
{
return view('buyer.auth.register-email');
}
/**
* STEP 2: Handle email submission and verification
* Simplified: Just check if user exists, then send verification
*/
public function checkEmail(Request $request): JsonResponse
{
$request->validate([
'email' => ['required', 'email', 'max:255'],
]);
$email = $request->email;
// Check if email already exists as a user
if (User::where('email', $email)->exists()) {
return response()->json([
'status' => 'exists',
'message' => 'This email already has an account. Please try logging in or use the forgot password option.'
]);
}
// Create verification token and send email
try {
$token = $this->emailVerificationService->createVerification($email);
$this->emailVerificationService->sendVerificationEmail($email, $token);
return response()->json([
'status' => 'verification_sent',
'message' => 'Please check your email for a verification link to complete your registration.'
]);
} catch (\Exception $e) {
\Log::error('Registration verification email error', [
'error' => $e->getMessage(),
'email' => $email,
]);
return response()->json([
'status' => 'error',
'message' => 'There was an error sending verification email. Please try again.'
], 500);
}
}
/**
* STEP 3: Show the complete registration form after token verification
* Simplified: Always show full registration form
*/
public function showCompleteForm(string $token): View|RedirectResponse
{
$verification = $this->emailVerificationService->validateToken($token);
if (!$verification) {
return redirect()->route('buyer.register')
->withErrors(['token' => 'Invalid or expired verification link. Please try again.']);
}
// Get buyer-specific contact types
$contactTypes = collect(ContactType::buyerTypes())->mapWithKeys(function ($type) {
return [$type->value => $type->label()];
})->toArray();
return view('buyer.auth.register-complete', [
'token' => $token,
'prefill' => ['email' => $verification->email],
'isExistingContact' => false, // Always false for now (contacts created later during company setup)
'contactTypes' => $contactTypes,
]);
}
/**
* STEP 4: Process the complete registration
* Simplified: Always create new user account
*/
public function processRegistration(CompleteRegistrationRequest $request): RedirectResponse
{
// Validate token first
$verification = $this->emailVerificationService->validateToken($request->token);
if (!$verification) {
return back()->withErrors(['token' => 'Invalid or expired verification link. Please request a new one.']);
}
try {
// Create new user account
$user = User::create([
'first_name' => $request->first_name,
'last_name' => $request->last_name,
'email' => $verification->email,
'password' => Hash::make($request->password),
'phone' => $request->phone,
'user_type' => 'buyer',
'status' => 'active',
'temp_business_name' => $request->business_name,
'temp_market' => $request->market,
'temp_contact_type' => $request->contact_type, // Store for later use in company setup
]);
// Fire registered event
event(new \Illuminate\Auth\Events\Registered($user));
// Consume the verification token
$this->emailVerificationService->consumeToken($request->token);
// Log the user in
Auth::login($user);
// Redirect to dashboard
return redirect()->route('buyer.dashboard')->with([
'success' => true,
'success_header' => "Welcome to Cannabrands, {$user->first_name}!",
'success_message' => "Your account has been created. Let's set up your company profile to start ordering."
]);
} catch (\Exception $e) {
\Log::error('Registration completion failed', [
'error' => $e->getMessage(),
'email' => $verification->email,
]);
return back()->withErrors(['general' => 'There was an error completing your registration. Please try again.']);
}
}
}