Replace the smart redirect on /dashboard with an overview hub (stats, recent accounts, pending orders) matching Domains and Email, and move the full account list to /hosting/accounts. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -25,71 +25,6 @@ use Illuminate\View\View;
|
||||
|
||||
class HostingProductController extends Controller
|
||||
{
|
||||
/**
|
||||
* Smart hosting redirect - routes user based on their hosting accounts
|
||||
*/
|
||||
public function index(Request $request): View|RedirectResponse
|
||||
{
|
||||
$user = $request->user();
|
||||
|
||||
// Get all shared hosting types (not VPS/dedicated)
|
||||
$sharedTypes = [
|
||||
HostingProduct::TYPE_SINGLE_DOMAIN,
|
||||
HostingProduct::TYPE_MULTI_DOMAIN,
|
||||
HostingProduct::TYPE_WORDPRESS,
|
||||
];
|
||||
|
||||
// Get user's hosting accounts (owned + team member access)
|
||||
$sharedAccountIds = HostingAccountMember::query()
|
||||
->where('user_id', $user->id)
|
||||
->pluck('hosting_account_id');
|
||||
|
||||
$hostingAccounts = HostingAccount::query()
|
||||
->where(function ($query) use ($user, $sharedAccountIds) {
|
||||
$query->where('user_id', $user->id);
|
||||
if ($sharedAccountIds->isNotEmpty()) {
|
||||
$query->orWhereIn('id', $sharedAccountIds);
|
||||
}
|
||||
})
|
||||
->whereHas('product', fn ($q) => $q->whereIn('type', $sharedTypes))
|
||||
->with('product')
|
||||
->latest()
|
||||
->get();
|
||||
|
||||
// Get user's hosting orders
|
||||
$orders = CustomerHostingOrder::query()
|
||||
->forUser($user->id)
|
||||
->whereHas('product', fn ($q) => $q->whereIn('type', $sharedTypes))
|
||||
->with(['product', 'hostingAccount'])
|
||||
->latest()
|
||||
->get();
|
||||
|
||||
// Combine accounts from orders and direct assignments
|
||||
$allAccounts = $hostingAccounts->merge(
|
||||
$orders->filter(fn ($o) => $o->hostingAccount)->map(fn ($o) => $o->hostingAccount)
|
||||
)->unique('id');
|
||||
|
||||
// No hosting accounts - show selection modal
|
||||
if ($allAccounts->isEmpty()) {
|
||||
return view('hosting.select-type', [
|
||||
'title' => 'Choose Hosting Plan',
|
||||
]);
|
||||
}
|
||||
|
||||
// Single account — account overview (matches monolith; panel via Control Panel)
|
||||
if ($allAccounts->count() === 1) {
|
||||
$account = $allAccounts->first();
|
||||
|
||||
return redirect()->route('hosting.accounts.show', $account);
|
||||
}
|
||||
|
||||
// Multiple accounts - show list page
|
||||
return view('hosting.accounts-list', [
|
||||
'title' => 'Your Hosting Accounts',
|
||||
'accounts' => $allAccounts,
|
||||
]);
|
||||
}
|
||||
|
||||
public function singleDomain(Request $request): View
|
||||
{
|
||||
return $this->renderHostingPage($request, HostingProduct::TYPE_SINGLE_DOMAIN, 'Single Domain Hosting');
|
||||
|
||||
@@ -3,13 +3,114 @@
|
||||
namespace App\Http\Controllers\Hosting;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use App\Models\CustomerHostingOrder;
|
||||
use App\Models\HostedSite;
|
||||
use App\Models\HostingAccount;
|
||||
use App\Models\HostingAccountMember;
|
||||
use App\Models\HostingProduct;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class OverviewController extends Controller
|
||||
{
|
||||
public function index(Request $request): RedirectResponse
|
||||
/** Authenticated hosting dashboard (overview hub). */
|
||||
public function index(Request $request): View
|
||||
{
|
||||
return redirect()->route('hosting.dashboard');
|
||||
$user = $request->user();
|
||||
$accounts = $this->sharedHostingAccounts($user);
|
||||
$accountIds = $accounts->pluck('id');
|
||||
|
||||
$pendingOrders = CustomerHostingOrder::query()
|
||||
->forUser($user->id)
|
||||
->whereHas('product', fn ($q) => $q->whereIn('type', $this->sharedTypes()))
|
||||
->whereIn('status', [
|
||||
CustomerHostingOrder::STATUS_PENDING_PAYMENT,
|
||||
CustomerHostingOrder::STATUS_PENDING_APPROVAL,
|
||||
CustomerHostingOrder::STATUS_APPROVED,
|
||||
CustomerHostingOrder::STATUS_PROVISIONING,
|
||||
])
|
||||
->with('product')
|
||||
->latest()
|
||||
->take(5)
|
||||
->get();
|
||||
|
||||
$linkedDomains = $accountIds->isEmpty()
|
||||
? 0
|
||||
: HostedSite::query()->whereIn('hosting_account_id', $accountIds)->count();
|
||||
|
||||
return view('hosting.dashboard', [
|
||||
'accounts' => $accounts,
|
||||
'activeCount' => $accounts->where('status', HostingAccount::STATUS_ACTIVE)->count(),
|
||||
'expiringCount' => $accounts
|
||||
->where('status', HostingAccount::STATUS_ACTIVE)
|
||||
->filter(fn (HostingAccount $account) => $account->expires_at !== null && $account->expires_at->between(now(), now()->addDays(30)))
|
||||
->count(),
|
||||
'pendingOrderCount' => CustomerHostingOrder::query()
|
||||
->forUser($user->id)
|
||||
->whereHas('product', fn ($q) => $q->whereIn('type', $this->sharedTypes()))
|
||||
->whereIn('status', [
|
||||
CustomerHostingOrder::STATUS_PENDING_PAYMENT,
|
||||
CustomerHostingOrder::STATUS_PENDING_APPROVAL,
|
||||
CustomerHostingOrder::STATUS_APPROVED,
|
||||
CustomerHostingOrder::STATUS_PROVISIONING,
|
||||
])
|
||||
->count(),
|
||||
'linkedDomains' => $linkedDomains,
|
||||
'recent' => $accounts->take(5),
|
||||
'pendingOrders' => $pendingOrders,
|
||||
]);
|
||||
}
|
||||
|
||||
public function accounts(Request $request): View
|
||||
{
|
||||
return view('hosting.accounts-list', [
|
||||
'title' => 'Your Hosting Accounts',
|
||||
'accounts' => $this->sharedHostingAccounts($request->user()),
|
||||
]);
|
||||
}
|
||||
|
||||
/** @return list<string> */
|
||||
private function sharedTypes(): array
|
||||
{
|
||||
return [
|
||||
HostingProduct::TYPE_SINGLE_DOMAIN,
|
||||
HostingProduct::TYPE_MULTI_DOMAIN,
|
||||
HostingProduct::TYPE_WORDPRESS,
|
||||
];
|
||||
}
|
||||
|
||||
/** @return Collection<int, HostingAccount> */
|
||||
private function sharedHostingAccounts(User $user): Collection
|
||||
{
|
||||
$sharedTypes = $this->sharedTypes();
|
||||
|
||||
$sharedAccountIds = HostingAccountMember::query()
|
||||
->where('user_id', $user->id)
|
||||
->pluck('hosting_account_id');
|
||||
|
||||
$hostingAccounts = HostingAccount::query()
|
||||
->where(function ($query) use ($user, $sharedAccountIds) {
|
||||
$query->where('user_id', $user->id);
|
||||
if ($sharedAccountIds->isNotEmpty()) {
|
||||
$query->orWhereIn('id', $sharedAccountIds);
|
||||
}
|
||||
})
|
||||
->whereHas('product', fn ($q) => $q->whereIn('type', $sharedTypes))
|
||||
->with(['product', 'sites'])
|
||||
->latest()
|
||||
->get();
|
||||
|
||||
$orderAccounts = CustomerHostingOrder::query()
|
||||
->forUser($user->id)
|
||||
->whereHas('product', fn ($q) => $q->whereIn('type', $sharedTypes))
|
||||
->with(['hostingAccount.product', 'hostingAccount.sites'])
|
||||
->latest()
|
||||
->get()
|
||||
->filter(fn (CustomerHostingOrder $order) => $order->hostingAccount !== null)
|
||||
->map(fn (CustomerHostingOrder $order) => $order->hostingAccount);
|
||||
|
||||
return $hostingAccounts->merge($orderAccounts)->unique('id')->values();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user