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
156 lines
5.5 KiB
PHP
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.']);
|
|
}
|
|
}
|
|
}
|